Skip to content
Snippets Groups Projects
scene_amaranth_toolset.py 116 KiB
Newer Older
  • Learn to ignore specific revisions
  • Pablo Vazquez's avatar
    Pablo Vazquez committed
        if ob and ob.dupli_group and ob.dupli_group.library:
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            lib = ob.dupli_group.library.filepath
    
            row.operator(AMTH_SCENE_OT_blender_instance_open.bl_idname,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                text="Library: %s" % lib,
                emboss=False,
                icon="LINK_BLEND").filepath=lib
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # // FEATURE: Dupli  Group Path
    
    # FEATURE: Color Management Presets
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    class AMTH_SCENE_MT_color_management_presets(Menu):
    
        """List of Color Management presets"""
        bl_label = "Color Management Presets"
        preset_subdir = "color"
        preset_operator = "script.execute_preset"
        draw = Menu.draw_preset
    
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    class AMTH_AddPresetColorManagement(AddPresetBase, Operator):
    
        """Add or remove a Color Management preset"""
        bl_idname = "scene.color_management_preset_add"
        bl_label = "Add Color Management Preset"
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        preset_menu = "AMTH_SCENE_MT_color_management_presets"
    
    
        preset_defines = [
            "scene = bpy.context.scene"
        ]
    
        preset_values = [
            "scene.view_settings.view_transform",
            "scene.display_settings.display_device",
            "scene.view_settings.exposure",
            "scene.view_settings.gamma",
            "scene.view_settings.look",
            "scene.view_settings.use_curve_mapping",
            "scene.sequencer_colorspace_settings.name",
        ]
    
        preset_subdir = "color"
    
    def ui_color_management_presets(self, context):
        
        layout = self.layout
    
        row = layout.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        row.menu("AMTH_SCENE_MT_color_management_presets", text=bpy.types.AMTH_SCENE_MT_color_management_presets.bl_label)
    
        row.operator("scene.color_management_preset_add", text="", icon="ZOOMIN")
        row.operator("scene.color_management_preset_add", text="", icon="ZOOMOUT").remove_active = True
        layout.separator()
    # // FEATURE: Color Management Presets
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # FEATURE: Sequencer Extra Info
    def act_strip(context):
        try:
            return context.scene.sequence_editor.active_strip
        except AttributeError:
            return None
    
    def ui_sequencer_extra_info(self, context):
    
        layout = self.layout
        strip = act_strip(context)
    
        if strip:
            seq_type = strip.type
    
            if seq_type and seq_type == 'IMAGE':
                elem = strip.strip_elem_from_frame(context.scene.frame_current)
                if elem:
                    layout.label(text="%s %s" % (
                        elem.filename,
                        "[%s]" % (context.scene.frame_current - strip.frame_start)))
    # // FEATURE: Sequencer Extra Info
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # FEATURE: Normal Node Values, by Lukas Tönne
    def normal_vector_get(self):
        return self.outputs['Normal'].default_value
    
    def normal_vector_set(self, values):
        # default_value allows un-normalized values,
        # do this here to prevent awkward results
        values = Vector(values).normalized()
        self.outputs['Normal'].default_value = values
    
    prop_normal_vector = bpy.props.FloatVectorProperty(
                            name="Normal", size=3, subtype='XYZ',
                            min=-1.0, max=1.0, soft_min=-1.0, soft_max=1.0,
                            get=normal_vector_get, set=normal_vector_set
                            )
    
    def act_node(context):
        try:
            return context.active_node
        except AttributeError:
            return None
    
    def ui_node_normal_values(self, context):
    
        node = act_node(context)
    
        if act_node:
            if node and node.type == 'NORMAL':
                self.layout.prop(node, "normal_vector", text="")
    
    # // FEATURE: Normal Node Values, by Lukas Tönne
    
    # FEATURE: Object ID for objects inside DupliGroups
    class AMTH_OBJECT_OT_id_dupligroup(Operator):
        '''Set the Object ID for objects in the dupli group'''
        bl_idname = "object.amaranth_object_id_duplis"
        bl_label = "Apply Object ID to Duplis"
    
        clear = False
    
        @classmethod
        def poll(cls, context):
            return context.active_object.dupli_group
    
        def execute(self, context):
            self.__class__.clear = False
            ob = context.active_object
            amth_text_exists = amaranth_text_startup(context)
            script_exists = False
            script_intro = "# OB ID: %s" % ob.name
            obdata = "bpy.data.objects['%s']" % ob.name
            script = "%s" % (
                "\nif %(obdata)s and %(obdata)s.dupli_group and %(obdata)s.pass_index != 0: %(obname)s \n"
                "    for dob in %(obdata)s.dupli_group.objects: %(obname)s \n"
                "        dob.pass_index = %(obdata)s.pass_index %(obname)s \n" %
                    {'obdata' : obdata, 'obname' : script_intro})
    
            for txt in bpy.data.texts:
                if txt.name == amth_text.name:
                    for li in txt.lines:
                        if script_intro == li.body:
                            script_exists = True
                            continue
    
            if not script_exists:
                amth_text.write("\n")
                amth_text.write(script_intro)
                amth_text.write(script)
    
            if ob and ob.dupli_group:
                if ob.pass_index != 0:
                    for dob in ob.dupli_group.objects:
                        dob.pass_index = ob.pass_index
    
            self.report({'INFO'},
                "%s ID: %s to all objects in this Dupli Group" % (
                    "Applied" if not script_exists else "Updated",
                    ob.pass_index))
    
            return{'FINISHED'}
    
    class AMTH_OBJECT_OT_id_dupligroup_clear(Operator):
        '''Clear the Object ID from objects in dupli group'''
        bl_idname = "object.amaranth_object_id_duplis_clear"
        bl_label = "Clear Object ID from Duplis"
    
        @classmethod
        def poll(cls, context):
            return context.active_object.dupli_group
    
        def execute(self, context):
            context.active_object.pass_index = 0
            AMTH_OBJECT_OT_id_dupligroup.clear = True
            amth_text_exists = amaranth_text_startup(context)
            match_first = "# OB ID: %s" % context.active_object.name
    
            if amth_text_exists:
                for txt in bpy.data.texts:
                    if txt.name == amth_text.name:
                        for li in txt.lines:
                            if match_first in li.body:
                                li.body = ''
                                continue
    
            self.report({'INFO'}, "Object IDs back to normal")
            return{'FINISHED'}
    
    def ui_object_id_duplis(self, context):
    
        if context.active_object.dupli_group:
            split = self.layout.split()
            row = split.row(align=True)
            row.enabled = context.active_object.pass_index != 0
            row.operator(
                AMTH_OBJECT_OT_id_dupligroup.bl_idname)
            row.operator(
                AMTH_OBJECT_OT_id_dupligroup_clear.bl_idname,
                icon="X", text="")
            split.separator()
    
            if AMTH_OBJECT_OT_id_dupligroup.clear:
                self.layout.label(text="Next time you save/reload this file, "
                                            "object IDs will be back to normal",
                                  icon="INFO")
    
    # // FEATURE: Object ID for objects inside DupliGroups
    # UI: Warning about Z not connected when using EXR
    def ui_render_output_z(self, context):
    
        scene = bpy.context.scene
        image = scene.render.image_settings
        if scene.render.use_compositing and \
            image.file_format == 'OPEN_EXR' and \
            image.use_zbuffer:
            if scene.node_tree and scene.node_tree.nodes:
                for no in scene.node_tree.nodes:
                    if no.type == 'COMPOSITE':
                        if not no.inputs['Z'].is_linked:
                            self.layout.label(
                                text="The Z output in node \"%s\" is not connected" % 
                                    no.name, icon="ERROR")
    
    # // UI: Warning about Z not connected
    
    # FEATURE: Delete Materials not assigned to any verts
    class AMTH_OBJECT_OT_material_remove_unassigned(Operator):
        '''Remove materials not assigned to any vertex'''
        bl_idname = "object.amaranth_object_material_remove_unassigned"
        bl_label = "Remove Unassigned Materials"
    
        @classmethod
        def poll(cls, context):
            return context.active_object.material_slots
    
        def execute(self, context):
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            scene = context.scene
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            act_ob = context.active_object
            count = len(act_ob.material_slots)
            materials_removed = []
            act_ob.active_material_index = 0
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            is_visible = True
    
            if act_ob not in context.visible_objects:
                is_visible = False
                n = -1
                for lay in act_ob.layers:
                    n += 1
                    if lay:
                        break
    
                scene.layers[n] = True
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
            for slot in act_ob.material_slots:
                count -= 1
    
                bpy.ops.object.mode_set(mode='EDIT')
                bpy.ops.mesh.select_all(action='DESELECT')
                act_ob.active_material_index = count
                bpy.ops.object.material_slot_select()
                
                if act_ob.data.total_vert_sel == 0 or \
                    (len(act_ob.material_slots) == 1 and not \
                        act_ob.material_slots[0].material):
                    materials_removed.append(
                        "%s" % act_ob.active_material.name if act_ob.active_material else "Empty")
                    bpy.ops.object.mode_set(mode='OBJECT')
                    bpy.ops.object.material_slot_remove()
                else:
                    pass
    
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.select_all(action='DESELECT')
            bpy.ops.object.mode_set(mode='OBJECT')
    
            if materials_removed:
                print("\n* Removed %s Unassigned Materials \n" % len(materials_removed))
    
                count_mr = 0
    
                for mr in materials_removed:
                    count_mr += 1
                    print("%0.2d. %s" % (count_mr, materials_removed[count_mr - 1]))
    
                print("\n")
                self.report({'INFO'}, "Removed %s Unassigned Materials" %
                    len(materials_removed))
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            if not is_visible:
                scene.layers[n] = False
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            return{'FINISHED'}
    
    def ui_material_remove_unassigned(self, context):
    
        self.layout.operator(
            AMTH_OBJECT_OT_material_remove_unassigned.bl_idname,
            icon="X")
    
    # // FEATURE: Delete Materials not assigned to any verts
    # FEATURE: Cycles Samples Percentage
    class AMTH_RENDER_OT_cycles_samples_percentage_set(Operator):
        '''Save the current number of samples per shader as final (gets saved in .blend)'''
        bl_idname = "scene.amaranth_cycles_samples_percentage_set"
        bl_label = "Set as Render Samples"
    
        def execute(self, context):
            cycles = context.scene.cycles
            cycles.use_samples_final = True
    
            context.scene['amth_cycles_samples_final'] = [
                cycles.diffuse_samples,
                cycles.glossy_samples,
                cycles.transmission_samples,
                cycles.ao_samples,
                cycles.mesh_light_samples,
                cycles.subsurface_samples,
                cycles.volume_samples]
    
            self.report({'INFO'}, "Render Samples Saved")
    
            return{'FINISHED'}
    
    
    class AMTH_RENDER_OT_cycles_samples_percentage(Operator):
        '''Set a percentage of the final render samples'''
        bl_idname = "scene.amaranth_cycles_samples_percentage"
        bl_label = "Set Render Samples Percentage"
    
        percent = IntProperty(
                    name="Percentage",
                    description="Percentage to divide render samples by",
                    subtype='PERCENTAGE',
                    default=0)
    
        def execute(self, context):
            percent = self.percent
            cycles = context.scene.cycles
            cycles_samples_final = context.scene['amth_cycles_samples_final']
    
            cycles.use_samples_final = False
    
            if percent == 100:
                cycles.use_samples_final = True
    
            cycles.diffuse_samples = int((cycles_samples_final[0] / 100) * percent)
            cycles.glossy_samples = int((cycles_samples_final[1] / 100) * percent)
            cycles.transmission_samples = int((cycles_samples_final[2] / 100) * percent)
            cycles.ao_samples = int((cycles_samples_final[3] / 100) * percent)
            cycles.mesh_light_samples = int((cycles_samples_final[4] / 100) * percent)
            cycles.subsurface_samples = int((cycles_samples_final[5] / 100) * percent)
            cycles.volume_samples = int((cycles_samples_final[6] / 100) * percent)
    
            return{'FINISHED'}
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # //FEATURE: Cycles Samples Percentage
    # FEATURE: Jump forward/backward every N frames
    class AMTH_SCREEN_OT_frame_jump(Operator):
        '''Jump a number of frames forward/backwards'''
        bl_idname = "screen.amaranth_frame_jump"
        bl_label = "Jump Frames"
    
        forward = BoolProperty(default=True)
    
        def execute(self, context):
            scene = context.scene
            preferences = context.user_preferences.addons[__name__].preferences
    
            if self.forward:
                scene.frame_current = scene.frame_current + preferences.frames_jump
            else:
                scene.frame_current = scene.frame_current - preferences.frames_jump
    
            return{'FINISHED'}
    
    def ui_userpreferences_edit(self, context):
        preferences = context.user_preferences.addons[__name__].preferences
    
        col = self.layout.column()
        split = col.split(percentage=0.21)
        split.prop(preferences, "frames_jump",
                   text="Frames to Jump")
    
    # // FEATURE: Jump forward/backward every N frames
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # FEATURE: Set Layers to Render
    class AMTH_SCENE_OT_layers_render_save(Operator):
        '''Save the current scene layers as those that should be enabled for final renders'''
        bl_idname = "scene.amaranth_layers_render_save"
        bl_label = "Save as Layers for Render"
    
        def execute(self, context):
            which = []
            n = -1
    
            for l in context.scene.layers:
                n += 1
                if l:
                    which.append(n)
    
            context.scene['amth_layers_for_render'] = which
            self.report({'INFO'}, "Layers for Render Saved")
    
            return{'FINISHED'}
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    class AMTH_SCENE_OT_layers_render_view(Operator):
        '''Enable the scene layers that should be active for final renders'''
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        bl_idname = "scene.amaranth_layers_render_view"
        bl_label = "View Layers for Render"
    
        def execute(self, context):
            scene = context.scene
            layers_render = scene['amth_layers_for_render']
    
            for window in bpy.context.window_manager.windows:
                screen = window.screen
    
                for area in screen.areas:
                    if area.type == 'VIEW_3D':
    
                        override = {'window': window, 'screen': screen, 'scene': scene, 
                                    'area': area, 'region': area.regions[4],
                                    'blend_data': context.blend_data}
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
                        if layers_render:
                            bpy.ops.view3d.layers(override, nr=layers_render[0]+1, extend=False, toggle=False)
    
                            for n in layers_render:
                                context.scene.layers[n] = True
                        else:
                            bpy.ops.view3d.layers(override, nr=1, extend=False, toggle=False)
                            self.report({'INFO'}, "No layers set for render")
    
                        break
    
            return{'FINISHED'}
    
    class AMTH_SCENE_OT_layers_render_set_individual(Operator):
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        '''Whether this layer should be enabled or not for final renders'''
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        bl_idname = "scene.amaranth_layers_render_set_individual"
        bl_label = "Set This Layer for Render"
    
        toggle = BoolProperty()
        number = IntProperty()
    
        def execute(self, context):
            toggle = self.toggle
            number = self.number
    
            new_layers = []
    
            for la in context.scene['amth_layers_for_render']:
                new_layers.append(la)
    
            if len(context.scene['amth_layers_for_render']) and number in new_layers:
                new_layers.remove(number)
            else:
                new_layers.append(number)
    
            # Remove Duplicates
            new_layers = list(set(new_layers))
            context.scene['amth_layers_for_render'] = new_layers
    
            bpy.ops.scene.amaranth_layers_render_view()
    
            return{'FINISHED'}
    
    class AMTH_SCENE_OT_layers_render_clear(Operator):
        '''Clear layers for render'''
        bl_idname = "scene.amaranth_layers_render_clear"
        bl_label = "Clear Layers for Render"
    
        def execute(self, context):
    
            if context.scene.get('amth_layers_for_render'):
                context.scene['amth_layers_for_render'] = []
    
            return{'FINISHED'}
    
    def ui_layers_for_render(self, context):
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        preferences = context.user_preferences.addons[__name__].preferences
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
        if preferences.use_layers_for_render:
            lfr_available = context.scene.get('amth_layers_for_render')
            if lfr_available:
                lfr = context.scene['amth_layers_for_render']
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            layout = self.layout
            layout.label("Layers for Rendering:")
            split = layout.split()
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            col = split.column(align=True)
            row = col.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            row.operator(
                AMTH_SCENE_OT_layers_render_save.bl_idname,
                text="Replace Layers" if lfr_available else "Save Current Layers for Render",
                icon="FILE_REFRESH" if lfr_available else 'LAYER_USED')
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            if lfr_available:
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                row.operator(
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    AMTH_SCENE_OT_layers_render_clear.bl_idname,
                    icon='X', text="")
                col = col.column(align=True)
                col.enabled = True if lfr_available else False
                col.operator(
                    AMTH_SCENE_OT_layers_render_view.bl_idname,
                    icon="RESTRICT_VIEW_OFF")
    
                split = split.split()
                col = split.column(align=True)
                row = col.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                for n in range(0,5):
                    row.operator(
                        AMTH_SCENE_OT_layers_render_set_individual.bl_idname, text="",
                        icon='LAYER_ACTIVE' if n in lfr else 'BLANK1').number = n
                row = col.row(align=True)
                for n in range(10,15):
                    row.operator(
                        AMTH_SCENE_OT_layers_render_set_individual.bl_idname, text="",
                        icon='LAYER_ACTIVE' if n in lfr else 'BLANK1').number = n
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                split = split.split()
                col = split.column(align=True)
                row = col.row(align=True)
    
                for n in range(5,10):
                    row.operator(
                        AMTH_SCENE_OT_layers_render_set_individual.bl_idname, text="",
                        icon='LAYER_ACTIVE' if n in lfr else 'BLANK1').number = n
                row = col.row(align=True)
                for n in range(15,20):
                    row.operator(
                        AMTH_SCENE_OT_layers_render_set_individual.bl_idname, text="",
                        icon='LAYER_ACTIVE' if n in lfr else 'BLANK1').number = n
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
    def ui_layers_for_render_header(self, context):
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
        preferences = context.user_preferences.addons[__name__].preferences
    
        if preferences.use_layers_for_render:
            if context.scene.get('amth_layers_for_render'):
                self.layout.operator(
                    AMTH_SCENE_OT_layers_render_view.bl_idname,
                    text="", icon="IMGDISPLAY")
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # // FEATURE: Set Layers to Render
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # FEATURE: Lighters Corner
    class AMTH_LightersCorner(bpy.types.Panel):
        """The Lighters Panel"""
        bl_label = "Lighter's Corner"
        bl_idname = "AMTH_SCENE_PT_lighters_corner"
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "scene"
    
        @classmethod
        def poll(cls, context):
            any_lamps = False
            for ob in bpy.data.objects:
    
                if ob.type == 'LAMP' or cycles_is_emission(context, ob):
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    any_lamps = True
                else:
                    pass
            return any_lamps
    
        def draw_header(self, context):
            layout = self.layout
            layout.label(text="", icon="LAMP_SUN")
    
        def draw(self, context):
            layout = self.layout
            scene = context.scene
            objects =  bpy.data.objects
            ob_act = context.active_object
            lamps = bpy.data.lamps
    
            list_meshlights = scene.amaranth_lighterscorner_list_meshlights
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            engine = scene.render.engine
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            if cycles_exists:
                layout.prop(scene, "amaranth_lighterscorner_list_meshlights")
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
            box = layout.box()
            if lamps:
                if objects:
                    row = box.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    split = row.split(percentage=0.45)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    col = split.column()
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    col.label(text="Name")
    
                    if engine in ['CYCLES', 'BLENDER_RENDER']:
                        if engine == 'BLENDER_RENDER':
                            split = split.split(percentage=0.7)
                        else:
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            split = split.split(percentage=0.27)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                        col = split.column()
                        col.label(text="Samples")
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    if cycles_exists and engine == 'CYCLES':
                        split = split.split(percentage=0.2)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                        col = split.column()
                        col.label(text="Size")
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    split = split.split(percentage=1.0)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    col = split.column()
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                    col.label(text="%sRender Visibility" % 
                        'Rays /' if cycles_exists else '')
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
                    for ob in objects:
    
                        is_lamp = ob.type == 'LAMP'
                        is_emission = True if cycles_is_emission(context, ob) and list_meshlights else False
    
                        if ob and is_lamp or is_emission:
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            lamp = ob.data
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            if cycles_exists:
                                clamp = ob.data.cycles
                                visibility = ob.cycles_visibility
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    
                            row = box.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            split = row.split(percentage=1.0)
                            col = split.column()
                            row = col.row(align=True)
                            col.active = ob == ob_act
                            row.label(icon="%s" % ('LAMP_%s' % ob.data.type if is_lamp else 'MESH_GRID'))
                            split = row.split(percentage=.45)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            col = split.column()
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            row = col.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            row.alignment = 'LEFT'
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            row.active = True
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            row.operator(AMTH_SCENE_OT_amaranth_object_select.bl_idname,
                                        text='%s %s%s' % (
                                            " [L] " if ob.library else "",
                                            ob.name,
                                            "" if ob.name in context.scene.objects else " [Not in Scene]"),
                                        emboss=False).object = ob.name
                            if ob.library:
                                row = col.row(align=True)
                                row.alignment = "LEFT"
                                row.operator(AMTH_SCENE_OT_blender_instance_open.bl_idname,
                                             text=ob.library.filepath,
                                             icon="LINK_BLEND",
                                             emboss=False).filepath=ob.library.filepath
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            if cycles_exists and engine == 'CYCLES':
                                split = split.split(percentage=0.25)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                                col = split.column()
    
                                if is_lamp:
                                    if scene.cycles.progressive == 'BRANCHED_PATH':
                                        col.prop(clamp, "samples", text="")
                                    if scene.cycles.progressive == 'PATH':
                                       col.label(text="N/A")
                                else:
                                  col.label(text="N/A")
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            if engine == 'BLENDER_RENDER':
                                split = split.split(percentage=0.7)
                                col = split.column()
    
                                if is_lamp:
                                    if lamp.type == 'HEMI':
                                        col.label(text="Not Available")
                                    elif lamp.type == 'AREA' and lamp.shadow_method == 'RAY_SHADOW':
                                        row = col.row(align=True)
                                        row.prop(lamp, "shadow_ray_samples_x", text="X")
                                        if lamp.shape == 'RECTANGLE':
                                            row.prop(lamp, "shadow_ray_samples_y", text="Y")
                                    elif lamp.shadow_method == 'RAY_SHADOW':
                                        col.prop(lamp, "shadow_ray_samples", text="Ray Samples")
                                    elif lamp.shadow_method == 'BUFFER_SHADOW':
                                        col.prop(lamp, "shadow_buffer_samples", text="Buffer Samples")
                                    else:
                                        col.label(text="No Shadow")
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                                else:
    
                                  col.label(text="N/A")
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            if cycles_exists and engine == 'CYCLES':
                                split = split.split(percentage=0.2)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                                col = split.column()
    
                                if is_lamp:
                                    if lamp.type in ['POINT','SUN', 'SPOT']:
                                        col.label(text="%.2f" % lamp.shadow_soft_size)
                                    elif lamp.type == 'HEMI':
                                        col.label(text="N/A")
                                    elif lamp.type == 'AREA' and lamp.shape == 'RECTANGLE':
                                        col.label(text="%.2fx%.2f" % (lamp.size, lamp.size_y))
                                    else:
                                        col.label(text="%.2f" % lamp.size)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                                else:
    
                                  col.label(text="N/A")
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            split = split.split(percentage=1.0)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            col = split.column()
                            row = col.row(align=True)
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            if cycles_exists:
                                row.prop(visibility, "camera", text="")
                                row.prop(visibility, "diffuse", text="")
                                row.prop(visibility, "glossy", text="")
                                row.prop(visibility, "shadow", text="")
                                row.separator()
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
                            row.prop(ob, "hide", text="", emboss=False)
                            row.prop(ob, "hide_render", text="", emboss=False)
            else:
                box.label(text="No Lamps", icon="LAMP_DATA")
    
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    # FEATURE: Jump to frame in-between next and previous keyframe
    class AMTH_SCREEN_OT_keyframe_jump_inbetween(Operator):
        '''Jump to half in-between keyframes'''
        bl_idname = "screen.amth_keyframe_jump_inbetween"
        bl_label = "Jump to Keyframe In-between"
    
        backwards = BoolProperty()
    
        def execute(self, context):
            back = self.backwards
    
            scene = context.scene
            ob = bpy.context.object
            frame_start = scene.frame_start
            frame_end = scene.frame_end
    
            if not context.scene.get('amth_keyframes_jump'):
                context.scene['amth_keyframes_jump'] = []
    
            keyframes_list = context.scene['amth_keyframes_jump']
    
            for f in range(frame_start, frame_end):
                if ob.is_keyframe(f):
                     keyframes_list = list(keyframes_list)
                     keyframes_list.append(f)
    
            if keyframes_list:
                i = 0
                keyframes_list_half = []
    
                for item in keyframes_list:
                    try:
                        keyframes_list_half.append(int((keyframes_list[i] + keyframes_list[i+1]) / 2))
                        i += 1
                    except:
                        pass
    
                if len(keyframes_list_half) > 1:
                    if back:
                        if scene.frame_current == keyframes_list_half[::-1][-1] or \
                            scene.frame_current < keyframes_list_half[::-1][-1]:
                            self.report({'INFO'}, "No keyframes behind")
                        else:
                            for i in keyframes_list_half[::-1]:
                                if scene.frame_current > i:
                                    scene.frame_current = i
                                    break
                    else:
                        if scene.frame_current == keyframes_list_half[-1] or \
                            scene.frame_current > keyframes_list_half[-1]:
                            self.report({'INFO'}, "No keyframes ahead")
                        else:
                            for i in keyframes_list_half:
                                if scene.frame_current < i:
                                    scene.frame_current = i
                                    break
                else:
                    self.report({'INFO'}, "Object has only 1 keyframe")
            else:
                self.report({'INFO'}, "Object has no keyframes")
    
            return{'FINISHED'}
    # // FEATURE: Jump to frame in-between next and previous keyframe
    # FEATURE: Toggle Wire Display
    class AMTH_OBJECT_OT_wire_toggle(Operator):
        '''Turn on/off wire display on mesh objects'''
        bl_idname = "object.amth_wire_toggle"
        bl_label = "Display Wireframe"
        bl_options = {'REGISTER', 'UNDO'}
    
        clear = BoolProperty(
            default=False, name="Clear Wireframe",
            description="Clear Wireframe Display")
    
        def execute(self, context):
    
            scene = context.scene
            is_all_scenes = scene.amth_wire_toggle_scene_all
            is_selected = scene.amth_wire_toggle_is_selected
            is_all_edges = scene.amth_wire_toggle_edges_all
            is_optimal = scene.amth_wire_toggle_optimal
            clear = self.clear
    
            if is_all_scenes:
                which = bpy.data.objects
            elif is_selected:
                if not context.selected_objects:
                    self.report({'INFO'}, "No selected objects")
                which = context.selected_objects
            else:
                which = scene.objects
    
            if which:
                for ob in which:
                    if ob and ob.type in {
                        'MESH', 'EMPTY', 'CURVE',
                        'META','SURFACE','FONT'}:
    
                        ob.show_wire = False if clear else True
                        ob.show_all_edges = is_all_edges
    
                        for mo in ob.modifiers:
                            if mo and mo.type == 'SUBSURF':
                                mo.show_only_control_edges = is_optimal
    
            return{'FINISHED'}
    
    def ui_object_wire_toggle(self, context):
    
        scene = context.scene
    
        self.layout.separator()
        col = self.layout.column(align=True)
        row = col.row(align=True)
        row.operator(AMTH_OBJECT_OT_wire_toggle.bl_idname,
            icon='MOD_WIREFRAME').clear = False
        row.operator(AMTH_OBJECT_OT_wire_toggle.bl_idname,
            icon='X', text="").clear = True
        col.separator()
        row = col.row(align=True)
        row.prop(scene, "amth_wire_toggle_edges_all")
        row.prop(scene, "amth_wire_toggle_optimal")
        row = col.row(align=True)
        sub = row.row(align=True)
        sub.active = not scene.amth_wire_toggle_scene_all
        sub.prop(scene, "amth_wire_toggle_is_selected")
        sub = row.row(align=True)
        sub.active = not scene.amth_wire_toggle_is_selected
        sub.prop(scene, "amth_wire_toggle_scene_all")
    
    # //FEATURE: Toggle Wire Display
    # FEATURE: Add Meshlight
    class AMTH_OBJECT_OT_meshlight_add(bpy.types.Operator):
        """Add a light emitting mesh"""
        bl_idname = "object.meshlight_add"
        bl_label = "Add Meshlight"
        bl_options = {'REGISTER', 'UNDO'}
    
        single_sided = BoolProperty(
                name="Single Sided",
                default=True,
                description="Only emit light on one side",
                )
    
        visible = BoolProperty(
                name="Visible on Camera",
                default=False,
                description="Show the meshlight on Cycles preview",
                )
    
        size = FloatProperty(
                name="Size",
                description="Meshlight size",
                min=0.01, max=100.0,
                default=1.0,
                )
    
        strength = FloatProperty(
                name="Strength",
                min=0.01, max=100000.0,
                default=1.5,
                step=0.25,
                )
    
        temperature = FloatProperty(
                name="Temperature",
                min=800, max=12000.0,
                default=5500.0,
                step=800.0,
                )
    
        rotation = FloatVectorProperty(
                name="Rotation",
                subtype='EULER',
                )
    
        def execute(self, context):
            scene = context.scene
            exists = False
            number = 1
    
            for obs in bpy.data.objects:
                if obs.name.startswith("light_meshlight"):
                    number +=1
    
            meshlight_name = 'light_meshlight_%.2d' % number
    
            bpy.ops.mesh.primitive_grid_add(
                x_subdivisions=4, y_subdivisions=4,
                rotation=self.rotation, radius=self.size)
    
            bpy.context.object.name = meshlight_name
            meshlight = scene.objects[meshlight_name]
            meshlight.show_wire = True
            meshlight.show_all_edges = True
    
            material = bpy.data.materials.get(meshlight_name)
    
            if not material:
                material = bpy.data.materials.new(meshlight_name)
    
            bpy.ops.object.material_slot_add()
            meshlight.active_material = material
    
            material.use_nodes = True
            material.diffuse_color = (1, 0.5, 0)
            nodes = material.node_tree.nodes
            links = material.node_tree.links
    
            # clear default nodes to start nice fresh
            for no in nodes:
                nodes.remove(no)
    
            if self.single_sided:
                geometry = nodes.new(type="ShaderNodeNewGeometry")
    
                transparency = nodes.new(type="ShaderNodeBsdfTransparent")
                transparency.inputs[0].default_value = (1,1,1,1)
                transparency.location = geometry.location
                transparency.location += Vector((0.0, -55.0))
    
                emission = nodes.new(type="ShaderNodeEmission")
                emission.inputs['Strength'].default_value = self.strength
                emission.location = transparency.location
                emission.location += Vector((0.0, -80.0))
                emission.inputs[0].show_expanded = True # so it shows slider on properties editor
    
                blackbody = nodes.new(type="ShaderNodeBlackbody")
                blackbody.inputs['Temperature'].default_value = self.temperature
                blackbody.location = emission.location
                blackbody.location += Vector((-180.0, 0.0))
    
                mix = nodes.new(type="ShaderNodeMixShader")
                mix.location = geometry.location
                mix.location += Vector((180.0, 0.0))
                mix.inputs[2].show_expanded = True
    
                output = nodes.new(type="ShaderNodeOutputMaterial")
                output.inputs[1].hide = True
                output.inputs[2].hide = True
                output.location = mix.location
                output.location += Vector((180.0, 0.0))
    
                # Make links
                links.new(geometry.outputs['Backfacing'], mix.inputs['Fac'])
                links.new(transparency.outputs['BSDF'], mix.inputs[1])
                links.new(emission.outputs['Emission'], mix.inputs[2])
                links.new(blackbody.outputs['Color'], emission.inputs['Color'])
                links.new(mix.outputs['Shader'], output.inputs['Surface'])
    
                for sockets in geometry.outputs:
                    sockets.hide = True
            else:
                emission = nodes.new(type="ShaderNodeEmission")
                emission.inputs['Strength'].default_value = self.strength
                emission.inputs[0].show_expanded = True
    
                blackbody = nodes.new(type="ShaderNodeBlackbody")
                blackbody.inputs['Temperature'].default_value = self.temperature
                blackbody.location = emission.location
                blackbody.location += Vector((-180.0, 0.0))
    
                output = nodes.new(type="ShaderNodeOutputMaterial")
                output.inputs[1].hide = True
                output.inputs[2].hide = True
                output.location = emission.location
                output.location += Vector((180.0, 0.0))
    
                links.new(blackbody.outputs['Color'], emission.inputs['Color'])
                links.new(emission.outputs['Emission'], output.inputs['Surface'])
    
            material.cycles.sample_as_light = True
            meshlight.cycles_visibility.shadow = False
            meshlight.cycles_visibility.camera = self.visible
    
            return {'FINISHED'}
    
    def ui_menu_lamps_add(self, context):
        if cycles_exists and context.scene.render.engine == 'CYCLES':
            self.layout.separator()
            self.layout.operator(
                AMTH_OBJECT_OT_meshlight_add.bl_idname,
                icon="LAMP_AREA", text="Meshlight")
    
    # //FEATURE: Add Meshlight: Single Sided
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
    classes = (AMTH_SCENE_MT_color_management_presets,
               AMTH_AddPresetColorManagement,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_LightersCorner,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_PT_scene_debug,
               AMTH_SCENE_OT_refresh,
               AMTH_SCENE_OT_cycles_shader_list_nodes,
               AMTH_SCENE_OT_cycles_shader_list_nodes_clear,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_OT_amaranth_object_select,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_OT_list_missing_node_links,
               AMTH_SCENE_OT_list_missing_material_slots,
               AMTH_SCENE_OT_list_missing_material_slots_clear,
               AMTH_SCENE_OT_blender_instance_open,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_OT_layers_render_save,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_OT_layers_render_view,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_SCENE_OT_layers_render_set_individual,
               AMTH_SCENE_OT_layers_render_clear,
    
    Pablo Vazquez's avatar
    Pablo Vazquez committed
               AMTH_WM_OT_save_reload,
               AMTH_MESH_OT_find_asymmetric,