<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Boole Object causes version 2024 to freeze]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">for demonstration purposes, I have an extremely stripped down version (1200 LOC) of my  plugin (6000 LOC) here.<br />
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.</p>
<ul>
<li><strong>Condition: the window bars must be activated. Error with Boole happens in the method</strong></li>
</ul>
<pre><code>def bar_cutter(op, obj, bars, fixed=False)
</code></pre>
<hr />
<h4><strong>Description:</strong></h4>
<p dir="auto">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.</p>
<ul>
<li>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.</li>
<li>I then create a Boole object and throw the previously created bars together with the extrude into the Boole object.</li>
</ul>
<p dir="auto">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.</p>
<hr />
<h4><strong>Problem:</strong></h4>
<p dir="auto">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)</p>
<p dir="auto">And in version 23-2023.2 this works, as can be seen in the video.<br />
But in version 2024 when the polygons intersect, <strong>Cinema 4d freezes.</strong></p>
<p dir="auto">I have a short video to watch here.<br />
<video class="embed-video-local" controls src="https://developers.maxon.net/forum/assets/uploads/files/1705442888217-comparison.mp4">
<p dir="auto">Also the version of the plugin in a zip file for R23-2023 and 2024 for easy reference.<br />
<a href="https://developers.maxon.net/forum/assets/uploads/files/1705443057912-boole-problem.zip" target="_blank" rel="noopener noreferrer nofollow ugc">Boole-Problem.zip</a></p>
<p dir="auto">It actually only happens when the intersection of the intersected polygons creates a slightly deformed extruder.</p>
<hr />
<h4><strong>Question:</strong></h4>
<p dir="auto">Why does this freeze in 2024... Version and in R23-2023 not?</p>
<hr />
<h4><strong>Temporary Solution:</strong></h4>
<p dir="auto">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......</p>
<p dir="auto">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.</p>
<pre><code>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 &gt; height:
                length = width
            else:
                length = height
            if full_spiral:

                if count &lt;= 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 &lt;= 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 &gt; 4:
                        bar_container.SetRelRot(c4d.Vector(0, 0, c4d.utils.DegToRad(180)))
            else:

                if count &lt; 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] &gt; 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] &lt;= 1:
                    return False

        return True</code></pre>
</video></p>]]></description><link>http://developers.maxon.net/forum/topic/15334/boole-object-causes-version-2024-to-freeze</link><generator>RSS for Node</generator><lastBuildDate>Thu, 18 Jun 2026 07:36:45 GMT</lastBuildDate><atom:link href="http://developers.maxon.net/forum/topic/15334.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 16 Jan 2024 22:46:19 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Boole Object causes version 2024 to freeze on Thu, 18 Jan 2024 23:50:59 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a><br />
Hello Ferdinand,<br />
Thank you very much first of all.<br />
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.</p>
<p dir="auto">Regarding the problem itself, I can only say that reinstalling CINEMA 4D solved our problem.</p>
<p dir="auto">Cheers</p>
]]></description><link>http://developers.maxon.net/forum/post/73558</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73558</guid><dc:creator><![CDATA[ThomasB]]></dc:creator><pubDate>Thu, 18 Jan 2024 23:50:59 GMT</pubDate></item><item><title><![CDATA[Reply to Boole Object causes version 2024 to freeze on Fri, 19 Jan 2024 09:11:01 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/thomasb">@<bdi>ThomasB</bdi></a>,</p>
<p dir="auto">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.</p>
<p dir="auto">I gave your plugin a spin and tried to recreate your bug conditions, but at least in <em>2024.2 Win</em> 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 <a href="https://developers.maxon.net/forum/topic/15244/support-procedures" target="_blank" rel="noopener noreferrer nofollow ugc">Support Procedures: Reporting Bugs</a>.</p>
<p dir="auto">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 <code>SendModelingCommand</code>. When you run <code>SMC</code> from a threaded context such as <code>GetVirtualObjects</code>, you are bound by the <a href="https://developers.maxon.net/docs/py/2024_2_0/manuals/manual_threading.html#threading-information" target="_blank" rel="noopener noreferrer nofollow ugc">threading restrictions</a> and therefore cannot alter a loaded document, e.g., the document your plugin instance lives in.</p>
<p dir="auto">You however pass multiple times <code>op.GetDocument()</code> as <code>doc</code> 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 <a href="https://developers.maxon.net/docs/cpp/2024_2_0/manual_migrating_plugins_to_2024.html" target="_blank" rel="noopener noreferrer nofollow ugc">C++ API overhaul</a>. What you also do, and what is even worse, is that you pass a document as <code>doc</code> where your SMC operand is actually <strong>not</strong> a member of. You do this for example here in <code>bar_cutter</code>:</p>
<pre><code class="language-py">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]
</code></pre>
<p dir="auto"><code>extrude</code> is not a member of the document of <code>op</code>, it is in fact not a member of any document. In <a href="https://github.com/PluginCafe/cinema4d_py_sdk_extended/blob/master/scripts/04_3d_concepts/modeling/modeling_commands/smc_extrude_s26.py" target="_blank" rel="noopener noreferrer nofollow ugc">smc_extrude_s26.py</a> I once dissected the subject of how to run SMC in different scenarios. In the <code>bar_cutter</code> case things are quite easy since <code>extrude</code> is an orphaned node anyway. You can just insert it into a dummy document you create. When you then want to include <code>extrude</code> in the output of your <code>GetVirtualObjects</code>, you must not forget to remove it from your dummy document again (<code>extrude.Remove()</code>) as nodes can only be part of one document.</p>
<p dir="auto">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  <a href="https://developers.maxon.net/forum/topic/15244/support-procedures" target="_blank" rel="noopener noreferrer nofollow ugc">Support Procedures: Reporting Bugs</a>).</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
<p dir="auto">Running your plugin on my Windows machine in 2024.2.</p>
<p dir="auto"><video class="embed-video-local" controls src="/forum/assets/uploads/files/1705486441291-c4d_windows_2024_no_crash.mp4">
<p dir="auto">My console, despite the print out, I have loaded the 2024.0 version and am running 2024.2.<br />
<img src="/forum/assets/uploads/files/1705490778650-b5e611af-1b54-4bcd-b12b-feff540dbd8b-image.png" alt="b5e611af-1b54-4bcd-b12b-feff540dbd8b-image.png" class=" img-fluid img-markdown" /></p>
</video></p>]]></description><link>http://developers.maxon.net/forum/post/73552</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/73552</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Fri, 19 Jan 2024 09:11:01 GMT</pubDate></item></channel></rss>