Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
324 lines (254 sloc) 11.2 KB
"""
RoundedTube
Copyright: MAXON Computer GmbH
Written for Cinema 4D R18
Modified Date: 10/01/2017
"""
import os
import math
import sys
import c4d
from c4d import plugins, utils, bitmaps, gui
# Be sure to use a unique ID obtained from www.plugincafe.com
PLUGIN_ID = 1025250
class RoundedTube(plugins.ObjectData):
"""RoundedTube Generator"""
HANDLECOUNT = 5
def __init__(self):
self.SetOptimizeCache(True)
@staticmethod
def SetAxis(op, axis):
if axis is c4d.PRIM_AXIS_YP: return
padr = op.GetAllPoints()
if padr is None: return
elif axis is c4d.PRIM_AXIS_XP:
for i, p in enumerate(padr):
op.SetPoint(i, c4d.Vector( p.y, -p.x, p.z))
elif axis is c4d.PRIM_AXIS_XN:
for i, p in enumerate(padr):
op.SetPoint(i, c4d.Vector(-p.y, p.x, p.z))
elif axis is c4d.PRIM_AXIS_YN:
for i, p in enumerate(padr):
op.SetPoint(i, c4d.Vector(-p.x, -p.y, p.z))
elif axis is c4d.PRIM_AXIS_ZP:
for i, p in enumerate(padr):
op.SetPoint(i, c4d.Vector(p.x, -p.z, p.y))
elif axis is c4d.PRIM_AXIS_ZN:
for i, p in enumerate(padr):
op.SetPoint(i, c4d.Vector(p.x, p.z, -p.y))
op.Message(c4d.MSG_UPDATE)
@staticmethod
def SwapPoint(p, axis):
if axis is c4d.PRIM_AXIS_XP:
return c4d.Vector(p.y, -p.x, p.z)
elif axis is c4d.PRIM_AXIS_XN:
return c4d.Vector(-p.y, p.x, p.z)
elif axis is c4d.PRIM_AXIS_YN:
return c4d.Vector(-p.x, -p.y, p.z)
elif axis is c4d.PRIM_AXIS_ZP:
return c4d.Vector(p.x, -p.z, p.y)
elif axis is c4d.PRIM_AXIS_ZN:
return c4d.Vector(p.x, p.z, -p.y)
return p
def GetHandleCount(self, op):
return self.HANDLECOUNT
def GetHandle(self, op, i, info):
rad = op[c4d.PY_TUBEOBJECT_RAD]
if rad is None: rad = 200.0
iradx = op[c4d.PY_TUBEOBJECT_IRADX]
if iradx is None: iradx = 50.0
irady = op[c4d.PY_TUBEOBJECT_IRADY]
if irady is None: irady = 50.0
rrad = op[c4d.PY_TUBEOBJECT_ROUNDRAD]
if rrad is None: rrad = 10.0
axis = op[c4d.PRIM_AXIS]
if axis is None: return
if i is 0:
info.position = c4d.Vector(rad, 0.0, 0.0)
info.direction = c4d.Vector(1.0, 0.0, 0.0)
elif i is 1:
info.position = c4d.Vector(rad+iradx, 0.0, 0.0)
info.direction = c4d.Vector(1.0, 0.0, 0.0)
elif i is 2:
info.position = c4d.Vector(rad, irady, 0.0)
info.direction = c4d.Vector(0.0, 1.0, 0.0)
elif i is 3:
info.position = c4d.Vector(rad+iradx, irady-rrad, 0.0)
info.direction = c4d.Vector(0.0, -1.0, 0.0)
elif i is 4:
info.position = c4d.Vector(rad+iradx-rrad, irady, 0.0)
info.direction = c4d.Vector(-1.0, 0.0, 0.0)
info.position = RoundedTube.SwapPoint(info.position, axis)
info.direction = RoundedTube.SwapPoint(info.direction, axis)
info.type = c4d.HANDLECONSTRAINTTYPE_LINEAR
def SetHandle(self, op, i, p, info):
data = op.GetDataInstance()
if data is None: return
tmp = c4d.HandleInfo()
self.GetHandle(op, i, tmp)
val = (p-tmp.position)*info.direction
if i is 0:
op[c4d.PY_TUBEOBJECT_RAD] = utils.FCut(op[c4d.PY_TUBEOBJECT_RAD]+val, op[c4d.PY_TUBEOBJECT_IRADX], sys.maxint)
elif i is 1:
op[c4d.PY_TUBEOBJECT_IRADX] = utils.FCut(op[c4d.PY_TUBEOBJECT_IRADX]+val, op[c4d.PY_TUBEOBJECT_ROUNDRAD], op[c4d.PY_TUBEOBJECT_RAD])
elif i is 2:
op[c4d.PY_TUBEOBJECT_IRADY] = utils.FCut(op[c4d.PY_TUBEOBJECT_IRADY]+val, op[c4d.PY_TUBEOBJECT_ROUNDRAD], sys.maxint)
elif i is 3 or i is 4:
op[c4d.PY_TUBEOBJECT_ROUNDRAD] = utils.FCut(op[c4d.PY_TUBEOBJECT_ROUNDRAD]+val, 0.0, min(op[c4d.PY_TUBEOBJECT_IRADX], op[c4d.PY_TUBEOBJECT_IRADY]))
def Draw(self, op, drawpass, bd, bh):
if drawpass!=c4d.DRAWPASS_HANDLES: return c4d.DRAWRESULT_SKIP
rad = op[c4d.PY_TUBEOBJECT_RAD]
iradx = op[c4d.PY_TUBEOBJECT_IRADX]
irady = op[c4d.PY_TUBEOBJECT_IRADY]
axis = op[c4d.PRIM_AXIS]
bd.SetPen(c4d.GetViewColor(c4d.VIEWCOLOR_ACTIVEPOINT))
hitid = op.GetHighlightHandle(bd)
bd.SetMatrix_Matrix(op, bh.GetMg())
for i in xrange(self.HANDLECOUNT):
if i==hitid:
bd.SetPen(c4d.GetViewColor(c4d.VIEWCOLOR_SELECTION_PREVIEW))
else:
bd.SetPen(c4d.GetViewColor(c4d.VIEWCOLOR_ACTIVEPOINT))
info = c4d.HandleInfo()
self.GetHandle(op, i, info)
bd.DrawHandle(info.position, c4d.DRAWHANDLE_BIG, 0)
bd.SetPen(c4d.GetViewColor(c4d.VIEWCOLOR_ACTIVEPOINT))
if i is 0:
info2 = c4d.HandleInfo()
self.GetHandle(op, 1, info2)
bd.DrawLine(info.position, info2.position, 0)
self.GetHandle(op, 2, info2)
bd.DrawLine(info.position, info2.position, 0)
elif i is 3:
bd.DrawLine(info.position, RoundedTube.SwapPoint(c4d.Vector(rad+iradx, irady, 0.0), axis), 0)
elif i is 4:
bd.DrawLine(info.position, RoundedTube.SwapPoint(c4d.Vector(rad+iradx, irady, 0.0), axis), 0)
return c4d.DRAWRESULT_OK
def Init(self, op):
self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_RAD])
self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_IRADX])
self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_IRADY])
self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_SUB])
self.InitAttr(op, int, [c4d.PY_TUBEOBJECT_ROUNDSUB])
self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_ROUNDRAD])
self.InitAttr(op, int, [c4d.PY_TUBEOBJECT_SEG])
self.InitAttr(op, int, [c4d.PRIM_AXIS])
op[c4d.PY_TUBEOBJECT_RAD]= 200.0
op[c4d.PY_TUBEOBJECT_IRADX] = 50.0
op[c4d.PY_TUBEOBJECT_IRADY] = 50.0
op[c4d.PY_TUBEOBJECT_SUB] = 1
op[c4d.PY_TUBEOBJECT_ROUNDSUB] = 8
op[c4d.PY_TUBEOBJECT_ROUNDRAD] = 10.0
op[c4d.PY_TUBEOBJECT_SEG] = 36
op[c4d.PRIM_AXIS] = c4d.PRIM_AXIS_YP
return True
def GenerateLathe(self, cpadr, cpcnt, sub):
op = tag = padr = vadr = None
i = j = pcnt = vcnt = a = b = c = d = 0
length = sn = cs = v1 = v2 = 0.0
pcnt = cpcnt * sub
vcnt = cpcnt * sub
op = c4d.PolygonObject(pcnt, vcnt)
if op is None: return None
uvadr = [0.0]*(cpcnt+1)
for i in xrange(cpcnt):
uvadr[i] = length
length += (cpadr[ (i+1)%cpcnt ] - cpadr[i] ).GetLength()
if length > 0.0: length = 1.0/length
for i in xrange(cpcnt):
uvadr[i] *= length
uvadr[cpcnt] = 1.0
vcnt = 0
for i in xrange(sub):
sn, cs = utils.SinCos(math.pi*2 * float(i) / float(sub))
v1 = float(i) / float(sub)
v2 = float(i+1) / float(sub)
for j in xrange(cpcnt):
a = cpcnt*i+j
op.SetPoint(a, c4d.Vector(cpadr[j].x*cs,cpadr[j].y,cpadr[j].x*sn))
if i < sub:
b = cpcnt*i +((j+1)%cpcnt)
c = cpcnt*((i+1)%sub)+((j+1)%cpcnt)
d = cpcnt*((i+1)%sub)+j
pol = c4d.CPolygon(a,b,c,d)
op.SetPolygon(vcnt, pol)
vcnt += 1
op.Message(c4d.MSG_UPDATE)
op.SetPhong(True, 1, utils.Rad(80.0))
return op
def GetDimension(self, op, mp, rad):
rado = op[c4d.PY_TUBEOBJECT_RAD]
if rado is None: return
radx = op[c4d.PY_TUBEOBJECT_IRADX]
if radx is None: return
rady = op[c4d.PY_TUBEOBJECT_IRADY]
if rady is None: return
axis = op[c4d.PRIM_AXIS]
if axis is None: return
mp = 0.0
if axis is c4d.PRIM_AXIS_XP or axis is c4d.PRIM_AXIS_XN:
rad.x = rady
rad.y = rado+radx
rad.z = rado+radx
elif axis is c4d.PRIM_AXIS_YP or axis is c4d.PRIM_AXIS_YN:
rad.x = rado+radx
rad.y = rady
rad.z = rado+radx
elif axis is c4d.PRIM_AXIS_ZP or axis is c4d.PRIM_AXIS_ZN:
rad.x = rado+radx
rad.y = rado+radx
rad.z = rady
def GetVirtualObjects(self, op, hierarchyhelp):
# Disabled the following lines because cache flag was set
# So the cache build is done before this method is called
#dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA)
#if dirty is False: return op.GetCache(hierarchyhelp)
rad = op[c4d.PY_TUBEOBJECT_RAD]
if rad is None: rad = 200.0
iradx = op[c4d.PY_TUBEOBJECT_IRADX]
if iradx is None: iradx = 50.0
irady = op[c4d.PY_TUBEOBJECT_IRADY]
if irady is None: irady = 50.0
rrad = op[c4d.PY_TUBEOBJECT_ROUNDRAD]
if rrad is None: rrad = 10.0
num_sub = op[c4d.PY_TUBEOBJECT_SUB]
if num_sub is None: num_sub = 1
sub = utils.CalcLOD(num_sub, 1, 1, 1000)
num_rsub = op[c4d.PY_TUBEOBJECT_ROUNDSUB]
if num_rsub is None: num_rsub = 8
rsub = utils.CalcLOD(num_rsub, 1, 1, 1000)
num_seg = op[c4d.PY_TUBEOBJECT_SEG]
if num_seg is None: num_seg = 36
seg = utils.CalcLOD(num_seg, 1, 3, 1000)
i = 0
sn = 0.0
cs = 0.0
cpcnt = 4*(sub+rsub)
cpadr = [c4d.Vector()]*cpcnt
for i in xrange(sub):
cpadr[i] = c4d.Vector(rad-iradx, (1.0 - float(i)/sub*2.0)*(irady-rrad), 0.0)
cpadr[i+sub+rsub] = c4d.Vector(rad+(float(i)/sub*2.0-1.0)*(iradx-rrad), -irady, 0.0)
cpadr[i+2*(sub+rsub)] = c4d.Vector(rad+iradx, (float(i)/float(sub)*2.0-1.0)*(irady-rrad), 0.0)
cpadr[i+3*(sub+rsub)] = c4d.Vector(rad+(1.0-float(i)/float(sub)*2.0)*(iradx-rrad), irady, 0.0)
pi05 = 1.570796326
for i in xrange(rsub):
sn, cs = utils.SinCos(float(i)/rsub*pi05)
cpadr[i+sub] = c4d.Vector(rad-(iradx-rrad+cs*rrad), -(irady-rrad+sn*rrad), 0.0)
cpadr[i+sub+(sub+rsub)] = c4d.Vector(rad+(iradx-rrad+sn*rrad), -(irady-rrad+cs*rrad), 0.0)
cpadr[i+sub+2*(sub+rsub)] = c4d.Vector(rad+(iradx-rrad+cs*rrad), +(irady-rrad+sn*rrad), 0.0)
cpadr[i+sub+3*(sub+rsub)] = c4d.Vector(rad-(iradx-rrad+sn*rrad), +(irady-rrad+cs*rrad), 0.0)
ret = self.GenerateLathe(cpadr, cpcnt, seg)
if ret is None: return None
axis = op[c4d.PRIM_AXIS]
if axis is None: return None
RoundedTube.SetAxis(ret, axis)
ret.SetName(op.GetName())
return ret
if __name__ == "__main__":
dir, file = os.path.split(__file__)
icon = bitmaps.BaseBitmap()
icon.InitWith(os.path.join(dir, "res", "oroundedtube.tif"))
plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="Py-RoundedTube",
g=RoundedTube,
description="roundedtube", icon=icon,
info=c4d.OBJECT_GENERATOR)