Skip to content

Commit 9c2bf1c

Browse files
Merge remote-tracking branch 'origin/blender_issue62' into develop_v0.3.x
2 parents d0f722a + 68fb492 commit 9c2bf1c

9 files changed

Lines changed: 763 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@ if (BUILD_PYTHON)
570570
add_subdirectory(python)
571571
endif ()
572572

573+
add_subdirectory(blender)
574+
573575
if (BUILD_DOCS)
574576
add_subdirectory(docs)
575577
endif ()

blender/CMakeLists.txt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright (C) 2021 David Cattermole.
2+
#
3+
# This file is part of mmSolver.
4+
#
5+
# mmSolver is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as
7+
# published by the Free Software Foundation, either version 3 of the
8+
# License, or (at your option) any later version.
9+
#
10+
# mmSolver is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
17+
# ---------------------------------------------------------------------
18+
#
19+
# Generate and install the mmSolver addon for Blender.
20+
#
21+
22+
function(zip_up_blender_addon
23+
name
24+
input_directory
25+
output_file
26+
working_dir)
27+
add_custom_command(
28+
COMMAND ${CMAKE_COMMAND} -E tar "cf" "${output_file}" --format=zip -- ${input_directory}
29+
WORKING_DIRECTORY "${working_dir}"
30+
OUTPUT "${output_file}"
31+
DEPENDS ${input_files}
32+
COMMENT "Zipping ${name} to ${output_file}."
33+
)
34+
add_custom_target(
35+
create_zip_${name} ALL
36+
DEPENDS ${output_file}
37+
COMMENT "Zipping ${name}"
38+
)
39+
endfunction()
40+
41+
zip_up_blender_addon(
42+
mmSolver_blender_addon
43+
${CMAKE_CURRENT_SOURCE_DIR}/mmSolver_blender_addon
44+
${CMAKE_CURRENT_SOURCE_DIR}/mmSolver_blender_addon.zip
45+
${CMAKE_CURRENT_SOURCE_DIR}
46+
)
47+
48+
# Install Blender addon.
49+
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/mmSolver_blender_addon.zip"
50+
DESTINATION "${MODULE_FULL_NAME}/blender/")
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright (C) 2021 David Cattermole.
2+
#
3+
# This file is part of mmSolver.
4+
#
5+
# mmSolver is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as
7+
# published by the Free Software Foundation, either version 3 of the
8+
# License, or (at your option) any later version.
9+
#
10+
# mmSolver is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
17+
#
18+
19+
bl_info = {
20+
'name': 'MM Solver Blender Tools',
21+
'author': 'David Cattermole',
22+
'version': (0, 1, 0),
23+
'blender': (2, 80, 0),
24+
'location': 'Motion Clip Editor > Sidebar and File > Export > Export Selected 2D Tracks (MM Solver .uv)',
25+
'description': 'Tools to use mmSolver with Blender',
26+
'warning': '',
27+
'doc_url': 'https://david-cattermole.github.io/mayaMatchMoveSolver/index.html',
28+
'support': 'COMMUNITY',
29+
'category': 'Import-Export',
30+
}
31+
32+
33+
def register():
34+
from . import mmsolver_2d_tracks_export
35+
from . import mmsolver_2d_tracks_copy
36+
from . import mmsolver_panel
37+
mmsolver_2d_tracks_export.register()
38+
mmsolver_2d_tracks_copy.register()
39+
mmsolver_panel.register()
40+
41+
42+
def unregister():
43+
from . import mmsolver_2d_tracks_export
44+
from . import mmsolver_2d_tracks_copy
45+
from . import mmsolver_panel
46+
mmsolver_2d_tracks_export.unregister()
47+
mmsolver_2d_tracks_copy.unregister()
48+
mmsolver_panel.unregister()
49+
50+
51+
if __name__ == '__main__':
52+
register()
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Copyright (C) 2021 David Cattermole.
2+
#
3+
# This file is part of mmSolver.
4+
#
5+
# mmSolver is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as
7+
# published by the Free Software Foundation, either version 3 of the
8+
# License, or (at your option) any later version.
9+
#
10+
# mmSolver is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
17+
#
18+
"""
19+
Copy 2D Tracks from Blender, as .uv format.
20+
"""
21+
22+
import bpy
23+
24+
from . import uvtrack_format_blender as uv_fmt
25+
from . import utils
26+
27+
28+
class MmSolver_OT_copySelectedMarkers(bpy.types.Operator):
29+
"""Save a temporary .uv file for 2D Tracks."""
30+
bl_idname = 'mmsolver.copy_selected_markers'
31+
bl_label = 'Copy Markers'
32+
33+
def invoke(self, context, event):
34+
clip, cam, tracks = utils.get_selected_clip_objects(context)
35+
if clip is None or cam is None or tracks is None:
36+
msg = (
37+
'mmSolver: Copy 2D Tracks: '
38+
'Please select 2D Tracks in the Movie Clip Editor. '
39+
'Could not get selected 2D Tracks.'
40+
)
41+
self.report({'WARNING'}, msg)
42+
return {'CANCELLED'}
43+
44+
start_frame = clip.frame_start
45+
end_frame = start_frame + clip.frame_duration
46+
frame_range = (start_frame, end_frame)
47+
48+
data_str = uv_fmt.generate(
49+
context,
50+
clip, cam, tracks,
51+
frame_range,
52+
fmt=uv_fmt.UV_TRACK_FORMAT_VERSION_PREFERRED)
53+
if data_str is None or len(data_str) == 0:
54+
msg = 'mmSolver: Copy 2D Tracks: Could not generate file data.'
55+
self.report({'ERROR'}, msg)
56+
return {'FINISHED'}
57+
58+
file_path = utils.write_text_data_to_temp_file(data_str)
59+
if file_path is None or len(file_path) == 0:
60+
msg = 'mmSolver: Copy 2D Tracks: Could not write file data.'
61+
self.report({'ERROR'}, msg)
62+
return {'FINISHED'}
63+
msg = 'mmSolver: Copy 2D Tracks: Successfully written file: {}'.format(file_path)
64+
self.report({'INFO'}, msg)
65+
66+
# Encode text so it includes formatting characters like a file
67+
# read.
68+
file_path = file_path.encode('utf8')
69+
bpy.context.window_manager.clipboard = file_path
70+
return {'FINISHED'}
71+
72+
73+
def register():
74+
bpy.utils.register_class(MmSolver_OT_copySelectedMarkers)
75+
76+
77+
def unregister():
78+
bpy.utils.unregister_class(MmSolver_OT_copySelectedMarkers)
79+
80+
81+
if __name__ == '__main__':
82+
register()
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Copyright (C) 2021 David Cattermole.
2+
#
3+
# This file is part of mmSolver.
4+
#
5+
# mmSolver is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as
7+
# published by the Free Software Foundation, either version 3 of the
8+
# License, or (at your option) any later version.
9+
#
10+
# mmSolver is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
17+
#
18+
"""
19+
Export 2D Markers from Blender.
20+
"""
21+
22+
import os
23+
24+
import bpy
25+
from bpy.props import StringProperty, IntProperty, BoolProperty, EnumProperty
26+
from bpy_extras.io_utils import ExportHelper
27+
28+
from . import utils
29+
from . import uvtrack_format_blender as uv_fmt
30+
31+
32+
class MmSolver_OT_exportSelectedMarkers(bpy.types.Operator, ExportHelper):
33+
"""Save a .uv file for 2D Tracks."""
34+
bl_idname = 'mmsolver.export_selected_markers'
35+
bl_label = 'Export Selected 2D Tracks'
36+
37+
filename_ext = '.uv'
38+
filter_glob: StringProperty(
39+
default='*.uv',
40+
options={'HIDDEN'},
41+
maxlen=255, # Max internal buffer length, longer would be clamped.
42+
)
43+
44+
frame_start: IntProperty(name='Start Frame',
45+
description='Start frame for export',
46+
default=1, min=1, max=300000)
47+
frame_end: IntProperty(name='End Frame',
48+
description='End frame for export',
49+
default=250, min=1, max=300000)
50+
51+
def execute(self, context):
52+
file_path = self.filepath
53+
if file_path is None or len(file_path) == 0:
54+
msg = 'mmSolver: Export 2D Tracks: Could not write file data.'
55+
self.report({'ERROR'}, msg)
56+
return {'FINISHED'}
57+
58+
clip, cam, tracks = utils.get_selected_clip_objects(context)
59+
if clip is None or cam is None or tracks is None:
60+
msg = (
61+
'mmSolver: Export 2D Tracks: '
62+
'Please select 2D Tracks in the Movie Clip Editor. '
63+
'Could not get selected 2D Tracks.'
64+
)
65+
self.report({'WARNING'}, msg)
66+
return {'CANCELLED'}
67+
68+
start_frame = clip.frame_start
69+
end_frame = start_frame + clip.frame_duration
70+
frame_range = (max(self.frame_start, start_frame),
71+
min(self.frame_end, end_frame))
72+
73+
data_str = uv_fmt.generate(
74+
context,
75+
clip, cam, tracks,
76+
frame_range,
77+
fmt=uv_fmt.UV_TRACK_FORMAT_VERSION_PREFERRED)
78+
if data_str is None or len(data_str) == 0:
79+
msg = 'mmSolver: Export 2D Tracks: Could not generate file data.'
80+
self.report({'ERROR'}, msg)
81+
return {'FINISHED'}
82+
83+
file_path = utils.write_text_data_to_file(data_str, file_path)
84+
msg = 'mmSolver: Export 2D Tracks: Successfully written file: {}'
85+
self.report({'INFO'}, msg.format(file_path))
86+
return {'FINISHED'}
87+
88+
def invoke(self, context, event):
89+
self.frame_start = context.scene.frame_start
90+
self.frame_end = context.scene.frame_end
91+
92+
wm = context.window_manager
93+
wm.fileselect_add(self)
94+
return {'RUNNING_MODAL'}
95+
96+
97+
def menu_export(self, context):
98+
default_path = os.path.splitext(bpy.data.filepath)[0] + '.uv'
99+
op = self.layout.operator(
100+
MmSolver_OT_exportSelectedMarkers.bl_idname,
101+
text='Export Selected 2D Tracks (MM Solver .uv)')
102+
op.filepath = default_path
103+
104+
105+
def register():
106+
bpy.utils.register_class(MmSolver_OT_exportSelectedMarkers)
107+
bpy.types.TOPBAR_MT_file_export.append(menu_export)
108+
109+
110+
def unregister():
111+
bpy.utils.unregister_class(MmSolver_OT_exportSelectedMarkers)
112+
bpy.types.TOPBAR_MT_file_export.remove(menu_export)
113+
114+
115+
if __name__ == '__main__':
116+
register()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (C) 2021 David Cattermole.
2+
#
3+
# This file is part of mmSolver.
4+
#
5+
# mmSolver is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as
7+
# published by the Free Software Foundation, either version 3 of the
8+
# License, or (at your option) any later version.
9+
#
10+
# mmSolver is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with mmSolver. If not, see <https://www.gnu.org/licenses/>.
17+
#
18+
import bpy
19+
20+
21+
class MmSolverPanel(bpy.types.Panel):
22+
bl_idname = 'MMSOLVER_PT_mmSolverPanel'
23+
24+
# Nice name of the panel in the GUI.
25+
bl_label = 'MM Solver'
26+
27+
# Specifies the space (in fact - the window), where the panel will
28+
# be located. It can take the following values:
29+
#
30+
# EMPTY, VIEW_3D, TIMELINE, GRAPH_EDITOR, DOPESHEET_EDITOR,
31+
# NLA_EDITOR, IMAGE_EDITOR, SEQUENCE_EDITOR, CLIP_EDITOR,
32+
# TEXT_EDITOR, NODE_EDITOR, LOGIC_EDITOR, PROPERTIES, OUTLINER,
33+
# USER_PREFERENCES, INFO, FILE_BROWSER, CONSOLE
34+
bl_space_type = 'CLIP_EDITOR'
35+
36+
# Specifies the region in space to place the panel. It can take
37+
# the following values:
38+
#
39+
# WINDOW, HEADER, CHANNELS, TEMPORARY, UI, TOOLS, TOOL_PROPS,
40+
# PREVIEW, HUD, NAVIGATION_BAR, EXECUTE, FOOTER, TOOL_HEADER, XR.
41+
bl_region_type = 'UI'
42+
43+
# Specifies the panel placement context.
44+
bl_context = 'object'
45+
46+
# Specifies the panel placement group.
47+
bl_category = 'Track'
48+
49+
# Possible Values:
50+
#
51+
# - DEFAULT_CLOSED - Defines if the panel has to be open or
52+
# collapsed at the time of its creation.
53+
#
54+
# - HIDE_HEADER - If set to False, the panel shows a header, which
55+
# contains a clickable arrow to collapse the panel and the label
56+
# (see bl_label).
57+
#
58+
# - INSTANCED - Multiple panels with this type can be used as part
59+
# of a list depending on data external to the UI. Used to create
60+
# panels for the modifiers and other stacks.
61+
#
62+
# - HEADER_LAYOUT_EXPAND - Allow buttons in the header to stretch
63+
# and shrink to fill the entire layout width.
64+
bl_options = {'DEFAULT_CLOSED'}
65+
66+
def draw(self, context):
67+
self.layout.operator(
68+
'mmsolver.copy_selected_markers',
69+
icon='COPYDOWN',
70+
text='Copy 2D Tracks')
71+
72+
self.layout.operator(
73+
'mmsolver.export_selected_markers',
74+
icon='EXPORT',
75+
text='Export 2D Tracks...')
76+
77+
78+
def register():
79+
bpy.utils.register_class(MmSolverPanel)
80+
81+
82+
def unregister():
83+
bpy.utils.unregister_class(MmSolverPanel)

0 commit comments

Comments
 (0)