@ferdinand
Details ansehen
1.211 / 5.000
Übersetzungsergebnisse
Übersetzung
I'm sorry Ferdinand for being such a stupid person. I haven't been programming plugins that long and I have to be honest, the road to get there was really rocky, so getting into the API wasn't particularly easy for me. I had to fight through it myself.
But no matter here you have a test code.
It's all still a bit muddled, especially as far as the description IDs are concerned, sometimes they don't initialize, well, it doesn't matter. I wasn't so aware of the self.parameter.
Well, the class BowSpline calculates the spline, other splines are supposed to be calculated later in the same class with other methods. I could also do this with functions?
Well the problem is it doesn't update the spline in the viewport when I change a parameter in the description even though it breaks. Then I thought I'd catch that with POSTSETPARAMETER and call a redraw.
Oh, the problem here with the instances is that if I want to make them editable, Cinema freezes.
I load the profile spline and the handle in the GVO using a method which loads the hyperfile..
I could possibly do that in my init_(self) method.
here is the code: as already said something messi yet.
import c4d
from c4d import plugins, bitmaps
import os
import math
# import copy
PLUGIN_ID = 223456789
doc = c4d.documents.GetActiveDocument()
HANDLE_X = 7
HANDLE_Z = 8.6
PY_WINDOW_LIST = 10002
PY_WINDOW_WIDTH = 10101
PY_WINDOW_HEIGHT = 10102
PY_ARCH_HEIGHT = 10103
PY_ARCH_SUBD = 10104
PY_OFFSET = 10105
PY_TILT_CHECK = 10106
PY_WINDOW_OPEN = 10107
PY_WINDOW_DIRECTION = 10108
PY_BANK = 10109
class BowSpline():
def __init__(self, width, height, arch, subd):
self.spline = c4d.BaseObject(c4d.Ospline)
self.spline[c4d.SPLINEOBJECT_CLOSED] = True
self.height = height
self.width = width
self.arch_height = arch
if self.arch_height > self.width / 2:
self.arch_height = self.width / 2
if self.height < self.arch_height:
self.height = self.arch_height
self.subd_points = subd
self.create()
def create(self):
if self.subd_points % 2 != 0:
pass
elif self.subd_points % 2 == 0:
if self.subd_points >= 0:
self.subd_points = self.subd_points + 1
# else:
# self.subd_points = 0
if self.arch_height == 0:
self.subd_points = 0
points = self.subd_points + 4
self.spline.ResizeObject(points)
y_value = self.height - self.arch_height
self.spline.SetPoint(1, c4d.Vector(self.width, 0, 0))
self.spline.SetPoint(2, c4d.Vector(self.width, y_value, 0))
self.spline.SetPoint(points - 1, c4d.Vector(0, y_value, 0))
if self.subd_points >= 0:
if self.arch_height != 0:
radius = (4 * (self.arch_height ** 2) + self.width ** 2) / (8 * self.arch_height)
else:
radius = 0
midpoint_pos = c4d.Vector(self.width / 2, self.height - radius, 0)
rv_corner = self.spline.GetPoint(2) - midpoint_pos
rv_right = c4d.Vector(self.width, midpoint_pos.y, 0) - midpoint_pos
first_point_angle = c4d.utils.GetAngle(rv_right, rv_corner)
last_point_angle = c4d.utils.DegToRad(180 - c4d.utils.RadToDeg(first_point_angle))
angle_adder = (c4d.utils.DegToRad(180) - (2 * first_point_angle)) / (self.subd_points + 1)
angle = first_point_angle + angle_adder
for index in range(3, points - 1):
sine, cose = c4d.utils.SinCos(angle)
y = sine * radius
x = cose * radius
new_point = c4d.Vector(midpoint_pos.x + x, midpoint_pos.y + y, 0)
self.spline.SetPoint(index, new_point)
angle += angle_adder
class Windows2023(plugins.ObjectData):
def __init__(self):
self.pos = 5 # index where to position the window axis
self.SetOptimizeCache(True)
self.profile = None
self.frame_spline = None
self.window_spline = None
self.new_doc = c4d.documents.BaseDocument()
self.spline = c4d.BaseObject(c4d.Ospline)
self.frame_sweep = c4d.BaseObject(c4d.Osweep)
self.window_sweep = c4d.BaseObject(c4d.Osweep)
self.extrude = None
self.load_profile()
self.start = True
def Init(self, op):
# self.SetOptimizeCache(True)
self.InitAttr(op, int, c4d.PY_WINDOW_LIST)
op[c4d.PY_WINDOW_LIST] = 1
self.InitAttr(op, float, c4d.PY_WINDOW_WIDTH)
op[c4d.PY_WINDOW_WIDTH] = 100
self.InitAttr(op, float, c4d.PY_WINDOW_HEIGHT)
op[c4d.PY_WINDOW_HEIGHT] = 120
self.InitAttr(op, float, c4d.PY_ARCH_HEIGHT)
op[c4d.PY_ARCH_HEIGHT] = 20
self.InitAttr(op, int, c4d.PY_ARCH_SUBD)
op[c4d.PY_ARCH_SUBD] = 12
self.InitAttr(op, bool, 10106)
op[10106] = False
self.InitAttr(op, float, 10107)
op[10107] = 0.0
self.InitAttr(op, bool, 10108)
op[10108] = False
self.InitAttr(op, float, 10109)
op[10109] = 0.0
# self.InitAttr(op, float, c4d.PY_OFFSET)
# op[c4d.PY_OFFSET] = 0.0
return True
def load_profile(self):
# c4d.documents.MergeDocument(self.new_doc, f"{path}/res/profile.c4d", c4d.SCENEFILTER_OBJECTS)
frame_path = os.path.join(path, "res", "w_f")
window_path = os.path.join(path, "res", "w_w")
frame_profile = c4d.BaseObject(c4d.Ospline)
window_profile = c4d.BaseObject(c4d.Ospline)
c4d.storage.ReadHyperFile(None, frame_profile, frame_path, 100)
c4d.storage.ReadHyperFile(None, window_profile, window_path, 100)
return frame_profile, window_profile
def load_handle(self):
handle_path = os.path.join(path, "res", "w_h")
handle = c4d.BaseObject(c4d.Opolygon)
c4d.storage.ReadHyperFile(None, handle, handle_path, 100)
return handle
def load_sill(self):
sill_path = os.path.join(path, "res", "b_al")
sill = c4d.BaseObject(c4d.Ospline)
c4d.storage.ReadHyperFile(None, sill, sill_path, 100)
return sill
def make_sill(self, op):
extrude: c4d.BaseObject = c4d.BaseObject(c4d.Oextrude)
extrude[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET] = - op[c4d.PY_WINDOW_WIDTH]
sill = self.load_sill()
vector_z = op[PY_BANK]
if vector_z < 0:
vector_z *= -1
for point in range(sill.GetPointCount()):
if point == 6 or point == 7:
continue
if sill.GetPoint(point).z >= 0:
vector_z = 0
sill.SetPoint(point, sill.GetPoint(point) - c4d.Vector(0, 0, vector_z))
vector_z = op[PY_BANK]
sill.InsertUnder(extrude)
extrude = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
doc=op.GetDocument(),
list=[extrude])[0]
for tag in extrude.GetTags():
if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
tag.Remove()
extrude.SetName("Sill")
extrude.SetPhong(on=True, anglelimit=True, angle=c4d.utils.DegToRad(60))
return extrude
def bow_spline(self, width, height, arch, subd):
spline = c4d.BaseObject(c4d.Ospline)
spline[c4d.SPLINEOBJECT_CLOSED] = True
if width != 0:
pass
elif subd % 2 == 0:
if subd >= 0:
subd += 1
# else:
# self.subd_points = 0
if arch == 0:
subd = 1
points = subd + 4
spline.ResizeObject(points)
# if self.arch_height > self.width/ 2:
#
# self.arch_height = self.width/ 2
# if self.width < self.arch_height:
# self.width = self.arch_height
y_value = height - arch
spline.SetPoint(1, c4d.Vector(width, 0, 0))
spline.SetPoint(2, c4d.Vector(width, y_value, 0))
spline.SetPoint(points - 1, c4d.Vector(0, y_value, 0))
# b_height_pos = c4d.Vector(width / 2, height + b_height, 0)
# B = 4 H = 5
if subd > 0:
if arch != 0:
radius = (4 * (arch ** 2) + width ** 2) / (8 * arch)
else:
radius = 0
bogen_height = arch
midpoint_pos = c4d.Vector(width / 2, height - radius, 0)
rv_corner = spline.GetPoint(2) - midpoint_pos
rv_right = c4d.Vector(width, midpoint_pos.y, 0) - midpoint_pos
first_point_angle = c4d.utils.GetAngle(rv_right, rv_corner)
last_point_angle = c4d.utils.DegToRad(180 - c4d.utils.RadToDeg(first_point_angle))
angle_adder = (c4d.utils.DegToRad(180) - (2 * first_point_angle)) / (subd + 1)
angle = first_point_angle + angle_adder
for index in range(3, points - 1):
sine, cose = c4d.utils.SinCos(angle)
y = sine * radius
x = cose * radius
new_point = c4d.Vector(midpoint_pos.x + x, midpoint_pos.y + y, 0)
spline.SetPoint(index, new_point)
angle += angle_adder
return spline
def make_glass(self, width, height, arch=0, subd=0):
spline = BowSpline()
def make_arch_frames(self, node):
# self.new_doc.Flush()
if node[10108]:
self.pos = 38 #the index of the frame where to position the axis
else:
self.pos = 17
frame_spline = BowSpline(node[c4d.PY_WINDOW_WIDTH], node[c4d.PY_WINDOW_HEIGHT], node[c4d.PY_ARCH_HEIGHT],
node[c4d.PY_ARCH_SUBD]).spline
frame_sweep = c4d.BaseObject(c4d.Osweep)
frame_sweep.SetName("Frame")
frame_spline.InsertUnder(frame_sweep)
window_spline = BowSpline(node[c4d.PY_WINDOW_WIDTH], node[c4d.PY_WINDOW_HEIGHT], node[c4d.PY_ARCH_HEIGHT],
node[c4d.PY_ARCH_SUBD]).spline
window_sweep = c4d.BaseObject(c4d.Osweep)
window_sweep.SetName("Window")
window_spline.InsertUnder(window_sweep)
profiles = self.load_profile()
frame_profile = profiles[0]
frame_profile.InsertUnder(frame_sweep)
window_profile = profiles[1]
window_profile.InsertUnder(window_sweep)
frame_sweep: c4d.BaseObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[frame_sweep],
doc=node.GetDocument())[0]
window_sweep: c4d.BaseObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[window_sweep],
doc=node.GetDocument())[0]
frame_sweep.SetPhong(on=True, anglelimit=True, angle=c4d.utils.DegToRad(60))
window_sweep.SetPhong(on=True, anglelimit=True, angle=c4d.utils.DegToRad(60))
pos = window_sweep.GetPoint(self.pos)
window_axis = c4d.BaseObject(c4d.Onull)
window_axis.SetName("Axis")
container = c4d.BaseObject(c4d.Onull)
frame_sweep.InsertUnder(container)
window_axis.InsertUnder(container.GetDown())
window_axis.SetAbsPos(pos)
window_sweep.InsertUnder(window_axis)
window_sweep.SetRelPos(container.GetAbsPos() - pos)
if node[10105]:
container.GetDown().SetRelPos(c4d.Vector(0, 0, node[10105]))
if node[10106] is not None:
if node[10106]:
if self.pos == 17:
if node[10107] is not None:
window_axis.SetRelRot(c4d.Vector(0, c4d.utils.DegToRad(-5), 0))
else:
if node[10107] is not None:
window_axis.SetRelRot(c4d.Vector(0, c4d.utils.DegToRad(-5), 0))
else:
if self.pos == 38:
if node[10107] is not None:
window_axis.SetRelRot(c4d.Vector(-node[10107], 0, 0))
else:
if node[10107] is not None:
window_axis.SetRelRot(c4d.Vector(node[10107], 0, 0))
#self.new_doc.Flush()
return container
# return frame, window
def Message(self, node, type, data):
# Arch Bow Settings
# if node[c4d.PY_WINDOW_LIST] == 1:
if type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
if c4d.threading.GeIsMainThread():
c4d.CallCommand(12147)
if type == c4d.MSG_DESCRIPTION_COMMAND:
if data['id'][0].id == c4d.PY_CREATE_BOOL:
self.extrude = c4d.BaseObject(c4d.Oextrude)
self.extrude.SetName("Boole")
self.extrude[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1
tag = self.extrude.MakeTag(c4d.Tdisplay)
tag[c4d.DISPLAYTAG_AFFECT_DISPLAYMODE] = True
tag[c4d.DISPLAYTAG_SDISPLAYMODE] = 6
tag[c4d.DISPLAYTAG_WDISPLAYMODE] = 0
frame_spline = BowSpline(node[c4d.PY_WINDOW_WIDTH], node[c4d.PY_WINDOW_HEIGHT],
node[c4d.PY_ARCH_HEIGHT],
node[c4d.PY_ARCH_SUBD]).spline
frame_spline.InsertUnder(self.extrude)
self.extrude = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
doc=node.GetDocument(),
list=[self.extrude])[0]
null = c4d.BaseObject(c4d.Onull)
null.SetName("Window_Bool Axis")
extrude: c4d.BaseObject = self.extrude.GetDown()
extrude.SetName("Window-Boole")
# del tags
for tag in extrude.GetTags():
if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
tag.Remove()
extrude[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1
extrude.InsertUnder(null)
self.extrude = None
extrude.SetRelPos(extrude.GetRelPos() - c4d.Vector(0, 0, 10))
null.SetMg(node.GetMg())
node.GetDocument().InsertObject(null)
c4d.EventAdd()
elif data['id'][0].id == 10004:
c4d.CallCommand(5126)
return True
def GetVirtualObjects(self, op, hh):
# dirty = True if a cache is dirty or if the data (any parameters) of the object changed.
# If nothing changed and a cache is present, return the cache
# cache deaktiveren
dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTYFLAGS_DESCRIPTION)
if not dirty:
return op.GetCache(hh)
"""Settings for Arch Window"""
if op[c4d.PY_WINDOW_LIST] == 1:
frames = self.make_arch_frames(op)
handle = self.load_handle()
handle.InsertUnder(frames.GetDown().GetDown().GetDown())
sill = self.make_sill(op)
sill.InsertUnder(frames.GetDown())
if op[PY_WINDOW_DIRECTION]:
handle.SetRelPos(c4d.Vector(HANDLE_X, op[c4d.PY_WINDOW_HEIGHT] / 2, HANDLE_Z))
else:
handle.SetRelPos(c4d.Vector(op[c4d.PY_WINDOW_WIDTH] - HANDLE_X, op[c4d.PY_WINDOW_HEIGHT] / 2, HANDLE_Z))
return frames
elif op[c4d.PY_WINDOW_LIST] == 2:
return c4d.BaseObject(c4d.Ocube)
def GetDDescription(self, op, description, flags):
if not description.LoadDescription(op.GetType()):
return False
single_id = description.GetSingleDescID()
arch_height = c4d.DescID(c4d.PY_ARCH_HEIGHT) # using ID from above post
height = c4d.DescID(c4d.PY_WINDOW_HEIGHT)
if single_id is None or arch_height.IsPartOf(single_id)[0]:
db = description.GetParameterI(c4d.PY_ARCH_HEIGHT)
db.SetFloat(c4d.DESC_MAX, op[c4d.PY_WINDOW_WIDTH] / 2)
if op[c4d.PY_ARCH_HEIGHT] is not None:
if single_id is None or height.IsPartOf(single_id)[0]:
db2 = description.GetParameterI(c4d.PY_WINDOW_HEIGHT)
db2.SetFloat(c4d.DESC_MIN, op[c4d.PY_ARCH_HEIGHT])
group_1 = c4d.DescID(c4d.PY_GROUP_1)
if single_id is None or group_1.IsPartOf(single_id)[0]:
if op[c4d.PY_WINDOW_LIST] != 1:
db = description.GetParameterI(c4d.PY_GROUP_1)
db.SetBool(c4d.DESC_HIDE, True)
return (True, flags | c4d.DESCFLAGS_DESC_LOADED)
# def GetDEnabling(self, op, did, t_data, flags, itemdesc):
#
# if did[0].id == c4d.PY_ANIMATION_DISTANCE and op[c4d.PY_LED_MODE] == 0:
# return False
# elif did[0].id == c4d.PY_VERT_ANIMATION_DISTANCE and op[c4d.PY_LED_MODE] == 0:
# return False
# elif did[0].id == c4d.PY_PANEL_LENGTH and op[c4d.PY_LED_MODE] == 0:
# return False
# elif did[0].id == c4d.PY_VERT_ANIMATION_DISTANCE and op[c4d.PY_LED_MODE] == 2:
# return False
#
# return True
if __name__ == "__main__":
path, file = os.path.split(__file__)
files = "icon.tif"
new_path = os.path.join(path, "res", files)
bitmap = bitmaps.BaseBitmap()
bitmap.InitWith(new_path)
plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="Windows2023", g=Windows2023, description="windows2023",
icon=bitmap,
info=c4d.OBJECT_GENERATOR)