Skip to content
Snippets Groups Projects
operators.py 56.1 KiB
Newer Older
  • Learn to ignore specific revisions
  •                 # 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'''
        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
    
            view_layer = context.view_layer.name
    
            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 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'''
    
        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 == {"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'''
        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
    
            view_layer = context.view_layer.name
    
            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 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)
    
            # 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": {},
                       "hide_history": {},
                       "disable_history": {},
                       "render_history": {},
    
                       "exclude_all_history": [],
                       "select_all_history": [],
                       "hide_all_history": [],
                       "disable_all_history": [],
                       "render_all_history": []
                       }
    
    
    class CMPhantomModeOperator(Operator):
    
        '''Toggle Phantom Mode'''
        bl_label = "Toggle Phantom Mode"
        bl_idname = "view3d.toggle_phantom_mode"
    
        def execute(self, context):
            global phantom_history
            global rto_history
    
            cm = context.scene.collection_manager
            view_layer = context.view_layer
    
            # enter Phantom Mode
    
            if not cm.in_phantom_mode:
    
                cm.in_phantom_mode = True
    
                # save current visibility state
    
                phantom_history["view_layer"] = view_layer.name
    
                laycol_iter_list = [view_layer.layer_collection.children]
    
                while len(laycol_iter_list) > 0:
                    new_laycol_iter_list = []
                    for laycol_iter in laycol_iter_list:
                        for layer_collection in laycol_iter:
                            phantom_history["initial_state"][layer_collection.name] = {
                                "exclude": layer_collection.exclude,
                                "select": layer_collection.collection.hide_select,
                                "hide": layer_collection.hide_viewport,
                                "disable": layer_collection.collection.hide_viewport,
                                "render": 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
    
                # save current rto history
                for rto, history, in rto_history.items():
    
                    if history.get(view_layer.name, None):
                        phantom_history[rto+"_history"] = deepcopy(history[view_layer.name])
    
            # return to normal mode
            else:
    
                laycol_iter_list = [view_layer.layer_collection.children]
    
                while len(laycol_iter_list) > 0:
                    new_laycol_iter_list = []
                    for laycol_iter in laycol_iter_list:
                        for layer_collection in laycol_iter:
                            phantom_laycol = phantom_history["initial_state"][layer_collection.name]
    
                            layer_collection.exclude = \
                                phantom_laycol["exclude"]
    
                            layer_collection.collection.hide_select = \
                                phantom_laycol["select"]
    
                            layer_collection.hide_viewport = \
                                phantom_laycol["hide"]
    
                            layer_collection.collection.hide_viewport = \
                                phantom_laycol["disable"]
    
                            layer_collection.collection.hide_render = \
                                phantom_laycol["render"]
    
                            if len(layer_collection.children) > 0:
                                new_laycol_iter_list.append(layer_collection.children)
    
                    laycol_iter_list = new_laycol_iter_list
    
                # restore previous rto history
                for rto, history, in rto_history.items():
    
                    if view_layer.name in history:
                        del history[view_layer.name]
    
                    if phantom_history[rto+"_history"]:
    
                        history[view_layer.name] = deepcopy(phantom_history[rto+"_history"])
    
                    phantom_history[rto+"_history"].clear()
    
                cm.in_phantom_mode = False
    
            return {'FINISHED'}