diff --git a/README.md b/README.md index 452ab2a..748c2ed 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,12 @@ __Update existing import (if any)__ - If checked, any previously created camera __Import background image__ - If checked, the image from the fSpy project file will be used as the background image for the Blender camera. +### Panel + +If you are using multiple cameras with different reference image sizes, you can quickly switch from one render resolution to another using the `Set Render Dimensions` button in the fSpy panel: + +![fSpy Panel](readme_images/panel.png) + # Support for Blender versions older than 2.80 Starting with version 1.0.3, the addon is only compatible with Blender 2.80 and up. If you are using an older Blender version, please [download version 1.0.2](https://github.com/stuffmatic/fSpy-Blender/releases/tag/v1.0.2) of the add-on. diff --git a/build.py b/build.py index 356b684..f142d9e 100644 --- a/build.py +++ b/build.py @@ -11,7 +11,7 @@ version_string = line.split("(")[1] version_string = version_string.split(")")[0] version_parts = version_string.split(",") - version_parts = map(str.strip, version_parts) + version_parts = list(map(str.strip, version_parts)) break init_file.close() diff --git a/fspy_blender/__init__.py b/fspy_blender/__init__.py index d123a0d..0f26137 100644 --- a/fspy_blender/__init__.py +++ b/fspy_blender/__init__.py @@ -19,7 +19,7 @@ "name": "Import fSpy project", "author": "Per Gantelius", "description": "Imports the background image and camera parameters from an fSpy project.", - "version": (1, 0, 3), + "version": (1, 1, 0), "blender": (2, 80, 0), "location": "File > Import > fSpy", "url": "https://github.com/stuffmatic/fSpy-Blender", @@ -36,8 +36,12 @@ import importlib importlib.reload(fspy) importlib.reload(addon) + importlib.reload(properties) + importlib.reload(panel) else: from . import addon + from . import panel + from . import properties from . import fspy import bpy @@ -47,7 +51,10 @@ def menu_func_import(self, context): self.layout.operator(addon.ImportfSpyProject.bl_idname, text="fSpy (.fspy)") def register(): + properties.register() bpy.utils.register_class(addon.ImportfSpyProject) + bpy.utils.register_class(addon.SetRenderDimensions) + panel.register() # Add import menu item if hasattr(bpy.types, 'TOPBAR_MT_file_import'): #2.8+ @@ -56,7 +63,10 @@ def register(): bpy.types.INFO_MT_file_import.append(menu_func_import) def unregister(): + panel.unregister() bpy.utils.unregister_class(addon.ImportfSpyProject) + bpy.utils.unregister_class(addon.SetRenderDimensions) + properties.unregister() # Remove import menu item if hasattr(bpy.types, 'TOPBAR_MT_file_import'): #2.8+ diff --git a/fspy_blender/addon.py b/fspy_blender/addon.py index dc3ac37..53cce42 100644 --- a/fspy_blender/addon.py +++ b/fspy_blender/addon.py @@ -121,6 +121,12 @@ def set_up_camera(self, project, update_existing_camera): camera.data.shift_x = x_shift_scale * (0.5 - pp_rel[0]) camera.data.shift_y = y_shift_scale * (-0.5 + pp_rel[1]) + camera.data.fspy.use_fspy = True + camera.data.fspy.reference_dimensions = ( + camera_parameters.image_width, + camera_parameters.image_height + ) + # Return the configured camera return camera @@ -267,3 +273,22 @@ def import_fpsy_project(self, context, filepath, update_existing_camera, set_bac except fspy.ParsingError as e: self.report({ 'ERROR' }, 'fSpy import error: ' + str(e)) return {'CANCELLED'} + + +class SetRenderDimensions(Operator): + """Set the dimensions of the render to the dimensions of the + reference image that was used for this camera""" + bl_idname = "fspy_blender.set_render_dimensions" + bl_label = "Set Render Dimensions" + + @classmethod + def poll(cls, context): + return context.active_object.type == 'CAMERA' + + def execute(self, context): + scene = context.scene + cam = context.active_object.data + w, h = cam.fspy.reference_dimensions + scene.render.resolution_x = w + scene.render.resolution_y = h + return {'FINISHED'} diff --git a/fspy_blender/panel.py b/fspy_blender/panel.py new file mode 100644 index 0000000..1399287 --- /dev/null +++ b/fspy_blender/panel.py @@ -0,0 +1,30 @@ +import bpy +from bpy.types import Panel + +from . import addon as ops + +class FspyPanel(Panel): + bl_label = "fSpy" + bl_idname = "SCENE_PT_fSpy" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "data" + + @classmethod + def poll(cls, context): + obj = context.active_object + return ( + obj.type == 'CAMERA' + and obj.data.fspy.use_fspy + ) + + def draw(self, context): + cam = context.active_object.data + layout = self.layout + #layout.prop(cam.fspy, "reference_dimensions") + layout.operator(ops.SetRenderDimensions.bl_idname) + +classes = ( + FspyPanel, +) +register, unregister = bpy.utils.register_classes_factory(classes) diff --git a/fspy_blender/properties.py b/fspy_blender/properties.py new file mode 100644 index 0000000..81c9f9d --- /dev/null +++ b/fspy_blender/properties.py @@ -0,0 +1,31 @@ +import bpy +from bpy.props import IntVectorProperty, PointerProperty, BoolProperty +from bpy.types import Camera, PropertyGroup + +class FspyProperties(PropertyGroup): + use_fspy: BoolProperty( + name = "Use fSpy", + description = "Turned true when the camera was imported using fSpy", + default = False, + ) + + reference_dimensions: IntVectorProperty( + name = "Reference Dimension", + description = "Width and height in pixels of the reference image that was used in fSpy", + size = 2, + default = (0,0), + min = 0, + ) + +classes = ( + FspyProperties, +) +register_cls, unregister_cls = bpy.utils.register_classes_factory(classes) + +def register(): + register_cls() + Camera.fspy = PointerProperty(type=FspyProperties) + +def unregister(): + del Camera.fspy + unregister_cls() diff --git a/readme_images/panel.png b/readme_images/panel.png new file mode 100644 index 0000000..988e1a1 Binary files /dev/null and b/readme_images/panel.png differ