diff --git a/src/addon/__init__.py b/src/addon/__init__.py index 333fc05..220121b 100644 --- a/src/addon/__init__.py +++ b/src/addon/__init__.py @@ -35,8 +35,9 @@ import bpy # nopep8 -classes: list[type] = [operator.DropEventListener, preferences.DragAndDropPreferences] +classes: list[type] = [preferences.DragAndDropPreferences] +classes.extend(operator.get_operators()) classes.extend(formats.CLASSES) diff --git a/src/addon/formats/__init__.py b/src/addon/formats/__init__.py index 944f0ce..31469b3 100644 --- a/src/addon/formats/__init__.py +++ b/src/addon/formats/__init__.py @@ -12,6 +12,7 @@ from . import glb from . import obj from . import obj_legacy +from . import png from . import ply from . import stl from . import stl_legacy @@ -33,6 +34,7 @@ CLASSES.extend(fbx.OPERATORS) CLASSES.extend(glb.OPERATORS) CLASSES.extend(obj.OPERATORS) +CLASSES.extend(png.OPERATORS) CLASSES.extend(ply.OPERATORS) CLASSES.extend(stl.OPERATORS) CLASSES.extend(svg.OPERATORS) diff --git a/src/addon/formats/abc.py b/src/addon/formats/abc.py index 5443c9c..1e0ec1b 100644 --- a/src/addon/formats/abc.py +++ b/src/addon/formats/abc.py @@ -81,7 +81,8 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_ABC(VIEW3D_MT_Space_Import_BASE): bl_label = "Import ABC File" - def format(self): + @staticmethod + def format(): return "abc" diff --git a/src/addon/formats/bvh.py b/src/addon/formats/bvh.py index 02f7b42..c36ba3b 100644 --- a/src/addon/formats/bvh.py +++ b/src/addon/formats/bvh.py @@ -134,7 +134,8 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_BVH(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Biovision Hierarchy File" - def format(self): + @staticmethod + def format(): return "bvh" diff --git a/src/addon/formats/dae.py b/src/addon/formats/dae.py index 1beef79..dd56ba2 100644 --- a/src/addon/formats/dae.py +++ b/src/addon/formats/dae.py @@ -84,7 +84,8 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_DAE(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Collada File" - def format(self): + @staticmethod + def format(): return "dae" diff --git a/src/addon/formats/fbx.py b/src/addon/formats/fbx.py index c70edcc..ccd8a89 100644 --- a/src/addon/formats/fbx.py +++ b/src/addon/formats/fbx.py @@ -204,7 +204,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_FBX(VIEW3D_MT_Space_Import_BASE): bl_label = "Import FBX File" - def format(self): + @staticmethod + def format(): return "fbx" diff --git a/src/addon/formats/glb.py b/src/addon/formats/glb.py index d8f5b05..8afcf77 100644 --- a/src/addon/formats/glb.py +++ b/src/addon/formats/glb.py @@ -96,14 +96,16 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_GLB(VIEW3D_MT_Space_Import_BASE): bl_label = "Import glTF File" - def format(self): + @staticmethod + def format(): return "glb" class VIEW3D_MT_Space_Import_GLTF(VIEW3D_MT_Space_Import_BASE): bl_label = "Import glTF File" - def format(self): + @staticmethod + def format(): return "glb" diff --git a/src/addon/formats/obj.py b/src/addon/formats/obj.py index 9665e00..b93b507 100644 --- a/src/addon/formats/obj.py +++ b/src/addon/formats/obj.py @@ -106,7 +106,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_OBJ(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Wavefront OBJ File" - def format(self): + @staticmethod + def format(): return "obj" diff --git a/src/addon/formats/obj_legacy.py b/src/addon/formats/obj_legacy.py index 8ee1b04..11b20ad 100644 --- a/src/addon/formats/obj_legacy.py +++ b/src/addon/formats/obj_legacy.py @@ -131,7 +131,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_OBJLegacy(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Wavefront OBJ File" - def format(self): + @staticmethod + def format(): return "obj" diff --git a/src/addon/formats/ply.py b/src/addon/formats/ply.py index c39fb05..9d1e3f9 100644 --- a/src/addon/formats/ply.py +++ b/src/addon/formats/ply.py @@ -97,7 +97,8 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_PLY(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Polygon File Format File" - def format(self): + @staticmethod + def format(): return "ply" diff --git a/src/addon/formats/png.py b/src/addon/formats/png.py new file mode 100644 index 0000000..102951b --- /dev/null +++ b/src/addon/formats/png.py @@ -0,0 +1,278 @@ +# ------------------------------------------------------------------------------------------ +# Copyright (c) Natsuneko. All rights reserved. +# Licensed under the MIT License. See LICENSE in the project root for license information. +# ------------------------------------------------------------------------------------------ + +# pyright: reportGeneralTypeIssues=false +# pyright: reportUnknownArgumentType=false +# pyright: reportUnknownMemberType=false + + +import bpy.ops + +from typing import cast +from bpy.types import Context + +from .super import ( + ImportWithDefaultsBase, + VIEW3D_MT_Space_Import_BASE, +) + + +class ImportImageWithDefaults(ImportWithDefaultsBase): + bl_idname = "object.import_image_with_defaults" + bl_label = "Import PNG File" + + def execute(self, context: Context): + + bpy.ops.object.empty_add( + type="IMAGE", + align="VIEW", + location=context.scene.cursor.location, + scale=(5, 5, 5), + ) + + empty = bpy.context.active_object + + bpy.ops.image.open(filepath=self.filepath()) + img = self.find_opened_image(self.filepath()) + + if img is not None: + empty.data = img + + return {"FINISHED"} + + def find_opened_image(self, path: str) -> bpy.types.Image | None: + for ( + item + ) in bpy.data.images.items(): # pyright: ignore[reportUnknownVariableType] + i = cast(bpy.types.Image, item[1]) # pyright: ignore[reportInvalidTypeForm] + + if i.filepath == path: + return i + + +class VIEW3D_MT_Space_Import_BMP(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import BMP File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_BW(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Iris File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_CIN(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Cineon & DPX File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_DPX(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Cineon & DPX File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_EXR(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import OpenEXR File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_HDR(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import HDR File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_J2C(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import JPEG 2000 File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_JP2(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import JPEG 2000 File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_JPG(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import JPEG File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_JPEG(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import JPEG File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_PNG(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import PNG File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_RGB(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Iris File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_SGI(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Iris File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_TIF(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import TIFF File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_TIFF(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import TIFF File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_TGA(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import Targa File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +class VIEW3D_MT_Space_Import_WEBP(VIEW3D_MT_Space_Import_BASE): + bl_label = "Import WebP File" + + @staticmethod + def format(): + return "image" + + @staticmethod + def has_custom_importer() -> bool: + return False + + +OPERATORS = [ + ImportImageWithDefaults, + VIEW3D_MT_Space_Import_BMP, + VIEW3D_MT_Space_Import_BW, + VIEW3D_MT_Space_Import_CIN, + VIEW3D_MT_Space_Import_DPX, + VIEW3D_MT_Space_Import_EXR, + VIEW3D_MT_Space_Import_HDR, + VIEW3D_MT_Space_Import_J2C, + VIEW3D_MT_Space_Import_JP2, + VIEW3D_MT_Space_Import_JPG, + VIEW3D_MT_Space_Import_JPEG, + VIEW3D_MT_Space_Import_PNG, + VIEW3D_MT_Space_Import_RGB, + VIEW3D_MT_Space_Import_SGI, + VIEW3D_MT_Space_Import_TIF, + VIEW3D_MT_Space_Import_TIFF, + VIEW3D_MT_Space_Import_TGA, + VIEW3D_MT_Space_Import_WEBP, +] diff --git a/src/addon/formats/stl.py b/src/addon/formats/stl.py index 38bbb5a..5bb85d9 100644 --- a/src/addon/formats/stl.py +++ b/src/addon/formats/stl.py @@ -89,7 +89,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_STL(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Wavefront STL File (Experimental)" - def format(self): + @staticmethod + def format(): return "stl" diff --git a/src/addon/formats/stl_legacy.py b/src/addon/formats/stl_legacy.py index e608359..d52c4d8 100644 --- a/src/addon/formats/stl_legacy.py +++ b/src/addon/formats/stl_legacy.py @@ -93,7 +93,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_STLLegacy(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Wavefront STL File" - def format(self): + @staticmethod + def format(): return "stl" diff --git a/src/addon/formats/super.py b/src/addon/formats/super.py index d895886..a085599 100644 --- a/src/addon/formats/super.py +++ b/src/addon/formats/super.py @@ -80,43 +80,49 @@ def draw(self, context: Context | None): layout = self.layout format = self.format() - if format in selectable_importers: - importers = selectable_importers[format]() + if self.has_custom_importer(): + if format in selectable_importers: + importers = selectable_importers[format]() - col = layout.column() + col = layout.column() - for importer in importers: - text, name = importer + for importer in importers: + text, name = importer - col.operator( - f"object.import_{name}_with_defaults", - text=f"Import with Defaults {text}".strip(), - ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore + col.operator( + f"object.import_{name}_with_defaults", + text=f"Import with Defaults {text}".strip(), + ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore - col = layout.column() - col.operator_context = "INVOKE_DEFAULT" + col = layout.column() + col.operator_context = "INVOKE_DEFAULT" - for importer in importers: - text, name = importer + for importer in importers: + text, name = importer + col.operator( + f"object.import_{name}_with_custom_settings", + text=f"Import with Custom Settings {text}".strip(), + ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore + + else: + col = layout.column() col.operator( - f"object.import_{name}_with_custom_settings", - text=f"Import with Custom Settings {text}".strip(), + f"object.import_{self.format()}_with_defaults", + text="Import with Defaults", ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore - else: - col = layout.column() - col.operator( - f"object.import_{self.format()}_with_defaults", - text="Import with Defaults", - ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore - - col = layout.column() - col.operator_context = "INVOKE_DEFAULT" - col.operator( - f"object.import_{self.format()}_with_custom_settings", - text="Import with Custom Settings", - ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore - - def format(self) -> str: + col = layout.column() + col.operator_context = "INVOKE_DEFAULT" + col.operator( + f"object.import_{self.format()}_with_custom_settings", + text="Import with Custom Settings", + ).filename = VIEW3D_MT_Space_Import_BASE.filename # type: ignore + + @staticmethod + def format() -> str: return "" + + @staticmethod + def has_custom_importer() -> bool: + return True diff --git a/src/addon/formats/svg.py b/src/addon/formats/svg.py index eb037a2..4593bc0 100644 --- a/src/addon/formats/svg.py +++ b/src/addon/formats/svg.py @@ -43,7 +43,8 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_SVG(VIEW3D_MT_Space_Import_BASE): bl_label = "Import SVG File" - def format(self): + @staticmethod + def format(): return "svg" diff --git a/src/addon/formats/usd.py b/src/addon/formats/usd.py index 547f0ac..4eaec08 100644 --- a/src/addon/formats/usd.py +++ b/src/addon/formats/usd.py @@ -190,28 +190,32 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_USD(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Universal Scene Description File" - def format(self): + @staticmethod + def format(): return "usd" class VIEW3D_MT_Space_Import_USDA(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Universal Scene Description File" - def format(self): + @staticmethod + def format(): return "usd" class VIEW3D_MT_Space_Import_USDC(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Universal Scene Description File" - def format(self): + @staticmethod + def format(): return "usd" class VIEW3D_MT_Space_Import_USDZ(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Universal Scene Description File" - def format(self): + @staticmethod + def format(): return "usd" diff --git a/src/addon/formats/vrm.py b/src/addon/formats/vrm.py index 7749488..907a816 100644 --- a/src/addon/formats/vrm.py +++ b/src/addon/formats/vrm.py @@ -82,7 +82,8 @@ def execute(self, context: Context): class VIEW3D_MT_Space_Import_VRM(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Virtual Reality Model File" - def format(self): + @staticmethod + def format(): return "vrm" diff --git a/src/addon/formats/x3d.py b/src/addon/formats/x3d.py index 1fb521e..6e362c6 100644 --- a/src/addon/formats/x3d.py +++ b/src/addon/formats/x3d.py @@ -81,14 +81,16 @@ def execute(self, context: Context) -> Set[str] | Set[int]: class VIEW3D_MT_Space_Import_X3D(VIEW3D_MT_Space_Import_BASE): bl_label = "Import Extensible 3D File Format File" - def format(self): + @staticmethod + def format(): return "x3d" class VIEW3D_MT_Space_Import_WRL(VIEW3D_MT_Space_Import_BASE): bl_label = "Import WRL File" - def format(self): + @staticmethod + def format(): return "x3d" diff --git a/src/addon/operator.py b/src/addon/operator.py index 82682e8..a51596e 100644 --- a/src/addon/operator.py +++ b/src/addon/operator.py @@ -16,6 +16,7 @@ from bpy.props import StringProperty # pyright: ignore[reportUnknownVariableType] from bpy.types import Context, Event, Operator +from .formats import CLASSES from .formats.super import VIEW3D_MT_Space_Import_BASE # formats that Blender does not supported by default @@ -23,6 +24,8 @@ "vrm": lambda: hasattr(bpy.ops.import_scene, "vrm"), } +operators: list[type] = [] + class DropEventListener(Operator): bl_idname = "object.drop_event_listener" @@ -30,9 +33,25 @@ class DropEventListener(Operator): filename: StringProperty() # type: ignore - def inflate(self, name: str): + def find_class(self, ext: str) -> VIEW3D_MT_Space_Import_BASE | None: + for c in CLASSES: + if c.__name__ == f"VIEW3D_MT_Space_Import_{ext}": + return typing.cast(VIEW3D_MT_Space_Import_BASE, c) + + def inflate(self, name: str, ext: str): VIEW3D_MT_Space_Import_BASE.filename = self.filename # type: ignore - bpy.ops.wm.call_menu(name=name) # type: ignore + + c = self.find_class(ext) + if c is None: + return # invalid operation + + if c.has_custom_importer(): + bpy.ops.wm.call_menu(name=name) # type: ignore + else: + i = getattr(bpy.ops.object, f"import_{c.format()}_with_defaults") + if i is not None: + print(i) + i("EXEC_DEFAULT", filename=self.filename) return def invoke(self, context: Context, event: Event): @@ -46,10 +65,20 @@ def invoke(self, context: Context, event: Event): # dynamically called importer name = f"VIEW3D_MT_Space_Import_{ext[1:].upper()}" - self.inflate(name) + self.inflate(name, ext[1:].upper()) except TypeError as e: print(e) except RuntimeError as e: print(e) return {"FINISHED"} + + @classmethod + def poll(cls, context: bpy.types.Context): + return context.area and context.area.type == "VIEW_3D" + + +operators.append(DropEventListener) + +def get_operators(): + return operators diff --git a/src/dll/BlenderPatcher.cpp b/src/dll/BlenderPatcher.cpp index 73580d3..b30b6d7 100644 --- a/src/dll/BlenderPatcher.cpp +++ b/src/dll/BlenderPatcher.cpp @@ -125,9 +125,9 @@ void BlenderPatcher::Patch() } catch (std::out_of_range&) { - std::cout << "[ERROR] exception: out of range" << std::endl; - std::cout << "[ERROR] injector detected the unsupported version of Blender. Please upgrade Drag-and-Drop Support or downgrade Blender" << std::endl; - std::cout << "[ERROR] detected version : " << this->_versionString << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] exception: out of range" << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] injector detected the unsupported version of Blender. Please upgrade Drag-and-Drop Support or downgrade Blender" << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] detected version : " << this->_versionString << std::endl; } } @@ -139,9 +139,9 @@ void BlenderPatcher::UnPatch() } catch (std::out_of_range&) { - std::cout << "[ERROR] exception: out of range" << std::endl; - std::cout << "[ERROR] injector detected the unsupported version of Blender. Please upgrade Drag-and-Drop Support or downgrade Blender" << std::endl; - std::cout << "[ERROR] detected version : " << this->_versionString << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] exception: out of range" << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] injector detected the unsupported version of Blender. Please upgrade Drag-and-Drop Support or downgrade Blender" << std::endl; + std::cout << "[DRAG-AND-DROP-SUPPORT] detected version : " << this->_versionString << std::endl; } }