Jimstein
10-03-2011, 07:30 PM
This script is an attempt to replicate the keying behavior I got used to in Lightwave3D, in combination with a hotkey the script or plugin becomes a very powerful workflow enhancement
This is a Python-”shortcut”-script for manually picking and setting a key with KeyFrameSelection on translate/rotate/scale. Instead of keying everything (like the Record button does by setting a key on every channel) this will only record the motion channels you've enabled; not dense keying. As an added bonus you dont have to move the time scrubber before generating the keys, this means that the current frame is the key generating source frame but you decide on what frame the keys will be inserted at, so you do not need to be afraid of overwriting the keys on the current frame just because you did forget to move the time slider to the location you want to insert the key.
Updated script and plugin on the 27th of October 2011
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import c4d
from c4d import gui
# -------------------------------------------
# GLOBALS
# -------------------------------------------
# unique ID
PLUGIN_VERSION = 1.01
PLUGIN_NAME = "SpaKey"
PLUGIN_HELP = "Sparse Keyframe"
PLUGIN_ABOUT = """
(C) 2011 Jimmy Esbjörnsson jimstein3d@hotmail.com
This is a Python-”shortcut”-script for manually picking and setting a key with KeyFrameSelection on translate/rotate/scale. Instead of keying everything (like the Record button does by setting a key on every channel) this will only record the motion channels you've enabled; not dense keying. As an added bonus you dont have to move the time scrubber before generating the keys, this means that the current frame is the key generating source frame but you decide on what frame the keys will be inserted at, so you do not need to be afraid of overwriting the keys on the current frame just because you did forget to move the time slider to the location you want to insert the key.
This script is an attempt to replicate the keying behavior I got used to in Lightwave3D
I don't consider this script finished so suggestions and/or improvements are welcome.
"""
# Element IDs
GROUP_ID1=1000
FRAME=1001
KEY=1002
PX=1004
PY=1005
PZ=1006
RX=1007
RY=1008
RZ=1009
SX=1010
SY=1011
SZ=1012
# ------------------------------------------------------
# User Interface
# ------------------------------------------------------
class SpaKeysDialog(gui.GeDialog):
def CreateLayout(self):
#creat the layout of the dialog
self.GroupBegin(GROUP_ID1, c4d.BFH_SCALEFIT, 3, 1)
self.AddCheckbox(PX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.X")
self.AddCheckbox(PY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.Y")
self.AddCheckbox(PZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.Z")
self.AddCheckbox(RX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.H")
self.AddCheckbox(RY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.P")
self.AddCheckbox(RZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.B")
self.AddCheckbox(SX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.X")
self.AddCheckbox(SY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.Y")
self.AddCheckbox(SZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.Z")
self.AddButton(KEY, c4d.BFH_SCALEFIT, name="Create Key At")
self.AddEditNumberArrows(FRAME, c4d.BFH_SCALEFIT)
self.GroupEnd()
return True
def InitValues(self):
#initiate the gadgets with values
self.SetTitle("SpaKey")
self.SetReal(FRAME, doc.GetTime().GetFrame(doc.GetFps()))
self.SetBool(PX,False)
self.SetBool(PY,False)
self.SetBool(PZ,False)
self.SetBool(RX,False)
self.SetBool(RY,False)
self.SetBool(RZ,False)
self.SetBool(SX,False)
self.SetBool(SY,False)
self.SetBool(SZ,False)
return True
def Command(self, id, msg):
#handle user input
if id==KEY:
posOn = c4d.IsCommandChecked(12417) # Position
scaleOn = c4d.IsCommandChecked(12418) # Scale
rotOn = c4d.IsCommandChecked(12419) # Rotation
#turn on
if posOn is False: c4d.CallCommand(12417) # Position
if scaleOn is False: c4d.CallCommand(12418) # Scale
if rotOn is False: c4d.CallCommand(12419) # Rotation
frame = int(self.GetReal(FRAME)) #int(gui.RenameDialog(frame))
doc.SetTime(c4d.BaseTime(frame, doc.GetFps())) #sets time slider to frame 0
selected = doc.GetActiveObjects(False) #Find the active objects
if len(selected) == 0:
gui.MessageDialog("You must select an Object!")
return False
doc.StartUndo()
for obj in selected:
obj.ClearKeyframeSelection() #Clears the Keyframe Selections
if self.GetBool(PX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(PY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(PZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
c4d.CallCommand(12410) #Record Button
obj.ClearKeyframeSelection() #Clears the Keyframe Selections
#turn back off
if posOn is False: c4d.CallCommand(12417) # Position
if scaleOn is False: c4d.CallCommand(12418) # Scale
if rotOn is False: c4d.CallCommand(12419) # Rotation
c4d.EventAdd()
doc.EndUndo()
if (c4d.GetC4DVersion() < 13000):
self.Close()
return True
# ----------------------------------------------------
# Main
# ----------------------------------------------------
if __name__=='__main__':
dlg = SpaKeysDialog()
if (c4d.GetC4DVersion() < 13000):
#R12 version...R12 doesn't support ASYNC dialogs
dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=50, defaulth=50)
else:
dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=50, defaulth=50)
c4d.EventAdd()
This is a Python-”shortcut”-script for manually picking and setting a key with KeyFrameSelection on translate/rotate/scale. Instead of keying everything (like the Record button does by setting a key on every channel) this will only record the motion channels you've enabled; not dense keying. As an added bonus you dont have to move the time scrubber before generating the keys, this means that the current frame is the key generating source frame but you decide on what frame the keys will be inserted at, so you do not need to be afraid of overwriting the keys on the current frame just because you did forget to move the time slider to the location you want to insert the key.
Updated script and plugin on the 27th of October 2011
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import c4d
from c4d import gui
# -------------------------------------------
# GLOBALS
# -------------------------------------------
# unique ID
PLUGIN_VERSION = 1.01
PLUGIN_NAME = "SpaKey"
PLUGIN_HELP = "Sparse Keyframe"
PLUGIN_ABOUT = """
(C) 2011 Jimmy Esbjörnsson jimstein3d@hotmail.com
This is a Python-”shortcut”-script for manually picking and setting a key with KeyFrameSelection on translate/rotate/scale. Instead of keying everything (like the Record button does by setting a key on every channel) this will only record the motion channels you've enabled; not dense keying. As an added bonus you dont have to move the time scrubber before generating the keys, this means that the current frame is the key generating source frame but you decide on what frame the keys will be inserted at, so you do not need to be afraid of overwriting the keys on the current frame just because you did forget to move the time slider to the location you want to insert the key.
This script is an attempt to replicate the keying behavior I got used to in Lightwave3D
I don't consider this script finished so suggestions and/or improvements are welcome.
"""
# Element IDs
GROUP_ID1=1000
FRAME=1001
KEY=1002
PX=1004
PY=1005
PZ=1006
RX=1007
RY=1008
RZ=1009
SX=1010
SY=1011
SZ=1012
# ------------------------------------------------------
# User Interface
# ------------------------------------------------------
class SpaKeysDialog(gui.GeDialog):
def CreateLayout(self):
#creat the layout of the dialog
self.GroupBegin(GROUP_ID1, c4d.BFH_SCALEFIT, 3, 1)
self.AddCheckbox(PX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.X")
self.AddCheckbox(PY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.Y")
self.AddCheckbox(PZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="P.Z")
self.AddCheckbox(RX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.H")
self.AddCheckbox(RY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.P")
self.AddCheckbox(RZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="R.B")
self.AddCheckbox(SX, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.X")
self.AddCheckbox(SY, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.Y")
self.AddCheckbox(SZ, c4d.BFH_SCALEFIT, initw=0, inith=0, name="S.Z")
self.AddButton(KEY, c4d.BFH_SCALEFIT, name="Create Key At")
self.AddEditNumberArrows(FRAME, c4d.BFH_SCALEFIT)
self.GroupEnd()
return True
def InitValues(self):
#initiate the gadgets with values
self.SetTitle("SpaKey")
self.SetReal(FRAME, doc.GetTime().GetFrame(doc.GetFps()))
self.SetBool(PX,False)
self.SetBool(PY,False)
self.SetBool(PZ,False)
self.SetBool(RX,False)
self.SetBool(RY,False)
self.SetBool(RZ,False)
self.SetBool(SX,False)
self.SetBool(SY,False)
self.SetBool(SZ,False)
return True
def Command(self, id, msg):
#handle user input
if id==KEY:
posOn = c4d.IsCommandChecked(12417) # Position
scaleOn = c4d.IsCommandChecked(12418) # Scale
rotOn = c4d.IsCommandChecked(12419) # Rotation
#turn on
if posOn is False: c4d.CallCommand(12417) # Position
if scaleOn is False: c4d.CallCommand(12418) # Scale
if rotOn is False: c4d.CallCommand(12419) # Rotation
frame = int(self.GetReal(FRAME)) #int(gui.RenameDialog(frame))
doc.SetTime(c4d.BaseTime(frame, doc.GetFps())) #sets time slider to frame 0
selected = doc.GetActiveObjects(False) #Find the active objects
if len(selected) == 0:
gui.MessageDialog("You must select an Object!")
return False
doc.StartUndo()
for obj in selected:
obj.ClearKeyframeSelection() #Clears the Keyframe Selections
if self.GetBool(PX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(PY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(PZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(SZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_SCALE), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RX) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_X))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RY) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_Y))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
if self.GetBool(RZ) is True:
id = c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION), c4d.DescLevel(c4d.VECTOR_Z))
obj.SetKeyframeSelection(id, 1) #Adds a Keyframe Selection
c4d.CallCommand(12410) #Record Button
obj.ClearKeyframeSelection() #Clears the Keyframe Selections
#turn back off
if posOn is False: c4d.CallCommand(12417) # Position
if scaleOn is False: c4d.CallCommand(12418) # Scale
if rotOn is False: c4d.CallCommand(12419) # Rotation
c4d.EventAdd()
doc.EndUndo()
if (c4d.GetC4DVersion() < 13000):
self.Close()
return True
# ----------------------------------------------------
# Main
# ----------------------------------------------------
if __name__=='__main__':
dlg = SpaKeysDialog()
if (c4d.GetC4DVersion() < 13000):
#R12 version...R12 doesn't support ASYNC dialogs
dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=50, defaulth=50)
else:
dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=50, defaulth=50)
c4d.EventAdd()
