PY Double Circle example not working

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 18/04/2012 at 02:09, xxxxxxxx wrote:

Tangents are not swapped so here is the code for the fixed OrientObject() method:

``````@staticmethod
def OrientObject(op, plane, reverse) :
pcnt = op.GetPointCount()
points = op.GetAllPoints()

if plane>=c4d.PRIM_PLANE_ZY:
if plane==c4d.PRIM_PLANE_ZY:
for i, point in enumerate(points) :
x = -point.z
y = point.y
z = point.x

op.SetPoint(i, c4d.Vector(x, y, z))

h = op.GetTangent(i)
vl = h["vl"]
vr = h["vr"]
vl = c4d.Vector(-vl.z, vl.y, vl.x)
vr = c4d.Vector(-vr.z, vr.y, vr.x)

op.SetTangent(i, vl, vr)

elif plane==c4d.PRIM_PLANE_XZ:
for i, point in enumerate(points) :
x = point.x
y = -point.z
z = point.y

op.SetPoint(i, c4d.Vector(x, y, z))

h = op.GetTangent(i)
vl = h["vl"]
vr = h["vr"]
vl = c4d.Vector(vl.x, -vl.z, vl.y)
vr = c4d.Vector(vr.x, -vr.z, vr.y)

op.SetTangent(i, vl, vr)

if reverse:
to = pcnt/float(2)
if pcnt%2:
to+=1
for i, point in enumerate(points[:int(to)]) :
op.SetPoint(i, points[pcnt-1-i])
op.SetPoint(pcnt-1-i, point)

h = op.GetTangent(i)
tangents = op.GetTangent(pcnt-1-i)
# Move from right to left
vr, vl = tangents["vl"], tangents["vr"]
op.SetTangent(i, vl, vr)

op.SetTangent(pcnt-1-i, h["vr"], h["vl"])

op.Message(c4d.MSG_UPDATE)
``````

And MoveHandle() :

``````def MoveHandle(self, op, undo, mouse_pos, hit_id, qualifier, bd) :

if hit_id==c4d.NOTOK: return False

src = undo.GetDataInstance()
dst = op.GetDataInstance()
handle_dir = c4d.Vector(1.0, 0.0, 0.0)
handle_dir = DoubleCircleData.SwapPoint(handle_dir, src.GetLong(c4d.PRIM_PLANE))
val = 0 #tm.off.Dot(handle_dir) # FIX

return True
``````

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 18/04/2012 at 02:19, xxxxxxxx wrote:

Much appreciate the great support Yannick

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 19/04/2012 at 01:06, xxxxxxxx wrote:

Originally posted by xxxxxxxx

cinema callls GetDEnabling for each description element  . by returning true or false you
enable/disable this element.

something like that :

``````def GetDEnabling(self, node, id, t_data, flags, itemdesc) :
if (id[0].id == c4d.ElementToDisable) :
if (node[c4d.ElementThatDrivesDisableState] == True)
return True # unhide the element
else :
return False # hides the element
# when your criteria don't match, close with a call to the parent class of your plugin
return super(yourPluginClass, self).GetDEnabling(self, node, id, t_data, flags, itemdesc)
``````

not sure if that last line actually works this way in pyhton , i switched to c++ before getting
deeper into this. in c++ it is working for GetDDescription with :

``````return __super::GetDDescription(node, description, flags);
``````

however this call to the parent isn't mandatory. things will work without it, but maxon wants us
to do it you could just return true instead of it.

I can't see how you set the itemdesc container (its a basecontainer - but how to set) no python examples (C++SDK tells me its a pointer to a basecontainer - so I;m no futher)

OK look at it from newbie world

GetDEnabling(self, node, id, t_data, flags, itemdesc) :

if you were calling this method and writing in words what the params were

JSplineObject, self.GetDEnabling(self, op(current object), 37000(ID in the res file of item ), 100 (Value in init or current vale?), flags(not used), itemdesc (a base container (set how))

and in the method
if (id[0].id == c4d.ElementToDisable) :
if (node[c4d.ElementThatDrivesDisableState] == True)

what does ElementToDisable and ElementThatDrivesDisableState refer to?

tia

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 19/04/2012 at 02:57, xxxxxxxx wrote:

read the thread i have posted on GetDEnabling. don't mess with itemdesc, it is meant to be
read only. it also doesn't seem to be the description container of your current instance of
your class, but the the class itself.

you do not call GetDEnabling, you overwrite it. not sure if you are aware of the basics of object
orientation / polymorphism, so a quick explanation. you have a class GenericAnimal which
implements the method MakeSound which does nothing. now you create two other classes which
inherit from GenericAnimal - CowClass and DogClass they both overwrite the method MakeSound
which they inherited from their parent class GenericAnimal. if you call MakeSound on CowClass you
could let it print "moo", if you call it on DogClass you could let it print "bark".

this is what you are doing for Init(), GetContour(), GetDEanabling(), Message() and so on.
the BaseObject class your plugin inherts from is the GenericAnimal class which provides virtual
implementations for these methods. JSpline is your CowClass which has to overwrite GetDEnabling
(MakeSound) to fill it with some logic.

the example was actually quite close to copy & paste ready. an example with real world ids:

``````def GetDEnabling(self, node, id, t_data, flags, itemdesc) :
if (id[0].id == c4d.SPLINEOBJECT_ANGLE ) :
if (node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_ADAPTIVE or node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_SUBDIV )
return True # the angle interpolation input box is shown when the interpolation mode is set to adapative or subdiv
else :
return False # hides the element
# when your criteria don't match, close with a call to the parent class of your plugin
return super(JSplineObject, self).GetDEnabling(self, node, id, t_data, flags, itemdesc)
``````

edit : to clearify things a bit - as i wrote earlier GetDEnabling is called for each description
element of your plugin. id is the the DescID of the element GetDEnabling is called for.

edit2 : forgot some c4d. on the ids in my example

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 19/04/2012 at 06:15, xxxxxxxx wrote:

LD - thanks , those few lines explain a lot.  I'm a designer who in daily life is full of logos, brochures, type, colours etc and the occasional need to deal with PHP, MYSQL, JS and a little programming in C4D. Many moons ago I wrote Z80 assembler (running code with system hooks) and enough C to understand pointers and basic classes (also with PHP)

The inheritance thing is now much clearer, thank you for talking the time to explain.

From what I now understand we define  what GetDEnabling  will do   for this particular class.
From there, its almost like we've hooked into something that is always run by C4D and if nothing needs to be changed - use the return to carry on with the rest of the plugin/class

OK - sorry for all the questions

what is an atom? (OK looks like the root base container - but I don't see the point or it being used much)

the 'node' thing is still confusing. (an object that contains data and links to other nodes)

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 19/04/2012 at 07:00, xxxxxxxx wrote:

first of all, i am also not very good at coding, just messing arround, i am an architect, so i have
a basic understanding of math, but my explanations might not be 100% accurate.

you have different implementations of the same method.

``````class Dog (GenericAnimal)
def MakeNoise()        // this is overwriting (assuming MakeNoise is also defined in GenericAnimal)
print "Bark !"
def MakeNoise(mood) // this is overloading, we create a 2nd def of MakeNoise, which accepts a parameter and behaves differently
if (mood == "agressive") :
print "Bark !"
elif (mood == "scared") :
print "Whimper !"
else:
print "Hackle !"
``````

a c4datom is the parent class of most of the classes in c4d which have some kind of object
manager representation. a basecontainer has nothing to do with c4datom. never had to use
atoms yet, so i guess you have only to deal with them, when you are doing really fundamental
stuff.

you could read node as op if it is easier to understand for you, it is the current instance of your
class, aka the GeListNode which originally implemented GetDEnabling and now is calling it.

GeListNode > BaseList2D > BaseObject > YourPlugin is the chain of inheritance. note that there
is an inheritance diagramm for the c4d sdk. http://www.thirdpartyplugins.com/python/misc/diagram.html

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 19/04/2012 at 08:14, xxxxxxxx wrote:

Even more fog clearing - thanks LD

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 20/04/2012 at 01:32, xxxxxxxx wrote:

All works OK

but when run i.e. an interface element is selected

i get TypeError: element 5

from the last return line

``````	##########################
def GetDEnabling(self, node, id, t_data, flags, itemdesc) :

#### disable the chamfer amount if both chamfer switches are off
if (id[0].id == c4d.CHAMFER) :
if (node[c4d.CHAMFER_BASE] == False) and (node[c4d.CHAMFER_TAIL] == False) :
return False  # disable the chamfer amount if both chamfer switches are off
else:
return True # show the element

#### enable/disable appropriate gui for selected spline type

if (id[0].id == c4d.SPLINEOBJECT_SUB) :
if ((node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_NATURAL) or (node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_UNIFORM )) :
return True # the angle interpolation input box is shown when the interpolation mode is set to adapative or subdiv
else:
return False # hides the element

if (id[0].id == c4d.SPLINEOBJECT_ANGLE) :
if ((node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_ADAPTIVE) or (node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_SUBDIV)) :
return True # the angle interpolation input box is shown when the interpolation mode is set to adapative or subdiv
else:
return False # hides the element

if (id[0].id == c4d.SPLINEOBJECT_MAXIMUMLENGTH) :
if (node[c4d.SPLINEOBJECT_INTERPOLATION] == c4d.SPLINEOBJECT_INTERPOLATION_SUBDIV) :
return True # the angle interpolation input box is shown when the interpolation mode is set to adapative or subdiv
else:
return False # hides the element

# when your criteria doesn't match, close with a call to the parent class of your plugin
return super(JSplineObject, self).GetDEnabling( node, id, t_data, flags, itemdesc)

##########################
``````

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 20/04/2012 at 02:55, xxxxxxxx wrote:

try :

return super(JSplineObject, self).GetDEnabling( self, node, id, t_data, flags, itemdesc)

or as i said use return true instead of it, as i am not 100% sure about the super call snytax in python.

ps : as a sidenote, stop using hash keys to seperate you methods, in this case it doesn't matter,
but for larger code chunks it makes it more difficult to read the code. whitespaces are interpreted
differently by different text display softwares.

use an editor with code folding like notepad++ or sublimetext2 (great editor), or use a fully blown
ide like eclipse with a python module.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 20/04/2012 at 03:32, xxxxxxxx wrote:

Sorry - missed that

Text Wranger on Mac is a nice simple text editor and it has fold

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 22/04/2012 at 23:51, xxxxxxxx wrote:

I still couldn't get the reverse to work

so I tried reversing the list - which worked

but I still can't figure why the tangents are set twice -
they appear to be read once from either end
written back in reverse point/index order from the Get above

in the write - one SetTangent uses indexes and vectors
the other uses reverse indexes and dictionary descriptions of the reversed vectors - why different methods ?

I just cant get my head around it - it appears to swap tangents from one end of hte spline, working to the middle, then do it again as the counters cross over?

can someone explain pls

``````		if reverse==True:

allpoints = op.GetAllPoints()
allpoints.reverse()
op.SetAllPoints(allpoints)

to = pcnt/float(2)
if pcnt%2:
to+=1

for i in range(int(to)) :
h = op.GetTangent(i)
tangents = op.GetTangent(pcnt-1-i)
# Move from right to left
vl = tangents["vr"]
vr = tangents["vl"]
op.SetTangent(i, vl, vr)
op.SetTangent(pcnt-1-i, h["vr"], h["vl"])

op.Message(c4d.MSG_UPDATE)
return
``````

this swaps the tangents - but doesn't work?
(surely the points have already been reversed by the first statements)

``````			for i in reversed(xrange(0, pcnt)) :
tangent = op.GetTangent(i)
tl = tangent["vr"]
tr = tangent["vl"]
op.SetTangent(i, tl,tr)
``````

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 23/04/2012 at 02:14, xxxxxxxx wrote:

1. your code sets the tangent twice, because you are looping with to through your points.
to = op.GetAllPoints() / float(2). so you are looping only through half of your objects
points. it seems to be meant to shorten the methods rutime, but this will only work for
symmetrical objects if i am not missing something.

2. your second code chunk (SetTangent i.p.) is working, did a quick test on the flower primitive.
however you have to consider that spline tangents are in most cases symmetrical and swapping
them won't lead to dramatic visual changes.

``````import c4d from c4d import documents def main() : obj = doc.GetActiveObject() for i in xrange(0, obj.GetPointCount()) : t1 = obj.GetTangent(i) obj.SetTangent(i, t1["vr"],t1["vl"]) t2 = obj.GetTangent(i) print 'Point {0}'.format(i) print 'old {0}'.format(t1) print 'new {0}'.format(t2) c4d.EventAdd() if __name__=='__main__': main()
``````

for the flower primitive it returns :

``````Point 0 old {'vr': Vector(0, 25, 0), 'vl': Vector(0, -25, 0)} new {'vr': Vector(0, -25, 0), 'vl': Vector(0, 25, 0)} Point 1 old {'vr': Vector(-9.588, -16.559, 0), 'vl': Vector(9.588, 16.559, 0)} new {'vr': Vector(9.588, 16.559, 0), 'vl': Vector(-9.588, -16.559, 0)} Point 2 old {'vr': Vector(18.488, -4.929, 0), 'vl': Vector(-18.488, 4.929, 0)} new {'vr': Vector(-18.488, 4.929, 0), 'vl': Vector(18.488, -4.929, 0)} Point 3 old {'vr': Vector(17.678, -17.678, 0), 'vl': Vector(-17.678, 17.678, 0)} new {'vr': Vector(-17.678, 17.678, 0), 'vl': Vector(17.678, -17.678, 0)} ...
``````