Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Login

    Boole Object causes version 2024 to freeze

    Cinema 4D SDK
    r23 2023 2024 python windows
    2
    3
    1.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ThomasBT
      ThomasB
      last edited by ferdinand

      Hi,

      for demonstration purposes, I have an extremely stripped down version (1200 LOC) of my plugin (6000 LOC) here.
      Unfortunately it was not possible to insert the whole Pyp file here because the post can only be a maximum of 32767 characters long. That's why I only have sent the classes and functions that are not so important are without code.

      • Condition: the window bars must be activated. Error with Boole happens in the method
      def bar_cutter(op, obj, bars, fixed=False)
      

      Description:

      Of course, it is not technically perfect and in this version it is more of a prototype. I was able to narrow down the error to the Bars_Cutter() function. That's why I only included the bar_cutter method.

      • In this function I read specific points from the created frame and create a spline, which I throw into an Extrude and then convert to a polygon object. this extrude is used to cut the window bars.
      • I then create a Boole object and throw the previously created bars together with the extrude into the Boole object.

      Normally I also create a polygon object from the Boole object with SendModelingCommand() but to prove that the error comes from the Boole, I insert the Boole object directly under the window frames.


      Problem:

      The problem now is this. If you reduce the arch height of this arched window, the polygons will now intersect. The following usually happens (R23-2023). The bars then simply disappear. And the glass is no longer displayed correctly either. That's actually OK. The user immediately knows that something is intersected. (Watch Video)

      And in version 23-2023.2 this works, as can be seen in the video.
      But in version 2024 when the polygons intersect, Cinema 4d freezes.

      I have a short video to watch here.

      Also the version of the plugin in a zip file for R23-2023 and 2024 for easy reference.
      Boole-Problem.zip

      It actually only happens when the intersection of the intersected polygons creates a slightly deformed extruder.


      Question:

      Why does this freeze in 2024... Version and in R23-2023 not?


      Temporary Solution:

      I was now able to get around the problem by calculating the points of the extrude, how many there should be if Arch Subd has a certain value. When the polygon interesects, the extrude suddenly has more points. And I'll check that. If there are more, I simply don't create the Boole anymore. Then it works......

      For demonstration purposes, I only sent the content of the plugin, not the res, header and str files. These are then included in the plugin itself. I hope that's ok.

      class WindowHelper:
          def __init__(self):
              pass
      
          @staticmethod
          def create_tex_tags(op, name):
              tag = c4d.BaseTag(c4d.Ttexture)
              tag[c4d.TEXTURETAG_PROJECTION] = 6
              tag[c4d.ID_BASELIST_NAME] = name
              op.InsertTag(tag)
      
          @staticmethod
          def catch_tex_tag(op, name, goal):
              # new tag read from op
              frame_tag = None
              for tag in op.GetTags():
                  if tag.GetName().lower() == name:
                      frame_tag = tag
                      break
              if frame_tag is not None:
                  if goal:
                      goal.InsertTag(frame_tag.GetClone())
      
          @staticmethod
          def load_profile():
              # to less characters
      
          @staticmethod
          def set_handle_pos(op, frame, handle, f_type=1, w_type=1, h_pos=0):
             # to much characters
      
          @staticmethod
          def load_handle():
             # to much
      
          @staticmethod
          def load_sill():
              sill_path = os.path.join(path, "res", "b_al")
              sill = c4d.BaseObject(c4d.Ospline)
              c4d.storage.ReadHyperFile(None, sill, sill_path, 100)
              return sill
      
          @staticmethod
          def set_axis(op, pos):
              # to much
      
          @staticmethod
          def create_arch_spline(op, widtho, heighto, archo, subdo, multi=1, glass=False):
              # to much
              return spline
      
          def make_frames(self, node, f_spline, w_spline=None, pos=0, tilt=False, window_open=0):
      
              # to much
              return container
      
          @staticmethod
          def create_sill(op):
              # to much
              return extrude
      
          def make_sill(self, op):
              # to much
              return extrude
      
          @staticmethod
          def create_ring(op, radius=25, full_spiral=True, sub_d=8):
      
              tube = c4d.BaseObject(c4d.Otube)
              tube[c4d.PRIM_AXIS] = 5
              tube[c4d.PRIM_TUBE_ORAD] = radius
              if not full_spiral:
                  tube[c4d.PRIM_SLICE] = True
              tube[c4d.PRIM_TUBE_IRAD] = radius - op[PY_BAR_WIDTH]
              tube[c4d.PRIM_TUBE_SEG] = 4 * sub_d
              tube[c4d.PRIM_TUBE_HEIGHT] = 2 - 0.01
              tube[c4d.PRIM_TUBE_HSUB] = 1
              # pos = tube.GetRelPos() - c4d.Vector(0, 0, (2 - 0.01) / 2 + 0.01)
              # tube.SetRelPos(pos)
      
              tube: c4d.PolygonObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[tube],
                                                                      doc=op.GetDocument())[0]
              for tag in tube.GetTags():
                  if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
                      tag.Remove()
      
              for index in range(len(tube.GetAllPoints())):
                  tube.SetPoint(index, tube.GetPoint(index) - c4d.Vector(0, 0, (2 - 0.01) / 2 + 0.01))
              return tube
      
          @staticmethod
          def create_bar(op, length, width, angle=0):
              """ Creates a bar with the length"""
      
              spline = c4d.SplineObject(4, c4d.SPLINETYPE_LINEAR)
              spline[c4d.SPLINEOBJECT_CLOSED] = True
      
              if angle == 0:
                  bar = c4d.BaseObject(c4d.Oextrude)
                  spline.SetPoint(0, c4d.Vector(-width / 2, 0, -.01))
                  spline.SetPoint(1, c4d.Vector(width / 2, 0, -.01))
                  spline.SetPoint(2, c4d.Vector(width / 2, 0, -2))
                  spline.SetPoint(3, c4d.Vector(-width / 2, 0, -2))
                  bar[c4d.EXTRUDEOBJECT_DIRECTION] = 2
                  bar[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET] = length
                  spline.InsertUnder(bar)
      
              elif angle == 90:
                  bar = c4d.BaseObject(c4d.Oloft)
                  bar[c4d.LOFTOBJECT_SUBX] = 4
                  bar[c4d.LOFTOBJECT_SUBY] = 2
                  bar[c4d.LOFTOBJECT_ADAPTIVEY] = False
                  spline.SetPoint(0, c4d.Vector(0, width / 2, -.01))
                  spline.SetPoint(1, c4d.Vector(0, -width / 2, -.01))
                  spline.SetPoint(2, c4d.Vector(0, -width / 2, -2))
                  spline.SetPoint(3, c4d.Vector(0, width / 2, -2))
                  spline2 = spline.GetClone()
                  spline.InsertUnder(bar)
                  spline2.InsertUnder(bar)
                  spline.SetRelPos(c4d.Vector(-length / 2, 0, 0))
                  spline2.SetRelPos(c4d.Vector(length / 2, 0, 0))
      
              bar.SetName("Bar")
      
              bar: c4d.PolygonObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[bar],
                                                                     doc=op.GetDocument())[0]
              for tag in bar.GetTags():
                  if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
                      tag.Remove()
      
              return bar
      
          @staticmethod
          def bars_maker(op, width, height, method=0, fixed=False, bank=False, vert=0, hor=0, height2=0, count=2,
                         full_spiral=True):
              container = c4d.BaseObject(c4d.Onull)
              if fixed != 4:
                  pro_width = PROFILE_WIDTH
                  z = 4
              else:
                  pro_width = FIXED_PROFILE_WIDTH
                  z = 2.7
              bar_width = op[PY_BAR_WIDTH]
              if method == 0:
                  return None
              elif method == 1:
                  # if not fixed:
                  offset_vert = (width - 2 * pro_width) / (vert + 1)
      
                  if not bank:
                      offset_hor = (height - 2 * pro_width) / (hor + 1)
                  else:
                      offset_hor = (height + SILL_HEIGHT - 2 * pro_width) / (hor + 1)
      
                  for index in range(vert):
                      pos_x = pro_width + (index + 1) * offset_vert
      
                      length = height
                      bar = WindowHelper().create_bar(op, length=length, width=bar_width)
                      bar.InsertUnder(container)
      
                      bar.SetRelPos(c4d.Vector(pos_x, 0, z))
      
                  # horizontal length calc inside arch
      
                  for index in range(hor):
                      pos_y = pro_width + ((index + 1) * offset_hor)
                      length = width
                      bar = WindowHelper().create_bar(op, length=length, width=bar_width, angle=90)
                      bar.InsertUnder(container)
                      bar.SetRelPos(c4d.Vector(width / 2, pos_y, z))
      
                  return container
      
              elif method == 2:
                  if bank:
                      y = SILL_HEIGHT
                  else:
                      y = 0
                  offset_vert = (width - 2 * pro_width) / (vert + 1)
                  offset_vert2 = (width - 2 * pro_width) / (hor + 1)
      
                  bar_middle = WindowHelper().create_bar(op, length=width, width=bar_width, angle=90)
                  bar_middle.InsertUnder(container)
                  bar_middle.SetRelPos(c4d.Vector(width / 2, height2 + y, z))
      
                  for index in range(vert):
                      pos_x_bottom = pro_width + (index + 1) * offset_vert
                      length = height2 - bar_width / 2
                      bar = WindowHelper().create_bar(op, length=length + y, width=bar_width)
                      bar.InsertUnder(container)
                      bar.SetRelPos(c4d.Vector(pos_x_bottom, 0, z))
      
                  for index in range(hor):
                      pos_x_top = pro_width + (index + 1) * offset_vert2
                      length = height - height2 - bar_width / 2
                      bar = WindowHelper().create_bar(op, length=length, width=bar_width)
                      bar.InsertUnder(container)
                      bar.SetRelPos(c4d.Vector(pos_x_top, height2 + y + bar_width / 2, z))
      
                  return container
      
              elif method == 3:
                  radius = height2
                  if hor == 0:
                      sub_d = 1
                  else:
                      sub_d = hor * 3
      
                  if full_spiral:
                      y_pos = height / 2
                  else:
                      if fixed != 4:
                          y_pos = PROFILE_WIDTH - 1
                      else:
                          y_pos = FIXED_PROFILE_WIDTH
      
                  ring = WindowHelper().create_ring(op, radius=radius, full_spiral=full_spiral, sub_d=sub_d)
      
                  ring.InsertUnder(container)
                  ring.SetRelPos(c4d.Vector(width / 2, y_pos, z))
      
                  bar_boole = c4d.BaseObject(c4d.Oboole)
                  bar_boole[c4d.BOOLEOBJECT_SINGLE_OBJECT] = True
                  bar_boole[c4d.BOOLEOBJECT_HIDE_NEW_EDGES] = True
      
                  bar_cutter = c4d.BaseObject(c4d.Ocylinder)
                  bar_cutter[c4d.PRIM_AXIS] = 5
                  if not full_spiral:
                      bar_cutter[c4d.PRIM_SLICE] = True
                  bar_cutter[c4d.PRIM_CYLINDER_HSUB] = 1
                  bar_cutter[c4d.PRIM_CYLINDER_SEG] = 4 * sub_d
                  bar_cutter[c4d.PRIM_CYLINDER_RADIUS] = radius
      
                  bar_container = c4d.BaseObject(c4d.Onull)
                  if width > height:
                      length = width
                  else:
                      length = height
                  if full_spiral:
      
                      if count <= 2:
                          # create the spiral bars
      
                          bar = WindowHelper().create_bar(op, length=length, width=bar_width, angle=0)
                          bar_2 = bar.GetClone()
                          bar.InsertUnder(bar_container)
                          bar_2.InsertUnder(bar_container)
                          if count <= 1:
                              bar.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(90)))
                              bar_2.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(-90)))
                          else:
                              bar.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(0)))
                              bar_2.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(180)))
      
                      else:
                          angle_adder = 360.0 / count
                          angle = 90 - angle_adder
                          for index in range(count):
                              bar = WindowHelper().create_bar(op, length=length, width=bar_width, angle=0)
                              bar.InsertUnder(bar_container)
      
                              bar.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(angle + abs(angle_adder - 90))))
                              angle += angle_adder
      
                          if count > 4:
                              bar_container.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(180)))
                  else:
      
                      if count < 1:
                          count = 1
                      angle_adder = 180.0 / (count + 1)
                      angle = 0 + angle_adder
                      for index in range(count):
                          bar = WindowHelper().create_bar(op, length=length, width=bar_width, angle=0)
                          bar.InsertUnder(bar_container)
      
                          bar.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(angle - 90)))
                          angle += angle_adder
      
                  bar_cutter.InsertUnder(bar_boole)
                  bar_container.InsertUnder(bar_boole)
                  bar_boole.InsertUnder(container)
                  bar_boole.SetRelPos(c4d.Vector(width / 2, y_pos, z))
      
                  return container
      
          @staticmethod
          def bar_cutter(op, obj, bars, fixed=False):
              normal = False
              direction = 5
              if fixed != 4:
                  frame: c4d.BaseObject = obj.GetDown().GetDown().GetDown()
                  numbers = frame.GetPointCount() // 21
                  points_list = []
                  start = CUTTER_POS
                  for point in range(numbers):
                      points_list.append(frame.GetPoint(start))
                      start += 21
              else:
                  # print(obj.GetDown())
                  direction = 5
                  normal = False
                  frame: c4d.BaseObject = obj.GetDown()
                  numbers = frame.GetPointCount() // 12
                  points_list = []
                  start = FIXED_CUTTER_POS
                  for point in range(numbers):
                      points_list.append(frame.GetPoint(start))
                      start += 12
      
              glass_spline = c4d.SplineObject(len(points_list), type=c4d.SPLINETYPE_LINEAR)
              glass_spline.SetAllPoints(points_list)
              glass_spline[c4d.SPLINEOBJECT_CLOSED] = True
              extrude = c4d.BaseObject(c4d.Oextrude)
              extrude[c4d.EXTRUDEOBJECT_FLIPNORMALS] = normal
              extrude[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET] = direction
              extrude.SetName("Glass")
              glass_spline.InsertUnder(extrude)
      
              # doc = c4d.documents.BaseDocument()
              # doc.InsertObject(extrude)
              # extrude = doc.GetFirstObject()
      
              extrude: c4d.PolygonObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                                                                         list=[extrude.GetClone()],
                                                                         doc=op.GetDocument())[0]
      
              for tag in extrude.GetTags():
                  if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
                      tag.Remove()
      
              boolen = c4d.BaseObject(c4d.Oboole)
              boolen[c4d.BOOLEOBJECT_TYPE] = 2
              boolen[c4d.BOOLEOBJECT_SINGLE_OBJECT] = True
              boolen[c4d.BOOLEOBJECT_BREAK_CUT_EDGES] = True
      
              if not bars.GetDown():
                  bars = c4d.BaseObject(c4d.Onull)
                  bars.SetName("Bars")
                  bars.InsertUnder(frame)
              else:
                  bars.InsertUnder(boolen)
                  extrude.InsertUnder(boolen)
      
                  # doc = c4d.documents.BaseDocument()
                  # doc.InsertObject(boolen)
                  # bars = doc.GetFirstObject().GetClone()
      
                  # bars: c4d.BaseObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                  #                                                      list=[boolen],
                  #                                                      doc=op.GetDocument())[0]
                  #
                  # if not bars.IsInstanceOf(c4d.Oboole):
                  #     bars.SetPhong(True, anglelimit=True, angle=c4d.utils.DegToRad(40))
                  #
                  #     bars.SetName("Bars")
                  #     for tag in bars.GetTags():
                  #         if tag.IsInstanceOf(c4d.Tedgeselection):
                  #             tag.Remove()
                  #     WindowHelper().catch_tex_tag(op, "bars", bars)
                  #
                  #     bars.InsertUnder(frame)
      
                  WindowHelper().catch_tex_tag(op, "bars", boolen)
                  boolen.InsertUnder(frame)
      
      
      
      
          def window_arch(self, op):
              container = c4d.BaseObject(c4d.Onull)
              # self.create_arch_window(op)
      
              spline = self.create_arch_spline(op, op[PY_WINDOW_WIDTH], op[PY_WINDOW_HEIGHT],
                                               op[PY_ARCH_HEIGHT],
                                               op[PY_ARCH_SUBD], multi=1.5)
      
              w_spline = self.create_arch_spline(op, op[PY_WINDOW_WIDTH], op[PY_WINDOW_HEIGHT],
                                                 op[PY_ARCH_HEIGHT],
                                                 op[PY_ARCH_SUBD], multi=.95)
              frames = self.make_frames(op, spline, w_spline, op[PY_WINDOW_DIRECTION], tilt=op[PY_TILT_CHECK],
                                        window_open=op[PY_WINDOW_OPEN])
      
              # glass creation
              self.preshious_glass(op, frames)
      
              # handle creation
              handle = self.handle.GetClone()
              WindowHelper().catch_tex_tag(op, "handle", handle)  # Mats for handle
              handle.InsertUnder(frames.GetDown().GetDown().GetDown())
      
              # test new handel function
              self.set_handle_pos(op, frames, handle, w_type=1, h_pos=op[PY_WINDOW_DIRECTION])
      
              # new bars IDs =========================================
              if op[PY_1BARS_LEFT] > 0:
                  if op[PY_1BARS_LEFT] == 1:
                      # Grid
                      bars_container = self.bars_maker(op, width=op[PY_WINDOW_WIDTH],
                                                       height=op[PY_WINDOW_HEIGHT],
                                                       method=op[PY_1BARS_LEFT],
                                                       bank=op[PY_BANK],
                                                       vert=op[PY_1BARS_LEFTVERT],
                                                       hor=op[PY_1BARS_LEFTHOR],
                                                       height2=op[PY_1BARS_LEFTMETHOD2DISTANCE],
                                                       )
      
                  elif op[PY_1BARS_LEFT] == 2:
                      # Dual Grid
                      bars_container = self.bars_maker(op, width=op[PY_WINDOW_WIDTH],
                                                       height=op[PY_WINDOW_HEIGHT],
                                                       method=op[PY_1BARS_LEFT],
                                                       bank=op[PY_BANK],
                                                       vert=op[PY_1BARS_LEFTDUALVERT],
                                                       hor=op[PY_1BARS_LEFTDUALHOR],
                                                       height2=op[PY_1BARS_LEFTMETHOD2DISTANCE],
                                                       count=op[PY_1BARS_LEFTVERT])
      
                  elif op[PY_1BARS_LEFT] == 3:
                      # Star
                      bars_container = self.bars_maker(op, width=op[PY_WINDOW_WIDTH], height=op[PY_WINDOW_HEIGHT],
                                                       method=op[PY_1BARS_LEFT],
                                                       bank=op[PY_BANK],
                                                       vert=op[PY_1BARS_LEFTSTARSTREAKS],
                                                       hor=op[PY_1BARS_LEFTSTARSUBD],
                                                       height2=op[PY_1BARS_LEFTSTARRADIUS],
                                                       count=op[PY_1BARS_LEFTSTARSTREAKS])
      
                  self.bar_cutter(op, frames, bars_container)
                  # bars_container = frames.GetDown().GetDown().GetDown().GetDown()
                  # if bars_container.IsInstanceOf(c4d.Oboole):
                  #     bars_container.Remove()
      
      
              # Bars End ==========================================================
      
              if op[PY_BANK]:
                  # sill = self.make_sill(op)
                  sill = self.create_sill(op)
                  sill.InsertUnder(frames.GetDown())
      
              frames.InsertUnder(container)
      
              if op[PY_OFFSET] is not None:
                  window = container.GetDown().GetDown()#.GetClone()
                  window.SetRelPos(c4d.Vector(0, 0, op[PY_OFFSET]))
      
              return container
      
          @staticmethod
          def preshious_glass(op, obj, fixed=0, toplightarch=False):
              direction = 1.5
              normal = False
              if fixed != 4:
                  if toplightarch:
                      direction = -1.5
                      normal = True
                  else:
                      direction = 1.5
                      normal = False
      
                  frame: c4d.BaseObject = obj.GetDown().GetDown().GetDown()
                  numbers = frame.GetPointCount() // 21
                  points_list = []
                  start = 7
                  for point in range(numbers):
                      points_list.append(frame.GetPoint(start))
                      start += 21
              else:
                  # print(obj.GetDown())
                  direction = 1.5
                  normal = False
                  frame: c4d.BaseObject = obj.GetDown()
                  numbers = frame.GetPointCount() // 12
                  points_list = []
                  start = 4
                  for point in range(numbers):
                      points_list.append(frame.GetPoint(start))
                      start += 12
      
              glass_spline = c4d.SplineObject(len(points_list), type=c4d.SPLINETYPE_LINEAR)
      
              glass_spline.SetAllPoints(points_list)
              glass_spline[c4d.SPLINEOBJECT_CLOSED] = True
              extrude = c4d.BaseObject(c4d.Oextrude)
              extrude[c4d.EXTRUDEOBJECT_FLIPNORMALS] = normal
              extrude[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET] = direction
              extrude.SetName("Glass")
              glass_spline.InsertUnder(extrude)
              extrude: c4d.PolygonObject = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                                                                         list=[extrude],
                                                                         doc=op.GetDocument())[0]
      
              for tag in extrude.GetTags():
                  if tag.IsInstanceOf(c4d.Tpolygonselection) or tag.IsInstanceOf(c4d.Tedgeselection):
                      tag.Remove()
      
              WindowHelper().catch_tex_tag(op, "glass", extrude)
      
              extrude.InsertUnder(frame)
      
          def desc_arch(self, op, single_id, description, flags):
              arch_height = c4d.DescID(PY_ARCH_HEIGHT)  # using ID from above post
              height = c4d.DescID(PY_WINDOW_HEIGHT)
              width = c4d.DescID(PY_WINDOW_WIDTH)
      
              # Begrenzung =======================================
      
              if single_id is None or width.IsPartOf(single_id)[0]:
                  db = description.GetParameterI(width)
      
                  width_limiter = PROFILE_WIDTH * 2
      
                  db.SetFloat(c4d.DESC_MIN, width_limiter)
      
              if op[PY_ARCH_HEIGHT] is not None:
                  if single_id is None or height.IsPartOf(single_id)[0]:
                      db2 = description.GetParameterI(PY_WINDOW_HEIGHT)
                      width_limiter = op[PY_WINDOW_WIDTH] / 1
      
                      db2.SetFloat(c4d.DESC_MIN, op[PY_ARCH_HEIGHT] + width_limiter)
      
              # Hiding the Bars
              vert = c4d.DescID(PY_1BARS_LEFTVERT)
              hor = c4d.DescID(PY_1BARS_LEFTHOR)
              vert2 = c4d.DescID(PY_1BARS_LEFTDUALVERT)
              hor2 = c4d.DescID(PY_1BARS_LEFTDUALHOR)
              radius = c4d.DescID(PY_1BARS_LEFTSTARRADIUS)
              height = c4d.DescID(PY_1BARS_LEFTMETHOD2DISTANCE)
              streaks = c4d.DescID(PY_1BARS_LEFTSTARSTREAKS)
              segments = c4d.DescID(PY_1BARS_LEFTSTARSUBD)
      
              # left segment
              if single_id is None or vert.IsPartOf(single_id)[0]:
                  vert_bc = description.GetParameterI(PY_1BARS_LEFTVERT)
                  if op[PY_1BARS_LEFT] != 1:
                      vert_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or hor.IsPartOf(single_id)[0]:
                  hor_bc = description.GetParameterI(PY_1BARS_LEFTHOR)
                  if op[PY_1BARS_LEFT] != 1:
                      hor_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or vert2.IsPartOf(single_id)[0]:
                  vert2_bc = description.GetParameterI(PY_1BARS_LEFTDUALVERT)
                  if op[PY_1BARS_LEFT] != 2:
                      vert2_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or hor2.IsPartOf(single_id)[0]:
                  hor2_bc = description.GetParameterI(PY_1BARS_LEFTDUALHOR)
                  if op[PY_1BARS_LEFT] != 2:
                      hor2_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or streaks.IsPartOf(single_id)[0]:
                  streaks_bc = description.GetParameterI(PY_1BARS_LEFTSTARSTREAKS)
                  if op[PY_1BARS_LEFT] != 3:
                      streaks_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or segments.IsPartOf(single_id)[0]:
                  segments_bc = description.GetParameterI(PY_1BARS_LEFTSTARSUBD)
                  if op[PY_1BARS_LEFT] != 3:
                      segments_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or radius.IsPartOf(single_id)[0]:
                  radius_bc = description.GetParameterI(PY_1BARS_LEFTSTARRADIUS)
                  if op[PY_1BARS_LEFT] != 3:
                      radius_bc.SetBool(c4d.DESC_HIDE, True)
              if single_id is None or height.IsPartOf(single_id)[0]:
                  height_bc = description.GetParameterI(PY_1BARS_LEFTMETHOD2DISTANCE)
                  if op[PY_1BARS_LEFT] == 0 or op[PY_1BARS_LEFT] == 3:
                      height_bc.SetBool(c4d.DESC_HIDE, True)
      
      
      class Windows2023(plugins.ObjectData, WindowHelper):
      
          def __init__(self):
              self.SetOptimizeCache(True)
              self.profile = self.load_profile()
              self.handle = self.load_handle()
              self.sill = self.load_sill()
      
          def Init(self, op, isCloneInit):
      
              # Global Paramters
              self.InitAttr(op, bool, PY_BANK)
              self.InitAttr(op, float, PY_BANK_SIZE)
              self.InitAttr(op, float, PY_BANK_INNERSIZE)
              self.InitAttr(op, float, PY_BAR_WIDTH)
      
              # Arch Window Paramters
      
              self.InitAttr(op, float, PY_ARCH_HEIGHT)
              self.InitAttr(op, int, PY_ARCH_SUBD)
              self.InitAttr(op, bool, PY_TILT_CHECK)
              self.InitAttr(op, float, PY_WINDOW_OPEN)
              self.InitAttr(op, bool, PY_WINDOW_DIRECTION)
              self.InitAttr(op, bool, PY_ARCH_POINTED)
              self.InitAttr(op, bool, PY_ARCH_FIXER)
              self.InitAttr(op, float, PY_ARCH_STRENGTH)
      
              # Bars Arch left
              self.InitAttr(op, int, PY_1BARS_LEFT)
              self.InitAttr(op, int, PY_1BARS_LEFTVERT)
              self.InitAttr(op, int, PY_1BARS_LEFTHOR)
              self.InitAttr(op, float, PY_1BARS_LEFTMETHOD2DISTANCE)
              self.InitAttr(op, float, PY_1BARS_LEFTSTARRADIUS)
              self.InitAttr(op, int, PY_1BARS_LEFTDUALVERT)
              self.InitAttr(op, int, PY_1BARS_LEFTDUALHOR)
              self.InitAttr(op, int, PY_1BARS_LEFTSTARSTREAKS)
              self.InitAttr(op, int, PY_1BARS_LEFTSTARSUBD)
      
              if not isCloneInit:
      
                  # Global Parameters
                  op[PY_WINDOW_LIST] = 1
                  op[PY_WINDOW_WIDTH] = 100
                  op[PY_WINDOW_HEIGHT] = 120
      
                  op[PY_BANK] = False
                  op[PY_BANK_SIZE] = 0.0
                  op[PY_BANK_INNERSIZE] = 0.0
                  op[PY_BAR_WIDTH] = 2.0
      
                  # Arch Window
                  op[PY_WINDOW_SEGMENTS] = False
                  op[PY_ARCH_POINTED] = False
                  op[PY_ARCH_FIXER] = False
                  op[PY_ARCH_STRENGTH] = 30
                  op[PY_ARCH_HEIGHT] = 20
                  op[PY_ARCH_SUBD] = 8
                  op[PY_TILT_CHECK] = False
                  op[PY_WINDOW_OPEN] = 0.0
                  op[PY_WINDOW_DIRECTION] = False
      
                  # Bars Arch Window left
                  op[PY_1BARS_LEFT] = 0
                  op[PY_1BARS_LEFTVERT] = 1
                  op[PY_1BARS_LEFTHOR] = 1
                  op[PY_1BARS_LEFTMETHOD2DISTANCE] = 50
                  op[PY_1BARS_LEFTSTARRADIUS] = 20
                  op[PY_1BARS_LEFTDUALVERT] = 3
                  op[PY_1BARS_LEFTDUALHOR] = 1
                  op[PY_1BARS_LEFTSTARSTREAKS] = 4
                  op[PY_1BARS_LEFTSTARSUBD] = 2
      
              # op[c4d.MSG_CHANGE]
              return True
      
          def Message(self, node, type, data):
      
              if type == c4d.MSG_MENUPREPARE:
                  self.create_tex_tags(node, "Sill")
                  self.create_tex_tags(node, "Handle")
                  self.create_tex_tags(node, "Bars")
                  self.create_tex_tags(node, "Glass")
                  self.create_tex_tags(node, "Frame")
      
              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)
      
              return self.window_arch(op)
      
          def GetDDescription(self, op, description, flags):
      
              if not description.LoadDescription(op.GetType()):
                  return False
      
              single_id = description.GetSingleDescID()
      
              # Window 1 : Arch Window ==========================
              if op[PY_WINDOW_LIST] == 1:
                  self.desc_arch(op, single_id, description, flags)
      
              return True, flags | c4d.DESCFLAGS_DESC_LOADED
      
          def GetDEnabling(self, op, did, t_data, flags, itemdesc):
      
              # Window 1: Arch Window
              if op[PY_WINDOW_LIST] == 1:
                  if did[0].id == PY_1BARS_LEFTMETHOD2DISTANCE:
                      if op[PY_1BARS_LEFT] <= 1:
                          return False
      
              return True

      Thanks,
      T.S.B

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @ThomasB
        last edited by ferdinand

        Hey @ThomasB,

        Thank you for reaching out to us. As a minor side note - when you want to embed an mp4 video, you must give it its own line/paragraph, otherwise the embedding won't trigger. I have fixed that for you in your posting.

        I gave your plugin a spin and tried to recreate your bug conditions, but at least in 2024.2 Win was unable to trigger the bug (see video at the end of my posting). When my answer does not help, you should consider describing your bug more precisely. You should have a look at Support Procedures: Reporting Bugs.

        But despite the fact that your plugin runs fine on my machine, there is one thing that sticks out in your code, namely that you misuse SendModelingCommand. When you run SMC from a threaded context such as GetVirtualObjects, you are bound by the threading restrictions and therefore cannot alter a loaded document, e.g., the document your plugin instance lives in.

        You however pass multiple times op.GetDocument() as doc to SMC. I.e., you try to run SMC in the document your node is contained in. This is a threading violation which easily can lead to a freeze in 2024 with its C++ API overhaul. What you also do, and what is even worse, is that you pass a document as doc where your SMC operand is actually not a member of. You do this for example here in bar_cutter:

        extrude = c4d.BaseObject(c4d.Oextrude)
        extrude[c4d.EXTRUDEOBJECT_FLIPNORMALS] = normal
        extrude[c4d.EXTRUDEOBJECT_EXTRUSIONOFFSET] = direction
        extrude.SetName("Glass")
        glass_spline.InsertUnder(extrude)
        
        extrude: c4d.PolygonObject = c4d.utils.SendModelingCommand(
            command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
            list=[extrude.GetClone()],
            doc=op.GetDocument())[0]
        

        extrude is not a member of the document of op, it is in fact not a member of any document. In smc_extrude_s26.py I once dissected the subject of how to run SMC in different scenarios. In the bar_cutter case things are quite easy since extrude is an orphaned node anyway. You can just insert it into a dummy document you create. When you then want to include extrude in the output of your GetVirtualObjects, you must not forget to remove it from your dummy document again (extrude.Remove()) as nodes can only be part of one document.

        When you are still running into problems, please provide a more precise freeze report (exact c4d and OS version, as well as a step-by-step in reproduction list as shown in Support Procedures: Reporting Bugs).

        Cheers,
        Ferdinand

        Running your plugin on my Windows machine in 2024.2.

        My console, despite the print out, I have loaded the 2024.0 version and am running 2024.2.
        b5e611af-1b54-4bcd-b12b-feff540dbd8b-image.png

        MAXON SDK Specialist
        developers.maxon.net

        ThomasBT 1 Reply Last reply Reply Quote 1
        • ThomasBT
          ThomasB @ferdinand
          last edited by

          @ferdinand
          Hello Ferdinand,
          Thank you very much first of all.
          yes, you're right, I worked extremely sloppily with the SMC method, of course I'll take the threading into account and also work with a Temp Document.

          Regarding the problem itself, I can only say that reinstalling CINEMA 4D solved our problem.

          Cheers

          Thanks,
          T.S.B

          1 Reply Last reply Reply Quote 1
          • First post
            Last post