Connecting Camera Focus Distance to Null Object with Python
-
Hi there. I wonder if anyone would be able to help a not-very-savvy coder figure out a tiny bit of Python code. For this code, Iβm trying to import and position a camera into my scene. I then want to connect the 'focus distance' field of the camera to a null object which I have also imported into the scene. I thought it would be as easy as adding some variation of "camera[c4d.CAMERAOBJECT_TARGETOBJECT] = null" into my code, but no amount of tweaking seems to work for this. I feel like I'm missing a step. If anyone knows the answer please let me know. My code can be viewed below.
import c4d from c4d import gui # Lighting Stage def main(): def tool(): return c4d.plugins.FindPlugin(doc.GetAction(), c4d.PLUGINTYPE_TOOL) def object(): return doc.GetActiveObject() def tag(): return doc.GetActiveTag() def renderdata(): return doc.GetActiveRenderData() def prefs(id): return c4d.plugins.FindPlugin(id, c4d.PLUGINTYPE_PREFS) c4d.CallCommand(5140) # Create Camera Targeting Null object()[c4d.NULLOBJECT_DISPLAY] = 13 object()[c4d.NULLOBJECT_RADIUS] = 80 object()[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = 276 object()[c4d.ID_BASELIST_NAME] = "Camera_Target" c4d.CallCommand(5103) # Create Camera with Redshift Tag object()[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X] = 0 object()[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_Y] = -0.175 object()[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_Z] = 0 object()[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = 0 object()[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = 433 object()[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Z] = -884 c4d.CallCommand(100004788, 50075) # New Tag tag()[c4d.REDSHIFT_POSTEFFECTS_DOF_OVERRIDE] = True tag()[c4d.REDSHIFT_POSTEFFECTS_DOF_ENABLED] = True tag()[c4d.REDSHIFT_POSTEFFECTS_DOF_RADIUS] = 8.5 camera[c4d.CAMERAOBJECT_TARGETOBJECT] = null if __name__=='__main__': main() c4d.EventAdd()
-
Hi,
the problem with your code is that you neither defined the symbol
camera
nor the symbolnull
which you used in your code. Script log code is also usually not a very good staring point (I assume this was derived from a script log) . I wrote a little piece of narrative code which roughly does what you want and which you might find helpful."""Run this in the script manager with an object in your scene, called "my_taregt". """ import c4d def main(): """ """ # "doc" is a predefined variable in Script Manager scripts, which # points to the currently active document. "BaseDocument.SearchObject" # is looking for the first object with the given name in the document. # There are better ways to select objects, but this is an easy one and # might be sufficient for your case. If you have an object named # "my_target" in your scene, the variable "target" will point to it. target = doc.SearchObject("my_target") # "target" will be "None" if we did not find it, this will just signal # that. if not target: raise IOError("Could not find target object.") # We can instantiate an object, a tag, a material or a shader with the # type BaseList2D. You have to pass in the ID of the node you want to # build. Here we are passing "c4d.Ocamera" to build a camera. Ocamera # is just an alias for the integer 5103, which you also used in your # CallCommand. # But unlike CallCommand constructing an object with the type BaseList2D # will give us a symbol under which we can access our object ("camera" # here). camera = c4d.BaseList2D(c4d.Ocamera) # Setting the target is just as easy as you thought, the problem in # your code was that you never defined something as "camera". camera[c4d.CAMERAOBJECT_TARGETOBJECT] = target # Setting the relative position and rotation could be shortened a bit, # but your way was totally fine. position = c4d.Vector(0, 433, -800) rotation = c4d.Vector(0, -0.175, 0) camera[c4d.ID_BASEOBJECT_REL_POSITION] = position camera[c4d.ID_BASEOBJECT_REL_ROTATION] = rotation # There are also two methods of the type BaseObject (our camera is such # an BaseObject) which do the same as the attribute access. camera.SetRelPos(position) camera.SetRelRot(rotation) # Since I do not own RedShift, I will just create an target expression # on the camera instead. This should look a bit familiar by now. tag = c4d.BaseList2D(c4d.Ttargetexpression) tag[c4d.TARGETEXPRESSIONTAG_LINK] = target # Now we just need to attach our tag to our camera ... camera.InsertTag(tag) # ... and insert that object into the active document. doc.InsertObject(camera) # Finally we need to tell Cinema, that we modified something. c4d.EventAdd() if __name__ == "__main__": main()
Cheers,
zipit -
@curripod00 said in Connecting Camera Focus Distance to Null Object with Python:
camera[c4d.CAMERAOBJECT_TARGETOBJECT] = null
This line cannot work because "null" is an undefined variable name (and "camera" actually too). It references nothing.
Instead, you will need to find the actual target null by searching:camera = doc.SearchObject("Camera") camera[c4d.CAMERAOBJECT_TARGETOBJECT] = doc.SearchObject("Camera_Target")
(I did not test that, just slapped together from memory.)
This is still not very good code because it assumes that the new camera's name is "Camera" which is not very original and may be duplicate in the scene already. Feel free to call the camera something else by setting the name when you generate the object.
Or instead of searching, you store the objects after generation in a variable. Following code should do it (I didn't test, as I don't have Redshift):
import c4d from c4d import gui def main(): def object(): return doc.GetActiveObject() def tag(): return doc.GetActiveTag() c4d.CallCommand(5140) # Create Camera Targeting Null cameraTarget = object() cameraTarget[c4d.NULLOBJECT_DISPLAY] = 13 cameraTarget[c4d.NULLOBJECT_RADIUS] = 80 cameraTarget[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = 276 cameraTarget[c4d.ID_BASELIST_NAME] = "Camera_Target" c4d.CallCommand(5103) # Create Camera with Redshift Tag camera = object() camera[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X] = 0 camera[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_Y] = -0.175 camera[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_Z] = 0 camera[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = 0 camera[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = 433 camera[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Z] = -884 c4d.CallCommand(100004788, 50075) # New Tag cameratag = tag() cameratag[c4d.REDSHIFT_POSTEFFECTS_DOF_OVERRIDE] = True cameratag[c4d.REDSHIFT_POSTEFFECTS_DOF_ENABLED] = True cameratag[c4d.REDSHIFT_POSTEFFECTS_DOF_RADIUS] = 8.5 camera[c4d.CAMERAOBJECT_TARGETOBJECT] = cameraTarget if __name__=='__main__': main() c4d.EventAdd()
Learn more about Python for C4D scripting:
https://www.patreon.com/cairyn -
@zipit okaaaay I get it: you NEVER EVER sleep!
-
@zipit This is fantastic, thank you for going through and explaining why my code was lacking, I have a better understanding of this process now and my camera focus works perfectly using your method.
-
@Cairyn Thanks for this fantastic resource, I will definitely use this summer to level up with Python.