From 197b739ef6b13e06594e9dd7801a5dd1c1d62c53 Mon Sep 17 00:00:00 2001 From: SimonNordon4 Date: Fri, 13 Sep 2024 17:18:45 +1000 Subject: [PATCH] improved extension creation. --- ui.py => extension_setup_ui.py | 46 ++++++++++-------- lightmapper/lightmapper_operators.py | 24 +++++++-- lightmapper/lightmapper_panel.py | 5 +- lightmapper/lightmapper_properties.py | 7 ++- .../{tests => ~tests}/lightmap_test.blend | Bin 5 files changed, 56 insertions(+), 26 deletions(-) rename ui.py => extension_setup_ui.py (77%) rename lightmapper/{tests => ~tests}/lightmap_test.blend (100%) diff --git a/ui.py b/extension_setup_ui.py similarity index 77% rename from ui.py rename to extension_setup_ui.py index 21c58bf..eef8ebb 100644 --- a/ui.py +++ b/extension_setup_ui.py @@ -64,24 +64,32 @@ def create_addon_from_template(): messagebox.showinfo("Success", f"Addon '{addon_name}' created from template.") def zip_addon(): - base_dir = os.getcwd() # Directory where your add-ons are located - ignored_dirs = {"template", ".git", "images"} - - for item in os.listdir(base_dir): - item_path = os.path.join(base_dir, item) - if os.path.isdir(item_path) and item not in ignored_dirs: - zip_name = os.path.join(base_dir, f"{item}.zip") - if os.path.exists(zip_name): - os.remove(zip_name) # Remove the existing zip file if it exists - with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf: - for root, dirs, files in os.walk(item_path): - dirs[:] = [d for d in dirs if d not in ignored_dirs] # Filter out ignored directories - for file in files: - file_path = os.path.join(root, file) - arcname = os.path.relpath(file_path, base_dir) - zipf.write(file_path, arcname) + # Get the directory where the script is located + script_dir = os.path.dirname(os.path.abspath(__file__)) + # Let the user select a directory to zip, starting from the script's directory + directory_to_zip = filedialog.askdirectory(title="Select Directory to Zip", initialdir=script_dir) + if not directory_to_zip: + return # User cancelled + + base_dir = directory_to_zip # The directory to zip + zip_name = os.path.join(os.path.dirname(base_dir), f"{os.path.basename(base_dir)}.zip") - messagebox.showinfo("Success", "All addons zipped successfully.") + if os.path.exists(zip_name): + os.remove(zip_name) # Remove the existing zip file if it exists + + with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf: + for root, dirs, files in os.walk(base_dir): + # Exclude directories starting with '~' or named '__pycache__' + dirs[:] = [d for d in dirs if not (d.startswith('~') or d == '__pycache__')] + for file in files: + file_path = os.path.join(root, file) + # Set arcname relative to the directory's contents, not the directory itself + arcname = os.path.relpath(file_path, base_dir) + zipf.write(file_path, arcname) + + messagebox.showinfo("Success", f"Contents of '{os.path.basename(base_dir)}' zipped successfully.") + + def build_blender_extensions(): @@ -141,8 +149,8 @@ def apply_dark_mode(widget): frame_build_extensions.grid_columnconfigure(1, weight=1) frame_build_extensions.grid_columnconfigure(2, weight=1) -# Add the "Zip Addon" button to the second frame -zip_button = tk.Button(frame_build_extensions, text="Zip Addons", command=zip_addon) +# Update the button label in the GUI setup +zip_button = tk.Button(frame_build_extensions, text="Zip Directory", command=zip_addon) zip_button.grid(row=0, column=0, columnspan=3, padx=10, pady=5, sticky="ew") # Add the "Build Blender Extensions" button to the second frame diff --git a/lightmapper/lightmapper_operators.py b/lightmapper/lightmapper_operators.py index 6365dc9..8dbea22 100644 --- a/lightmapper/lightmapper_operators.py +++ b/lightmapper/lightmapper_operators.py @@ -244,10 +244,10 @@ def _create_bake_image(self, context): # new_image.color_space = 'sRGB' # Don't need to set for now. return new_image - def _create_bakeable_object(self, mesh_objects): - """ Create a combined mesh from the selected objects, including UVs and materials. """ + """ Create a combined mesh from the selected objects, including UVs, materials, and normals. """ + # Create a new mesh new_mesh = bpy.data.meshes.new(name="BakeableMesh") @@ -262,7 +262,7 @@ def _create_bakeable_object(self, mesh_objects): # Dictionary to map temporary vertices to the combined bmesh vertices vertex_map = {} - + # Create a dictionary to hold the UV layer mappings for each UV map uv_map_layers = {} @@ -326,6 +326,11 @@ def _create_bakeable_object(self, mesh_objects): mat = obj.material_slots[mat_index].material bm_face.material_index = material_map[mat] + # Copy normals + for vert in temp_bm.verts: + if vert in vertex_map: + vertex_map[vert].normal = vert.normal + # Free the temporary bmesh temp_bm.free() @@ -336,6 +341,7 @@ def _create_bakeable_object(self, mesh_objects): # Ensure the new object has all materials correctly assigned new_object.data.update() return new_object + def _get_empty_material(self): """ Creates a bake compatible material for the bake object. """ @@ -458,6 +464,12 @@ def save_state(self, context): def restore_state(self, context): self.scene_state.restore(context) + # get debug_mode property + debug_mode = context.scene.lightmapper_properties.debug_mode + # Skip the deletion step if we're in debug mode. + if debug_mode: + return + # remove the bake object if self.bake_object is not None: if self.bake_object.data is not None: @@ -476,10 +488,12 @@ def execute(self, context): context.window_manager.modal_handler_add(self) bake_name_target = bpy.context.scene.lightmapper_properties.bake_name - if bake_name_target is 'ACTIVE_OBJECT': + if bake_name_target == 'ACTIVE_OBJECT': self.bake_name = context.active_object.name - else: + elif bake_name_target == 'COLLECTION': self.bake_name = context.view_layer.active_layer_collection.collection.name + else: + self.bake_name = "error: bad_name" return {'RUNNING_MODAL'} diff --git a/lightmapper/lightmapper_panel.py b/lightmapper/lightmapper_panel.py index eaad4a3..b13636b 100644 --- a/lightmapper/lightmapper_panel.py +++ b/lightmapper/lightmapper_panel.py @@ -13,7 +13,8 @@ class LIGHTMAPPER_PT_main_panel(bpy.types.Panel): def draw_header(self, context): layout = self.layout - layout.label(text="", icon="OUTLINER_DATA_LIGHTPROBE") + props = context.scene.lightmapper_properties + layout.prop(props, "debug_mode", text="", icon='OUTLINER_DATA_LIGHTPROBE') def draw(self, context): layout = self.layout @@ -41,6 +42,8 @@ def draw(self, context): box.label(text="Bake Name", icon='TEXTURE') export_row = box.row(align=True) export_row.prop(props, "bake_name", expand=True) + + # Bake Button layout.separator() diff --git a/lightmapper/lightmapper_properties.py b/lightmapper/lightmapper_properties.py index bbb5845..7b95925 100644 --- a/lightmapper/lightmapper_properties.py +++ b/lightmapper/lightmapper_properties.py @@ -1,5 +1,5 @@ import bpy -from bpy.props import EnumProperty, StringProperty # type: ignore +from bpy.props import EnumProperty, StringProperty, BoolProperty # type: ignore class LIGHTMAPPER_PT_properties(bpy.types.PropertyGroup): lightmap_width: bpy.props.IntProperty( @@ -44,6 +44,11 @@ class LIGHTMAPPER_PT_properties(bpy.types.PropertyGroup): max=256 ) # type: ignore + debug_mode: BoolProperty( + name="Debug Mode", + description="Will not remove temporary bake objects after baking.", + default=False + ) # type: ignore def register(): diff --git a/lightmapper/tests/lightmap_test.blend b/lightmapper/~tests/lightmap_test.blend similarity index 100% rename from lightmapper/tests/lightmap_test.blend rename to lightmapper/~tests/lightmap_test.blend