On 16/10/2015 at 05:07, xxxxxxxx wrote:
I'm trying to write my first experimental lines of Python code in C4D.
Allow me to first explain what I'm after:
Unfortunately, C4D has no "working pivot" yet, like XSI or 3ds Max.
For those unfamiliar - it allows for simple and non-destructive repositioning of any object selection, without changing any axes.
In C4D's component mode, the Axis pretty much already works like this.
Yet, in object mode, when the selection contains not only editable meshes but also parametric objects like primitives, nulls or generators, moving the Axis in Axis mode can lead to undesirable offsets of those parametric objects.
Also, there seems to be no decent way to utilize snapping as needed.
A workaround could be to temporarily group the objects, and moving the parent null, but that could rip objects out of their hierarchy.
So, here's the script idea:
- Create a null, call it "TempAxis", create a second null as it's child.
- Create a Parent Constraint on each selected object, Link the target to the child null.
- Select the TempAxis, enter Axis mode - script ends here.
Now the user can now snap the TempAxis null to a first position, leave Axis mode, move to the second postion, and the selected objects follow. VoilÃ¡, a working pivot - theoretically.
(To avoid cluttering the scene with lots of Parent Constraint Tags, some cleaning up would be done beforehand in the script.)
Here's the problem:
I figured how to create the Parent Constraint Tag...
#oSel = some object
oTag = oSel.MakeTag(1019364)
oTag[c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True
... how do I link the target to an object (the child null)?
On 16/10/2015 at 12:05, xxxxxxxx wrote:
the easiest way to find out about IDs is to simply drag a parameter into the command field at the bottom of the console window.
As the Constraint tag can have an arbitrary number of different constraints, the IDs are dynamic.
The first Parent constraint for example has 30001 (use above drag method to find out more).
Here's some code to get you started:
from c4d import gui
def main() :
listSel = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
if len(listSel) == 0:
oTempAxis = c4d.BaseObject(c4d.Onull)
if oTempAxis is None:
oChild = c4d.BaseObject(c4d.Onull)
if oChild is None:
for obj in listSel:
oTag = obj.MakeTag(1019364) # Constraint tag
if oTag is None:
oTag[c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True
oTag = oChild # NOTE: These IDs are dynamic IDs, depending on number and type of constraint
doc[c4d.DOCUMENT_AXIS] = True # Enable Axis mode
On 17/10/2015 at 01:23, xxxxxxxx wrote:
Thanks a lot, Andreas!!
That's the trick:
oTag = oChild
Interesting are the ways of C4D...
Here's my go at it: (how do I get this dashed code frame?)
#Temporary Axis import c4d from c4d import gui from c4d.modules import snap def main() : oDoc = c4d.documents.GetActiveDocument() if oDoc.IsEditMode() : # No Temp Axis is needed in Component mode. # We simply assume that the user wants to turn on Axis Mode. oDoc[c4d.DOCUMENT_AXIS] = True # Axis mode return else: # Object mode lSel = oDoc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0) # Get selection without children. if len(lSel) == 0: return # Clean up previous Temp Axis and Constraint Tags. oAxis = oDoc.SearchObject('_TEMP_AXIS_') if oAxis: oAxis.Remove() for oSel in lSel: lTags = oSel.GetTags() for oTag in lTags: if oTag.GetName() == '_TEMP_AXIS_': oTag.Remove() # Create "Temp Axis" Null oTempAxis = c4d.BaseObject(c4d.Onull) if oTempAxis is None: return oTempAxis.SetName('_TEMP_AXIS_') oTempAxis[c4d.NULLOBJECT_DISPLAY] = 1 # Display as a point, not dot. oTempAxis[c4d.NULLOBJECT_ORIENTATION] = 1 # XY # We want the Temp Axis to be moved in Axis mode with "child compensation". # For that, we need a child null. oNull = c4d.BaseObject(c4d.Onull) oNull.SetName('_TEMP_AXIS_NULL_') oNull[c4d.NULLOBJECT_DISPLAY] = 1 oNull[c4d.NULLOBJECT_ORIENTATION] = 1 oNull[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 oNull.InsertUnder(oTempAxis) oDoc.InsertObject(oTempAxis) # The selected objects are moved via Constraint Tag. for oSel in lSel: oTag = oSel.MakeTag(1019364) oTag[c4d.ID_BASELIST_NAME] = '_TEMP_AXIS_' oTag[c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True # Parent constraint oTag = oNull doc.SetActiveObject(oTempAxis, c4d.SELECTION_NEW) oDoc[c4d.DOCUMENT_AXIS] = True # Enable Axis mode c4d.CallCommand(c4d.ID_MODELING_MOVE) # Enable Move Tool snap.EnableSnap(True, oDoc)# Enable Snapping c4d.EventAdd() def Group(lObj) : oNull = c4d.BaseObject(c4d.Onull) for oObj in lObj: oObj.InsertUnder(oNull) return oNull if __name__=='__main__': main()
On 17/10/2015 at 01:27, xxxxxxxx wrote:
Put the script under some shortcut (mine's 'T'), and Axis mode under another (mine's 'D').
Select some objects, press T, move/snap to the source location, press D, move to the target location.
Works allright for now, although there are special cases to take care of, like editable meshes in component mode are selected, but also parametric objects.
On 20/10/2015 at 07:24, xxxxxxxx wrote:
Could you please also show me the script line how to change the Constraint's "Priority" parameter to something else? (I need "Initial")
Thanks a lot!
On 21/10/2015 at 12:58, xxxxxxxx wrote:
Never mind, I figured:
Sorry for the noise!