Hi @ferdinand
Thanks for the response.
Found a workaround it.
Basically, just name the poses properly in a sorting order.
Query the GetName()
method and perform my own sorting.
Regards,
Ben
Hi @ferdinand
Thanks for the response.
Found a workaround it.
Basically, just name the poses properly in a sorting order.
Query the GetName()
method and perform my own sorting.
Regards,
Ben
Hi,
By default when you perform morph.GetCount()
, it returns a count based on the order they inserted.
Is there a way to get the order based on the UI order?
See illustration below:
Gotcha. Thanks for the response.
c4d.CallButton(op, c4d.ID_BASEOBJECT_FROZEN_RESET) works as expected.
Hi,
Is there a way to access the Unfreeze All Button in the Object's Coordinate Tab? Specifically, clicking it.
Searching "Unfreeze All" in the documentation and the forum doesn't yield relevant (or direct results).
Thanks for the response. Your code works without the program freezing up (although I think it's GeGetCurrentThread instead of GetCurrentThread()). Other than that, it works as expected.
Ah. I didn't think to just pass objects from different documents.
I was thinking of something like this:
The problem was that in #3, the generator no longer has access to that object for some reason. So it keeps creating a dummy object lol
Anyway, enough for my excuses. Sorry for the trouble and thanks again for your patience.
Hi @ferdinand
I admit I'm on the slow side. It's a bit hard to comprehend on my level.
Can I get a baseline answer (yes or no) on:
The examples are for Python Script/Manager and not for Python Generator (which is what I am after).
Is it doable in Python Generator?
I can execute your script just find. It gives me caches etc. But when it comes to generator it does not.
For example, as soon as I add BaseDocument.ExecutePasses
the document freezes
def PrintCacheTree():
...
def GetCaches():
...
def main():
text = c4d.BaseObject(1019268)
doc.InsertObject(text)
doc.ExecutePasses(None, False, False, True, c4d.BUILDFLAGS_NONE)
GetCaches(text)
return text
Hi @ferdinand
I'm not sure I get it. The examples are for Python Script/Manager and not for Python Generator (which is what I am after).
Anyhow, I'm guessing you are referring to GetCaches(node: c4d.BaseObject)
from geometry_caches_s26.py
If so I did try it in the Python Generator (not in the Python Script):
def PrintCacheTree():
...
def GetCaches():
...
def main():
text = c4d.BaseObject(1019268)
GetCaches(text)
return text
The result still gives me none, of which I am unable to access the individual extrude parameters of each letters.
Retrieving Caches:
Text.GetCache() = None
Text.GetDeformCache() = None
Cache Tree of 'Text':
Text(Text)
Building Caches:
Cache for newly allocated object: None
Cache after executing the cache pass: <c4d.PolygonObject object called Cube/Polygon with ID 5100 at 2640357790656>
Hi @ferdinand
Thanks for the respond.
RE: Caches do not exist for freshly allocated objects
Ah gotcha. Thanks for the confirmation.
Based on your reply, I can do it through a python script (i.e. insert the object temporarily and just destroy it or something like that).
But how do I go about it on Python Generator object? Is it possible?
Ultimately, what I want is to have a procedural text object that allows me to modify the extrude parameter of each letter. Currently, the extrude parameter of a default text object applies to all letters.
Hi,
I have a Text
object inside the Python Generator. I want to "bake" down (or equivalent to current state object commant) the text object so I can access it further but the GetCache
seems to return none.
# inside the python generator
def main() -> c4d.BaseObject:
text = c4d.BaseObject(1019268)
text[c4d.PRIM_TEXT_TEXT] = "Generator"
print (text.GetCache()) # returns None
clone = text.GetClone()
print (clone.GetCache()) # returns None
# I also tried the `SendModellingCommand` but it gives me `False` instead of `True`
base = c4d.utils.SendModelingCommand(c4d.MCOMMAND_CURRENTSTATETOOBJECT,[clone],c4d.MODELINGCOMMANDMODE_ALL,c4d.BaseContainer(),clone.GetDocument())
print (clone) # returns False instead of True
I'm guessting there is a prerequisite on the operation.
What am I missing?
yea python is much more forgiving than C++. i was just wondering if there was an already existing API for such task.
Okay. Manage it figure moving it without using the MoveKey. Still verbose though
import c4d
def main():
obj = doc.GetActiveObject()
desc_x = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_POSITION, c4d.DTYPE_VECTOR, 0),
c4d.DescLevel(c4d.VECTOR_X, c4d.DTYPE_REAL, 0))
track = obj.FindCTrack(desc_x)
curve = track.GetCurve()
key_count = curve.GetKeyCount()
fps = 24
offset_frame = 2
for index, value in enumerate(range(key_count)):
key = curve.GetKey(index)
time = key.GetTime()
frame = (time.GetFrame(fps))
new_frame = frame + offset_frame
new_time = c4d.BaseTime(new_frame/fps)
key.SetTime(curve, new_time)
c4d.EventAdd()
main()
Hi,
Is there an easy way to offset an animation of an object?
For example, I have a position.x track keyframe to from 5 to 10.
I just want to offset it by 2 frames through python.
Is there a one liner to do it? c4d.MoveTrack(frame=2) or something?
Haven't tried it but there is CCurve.MoveKey or something.
So it woud be like. Get Track. Get Curve. Get Key shenanigan. Loop through those keys. Loop through those curves etc.
I just really want to offset it Track.
Is there an easier of doing that?
P.S. And I think there's no sample code on how to do it in the forum or in the documentation.
Hi @ferdinand
Apologies for the late response.
RE: You should show me how you access that key.
My bad. But it's on the previous thread you answered by manually selecting a keyframe and storign it in a variable.
https://developers.maxon.net/forum/topic/15344/get-selected-keyframes/3
RE: I just showed you above how to operate with percentage values in Cinema 4D.
My bad. I missed it. I was looking immediately at the declaration.
keyA: c4d.CKey
keyB: c4d.CKey
which I only want one key to be declared.
===
In summary, the GetNext() and GetPred() solved the problem in getting the Neighboring Keys from a Selected Key.
Hi @ferdinand
Thanks for the response:
Basically, in your script:
keyA and keyB is already declared.
In my case, I only want keyB declared (as it is being detected). and have a script determine the neighbor key (which is keyA).
Is that possible?
I just need the neighboring keys so I can normalize the tangents to a 0 to 1 value.
For reference, houdini has set its tangent in 0 to 1 (or in percentage) so it can easily modified.
Hi,
Is there a way to get the neighboring key from a selected key?
My end goal is to set the key tangent of a selected key.
Apparently, the value to be set is not in percentage but in actual value relative to the neighboring keys. Hence the question.
Is this possible?
Slr. I can confirm the "Select2" works as expected.
Just want to point out though. That option is present in the documentation but doesn't have a proper description (?).
It's set to Private.
https://developers.maxon.net/docs/py/2024_2_0/consts/NBIT.html?highlight=nbit_tl1_select
Thanks for the response. This is probably the info I missed out:
CKey is a C4DAtom and a GeListNode, but not a BaseList2D, which is a quite uncommon thing
I tried your code but I'm not sure if its a bug.
If I select a key in the timeline (dope sheet mode). It works.
But if I select a key in the timeline (fcurve sheet mode). It doesn't.
(It spits out a value but the value it spits out is the last selected key in dopesheet and not the actively selected key in fcurve)
So I'm guessing I need to replace NBIT_TL1_SELECT
with NBIT_TL1_FCSELECT
but it still doesn't work.
Am I missing something?
Hi,
Is there now an API in getting the selected keyframe?
Much like doc.GetActiveObjects
or doc.GetActiveMaterials
My end goal operation is change the tangent handles (in the graph editor) of the selected kefyrames.
The closest solution is in this thead (https://developers.maxon.net/forum/topic/10989/how-to-get-the-selected-keyframes-in-active-timeline-fcurve-manager/7)
But it doesn't work on the latest versions of Cinema4D (even if you changed it to Python 3 syntax).
Is there a way around this?
@Dunhou
Thanks for the reference but yea I'm unfortunately using the xpresso here instead of the new node editor.
Which in all regards, an unfortunate scenario is xpresso is not integrated to the new node editor.
@m_adam
Gotcha. Thanks. Looking forward to the update.
Thanks for the confirmation.
I guess I'll just let the users do some reordering the nodes themselves. lol
The nodes are creating procedurally so the nodes are just stacked on top of each other. haha