-
Damien Picard authored
This rig is mostly useful for 2D shots, when the camera is static and the action happens in front of it (like a theatre stage). In a 2D production (and some shots in 3D as well), you sometimes need to rotate the camera while zooming, effectively "cropping" the field, just as you would using a rostrum camera. This is tedious and error-prone if animating built-in basic transforms, so this rig implements a more intuitive way to do that, by just animating the two lower corners of the camera's field. Also improved other stuff in the add-on: - add the GPL license block to create_widgets.py; - rename "arm[ature]" to "rig" in some functions, for consistency and to avoid confusion with the crane's arm; - changes to the UI panel: - remove the boxes, - put focal length at the top of the panel, - group related properties using aligned columns, - change the Make Camera Active operator's poll method, so that it is always visible in the UI, but greyed out when the camera is already active.
Damien Picard authoredThis rig is mostly useful for 2D shots, when the camera is static and the action happens in front of it (like a theatre stage). In a 2D production (and some shots in 3D as well), you sometimes need to rotate the camera while zooming, effectively "cropping" the field, just as you would using a rostrum camera. This is tedious and error-prone if animating built-in basic transforms, so this rig implements a more intuitive way to do that, by just animating the two lower corners of the camera's field. Also improved other stuff in the add-on: - add the GPL license block to create_widgets.py; - rename "arm[ature]" to "rig" in some functions, for consistency and to avoid confusion with the crane's arm; - changes to the UI panel: - remove the boxes, - put focal length at the top of the panel, - group related properties using aligned columns, - change the Make Camera Active operator's poll method, so that it is always visible in the UI, but greyed out when the camera is already active.
create_widgets.py 16.17 KiB
# ##### 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 #####
import bpy
from mathutils import Vector
from math import cos, sin, pi
def create_widget(name):
"""Create an empty widget object and return the object"""
prefs = bpy.context.preferences.addons["add_camera_rigs"].preferences
widget_prefix = prefs.widget_prefix
obj_name = widget_prefix + name
scene = bpy.context.scene
obj = bpy.data.objects.get(obj_name)
if obj is None:
mesh = bpy.data.meshes.new(obj_name)
obj = bpy.data.objects.new(obj_name, mesh)
# Create a new collection for the widgets
collection_name = prefs.camera_widget_collection_name
coll = bpy.data.collections.get(collection_name)
if coll is None:
coll = bpy.data.collections.new(collection_name)
scene.collection.children.link(coll)
coll.hide_viewport = True
coll.hide_render = True
# Link the collection
coll.objects.link(obj)
return obj
def create_corner_widget(name, reverse=False):
"""Create a wedge-shaped widget"""
obj = create_widget(name)
if not obj.data.vertices:
reverse = -1 if reverse else 1
verts = (Vector((reverse * 0.0, 0.0, 0.0)),
Vector((reverse * 0.0, 1.0, 0.0)),
Vector((reverse * -0.1, 1.0, 0.0)),
Vector((reverse * -0.1, 0.1, 0.0)),
Vector((reverse * -1.0, 0.1, 0.0)),
Vector((reverse * -1.0, 0.0, 0.0)),
)
edges = [(n, (n+1) % len(verts)) for n in range(len(verts))]
mesh = obj.data
mesh.from_pydata(verts, edges, ())
mesh.update()
return obj
def create_circle_widget(name, radius=1.0):
"""Create a circle-shaped widget"""
obj = create_widget(name)
if not obj.data.vertices:
vert_n = 16
verts = []
for n in range(vert_n):
angle = n / vert_n * 2*pi
verts.append(Vector((cos(angle) * radius,
sin(angle) * radius, 0.0)))
edges = [(n, (n+1) % len(verts)) for n in range(len(verts))]
mesh = obj.data
mesh.from_pydata(verts, edges, ())
mesh.update()
return obj
def create_root_widget(name):
"""Create a compass-shaped widget"""
obj = create_widget(name)
if not obj.data.vertices:
verts = [(0.6307649612426758, 0.6271349787712097, 0.0),
(0.3413670063018799, 0.8205029964447021, 0.0),
(0.0, 0.8884050250053406, 0.0),
(-0.3413670063018799, 0.8205029964447021, 0.0),
(-0.6307649612426758, 0.6271349787712097, 0.0),
(-0.8241360187530518, 0.3377370238304138, 0.0),
(-0.8920379877090454, -0.003631560131907463, 0.0),
(0.8920379877090454, -0.003631379920989275, 0.0),
(0.824133038520813, 0.3377370238304138, 0.0),
(0.21458700299263, 1.5175920724868774, 0.0),
(-0.21458669006824493, 1.5175920724868774, 0.0),
(-0.21458700299263, 1.1372729539871216, 0.0),
(0.21458700299263, 1.1372729539871216, 0.0),
(-0.3977609872817993, 1.5175920724868774, 0.0),
(0.3977609872817993, 1.5175920724868774, 0.0),
(0.0, 2.002802848815918, 0.0),
(-0.8241360187530518, -0.3449999988079071, 0.0),
(0.8241360187530518, -0.3449999988079071, 0.0),
(0.6307649612426758, -0.6343979835510254, 0.0),
(0.3413670063018799, -0.8277660012245178, 0.0),
(0.0, -0.8956680297851562, 0.0),
(-0.3413670063018799, -0.8277660012245178, 0.0),
(-0.6307649612426758, -0.6343979835510254, 0.0),
(-2.0064330101013184, -0.003630870021879673, 0.0),
(-1.5212249755859375, 0.39413100481033325, 0.0),
(-1.5212249755859375, -0.4013940095901489, 0.0),
(-1.1409029960632324, 0.21095609664916992, 0.0),
(-1.1409029960632324, -0.2182179093360901, 0.0),
(-1.5212249755859375, -0.2182179093360901, 0.0),
(-1.5212249755859375, 0.21095609664916992, 0.0),
(1.5212249755859375, -0.2182179093360901, 0.0),
(1.5212249755859375, 0.21095609664916992, 0.0),
(1.1409029960632324, 0.21095609664916992, 0.0),
(1.1409029960632324, -0.2182179093360901, 0.0),
(1.5212249755859375, 0.39413100481033325, 0.0),
(1.5212249755859375, -0.4013940095901489, 0.0),
(2.0064330101013184, -0.0036309000570327044, 0.0),
(0.0, -2.0100629329681396, 0.0),
(-0.3977609872817993, -1.5248548984527588, 0.0),
(0.3977609872817993, -1.5248548984527588, 0.0),
(-0.21458669006824493, -1.144536018371582, 0.0),
(0.21458730101585388, -1.144536018371582, 0.0),
(0.21458730101585388, -1.5248548984527588, 0.0),
(-0.21458669006824493, -1.5248548984527588, 0.0)]
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8),
(10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15),
(16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17),
(6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 27), (26, 29),
(27, 28), (31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36),
(35, 36), (37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43),
(41, 42)]
mesh = obj.data
mesh.from_pydata(verts, edges, [])
mesh.update()
return obj
def create_camera_widget(name):
"""Create a camera control widget"""
obj = create_widget(name)
if not obj.data.vertices:
verts = [(0.27513638138771057, 0.0, -0.27513638138771057),
(0.359483003616333, 0.0, -0.14890272915363312),
(0.38910162448883057, 0.0, 0.0),
(0.359483003616333, 0.0, 0.1489027738571167),
(0.27513638138771057, 0.0, 0.27513638138771057),
(0.1489027589559555, 0.0, 0.359483003616333),
(-1.9481809943044937e-07, 0.0, 0.38910162448883057),
(-1.175054293867106e-07, 0.0, -0.38910162448883057),
(0.148903027176857, 0.0, -0.35948291420936584),
(0.6635494828224182, 0.0, -0.09360162913799286),
(0.6635494828224182, 0.0, 0.09360162913799286),
(0.49765610694885254, 0.0, 0.09360162913799286),
(0.49765610694885254, 0.0, -0.09360168874263763),
(0.6635494828224182, 0.0, 0.17350149154663086),
(0.6635494828224182, 0.0, -0.17350149154663086),
(0.8751950263977051, 0.0, 0.0),
(-0.14890296757221222, 0.0, 0.35948291420936584),
(-0.14890283346176147, 0.0, -0.359483003616333),
(-0.27513641119003296, 0.0, -0.2751363217830658),
(-0.359483003616333, 0.0, -0.14890272915363312),
(-0.38910162448883057, 0.0, 0.0),
(-0.359483003616333, 0.0, 0.1489028036594391),
(-0.2751363217830658, 0.0, 0.27513641119003296),
(1.0342557033027333e-07, 0.0, 0.8751950263977051),
(0.17350155115127563, 0.0, 0.6635494828224182),
(-0.17350146174430847, 0.0, 0.6635494828224182),
(0.09360174089670181, 0.0, 0.49765610694885254),
(-0.09360159188508987, 0.0, 0.49765610694885254),
(-0.09360159188508987, 0.0, 0.6635494828224182),
(0.09360168874263763, 0.0, 0.6635494828224182),
(-0.0936015248298645, 0.0, -0.6635494828224182),
(0.09360174834728241, 0.0, -0.6635494828224182),
(0.09360172599554062, 0.0, -0.49765610694885254),
(-0.09360159933567047, 0.0, -0.49765610694885254),
(0.1735016107559204, 0.0, -0.6635494828224182),
(-0.1735014021396637, 0.0, -0.6635494828224182),
(9.422691960025986e-08, 0.0, -0.8751950263977051),
(-0.8751950263977051, 0.0, 0.0),
(-0.6635494828224182, 0.0, 0.17350131273269653),
(-0.6635494828224182, 0.0, -0.17350167036056519),
(-0.49765610694885254, 0.0, 0.0936015397310257),
(-0.49765610694885254, 0.0, -0.0936017706990242),
(-0.6635494828224182, 0.0, -0.09360179305076599),
(-0.6635494828224182, 0.0, 0.09360147267580032),
(-0.16527177393436432, 0.0, 0.1652718484401703),
(-0.21593798696994781, 0.0, 0.08944448828697205),
(-0.23372963070869446, 0.0, 0.0),
(-0.21593798696994781, 0.0, -0.08944445103406906),
(-0.1652718484401703, 0.0, -0.16527177393436432),
(-0.08944450318813324, 0.0, -0.21593798696994781),
(-0.0894445851445198, 0.0, 0.21593795716762543),
(0.0894446149468422, 0.0, -0.21593795716762543),
(-7.058439166485186e-08, 0.0, -0.23372963070869446),
(-1.1702535118729429e-07, 0.0, 0.23372963070869446),
(0.08944445848464966, 0.0, 0.21593798696994781),
(0.1652718037366867, 0.0, 0.1652718037366867),
(0.21593798696994781, 0.0, 0.08944446593523026),
(0.23372963070869446, 0.0, 0.0),
(0.21593798696994781, 0.0, -0.08944445848464966),
(0.1652718037366867, 0.0, -0.1652718037366867)]
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8),
(10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15),
(16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17),
(6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 29), (27, 28),
(31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), (35, 36),
(37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), (41, 42),
(50, 53), (49, 52), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49),
(44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), (56, 57),
(57, 58), (58, 59), (27, 26)]
mesh = obj.data
mesh.from_pydata(verts, edges, [])
mesh.update()
return obj
def create_aim_widget(name):
"""Create a camera aim widget"""
obj = create_widget(name)
if not obj.data.vertices:
verts = [(0.31008288264274597, 0.0, 0.31008288264274597),
(0.40514281392097473, 0.0, 0.1678156554698944),
(0.43852344155311584, 0.0, 0.0),
(0.40514281392097473, 0.0, -0.1678156852722168),
(0.31008288264274597, 0.0, -0.31008288264274597),
(0.1678156703710556, 0.0, -0.40514281392097473),
(-2.1956294915526087e-07, 0.0, -0.43852344155311584),
(-1.3243040086763358e-07, 0.0, 0.43852344155311584),
(0.16781596839427948, 0.0, 0.4051426947116852),
(0.7993937134742737, 0.0, 0.10549049079418182),
(0.7993937134742737, 0.0, -0.10549048334360123),
(0.9863580465316772, 0.0, -0.10549048334360123),
(0.9863580465316772, 0.0, 0.105490542948246),
(0.7993937134742737, 0.0, -0.19553886353969574),
(0.7993937134742737, 0.0, 0.19553886353969574),
(0.5608659386634827, 0.0, 0.0),
(-0.1678159236907959, 0.0, -0.4051426947116852),
(-0.16781575977802277, 0.0, 0.40514281392097473),
(-0.31008294224739075, 0.0, 0.3100828230381012),
(-0.40514281392097473, 0.0, 0.16781564056873322),
(-0.43852344155311584, 0.0, 0.0),
(-0.40514281392097473, 0.0, -0.16781572997570038),
(-0.3100828230381012, 0.0, -0.31008294224739075),
(5.8281088399780856e-08, 0.0, 0.5608659982681274),
(-0.19553889334201813, 0.0, 0.7993938326835632),
(0.1955389529466629, 0.0, 0.7993938326835632),
(-0.10549052804708481, 0.0, 0.9863581657409668),
(0.10549058020114899, 0.0, 0.9863581657409668),
(0.10549052804708481, 0.0, 0.7993938326835632),
(-0.10549046844244003, 0.0, 0.7993938326835632),
(0.10549034923315048, 0.0, -0.7993939518928528),
(-0.10549066960811615, 0.0, -0.7993939518928528),
(-0.10549074411392212, 0.0, -0.9863584041595459),
(0.10549039393663406, 0.0, -0.9863584041595459),
(-0.19553910195827484, 0.0, -0.7993938326835632),
(0.19553880393505096, 0.0, -0.7993940711021423),
(-1.4296951178494055e-07, 0.0, -0.5608659982681274),
(-0.5608660578727722, 0.0, 0.0),
(-0.7993939518928528, 0.0, -0.19553877413272858),
(-0.7993937134742737, 0.0, 0.19553901255130768),
(-0.9863580465316772, 0.0, -0.10549040883779526),
(-0.9863580465316772, 0.0, 0.10549063980579376),
(-0.7993938326835632, 0.0, 0.10549062490463257),
(-0.7993938326835632, 0.0, -0.10549038648605347),
(-0.12803608179092407, 0.0, -0.12803612649440765),
(-0.167287215590477, 0.0, -0.06929267197847366),
(-0.18107034265995026, 0.0, 0.0),
(-0.167287215590477, 0.0, 0.06929262727499008),
(-0.12803612649440765, 0.0, 0.12803608179092407),
(-0.06929267197847366, 0.0, 0.167287215590477),
(-0.06929274648427963, 0.0, -0.1672871708869934),
(0.06929276883602142, 0.0, 0.1672871708869934),
(-5.468173824851874e-08, 0.0, 0.18107034265995026),
(-9.065958295195742e-08, 0.0, -0.18107034265995026),
(0.06929264962673187, 0.0, -0.167287215590477),
(0.12803609669208527, 0.0, -0.12803609669208527),
(0.167287215590477, 0.0, -0.06929264962673187),
(0.18107034265995026, 0.0, 0.0),
(0.167287215590477, 0.0, 0.06929264217615128),
(0.12803609669208527, 0.0, 0.12803609669208527),
(-6.667435314966497e-08, 0.0, 0.060356780886650085),
(-7.866697160352487e-08, 0.0, -0.060356780886650085),
(-0.060356780886650085, 0.0, 0.0),
(0.060356780886650085, 0.0, 0.0)]
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8),
(10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15),
(16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17),
(6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 29), (27, 28),
(31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), (35, 36),
(37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), (41, 42),
(50, 53), (49, 52), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49),
(44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), (56, 57),
(57, 58), (58, 59), (27, 26), (60, 61), (62, 63)]
mesh = obj.data
mesh.from_pydata(verts, edges, [])
mesh.update()
return obj