diff --git a/__init__.py b/__init__.py index d3e5c548c..bd8835a96 100644 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ from . import addon_updater_ops -from .fast64_internal.utility import prop_split, multilineLabel, draw_and_check_tab +from .fast64_internal.utility import prop_split from .fast64_internal.repo_settings import ( draw_repo_settings, @@ -26,26 +26,9 @@ from .fast64_internal.mk64 import MK64_Properties, mk64_register, mk64_unregister -from .fast64_internal.f3d.f3d_material import ( - F3D_MAT_CUR_VERSION, - mat_register, - mat_unregister, - check_or_ask_color_management, -) -from .fast64_internal.f3d.f3d_render_engine import render_engine_register, render_engine_unregister -from .fast64_internal.f3d.f3d_writer import f3d_writer_register, f3d_writer_unregister -from .fast64_internal.f3d.f3d_parser import f3d_parser_register, f3d_parser_unregister -from .fast64_internal.f3d.flipbook import flipbook_register, flipbook_unregister -from .fast64_internal.f3d.op_largetexture import op_largetexture_register, op_largetexture_unregister, ui_oplargetexture - -from .fast64_internal.f3d_material_converter import ( - MatUpdateConvert, - upgrade_f3d_version_all_meshes, - bsdf_conv_register, - bsdf_conv_unregister, - bsdf_conv_panel_regsiter, - bsdf_conv_panel_unregsiter, -) +from .fast64_internal.f3d import f3d_register, f3d_unregister +from .fast64_internal.f3d.f3d_material import F3D_MAT_CUR_VERSION, check_or_ask_color_management +from .fast64_internal.f3d_material_converter import upgrade_f3d_version_all_meshes from .fast64_internal.render_settings import ( Fast64RenderSettings_Properties, @@ -73,36 +56,6 @@ ) -class F3D_GlobalSettingsPanel(bpy.types.Panel): - bl_idname = "F3D_PT_global_settings" - bl_label = "F3D Global Settings" - bl_space_type = "VIEW_3D" - bl_region_type = "UI" - bl_category = "Fast64" - - @classmethod - def poll(cls, context): - return True - - # called every frame - def draw(self, context): - col = self.layout.column() - col.scale_y = 1.1 # extra padding - prop_split(col, context.scene, "f3d_type", "F3D Microcode") - col.prop(context.scene, "saveTextures") - col.prop(context.scene, "f3d_simple", text="Simple Material UI") - col.prop(context.scene, "exportInlineF3D", text="Bleed and Inline Material Exports") - if context.scene.exportInlineF3D: - multilineLabel( - col.box(), - "While inlining, all meshes will be restored to world default values.\n You can configure these values in the world properties tab.", - icon="INFO", - ) - col.prop(context.scene, "ignoreTextureRestrictions") - if context.scene.ignoreTextureRestrictions: - col.box().label(text="Width/height must be < 1024. Must be png format.") - - class Fast64_GlobalSettingsPanel(bpy.types.Panel): bl_idname = "FAST64_PT_global_settings" bl_label = "Fast64 Global Settings" @@ -135,26 +88,6 @@ def draw(self, context): col.prop(fast64_settings, "prefer_rgba_over_ci") -class Fast64_GlobalToolsPanel(bpy.types.Panel): - bl_idname = "FAST64_PT_global_tools" - bl_label = "Fast64 Tools" - bl_space_type = "VIEW_3D" - bl_region_type = "UI" - bl_category = "Fast64" - - @classmethod - def poll(cls, context): - return True - - # called every frame - def draw(self, context): - col = self.layout.column() - col.operator(ArmatureApplyWithMeshOperator.bl_idname) - # col.operator(CreateMetarig.bl_idname) - ui_oplargetexture(col, context) - addon_updater_ops.update_notice_box_ui(self, context) - - def repo_path_update(self, context): load_repo_settings(context.scene, abspath(self.repo_settings_path), True) @@ -316,9 +249,7 @@ def draw(self, context): Fast64_Properties, Fast64_BoneProperties, Fast64_ObjectProperties, - F3D_GlobalSettingsPanel, Fast64_GlobalSettingsPanel, - Fast64_GlobalToolsPanel, UpgradeF3DMaterialsDialog, ) @@ -418,9 +349,7 @@ def register(): addon_updater_ops.register(bl_info) utility_anim_register() - mat_register() - render_engine_register() - bsdf_conv_register() + f3d_register(True) sm64_register(True) oot_register(True) mk64_register(True) @@ -430,12 +359,6 @@ def register(): for cls in classes: register_class(cls) - bsdf_conv_panel_regsiter() - f3d_writer_register() - flipbook_register() - f3d_parser_register() - op_largetexture_register() - # ROM bpy.types.Scene.ignoreTextureRestrictions = bpy.props.BoolProperty(name="Ignore Texture Restrictions") @@ -464,17 +387,10 @@ def register(): # called on add-on disabling def unregister(): utility_anim_unregister() - op_largetexture_unregister() - flipbook_unregister() - f3d_writer_unregister() - f3d_parser_unregister() + f3d_unregister(True) sm64_unregister(True) oot_unregister(True) mk64_unregister(True) - mat_unregister() - bsdf_conv_unregister() - bsdf_conv_panel_unregsiter() - render_engine_unregister() del bpy.types.Scene.fullTraceback del bpy.types.Scene.ignoreTextureRestrictions diff --git a/fast64_internal/__init__.py b/fast64_internal/__init__.py index 6bb605c2a..ade64e5ee 100644 --- a/fast64_internal/__init__.py +++ b/fast64_internal/__init__.py @@ -1,5 +1,4 @@ from .f3d_material_converter import * -from .f3d import * from .sm64 import * from .oot import * # is this really needed? from .panels import * diff --git a/fast64_internal/f3d/__init__.py b/fast64_internal/f3d/__init__.py index 9975de5d3..b8e3f4da4 100644 --- a/fast64_internal/f3d/__init__.py +++ b/fast64_internal/f3d/__init__.py @@ -1,4 +1,131 @@ -from .f3d_parser import * -from .f3d_material import * -from .f3d_render_engine import * -from .f3d_gbi import * +import bpy +from bpy.utils import register_class, unregister_class + +from ... import addon_updater_ops +from ..utility_anim import ArmatureApplyWithMeshOperator +from ..utility import prop_split, multilineLabel + +from .f3d_material import mat_register, mat_unregister +from .f3d_render_engine import render_engine_register, render_engine_unregister +from .f3d_writer import f3d_writer_register, f3d_writer_unregister +from .f3d_parser import f3d_parser_register, f3d_parser_unregister +from .flipbook import flipbook_register, flipbook_unregister +from .op_largetexture import op_largetexture_register, op_largetexture_unregister, ui_oplargetexture +from .bsdf_converter import bsdf_converter_register, bsdf_converter_unregister, bsdf_converter_panel_draw + + +class F3D_GlobalSettingsPanel(bpy.types.Panel): + bl_idname = "F3D_PT_global_settings" + bl_label = "F3D Global Settings" + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_category = "Fast64" + + @classmethod + def poll(cls, context): + return True + + # called every frame + def draw(self, context): + col = self.layout.column() + col.scale_y = 1.1 # extra padding + prop_split(col, context.scene, "f3d_type", "F3D Microcode") + col.prop(context.scene, "saveTextures") + col.prop(context.scene, "f3d_simple", text="Simple Material UI") + col.prop(context.scene, "exportInlineF3D", text="Bleed and Inline Material Exports") + if context.scene.exportInlineF3D: + multilineLabel( + col.box(), + "While inlining, all meshes will be restored to world default values.\n You can configure these values in the world properties tab.", + icon="INFO", + ) + col.prop(context.scene, "ignoreTextureRestrictions") + if context.scene.ignoreTextureRestrictions: + col.box().label(text="Width/height must be < 1024. Must be png format.") + + +class Fast64_GlobalToolsPanel(bpy.types.Panel): + bl_idname = "FAST64_PT_global_tools" + bl_label = "Fast64 Tools" + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_category = "Fast64" + + @classmethod + def poll(cls, context): + return True + + # called every frame + def draw(self, context): + # TODO: figure out why a circular import is happening, this is bad + from ..f3d_material_converter import ( + mat_updater_draw, + ) + + col = self.layout.column() + col.operator(ArmatureApplyWithMeshOperator.bl_idname) + # col.operator(CreateMetarig.bl_idname) + ui_oplargetexture(col, context) + col.separator() + + box = col.box().column() + box.label(text="Material Updater") + mat_updater_draw(box, context) + col.separator() + + box = col.box().column() + box.label(text="BSDF Converter") + bsdf_converter_panel_draw(box, context) + col.separator() + + addon_updater_ops.update_notice_box_ui(self, context) + + +classes = tuple() +panel_classes = (F3D_GlobalSettingsPanel, Fast64_GlobalToolsPanel) + + +def f3d_panel_register(): + for cls in panel_classes: + register_class(cls) + + +def f3d_panel_unregister(): + for cls in reversed(panel_classes): + unregister_class(cls) + + +def f3d_register(register_panels: bool): + from ..f3d_material_converter import mat_updater_register + + for cls in classes: + register_class(cls) + mat_register() + render_engine_register() + mat_updater_register() + f3d_writer_register() + flipbook_register() + f3d_parser_register() + op_largetexture_register() + bsdf_converter_register() + + if register_panels: + f3d_panel_register() + + +def f3d_unregister(unregister_panels): + from ..f3d_material_converter import mat_updater_unregister + + for cls in reversed(classes): + unregister_class(cls) + bsdf_converter_unregister() + op_largetexture_unregister() + f3d_parser_unregister() + flipbook_unregister() + f3d_writer_unregister() + mat_updater_unregister() + render_engine_unregister() + mat_unregister() + + if unregister_panels: + f3d_panel_unregister() diff --git a/fast64_internal/f3d/bsdf_converter/__init__.py b/fast64_internal/f3d/bsdf_converter/__init__.py new file mode 100644 index 000000000..06cc53284 --- /dev/null +++ b/fast64_internal/f3d/bsdf_converter/__init__.py @@ -0,0 +1,10 @@ +from .operators import bsdf_converter_ops_register, bsdf_converter_ops_unregister +from .ui import bsdf_converter_panel_draw + + +def bsdf_converter_register(): + bsdf_converter_ops_register() + + +def bsdf_converter_unregister(): + bsdf_converter_ops_unregister() diff --git a/fast64_internal/f3d/bsdf_converter/classes.py b/fast64_internal/f3d/bsdf_converter/classes.py new file mode 100644 index 000000000..bfc148369 --- /dev/null +++ b/fast64_internal/f3d/bsdf_converter/classes.py @@ -0,0 +1,11 @@ +import dataclasses + + +@dataclasses.dataclass +class SimpleN64Texture: + name: str + + +@dataclasses.dataclass +class SimpleN64Material: + name: str diff --git a/fast64_internal/f3d/bsdf_converter/operators.py b/fast64_internal/f3d/bsdf_converter/operators.py new file mode 100644 index 000000000..d64cb711c --- /dev/null +++ b/fast64_internal/f3d/bsdf_converter/operators.py @@ -0,0 +1,30 @@ +from bpy.utils import register_class, unregister_class + +from ...operators import OperatorBase + + +class F3D_ConvertF3DToBSDF(OperatorBase): + bl_idname = "scene.f3d_convert_to_bsdf" + bl_label = "Convert F3D to BSDF" + bl_options = {"REGISTER", "UNDO", "PRESET"} + icon = "MATERIAL" + + +class F3D_ConvertBSDFToF3D(OperatorBase): + bl_idname = "scene.bsdf_convert_to_f3d" + bl_label = "Convert BSDF to F3D" + bl_options = {"REGISTER", "UNDO", "PRESET"} + icon = "NODE_MATERIAL" + + +classes = (F3D_ConvertF3DToBSDF, F3D_ConvertBSDFToF3D) + + +def bsdf_converter_ops_register(): + for cls in classes: + register_class(cls) + + +def bsdf_converter_ops_unregister(): + for cls in reversed(classes): + unregister_class(cls) diff --git a/fast64_internal/f3d/bsdf_converter/ui.py b/fast64_internal/f3d/bsdf_converter/ui.py new file mode 100644 index 000000000..1cc658971 --- /dev/null +++ b/fast64_internal/f3d/bsdf_converter/ui.py @@ -0,0 +1,11 @@ +"""Usually this would be panel.py but there is no actual panel since we only draw in the tools panel.""" + +from bpy.types import UILayout, Context + +from .operators import F3D_ConvertF3DToBSDF, F3D_ConvertBSDFToF3D + + +def bsdf_converter_panel_draw(layout: UILayout, _context: Context): + col = layout.column() + F3D_ConvertF3DToBSDF.draw_props(col) + F3D_ConvertBSDFToF3D.draw_props(col) diff --git a/fast64_internal/f3d_material_converter.py b/fast64_internal/f3d_material_converter.py index 992c2c221..744ca79b3 100644 --- a/fast64_internal/f3d_material_converter.py +++ b/fast64_internal/f3d_material_converter.py @@ -1,7 +1,9 @@ # This is not in the f3d package since copying materials requires copying collision settings from all games as well. import bpy +from bpy.types import UILayout, Context from bpy.utils import register_class, unregister_class + from .f3d.f3d_material import * from .f3d.f3d_material_helpers import node_tree_copy from .utility import * @@ -164,105 +166,12 @@ def convertF3DtoNewVersion( traceback.print_exc() -def convertAllBSDFtoF3D(objs, renameUV): - # Dict of non-f3d materials : converted f3d materials - # handles cases where materials are used in multiple objects - materialDict = {} - for obj in objs: - if renameUV: - for uv_layer in obj.data.uv_layers: - uv_layer.name = "UVMap" - for index in range(len(obj.material_slots)): - material = obj.material_slots[index].material - if material is not None and not material.is_f3d: - if material in materialDict: - print("Existing material") - obj.material_slots[index].material = materialDict[material] - else: - print("New material") - convertBSDFtoF3D(obj, index, material, materialDict) - - -def convertBSDFtoF3D(obj, index, material, materialDict): - if not material.use_nodes: - newMaterial = createF3DMat(obj, preset="Shaded Solid", index=index) - with bpy.context.temp_override(material=newMaterial): - newMaterial.f3d_mat.default_light_color = material.diffuse_color - updateMatWithName(newMaterial, material, materialDict) - - elif "Principled BSDF" in material.node_tree.nodes: - tex0Node = material.node_tree.nodes["Principled BSDF"].inputs["Base Color"] - if len(tex0Node.links) == 0: - newMaterial = createF3DMat(obj, preset=getDefaultMaterialPreset("Shaded Solid"), index=index) - with bpy.context.temp_override(material=newMaterial): - newMaterial.f3d_mat.default_light_color = tex0Node.default_value - updateMatWithName(newMaterial, material, materialDict) - else: - if isinstance(tex0Node.links[0].from_node, bpy.types.ShaderNodeTexImage): - if "convert_preset" in material: - presetName = material["convert_preset"] - if presetName not in [enumValue[0] for enumValue in enumMaterialPresets]: - raise PluginError( - "During BSDF to F3D conversion, for material '" - + material.name - + "'," - + " enum '" - + presetName - + "' was not found in material preset enum list." - ) - else: - presetName = getDefaultMaterialPreset("Shaded Texture") - newMaterial = createF3DMat(obj, preset=presetName, index=index) - with bpy.context.temp_override(material=newMaterial): - newMaterial.f3d_mat.tex0.tex = tex0Node.links[0].from_node.image - updateMatWithName(newMaterial, material, materialDict) - else: - print("Principled BSDF material does not have an Image Node attached to its Base Color.") - else: - print("Material is not a Principled BSDF or non-node material.") - - def updateMatWithName(f3dMat, oldMat, materialDict): f3dMat.name = oldMat.name + "_f3d" update_preset_manual(f3dMat, bpy.context) materialDict[oldMat] = f3dMat -class BSDFConvert(bpy.types.Operator): - # set bl_ properties - bl_idname = "object.convert_bsdf" - bl_label = "Principled BSDF to F3D Converter" - bl_options = {"REGISTER", "UNDO", "PRESET"} - - # Called on demand (i.e. button press, menu item) - # Can also be called from operator search menu (Spacebar) - def execute(self, context): - try: - if context.mode != "OBJECT": - raise PluginError("Operator can only be used in object mode.") - - if context.scene.bsdf_conv_all: - convertAllBSDFtoF3D( - [obj for obj in bpy.data.objects if obj.type == "MESH"], - context.scene.rename_uv_maps, - ) - else: - if len(context.selected_objects) == 0: - raise PluginError("Mesh not selected.") - elif type(context.selected_objects[0].data) is not bpy.types.Mesh: - raise PluginError("Mesh not selected.") - - obj = context.selected_objects[0] - convertAllBSDFtoF3D([obj], context.scene.rename_uv_maps) - - except Exception as e: - raisePluginError(self, e) - return {"CANCELLED"} - - self.report({"INFO"}, "Created F3D material.") - return {"FINISHED"} # must return a set - - class MatUpdateConvert(bpy.types.Operator): # set bl_ properties bl_idname = "object.convert_f3d_update" @@ -297,62 +206,27 @@ def execute(self, context): return {"FINISHED"} # must return a set -class F3DMaterialConverterPanel(bpy.types.Panel): - bl_label = "F3D Material Converter" - bl_idname = "MATERIAL_PT_F3D_Material_Converter" - bl_space_type = "VIEW_3D" - bl_region_type = "UI" - bl_category = "Fast64" - - @classmethod - def poll(cls, context): - return True - # return hasattr(context, 'object') and context.object is not None and \ - # isinstance(context.object.data, bpy.types.Mesh) - - def draw(self, context): - # mesh = context.object.data - self.layout.operator(BSDFConvert.bl_idname) - self.layout.prop(context.scene, "bsdf_conv_all") - self.layout.prop(context.scene, "rename_uv_maps") - op = self.layout.operator(MatUpdateConvert.bl_idname) - op.update_conv_all = context.scene.update_conv_all - self.layout.prop(context.scene, "update_conv_all") - self.layout.operator(ReloadDefaultF3DPresets.bl_idname) - - -bsdf_conv_classes = ( - BSDFConvert, - MatUpdateConvert, -) +def mat_updater_draw(layout: UILayout, context: Context): + col = layout.column() + op = col.operator(MatUpdateConvert.bl_idname) + op.update_conv_all = context.scene.update_conv_all + col.prop(context.scene, "update_conv_all") + col.operator(ReloadDefaultF3DPresets.bl_idname) -bsdf_conv_panel_classes = (F3DMaterialConverterPanel,) - -def bsdf_conv_panel_regsiter(): - for cls in bsdf_conv_panel_classes: - register_class(cls) - - -def bsdf_conv_panel_unregsiter(): - for cls in bsdf_conv_panel_classes: - unregister_class(cls) +mat_updater_classes = (MatUpdateConvert,) -def bsdf_conv_register(): - for cls in bsdf_conv_classes: +def mat_updater_register(): + for cls in mat_updater_classes: register_class(cls) # Moved to Level Root - bpy.types.Scene.bsdf_conv_all = bpy.props.BoolProperty(name="Convert all objects", default=True) bpy.types.Scene.update_conv_all = bpy.props.BoolProperty(name="Convert all objects", default=True) - bpy.types.Scene.rename_uv_maps = bpy.props.BoolProperty(name="Rename UV maps", default=True) -def bsdf_conv_unregister(): - for cls in bsdf_conv_classes: +def mat_updater_unregister(): + for cls in mat_updater_classes: unregister_class(cls) - del bpy.types.Scene.bsdf_conv_all del bpy.types.Scene.update_conv_all - del bpy.types.Scene.rename_uv_maps