Fixed the UI to be much better

- ui for materials is now a list with no duplicates
- auto detects that materials have changed and prompts the user to reload
- due to context limitations in code, user is needed to reload the materials, but the ui is made so the user is forced to reload the materials to see them
- later on, we should prevent user from atlasing if the material list is not up to date.
This commit is contained in:
989onan
2024-07-14 15:36:01 -04:00
parent 23b4656859
commit e875f9192a
2 changed files with 103 additions and 45 deletions
+46 -5
View File
@@ -1,12 +1,50 @@
import bpy
from bpy.types import Scene, PropertyGroup, Object, Material, TextureNode, Context
from bpy.types import Scene, PropertyGroup, Object, Material, TextureNode, Context, SceneObjects
from bpy.props import BoolProperty, EnumProperty, FloatProperty, IntProperty, CollectionProperty, StringProperty, FloatVectorProperty, PointerProperty
from bpy.utils import register_class
class material_list_bool:
old_list: list[Material] = []
bool_material_list_expand: bool = False
def set_bool(self, value: bool) -> None:
material_list_bool.bool_material_list_expand = value
if value == False:
material_list_bool.old_list = []
def get_bool(self) -> bool:
newlist: list[Material] = []
for obj in bpy.context.scene.objects:
if len(obj.material_slots)>0:
for mat_slot in obj.material_slots:
if mat_slot.material:
if mat_slot.material not in newlist:
newlist.append(mat_slot.material)
still_the_same: bool = True
for item in newlist:
if item not in material_list_bool.old_list:
still_the_same = False
break
for item in material_list_bool.old_list:
if item not in newlist:
still_the_same = False
break
material_list_bool.bool_material_list_expand = still_the_same
return material_list_bool.bool_material_list_expand
class SceneMatClass(PropertyGroup):
mat: PointerProperty(type=Material)
def register_properties():
register_class(SceneMatClass)
#happy with how compressed this get_texture_node_list method is - @989onan
def get_texture_node_list(self: Material, context: Context) -> list[set[3]]:
if self.use_nodes:
@@ -25,11 +63,14 @@ def register_properties():
Material.texture_atlas_ambient_occlusion = EnumProperty(name="Ambient Occlusion", description="The texture that will be used for the ambient occlusion map atlas", default=0, items=get_texture_node_list)
Material.texture_atlas_height = EnumProperty(name="Height", description="The texture that will be used for the height map atlas", default=0, items=get_texture_node_list)
Scene.texture_atlas_material_index = IntProperty()#default=-1, get=(lambda self : -1), set=(lambda self,context : None)
Scene.texture_atlas_material_index = IntProperty(default=-1, get=(lambda self : -1), set=(lambda self,context : None))
#class Texture_Atlas_PropertyGroup(PropertyGroup):
# materials: CollectionProperty(type=Material)
#register_class(Texture_Atlas_PropertyGroup)
Scene.materials = CollectionProperty(type=SceneMatClass)
Scene.texture_atlas_Has_Mat_List_Shown = BoolProperty(default=False, get=material_list_bool.get_bool, set=material_list_bool.set_bool)
#Scene.texture_atlas_properties = PointerProperty(type=Texture_Atlas_PropertyGroup)
+55 -38
View File
@@ -1,7 +1,38 @@
from bpy.types import UIList, Panel, UILayout, Object,Context,MaterialSlot
from bpy.types import UIList, Panel, UILayout, Object, Context,Material, Operator
import bpy
from ..core.register import register_wrap
from .panel import AvatarToolkitPanel
from ..core.properties import SceneMatClass, material_list_bool
@register_wrap
class ExpandSection_Materials(Operator):
bl_idname = 'avatar_toolkit.expand_section_materials'
bl_label = ""
bl_description = ""
@classmethod
def poll(cls, context: Context) -> bool:
return True
def execute(self, context: Context) -> set:
if not context.scene.texture_atlas_Has_Mat_List_Shown:
context.scene.materials.clear()
newlist: list[Material] = []
for obj in bpy.context.scene.objects:
if len(obj.material_slots)>0:
for mat_slot in obj.material_slots:
if mat_slot.material:
if mat_slot.material not in newlist:
newlist.append(mat_slot.material)
newitem: SceneMatClass = context.scene.materials.add()
newitem.mat = mat_slot.material
material_list_bool.old_list = newlist
else:
context.scene.texture_atlas_Has_Mat_List_Shown = False
return {'FINISHED'}
@register_wrap
class MaterialTextureAtlasProperties(UIList):
@@ -11,45 +42,24 @@ class MaterialTextureAtlasProperties(UIList):
bl_region_type = 'UI'
def draw_item(self, context: Context, layout: UILayout, data: bpy.types.Object, item:MaterialSlot, icon, active_data, active_propname, index):
def draw_item(self , context: Context, layout: UILayout, data: bpy.types.Object, item:SceneMatClass, icon, active_data, active_propname, index):
if item.material:
box = layout.box()
col = box.row()
col.label(text="Material: \""+item.material.name+"\"")
if data.active_material_index == index:
col = box.row()
col.prop(item.material, "texture_atlas_albedo")
col = box.row()
col.prop(item.material, "texture_atlas_normal")
col = box.row()
col.prop(item.material, "texture_atlas_emission")
col = box.row()
col.prop(item.material, "texture_atlas_ambient_occlusion")
col = box.row()
col.prop(item.material, "texture_atlas_height")
else:
box = layout.box()
col = box.row()
col.label(text="Empty Material Slot.")
@register_wrap
class MaterialListPanel(UIList):
bl_label = "Texture Atlas Material List"
bl_idname = "Material_UL_avatar_toolkit_texture_atlas_mat_list"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
def draw_item(self, context: Context, layout: UILayout, data, item:Object, icon, active_data, active_propname, index):
custom_icon = "OBJECT_DATAMODE"
if context.scene.texture_atlas_Has_Mat_List_Shown:
box = layout.box()
row = box.row()
row.label(text=item.name, icon = custom_icon)
if context.scene.texture_atlas_material_index == index:
row = box.row()
box = row.box()
row.label(text=item.mat.name, icon = "MATERIAL")
col = box.row()
col.prop(item.mat, "texture_atlas_albedo")
col = box.row()
col.prop(item.mat, "texture_atlas_normal")
col = box.row()
col.prop(item.mat, "texture_atlas_emission")
col = box.row()
col.prop(item.mat, "texture_atlas_ambient_occlusion")
col = box.row()
col.prop(item.mat, "texture_atlas_height")
box.template_list("Material_UL_avatar_toolkit_texture_atlas_mat_list_mat", "The_Texture_Atlas_List_mat_"+item.name, item, "material_slots", item, "active_material_index")
@register_wrap
@@ -65,7 +75,14 @@ class TextureAtlasPanel(Panel):
layout = self.layout
row = layout.row()
boxoutter = row.box()
direction_icon = 'RIGHTARROW' if not context.scene.texture_atlas_Has_Mat_List_Shown else 'DOWNARROW_HLT'
row = boxoutter.row()
row.label(text=MaterialListPanel.bl_label)
row.operator(ExpandSection_Materials.bl_idname, text=("Reload Texture Atlas Material List" if not context.scene.texture_atlas_Has_Mat_List_Shown else "Loaded Texture Atlas Material List"), icon=direction_icon)
if context.scene.texture_atlas_Has_Mat_List_Shown:
#get_texture_node_list(bpy.context)
row = boxoutter.row()
row.template_list("Material_UL_avatar_toolkit_texture_atlas_mat_list", "The_Texture_Atlas_List", context.scene, "objects", context.scene, "texture_atlas_material_index")
row.template_list(MaterialTextureAtlasProperties.bl_idname, 'material_list', context.scene, 'materials',
context.scene, 'texture_atlas_material_index', rows=12, type='DEFAULT')