Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-12-30 05:39:55 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-12-30 05:39:55 +0400
commit33955940e4931e2184434393e0f8c15c36a5c3c6 (patch)
tree7b3c10343162a256e85ff4346f57122032715e82 /release/scripts/templates_py
parente12354c4c5850864f925d22f53ec31578384bc63 (diff)
add templates menu for OSL, use preprocessor directive color for decorators in python.
Diffstat (limited to 'release/scripts/templates_py')
-rw-r--r--release/scripts/templates_py/addon_add_object.py92
-rw-r--r--release/scripts/templates_py/background_job.py122
-rw-r--r--release/scripts/templates_py/batch_export.py33
-rw-r--r--release/scripts/templates_py/bmesh_simple.py22
-rw-r--r--release/scripts/templates_py/bmesh_simple_editmode.py23
-rw-r--r--release/scripts/templates_py/builtin_keyingset.py37
-rw-r--r--release/scripts/templates_py/driver_functions.py35
-rw-r--r--release/scripts/templates_py/gamelogic.py73
-rw-r--r--release/scripts/templates_py/gamelogic_module.py27
-rw-r--r--release/scripts/templates_py/gamelogic_simple.py17
-rw-r--r--release/scripts/templates_py/operator_file_export.py72
-rw-r--r--release/scripts/templates_py/operator_file_import.py75
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py122
-rw-r--r--release/scripts/templates_py/operator_modal.py51
-rw-r--r--release/scripts/templates_py/operator_modal_draw.py79
-rw-r--r--release/scripts/templates_py/operator_modal_timer.py45
-rw-r--r--release/scripts/templates_py/operator_modal_view3d.py70
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py110
-rw-r--r--release/scripts/templates_py/operator_node.py59
-rw-r--r--release/scripts/templates_py/operator_simple.py35
-rw-r--r--release/scripts/templates_py/operator_uv.py56
-rw-r--r--release/scripts/templates_py/script_stub.py14
-rw-r--r--release/scripts/templates_py/ui_menu.py49
-rw-r--r--release/scripts/templates_py/ui_menu_simple.py26
-rw-r--r--release/scripts/templates_py/ui_panel.py73
-rw-r--r--release/scripts/templates_py/ui_panel_simple.py38
26 files changed, 1455 insertions, 0 deletions
diff --git a/release/scripts/templates_py/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py
new file mode 100644
index 00000000000..66da6a969c7
--- /dev/null
+++ b/release/scripts/templates_py/addon_add_object.py
@@ -0,0 +1,92 @@
+bl_info = {
+ "name": "New Object",
+ "author": "Your Name Here",
+ "version": (1, 0),
+ "blender": (2, 65, 0),
+ "location": "View3D > Add > Mesh > New Object",
+ "description": "Adds a new Mesh Object",
+ "warning": "",
+ "wiki_url": "",
+ "tracker_url": "",
+ "category": "Add Mesh"}
+
+
+import bpy
+from bpy.types import Operator
+from bpy.props import FloatVectorProperty
+from bpy_extras.object_utils import AddObjectHelper, object_data_add
+from mathutils import Vector
+
+
+def add_object(self, context):
+ scale_x = self.scale.x
+ scale_y = self.scale.y
+
+ verts = [Vector((-1 * scale_x, 1 * scale_y, 0)),
+ Vector((1 * scale_x, 1 * scale_y, 0)),
+ Vector((1 * scale_x, -1 * scale_y, 0)),
+ Vector((-1 * scale_x, -1 * scale_y, 0)),
+ ]
+
+ edges = []
+ faces = [[0, 1, 2, 3]]
+
+ mesh = bpy.data.meshes.new(name="New Object Mesh")
+ mesh.from_pydata(verts, edges, faces)
+ # useful for development when the mesh may be invalid.
+ # mesh.validate(verbose=True)
+ object_data_add(context, mesh, operator=self)
+
+
+class OBJECT_OT_add_object(Operator, AddObjectHelper):
+ """Create a new Mesh Object"""
+ bl_idname = "mesh.add_object"
+ bl_label = "Add Mesh Object"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ scale = FloatVectorProperty(
+ name="scale",
+ default=(1.0, 1.0, 1.0),
+ subtype='TRANSLATION',
+ description="scaling",
+ )
+
+ def execute(self, context):
+
+ add_object(self, context)
+
+ return {'FINISHED'}
+
+
+# Registration
+
+def add_object_button(self, context):
+ self.layout.operator(
+ OBJECT_OT_add_object.bl_idname,
+ text="Add Object",
+ icon='PLUGIN')
+
+
+# This allows you to right click on a button and link to the manual
+def add_object_manual_map():
+ url_manual_prefix = "http://wiki.blender.org/index.php/Doc:2.6/Manual/"
+ url_manual_mapping = (
+ ("bpy.ops.mesh.add_object", "Modeling/Objects"),
+ )
+ return url_manual_prefix, url_manual_mapping
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_add_object)
+ bpy.utils.register_manual_map(add_object_manual_map)
+ bpy.types.INFO_MT_mesh_add.append(add_object_button)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_add_object)
+ bpy.utils.unregister_manual_map(add_object_manual_map)
+ bpy.types.INFO_MT_mesh_add.remove(add_object_button)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/background_job.py b/release/scripts/templates_py/background_job.py
new file mode 100644
index 00000000000..11b51e5a9b5
--- /dev/null
+++ b/release/scripts/templates_py/background_job.py
@@ -0,0 +1,122 @@
+# This script is an example of how you can run blender from the command line
+# (in background mode with no interface) to automate tasks, in this example it
+# creates a text object, camera and light, then renders and/or saves it.
+# This example also shows how you can parse command line options to scripts.
+#
+# Example usage for this test.
+# blender --background --factory-startup --python $HOME/background_job.py -- \
+# --text="Hello World" \
+# --render="/tmp/hello" \
+# --save="/tmp/hello.blend"
+#
+# Notice:
+# '--factory-startup' is used to avoid the user default settings from
+# interfearing with automated scene generation.
+#
+# '--' causes blender to ignore all following arguments so python can use them.
+#
+# See blender --help for details.
+
+import bpy
+
+
+def example_function(text, save_path, render_path):
+
+ scene = bpy.context.scene
+
+ # Clear existing objects.
+ scene.camera = None
+ for obj in scene.objects:
+ scene.objects.unlink(obj)
+
+ txt_data = bpy.data.curves.new(name="MyText", type='FONT')
+
+ # Text Object
+ txt_ob = bpy.data.objects.new(name="MyText", object_data=txt_data)
+ scene.objects.link(txt_ob) # add the data to the scene as an object
+ txt_data.body = text # the body text to the command line arg given
+ txt_data.align = 'CENTER' # center text
+
+ # Camera
+ cam_data = bpy.data.cameras.new("MyCam")
+ cam_ob = bpy.data.objects.new(name="MyCam", object_data=cam_data)
+ scene.objects.link(cam_ob) # instance the camera object in the scene
+ scene.camera = cam_ob # set the active camera
+ cam_ob.location = 0.0, 0.0, 10.0
+
+ # Lamp
+ lamp_data = bpy.data.lamps.new("MyLamp", 'POINT')
+ lamp_ob = bpy.data.objects.new(name="MyCam", object_data=lamp_data)
+ scene.objects.link(lamp_ob)
+ lamp_ob.location = 2.0, 2.0, 5.0
+
+ if save_path:
+ try:
+ f = open(save_path, 'w')
+ f.close()
+ ok = True
+ except:
+ print("Cannot save to path %r" % save_path)
+
+ import traceback
+ traceback.print_exc()
+
+ if ok:
+ bpy.ops.wm.save_as_mainfile(filepath=save_path)
+
+ if render_path:
+ render = scene.render
+ render.use_file_extension = True
+ render.filepath = render_path
+ bpy.ops.render.render(write_still=True)
+
+
+def main():
+ import sys # to get command line args
+ import argparse # to parse options for us and print a nice help message
+
+ # get the args passed to blender after "--", all of which are ignored by
+ # blender so scripts may receive their own arguments
+ argv = sys.argv
+
+ if "--" not in argv:
+ argv = [] # as if no args are passed
+ else:
+ argv = argv[argv.index("--") + 1:] # get all args after "--"
+
+ # When --help or no args are given, print this help
+ usage_text = \
+ "Run blender in background mode with this script:"
+ " blender --background --python " + __file__ + " -- [options]"
+
+ parser = argparse.ArgumentParser(description=usage_text)
+
+ # Example utility, add some text and renders or saves it (with options)
+ # Possible types are: string, int, long, choice, float and complex.
+ parser.add_argument("-t", "--text", dest="text", type=str, required=True,
+ help="This text will be used to render an image")
+
+ parser.add_argument("-s", "--save", dest="save_path", metavar='FILE',
+ help="Save the generated file to the specified path")
+ parser.add_argument("-r", "--render", dest="render_path", metavar='FILE',
+ help="Render an image to the specified path")
+
+ args = parser.parse_args(argv) # In this example we wont use the args
+
+ if not argv:
+ parser.print_help()
+ return
+
+ if not args.text:
+ print("Error: --text=\"some string\" argument not given, aborting.")
+ parser.print_help()
+ return
+
+ # Run the example function
+ example_function(args.text, args.save_path, args.render_path)
+
+ print("batch job finished, exiting")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py
new file mode 100644
index 00000000000..45d26f4b525
--- /dev/null
+++ b/release/scripts/templates_py/batch_export.py
@@ -0,0 +1,33 @@
+# exports each selected object into its own file
+
+import bpy
+import os
+
+# export to blend file location
+basedir = os.path.dirname(bpy.data.filepath)
+
+if not basedir:
+ raise Exception("Blend file is not saved")
+
+selection = bpy.context.selected_objects
+
+bpy.ops.object.select_all(action='DESELECT')
+
+for obj in selection:
+
+ obj.select = True
+
+ name = bpy.path.clean_name(obj.name)
+ fn = os.path.join(basedir, name)
+
+ bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
+
+ ## Can be used for multiple formats
+ # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
+
+ obj.select = False
+
+ print("written:", fn)
+
+for obj in selection:
+ obj.select = True
diff --git a/release/scripts/templates_py/bmesh_simple.py b/release/scripts/templates_py/bmesh_simple.py
new file mode 100644
index 00000000000..45e6b52d578
--- /dev/null
+++ b/release/scripts/templates_py/bmesh_simple.py
@@ -0,0 +1,22 @@
+# This example assumes we have a mesh object selected
+
+import bpy
+import bmesh
+
+# Get the active mesh
+me = bpy.context.object.data
+
+
+# Get a BMesh representation
+bm = bmesh.new() # create an empty BMesh
+bm.from_mesh(me) # fill it in from a Mesh
+
+
+# Modify the BMesh, can do anything here...
+for v in bm.verts:
+ v.co.x += 1.0
+
+
+# Finish up, write the bmesh back to the mesh
+bm.to_mesh(me)
+bm.free() # free and prevent further access
diff --git a/release/scripts/templates_py/bmesh_simple_editmode.py b/release/scripts/templates_py/bmesh_simple_editmode.py
new file mode 100644
index 00000000000..d79ba02c2cb
--- /dev/null
+++ b/release/scripts/templates_py/bmesh_simple_editmode.py
@@ -0,0 +1,23 @@
+# This example assumes we have a mesh object in edit-mode
+
+import bpy
+import bmesh
+
+# Get the active mesh
+obj = bpy.context.edit_object
+me = obj.data
+
+
+# Get a BMesh representation
+bm = bmesh.from_edit_mesh(me)
+
+bm.faces.active = None
+
+# Modify the BMesh, can do anything here...
+for v in bm.verts:
+ v.co.x += 1.0
+
+
+# Show the updates in the viewport
+# and recalculate n-gon tessellation.
+bmesh.update_edit_mesh(me, True)
diff --git a/release/scripts/templates_py/builtin_keyingset.py b/release/scripts/templates_py/builtin_keyingset.py
new file mode 100644
index 00000000000..19f92dc75e7
--- /dev/null
+++ b/release/scripts/templates_py/builtin_keyingset.py
@@ -0,0 +1,37 @@
+import bpy
+
+
+class BUILTIN_KSI_hello(bpy.types.KeyingSetInfo):
+ bl_label = "Hello World KeyingSet"
+
+ # poll - test for whether Keying Set can be used at all
+ def poll(ksi, context):
+ return context.active_object or context.selected_objects
+
+ # iterator - go over all relevant data, calling generate()
+ def iterator(ksi, context, ks):
+ for ob in context.selected_objects:
+ ksi.generate(context, ks, ob)
+
+ # generator - populate Keying Set with property paths to use
+ def generate(ksi, context, ks, data):
+ id_block = data.id_data
+
+ ks.paths.add(id_block, "location")
+
+ for i in range(5):
+ ks.paths.add(id_block, "layers", i, group_method='NAMED', group_name="5x Hello Layers")
+
+ ks.paths.add(id_block, "show_x_ray", group_method='NONE')
+
+
+def register():
+ bpy.utils.register_class(BUILTIN_KSI_hello)
+
+
+def unregister():
+ bpy.utils.unregister_class(BUILTIN_KSI_hello)
+
+
+if __name__ == '__main__':
+ register()
diff --git a/release/scripts/templates_py/driver_functions.py b/release/scripts/templates_py/driver_functions.py
new file mode 100644
index 00000000000..1c6af0e574f
--- /dev/null
+++ b/release/scripts/templates_py/driver_functions.py
@@ -0,0 +1,35 @@
+# This script defines functions to be used directly in drivers expressions to
+# extend the builtin set of python functions.
+#
+# This can be executed on manually or set to 'Register' to
+# initialize thefunctions on file load.
+
+
+# two sample functions
+def invert(f):
+ """ Simple function call:
+
+ invert(val)
+ """
+ return 1.0 - f
+
+
+uuid_store = {}
+
+
+def slow_value(value, fac, uuid):
+ """ Delay the value by a factor, use a unique string to allow
+ use in multiple drivers without conflict:
+
+ slow_value(val, 0.5, "my_value")
+ """
+ value_prev = uuid_store.get(uuid, value)
+ uuid_store[uuid] = value_new = (value_prev * fac) + (value * (1.0 - fac))
+ return value_new
+
+
+import bpy
+
+# Add variable defined in this script into the drivers namespace.
+bpy.app.driver_namespace["invert"] = invert
+bpy.app.driver_namespace["slow_value"] = slow_value
diff --git a/release/scripts/templates_py/gamelogic.py b/release/scripts/templates_py/gamelogic.py
new file mode 100644
index 00000000000..01ac27c56cd
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic.py
@@ -0,0 +1,73 @@
+# This script must be assigned to a python controller
+# where it can access the object that owns it and the sensors/actuators that it connects to.
+
+import bge
+
+# support for Vector(), Matrix() types and advanced functions like Matrix.Scale(...) and Matrix.Rotation(...)
+# import mathutils
+
+# for functions like getWindowWidth(), getWindowHeight()
+# import Rasterizer
+
+
+def main():
+ cont = bge.logic.getCurrentController()
+
+ # The KX_GameObject that owns this controller.
+ own = cont.owner
+
+ # for scripts that deal with spacial logic
+ own_pos = own.worldPosition
+
+ # Some example functions, remove to write your own script.
+ # check for a positive sensor, will run on any object without errors.
+ print("Logic info for KX_GameObject", own.name)
+ input = False
+
+ for sens in cont.sensors:
+ # The sensor can be on another object, we may want to use it
+ own_sens = sens.owner
+ print(" sensor:", sens.name, end=" ")
+ if sens.positive:
+ print("(true)")
+ input = True
+ else:
+ print("(false)")
+
+ for actu in cont.actuators:
+ # The actuator can be on another object, we may want to use it
+ own_actu = actu.owner
+ print(" actuator:", actu.name)
+
+ # This runs the actuator or turns it off
+ # note that actuators will continue to run unless explicitly turned off.
+ if input:
+ cont.activate(actu)
+ else:
+ cont.deactivate(actu)
+
+ # Its also good practice to get sensors and actuators by name
+ # rather then index so any changes to their order wont break the script.
+
+ # sens_key = cont.sensors["key_sensor"]
+ # actu_motion = cont.actuators["motion"]
+
+ # Loop through all other objects in the scene
+ sce = bge.logic.getCurrentScene()
+ print("Scene Objects:", sce.name)
+ for ob in sce.objects:
+ print(" ", ob.name, ob.worldPosition)
+
+ # Example where collision objects are checked for their properties
+ # adding to our objects "life" property
+ """
+ actu_collide = cont.sensors["collision_sens"]
+ for ob in actu_collide.objectHitList:
+ # Check to see the object has this property
+ if "life" in ob:
+ own["life"] += ob["life"]
+ ob["life"] = 0
+ print(own["life"])
+ """
+
+main()
diff --git a/release/scripts/templates_py/gamelogic_module.py b/release/scripts/templates_py/gamelogic_module.py
new file mode 100644
index 00000000000..88c8cf0d75b
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic_module.py
@@ -0,0 +1,27 @@
+# This module can be accessed by a python controller with
+# its execution method set to 'Module'
+# * Set the module string to "gamelogic_module.main" (without quotes)
+# * When renaming the script it MUST have a .py extension
+# * External text modules are supported as long as they are at
+# the same location as the blendfile or one of its libraries.
+
+import bge
+
+# variables defined here will only be set once when the
+# module is first imported. Set object specific vars
+# inside the function if you intend to use the module
+# with multiple objects.
+
+
+def main(cont):
+ own = cont.owner
+
+ sens = cont.sensors['mySensor']
+ actu = cont.actuators['myActuator']
+
+ if sens.positive:
+ cont.activate(actu)
+ else:
+ cont.deactivate(actu)
+
+# dont call main(bge.logic.getCurrentController()), the py controller will
diff --git a/release/scripts/templates_py/gamelogic_simple.py b/release/scripts/templates_py/gamelogic_simple.py
new file mode 100644
index 00000000000..dbfcf948b18
--- /dev/null
+++ b/release/scripts/templates_py/gamelogic_simple.py
@@ -0,0 +1,17 @@
+import bge
+
+
+def main():
+
+ cont = bge.logic.getCurrentController()
+ own = cont.owner
+
+ sens = cont.sensors['mySensor']
+ actu = cont.actuators['myActuator']
+
+ if sens.positive:
+ cont.activate(actu)
+ else:
+ cont.deactivate(actu)
+
+main()
diff --git a/release/scripts/templates_py/operator_file_export.py b/release/scripts/templates_py/operator_file_export.py
new file mode 100644
index 00000000000..9511cb163bc
--- /dev/null
+++ b/release/scripts/templates_py/operator_file_export.py
@@ -0,0 +1,72 @@
+import bpy
+
+
+def write_some_data(context, filepath, use_some_setting):
+ print("running write_some_data...")
+ f = open(filepath, 'w', encoding='utf-8')
+ f.write("Hello World %s" % use_some_setting)
+ f.close()
+
+ return {'FINISHED'}
+
+
+# ExportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ExportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+
+class ExportSomeData(Operator, ExportHelper):
+ """This appears in the tooltip of the operator and in the generated docs"""
+ bl_idname = "export_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed
+ bl_label = "Export Some Data"
+
+ # ExportHelper mixin class uses this
+ filename_ext = ".txt"
+
+ filter_glob = StringProperty(
+ default="*.txt",
+ options={'HIDDEN'},
+ )
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+ use_setting = BoolProperty(
+ name="Example Boolean",
+ description="Example Tooltip",
+ default=True,
+ )
+
+ type = EnumProperty(
+ name="Example Enum",
+ description="Choose between two items",
+ items=(('OPT_A', "First Option", "Description one"),
+ ('OPT_B', "Second Option", "Description two")),
+ default='OPT_A',
+ )
+
+ def execute(self, context):
+ return write_some_data(context, self.filepath, self.use_setting)
+
+
+# Only needed if you want to add into a dynamic menu
+def menu_func_export(self, context):
+ self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
+
+
+def register():
+ bpy.utils.register_class(ExportSomeData)
+ bpy.types.INFO_MT_file_export.append(menu_func_export)
+
+
+def unregister():
+ bpy.utils.unregister_class(ExportSomeData)
+ bpy.types.INFO_MT_file_export.remove(menu_func_export)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.export_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_file_import.py b/release/scripts/templates_py/operator_file_import.py
new file mode 100644
index 00000000000..9940a1b98eb
--- /dev/null
+++ b/release/scripts/templates_py/operator_file_import.py
@@ -0,0 +1,75 @@
+import bpy
+
+
+def read_some_data(context, filepath, use_some_setting):
+ print("running read_some_data...")
+ f = open(filepath, 'r', encoding='utf-8')
+ data = f.read()
+ f.close()
+
+ # would normally load the data here
+ print(data)
+
+ return {'FINISHED'}
+
+
+# ImportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ImportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+from bpy.types import Operator
+
+
+class ImportSomeData(Operator, ImportHelper):
+ """This appears in the tooltip of the operator and in the generated docs"""
+ bl_idname = "import_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed
+ bl_label = "Import Some Data"
+
+ # ImportHelper mixin class uses this
+ filename_ext = ".txt"
+
+ filter_glob = StringProperty(
+ default="*.txt",
+ options={'HIDDEN'},
+ )
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+ use_setting = BoolProperty(
+ name="Example Boolean",
+ description="Example Tooltip",
+ default=True,
+ )
+
+ type = EnumProperty(
+ name="Example Enum",
+ description="Choose between two items",
+ items=(('OPT_A', "First Option", "Description one"),
+ ('OPT_B', "Second Option", "Description two")),
+ default='OPT_A',
+ )
+
+ def execute(self, context):
+ return read_some_data(context, self.filepath, self.use_setting)
+
+
+# Only needed if you want to add into a dynamic menu
+def menu_func_import(self, context):
+ self.layout.operator(ImportSomeData.bl_idname, text="Text Import Operator")
+
+
+def register():
+ bpy.utils.register_class(ImportSomeData)
+ bpy.types.INFO_MT_file_import.append(menu_func_import)
+
+
+def unregister():
+ bpy.utils.unregister_class(ImportSomeData)
+ bpy.types.INFO_MT_file_import.remove(menu_func_import)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.import_test.some_data('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
new file mode 100644
index 00000000000..fa248cb9005
--- /dev/null
+++ b/release/scripts/templates_py/operator_mesh_add.py
@@ -0,0 +1,122 @@
+import bpy
+import bmesh
+
+
+def add_box(width, height, depth):
+ """
+ This function takes inputs and returns vertex and face arrays.
+ no actual mesh data creation is done here.
+ """
+
+ verts = [(+1.0, +1.0, -1.0),
+ (+1.0, -1.0, -1.0),
+ (-1.0, -1.0, -1.0),
+ (-1.0, +1.0, -1.0),
+ (+1.0, +1.0, +1.0),
+ (+1.0, -1.0, +1.0),
+ (-1.0, -1.0, +1.0),
+ (-1.0, +1.0, +1.0),
+ ]
+
+ faces = [(0, 1, 2, 3),
+ (4, 7, 6, 5),
+ (0, 4, 5, 1),
+ (1, 5, 6, 2),
+ (2, 6, 7, 3),
+ (4, 0, 3, 7),
+ ]
+
+ # apply size
+ for i, v in enumerate(verts):
+ verts[i] = v[0] * width, v[1] * depth, v[2] * height
+
+ return verts, faces
+
+
+from bpy.props import FloatProperty, BoolProperty, FloatVectorProperty
+
+
+class AddBox(bpy.types.Operator):
+ """Add a simple box mesh"""
+ bl_idname = "mesh.primitive_box_add"
+ bl_label = "Add Box"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ width = FloatProperty(
+ name="Width",
+ description="Box Width",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ height = FloatProperty(
+ name="Height",
+ description="Box Height",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ depth = FloatProperty(
+ name="Depth",
+ description="Box Depth",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+
+ # generic transform props
+ view_align = BoolProperty(
+ name="Align to View",
+ default=False,
+ )
+ location = FloatVectorProperty(
+ name="Location",
+ subtype='TRANSLATION',
+ )
+ rotation = FloatVectorProperty(
+ name="Rotation",
+ subtype='EULER',
+ )
+
+ def execute(self, context):
+
+ verts_loc, faces = add_box(self.width,
+ self.height,
+ self.depth,
+ )
+
+ mesh = bpy.data.meshes.new("Box")
+
+ bm = bmesh.new()
+
+ for v_co in verts_loc:
+ bm.verts.new(v_co)
+
+ for f_idx in faces:
+ bm.faces.new([bm.verts[i] for i in f_idx])
+
+ bm.to_mesh(mesh)
+ mesh.update()
+
+ # add the mesh as an object into the scene with this utility module
+ from bpy_extras import object_utils
+ object_utils.object_data_add(context, mesh, operator=self)
+
+ return {'FINISHED'}
+
+
+def menu_func(self, context):
+ self.layout.operator(AddBox.bl_idname, icon='MESH_CUBE')
+
+
+def register():
+ bpy.utils.register_class(AddBox)
+ bpy.types.INFO_MT_mesh_add.append(menu_func)
+
+
+def unregister():
+ bpy.utils.unregister_class(AddBox)
+ bpy.types.INFO_MT_mesh_add.remove(menu_func)
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.mesh.primitive_box_add()
diff --git a/release/scripts/templates_py/operator_modal.py b/release/scripts/templates_py/operator_modal.py
new file mode 100644
index 00000000000..88e5ee80590
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal.py
@@ -0,0 +1,51 @@
+import bpy
+from bpy.props import IntProperty, FloatProperty
+
+
+class ModalOperator(bpy.types.Operator):
+ """Move an object with the mouse, example"""
+ bl_idname = "object.modal_operator"
+ bl_label = "Simple Modal Operator"
+
+ first_mouse_x = IntProperty()
+ first_value = FloatProperty()
+
+ def modal(self, context, event):
+ if event.type == 'MOUSEMOVE':
+ delta = self.first_mouse_x - event.mouse_x
+ context.object.location.x = self.first_value + delta * 0.01
+
+ elif event.type == 'LEFTMOUSE':
+ return {'FINISHED'}
+
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
+ context.object.location.x = self.first_value
+ return {'CANCELLED'}
+
+ return {'RUNNING_MODAL'}
+
+ def invoke(self, context, event):
+ if context.object:
+ self.first_mouse_x = event.mouse_x
+ self.first_value = context.object.location.x
+
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+ else:
+ self.report({'WARNING'}, "No active object, could not finish")
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ModalOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(ModalOperator)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.object.modal_operator('INVOKE_DEFAULT')
diff --git a/release/scripts/templates_py/operator_modal_draw.py b/release/scripts/templates_py/operator_modal_draw.py
new file mode 100644
index 00000000000..d11ddf0b467
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_draw.py
@@ -0,0 +1,79 @@
+import bpy
+import bgl
+import blf
+
+
+def draw_callback_px(self, context):
+ print("mouse points", len(self.mouse_path))
+
+ font_id = 0 # XXX, need to find out how best to get this.
+
+ # draw some text
+ blf.position(font_id, 15, 30, 0)
+ blf.size(font_id, 20, 72)
+ blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))
+
+ # 50% alpha, 2 pixel width line
+ bgl.glEnable(bgl.GL_BLEND)
+ bgl.glColor4f(0.0, 0.0, 0.0, 0.5)
+ bgl.glLineWidth(2)
+
+ bgl.glBegin(bgl.GL_LINE_STRIP)
+ for x, y in self.mouse_path:
+ bgl.glVertex2i(x, y)
+
+ bgl.glEnd()
+
+ # restore opengl defaults
+ bgl.glLineWidth(1)
+ bgl.glDisable(bgl.GL_BLEND)
+ bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
+
+class ModalDrawOperator(bpy.types.Operator):
+ """Draw a line with the mouse"""
+ bl_idname = "view3d.modal_operator"
+ bl_label = "Simple Modal View3D Operator"
+
+ def modal(self, context, event):
+ context.area.tag_redraw()
+
+ if event.type == 'MOUSEMOVE':
+ self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
+
+ elif event.type == 'LEFTMOUSE':
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ return {'FINISHED'}
+
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+ return {'CANCELLED'}
+
+ return {'RUNNING_MODAL'}
+
+ def invoke(self, context, event):
+ if context.area.type == 'VIEW_3D':
+ # the arguments we pass the the callback
+ args = (self, context)
+ # Add the region OpenGL drawing callback
+ # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
+ self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
+
+ self.mouse_path = []
+
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+ else:
+ self.report({'WARNING'}, "View3D not found, cannot run operator")
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ModalDrawOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(ModalDrawOperator)
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/operator_modal_timer.py b/release/scripts/templates_py/operator_modal_timer.py
new file mode 100644
index 00000000000..72c153df9d2
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_timer.py
@@ -0,0 +1,45 @@
+import bpy
+
+
+class ModalTimerOperator(bpy.types.Operator):
+ """Operator which runs its self from a timer"""
+ bl_idname = "wm.modal_timer_operator"
+ bl_label = "Modal Timer Operator"
+
+ _timer = None
+
+ def modal(self, context, event):
+ if event.type == 'ESC':
+ return self.cancel(context)
+
+ if event.type == 'TIMER':
+ # change theme color, silly!
+ color = context.user_preferences.themes[0].view_3d.space.back
+ color.s = 1.0
+ color.h += 0.01
+
+ return {'PASS_THROUGH'}
+
+ def execute(self, context):
+ self._timer = context.window_manager.event_timer_add(0.1, context.window)
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+
+ def cancel(self, context):
+ context.window_manager.event_timer_remove(self._timer)
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ModalTimerOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(ModalTimerOperator)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.wm.modal_timer_operator()
diff --git a/release/scripts/templates_py/operator_modal_view3d.py b/release/scripts/templates_py/operator_modal_view3d.py
new file mode 100644
index 00000000000..c870bbffdcf
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_view3d.py
@@ -0,0 +1,70 @@
+import bpy
+from mathutils import Vector
+from bpy.props import FloatVectorProperty
+
+
+class ViewOperator(bpy.types.Operator):
+ """Translate the view using mouse events"""
+ bl_idname = "view3d.modal_operator"
+ bl_label = "Simple View Operator"
+
+ offset = FloatVectorProperty(
+ name="Offset",
+ size=3,
+ )
+
+ def execute(self, context):
+ v3d = context.space_data
+ rv3d = v3d.region_3d
+
+ rv3d.view_location = self._initial_location + Vector(self.offset)
+
+ def modal(self, context, event):
+ v3d = context.space_data
+ rv3d = v3d.region_3d
+
+ if event.type == 'MOUSEMOVE':
+ self.offset = (self._initial_mouse - Vector((event.mouse_x, event.mouse_y, 0.0))) * 0.02
+ self.execute(context)
+ context.area.header_text_set("Offset %.4f %.4f %.4f" % tuple(self.offset))
+
+ elif event.type == 'LEFTMOUSE':
+ context.area.header_text_set()
+ return {'FINISHED'}
+
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
+ rv3d.view_location = self._initial_location
+ context.area.header_text_set()
+ return {'CANCELLED'}
+
+ return {'RUNNING_MODAL'}
+
+ def invoke(self, context, event):
+
+ if context.space_data.type == 'VIEW_3D':
+ v3d = context.space_data
+ rv3d = v3d.region_3d
+
+ if rv3d.view_perspective == 'CAMERA':
+ rv3d.view_perspective = 'PERSP'
+
+ self._initial_mouse = Vector((event.mouse_x, event.mouse_y, 0.0))
+ self._initial_location = rv3d.view_location.copy()
+
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+ else:
+ self.report({'WARNING'}, "Active space must be a View3d")
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ViewOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(ViewOperator)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
new file mode 100644
index 00000000000..eac76922187
--- /dev/null
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -0,0 +1,110 @@
+import bpy
+from mathutils import Vector
+from bpy_extras import view3d_utils
+
+
+def main(context, event, ray_max=10000.0):
+ """Run this function on left mouse, execute the ray cast"""
+ # get the context arguments
+ scene = context.scene
+ region = context.region
+ rv3d = context.region_data
+ coord = event.mouse_region_x, event.mouse_region_y
+
+ # get the ray from the viewport and mouse
+ view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
+ ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
+ ray_target = ray_origin + (view_vector * ray_max)
+
+
+ def visible_objects_and_duplis():
+ """Loop over (object, matrix) pairs (mesh only)"""
+
+ for obj in context.visible_objects:
+ if obj.type == 'MESH':
+ yield (obj, obj.matrix_world.copy())
+
+ if obj.dupli_type != 'NONE':
+ obj.dupli_list_create(scene)
+ for dob in obj.dupli_list:
+ obj_dupli = dob.object
+ if obj_dupli.type == 'MESH':
+ yield (obj_dupli, dob.matrix.copy())
+
+ obj.dupli_list_clear()
+
+ def obj_ray_cast(obj, matrix):
+ """Wrapper for ray casting that moves the ray into object space"""
+
+ # get the ray relative to the object
+ matrix_inv = matrix.inverted()
+ ray_origin_obj = matrix_inv * ray_origin
+ ray_target_obj = matrix_inv * ray_target
+
+ # cast the ray
+ hit, normal, face_index = obj.ray_cast(ray_origin_obj, ray_target_obj)
+
+ if face_index != -1:
+ return hit, normal, face_index
+ else:
+ return None, None, None
+
+ # cast rays and find the closest object
+ best_length_squared = ray_max * ray_max
+ best_obj = None
+
+ for obj, matrix in visible_objects_and_duplis():
+ if obj.type == 'MESH':
+ hit, normal, face_index = obj_ray_cast(obj, matrix)
+ if hit is not None:
+ hit_world = matrix * hit
+ scene.cursor_location = hit_world
+ length_squared = (hit_world - ray_origin).length_squared
+ if length_squared < best_length_squared:
+ best_length_squared = length_squared
+ best_obj = obj
+
+ # 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
+ context.scene.objects.active = best_obj
+
+
+class ViewOperatorRayCast(bpy.types.Operator):
+ """Modal object selection with a ray cast"""
+ bl_idname = "view3d.modal_operator_raycast"
+ bl_label = "RayCast View Operator"
+
+ def modal(self, context, event):
+ if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
+ # allow navigation
+ return {'PASS_THROUGH'}
+ elif event.type == 'LEFTMOUSE':
+ main(context, event)
+ return {'RUNNING_MODAL'}
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
+ return {'CANCELLED'}
+
+ return {'RUNNING_MODAL'}
+
+ def invoke(self, context, event):
+ if context.space_data.type == 'VIEW_3D':
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+ else:
+ self.report({'WARNING'}, "Active space must be a View3d")
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ViewOperatorRayCast)
+
+
+def unregister():
+ bpy.utils.unregister_class(ViewOperatorRayCast)
+
+
+if __name__ == "__main__":
+ register()
+
diff --git a/release/scripts/templates_py/operator_node.py b/release/scripts/templates_py/operator_node.py
new file mode 100644
index 00000000000..b689ce7634e
--- /dev/null
+++ b/release/scripts/templates_py/operator_node.py
@@ -0,0 +1,59 @@
+import bpy
+
+
+def main(context):
+ space = context.space_data
+ node_tree = space.node_tree
+ node_active = context.active_node
+ node_selected = context.selected_nodes
+
+ # now we have the context, perform a simple operation
+ if node_active in node_selected:
+ node_selected.remove(node_active)
+ if len(node_selected) != 1:
+ operator.report({'ERROR'}, "2 nodes must be selected")
+ return
+
+ node_other, = node_selected
+
+ # now we have 2 nodes to operate on
+ if not node_active.inputs:
+ operator.report({'ERROR'}, "Active node has no inputs")
+ return
+
+ if not node_other.outputs:
+ operator.report({'ERROR'}, "Selected node has no outputs")
+ return
+
+ socket_in = node_active.inputs[0]
+ socket_out = node_other.outputs[0]
+
+ # add a link between the two nodes
+ node_link = node_tree.links.new(socket_in, socket_out)
+
+
+class NodeOperator(bpy.types.Operator):
+ """Tooltip"""
+ bl_idname = "node.simple_operator"
+ bl_label = "Simple Node Operator"
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ return space.type == 'NODE_EDITOR'
+
+ def execute(self, context):
+ main(context)
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(NodeOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(NodeOperator)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/operator_simple.py b/release/scripts/templates_py/operator_simple.py
new file mode 100644
index 00000000000..715daa3a8b4
--- /dev/null
+++ b/release/scripts/templates_py/operator_simple.py
@@ -0,0 +1,35 @@
+import bpy
+
+
+def main(context):
+ for ob in context.scene.objects:
+ print(ob)
+
+
+class SimpleOperator(bpy.types.Operator):
+ """Tooltip"""
+ bl_idname = "object.simple_operator"
+ bl_label = "Simple Object Operator"
+
+ @classmethod
+ def poll(cls, context):
+ return context.active_object is not None
+
+ def execute(self, context):
+ main(context)
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(SimpleOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(SimpleOperator)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.object.simple_operator()
diff --git a/release/scripts/templates_py/operator_uv.py b/release/scripts/templates_py/operator_uv.py
new file mode 100644
index 00000000000..fdd0b993f8b
--- /dev/null
+++ b/release/scripts/templates_py/operator_uv.py
@@ -0,0 +1,56 @@
+import bpy
+
+
+def main(context):
+ obj = context.active_object
+ mesh = obj.data
+
+ is_editmode = (obj.mode == 'EDIT')
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ if not mesh.uv_textures:
+ uvtex = bpy.ops.mesh.uv_texture_add()
+ else:
+ uvtex = mesh.uv_textures.active
+
+ # adjust UVs
+ for i, uv in enumerate(uvtex.data):
+ uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
+ for j, v_idx in enumerate(mesh.faces[i].vertices):
+ if uv.select_uv[j]:
+ # apply the location of the vertex as a UV
+ uvs[j][:] = mesh.vertices[v_idx].co.xy
+
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+
+class UvOperator(bpy.types.Operator):
+ """UV Operator description"""
+ bl_idname = "uv.simple_operator"
+ bl_label = "Simple UV Operator"
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.active_object
+ return (obj and obj.type == 'MESH')
+
+ def execute(self, context):
+ main(context)
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(UvOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(UvOperator)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.uv.simple_operator()
diff --git a/release/scripts/templates_py/script_stub.py b/release/scripts/templates_py/script_stub.py
new file mode 100644
index 00000000000..44c7b802e2c
--- /dev/null
+++ b/release/scripts/templates_py/script_stub.py
@@ -0,0 +1,14 @@
+# This stub runs a python script relative to the currently open
+# blend file, useful when editing scripts externally.
+
+import bpy
+import os
+
+# Use your own script name here:
+filename = "my_script.py"
+
+filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename)
+global_namespace = {"__file__": filepath, "__name__": "__main__"}
+file = open(filepath, 'rb')
+exec(compile(file.read(), filepath, 'exec'), global_namespace)
+file.close()
diff --git a/release/scripts/templates_py/ui_menu.py b/release/scripts/templates_py/ui_menu.py
new file mode 100644
index 00000000000..a21e5ed86c8
--- /dev/null
+++ b/release/scripts/templates_py/ui_menu.py
@@ -0,0 +1,49 @@
+import bpy
+
+
+class CustomMenu(bpy.types.Menu):
+ bl_label = "Custom Menu"
+ bl_idname = "OBJECT_MT_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile").copy = True
+
+ layout.operator("object.shade_smooth")
+
+ layout.label(text="Hello world!", icon='WORLD_DATA')
+
+ # use an operator enum property to populate a sub-menu
+ layout.operator_menu_enum("object.select_by_type",
+ property="type",
+ text="Select All by Type...",
+ )
+
+ # call another menu
+ layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
+
+
+def draw_item(self, context):
+ layout = self.layout
+ layout.menu(CustomMenu.bl_idname)
+
+
+def register():
+ bpy.utils.register_class(CustomMenu)
+
+ # lets add ourselves to the main header
+ bpy.types.INFO_HT_header.append(draw_item)
+
+
+def unregister():
+ bpy.utils.unregister_class(CustomMenu)
+
+ bpy.types.INFO_HT_header.remove(draw_item)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
diff --git a/release/scripts/templates_py/ui_menu_simple.py b/release/scripts/templates_py/ui_menu_simple.py
new file mode 100644
index 00000000000..2129dfd81a4
--- /dev/null
+++ b/release/scripts/templates_py/ui_menu_simple.py
@@ -0,0 +1,26 @@
+import bpy
+
+
+class SimpleCustomMenu(bpy.types.Menu):
+ bl_label = "Simple Custom Menu"
+ bl_idname = "OBJECT_MT_simple_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile")
+
+
+def register():
+ bpy.utils.register_class(SimpleCustomMenu)
+
+
+def unregister():
+ bpy.utils.unregister_class(SimpleCustomMenu)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
diff --git a/release/scripts/templates_py/ui_panel.py b/release/scripts/templates_py/ui_panel.py
new file mode 100644
index 00000000000..cacdb83e815
--- /dev/null
+++ b/release/scripts/templates_py/ui_panel.py
@@ -0,0 +1,73 @@
+import bpy
+
+
+class LayoutDemoPanel(bpy.types.Panel):
+ """Creates a Panel in the scene context of the properties editor"""
+ bl_label = "Layout Demo"
+ bl_idname = "SCENE_PT_layout"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "scene"
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+
+ # Create a simple row.
+ layout.label(text=" Simple Row:")
+
+ row = layout.row()
+ row.prop(scene, "frame_start")
+ row.prop(scene, "frame_end")
+
+ # Create an row where the buttons are aligned to each other.
+ layout.label(text=" Aligned Row:")
+
+ row = layout.row(align=True)
+ row.prop(scene, "frame_start")
+ row.prop(scene, "frame_end")
+
+ # Create two columns, by using a split layout.
+ split = layout.split()
+
+ # First column
+ col = split.column()
+ col.label(text="Column One:")
+ col.prop(scene, "frame_end")
+ col.prop(scene, "frame_start")
+
+ # Second column, aligned
+ col = split.column(align=True)
+ col.label(text="Column Two:")
+ col.prop(scene, "frame_start")
+ col.prop(scene, "frame_end")
+
+ # Big render button
+ layout.label(text="Big Button:")
+ row = layout.row()
+ row.scale_y = 3.0
+ row.operator("render.render")
+
+ # Different sizes in a row
+ layout.label(text="Different button sizes:")
+ row = layout.row(align=True)
+ row.operator("render.render")
+
+ sub = row.row()
+ sub.scale_x = 2.0
+ sub.operator("render.render")
+
+ row.operator("render.render")
+
+
+def register():
+ bpy.utils.register_class(LayoutDemoPanel)
+
+
+def unregister():
+ bpy.utils.unregister_class(LayoutDemoPanel)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/release/scripts/templates_py/ui_panel_simple.py b/release/scripts/templates_py/ui_panel_simple.py
new file mode 100644
index 00000000000..9bcc750560f
--- /dev/null
+++ b/release/scripts/templates_py/ui_panel_simple.py
@@ -0,0 +1,38 @@
+import bpy
+
+
+class HelloWorldPanel(bpy.types.Panel):
+ """Creates a Panel in the Object properties window"""
+ bl_label = "Hello World Panel"
+ bl_idname = "OBJECT_PT_hello"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+
+ obj = context.object
+
+ row = layout.row()
+ row.label(text="Hello world!", icon='WORLD_DATA')
+
+ row = layout.row()
+ row.label(text="Active object is: " + obj.name)
+ row = layout.row()
+ row.prop(obj, "name")
+
+ row = layout.row()
+ row.operator("mesh.primitive_cube_add")
+
+
+def register():
+ bpy.utils.register_class(HelloWorldPanel)
+
+
+def unregister():
+ bpy.utils.unregister_class(HelloWorldPanel)
+
+
+if __name__ == "__main__":
+ register()