diff --git a/blender/osci_render/__init__.py b/blender/osci_render/__init__.py index 54e4e82..c29f692 100644 --- a/blender/osci_render/__init__.py +++ b/blender/osci_render/__init__.py @@ -11,11 +11,13 @@ bl_info = { } import bpy +import os import bmesh import socket import json import atexit from bpy.app.handlers import persistent +from bpy_extras.io_utils import ImportHelper HOST = "localhost" PORT = 51677 @@ -36,10 +38,10 @@ class OBJECT_PT_osci_render_settings(bpy.types.Panel): def draw(self, context): global sock if sock is None: - self.layout.operator("render.osci_render_connect", text="Connect to osci-render") + self.layout.operator("render.osci_render_connect", text="Connect to osci-render instance") else: self.layout.operator("render.osci_render_close", text="Close osci-render connection") - + self.layout.operator("render.osci_render_save", text="Save line art to file") class osci_render_connect(bpy.types.Operator): bl_label = "Connect to osci-render" @@ -60,6 +62,35 @@ class osci_render_connect(bpy.types.Operator): return {"CANCELLED"} return {"FINISHED"} + +class osci_render_save(bpy.types.Operator, ImportHelper): + bl_label = "Save Line Art" + bl_idname = "render.osci_render_save" + bl_description = "Save line art to the chosen file" + filter_glob: bpy.props.StringProperty( + default='*.gpla', + options={'HIDDEN'} + ) + + def execute(self,context): + FilePath = self.filepath + filename, extension = os.path.splitext(self.filepath) + if (extension != ".gpla"): + extension = ".gpla" + FilePath = FilePath + ".gpla" + self.report({"INFO"}, FilePath) + if filename is not None and extension is not None: + fin = save_scene_to_file(bpy.context.scene, FilePath) + if (fin == 0): + self.report({"INFO"}, "File write successful!") + return {"FINISHED"} + else: + self.report({"WARNING"}, "Something went wrong in saving the file") + else: + filename = None + extension = None + self.report({"WARNING"}, "The filename or extension isn't right, action stopped for your own safety") + return {"CANCELLED"} class osci_render_close(bpy.types.Operator): @@ -87,6 +118,44 @@ def append_matrix(object_info, obj): camera_space = bpy.context.scene.camera.matrix_world.inverted() @ obj.matrix_world object_info["matrix"] = [camera_space[i][j] for i in range(4) for j in range(4)] return object_info + +@persistent +def save_scene_to_file(scene, FilePath): + returnFrame = scene.frame_current + + scene_info = {"frames": []} + for frame in range(0, scene.frame_end - scene.frame_start): + frame_info = {"objects": []} + scene.frame_set(frame + scene.frame_start) + for obj in bpy.data.objects: + if obj.visible_get() and obj.type == 'GPENCIL': + object_info = {"name": obj.name} + strokes = obj.data.layers.active.frames.data.frames[frame+1].strokes + + object_info["vertices"] = [] + for stroke in strokes: + object_info["vertices"].append([{ + "x": vert.co[0], + "y": vert.co[1], + "z": vert.co[2], + } for vert in stroke.points]) + + frame_info["objects"].append(append_matrix(object_info, obj)) + + frame_info["focalLength"] = -0.05 * bpy.data.cameras[0].lens + scene_info["frames"].append(frame_info) + + json_str = json.dumps(scene_info, separators=(',', ':')) + + if (FilePath is not None): + f = open(FilePath, "w") + f.write(json_str) + f.close() + else: + return 1 + + scene.frame_set(returnFrame) + return 0 @persistent @@ -120,7 +189,7 @@ def send_scene_to_osci_render(scene): sock = None -operations = [OBJECT_PT_osci_render_settings, osci_render_connect, osci_render_close] +operations = [OBJECT_PT_osci_render_settings, osci_render_connect, osci_render_close, osci_render_save] def register():