11bl_info = {
22 "name" : "Export Camera Animation to Diffusion Notebook String" ,
33 "author" : "Michael Walker (@mwalk10)" ,
4- "version" : (1 , 0 , 0 ),
4+ "version" : (1 , 1 , 4 ),
55 "blender" : (3 , 3 , 0 ),
66 "location" : "File > Export > Diffusion Notebook String" ,
7- "description" : "Export camera animations in a format for use in Deforum diffusion collab notebook animations." ,
7+ "description" : "Export camera animations formatted for use in Deforum diffusion collab notebook animations." ,
88 "warning" : "" ,
99 "wiki_url" : "" ,
1010 "category" : "Import-Export" ,
1616from mathutils import Vector
1717from bpy import context
1818from math import isclose
19+ import json
1920
20-
21+ def roundZero (num , magnitude_thresh = 0.00001 ):
22+ if abs (num ) > magnitude_thresh :
23+ return num
24+ else :
25+ return 0
26+
2127def arr_to_keyframes (arr ):
2228 keyframes = ""
2329 for i , val in enumerate (arr ):
30+ val = roundZero (val )
2431 #if we previously had a zero, then we can stop emitting zeroes until right before the next nonzero
25- last_is_same = i > 0 and isclose (val , arr [i - 1 ])
26- next_is_same = (i + 1 ) < len (arr ) and isclose (val , arr [i + 1 ])
32+ last_is_same = i > 0 and isclose (val , roundZero ( arr [i - 1 ]) )
33+ next_is_same = (i + 1 ) < len (arr ) and isclose (val , roundZero ( arr [i + 1 ]) )
2734
2835 omit = last_is_same and next_is_same
2936
3037 if not omit :
3138 keyframes += f"{ i } :({ val } ),"
3239 return keyframes
3340
34- def cameras_to_string (context , startFrame , endFrame , cameras , translation_scale = 50 ):
41+ def cameras_to_string (context , startFrame , endFrame , cameras , translation_scale = 50 , output_camcode = True , output_json = False , ):
3542 # get the current selection
3643 scene = context .scene
3744 currentFrame = scene .frame_current
@@ -76,31 +83,47 @@ def cameras_to_string(context, startFrame, endFrame, cameras, translation_scale
7683 translation_z .append (- translation_scale * posDiffLocal .z )
7784
7885 rotDiff = oldRot .rotation_difference (newRot ).to_euler ("XYZ" )
86+
7987 rotation_3d_x .append (degrees (rotDiff .x ))
80- rotation_3d_y .append (degrees (rotDiff .y ))
81- rotation_3d_z .append (degrees (rotDiff .z ))
88+ rotation_3d_y .append (degrees (- rotDiff .y ))
89+ rotation_3d_z .append (degrees (- rotDiff .z ))
8290
8391 oldMat = newMat
8492 oldRot = newRot
8593
8694 #Done looping over frames, now to format for print
8795 export_string += f"\n Camera Export: { sel .name } \n "
88-
96+
97+
8998 export_string += f'translation_x = "{ arr_to_keyframes (translation_x )} " #@param {{type:"string"}}\n '
9099 export_string += f'translation_y = "{ arr_to_keyframes (translation_y )} " #@param {{type:"string"}}\n '
91100 export_string += f'translation_z = "{ arr_to_keyframes (translation_z )} " #@param {{type:"string"}}\n '
92101 export_string += f'rotation_3d_x = "{ arr_to_keyframes (rotation_3d_x )} " #@param {{type:"string"}}\n '
93102 export_string += f'rotation_3d_y = "{ arr_to_keyframes (rotation_3d_y )} " #@param {{type:"string"}}\n '
94103 export_string += f'rotation_3d_z = "{ arr_to_keyframes (rotation_3d_z )} " #@param {{type:"string"}}\n '
104+
105+ if output_camcode :
106+ export_string += f'cam_code:\n (translation_x,translation_y,translation_z,rotation_3d_x,rotation_3d_y,rotation_3d_z) = ("{ arr_to_keyframes (translation_x )} ", "{ arr_to_keyframes (translation_y )} ", "{ arr_to_keyframes (translation_z )} ", "{ arr_to_keyframes (rotation_3d_x )} ", "{ arr_to_keyframes (rotation_3d_y )} ", "{ arr_to_keyframes (rotation_3d_z )} ")\n '
107+
108+ if output_json :
109+ jsondict = {
110+ "translation_x" : translation_x ,
111+ "translation_y" : translation_y ,
112+ "translation_z" : translation_z ,
113+ "rotation_3d_x" : rotation_3d_x ,
114+ "rotation_3d_y" : rotation_3d_y ,
115+ "rotation_3d_z" : rotation_3d_z }
116+ export_string += f"JSON:\n { json .dumps (jsondict )} \n "
117+
95118 export_string += "\n "
96119
97120 #Done saving all cameras, restore original animation frame
98121 scene .frame_set (currentFrame )
99122 return export_string
100123
101- def write_camera_data (context , filepath , start , end , cams , scale ):
124+ def write_camera_data (context , filepath , start , end , cams , scale , output_camcode , output_json ):
102125 print ("running write_camera_data..." )
103- outputString = cameras_to_string (context , start , end , cams , scale )
126+ outputString = cameras_to_string (context , start , end , cams , scale , output_camcode , output_json )
104127 with open (filepath , 'w' , encoding = 'utf-8' ) as f :
105128 f .write (f"Export frames { start } - { end } \n " )
106129 f .write (f"Export cameras { [c .name for c in cams ]} \n " )
@@ -139,8 +162,11 @@ class ExportDiffusionString(Operator, ExportHelper):
139162# default='3D',
140163# )
141164
142- frame_start : IntProperty (name = "Start" , default = 0 )
143- frame_end : IntProperty (name = "End" , default = 100 )#bpy.context.scene.frame_end
165+ output_json : BoolProperty (name = "Output JSON" , default = False )
166+ output_cam_code : BoolProperty (name = "Output cam_code" , default = True )
167+
168+ frame_start : IntProperty (name = "Start" , default = - 1 )
169+ frame_end : IntProperty (name = "End" , default = - 1 )#bpy.context.scene.frame_end
144170
145171 which_cams : EnumProperty (
146172 name = "Which Cams" ,
@@ -167,8 +193,10 @@ def draw(self, context):
167193
168194 row = layout .row ()
169195 row .label (text = "Frames" )
170- self .frame_start = bpy .context .scene .frame_start
171- self .frame_end = bpy .context .scene .frame_end
196+ if self .frame_start == - 1 :
197+ self .frame_start = bpy .context .scene .frame_start
198+ if self .frame_end == - 1 :
199+ self .frame_end = bpy .context .scene .frame_end
172200 row .prop (self , "frame_start" )
173201 row .prop (self , "frame_end" )
174202
@@ -177,6 +205,11 @@ def draw(self, context):
177205 row = layout .row ()
178206 row .prop (self , "translation_scale" )
179207
208+ row = layout .row ()
209+ row .prop (self , "output_cam_code" )
210+ row = layout .row ()
211+ row .prop (self , "output_json" )
212+
180213 def execute (self , context ):
181214 export_cams = []
182215 if self .which_cams == "ACTIVE" :
@@ -185,7 +218,8 @@ def execute(self, context):
185218 export_cams = [cam for cam in context .selected_objects if cam .type == 'CAMERA' ]
186219 elif self .which_cams == "ALL" :
187220 export_cams = [cam for cam in context .scene .objects if cam .type == 'CAMERA' ]
188- return write_camera_data (context , self .filepath , self .frame_start , self .frame_end , export_cams , self .translation_scale )
221+ return write_camera_data (context , self .filepath , self .frame_start , self .frame_end , export_cams ,
222+ self .translation_scale , self .output_cam_code , self .output_json )
189223
190224
191225# Only needed if you want to add into a dynamic menu
0 commit comments