Selected Keys? Move Keys?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 23/02/2011 at 21:55, xxxxxxxx wrote:
Now, i got it all work. Only thing missing is the GetNBit, cause I have not enough Time now. I'll post the full code later on.
But a look in the SDK makes me think that CKeys doesn't have the function GetNBit because it's a method of the GeListNode Class.. ?PS: Still don't understand why you used an Invers Iteration.
//edit:
So, here's the complete function:
Even with Undo-Functionalitydef MoveSelectedKeys(op,offset,timeln = 1) : # offset in frames import c4d if (not op) or (not offset) : return False if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) MoveSelectedKeys(op,offset,timeln) doc = op.GetDocument() doc.StartUndo() track = op.GetFirstCTrack() if not track: return False fps = float(doc.GetFps()) while track: curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(i) if key.GetNBit(int(timeln)) == True: tme = key.GetTime() doc.AddUndo(c4d.UNDOTYPE_CHANGE,op) key.SetTime(curve,c4d.BaseTime(offset/fps+tme.Get())) track = track.GetNext() doc.EndUndo() c4d.EventAdd(c4d.MSG_UPDATE) return True
Is there a bit for keys in the "usual" timeline ? This one does only affect the selected keys in the Manager ..
Cheers, nux
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 24/02/2011 at 07:56, xxxxxxxx wrote:
Good job nux.
I like how you implemented the other timeline windows.I needed to use a reverse loop in Coffee because if I had for example: keys ten frames apart and an offset value of ten. The first key would get moved on top of the last key. Then when the loop came around a second time. The keys were all on the same frame and it couldn't figure out what to move.
I didn't know of any other way to do it.Deepshade,
Just in case you don't know this. What nux posted is a method.
So if you want to use this in the python script manager. You paste it above the def main section.
Then call to the method like this:def main() : obj = doc.GetActiveObject() offset = 15 #change this value as needed MoveSelectedKeys(obj,offset,timeln = 1) if __name__=='__main__': main()
-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 24/02/2011 at 08:34, xxxxxxxx wrote:
OMG - just dropped in for a look. Middle of some exhibition visual at present. Back this evening. Will have a good read later.
cheers all
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 24/02/2011 at 08:34, xxxxxxxx wrote:
Let me add, that in the SkriptManager op is automatically the selected Object.
And you don't need to overload the timeln since you don't want timeline 2,3 or 4.
So this works too:import c4d def main() : offset = 15 #change this value as needed MoveSelectedKeys(op,offset) if __name__=='__main__': main()
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 25/02/2011 at 03:47, xxxxxxxx wrote:
Hi All
Sorry for lack of contribution - yesterdays work over ran
try to get back to this as soon as job is out of the door -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 02:07, xxxxxxxx wrote:
Hi all
Finally escaped from the last job.
A couple of things
1
Confusion
Just to confirm - the original concept was for staggered keys on multiple objects
Don't get me wrong - not complaining - just need to be clear what I'm seeingThe code is there in the while loop looks like it iterates through all the tracks of a single selected object.
If I select more than one object - nothing happens? (no provision in script so far)2
I'd assume (if you want to modify keys differently for different objects) it would be better to write a small function
and modify the Key value before running Key.SetTime(...etc
dependent on the number of selected tracks
Sadly I cant see a way to return the count of selected tracks (yes Scott I now see the route) - so I guess
the whole things needs to run in an outer loop - iterating through the selected objects?Another issue - if you modify the offset inside the While track loop
ie after
key.SetTime..
with something as simple as offset = offset + 10
Assuming you have a POS ROT SCALE tracks as well
Selecting all tracks is fine
Selecting just one track ie POS - inserts two extra sets of keyframes
as the while loop count is based on the total number of tracks
Cant see a simple solution3
can't find reference to
C4d.NBIT_TL1_SELECT in the SDK - I take it these refer to the 4 timelines
Where did you get that info pls?def MoveSelectedKeys(op,offset,timeln = 1) : # offset in frames import c4d if (not op) or (not offset) : return False if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) MoveSelectedKeys(op,offset,timeln) doc = op.GetDocument() doc.StartUndo() track = op.GetFirstCTrack() if not track: return False fps = float(doc.GetFps()) while track: curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(i) if key.GetNBit(int(timeln)) == True: tme = key.GetTime() doc.AddUndo(c4d.UNDOTYPE_CHANGE,op) key.SetTime(curve,c4d.BaseTime(offset/fps+tme.Get())) track = track.GetNext() doc.EndUndo() c4d.EventAdd(c4d.MSG_UPDATE) return True import c4d def main() : offset = 50 #change this value as needed MoveSelectedKeys(op,offset) if __name__=='__main__': main()
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 03:06, xxxxxxxx wrote:
1:
You can simply use the function in an iteration through the selected objects.What means staggered ? Don't know the word ^^
2:
Why modifieng the
key value ? I thought it's about moving keys ?
And what do you want to achieve with offset = offset + 10Don't select a track, select the keys.
3:
It's in the GetNBits() function. Search for it without the c4d. in front.I'll can answer your questions better later when im at home in about 2 hours.
Till then,cheers
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 04:32, xxxxxxxx wrote:
What means staggered ? Don't know the word ^^
All explained here
http://forums.cgsociety.org/showthread.php?f=182&t=959094
with sample file (first post)file shows example of before and after stagger
hth
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 05:23, xxxxxxxx wrote:
Ah, you mean the 2nd Cube should start moving when the 1st one finished ?
That shouldn't be a problem.
I'll be back in a minute with a function doing this.cheers
PS: Do still only the selected keys need to be moved ?
//So, this is a bit more complex than i thought.
But it works fineimport c4d from c4d import documents overlap = 20 ## Change this to the Frame you want to let the keys beeing overlapped def MoveSelectedKeys(op,offset,timeln = 1) : # offset in frames import c4d if (not op) or (not offset) : return False if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) MoveSelectedKeys(op,offset,timeln) doc = op.GetDocument() track = op.GetFirstCTrack() if not track: return False fps = float(doc.GetFps()) while track: curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(i) if key.GetNBit(int(timeln)) == True: tme = key.GetTime() key.SetTime(curve,c4d.BaseTime(offset/fps+tme.Get())) track = track.GetNext() c4d.EventAdd(c4d.MSG_UPDATE) return True def GetLastSelectedKey(track, timeln = 1) : import c4d if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) MoveSelectedKeys(op,offset,timeln) curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(cnt-i-1) if key.GetNBit(int(timeln)) == True: return key def GetHNext(op) : if not op: return if op.GetDown() : return op.GetDown() while not op.GetNext() and op.GetUp() : op = op.GetUp() return op.GetNext() def GetActiveObjects(doc) : import c4d lst = list() op = doc.GetFirstObject() while op: if op.GetBit(c4d.BIT_ACTIVE) == True: lst.append(op) op = GetHNext(op) return lst def main() : doc = documents.GetActiveDocument() doc.StartUndo() lst = GetActiveObjects(doc) op = lst[0] if not op: return False key = GetLastSelectedKey(op.GetFirstCTrack()) if not key: offset = 0 else: offset = key.GetTime().GetFrame(doc.GetFps())-overlap for i in xrange(len(lst)) : doc.AddUndo(c4d.UNDOTYPE_CHANGE,op) MoveSelectedKeys(op,offset) key = GetLastSelectedKey(op.GetFirstCTrack()) if not key: offset = 0 else: offset = key.GetTime().GetFrame(doc.GetFps())-overlap print op.GetName() op = lst[i+1] doc.EndUndo() if __name__=='__main__': main()
Here a tiny Screencast to show you how to use it:
" target="_blank" rel="noopener noreferrer nofollow ugc">
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 12:08, xxxxxxxx wrote:
Hey Nux95
This is just great
And there's so much useful stuff here for reference
It's really appreciated - many thanksline 103
op=list[i+1]
is throwing an error
index out of rangeI guess this is just incrementing one object too many? at the end of the selected objects
Not wanting to take anything away from what you've done here - far beyond the call of duty
I think it would be nice to have the 'processing' part of the script possibly
in a functionie release a collection of key manipulating scripts - by just changing the function
stagger - by offset - as we have now
stagger - by total time - total time over which to stagger all frames
stagger exponentially large to small
stagger exponentially small to large
etc etccheers again
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2011 at 13:22, xxxxxxxx wrote:
Originally posted by xxxxxxxx
line 103
op=list[i+1]
is throwing an error
index out of rangeDo you recieve that message every time ? It didn't appear when I was using the Script.
I guess this is just incrementing one object too many? at the end of the selected objects
Shouldnt. 'op' is already the object with index 0, and 'i' starts with '0', so the next object for 'op' in the first iteration should be 1 => 'i+1'
But .. Hm, very bizarre. I didn't recieve that error, but as I think about it, that error MUST occure at the end of the loop.
Try it like this and tell me if the problen still exists:op = lst[i+1] if not op: break # Hopefully there is a 'break' expression for 'for'-loops. If not try something that stops the loop
stagger - by total time - total time over which to stagger all frames
stagger exponentially large to small
stagger exponentially small to large
etc etcWhy not writing a Plugin ?
cheers, nux
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/02/2011 at 03:10, xxxxxxxx wrote:
Using
if i+1 < len(lst) : op = lst[i+1]
got rid of the index error
As far as writing a plugin. A bit beyond me at present, probably best to learn from your foundation work here Nux.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 27/02/2011 at 08:05, xxxxxxxx wrote:
Trying to move this on in a more modular way
ie have a function for each transformation on selected keysjust wondered if I was heading in the right direction???
(ignore print checkpoints just for testing)Next objective to 'nudge' everything back
as 'everything' gets moved over by staggering process
ie first track shouldnt move - everything else - stagger##################################### Updated version in later post
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 01/03/2011 at 00:42, xxxxxxxx wrote:
Making an effort to understand what I'm seeing
Line 14 function call within itself - seems incorrect?
MoveSelectedKeys(op,offset,timeln) -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 01/03/2011 at 07:21, xxxxxxxx wrote:
I am sorry, I may can go to my pc this weekend, but not earlier.
Does the Console tell you this ? O.o
If A function calls itself, everything starts again. But you may have changed some values before. (Here the timeln variable)
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/03/2011 at 01:03, xxxxxxxx wrote:
Can anyone tell me why this message
doesn't pop up if NO object is selected using the function from the code above?lst = GetActiveObjects(doc)
op = lst[0]
if not op:
gui.MessageDialog("No objects selected")
return False #leave the script if not an object -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/03/2011 at 02:37, xxxxxxxx wrote:
Dunnoo .. Gonna test this this weekend. Maybe it's because op = lst[0] ist not in the right column ?
lst = GetActiveObjects(doc) op = lst[0] ## here if not op: gui.MessageDialog("No objects selected") return False #leave the script if not an object
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/03/2011 at 03:03, xxxxxxxx wrote:
Hi Nux
nope, not that - must be forum paste incorrect
indent is as your exampleappreciate you can't test at moment
I think its to do with this function setting op to the first object in doc
if nothing selected
that way op is never NULL
#####################################
def GetActiveObjects(doc) :
import c4d
lst = list()
op = doc.GetFirstObject()
while op:
if op.GetBit(c4d.BIT_ACTIVE) == True: lst.append(op)
op = GetHNext(op)
return lst
##################################### -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/03/2011 at 03:22, xxxxxxxx wrote:
the list only gets appended if op is selected.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/03/2011 at 06:11, xxxxxxxx wrote:
And this is where I'm at so far
Ignore some Print items - just for console checks
Still trying to make it modular
ie have a function for each type of key transform - (just stagger in this one)
appreciate any advice on good/bad code formadded gui to take offset
count selected objects - need more than 2
and now first object doesnt get offset (its popped off array)##################################### def MoveSelectedKeys(op,offset,timeln = 1) : # offset in frames import c4d if (not op) or (not offset) : return False if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) doc = op.GetDocument() track = op.GetFirstCTrack() if not track: return False fps = float(doc.GetFps()) while track: curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(i) if key.GetNBit(int(timeln)) == True: tme = key.GetTime() key.SetTime(curve,c4d.BaseTime(offset/fps+tme.Get())) track = track.GetNext() c4d.EventAdd(c4d.MSG_UPDATE) return True ##################################### def GetLastSelectedKey(track, timeln = 1) : import c4d if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) curve = track.GetCurve() cnt = curve.GetKeyCount() for i in xrange(cnt) : key = curve.GetKey(cnt-i-1) if key.GetNBit(int(timeln)) == True: return key ####################################MINE def GetFirstSelectedKey(track, timeln = 1) : import c4d if timeln == 1: timeln = c4d.NBIT_TL1_SELECT elif timeln == 2: timeln = c4d.NBIT_TL2_SELECT elif timeln == 3: timeln = c4d.NBIT_TL3_SELECT elif timeln == 4: timeln = c4d.NBIT_TL4_SELECT else: import math timeln = math.fmod(timeln,4) curve = track.GetCurve() cnt = curve.GetKeyCount() key = curve.GetKey(0) if key.GetNBit(int(timeln)) == True: return key ##################################### def GetHNext(op) : if not op: return if op.GetDown() : return op.GetDown() while not op.GetNext() and op.GetUp() : op = op.GetUp() return op.GetNext() ##################################### def GetActiveObjects(doc) : import c4d lst = list() op = doc.GetFirstObject() while op: if op.GetBit(c4d.BIT_ACTIVE) == True: lst.append(op) op = GetHNext(op) return lst #####################################MINE def Stagger(doc,op,lst,keylast,overlap) : import c4d print "Length of list before pop", len(lst) lst.pop(0) #remove the first object as its not moved op = lst[0] #get fist active object again, less original first object print "Length of list after pop", len(lst) offset = keylast.GetTime().GetFrame(doc.GetFps())-overlap for i in xrange(len(lst)) : #increment through allthe objects selected doc.AddUndo(c4d.UNDOTYPE_CHANGE,op) MoveSelectedKeys(op,offset) #moves all the selected keys on a track keylast = GetLastSelectedKey(op.GetFirstCTrack()) if not keylast: offset = 0 # the original cal moved everything # else: offset = key.GetTime().GetFrame(doc.GetFps())-overlap else: print "OS1", offset offset = keylast.GetTime().GetFrame(doc.GetFps())-overlap print "OS2", offset # object namecheck # print op.GetName() if i+1 < len(lst) : # +1 stops index going out of range ie more objects than listed op = lst[i+1]# ok to get next object in list return ##################################### def main() : import c4d from c4d import documents from c4d import gui c4d.CallCommand(1024314); # clear the python console # get a value form the user guival = gui.InputDialog("Enter a value < your max keyspan","10") print "Dialog Value =",guival overlap = int(guival) doc = documents.GetActiveDocument() doc.StartUndo() lst = GetActiveObjects(doc) #get selected objects print "List Length = ", len(lst) if len(lst)<=1: c4d.gui.MessageDialog("You need to select at least two objects") return False #leave if not enough objects selected op = lst[0] #get fist active object keyfirst = GetFirstSelectedKey(op.GetFirstCTrack()) keylast = GetLastSelectedKey(op.GetFirstCTrack()) keyfirstval = keyfirst.GetTime().GetFrame(doc.GetFps()) keylastval = keylast.GetTime().GetFrame(doc.GetFps()) keyspanval = keylastval - keyfirstval print "Selected Keyspan 1st track = ", keyspanval print "Keytime of start key = ", keyfirstval print "Keytime of end key = ", keylastval if not keylast: offset = 0 ##### else do the stagger else: Stagger(doc,op,lst,keylast,overlap) doc.EndUndo() if __name__=='__main__': main()