diff options
Diffstat (limited to 'release/scripts/templates_py')
6 files changed, 486 insertions, 4 deletions
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py index 6c77c5d6a1a..8de7a5e2903 100644 --- a/release/scripts/templates_py/batch_export.py +++ b/release/scripts/templates_py/batch_export.py @@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT') for obj in selection: - obj.select = True + obj.select_set(action='SELECT') # some exporters only use the active object scene.objects.active = obj @@ -31,7 +31,7 @@ for obj in selection: ## Can be used for multiple formats # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True) - obj.select = False + obj.select_set(action='DESELECT') print("written:", fn) @@ -39,4 +39,4 @@ for obj in selection: scene.objects.active = obj_active for obj in selection: - obj.select = True + obj.select_set(action='SELECT') diff --git a/release/scripts/templates_py/manipulator_custom_geometry.py b/release/scripts/templates_py/manipulator_custom_geometry.py new file mode 100644 index 00000000000..0f1ab72f9ef --- /dev/null +++ b/release/scripts/templates_py/manipulator_custom_geometry.py @@ -0,0 +1,158 @@ +# Example of a custom widget that defines it's own geometry. +# +# Usage: Select a lamp in the 3D view and drag the arrow at it's rear +# to change it's energy value. +# +import bpy +from bpy.types import ( + Manipulator, + ManipulatorGroup, +) + +# Coordinates (each one is a triangle). +custom_shape_verts = ( + (3.0, 1.0, -1.0), (2.0, 2.0, -1.0), (3.0, 3.0, -1.0), + (1.0, 3.0, 1.0), (3.0, 3.0, -1.0), (1.0, 3.0, -1.0), + (3.0, 3.0, 1.0), (3.0, 1.0, -1.0), (3.0, 3.0, -1.0), + (2.0, 0.0, 1.0), (3.0, 1.0, -1.0), (3.0, 1.0, 1.0), + (2.0, 0.0, -1.0), (2.0, 2.0, 1.0), (2.0, 2.0, -1.0), + (2.0, 2.0, -1.0), (0.0, 2.0, 1.0), (0.0, 2.0, -1.0), + (1.0, 3.0, 1.0), (2.0, 2.0, 1.0), (3.0, 3.0, 1.0), + (0.0, 2.0, -1.0), (1.0, 3.0, 1.0), (1.0, 3.0, -1.0), + (2.0, 2.0, 1.0), (3.0, 1.0, 1.0), (3.0, 3.0, 1.0), + (2.0, 2.0, -1.0), (1.0, 3.0, -1.0), (3.0, 3.0, -1.0), + (-3.0, -1.0, -1.0), (-2.0, -2.0, -1.0), (-3.0, -3.0, -1.0), + (-1.0, -3.0, 1.0), (-3.0, -3.0, -1.0), (-1.0, -3.0, -1.0), + (-3.0, -3.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -3.0, -1.0), + (-2.0, 0.0, 1.0), (-3.0, -1.0, -1.0), (-3.0, -1.0, 1.0), + (-2.0, 0.0, -1.0), (-2.0, -2.0, 1.0), (-2.0, -2.0, -1.0), + (-2.0, -2.0, -1.0), (0.0, -2.0, 1.0), (0.0, -2.0, -1.0), + (-1.0, -3.0, 1.0), (-2.0, -2.0, 1.0), (-3.0, -3.0, 1.0), + (0.0, -2.0, -1.0), (-1.0, -3.0, 1.0), (-1.0, -3.0, -1.0), + (-2.0, -2.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -3.0, 1.0), + (-2.0, -2.0, -1.0), (-1.0, -3.0, -1.0), (-3.0, -3.0, -1.0), + (1.0, -1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, -5.0), + (-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, 5.0), + (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, 5.0), + (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, 5.0), + (-1.0, 1.0, 0.0), (-1.0, -1.0, 0.0), (0.0, 0.0, 5.0), + (-1.0, -1.0, 0.0), (-1.0, 1.0, 0.0), (0.0, 0.0, -5.0), + (-1.0, 1.0, 0.0), (1.0, 1.0, 0.0), (0.0, 0.0, -5.0), + (1.0, 1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 0.0, -5.0), + (3.0, 1.0, -1.0), (2.0, 0.0, -1.0), (2.0, 2.0, -1.0), + (1.0, 3.0, 1.0), (3.0, 3.0, 1.0), (3.0, 3.0, -1.0), + (3.0, 3.0, 1.0), (3.0, 1.0, 1.0), (3.0, 1.0, -1.0), + (2.0, 0.0, 1.0), (2.0, 0.0, -1.0), (3.0, 1.0, -1.0), + (2.0, 0.0, -1.0), (2.0, 0.0, 1.0), (2.0, 2.0, 1.0), + (2.0, 2.0, -1.0), (2.0, 2.0, 1.0), (0.0, 2.0, 1.0), + (1.0, 3.0, 1.0), (0.0, 2.0, 1.0), (2.0, 2.0, 1.0), + (0.0, 2.0, -1.0), (0.0, 2.0, 1.0), (1.0, 3.0, 1.0), + (2.0, 2.0, 1.0), (2.0, 0.0, 1.0), (3.0, 1.0, 1.0), + (2.0, 2.0, -1.0), (0.0, 2.0, -1.0), (1.0, 3.0, -1.0), + (-3.0, -1.0, -1.0), (-2.0, 0.0, -1.0), (-2.0, -2.0, -1.0), + (-1.0, -3.0, 1.0), (-3.0, -3.0, 1.0), (-3.0, -3.0, -1.0), + (-3.0, -3.0, 1.0), (-3.0, -1.0, 1.0), (-3.0, -1.0, -1.0), + (-2.0, 0.0, 1.0), (-2.0, 0.0, -1.0), (-3.0, -1.0, -1.0), + (-2.0, 0.0, -1.0), (-2.0, 0.0, 1.0), (-2.0, -2.0, 1.0), + (-2.0, -2.0, -1.0), (-2.0, -2.0, 1.0), (0.0, -2.0, 1.0), + (-1.0, -3.0, 1.0), (0.0, -2.0, 1.0), (-2.0, -2.0, 1.0), + (0.0, -2.0, -1.0), (0.0, -2.0, 1.0), (-1.0, -3.0, 1.0), + (-2.0, -2.0, 1.0), (-2.0, 0.0, 1.0), (-3.0, -1.0, 1.0), + (-2.0, -2.0, -1.0), (0.0, -2.0, -1.0), (-1.0, -3.0, -1.0), +) + + +class MyCustomShapeWidget(Manipulator): + bl_idname = "VIEW3D_WT_auto_facemap" + bl_target_properties = ( + {"id": "offset", "type": 'FLOAT', "array_length": 1}, + ) + + __slots__ = ( + "custom_shape", + "init_mouse_y", + "init_value", + ) + + def _update_offset_matrix(self): + # offset behind the lamp + self.matrix_offset.col[3][2] = self.target_get_value("offset") / -10.0 + + def draw(self, context): + self._update_offset_matrix() + self.draw_custom_shape(self.custom_shape) + + def draw_select(self, context, select_id): + self._update_offset_matrix() + self.draw_custom_shape(self.custom_shape, select_id=select_id) + + def setup(self): + if not hasattr(self, "custom_shape"): + self.custom_shape = self.new_custom_shape('TRIS', custom_shape_verts) + + def invoke(self, context, event): + self.init_mouse_y = event.mouse_y + self.init_value = self.target_get_value("offset") + return {'RUNNING_MODAL'} + + def exit(self, context, cancel): + context.area.header_text_set() + if cancel: + self.target_set_value("offset", self.init_value) + + def modal(self, context, event, tweak): + delta = (event.mouse_y - self.init_mouse_y) / 10.0 + if 'SNAP' in tweak: + delta = round(delta) + if 'PRECISE' in tweak: + delta /= 10.0 + value = self.init_value + delta + self.target_set_value("offset", value) + context.area.header_text_set("My Manipulator: %.4f" % value) + return {'RUNNING_MODAL'} + + +class MyCustomShapeWidgetGroup(ManipulatorGroup): + bl_idname = "OBJECT_WGT_lamp_test" + bl_label = "Test Lamp Widget" + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_options = {'3D', 'PERSISTENT'} + + @classmethod + def poll(cls, context): + ob = context.object + return (ob and ob.type == 'LAMP') + + def setup(self, context): + # Assign the 'offset' target property to the lamp energy. + ob = context.object + mpr = self.manipulators.new(MyCustomShapeWidget.bl_idname) + mpr.target_set_prop("offset", ob.data, "energy") + mpr.matrix_basis = ob.matrix_world.normalized() + + mpr.color = 1.0, 0.5, 1.0 + mpr.alpha = 0.5 + + mpr.color_highlight = 1.0, 0.5, 1.0 + mpr.alpha_highlight = 0.5 + + # units are large, so shrink to something more reasonable. + mpr.scale_basis = 0.1 + mpr.use_draw_modal = True + + self.energy_widget = mpr + + def refresh(self, context): + ob = context.object + mpr = self.energy_widget + mpr.matrix_basis = ob.matrix_world.normalized() + + +classes = ( + MyCustomShapeWidget, + MyCustomShapeWidgetGroup, +) + +for cls in classes: + bpy.utils.register_class(cls) diff --git a/release/scripts/templates_py/manipulator_operator.py b/release/scripts/templates_py/manipulator_operator.py new file mode 100644 index 00000000000..00b24736b8e --- /dev/null +++ b/release/scripts/templates_py/manipulator_operator.py @@ -0,0 +1,231 @@ +# Example of an operator which uses manipulators to control its properties. +# +# Usage: Run this script, then in mesh edit-mode press Spacebar +# to activate the operator "Select Side of Plane" +# The manipulators can then be used to adjust the plane in the 3D view. +# +import bpy +import bmesh + +from bpy.types import ( + Operator, + ManipulatorGroup, +) + +from bpy.props import ( + FloatVectorProperty, +) + +def main(context, plane_co, plane_no): + obj = context.active_object + matrix = obj.matrix_world.copy() + me = obj.data + bm = bmesh.from_edit_mesh(me) + + plane_dot = plane_no.dot(plane_co) + + for v in bm.verts: + co = matrix * v.co + v.select = (plane_no.dot(co) > plane_dot) + bm.select_flush_mode() + + bmesh.update_edit_mesh(me) + + +class SelectSideOfPlane(Operator): + """UV Operator description""" + bl_idname = "mesh.select_side_of_plane" + bl_label = "Select Side of Plane" + bl_options = {'REGISTER', 'UNDO'} + + plane_co = FloatVectorProperty( + size=3, + default=(0, 0, 0), + ) + plane_no = FloatVectorProperty( + size=3, + default=(0, 0, 1), + ) + + @classmethod + def poll(cls, context): + return (context.mode == 'EDIT_MESH') + + def invoke(self, context, event): + + if not self.properties.is_property_set("plane_co"): + self.plane_co = context.scene.cursor_location + + if not self.properties.is_property_set("plane_no"): + if context.space_data.type == 'VIEW_3D': + rv3d = context.space_data.region_3d + view_inv = rv3d.view_matrix.to_3x3() + # view y axis + self.plane_no = view_inv[1].normalized() + + self.execute(context) + + if context.space_data.type == 'VIEW_3D': + wm = context.window_manager + wm.manipulator_group_type_add(SelectSideOfPlaneManipulatorGroup.bl_idname) + + return {'FINISHED'} + + def execute(self, context): + from mathutils import Vector + main(context, Vector(self.plane_co), Vector(self.plane_no)) + return {'FINISHED'} + + +# Manipulators for plane_co, plane_no +class SelectSideOfPlaneManipulatorGroup(ManipulatorGroup): + bl_idname = "MESH_WGT_select_side_of_plane" + bl_label = "Side of Plane Manipulator" + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_options = {'3D'} + + # Helper functions + @staticmethod + def my_target_operator(context): + wm = context.window_manager + op = wm.operators[-1] if wm.operators else None + if isinstance(op, SelectSideOfPlane): + return op + return None + + @staticmethod + def my_view_orientation(context): + rv3d = context.space_data.region_3d + view_inv = rv3d.view_matrix.to_3x3() + return view_inv.normalized() + + @classmethod + def poll(cls, context): + op = cls.my_target_operator(context) + if op is None: + wm = context.window_manager + wm.manipulator_group_type_remove(SelectSideOfPlaneManipulatorGroup.bl_idname) + return False + return True + + def setup(self, context): + from mathutils import Matrix, Vector + + # ---- + # Grab + + def grab_get_cb(): + op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context) + return op.plane_co + + def grab_set_cb(value): + op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context) + op.plane_co = value + # XXX, this may change! + op.execute(context) + + mpr = self.manipulators.new("MANIPULATOR_WT_grab_3d") + mpr.target_set_handler("offset", get=grab_get_cb, set=grab_set_cb) + + mpr.use_draw_value = True + + mpr.color = 0.8, 0.8, 0.8 + mpr.alpha = 0.5 + + mpr.color_highlight = 1.0, 1.0, 1.0 + mpr.alpha_highlight = 1.0 + + mpr.scale_basis = 0.2 + + self.widget_grab = mpr + + # ---- + # Dial + + def direction_get_cb(): + op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context) + + no_a = self.widget_dial.matrix_basis.col[1].xyz + no_b = Vector(op.plane_no) + + no_a = (no_a * self.view_inv).xy.normalized() + no_b = (no_b * self.view_inv).xy.normalized() + return no_a.angle_signed(no_b) + + def direction_set_cb(value): + op = SelectSideOfPlaneManipulatorGroup.my_target_operator(context) + matrix_rotate = Matrix.Rotation(-value, 3, self.rotate_axis) + no = matrix_rotate * self.widget_dial.matrix_basis.col[1].xyz + op.plane_no = no + op.execute(context) + + mpr = self.manipulators.new("MANIPULATOR_WT_dial_3d") + mpr.target_set_handler("offset", get=direction_get_cb, set=direction_set_cb) + mpr.draw_options = {'ANGLE_START_Y'} + + mpr.use_draw_value = True + + mpr.color = 0.8, 0.8, 0.8 + mpr.alpha = 0.5 + + mpr.color_highlight = 1.0, 1.0, 1.0, 1.0 + mpr.alpha_highlight = 1.0 + + self.widget_dial = mpr + + def draw_prepare(self, context): + from mathutils import Vector + + view_inv = self.my_view_orientation(context) + + self.view_inv = view_inv + self.rotate_axis = view_inv[2].xyz + self.rotate_up = view_inv[1].xyz + + op = self.my_target_operator(context) + + co = Vector(op.plane_co) + no = Vector(op.plane_no).normalized() + + # Grab + no_z = no + no_y = no_z.orthogonal() + no_x = no_z.cross(no_y) + + matrix = self.widget_grab.matrix_basis + matrix.identity() + matrix.col[0].xyz = no_x + matrix.col[1].xyz = no_y + matrix.col[2].xyz = no_z + matrix.col[3].xyz = co + + # Dial + no_z = self.rotate_axis + no_y = (no - (no.project(no_z))).normalized() + no_x = self.rotate_axis.cross(no_y) + + matrix = self.widget_dial.matrix_basis + matrix.identity() + matrix.col[0].xyz = no_x + matrix.col[1].xyz = no_y + matrix.col[2].xyz = no_z + matrix.col[3].xyz = co + + +classes = ( + SelectSideOfPlane, + SelectSideOfPlaneManipulatorGroup, +) + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + + +def unregister(): + for cls in reversed(classes): + bpy.utils.unregister_class(cls) + +if __name__ == "__main__": + register() diff --git a/release/scripts/templates_py/manipulator_operator_target.py b/release/scripts/templates_py/manipulator_operator_target.py new file mode 100644 index 00000000000..0abf6f2f654 --- /dev/null +++ b/release/scripts/templates_py/manipulator_operator_target.py @@ -0,0 +1,48 @@ +# Example of a manipulator that activates an operator +# using the predefined dial manipulator to change the camera roll. +# +# Usage: Run this script and select a camera in the 3D view. +# +import bpy +from bpy.types import ( + ManipulatorGroup, +) + +class MyCameraWidgetGroup(ManipulatorGroup): + bl_idname = "OBJECT_WGT_test_camera" + bl_label = "Object Camera Test Widget" + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_options = {'3D', 'PERSISTENT'} + + @classmethod + def poll(cls, context): + ob = context.object + return (ob and ob.type == 'CAMERA') + + def setup(self, context): + # Run an operator using the dial manipulator + ob = context.object + mpr = self.manipulators.new("MANIPULATOR_WT_dial_3d") + props = mpr.target_set_operator("transform.rotate") + props.constraint_axis = False, False, True + props.constraint_orientation = 'LOCAL' + props.release_confirm = True + + mpr.matrix_basis = ob.matrix_world.normalized() + mpr.line_width = 3 + + mpr.color = 0.8, 0.8, 0.8 + mpr.alpha = 0.5 + + mpr.color_highlight = 1.0, 1.0, 1.0 + mpr.alpha_highlight = 1.0 + + self.roll_widget = mpr + + def refresh(self, context): + ob = context.object + mpr = self.roll_widget + mpr.matrix_basis = ob.matrix_world.normalized() + +bpy.utils.register_class(MyCameraWidgetGroup) diff --git a/release/scripts/templates_py/manipulator_simple.py b/release/scripts/templates_py/manipulator_simple.py new file mode 100644 index 00000000000..7e02940d527 --- /dev/null +++ b/release/scripts/templates_py/manipulator_simple.py @@ -0,0 +1,45 @@ +# Example of a group that edits a single property +# using the predefined manipulator arrow. +# +# Usage: Select a lamp in the 3D view and drag the arrow at it's rear +# to change it's energy value. +# +import bpy +from bpy.types import ( + ManipulatorGroup, +) + +class MyLampWidgetGroup(ManipulatorGroup): + bl_idname = "OBJECT_WGT_lamp_test" + bl_label = "Test Lamp Widget" + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_options = {'3D', 'PERSISTENT'} + + @classmethod + def poll(cls, context): + ob = context.object + return (ob and ob.type == 'LAMP') + + def setup(self, context): + # Arrow manipulator has one 'offset' property we can assign to the lamp energy. + ob = context.object + mpr = self.manipulators.new("MANIPULATOR_WT_arrow_3d") + mpr.target_set_prop("offset", ob.data, "energy") + mpr.matrix_basis = ob.matrix_world.normalized() + mpr.draw_style = 'BOX' + + mpr.color = 1.0, 0.5, 0.0 + mpr.alpha = 0.5 + + mpr.color_highlight = 1.0, 0.5, 1.0 + mpr.alpha_highlight = 0.5 + + self.energy_widget = mpr + + def refresh(self, context): + ob = context.object + mpr = self.energy_widget + mpr.matrix_basis = ob.matrix_world.normalized() + +bpy.utils.register_class(MyLampWidgetGroup) diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index c4d661b4c1f..e3b63813fc4 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -67,7 +67,7 @@ def main(context, event): # now we have the object under the mouse cursor, # we could do lots of stuff but for the example just select. if best_obj is not None: - best_obj.select = True + best_obj.select_set(action='SELECT') context.scene.objects.active = best_obj |