Skip to content

Instantly share code, notes, and snippets.

@p2or
Last active January 19, 2024 09:37
Show Gist options
  • Save p2or/5560c142fcb14716c6ac490a1d9bfb6e to your computer and use it in GitHub Desktop.
Save p2or/5560c142fcb14716c6ac490a1d9bfb6e to your computer and use it in GitHub Desktop.
Export Camera to BMD Fusion [Blender 2.8x] from https://blenderartists.org/t/addon-export-camera-to-bmd-fusion #BlenderArtists
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Export Fusion Composition",
"author": "Michael Vorberg, Christian Brinkmann",
"version": (0, 6, 0),
"blender": (2, 80, 0),
"location": "File > Export > Fusion Comp (.comp)",
"description": "Export Cameras and PointClouds of motion tracking into a Fusion Composition(.comp)",
"warning": "",
"category": "Import-Export",
}
import bpy
from bpy_extras.io_utils import ExportHelper, axis_conversion
import math
import mathutils
import os
def write_cameras(context, filepath, frame_start, frame_end, only_selected=False):
data_attrs = (
'lens',
'shift_x',
'shift_y',
'dof_distance',
'clip_start',
'clip_end',
'draw_size',
)
scene = context.scene
bl_display_colorspace = scene.display_settings.display_device
#print (bl_display_colorspace)
fu_display_colorspace = ""
try:
if bl_display_colorspace == "sRGB":
fu_display_colorspace = "sRGB"
elif bl_display_colorspace == "Rec709":
fu_display_colorspace = "Rec709Display"
elif bl_display_colorspace == "XYZ":
fu_display_colorspace = "DCI"
elif bl_display_colorspace == "None":
fu_display_colorspace = "No Change"
elif bl_display_colorspace == "Filmic":
fu_display_colorspace = ""
elif bl_display_colorspace == "sRGB / BT.709":
fu_display_colorspace = "sRGB"
except:
fu_display_colorspace = ""
rot_x_neg90 = mathutils.Matrix.Rotation(-math.pi/2.0, 4, 'X')
obj_attrs = (
'hide_render',
)
with open(filepath, "w") as fw:
cameras = []
for obj in scene.objects:
if only_selected and not obj.select_get():
continue
if obj.type != 'CAMERA':
continue
cameras.append((obj, obj.data))
if len(cameras) == 0:
raise RuntimeError("no camera selected but \"only selected\" activated")
# write some settings for the composition
frame_range = range(frame_start, frame_end + 1)
fw.write("Composition {\n"
" CurrentTime = 0,\n")
fw.write(" RenderRange = { %d, %d, },\n"%(frame_start, frame_end))
fw.write(" GlobalRange = { %d, %d, },\n"%(frame_start, frame_end))
fw.write("""Prefs = {
Comp = {
Views = {
Right = {
Viewer = {
EnableLUTs = true,
LUTPlugin = "GamutViewLUT",
LUTSelected = "Gamut View LUT",
},
ViewLUT = {
{
Tools = ordered() {
GamutViewLUT1 = ViewOperator {
CtrlWZoom = false,
NameSet = true,
Inputs = {""")
fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace)
fw.write(""" },
},
},
ID = "GamutViewLUT",
},
SelectedPlugin = "GamutViewLUT",
SelectedName = "Gamut View LUT",
},
},
Left = {
Viewer = {
EnableLUTs = true,
LUTPlugin = "GamutViewLUT",
LUTSelected = "Gamut View LUT",
},
ViewLUT = {
{
Tools = ordered() {
GamutViewLUT = ViewOperator {
CtrlWZoom = false,
NameSet = true,
Inputs = {""")
fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace)
fw.write(""" },
},
},
ID = "GamutViewLUT",
},
SelectedPlugin = "GamutViewLUT",
SelectedName = "Gamut View LUT",
},
},
View1 = {
},
},
FrameFormat = {
Name = "Multimedia", """)
fw.write("Width = %d,\n"%(scene.render.resolution_x))
fw.write("Height = %d,\n"%(scene.render.resolution_y))
fw.write("Rate = %d,\n"%(scene.render.fps))
fw.write("""PerFeet = 1,
GuideRatio = 1.77777777777778,
},
},
Views = {
Right = {
SideB = {
PrevCtrlInactiveColor = 65280,
PickW = 1,
PickH = 1,
PrevCtrlActiveColor = 255,
Viewer = {
EnableLUTs = false,
LUTPlugin = "FusionViewLUT",
FitMarginY = 0,
FitMarginX = 0,
FitMarginType = 0,
FarZ = -1000,
NearZ = 0,
},
},
Viewer = {
EnableLUTs = true,
LUTPlugin = "GamutViewLUT",
LUTSelected = "Gamut View LUT",
},
ViewLUT = {
{
Tools = ordered() {
GamutViewLUT1 = ViewOperator {
NameSet = true,
Inputs = {""")
fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace)
fw.write(""" },
CtrlWZoom = false,
},
},
ID = "GamutViewLUT",
},
Recent = {
SelectedPlugin = "GamutViewLUT",
FusionViewLUT = {
Tools = ordered() {
FusionViewLUT = ViewLUTOp {
NameSet = true,
Inputs = {
},
},
},
},
SelectedName = "Gamut View LUT",
},
SelectedName = "Gamut View LUT",
SelectedPlugin = "GamutViewLUT",
},
},
Left = {
SideB = {
PrevCtrlInactiveColor = 65280,
PickW = 1,
PickH = 1,
PrevCtrlActiveColor = 255,
Viewer = {
EnableLUTs = false,
LUTPlugin = "FusionViewLUT",
FitMarginY = 0,
FitMarginX = 0,
FitMarginType = 0,
FarZ = -1000,
NearZ = 0,
},
},
Viewer = {
EnableLUTs = true,
LUTPlugin = "GamutViewLUT",
LUTSelected = "Gamut View LUT",
},
ViewLUT = {
{
Tools = ordered() {
GamutViewLUT = ViewOperator {
NameSet = true,
Inputs = {""")
fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace)
fw.write(""" },
CtrlWZoom = false,
},
},
ID = "GamutViewLUT",
},
SelectedPlugin = "GamutViewLUT",
SelectedName = "Gamut View LUT",
},
},
View1 = {
PrevCtrlInactiveColor = 0,
PickW = 1,
PickH = 1,
PrevCtrlActiveColor = 0,
SideB = {
PrevCtrlInactiveColor = 65280,
PickW = 1,
PickH = 1,
PrevCtrlActiveColor = 255,
Viewer = {
EnableLUTs = false,
LUTPlugin = "FusionViewLUT",
FitMarginY = 0,
FitMarginX = 0,
FitMarginType = 0,
FarZ = -1000,
NearZ = 0,
},
},
},
},
},
""")
# starting with the actual nodes
fw.write("Tools = {\n")
# look if we have a clip in the scene and create a loader node for it
try:
if bpy.data.movieclips[0]:
fw.write("""Loader1 = Loader {
Clips = {
Clip {
ID = "Clip1",\n""")
clip_filepath = os.path.normpath(bpy.data.movieclips[0].filepath)
clip_filepath_four_slashes = clip_filepath.replace("\\", "\\\\")
fw.write("Filename = \" %s \",\n"%(clip_filepath_four_slashes))
fw.write("StartFrame = %d,\n"%(frame_start))
fw.write("Length = %d,\n"%(frame_end))
fw.write("LengthSetManually = true,\n")
fw.write("TrimIn = %d,\n"%(frame_start-1))
fw.write("TrimOut = %d,\n"%(frame_end-1))
fw.write("""ExtendFirst = 0,
ExtendLast = 0,
Loop = 1,
AspectMode = 0,
Depth = 0,
TimeCode = 0,""")
fw.write("GlobalStart = %d,\n"%(frame_start))
fw.write("GlobalEnd = %d,\n"%(frame_end))
fw.write("""},
},
ViewInfo = OperatorInfo { Pos = { 300, 0, }, },
CtrlWZoom = false,
},
Gamut1 = GamutConvert {
Inputs = {
SourceSpace = Input { Value = FuID { "sRGB", }, },
Input = Input {
SourceOp = "Loader1",
Source = "Output",
},
},
ViewInfo = OperatorInfo { Pos = { 300, 100, }, },
},""")
except:
print("No clip found for Loader")
# create Camera3D nodes
try:
for obj, obj_data in cameras:
fw.write(" Camera3D_%s = Camera3D {\n" %obj_data.name.replace(".", "_").replace(".", "_"))
fw.write(" CtrlWZoom = false,\n"
" Inputs = {\n"
" [\"PerspNearClip\"] = Input {\n"
" SourceOp = \"Camera3D_%s_PerspNearClip\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"PerspFarClip\"] = Input {\n"
" SourceOp = \"Camera3D_%s_PerspFarClip\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"FLength\"] = Input {\n"
" SourceOp = \"Camera3D_%s_LensFlength\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"PlaneOfFocus\"] = Input {\n"
" SourceOp = \"Camera3D_%s_PlaneOfFocus\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"Transform3DOp.Translate.X\"] = Input {\n"
" SourceOp = \"Camera3D_%s_XOffset\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"Transform3DOp.Translate.Y\"] = Input {\n"
" SourceOp = \"Camera3D_%s_YOffset\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n"
" },\n"
" [\"Transform3DOp.Translate.Z\"] = Input {\n"
" SourceOp = \"Camera3D_%s_ZOffset\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n")
fw.write(" },\n"
" [\"Transform3DOp.Rotate.X\"] = Input {\n"
" SourceOp = \"Camera3D_%s_XRotation\",\n"%obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n")
fw.write(" },\n"
" [\"Transform3DOp.Rotate.Y\"] = Input {\n"
" SourceOp = \"Camera3D_%s_YRotation\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n")
fw.write(" },\n"
" [\"Transform3DOp.Rotate.Z\"] = Input {\n"
" SourceOp = \"Camera3D_%s_ZRotation\",\n" %obj_data.name.replace(".", "_"))
fw.write(" Source = \"Value\",\n")
fw.write(" },\n")
fw.write(" [\"Stereo.Mode\"] = Input { Value = FuID { \"Mono\", }, },\n"
" FilmBack = Input { Value = 1, },\n"
" FilmGate = Input { Value = FuID { \"User\", }, },\n")
fw.write(" LensShiftX = Input { Value = %r, },\n" %(-obj_data.shift_x))
fw.write(" LensShiftY = Input { Value = %r, },\n" %(-obj_data.shift_y*(scene.render.resolution_x/scene.render.resolution_y)))
ap_w = float(obj_data.sensor_width) / 25.4
fw.write(" ApertureW = Input { Value = %s, },\n" %str(ap_w))
ap_h = ap_w/(scene.render.resolution_x/scene.render.resolution_y)
fw.write(" ApertureH = Input { Value = %s, },\n" %str(ap_h))
if obj_data.sensor_fit == "HORIZONTAL":
fw.write(" AovType = Input { Value = 1, },\n")
if obj_data.sensor_fit == "VERTICAL":
fw.write(" AovType = Input { Value = 0, },\n")
fw.write(''' [\"SurfacePlaneInputs.ObjectID.ObjectID\"] = Input { Value = 1, },\n
[\"MtlStdInputs.MaterialID\"] = Input { Value = 1, },\n
},\n
ViewInfo = OperatorInfo { Pos = { 0, 100, }, },
},\n'''
)
fw.write(" Camera3D_%s_XOffset = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(''' NameSet = true,\n
KeyFrames = {\n''')
# X Translation
for f in frame_range:
scene.frame_set(f)
matrix = obj.matrix_world.copy()
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, matrix.to_translation()[0]))
fw.write(" },\n"
"},\n")
# Y Translation (Fusion Y)
fw.write(" Camera3D_%s_YOffset = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
matrix = obj.matrix_world.copy()
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, matrix.to_translation()[2]))
fw.write(" },\n"
"},\n")
# Z Translation (Fusion Z)
fw.write(" Camera3D_%s_ZOffset = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
matrix = obj.matrix_world.copy()
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, -matrix.to_translation()[1]))
fw.write(" },\n"
"},\n")
# X Rotation (Fusion X)
fw.write(" Camera3D_%s_XRotation = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
matrix_org = obj.matrix_world.copy()
matrix = rot_x_neg90 * matrix_org
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, (math.degrees(matrix.to_euler()[0]))))
fw.write(" },\n"
"},\n")
# Y Rotation (Fusion Y)
fw.write(" Camera3D_%s_YRotation = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
matrix_org = obj.matrix_world.copy()
matrix = rot_x_neg90 * matrix_org
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, math.degrees(matrix.to_euler()[1])))
fw.write(" },\n"
"},\n")
# Z Rotation (Fusion Z)
fw.write(" Camera3D_%s_ZRotation = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
matrix_org = obj.matrix_world.copy()
matrix = rot_x_neg90 * matrix_org
fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, math.degrees(matrix.to_euler()[2])))
fw.write(" },\n"
"},\n")
fw.write(" Camera3D_%s_LensFlength = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.lens))
fw.write(" },\n"
"},\n")
fw.write(" Camera3D_%s_PlaneOfFocus = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.dof_distance))
fw.write(" },\n"
"},\n")
fw.write(" Camera3D_%s_PerspNearClip = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(" NameSet = true,\n"
" KeyFrames = {\n")
for f in frame_range:
scene.frame_set(f)
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.clip_start))
fw.write(" },\n"
"},\n")
fw.write(" Camera3D_%s_PerspFarClip = BezierSpline {\n" %obj_data.name.replace(".", "_"))
fw.write(''' NameSet = true,\n
KeyFrames = {\n''')
for f in frame_range:
scene.frame_set(f)
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.clip_end))
fw.write(''' },\n
},\n''')
obj.select_set(False)
except:
print("No camera found/selected")
# write pointcloud3D node
# look if we have a clip in the scene
try:
if bpy.data.movieclips[0]:
fw.write('''
PointCloud3D1 = PointCloud3D {\n
CtrlWZoom = false,\n
ViewInfo = OperatorInfo { Pos = { 150, 0, }, },\n
Positions = {\n
Version = 0,\n
''')
curr_clip = bpy.data.movieclips[0]
zeroPosition = [0, 0, 0]
sceneCamera = bpy.data.objects['Camera']
track_list = []
for track in curr_clip.tracking.tracks:
if track.has_bundle is False:
continue
track_list.append(track)
for track in track_list:
track_name = track.name
bpy.ops.object.add(type='EMPTY',location = [0, 0, 0])
current_obj = context.active_object
bpy.ops.object.constraint_add(type="FOLLOW_TRACK")
context.object.constraints["Follow Track"].use_3d_position = True
context.object.constraints["Follow Track"].object = "Camera"
context.object.constraints["Follow Track"].track = track_name
context.object.constraints["Follow Track"].camera = sceneCamera
current_obj_data = bpy.data.objects[current_obj.name]
current_obj_data.name = track_name
print ("created object: ", current_obj_data.name)
i = 0
for track in track_list:
track_name = track.name
current_obj = context.active_object
current_obj_data = bpy.data.objects[track_name]
obj_name_matrix = current_obj_data.matrix_world.copy()
fw.write(
"[%d] = { %r, %r, %r, \"%s\", \"\", },\n" % (
i, obj_name_matrix.to_translation()[0],
obj_name_matrix.to_translation()[2],
-obj_name_matrix.to_translation()[1],
track_name
)
)
i += 1
current_obj_data.select_set(True)
# delete all helper tracks
bpy.ops.object.delete(use_global=False)
# close pointcloud3D and create Merge3D
fw.write(''' },\n
},\n
Merge3D1 = Merge3D {
Inputs = {
SceneInput1 = Input {''')
try:
if not obj_data.name:
fw.write("SourceOp = \"Camera3D_%s\",\n" % obj_data.name.replace(".", "_").replace(".", "_"))
else:
fw.write("SourceOp = \"\",\n")
except:
raise RuntimeError("no camera selected")
fw.write('''Source = \"Output\",
},
SceneInput2 = Input {
SourceOp = \"PointCloud3D1\",
Source = \"Output\",
},
},
ViewInfo = OperatorInfo { Pos = { 151, 100, }, },
},''')
except:
print("No clip found")
try:
if bpy.data.movieclips[0]:
#create2d trackers
print ("trying 2d tracks")
curr_clip = bpy.data.movieclips[0]
track_list = []
for track in curr_clip.tracking.tracks:
if track.has_bundle is False:
continue
track_list.append(track)
fw.write("""
Tracker1 = Tracker {
Trackers = {
""")
for track in track_list:
track_name = track.name.replace(".", "_")
track_name_orig = track.name
fw.write("""{
PatternTime = 1,
PatternX = 0.392840626111704,
PatternY = 0.699857685009488,
},""")
fw.write("""},
CtrlWZoom = false,
Inputs = {TrackerList = Input { Value = 1, },""")
i = 0
for track in track_list:
track_name = track.name.replace(".", "_")
track_name_orig = track.name
i += 1
fw.write("Name%d = Input { Value = \"%s\", }," %(i, track_name))
fw.write("PatternCenter%d = Input { Value = { %r, %r, }, },"% (
i, bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers[0].co.x,
bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers[0].co.y)
)
fw.write("PatternWidth%d = Input { Value = 0.0154571326929918, },"%i)
fw.write("PatternHeight%d = Input { Value = 0.020841239721695, },"%i)
fw.write("SearchWidth%d = Input { Value = 0.0574350764852365, },"%i)
fw.write("SearchHeight%d = Input { Value = 0.0714421252371915, }," %i)
fw.write("TrackedCenter%d = Input {" %i)
fw.write("SourceOp = \"Tracker1%sXYPath\"," %track_name)
fw.write("""Source = "Value",
},
""")
fw.write("""},\n ViewInfo = OperatorInfo { Pos = { 500, 0, }, },
},""")
for track in track_list:
track_name = track.name.replace(".", "_")
track_name_orig = track.name
print ("creating animation for 2d tracker: ", track_name)
fw.write("Tracker1%sXYPath = XYPath {" %track_name)
fw.write("""ShowKeyPoints = false,
DrawMode = "ModifyOnly",
CtrlWZoom = false,
NameSet = true,
Inputs = {
X = Input {""")
fw.write("SourceOp = \"XYPath_%sX\"," %track_name)
fw.write("""Source = "Value",
},
Y = Input {""")
fw.write("SourceOp = \"XYPath_%sY\"," %track_name)
fw.write("""Source = "Value",
},
},
},
""")
fw.write("XYPath_%sX = BezierSpline {" %track_name)
fw.write("""SplineColor = { Red = 255, Green = 0, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for f in frame_range:
marker_at_frame = bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers.find_frame(f)
if not marker_at_frame:
continue
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, marker_at_frame.co.x))
fw.write(""" },\n
},\n""")
fw.write("XYPath_%sY = BezierSpline {" %track_name)
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for f in frame_range:
marker_at_frame = bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers.find_frame(f)
if not marker_at_frame:
continue
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, marker_at_frame.co.y))
fw.write(""" },\n
},\n""")
#create lens distortion node
fw.write("""LensDistort1 = LensDistort {
CtrlWZoom = false,
Inputs = {
LensDistortionModel = Input { Value = 1, },
Model = Input { Value = FuID { "PFTrack", }, },\n""")
fw.write("[\"PFTrack.LowOrderDistortion\"] = Input { Value = %r, },\n" %-bpy.data.movieclips[0].tracking.camera.k1)
fw.write("[\"PFTrack.HighOrderDistortion\"] = Input { Value = %r, },\n" %-bpy.data.movieclips[0].tracking.camera.k2)
fw.write("[\"PFTrack.LensCenterX\"] = Input { Value = %r, },\n" % (bpy.data.movieclips[0].tracking.camera.principal[0]/bpy.data.movieclips[0].size[0]))
fw.write("[\"PFTrack.LensCenterY\"] = Input { Value = %r, },\n" %(bpy.data.movieclips[0].tracking.camera.principal[1]/bpy.data.movieclips[0].size[1]))
fw.write("""},
ViewInfo = OperatorInfo { Pos = { 700, 0, }, },
},
""")
except:
print("No clip found")
try:
if bpy.data.movieclips[0]:
curr_clip = bpy.data.movieclips[0]
plane_track_list = []
for plane_track in curr_clip.tracking.plane_tracks:
plane_track_list.append(plane_track)
if len(plane_track_list)>0:
for i,track in enumerate(plane_track_list):
track_name = track.name.replace(".", "_")
track_name_orig = track.name
fw.write("CornerPositioner%d = CornerPositioner {" %i)
fw.write('''Inputs = {
TopLeft = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath\"," %i)
fw.write('''Source = "Value",
},
TopRight = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath\"," %i)
fw.write('''Source = "Value",
},
BottomLeft = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath\"," %i)
fw.write('''Source = "Value",
},
BottomRight = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath\"," %i)
fw.write('''Source = "Value",
},
},''')
toolPos = 900+i*100
fw.write("ViewInfo = OperatorInfo { Pos = { %d, 0, }, }," %toolPos)
fw.write('''},''')
fw.write("PlaneTrack%dTrack1XYPath = XYPath {" %i)
fw.write('''ShowKeyPoints = false,
DrawMode = "InsertAndModify",
NameSet = true,
Inputs = {
X = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath%dX\"," %(i,i))
fw.write('''Source = "Value",
},
Y = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath%dY\"," %(i,i))
fw.write('''Source = "Value",
},
},
},''')
fw.write("PlaneTrack%dTrack2XYPath = XYPath {" %i)
fw.write('''ShowKeyPoints = false,
DrawMode = "InsertAndModify",
NameSet = true,
Inputs = {
X = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath%dX\"," %(i,i))
fw.write('''Source = "Value",
},
Y = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath%dY\"," %(i,i))
fw.write('''Source = "Value",
},
},
},''')
fw.write("PlaneTrack%dTrack3XYPath = XYPath {" %i)
fw.write('''ShowKeyPoints = false,
DrawMode = "InsertAndModify",
NameSet = true,
Inputs = {
X = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath%dX\"," %(i,i))
fw.write('''Source = "Value",
},
Y = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath%dY\"," %(i,i))
fw.write('''Source = "Value",
},
},
},''')
fw.write("PlaneTrack%dTrack4XYPath = XYPath {" %i)
fw.write('''ShowKeyPoints = false,
DrawMode = "InsertAndModify",
NameSet = true,
Inputs = {
X = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath%dX\"," %(i,i))
fw.write('''Source = "Value",
},
Y = Input {''')
fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath%dY\"," %(i,i))
fw.write('''Source = "Value",
},
},
},''')
fw.write("PlaneTrack%dTrack1XYPath%dX = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[3][0]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack1XYPath%dY = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[3][1]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack2XYPath%dX = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[2][0]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack2XYPath%dY = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[2][1]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack3XYPath%dX = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[0][0]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack3XYPath%dY = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[0][1]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack4XYPath%dX = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[1][0]))
fw.write(""" },\n
},\n""")
fw.write("PlaneTrack%dTrack4XYPath%dY = BezierSpline {" %(i,i))
fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, },
NameSet = true,
KeyFrames = {
""")
for j, marker in enumerate(track.markers):
fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[1][1]))
fw.write(""" },\n
},\n""")
fw.write("""
Tracker2 = Tracker {
Trackers = {
""")
fw.write("""{
PatternTime = 1,
PatternX = 0.392840626111704,
PatternY = 0.699857685009488,
},\n
{
PatternTime = 1,
PatternX = 0.392840626111704,
PatternY = 0.699857685009488,
},\n
{
PatternTime = 1,
PatternX = 0.392840626111704,
PatternY = 0.699857685009488,
},\n
{
PatternTime = 1,
PatternX = 0.392840626111704,
PatternY = 0.699857685009488,
},\n
""")
fw.write("""},
CtrlWZoom = false,
Inputs = {TrackerList = Input { Value = 2, },""")
fw.write("Name1 = Input { Value = \"PlaneTrack1\", }," )
fw.write("PatternCenter1 = Input { Value = { %r, %r, }, },"%( marker.corners[0][0],marker.corners[0][1]))
fw.write("PatternWidth1 = Input { Value = 0.0154571326929918, },")
fw.write("PatternHeight1 = Input { Value = 0.020841239721695, },")
fw.write("SearchWidth1 = Input { Value = 0.0574350764852365, },")
fw.write("SearchHeight1 = Input { Value = 0.0714421252371915, },")
fw.write("TrackedCenter1 = Input {" )
fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath\"," %i)
fw.write("""Source = "Value",
},
""")
fw.write("Name2 = Input { Value = \"PlaneTrack2\", }," )
fw.write("PatternCenter2 = Input { Value = { %r, %r, }, },"%( marker.corners[1][0],marker.corners[1][1]))
fw.write("PatternWidth2 = Input { Value = 0.0154571326929918, },")
fw.write("PatternHeight2 = Input { Value = 0.020841239721695, },")
fw.write("SearchWidth2 = Input { Value = 0.0574350764852365, },")
fw.write("SearchHeight2 = Input { Value = 0.0714421252371915, },")
fw.write("TrackedCenter2 = Input {" )
fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath\"," %i)
fw.write("""Source = "Value",
},
""")
fw.write("Name3 = Input { Value = \"PlaneTrack3\", }," )
fw.write("PatternCenter3 = Input { Value = { %r, %r, }, },"%( marker.corners[2][0],marker.corners[2][1]))
fw.write("PatternWidth3 = Input { Value = 0.0154571326929918, },")
fw.write("PatternHeight3 = Input { Value = 0.020841239721695, },")
fw.write("SearchWidth3 = Input { Value = 0.0574350764852365, },")
fw.write("SearchHeight3 = Input { Value = 0.0714421252371915, },")
fw.write("TrackedCenter3 = Input {" )
fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath\"," %i)
fw.write("""Source = "Value",
},
""")
fw.write("Name4 = Input { Value = \"PlaneTrack4\", }," )
fw.write("PatternCenter4 = Input { Value = { %r, %r, }, },"%( marker.corners[3][0],marker.corners[3][1]))
fw.write("PatternWidth4 = Input { Value = 0.0154571326929918, },")
fw.write("PatternHeight4 = Input { Value = 0.020841239721695, },")
fw.write("SearchWidth4 = Input { Value = 0.0574350764852365, },")
fw.write("SearchHeight4 = Input { Value = 0.0714421252371915, },")
fw.write("TrackedCenter4 = Input {" )
fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath\"," %i)
fw.write("""Source = "Value",
},
""")
##toolPosTracker = 1200+i*100
fw.write("ViewInfo = OperatorInfo { Pos = { %d, 100 } }," %toolPos)
fw.write("""
},},""")
i += 1
except:
print("No clip found plane_track")
# close composition
fw.write(" },\n}\n")
fw.close()
print("finished export to fusion comp")
# ------------------------------------------------------------------------
# Export Operator
# ------------------------------------------------------------------------
class EXPORT_OT_fusionComp(bpy.types.Operator, ExportHelper):
"""Save a python script which re-creates cameras and markers elsewhere"""
bl_idname = "export_scene.fusion_comp"
bl_label = "Export Fusion Composition"
filename_ext = ".comp"
filter_glob: bpy.props.StringProperty(
default="*.comp",
options={'HIDDEN'}
)
frame_start: bpy.props.IntProperty(
name="Start Frame",
description="Start frame for export",
default=1,
min=0, max=300000
)
frame_end: bpy.props.IntProperty(
name="End Frame",
description="End frame for export",
default=250,
min=1, max=300000
)
only_selected: bpy.props.BoolProperty(
name="Only Selected",
default=False
)
def execute(self, context):
write_cameras(context, self.filepath, self.frame_start, self.frame_end, self.only_selected)
return {'FINISHED'}
def invoke(self, context, event):
self.frame_start = context.scene.frame_start
self.frame_end = context.scene.frame_end
wm = context.window_manager
wm.fileselect_add(self)
return {'RUNNING_MODAL'}
def draw_fusion_export_menu(self, context):
default_path = os.path.splitext(bpy.data.filepath)[0] + ".comp"
self.layout.operator(
EXPORT_OT_fusionComp.bl_idname,
text="Fusion Composition (.comp)"
).filepath = default_path
# ------------------------------------------------------------------------
# Registration
# ------------------------------------------------------------------------
def register():
bpy.utils.register_class(EXPORT_OT_fusionComp)
bpy.types.TOPBAR_MT_file_export.append(draw_fusion_export_menu)
def unregister():
bpy.types.TOPBAR_MT_file_export.remove(draw_fusion_export_menu)
bpy.utils.unregister_class(EXPORT_OT_fusionComp)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment