hi,
I've created this example :
The first thing to do is to build an object without handle. Just create your parameters, and use them.
After that you can implement the handle that will changes those parameters. (and changing the parameter will change the handle).
I have a Float that will server me to store the rotation of the body, only on the Y axis, that's why I only need one float.
For the head, i'll store that in a vector.
The same idea must be done for scaling.
import math
import c4d
# Be sure to use a unique ID obtained from www.plugincafe.com
PLUGIN_ID = 1000001
OMINECHARAC_HEAD = 10000
OMINECHARAC_BODY = 10001
BODY_HEIGHT = 500
HEAD_HEIGHT = 100
class MineCharac(c4d.plugins.ObjectData):
"""CircleObject Generator"""
def Init(self, node):
"""
Called when Cinema 4D Initialize the ObjectData (used to define, default values)
:param node: The instance of the ObjectData.
:type node: c4d.GeListNode
:return: True on success, otherwise False.
"""
# Retrieves the BaseContainer Instance to set the default values
data = node.GetDataInstance()
if data is None:
return False
# Defines default values in the BaseContainer
data.SetVector(OMINECHARAC_HEAD, c4d.Vector(0))
data.SetFloat(OMINECHARAC_BODY, 0.0)
return True
"""========== Begin of Handle Management =========="""
def GetHandleCount(self, op):
"""
Called by Cinema 4D to retrieve the count of Handle the object will have.
:param op: The instance of the ObjectData.
:type op: c4d.BaseObject
:return: The number of handle
:rtype: int
"""
# One handle will be used for this object
return 2
def GetHandle(self, op, i, info):
"""
Called by Cinema 4D to retrieve the information of a given handle ID to represent a/some parameter(s).
:param op: The instance of the ObjectData.
:type op: c4d.BaseObject
:param i: The handle index.
:type i: int
:param info: The HandleInfo to fill with data.
:type info: c4d.HandleInfo
"""
# Retrieves the current BaseContainer
data = op.GetDataInstance()
if data is None:
return
# Defines the position, direction and type of the handle
radius = 250
# ID 0 will be head
if i == 0:
info.center = c4d.Vector(0, 600, 0)
position = data.GetVector(OMINECHARAC_HEAD)
mg = c4d.utils.HPBToMatrix(position)
info.position = info.center + ( mg.v3 * 100)
info.direction = data.GetVector(OMINECHARAC_HEAD)
info.type = c4d.HANDLECONSTRAINTTYPE_SPHERICAL
# ID 1 will be body
if i == 1:
sn, cs = c4d.utils.SinCos(data.GetFloat(OMINECHARAC_BODY))
info.position = c4d.Vector(-sn * radius, 0, cs * radius)
info.direction = c4d.Vector(0, 1, 0)
info.center = c4d.Vector(0, 0, 0)
info.type = c4d.HANDLECONSTRAINTTYPE_PLANAR
def SetHandle(self, op, i, p, info):
"""
Called by Cinema 4D when the user set the handle.
This is the place to retrieve the information of a given handle ID and drive your parameter(s).
:param op: The instance of the ObjectData.
:type op: c4d.BaseObject
:param i: The handle index.
:type i: int
:param p: The new Handle Position.
:type p: c4d.Vector
:param info: The HandleInfo filled with data.
:type info: c4d.HandleInfo
"""
data = op.GetDataInstance()
if data is None:
return
if i == 0:
hpb = c4d.utils.VectorToHPB(p - info.center)
data.SetVector(c4d.OMINECHARAC_HEAD, hpb)
if i == 1:
hpb = c4d.utils.VectorToHPB(p)
value = hpb.x
data.SetFloat(OMINECHARAC_BODY, value)
def Draw(self, op, drawpass, bd, bh):
"""
Called by Cinema 4d when the display is updated to display some visual element of your object in the 3D view.
This is also the place to draw Handle
:param op: The instance of the ObjectData.
:type op: c4d.BaseObject
:param drawpass:
:param bd: The editor's view.
:type bd: c4d.BaseDraw
:param bh: The BaseDrawHelp editor's view.
:type bh: c4d.plugins.BaseDrawHelp
:return: The result of the drawing (most likely c4d.DRAWRESULT_OK)
"""
# If the current draw pass is not the handle, skip this Draw Call.
if drawpass != c4d.DRAWPASS_HANDLES:
return c4d.DRAWRESULT_SKIP
# Defines the drawing matrix to the object matrix.
m = bh.GetMg()
bd.SetMatrix_Matrix(op, m)
# Checks if one of the handle of the current object is currently hovered by the mouse.
hitId = op.GetHighlightHandle(bd)
# Defines the color of the handle according of the hovered state of the object.
hoverColor = c4d.VIEWCOLOR_ACTIVEPOINT if hitId != 0 else c4d.VIEWCOLOR_SELECTION_PREVIEW
bd.SetPen(c4d.GetViewColor(hoverColor))
# Retrieves the information of the current handle.
infoHead = c4d.HandleInfo()
infoBody = c4d.HandleInfo()
self.GetHandle(op, 0, infoHead)
self.GetHandle(op, 1, infoBody)
# Draw the handle to the correct position
bd.DrawHandle(infoHead.position, c4d.DRAWHANDLE_BIG, 0)
bd.SetPen(c4d.GetViewColor( c4d.VIEWCOLOR_ACTIVEPOINT))
bd.DrawLine(infoHead.position, infoHead.center, 0)
self.GetHandle(op, 1, infoBody)
bd.DrawHandle(infoBody.position, c4d.DRAWHANDLE_BIG, 0)
bd.SetPen(c4d.GetViewColor( c4d.VIEWCOLOR_ACTIVEPOINT))
bd.DrawLine(infoBody.position, infoBody.center, 0)
return c4d.DRAWRESULT_OK
"""========== End of Handle Management =========="""
def GetVirtualObjects(self, op, hh):
dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTY_DATA)
if dirty is False:
return op.GetCache(hh)
parent = c4d.BaseObject(c4d.Onull)
data = op.GetDataInstance()
if data is None:
return
body_rotation = c4d.Vector(data.GetFloat(OMINECHARAC_BODY), 0, 0 )
body = c4d.BaseObject(c4d.Ocube)
body[c4d.PRIM_CUBE_LEN,c4d.VECTOR_Y] = BODY_HEIGHT
body.SetRelPos(c4d.Vector(0, BODY_HEIGHT * 0.5, 0))
body.SetRelRot(body_rotation)
head_rotation = data.GetVector(OMINECHARAC_HEAD)
head = c4d.BaseObject(c4d.Ocube)
head[c4d.PRIM_CUBE_LEN,c4d.VECTOR_Y] = HEAD_HEIGHT
head.SetRelPos(c4d.Vector(0,BODY_HEIGHT + HEAD_HEIGHT * 0.5 + 10 , 0))
head.SetRelRot(head_rotation)
head.InsertUnder(parent)
body.InsertUnder(parent)
return parent
if __name__ == "__main__":
# Registers the object plugin
c4d.plugins.RegisterObjectPlugin(id=PLUGIN_ID,
str="MineCharac",
g=MineCharac,
description="Ominecharac",
icon=None,
info=c4d.OBJECT_GENERATOR)
Cheers,
Manuel