Skip to content
Snippets Groups Projects
operators.py 73.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •                     laycol["ptr"].hide_viewport = False
                        laycol = laycol["parent"]
    
                    cls.isolated = True
    
            elif modifiers == {"ctrl"}:
    
                # toggle children
    
                # reset hide history
                del rto_history["hide"][view_layer]
    
                # toggle view of collection
                state = not laycol_ptr.hide_viewport
                laycol_ptr.hide_viewport = state
    
                # pass state to children
                laycol_iter_list = [laycol_ptr.children]
                while len(laycol_iter_list) > 0:
                    new_laycol_iter_list = []
                    for laycol_iter in laycol_iter_list:
                        for layer_collection in laycol_iter:
                            layer_collection.hide_viewport = state
                            if len(layer_collection.children) > 0:
                                new_laycol_iter_list.append(layer_collection.children)
    
                    laycol_iter_list = new_laycol_iter_list
    
                cls.isolated = False
    
            elif modifiers == {"ctrl", "shift"}:
                # isolate nested collections
    
                laycol = layer_collections[self.name]
    
                # check if previous state should be restored
                if cls.isolated and self.name == target:
                    # restore previous state
                    for x, item in enumerate(layer_collections.values()):
                        item["ptr"].hide_viewport = hide_history[x]
    
                    # reset hide history
                    del rto_history["hide"][view_layer]
    
                    cls.isolated = False
    
                else:
                    # isolate nested visibility
    
                    rto_history["hide"][view_layer]["target"] = self.name
    
                    # reset hide history
                    hide_history.clear()
    
                    # save state
                    for item in layer_collections.values():
                        hide_history.append(item["ptr"].hide_viewport)
    
                    # get child states
                    child_states = {}
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                child_states[layer_collection.name] = layer_collection.hide_viewport
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    # hide all collections
                    for laycol in layer_collections.values():
                        laycol["ptr"].hide_viewport = True
    
                    # show active collection plus parents
                    laycol_ptr.hide_viewport = False
    
                    laycol = layer_collections[self.name]
                    while laycol["id"] != 0:
                        laycol["ptr"].hide_viewport = False
                        laycol = laycol["parent"]
    
                    # restore child states
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                layer_collection.hide_viewport = child_states[layer_collection.name]
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    cls.isolated = True
    
    
                # reset hide history
                del rto_history["hide"][view_layer]
    
                # toggle view of collection
                laycol_ptr.hide_viewport = not laycol_ptr.hide_viewport
    
            # reset hide all history
            if view_layer in rto_history["hide_all"]:
                del rto_history["hide_all"][view_layer]
    
    class CMUnHideAllOperator(Operator):
    
        '''  * Click to toggle between current visibility state and all visible.\n  * Shift-Click to invert visibility status of all collections\n  * Ctrl-Click to Copy/Paste RTOs\n  * Ctrl-Alt-Click to swap RTOs\n  * Alt-Click to discard history and copy/swap actions'''
    
        bl_label = "Toggle Hidden Status Of All Collections"
        bl_idname = "view3d.un_hide_all_collections"
        bl_options = {'REGISTER', 'UNDO'}
    
        def invoke(self, context, event):
            global rto_history
    
            global copy_buffer
            global swap_buffer
    
            view_layer = context.view_layer.name
    
            modifiers = get_modifiers(event)
    
    
            if not view_layer in rto_history["hide_all"]:
                rto_history["hide_all"][view_layer] = []
    
            hide_all_history = rto_history["hide_all"][view_layer]
    
            if modifiers == {"alt"}:
                # clear RTO history
                del rto_history["hide_all"][view_layer]
    
                # clear copy buffer
                if copy_buffer["RTO"] == "hide_viewport":
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                # clear swap buffer
                if swap_buffer["A"]["RTO"] == "hide_viewport":
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl"}:
    
                if not copy_buffer["values"]:
                    # copy
                    copy_buffer["RTO"] = "hide_viewport"
                    for laycol in layer_collections.values():
                        copy_buffer["values"].append(laycol["ptr"].hide_viewport)
    
                else:
                    # paste
                    for x, laycol in enumerate(layer_collections.values()):
                        laycol["ptr"].hide_viewport = copy_buffer["values"][x]
    
                    # clear copy buffer
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl", "alt"}:
    
                if not swap_buffer["A"]["values"]:
                    # get A
                    swap_buffer["A"]["RTO"] = "hide_viewport"
                    for laycol in layer_collections.values():
                        swap_buffer["A"]["values"].append(laycol["ptr"].hide_viewport)
    
                else:
                    # get B
                    swap_buffer["B"]["RTO"] = "hide_viewport"
                    for laycol in layer_collections.values():
                        swap_buffer["B"]["values"].append(laycol["ptr"].hide_viewport)
    
                    # swap A with B
                    for x, laycol in enumerate(layer_collections.values()):
                        attr_A = attr_B = laycol["ptr"]
    
                        # get attributes
                        RTO_A = swap_buffer["A"]["RTO"].split(".")
                        RTO_B = swap_buffer["B"]["RTO"].split(".")
    
                        if RTO_A[0] == "collection":
                            attr_A = getattr(attr_A, RTO_A[0])
    
                        if RTO_B[0] == "collection":
                            attr_B = getattr(attr_B, RTO_B[0])
    
    
                        # swap values
                        setattr(attr_A, RTO_A[-1], swap_buffer["B"]["values"][x])
                        setattr(attr_B, RTO_B[-1], swap_buffer["A"]["values"][x])
    
                    # clear swap buffer
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
    
            if len(hide_all_history) == 0:
                hide_all_history.clear()
                keep_history = False
    
                for item in layer_collections.values():
                    if event.shift:
                        keep_history = True
                        hide_all_history.append(item["ptr"].hide_viewport)
                        item["ptr"].hide_viewport = not item["ptr"].hide_viewport
    
                    else:
                        if item["ptr"].hide_viewport:
                            keep_history = True
    
                        hide_all_history.append(item["ptr"].hide_viewport)
                        item["ptr"].hide_viewport = False
    
                if not keep_history:
                    del rto_history["hide_all"][view_layer]
    
            else:
                for x, item in enumerate(layer_collections.values()):
                    item["ptr"].hide_viewport = hide_all_history[x]
    
                del rto_history["hide_all"][view_layer]
    
    class CMDisableViewportOperator(Operator):
    
        '''  * Shift-Click to isolate/restore previous state\n  * Ctrl-Click to toggle children\n  * Shift-Ctrl-Click to toggle nested isolation\n  * Alt-Click to discard history'''
    
        bl_label = "Disable Collection in Viewport"
        bl_idname = "view3d.disable_viewport_collection"
        bl_options = {'REGISTER', 'UNDO'}
    
        name: StringProperty()
    
        # static class var
        isolated = False
    
    
        def invoke(self, context, event):
            global rto_history
    
            cls = CMDisableViewportOperator
    
            modifiers = get_modifiers(event)
    
            view_layer = context.view_layer.name
            laycol_ptr = layer_collections[self.name]["ptr"]
    
            if not view_layer in rto_history["disable"]:
                rto_history["disable"][view_layer] = {"target": "", "history": []}
    
            target = rto_history["disable"][view_layer]["target"]
    
            disable_history = rto_history["disable"][view_layer]["history"]
    
            if modifiers == {"alt"}:
                del rto_history["disable"][view_layer]
                cls.isolated = False
    
            elif modifiers == {"shift"}:
    
                # isolate/de-isolate disablement of collections in viewport
    
                laycol = layer_collections[self.name]
    
    
                # get active collections
    
                active_layer_collections = [x["ptr"] for x in layer_collections.values()
                                            if x["ptr"].collection.hide_viewport == False]
    
                # check if previous state should be restored
                if cls.isolated and self.name == target:
                    # restore previous state
                    for x, item in enumerate(layer_collections.values()):
                        item["ptr"].collection.hide_viewport = disable_history[x]
    
                    # reset disable history
                    del rto_history["disable"][view_layer]
    
                # check if all collections should be enabled
    
                elif (len(active_layer_collections) == 1 and
                      active_layer_collections[0].name == self.name):
    
                    # enable all collections in viewport
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_viewport = False
    
                    # reset disable history
                    del rto_history["disable"][view_layer]
    
                     # isolate disable
    
                    rto_history["disable"][view_layer]["target"] = self.name
    
    
                    # reset disable history
                    disable_history.clear()
    
                    # save state
                    for item in layer_collections.values():
                        disable_history.append(item["ptr"].collection.hide_viewport)
    
                    # disable all collections in viewport
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_viewport = True
    
                    # enable active collection plus parents in viewport
                    laycol_ptr.collection.hide_viewport = False
    
                    laycol = layer_collections[self.name]
                    while laycol["id"] != 0:
                        laycol["ptr"].collection.hide_viewport = False
                        laycol = laycol["parent"]
    
                    cls.isolated = True
    
            elif modifiers == {"ctrl"}:
    
                # toggle children
    
                # reset disable history
                del rto_history["disable"][view_layer]
    
                # toggle view of collection
                state = not laycol_ptr.collection.hide_viewport
                laycol_ptr.collection.hide_viewport = state
    
                # pass state to children
                laycol_iter_list = [laycol_ptr.children]
                while len(laycol_iter_list) > 0:
                    new_laycol_iter_list = []
                    for laycol_iter in laycol_iter_list:
                        for layer_collection in laycol_iter:
                            layer_collection.collection.hide_viewport = state
                            if len(layer_collection.children) > 0:
                                new_laycol_iter_list.append(layer_collection.children)
    
                    laycol_iter_list = new_laycol_iter_list
    
                cls.isolated = False
    
            elif modifiers == {"ctrl", "shift"}:
                # isolate nested collections
    
                laycol = layer_collections[self.name]
    
                # check if previous state should be restored
                if cls.isolated and self.name == target:
                    # restore previous state
                    for x, item in enumerate(layer_collections.values()):
                        item["ptr"].collection.hide_viewport = disable_history[x]
    
                    # reset disable history
                    del rto_history["disable"][view_layer]
    
                    cls.isolated = False
    
                else:
                     # isolate nested disable
    
                    rto_history["disable"][view_layer]["target"] = self.name
    
                    # reset disable history
                    disable_history.clear()
    
                    # save state
                    for item in layer_collections.values():
                        disable_history.append(item["ptr"].collection.hide_viewport)
    
                    # get child states
                    child_states = {}
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                child_states[layer_collection.name] = layer_collection.collection.hide_viewport
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    # disable all collections in viewport
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_viewport = True
    
                    # enable active collection plus parents in viewport
                    laycol_ptr.collection.hide_viewport = False
    
                    laycol = layer_collections[self.name]
                    while laycol["id"] != 0:
                        laycol["ptr"].collection.hide_viewport = False
                        laycol = laycol["parent"]
    
                    # restore child states
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                layer_collection.collection.hide_viewport = child_states[layer_collection.name]
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    cls.isolated = True
    
    
                # reset disable history
                del rto_history["disable"][view_layer]
    
                # toggle disable of collection in viewport
                laycol_ptr.collection.hide_viewport = not laycol_ptr.collection.hide_viewport
    
            # reset disable all history
            if view_layer in rto_history["disable_all"]:
                del rto_history["disable_all"][view_layer]
    
    class CMUnDisableViewportAllOperator(Operator):
    
        '''  * Click to toggle between current viewport display and all enabled.\n  * Shift-Click to invert viewport display of all collections\n  * Ctrl-Click to Copy/Paste RTOs\n  * Ctrl-Alt-Click to swap RTOs\n  * Alt-Click to discard history and copy/swap actions'''
    
        bl_label = "Toggle Viewport Display of All Collections"
        bl_idname = "view3d.un_disable_viewport_all_collections"
        bl_options = {'REGISTER', 'UNDO'}
    
        def invoke(self, context, event):
            global rto_history
    
            global copy_buffer
            global swap_buffer
    
            view_layer = context.view_layer.name
    
            modifiers = get_modifiers(event)
    
    
            if not view_layer in rto_history["disable_all"]:
                rto_history["disable_all"][view_layer] = []
    
            disable_all_history = rto_history["disable_all"][view_layer]
    
            if modifiers == {"alt"}:
                # clear RTO history
                del rto_history["disable_all"][view_layer]
    
                # clear copy buffer
                if copy_buffer["RTO"] == "collection.hide_viewport":
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                # clear swap buffer
                if swap_buffer["A"]["RTO"] == "collection.hide_viewport":
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl"}:
    
                if not copy_buffer["values"]:
                    # copy
                    copy_buffer["RTO"] = "collection.hide_viewport"
                    for laycol in layer_collections.values():
                        copy_buffer["values"].append(laycol["ptr"].collection.hide_viewport)
    
                else:
                    # paste
                    for x, laycol in enumerate(layer_collections.values()):
                        laycol["ptr"].collection.hide_viewport = copy_buffer["values"][x]
    
                    # clear copy buffer
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl", "alt"}:
    
                if not swap_buffer["A"]["values"]:
                    # get A
                    swap_buffer["A"]["RTO"] = "collection.hide_viewport"
                    for laycol in layer_collections.values():
                        swap_buffer["A"]["values"].append(laycol["ptr"].collection.hide_viewport)
    
                else:
                    # get B
                    swap_buffer["B"]["RTO"] = "collection.hide_viewport"
                    for laycol in layer_collections.values():
                        swap_buffer["B"]["values"].append(laycol["ptr"].collection.hide_viewport)
    
                    # swap A with B
                    for x, laycol in enumerate(layer_collections.values()):
                        attr_A = attr_B = laycol["ptr"]
    
                        # get attributes
                        RTO_A = swap_buffer["A"]["RTO"].split(".")
                        RTO_B = swap_buffer["B"]["RTO"].split(".")
    
                        if RTO_A[0] == "collection":
                            attr_A = getattr(attr_A, RTO_A[0])
    
                        if RTO_B[0] == "collection":
                            attr_B = getattr(attr_B, RTO_B[0])
    
    
                        # swap values
                        setattr(attr_A, RTO_A[-1], swap_buffer["B"]["values"][x])
                        setattr(attr_B, RTO_B[-1], swap_buffer["A"]["values"][x])
    
                    # clear swap buffer
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
    
            if len(disable_all_history) == 0:
                disable_all_history.clear()
                keep_history = False
    
                for item in layer_collections.values():
    
                    collection = item["ptr"].collection
    
    
                    if event.shift:
                        keep_history = True
    
                        disable_all_history.append(collection.hide_viewport)
                        collection.hide_viewport = not collection.hide_viewport
    
                        if collection.hide_viewport:
    
                            keep_history = True
    
                        disable_all_history.append(collection.hide_viewport)
                        collection.hide_viewport = False
    
                if not keep_history:
                    del rto_history["disable_all"][view_layer]
    
            else:
                for x, item in enumerate(layer_collections.values()):
                    item["ptr"].collection.hide_viewport = disable_all_history[x]
    
                del rto_history["disable_all"][view_layer]
    
    class CMDisableRenderOperator(Operator):
    
        '''  * Shift-Click to isolate/restore previous state\n  * Ctrl-Click to toggle children\n  * Shift-Ctrl-Click to toggle nested isolation\n  * Alt-Click to discard history'''
    
        bl_label = "Disable Collection in Render"
        bl_idname = "view3d.disable_render_collection"
        bl_options = {'REGISTER', 'UNDO'}
    
        name: StringProperty()
    
        # static class var
        isolated = False
    
    
        def invoke(self, context, event):
            global rto_history
    
            cls = CMDisableRenderOperator
    
            modifiers = get_modifiers(event)
    
            view_layer = context.view_layer.name
            laycol_ptr = layer_collections[self.name]["ptr"]
    
            if not view_layer in rto_history["render"]:
                rto_history["render"][view_layer] = {"target": "", "history": []}
    
    
            target = rto_history["render"][view_layer]["target"]
    
            render_history = rto_history["render"][view_layer]["history"]
    
    
            if modifiers == {"alt"}:
                del rto_history["render"][view_layer]
                cls.isolated = False
    
            elif modifiers == {"shift"}:
    
                # isolate/de-isolate render of collections
    
                laycol = layer_collections[self.name]
    
    
                # get active collections
    
                active_layer_collections = [x["ptr"] for x in layer_collections.values()
                                            if x["ptr"].collection.hide_render == False]
    
                # check if previous state should be restored
                if cls.isolated and self.name == target:
                    # restore previous state
                    for x, item in enumerate(layer_collections.values()):
                        item["ptr"].collection.hide_render = render_history[x]
    
                    # reset render history
                    del rto_history["render"][view_layer]
    
                # check if all collections should be enabled
    
                elif (len(active_layer_collections) == 1 and
                      active_layer_collections[0].name == self.name):
    
                    # allow render of all collections
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_render = False
    
                    # reset render history
                    del rto_history["render"][view_layer]
    
                    # isolate renderability
    
                    rto_history["render"][view_layer]["target"] = self.name
    
    
                    # reset render history
                    render_history.clear()
    
                    # save state
                    for item in layer_collections.values():
                        render_history.append(item["ptr"].collection.hide_render)
    
                    # disallow render of all collections
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_render = True
    
                    # allow render of active collection plus parents
                    laycol_ptr.collection.hide_render = False
    
                    laycol = layer_collections[self.name]
                    while laycol["id"] != 0:
                        laycol["ptr"].collection.hide_render = False
                        laycol = laycol["parent"]
    
                    cls.isolated = True
    
            elif modifiers == {"ctrl"}:
    
                # toggle children
    
                # reset render history
                del rto_history["render"][view_layer]
    
                # toggle view of collection
                state = not laycol_ptr.collection.hide_render
                laycol_ptr.collection.hide_render = state
    
                # pass state to children
                laycol_iter_list = [laycol_ptr.children]
                while len(laycol_iter_list) > 0:
                    new_laycol_iter_list = []
                    for laycol_iter in laycol_iter_list:
                        for layer_collection in laycol_iter:
                            layer_collection.collection.hide_render = state
                            if len(layer_collection.children) > 0:
                                new_laycol_iter_list.append(layer_collection.children)
    
                    laycol_iter_list = new_laycol_iter_list
    
                cls.isolated = False
    
            elif modifiers == {"ctrl", "shift"}:
                # isolate nested collections
    
                laycol = layer_collections[self.name]
    
                # check if previous state should be restored
                if cls.isolated and self.name == target:
                    # restore previous state
                    for x, item in enumerate(layer_collections.values()):
                        item["ptr"].collection.hide_render = render_history[x]
    
                    # reset render history
                    del rto_history["render"][view_layer]
    
                    cls.isolated = False
    
                else:
                    # isolate nested renderability
    
                    rto_history["render"][view_layer]["target"] = self.name
    
                    # reset render history
                    render_history.clear()
    
                    # save state
                    for item in layer_collections.values():
                        render_history.append(item["ptr"].collection.hide_render)
    
                    # get child states
                    child_states = {}
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                child_states[layer_collection.name] = layer_collection.collection.hide_render
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    # disallow render of all collections
                    for laycol in layer_collections.values():
                        laycol["ptr"].collection.hide_render = True
    
                    # allow render of active collection plus parents
                    laycol_ptr.collection.hide_render = False
    
                    laycol = layer_collections[self.name]
                    while laycol["id"] != 0:
                        laycol["ptr"].collection.hide_render = False
                        laycol = laycol["parent"]
    
                    # restore child states
                    laycol_iter_list = [laycol_ptr.children]
                    while len(laycol_iter_list) > 0:
                        new_laycol_iter_list = []
                        for laycol_iter in laycol_iter_list:
                            for layer_collection in laycol_iter:
                                layer_collection.collection.hide_render = child_states[layer_collection.name]
                                if len(layer_collection.children) > 0:
                                    new_laycol_iter_list.append(layer_collection.children)
    
                        laycol_iter_list = new_laycol_iter_list
    
                    cls.isolated = True
    
    
                # reset render history
                del rto_history["render"][view_layer]
    
                # toggle renderability of collection
                laycol_ptr.collection.hide_render = not laycol_ptr.collection.hide_render
    
            # reset render all history
            if view_layer in rto_history["render_all"]:
                del rto_history["render_all"][view_layer]
    
    class CMUnDisableRenderAllOperator(Operator):
    
        '''  * Click to toggle between current render status and all rendered.\n  * Shift-Click to invert render status of all collections\n  * Ctrl-Click to Copy/Paste RTOs\n  * Ctrl-Alt-Click to swap RTOs\n  * Alt-Click to discard history and copy/swap actions'''
    
        bl_label = "Toggle Render Status of All Collections"
        bl_idname = "view3d.un_disable_render_all_collections"
        bl_options = {'REGISTER', 'UNDO'}
    
        def invoke(self, context, event):
            global rto_history
    
            global copy_buffer
            global swap_buffer
    
            view_layer = context.view_layer.name
    
            modifiers = get_modifiers(event)
    
    
            if not view_layer in rto_history["render_all"]:
                rto_history["render_all"][view_layer] = []
    
            render_all_history = rto_history["render_all"][view_layer]
    
            if modifiers == {"alt"}:
                # clear RTO history
                del rto_history["render_all"][view_layer]
    
                # clear copy buffer
                if copy_buffer["RTO"] == "collection.hide_render":
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                # clear swap buffer
                if swap_buffer["A"]["RTO"] == "collection.hide_render":
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl"}:
    
                if not copy_buffer["values"]:
                    # copy
                    copy_buffer["RTO"] = "collection.hide_render"
                    for laycol in layer_collections.values():
                        copy_buffer["values"].append(laycol["ptr"].collection.hide_render)
    
                else:
                    # paste
                    for x, laycol in enumerate(layer_collections.values()):
                        laycol["ptr"].collection.hide_render = copy_buffer["values"][x]
    
                    # clear copy buffer
                    copy_buffer["RTO"] = ""
                    copy_buffer["values"].clear()
    
                return {'FINISHED'}
    
            if modifiers == {"ctrl", "alt"}:
    
                if not swap_buffer["A"]["values"]:
                    # get A
                    swap_buffer["A"]["RTO"] = "collection.hide_render"
                    for laycol in layer_collections.values():
                        swap_buffer["A"]["values"].append(laycol["ptr"].collection.hide_render)
    
                else:
                    # get B
                    swap_buffer["B"]["RTO"] = "collection.hide_render"
                    for laycol in layer_collections.values():
                        swap_buffer["B"]["values"].append(laycol["ptr"].collection.hide_render)
    
                    # swap A with B
                    for x, laycol in enumerate(layer_collections.values()):
                        attr_A = attr_B = laycol["ptr"]
    
                        # get attributes
                        RTO_A = swap_buffer["A"]["RTO"].split(".")
                        RTO_B = swap_buffer["B"]["RTO"].split(".")
    
                        if RTO_A[0] == "collection":
                            attr_A = getattr(attr_A, RTO_A[0])
    
                        if RTO_B[0] == "collection":
                            attr_B = getattr(attr_B, RTO_B[0])
    
    
                        # swap values
                        setattr(attr_A, RTO_A[-1], swap_buffer["B"]["values"][x])
                        setattr(attr_B, RTO_B[-1], swap_buffer["A"]["values"][x])
    
                    # clear swap buffer
                    swap_buffer["A"]["RTO"] = ""
                    swap_buffer["A"]["values"].clear()
                    swap_buffer["B"]["RTO"] = ""
                    swap_buffer["B"]["values"].clear()
    
                return {'FINISHED'}
    
    
            if len(render_all_history) == 0:
                render_all_history.clear()
                keep_history = False
    
                for item in layer_collections.values():
    
                    collection = item["ptr"].collection
    
    
                    if event.shift:
                        keep_history = True
    
                        render_all_history.append(collection.hide_render)
                        collection.hide_render = not collection.hide_render
    
                        if collection.hide_render:
    
                            keep_history = True
    
                        render_all_history.append(collection.hide_render)
                        collection.hide_render = False
    
                if not keep_history:
                    del rto_history["render_all"][view_layer]
    
            else:
                for x, item in enumerate(layer_collections.values()):
                    item["ptr"].collection.hide_render = render_all_history[x]
    
                del rto_history["render_all"][view_layer]
    
    class CMRemoveCollectionOperator(Operator):
    
        '''Remove Collection'''
        bl_label = "Remove Collection"
        bl_idname = "view3d.remove_collection"
        bl_options = {'UNDO'}
    
        collection_name: StringProperty()
    
        def execute(self, context):
            global rto_history
    
            cm = context.scene.collection_manager
    
    
            laycol = layer_collections[self.collection_name]
            collection = laycol["ptr"].collection
    
            parent_collection = laycol["parent"]["ptr"].collection
    
            # shift all objects in this collection to the parent collection
    
            for obj in collection.objects:
                if obj.name not in parent_collection.objects:
                    parent_collection.objects.link(obj)
    
            # shift all child collections to the parent collection
            if collection.children:
                for subcollection in collection.children:
    
                    parent_collection.children.link(subcollection)
    
            # remove collection and update tree view
            bpy.data.collections.remove(collection)
            update_property_group(context)
    
            if len(cm.cm_list_collection) == cm.cm_list_index:
                cm.cm_list_index = len(cm.cm_list_collection) - 1
    
                update_property_group(context)
    
            if qcd_slots.contains(name=self.collection_name):
                qcd_slots.del_slot(name=self.collection_name)
    
    
            if self.collection_name in qcd_slots.overrides:
                del qcd_slots.overrides[self.collection_name]
    
    
            # reset history
            for rto in rto_history.values():
                rto.clear()
    
            return {'FINISHED'}
    
    rename = [False]
    
    class CMNewCollectionOperator(Operator):
    
        '''Add New Collection'''
        bl_label = "Add New Collection"
        bl_idname = "view3d.add_collection"
        bl_options = {'UNDO'}
    
        child: BoolProperty()
    
        def execute(self, context):
            global rto_history
    
            new_collection = bpy.data.collections.new('Collection')
    
            cm = context.scene.collection_manager
    
    
            # if there are collections
    
            if len(cm.cm_list_collection) > 0:
    
                # get selected collection
    
                laycol = layer_collections[cm.cm_list_collection[cm.cm_list_index].name]
    
                # add new collection
                if self.child:
                    laycol["ptr"].collection.children.link(new_collection)
                    expanded.append(laycol["name"])
    
                    # update tree view property
                    update_property_group(context)
    
                    cm.cm_list_index = layer_collections[new_collection.name]["row_index"]
    
                else:
                    laycol["parent"]["ptr"].collection.children.link(new_collection)
    
                    # update tree view property
                    update_property_group(context)
    
                    cm.cm_list_index = layer_collections[new_collection.name]["row_index"]
    
            # if no collections add top level collection and select it
            else:
    
                context.scene.collection.children.link(new_collection)
    
                # update tree view property
                update_property_group(context)
    
                cm.cm_list_index = 0
    
            global rename
            rename[0] = True
    
            # reset history
            for rto in rto_history.values():
                rto.clear()
    
            return {'FINISHED'}
    
    
    phantom_history = {"view_layer": "",
                       "initial_state": {},
    
                       "exclude_history": {},
                       "select_history": {},