PY Double Circle example not working



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

    On 17/04/2012 at 13:20, xxxxxxxx wrote:

    SDK Plugin Example file -  PY Double Circle
    (apart from the handles not working)

    OrientObject(op, plane, reverse) :

    doesn't appear to be working

    I've been trying to learn from the examples but can't figure whats wrong with it

    anyone?



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

    On 17/04/2012 at 13:27, xxxxxxxx wrote:

    not sure what is going wrong with the python examples, but the logic is to remap the three axis
    of the input vector on the output vector. from the c++ sdk rounded tube example :

    static Vector SwapPoint(const Vector &p, LONG axis)
    {
    	switch (axis)
    	{
    		case 0: return Vector(p.y,-p.x,p.z); break;
    		case 1: return Vector(-p.y,p.x,p.z); break;
    		case 3: return Vector(-p.x,-p.y,p.z); break;
    		case 4: return Vector(p.x,-p.z,p.y); break;
    		case 5: return Vector(p.x,p.z,-p.y); break;
    	}
    	return p;
    }
    

    i haven't used splines very much yet, so i can't say anything spcefic on the splineplanes, but i 
    guess the general idea is the same. you might have to rotate some tangents to.



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

    On 17/04/2012 at 13:55, xxxxxxxx wrote:

    Thanks Ferdinand

    I think the tangent code is broken as well - as the Circle is twisted when transformed

    Can the support team supply a working version (without the handles) please

    While we are here......

    I noticed that the c4d spline primitive hide and show UI elements (length angle etc) based on the interpolation type
    how is that done?
    obviously some logiC 'ifs' etc
    but how do you access the HIDE SHOW ?

    tia

    Paul



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

    On 17/04/2012 at 14:09, xxxxxxxx wrote:

    to disable / enable description elements you have to overwrite GetDEnabling for your plugin,

    https://plugincafe.maxon.net/topic/6287/6675_getdenabling--getddescription-in-python--c

    actually hiding stuff is only possible in c++. note that the python sdk description of GetDEnabling
    is at least very confusing, not to say wrong. the thread explains it more or less in details.



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

    On 17/04/2012 at 14:21, xxxxxxxx wrote:

    **
    GetDEnabling
    **
    **
    returns True**  if the parameter should be enabled, otherwise  False.

    should be enabled ?



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

    On 17/04/2012 at 14:42, xxxxxxxx wrote:

    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.



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

    On 17/04/2012 at 21:32, xxxxxxxx wrote:

    Can the support team supply a working version of the SDK Example (without the handles) please



  • 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
        
        cut = utils.FCut(src.GetReal(c4d.PYCIRCLEOBJECT_RAD)+val, 0.0, sys.maxint)
        dst.SetReal(c4d.PYCIRCLEOBJECT_RAD, cut)
        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

    is overloading the same thing as you refer to as overwriting?

    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.

    overloading is also polymorphism , but not the same as overwriting. overloading means that
    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

    loads 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)} ...
    

Log in to reply