Hello,
I'm searching if there a method to dynamically change the HandleInfo.direction depend on the rotation and pitch value of my object. I created the following object plugin example to illustrate exactly what I want to do.
Screen video:
pyp file:
import c4d, os
from c4d import utils, DescID, BaseObject, bitmaps, plugins, Vector, HandleInfo
from math import radians
PLUGIN_ID = 1055615
class Osobject(plugins.ObjectData):
def Init(self, op):
self.fs_mg = c4d.Matrix()
self.head_obj_h = 36
data = op.GetDataInstance()
data.SetFloat(c4d.OSOBJECT_SIZEX, 60.0)
data.SetFloat(c4d.OSOBJECT_SIZEY, 50.0)
data.SetFloat(c4d.OSOBJECT_DEPTH, 50.0)
data.SetFloat(c4d.OSOBJECT_PITCH, radians(-30))
data.SetFloat(c4d.OSOBJECT_ROTATION, radians(90))
return True
def GetVirtualObjects(self, op, hh):
dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTY_MATRIX | c4d.DIRTY_DATA)
if not dirty:
return op.GetCache(hh)
data = op.GetDataInstance()
size_x = data.GetFloat(c4d.OSOBJECT_SIZEX)
size_y = data.GetFloat(c4d.OSOBJECT_SIZEY)
depth = data.GetFloat(c4d.OSOBJECT_DEPTH)
pitch = data.GetFloat(c4d.OSOBJECT_PITCH)
rotation = data.GetFloat(c4d.OSOBJECT_ROTATION)
container = BaseObject(c4d.Onull)
container.SetRelPos(Vector(0, 40, 0))
bar = BaseObject(c4d.Ocylinder)
bar.SetName("bar")
bar.InsertUnder(container)
bar.SetParameter(DescID(c4d.PRIM_CYLINDER_RADIUS), 1.5, c4d.DESCFLAGS_GET_0)
bar.SetParameter(DescID(c4d.PRIM_CYLINDER_HEIGHT), 40, c4d.DESCFLAGS_GET_0)
bar.SetParameter(DescID(c4d.PRIM_AXIS), 2, c4d.DESCFLAGS_GET_0)
bar.SetRelPos(Vector(0, -20, 0))
# Rotation Object
rot_obj = BaseObject(c4d.Onull)
rot_obj.SetRelRot(Vector(rotation, 0, 0))
rot_obj.SetName("rotation")
rot_obj.InsertUnder(container)
# Pith Object
pitch_obj = BaseObject(c4d.Onull)
pitch_obj.SetRelRot(Vector(0, pitch, 0))
pitch_obj.SetName("pitch")
pitch_obj.InsertUnder(rot_obj)
# Head Container
head_container = BaseObject(c4d.Onull)
head_container.SetName("head_container")
head_container.InsertUnder(pitch_obj)
# Head Object
head_obj = BaseObject(c4d.Ocylinder)
head_obj.SetName("head")
head_obj.InsertUnder(head_container)
head_obj.SetParameter(DescID(c4d.PRIM_CYLINDER_RADIUS), 10, c4d.DESCFLAGS_GET_0)
head_obj.SetParameter(DescID(c4d.PRIM_CYLINDER_HEIGHT), self.head_obj_h, c4d.DESCFLAGS_GET_0)
head_obj.SetParameter(DescID(c4d.PRIM_AXIS), 5, c4d.DESCFLAGS_GET_0)
# depth Object
depth_obj = BaseObject(c4d.Ocylinder)
depth_obj.SetName("cyl")
depth_obj.InsertUnder(head_container)
depth_obj.SetParameter(DescID(c4d.PRIM_CYLINDER_RADIUS), 3, c4d.DESCFLAGS_GET_0)
depth_obj.SetParameter(DescID(c4d.PRIM_CYLINDER_HEIGHT), depth, c4d.DESCFLAGS_GET_0)
depth_obj.SetParameter(DescID(c4d.PRIM_AXIS), 5, c4d.DESCFLAGS_GET_0)
depth_obj_pos = self.head_obj_h/2 + depth/2
depth_obj.SetRelPos(Vector(0, 0, depth_obj_pos))
# Front Surface Object
fs_obj = BaseObject(c4d.Oplane)
fs_obj.SetName("front_surface")
fs_obj.InsertUnder(head_container)
self.fs_mg = fs_obj.GetMg()
fs_obj.SetParameter(DescID(c4d.PRIM_PLANE_WIDTH), size_x, c4d.DESCFLAGS_GET_0)
fs_obj.SetParameter(DescID(c4d.PRIM_PLANE_HEIGHT), size_y, c4d.DESCFLAGS_GET_0)
fs_obj.SetParameter(DescID(c4d.PRIM_PLANE_SUBW), 1, c4d.DESCFLAGS_GET_0)
fs_obj.SetParameter(DescID(c4d.PRIM_PLANE_SUBH), 1, c4d.DESCFLAGS_GET_0)
fs_obj.SetParameter(DescID(c4d.PRIM_AXIS), 5, c4d.DESCFLAGS_GET_0)
fs_obj_pos = self.head_obj_h/2 + depth
fs_obj.SetRelPos(Vector(0, 0, fs_obj_pos))
return container
def GetHandleCount(self, op):
return 4
def GetHandle(self, op, handle_index, info):
data = op.GetDataInstance()
size_x = data.GetFloat(c4d.OSOBJECT_SIZEX)
size_y = data.GetFloat(c4d.OSOBJECT_SIZEY)
depth = data.GetFloat(c4d.OSOBJECT_DEPTH)
pitch = data.GetFloat(c4d.OSOBJECT_PITCH)
rotation = data.GetFloat(c4d.OSOBJECT_ROTATION)
size_x = size_x/2
size_y = size_y/2
depth = depth+self.head_obj_h/2
mg = self.fs_mg
pos = mg.off
rot = utils.MatrixToHPB(mg, c4d.ROTATIONORDER_DEFAULT)
rot_mx = utils.HPBToMatrix(rot)
rot_mx.off += pos
if handle_index == 0: # Width
info.position = rot_mx * Vector(-size_x, 0, depth)
info.direction = Vector(1, 0, 0)
elif handle_index == 1: # Height
info.position = rot_mx * Vector(0, size_y, depth)
info.direction = Vector(0, 1, 0)
elif handle_index == 2: # Depth
info.position = rot_mx * Vector(0, 0, depth)
info.direction = Vector(0, 0, 1)
info.type = c4d.HANDLECONSTRAINTTYPE_LINEAR
def SetHandle(self, op, handle_index, handle_position, info):
handle_origin = HandleInfo()
self.GetHandle(op, handle_index, handle_origin)
data = op.GetDataInstance()
size_x = data.GetFloat(c4d.OSOBJECT_SIZEX)
size_y = data.GetFloat(c4d.OSOBJECT_SIZEY)
depth = data.GetFloat(c4d.OSOBJECT_DEPTH)
pitch = data.GetFloat(c4d.OSOBJECT_PITCH)
rotation = data.GetFloat(c4d.OSOBJECT_ROTATION)
size_x = size_x/2
size_y = size_y/2
value = (handle_position - handle_origin.position) * info.direction
if handle_index == 0:
op[c4d.OSOBJECT_SIZEX] -= value
elif handle_index == 1:
op[c4d.OSOBJECT_SIZEY] += value
elif handle_index == 2:
op[c4d.OSOBJECT_DEPTH] -= value
def Draw(self, op, drawpass, bd, bh):
if drawpass != c4d.DRAWPASS_HANDLES:
return c4d.DRAWRESULT_SKIP
data = op.GetDataInstance()
size_x = data.GetFloat(c4d.OSOBJECT_SIZEX)
size_y = data.GetFloat(c4d.OSOBJECT_SIZEY)
depth = data.GetFloat(c4d.OSOBJECT_DEPTH)
pitch = data.GetFloat(c4d.OSOBJECT_PITCH)
rotation = data.GetFloat(c4d.OSOBJECT_ROTATION)
size_x = size_x/2
size_y = size_y/2
bd.SetMatrix_Matrix(op, bh.GetMg())
hitid = op.GetHighlightHandle(bd)
for i in xrange(self.GetHandleCount(op)):
bd.SetPen(c4d.GetViewColor(c4d.VIEWCOLOR_ACTIVEPOINT))
info = HandleInfo()
self.GetHandle(op, i, info)
bd.DrawHandle(info.position, c4d.DRAWHANDLE_BIG, 0)
bd.SetMatrix_Matrix(op, bh.GetMg())
return c4d.DRAWRESULT_OK
if __name__ == "__main__":
icon = bitmaps.BaseBitmap()
icon.InitWith(os.path.join(os.path.dirname(__file__), 'res', 'icon.tif'))
plugins.RegisterObjectPlugin(PLUGIN_ID, 'Super Object', Osobject, 'osobject', c4d.OBJECT_GENERATOR, icon)
And here the full example files: osobject.zip
Thanks