Merge from trunk -r 25003:25745.
authorArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 5 Jan 2010 19:21:59 +0000 (19:21 +0000)
committerArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 5 Jan 2010 19:21:59 +0000 (19:21 +0000)
52 files changed:
CMake/macros.cmake
CMakeLists.txt
config/linux2-config.py
config/win32-vc-config.py
config/win64-vc-config.py
release/scripts/io/import_bvh.py [new file with mode: 0644]
release/ui/bpy_ops.py [new file with mode: 0644]
release/ui/buttons_data_armature.py [new file with mode: 0644]
release/ui/buttons_data_bone.py [new file with mode: 0644]
release/ui/buttons_data_camera.py [new file with mode: 0644]
release/ui/buttons_data_curve.py [new file with mode: 0644]
release/ui/buttons_data_empty.py [new file with mode: 0644]
release/ui/buttons_data_lamp.py [new file with mode: 0644]
release/ui/buttons_data_lattice.py [new file with mode: 0644]
release/ui/buttons_data_mesh.py [new file with mode: 0644]
release/ui/buttons_data_metaball.py [new file with mode: 0644]
release/ui/buttons_data_modifier.py [new file with mode: 0644]
release/ui/buttons_data_text.py [new file with mode: 0644]
release/ui/buttons_game.py [new file with mode: 0644]
release/ui/buttons_material.py [new file with mode: 0644]
release/ui/buttons_object.py [new file with mode: 0644]
release/ui/buttons_object_constraint.py [new file with mode: 0644]
release/ui/buttons_particle.py [new file with mode: 0644]
release/ui/buttons_physics_cloth.py [new file with mode: 0644]
release/ui/buttons_physics_field.py [new file with mode: 0644]
release/ui/buttons_physics_fluid.py [new file with mode: 0644]
release/ui/buttons_physics_smoke.py [new file with mode: 0644]
release/ui/buttons_physics_softbody.py [new file with mode: 0644]
release/ui/buttons_scene.py [new file with mode: 0644]
release/ui/buttons_texture.py [new file with mode: 0644]
release/ui/buttons_world.py [new file with mode: 0644]
release/ui/space_buttons.py [new file with mode: 0644]
release/ui/space_console.py [new file with mode: 0644]
release/ui/space_filebrowser.py [new file with mode: 0644]
release/ui/space_image.py [new file with mode: 0644]
release/ui/space_info.py [new file with mode: 0644]
release/ui/space_logic.py [new file with mode: 0644]
release/ui/space_node.py [new file with mode: 0644]
release/ui/space_outliner.py [new file with mode: 0644]
release/ui/space_sequencer.py [new file with mode: 0644]
release/ui/space_text.py [new file with mode: 0644]
release/ui/space_time.py [new file with mode: 0644]
release/ui/space_userpref.py [new file with mode: 0644]
release/ui/space_view3d.py [new file with mode: 0644]
release/ui/space_view3d_toolbar.py [new file with mode: 0644]
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/intern/image.c
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/windowmanager/intern/wm_operators.c
tools/Blender.py
tools/mstoolkit.py [changed mode: 0644->0755]

index 258cbdf..de84b5f 100644 (file)
@@ -67,6 +67,11 @@ MACRO(SETUP_LIBDIRS)
   IF(WITH_OPENAL)
     LINK_DIRECTORIES(${OPENAL_LIBPATH})
   ENDIF(WITH_OPENAL)
+  IF(WITH_OPENCOLLADA)
+    LINK_DIRECTORIES(${OPENCOLLADA_LIBPATH})
+    LINK_DIRECTORIES(${PCRE_LIBPATH})
+    LINK_DIRECTORIES(${EXPAT_LIBPATH})
+  ENDIF(WITH_OPENCOLLADA)
   IF(WITH_JACK)
     LINK_DIRECTORIES(${JACK_LIBPATH})
   ENDIF(WITH_JACK)
@@ -76,11 +81,6 @@ MACRO(SETUP_LIBDIRS)
   IF(WITH_FFTW3)
     LINK_DIRECTORIES(${FFTW3_LIBPATH})
   ENDIF(WITH_FFTW3)
-  IF(WITH_OPENCOLLADA)
-    LINK_DIRECTORIES(${OPENCOLLADA_LIBPATH})
-    LINK_DIRECTORIES(${PCRE_LIBPATH})
-    LINK_DIRECTORIES(${EXPAT_LIBPATH})
-  ENDIF(WITH_OPENCOLLADA)
 
   IF(WIN32)
     LINK_DIRECTORIES(${PTHREADS_LIBPATH})
index a926b48..c5bce89 100644 (file)
@@ -79,7 +79,7 @@ OPTION(WITH_LZMA          "Enable best LZMA compression, used for pointcache" ON
 OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation" OFF)
 OPTION(WITH_BUILDINFO     "Include extra build details" ON)
 OPTION(WITH_INSTALL       "Install accompanying scripts and language files needed to run blender" ON)
-OPTION(WITH_OPENCOLLADA                "Enable OpenCollada Support (http://www.opencollada.org/)"      OFF)
+OPTION(WITH_OPENCOLLADA                "Enable OpenCollada Support (http://www.opencollada.org/)"      ON)
 
 # Unix defaults to OpenMP On
 IF (UNIX)
index abe79ba..fe07d6d 100644 (file)
@@ -151,7 +151,7 @@ BF_OPENGL_LIB = 'GL GLU X11 Xi'
 BF_OPENGL_LIBPATH = '/usr/X11R6/lib'
 BF_OPENGL_LIB_STATIC = '${BF_OPENGL_LIBPATH}/libGL.a ${BF_OPENGL_LIBPATH}/libGLU.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a ${BF_OPENGL_LIBPATH}/libX11.a ${BF_OPENGL_LIBPATH}/libXi.a ${BF_OPENGL_LIBPATH}/libXext.a ${BF_OPENGL_LIBPATH}/libXxf86vm.a'
 
-WITH_BF_COLLADA = False
+WITH_BF_COLLADA = True
 BF_COLLADA = '#source/blender/collada'
 BF_COLLADA_INC = '${BF_COLLADA}'
 BF_COLLADA_LIB = 'bf_collada'
index f18ed3e..a93145d 100644 (file)
@@ -138,7 +138,7 @@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
 WITH_BF_REDCODE = False  
 BF_REDCODE_INC = '#extern'
 
-WITH_BF_COLLADA = False
+WITH_BF_COLLADA = True
 BF_COLLADA = '#source/blender/collada'
 BF_COLLADA_INC = '${BF_COLLADA}'
 BF_COLLADA_LIB = 'bf_collada'
index 4576405..ee70b62 100644 (file)
@@ -151,7 +151,7 @@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
 WITH_BF_REDCODE = False  
 BF_REDCODE_INC = '#extern'
 
-WITH_BF_COLLADA = False
+WITH_BF_COLLADA = True
 BF_COLLADA = '#source/blender/collada'
 BF_COLLADA_INC = '${BF_COLLADA}'
 BF_COLLADA_LIB = 'bf_collada'
diff --git a/release/scripts/io/import_bvh.py b/release/scripts/io/import_bvh.py
new file mode 100644 (file)
index 0000000..5265007
--- /dev/null
@@ -0,0 +1,881 @@
+import math
+
+# import Blender
+import bpy
+# import BPyMessages
+import Mathutils
+Vector= Mathutils.Vector
+Euler= Mathutils.Euler
+Matrix= Mathutils.Matrix
+RotationMatrix= Mathutils.RotationMatrix
+TranslationMatrix= Mathutils.TranslationMatrix
+
+# NASTY GLOBAL
+ROT_STYLE = 'QUAT'
+
+DEG2RAD = 0.017453292519943295
+
+class bvh_node_class(object):
+       __slots__=(\
+       'name',# bvh joint name
+       'parent',# bvh_node_class type or None for no parent
+       'children',# a list of children of this type.
+       'rest_head_world',# worldspace rest location for the head of this node
+       'rest_head_local',# localspace rest location for the head of this node
+       'rest_tail_world',# # worldspace rest location for the tail of this node
+       'rest_tail_local',# # worldspace rest location for the tail of this node
+       'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
+       'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
+       'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz)
+       'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1)
+       'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
+       'temp')# use this for whatever you want
+       
+       def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order):
+               self.name= name
+               self.rest_head_world= rest_head_world
+               self.rest_head_local= rest_head_local
+               self.rest_tail_world= None
+               self.rest_tail_local= None
+               self.parent= parent
+               self.channels= channels
+               self.rot_order= rot_order
+               
+               # convenience functions
+               self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1
+               self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1
+               
+               
+               self.children= []
+               
+               # list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
+               # even if the channels arnt used they will just be zero
+               # 
+               self.anim_data= [(0,0,0,0,0,0)] 
+               
+       
+       def __repr__(self):
+               return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\
+               (self.name,\
+               self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\
+               self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z)
+       
+
+
+# Change the order rotation is applied.
+MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
+MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
+
+def eulerRotate(x,y,z, rot_order): 
+       
+       # Clamp all values between 0 and 360, values outside this raise an error.
+       mats=[RotationMatrix(math.radians(x%360),3,'x'), RotationMatrix(math.radians(y%360),3,'y'), RotationMatrix(math.radians(z%360),3,'z')]
+       # print rot_order
+       # Standard BVH multiplication order, apply the rotation in the order Z,X,Y
+       
+       #XXX, order changes???
+       #eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler()   
+       eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).toEuler()     
+       
+       eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z) 
+       
+       return eul
+
+def read_bvh(context, file_path, GLOBAL_SCALE=1.0):
+       # File loading stuff
+       # Open the file for importing
+       file = open(file_path, 'rU')    
+       
+       # Seperate into a list of lists, each line a list of words.
+       file_lines = file.readlines()
+       # Non standard carrage returns?
+       if len(file_lines) == 1:
+               file_lines = file_lines[0].split('\r')
+       
+       # Split by whitespace.
+       file_lines =[ll for ll in [ l.split() for l in file_lines] if ll]
+       
+       
+       # Create Hirachy as empties
+       
+       if file_lines[0][0].lower() == 'hierarchy':
+               #print 'Importing the BVH Hierarchy for:', file_path
+               pass
+       else:
+               raise 'ERROR: This is not a BVH file'
+       
+       bvh_nodes= {None:None}
+       bvh_nodes_serial = [None]
+       
+       channelIndex = -1
+       
+
+       lineIdx = 0 # An index for the file.
+       while lineIdx < len(file_lines) -1:
+               #...
+               if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
+                       
+                       # Join spaces into 1 word with underscores joining it.
+                       if len(file_lines[lineIdx]) > 2:
+                               file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:])
+                               file_lines[lineIdx] = file_lines[lineIdx][:2]
+                       
+                       # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
+                       
+                       # Make sure the names are unique- Object names will match joint names exactly and both will be unique.
+                       name = file_lines[lineIdx][1]
+                       
+                       #print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * '  ', name,  bvh_nodes_serial[-1])
+                       
+                       lineIdx += 2 # Incriment to the next line (Offset)
+                       rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
+                       lineIdx += 1 # Incriment to the next line (Channels)
+                       
+                       # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
+                       # newChannel references indecies to the motiondata,
+                       # if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended 
+                       # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
+                       my_channel = [-1, -1, -1, -1, -1, -1] 
+                       my_rot_order= [None, None, None]
+                       rot_count= 0
+                       for channel in file_lines[lineIdx][2:]:
+                               channel= channel.lower()
+                               channelIndex += 1 # So the index points to the right channel
+                               if   channel == 'xposition':    my_channel[0] = channelIndex
+                               elif channel == 'yposition':    my_channel[1] = channelIndex
+                               elif channel == 'zposition':    my_channel[2] = channelIndex
+                               
+                               elif channel == 'xrotation':
+                                       my_channel[3] = channelIndex
+                                       my_rot_order[rot_count]= 0
+                                       rot_count+=1
+                               elif channel == 'yrotation':
+                                       my_channel[4] = channelIndex
+                                       my_rot_order[rot_count]= 1
+                                       rot_count+=1
+                               elif channel == 'zrotation':
+                                       my_channel[5] = channelIndex
+                                       my_rot_order[rot_count]= 2
+                                       rot_count+=1
+                       
+                       channels = file_lines[lineIdx][2:]
+                       
+                       my_parent= bvh_nodes_serial[-1] # account for none
+                       
+                       
+                       # Apply the parents offset accumletivly
+                       if my_parent==None:
+                               rest_head_world= Vector(rest_head_local)
+                       else:
+                               rest_head_world= my_parent.rest_head_world + rest_head_local
+                       
+                       bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order)
+                       
+                       # If we have another child then we can call ourselves a parent, else 
+                       bvh_nodes_serial.append(bvh_node)
+
+               # Account for an end node
+               if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
+                       lineIdx += 2 # Incriment to the next line (Offset)
+                       rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
+                       
+                       bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail
+                       bvh_nodes_serial[-1].rest_tail_local= rest_tail
+                       
+                       
+                       # Just so we can remove the Parents in a uniform way- End end never has kids
+                       # so this is a placeholder
+                       bvh_nodes_serial.append(None)
+               
+               if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
+                       bvh_nodes_serial.pop() # Remove the last item
+               
+               if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
+                       #print '\nImporting motion data'
+                       lineIdx += 3 # Set the cursor to the first frame
+                       break
+                       
+               lineIdx += 1
+       
+       
+       # Remove the None value used for easy parent reference
+       del bvh_nodes[None]
+       # Dont use anymore
+       del bvh_nodes_serial
+       
+       bvh_nodes_list= bvh_nodes.values()
+       
+       while lineIdx < len(file_lines):
+               line= file_lines[lineIdx]
+               for bvh_node in bvh_nodes_list:
+                       #for bvh_node in bvh_nodes_serial:
+                       lx= ly= lz= rx= ry= rz= 0.0
+                       channels= bvh_node.channels
+                       anim_data= bvh_node.anim_data
+                       if channels[0] != -1:
+                               lx= GLOBAL_SCALE * float(  line[channels[0]] )
+                               
+                       if channels[1] != -1:
+                               ly= GLOBAL_SCALE * float(  line[channels[1]] )
+                       
+                       if channels[2] != -1:
+                               lz= GLOBAL_SCALE * float(  line[channels[2]] )
+                       
+                       if channels[3] != -1 or channels[4] != -1 or channels[5] != -1:
+                               rx, ry, rz = float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] )
+                               
+                               if ROT_STYLE != 'NATIVE':
+                                       rx, ry, rz = eulerRotate(rx, ry, rz, bvh_node.rot_order)
+                               
+                               #x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
+                               
+                               # Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
+                               # Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
+                               
+                               while anim_data[-1][3] - rx >  180: rx+=360
+                               while anim_data[-1][3] - rx < -180: rx-=360
+                               
+                               while anim_data[-1][4] - ry >  180: ry+=360
+                               while anim_data[-1][4] - ry < -180: ry-=360
+                               
+                               while anim_data[-1][5] - rz >  180: rz+=360
+                               while anim_data[-1][5] - rz < -180: rz-=360
+                               
+                       # Done importing motion data #
+                       anim_data.append( (lx, ly, lz, rx, ry, rz) )
+               lineIdx += 1
+       
+       # Assign children
+       for bvh_node in bvh_nodes.values():             
+               bvh_node_parent= bvh_node.parent
+               if bvh_node_parent:
+                       bvh_node_parent.children.append(bvh_node)
+       
+       # Now set the tip of each bvh_node
+       for bvh_node in bvh_nodes.values():
+               
+               if not bvh_node.rest_tail_world:
+                       if len(bvh_node.children)==0:
+                               # could just fail here, but rare BVH files have childless nodes
+                               bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
+                               bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
+                       elif len(bvh_node.children)==1:
+                               bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
+                               bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
+                       else:
+                               # allow this, see above
+                               #if not bvh_node.children:
+                               #       raise 'error, bvh node has no end and no children. bad file'
+                                       
+                               # Removed temp for now
+                               rest_tail_world= Vector(0,0,0)
+                               rest_tail_local= Vector(0,0,0)
+                               for bvh_node_child in bvh_node.children:
+                                       rest_tail_world += bvh_node_child.rest_head_world
+                                       rest_tail_local += bvh_node_child.rest_head_local
+                               
+                               bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children))
+                               bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children))
+
+               # Make sure tail isnt the same location as the head.
+               if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE:
+                       
+                       bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10
+                       bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10
+                       
+               
+               
+       return bvh_nodes
+
+
+
+def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
+       
+       if IMPORT_START_FRAME<1:
+               IMPORT_START_FRAME= 1
+               
+       scn= context.scene
+       scn.objects.selected = []
+       
+       objects= []
+       
+       def add_ob(name):
+               ob = scn.objects.new('Empty')
+               objects.append(ob)
+               return ob
+       
+       # Add objects
+       for name, bvh_node in bvh_nodes.items():
+               bvh_node.temp= add_ob(name)
+       
+       # Parent the objects
+       for bvh_node in bvh_nodes.values():
+               bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast.
+       
+       # Offset
+       for bvh_node in bvh_nodes.values():
+               # Make relative to parents offset
+               bvh_node.temp.loc= bvh_node.rest_head_local
+       
+       # Add tail objects
+       for name, bvh_node in bvh_nodes.items():
+               if not bvh_node.children:
+                       ob_end= add_ob(name + '_end')
+                       bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast.
+                       ob_end.loc= bvh_node.rest_tail_local
+       
+       
+       # Animate the data, the last used bvh_node will do since they all have the same number of frames
+       for current_frame in range(len(bvh_node.anim_data)):
+               Blender.Set('curframe', current_frame+IMPORT_START_FRAME)
+               
+               for bvh_node in bvh_nodes.values():
+                       lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame]
+                       
+                       rest_head_local= bvh_node.rest_head_local
+                       bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
+                       
+                       bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
+                       
+                       bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
+       
+       scn.update(1)
+       return objects
+
+
+
+def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
+       
+       if IMPORT_START_FRAME<1:
+               IMPORT_START_FRAME= 1
+               
+       
+       # Add the new armature, 
+       scn = context.scene
+#XXX   scn.objects.selected = []
+       for ob in scn.objects:
+               ob.selected = False
+       
+       
+#XXX   arm_data= bpy.data.armatures.new()
+#XXX   arm_ob = scn.objects.new(arm_data)
+       bpy.ops.object.armature_add()
+       arm_ob= scn.objects[-1]
+       arm_data= arm_ob.data
+
+       
+       
+       
+#XXX   scn.objects.context = [arm_ob]
+#XXX   scn.objects.active = arm_ob
+       arm_ob.selected= True
+       scn.objects.active= arm_ob
+       print(scn.objects.active)
+       
+       
+       # Put us into editmode
+#XXX   arm_data.makeEditable()
+       
+       bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+       bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+       
+       
+       # Get the average bone length for zero length bones, we may not use this.
+       average_bone_length= 0.0
+       nonzero_count= 0
+       for bvh_node in bvh_nodes.values():
+               l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length
+               if l:
+                       average_bone_length+= l
+                       nonzero_count+=1
+       
+       # Very rare cases all bones couldbe zero length???
+       if not average_bone_length:
+               average_bone_length = 0.1
+       else:
+               # Normal operation
+               average_bone_length = average_bone_length/nonzero_count
+       
+       
+#XXX - sloppy operator code
+       
+       bpy.ops.armature.delete()
+       bpy.ops.armature.select_all_toggle()
+       bpy.ops.armature.delete()
+
+       ZERO_AREA_BONES= []
+       for name, bvh_node in bvh_nodes.items():
+               # New editbone
+               bpy.ops.armature.bone_primitive_add(name="Bone")
+               
+#XXX           bone= bvh_node.temp= Blender.Armature.Editbone()
+               bone= bvh_node.temp= arm_data.edit_bones[-1]
+
+               bone.name= name
+#              arm_data.bones[name]= bone
+               
+               bone.head= bvh_node.rest_head_world
+               bone.tail= bvh_node.rest_tail_world
+               
+               # ZERO AREA BONES.
+               if (bone.head-bone.tail).length < 0.001:
+                       if bvh_node.parent:
+                               ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local
+                               if ofs.length: # is our parent zero length also?? unlikely
+                                       bone.tail= bone.tail+ofs
+                               else:
+                                       bone.tail.y= bone.tail.y+average_bone_length
+                       else:
+                               bone.tail.y= bone.tail.y+average_bone_length
+                       
+                       ZERO_AREA_BONES.append(bone.name)
+       
+       
+       for bvh_node in bvh_nodes.values():
+               if bvh_node.parent:
+                       # bvh_node.temp is the Editbone
+                       
+                       # Set the bone parent
+                       bvh_node.temp.parent= bvh_node.parent.temp
+                       
+                       # Set the connection state
+                       if not bvh_node.has_loc and\
+                       bvh_node.parent and\
+                       bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
+                       bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
+                               bvh_node.temp.connected= True
+       
+       # Replace the editbone with the editbone name,
+       # to avoid memory errors accessing the editbone outside editmode
+       for bvh_node in bvh_nodes.values():
+               bvh_node.temp= bvh_node.temp.name
+       
+#XXX   arm_data.update()
+       
+       # Now Apply the animation to the armature
+       
+       # Get armature animation data
+       bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+       bpy.ops.object.mode_set(mode='POSE', toggle=False)
+       
+       pose= arm_ob.pose
+       pose_bones= pose.pose_channels
+       
+       
+       if ROT_STYLE=='NATIVE':
+               eul_order_lookup = {\
+                       (0,1,2):'XYZ',
+                       (0,2,1):'XZY',
+                       (1,0,2):'YXZ',
+                       (1,2,0):'YZX',
+                       (2,0,1):'ZXY',
+                       (2,1,0):'ZYZ'
+               }
+               
+               for bvh_node in bvh_nodes.values():
+                       bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
+                       pose_bone= pose_bones[bone_name]
+                       pose_bone.rotation_mode  = eul_order_lookup[tuple(bvh_node.rot_order)]
+               
+       elif ROT_STYLE=='XYZ':
+               for pose_bone in pose_bones:
+                       pose_bone.rotation_mode  = 'XYZ'
+       else:
+               # Quats default
+               pass 
+       
+       
+       bpy.ops.pose.select_all_toggle() # set
+       bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX -     -4 ???
+       
+
+       
+       
+       
+       #for p in pose_bones:
+       #       print(p)
+       
+       
+#XXX   action = Blender.Armature.NLA.NewAction("Action") 
+#XXX   action.setActive(arm_ob)
+       
+       #bpy.ops.act.new()
+       #action = bpy.data.actions[-1]
+       
+       # arm_ob.animation_data.action = action
+       action = arm_ob.animation_data.action
+       
+       
+       
+       
+       #xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ]
+       
+       # Replace the bvh_node.temp (currently an editbone)
+       # With a tuple  (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
+       for bvh_node in bvh_nodes.values():
+               bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
+               pose_bone= pose_bones[bone_name]
+               rest_bone= arm_data.bones[bone_name]
+#XXX           bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart()
+               bone_rest_matrix = rest_bone.matrix.rotationPart()
+               
+               
+               bone_rest_matrix_inv= Matrix(bone_rest_matrix)
+               bone_rest_matrix_inv.invert()
+               
+               bone_rest_matrix_inv.resize4x4()
+               bone_rest_matrix.resize4x4()
+               bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv)
+               
+       
+       # Make a dict for fast access without rebuilding a list all the time.
+       '''
+       xformConstants_dict={
+       (True,True):    [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\
+       (False,True):   [Blender.Object.Pose.ROT],\
+       (True,False):   [Blender.Object.Pose.LOC],\
+       (False,False):  [],\
+       }
+       '''
+       
+       # KEYFRAME METHOD, SLOW, USE IPOS DIRECT
+       
+       # Animate the data, the last used bvh_node will do since they all have the same number of frames
+       for current_frame in range(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
+               # print current_frame
+               
+               #if current_frame==150: # debugging
+               #       break
+               
+               # Dont neet to set the current frame
+               for bvh_node in bvh_nodes.values():
+                       pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+                       lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1]
+                       
+                       if bvh_node.has_rot:
+                               
+                               if ROT_STYLE=='QUAT':
+                                       # Set the rotation, not so simple
+                                       bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
+                                       
+                                       bone_rotation_matrix.resize4x4()
+                                       #XXX ORDER CHANGE???
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() # ORIGINAL
+                                       # pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
+                                       # pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).toQuat() # BAD
+                                       # pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
+                                       # pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
+                                       
+                                       #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()
+                                       
+                                       #pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix  * bone_rest_matrix_inv).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix  * bone_rest_matrix ).toQuat()
+                                       
+                                       pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
+                                       
+                               else:
+                                       bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
+                                       bone_rotation_matrix.resize4x4()
+                                       
+                                       eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toEuler()
+                                       
+                                       #pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz)
+                                       pose_bone.rotation_euler = eul
+                               
+                               print("ROTATION" + str(Euler(math.radians(rx), math.radians(ry), math.radians(rz))))
+                       
+                       if bvh_node.has_loc:
+                               # Set the Location, simple too
+                               
+                               #XXX ORDER CHANGE
+                               # pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works
+                               # pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translationPart()
+                               # pose_bone.location= lx, ly, lz
+                               pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local
+                               
+
+#XXX           # TODO- add in 2.5
+                       if 0:
+                               # Get the transform 
+                               xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
+                               
+                               if xformConstants:
+                                       # Insert the keyframe from the loc/quat
+                                       pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True )
+                       else:
+                               
+                               if bvh_node.has_loc:
+                                       pose_bone.keyframe_insert("location")
+                               if bvh_node.has_rot:
+                                       if ROT_STYLE=='QUAT':
+                                               pose_bone.keyframe_insert("rotation_quaternion")
+                                       else:
+                                               pose_bone.keyframe_insert("rotation_euler")
+                               
+                               
+                       
+               # bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX -     -4 ???
+               bpy.ops.screen.frame_offset(delta=1)
+               
+               # First time, set the IPO's to linear
+#XXX   #TODO
+               if 0:
+                       if current_frame==0:
+                               for ipo in action.getAllChannelIpos().values():
+                                       if ipo:
+                                               for cur in ipo:
+                                                       cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+                                                       if IMPORT_LOOP:
+                                                               cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
+                                                       
+                                               
+               else:
+                       for cu in action.fcurves:
+                               for bez in cu.keyframe_points:
+                                       bez.interpolation = 'CONSTANT'
+               
+       # END KEYFRAME METHOD
+       
+       
+       """
+       # IPO KEYFRAME SETTING
+       # Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/
+       for bvh_node in bvh_nodes.values():
+               pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+               
+               # Get the transform 
+               xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
+               if xformConstants:
+                       pose_bone.loc[:]= 0,0,0
+                       pose_bone.quat[:]= 0,0,1,0
+                       # Insert the keyframe from the loc/quat
+                       pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants)
+
+       
+       action_ipos= action.getAllChannelIpos()
+       
+       
+       for bvh_node in bvh_nodes.values():
+               has_loc= bvh_node.has_loc
+               has_rot= bvh_node.has_rot
+               
+               if not has_rot and not has_loc:
+                       # No animation data
+                       continue
+               
+               ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key
+               
+               if has_loc:
+                       curve_xloc= ipo[Blender.Ipo.PO_LOCX]
+                       curve_yloc= ipo[Blender.Ipo.PO_LOCY]
+                       curve_zloc= ipo[Blender.Ipo.PO_LOCZ]
+                       
+                       curve_xloc.interpolation= \
+                       curve_yloc.interpolation= \
+                       curve_zloc.interpolation= \
+                       Blender.IpoCurve.InterpTypes.LINEAR
+                       
+               
+               if has_rot:
+                       curve_wquat= ipo[Blender.Ipo.PO_QUATW]
+                       curve_xquat= ipo[Blender.Ipo.PO_QUATX]
+                       curve_yquat= ipo[Blender.Ipo.PO_QUATY]
+                       curve_zquat= ipo[Blender.Ipo.PO_QUATZ]
+                       
+                       curve_wquat.interpolation= \
+                       curve_xquat.interpolation= \
+                       curve_yquat.interpolation= \
+                       curve_zquat.interpolation= \
+                       Blender.IpoCurve.InterpTypes.LINEAR
+               
+               # Get the bone 
+               pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+               
+               
+               def pose_rot(anim_data):
+                       bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix()
+                       bone_rotation_matrix.resize4x4()
+                       return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz
+               
+               def pose_loc(anim_data):
+                       return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart())
+               
+               
+               last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1
+               
+               if has_loc:
+                       pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data]
+                       
+                       # Add the start at the end, we know the start is just 0,0,0 anyway
+                       curve_xloc.append((last_frame, pose_locations[-1][0]))
+                       curve_yloc.append((last_frame, pose_locations[-1][1]))
+                       curve_zloc.append((last_frame, pose_locations[-1][2]))
+                       
+                       if len(pose_locations) > 1:
+                               ox,oy,oz= pose_locations[0]
+                               x,y,z= pose_locations[1]
+                               
+                               for i in range(1, len(pose_locations)-1): # from second frame to second last frame
+                                       
+                                       nx,ny,nz= pose_locations[i+1]
+                                       xset= yset= zset= True # we set all these by default
+                                       if abs((ox+nx)/2 - x) < 0.00001:        xset= False
+                                       if abs((oy+ny)/2 - y) < 0.00001:        yset= False
+                                       if abs((oz+nz)/2 - z) < 0.00001:        zset= False
+                                       
+                                       if xset: curve_xloc.append((i+IMPORT_START_FRAME, x))
+                                       if yset: curve_yloc.append((i+IMPORT_START_FRAME, y))
+                                       if zset: curve_zloc.append((i+IMPORT_START_FRAME, z))
+                                       
+                                       # Set the old and use the new
+                                       ox,oy,oz=       x,y,z
+                                       x,y,z=          nx,ny,nz
+               
+               
+               if has_rot:
+                       pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data]
+                       
+                       # Add the start at the end, we know the start is just 0,0,0 anyway
+                       curve_wquat.append((last_frame, pose_rotations[-1][0]))
+                       curve_xquat.append((last_frame, pose_rotations[-1][1]))
+                       curve_yquat.append((last_frame, pose_rotations[-1][2]))
+                       curve_zquat.append((last_frame, pose_rotations[-1][3]))
+                       
+                       
+                       if len(pose_rotations) > 1:
+                               ow,ox,oy,oz= pose_rotations[0]
+                               w,x,y,z= pose_rotations[1]
+                               
+                               for i in range(1, len(pose_rotations)-1): # from second frame to second last frame
+                                       
+                                       nw, nx,ny,nz= pose_rotations[i+1]
+                                       wset= xset= yset= zset= True # we set all these by default
+                                       if abs((ow+nw)/2 - w) < 0.00001:        wset= False
+                                       if abs((ox+nx)/2 - x) < 0.00001:        xset= False
+                                       if abs((oy+ny)/2 - y) < 0.00001:        yset= False
+                                       if abs((oz+nz)/2 - z) < 0.00001:        zset= False
+                                       
+                                       if wset: curve_wquat.append((i+IMPORT_START_FRAME, w))
+                                       if xset: curve_xquat.append((i+IMPORT_START_FRAME, x))
+                                       if yset: curve_yquat.append((i+IMPORT_START_FRAME, y))
+                                       if zset: curve_zquat.append((i+IMPORT_START_FRAME, z))
+                                       
+                                       # Set the old and use the new
+                                       ow,ox,oy,oz=    w,x,y,z
+                                       w,x,y,z=                nw,nx,ny,nz
+
+       # IPO KEYFRAME SETTING
+       """
+       
+# XXX NOT NEEDED NOW?
+       # pose.update()
+       return arm_ob
+
+
+#=============#
+# TESTING     #
+#=============#
+
+#('/metavr/mocap/bvh/boxer.bvh')
+#('/d/staggered_walk.bvh')
+#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
+#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
+#('/metavr/mocap/bvh/walk4.bvh') # 0 channels
+
+'''
+import os
+DIR = '/metavr/mocap/bvh/'
+for f in ('/d/staggered_walk.bvh',):
+       #for f in os.listdir(DIR)[5:6]:
+       #for f in os.listdir(DIR):
+       if f.endswith('.bvh'):
+               s = Blender.Scene.New(f)
+               s.makeCurrent()
+               #file= DIR + f
+               file= f
+               print f
+               bvh_nodes= read_bvh(file, 1.0)
+               bvh_node_dict2armature(bvh_nodes, 1)
+'''
+
+def load_bvh_ui(context, file, PREF_UI= False):
+       
+#XXX   if BPyMessages.Error_NoFile(file):
+#XXX           return
+       
+#XXX   Draw= Blender.Draw
+       
+       IMPORT_SCALE = 0.1
+       IMPORT_START_FRAME = 1
+       IMPORT_AS_ARMATURE = 1
+       IMPORT_AS_EMPTIES = 0
+       IMPORT_LOOP = 0
+       
+       # Get USER Options
+       if PREF_UI:
+               pup_block = [\
+               ('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\
+               ('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\
+               ('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\
+               ('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\
+               ('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\
+               ]
+               
+#XXX           if not Draw.PupBlock('BVH Import...', pup_block):
+#XXX                   return
+       
+       # print('Attempting import BVH', file)
+       
+       if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES:
+               raise('No import option selected')
+
+#XXX   Blender.Window.WaitCursor(1)
+       # Get the BVH data and act on it.
+       import time
+       t1= time.time()
+       print('\tparsing bvh...', end= "")
+       bvh_nodes= read_bvh(context, file, IMPORT_SCALE)
+       print('%.4f' % (time.time()-t1))
+       t1= time.time()
+       print('\timporting to blender...', end="")
+       if IMPORT_AS_ARMATURE:  bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
+       if IMPORT_AS_EMPTIES:   bvh_node_dict2objects(context, bvh_nodes,  IMPORT_START_FRAME, IMPORT_LOOP)
+       
+       print('Done in %.4f\n' % (time.time()-t1))
+#XXX   Blender.Window.WaitCursor(0)
+
+def main():
+       Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh')
+
+from bpy.props import *
+
+class BvhImporter(bpy.types.Operator):
+       '''Load a Wavefront OBJ File.'''
+       bl_idname = "import.bvh"
+       bl_label = "Import BVH"
+       
+       path = StringProperty(name="File Path", description="File path used for importing the OBJ file", maxlen= 1024, default= "")
+       
+       def execute(self, context):
+               # print("Selected: " + context.active_object.name)
+
+               read_bvh(context, self.path)
+
+               return ('FINISHED',)
+       
+       def invoke(self, context, event):       
+               wm = context.manager
+               wm.add_fileselect(self)
+               return ('RUNNING_MODAL',)
+
+
+bpy.ops.add(BvhImporter)
+
+
+import dynamic_menu
+menu_func = lambda self, context: self.layout.itemO("import.bvh", text="Motion Capture (.bvh)...")
+menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
diff --git a/release/ui/bpy_ops.py b/release/ui/bpy_ops.py
new file mode 100644 (file)
index 0000000..dff8125
--- /dev/null
@@ -0,0 +1,137 @@
+# for slightly faster access
+from bpy.__ops__ import add            as op_add
+from bpy.__ops__ import remove         as op_remove
+from bpy.__ops__ import dir            as op_dir
+from bpy.__ops__ import call           as op_call
+from bpy.__ops__ import get_rna        as op_get_rna
+
+# Keep in sync with WM_types.h
+context_dict = {
+       'INVOKE_DEFAULT':0,
+       'INVOKE_REGION_WIN':1,
+       'INVOKE_AREA':2,
+       'INVOKE_SCREEN':3,
+       'EXEC_DEFAULT':4,
+       'EXEC_REGION_WIN':5,
+       'EXEC_AREA':6,
+       'EXEC_SCREEN':7,
+}
+
+class bpy_ops(object):
+       '''
+       Fake module like class.
+       
+        bpy.ops
+       '''
+       def add(self, pyop):
+               op_add(pyop)
+       
+       def remove(self, pyop):
+               op_remove(pyop)
+       
+       def __getattr__(self, module):
+               '''
+               gets a bpy.ops submodule
+               '''
+               return bpy_ops_submodule(module)
+               
+       def __dir__(self):
+               
+               submodules = set()
+               
+               # add this classes functions
+               for id_name in dir(self.__class__):
+                       if not id_name.startswith('__'):
+                               submodules.add(id_name)
+               
+               for id_name in op_dir():
+                       id_split = id_name.split('_OT_', 1)
+                       
+                       if len(id_split) == 2:
+                               submodules.add(id_split[0].lower())
+                       else:
+                               submodules.add(id_split[0])
+               
+               return list(submodules)
+               
+       def __repr__(self):
+               return "<module like class 'bpy.ops'>"
+
+
+class bpy_ops_submodule(object):
+       '''
+       Utility class to fake submodules.
+       
+       eg. bpy.ops.object
+       '''
+       __keys__ = ('module',)
+       
+       def __init__(self, module):
+               self.module = module
+               
+       def __getattr__(self, func):
+               '''
+               gets a bpy.ops.submodule function
+               '''
+               return bpy_ops_submodule_op(self.module, func)
+               
+       def __dir__(self):
+               
+               functions = set()
+               
+               module_upper = self.module.upper()
+               
+               for id_name in op_dir():
+                       id_split = id_name.split('_OT_', 1)
+                       if len(id_split) == 2 and module_upper == id_split[0]:
+                               functions.add(id_split[1])
+               
+               return list(functions)
+       
+       def __repr__(self):
+               return "<module like class 'bpy.ops.%s'>" % self.module
+
+class bpy_ops_submodule_op(object):
+       '''
+       Utility class to fake submodule operators.
+       
+       eg. bpy.ops.object.somefunc
+       '''
+       __keys__ = ('module', 'func')
+       def __init__(self, module, func):
+               self.module = module
+               self.func = func
+       
+       def idname(self):
+               # submod.foo -> SUBMOD_OT_foo
+               return self.module.upper() + '_OT_' + self.func
+       
+       def __call__(self, *args, **kw):
+               
+               # Get the operator from blender
+               if len(args) > 1:
+                       raise ValueError("only one argument for the execution context is supported ")
+               
+               if args:
+                       try:
+                               context = context_dict[args[0]]
+                       except:
+                               raise ValueError("Expected a single context argument in: " + str(list(context_dict.keys())))
+                       
+                       return op_call(self.idname(), kw, context)
+               
+               else:
+                       return op_call(self.idname(), kw)
+       
+       def get_rna(self):
+               '''
+               currently only used for '__rna__'
+               '''
+               return op_get_rna(self.idname())
+                       
+       
+       def __repr__(self):
+               return "<function bpy.ops.%s.%s at 0x%x'>" % (self.module, self.func, id(self))
+
+import bpy
+bpy.ops = bpy_ops()
diff --git a/release/ui/buttons_data_armature.py b/release/ui/buttons_data_armature.py
new file mode 100644 (file)
index 0000000..5924a2e
--- /dev/null
@@ -0,0 +1,177 @@
+
+import bpy
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.armature)
+
+class DATA_PT_context_arm(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               arm = context.armature
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif arm:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_skeleton(DataButtonsPanel):
+       __label__ = "Skeleton"
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               arm = context.armature
+               space = context.space_data
+
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Layers:")
+               col.itemR(arm, "layer", text="")
+               col.itemL(text="Protected Layers:")
+               col.itemR(arm, "layer_protection", text="")
+               col.itemL(text="Edit Options:")
+               col.itemR(arm, "x_axis_mirror")
+               col.itemR(arm, "auto_ik")
+               
+               col = split.column()
+               col.itemR(arm, "rest_position")
+               col.itemL(text="Deform:")
+               col.itemR(arm, "deform_vertexgroups", text="Vertex Groups")
+               col.itemR(arm, "deform_envelope", text="Envelopes")
+               col.itemR(arm, "deform_quaternion", text="Quaternion")
+               col.itemR(arm, "deform_bbone_rest", text="B-Bones Rest")
+               
+class DATA_PT_display(DataButtonsPanel):
+       __label__ = "Display"
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               arm = context.armature
+
+               layout.row().itemR(arm, "drawtype", expand=True)
+
+               flow = layout.column_flow()
+               flow.itemR(arm, "draw_names", text="Names")
+               flow.itemR(arm, "draw_axes", text="Axes")
+               flow.itemR(arm, "draw_custom_bone_shapes", text="Shapes")
+               flow.itemR(arm, "draw_group_colors", text="Colors")
+               flow.itemR(arm, "delay_deform", text="Delay Refresh")
+
+class DATA_PT_bone_groups(DataButtonsPanel):
+       __label__ = "Bone Groups"
+       
+       def poll(self, context):
+               return (context.object and context.object.type=='ARMATURE' and context.object.pose)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               pose = ob.pose
+               
+               row = layout.row()
+               row.template_list(pose, "bone_groups", pose, "active_bone_group_index")
+               
+               col = row.column(align=True)
+               col.active = (ob.proxy == None)
+               col.itemO("pose.group_add", icon='ICON_ZOOMIN', text="")
+               col.itemO("pose.group_remove", icon='ICON_ZOOMOUT', text="")
+               
+               group = pose.active_bone_group
+               if group:
+                       col = layout.column()
+                       col.active= (ob.proxy == None)
+                       col.itemR(group, "name")
+                       
+                       split = layout.split(0.5)
+                       split.active= (ob.proxy == None)
+                       split.itemR(group, "color_set")
+                       if group.color_set:
+                               split.template_triColorSet(group, "colors")
+               
+               row = layout.row(align=True)
+               row.active = (ob.proxy == None)
+               
+               row.itemO("pose.group_assign", text="Assign")
+               row.itemO("pose.group_remove", text="Remove") #row.itemO("pose.bone_group_remove_from", text="Remove")
+               #row.itemO("object.bone_group_select", text="Select")
+               #row.itemO("object.bone_group_deselect", text="Deselect")
+
+class DATA_PT_paths(DataButtonsPanel):
+       __label__ = "Paths"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               arm = context.armature
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(arm, "paths_show_around_current_frame", text="Around Frame")
+               
+               sub = col.column(align=True)
+               if (arm.paths_show_around_current_frame):
+                       sub.itemR(arm, "path_before_current", text="Before")
+                       sub.itemR(arm, "path_after_current", text="After")
+               else:
+                       sub.itemR(arm, "path_start_frame", text="Start")
+                       sub.itemR(arm, "path_end_frame", text="End")
+
+               sub.itemR(arm, "path_size", text="Step")        
+               col.itemR(arm, "paths_calculate_head_positions", text="Head")
+               
+               col = split.column()
+               col.itemL(text="Show:")
+               col.itemR(arm, "paths_show_frame_numbers", text="Frame Numbers")
+               col.itemR(arm, "paths_highlight_keyframes", text="Keyframes")
+               col.itemR(arm, "paths_show_keyframe_numbers", text="Keyframe Numbers")
+
+class DATA_PT_ghost(DataButtonsPanel):
+       __label__ = "Ghost"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               arm = context.armature
+
+               split = layout.split()
+
+               col = split.column()
+               col.itemR(arm, "ghost_type", text="")
+
+               sub = col.column(align=True)
+               if arm.ghost_type == 'RANGE':
+                       sub.itemR(arm, "ghost_start_frame", text="Start")
+                       sub.itemR(arm, "ghost_end_frame", text="End")
+                       sub.itemR(arm, "ghost_size", text="Step")
+               elif arm.ghost_type == 'CURRENT_FRAME':
+                       sub.itemR(arm, "ghost_step", text="Range")
+                       sub.itemR(arm, "ghost_size", text="Step")
+
+               col = split.column()
+               col.itemR(arm, "ghost_only_selected", text="Selected Only")
+
+bpy.types.register(DATA_PT_context_arm)
+bpy.types.register(DATA_PT_skeleton)
+bpy.types.register(DATA_PT_display)
+bpy.types.register(DATA_PT_bone_groups)
+bpy.types.register(DATA_PT_paths)
+bpy.types.register(DATA_PT_ghost)
diff --git a/release/ui/buttons_data_bone.py b/release/ui/buttons_data_bone.py
new file mode 100644 (file)
index 0000000..a012182
--- /dev/null
@@ -0,0 +1,278 @@
+
+import bpy
+class BoneButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "bone"
+       
+       def poll(self, context):
+               return (context.bone or context.edit_bone)
+
+class BONE_PT_context_bone(BoneButtonsPanel):
+       __show_header__ = False
+
+       def draw(self, context):
+               layout = self.layout
+               
+               bone = context.bone
+               if not bone:
+                       bone = context.edit_bone
+               
+               row = layout.row()
+               row.itemL(text="", icon='ICON_BONE_DATA')
+               row.itemR(bone, "name", text="")
+
+class BONE_PT_transform(BoneButtonsPanel):
+       __label__ = "Transform"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               bone = context.bone
+               if not bone:
+                       bone = context.edit_bone
+
+                       row = layout.row()
+                       row.column().itemR(bone, "head")
+                       row.column().itemR(bone, "tail")
+
+                       col = row.column()
+                       sub = col.column(align=True)
+                       sub.itemL(text="Roll:")
+                       sub.itemR(bone, "roll", text="")
+                       sub.itemL()
+                       sub.itemR(bone, "locked")
+
+               else:
+                       pchan = ob.pose.pose_channels[context.bone.name]
+
+                       layout.itemR(pchan, "rotation_mode")
+
+                       row = layout.row()
+                       col = row.column()
+                       col.itemR(pchan, "location")
+                       col.active = not (bone.parent and bone.connected)
+
+                       col = row.column()
+                       if pchan.rotation_mode == 'QUATERNION':
+                               col.itemR(pchan, "rotation", text="Rotation")
+                       elif pchan.rotation_mode == 'AXIS_ANGLE':
+                               col.itemL(text="Rotation")
+                               col.itemR(pchan, "rotation_angle", text="Angle")
+                               col.itemR(pchan, "rotation_axis", text="Axis")
+                       else:
+                               col.itemR(pchan, "euler_rotation", text="Rotation")
+
+                       row.column().itemR(pchan, "scale")
+
+                       if pchan.rotation_mode == 'QUATERNION':
+                               col = layout.column(align=True)
+                               col.itemL(text="Euler:")
+                               col.row().itemR(pchan, "euler_rotation", text="")
+                               
+class BONE_PT_transform_locks(BoneButtonsPanel):
+       __label__ = "Transform Locks"
+       
+       def poll(self, context):
+               return context.bone
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               bone = context.bone
+               pchan = ob.pose.pose_channels[context.bone.name]
+               
+               row = layout.row()
+               col = row.column()
+               col.itemR(pchan, "lock_location")
+               col.active = not (bone.parent and bone.connected)
+               
+               col = row.column()
+               if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+                       col.itemR(pchan, "lock_rotations_4d", text="Lock Rotation")
+                       if pchan.lock_rotations_4d:
+                               col.itemR(pchan, "lock_rotation_w", text="W")
+                       col.itemR(pchan, "lock_rotation", text="")
+               else:
+                       col.itemR(pchan, "lock_rotation", text="Rotation")
+               
+               row.column().itemR(pchan, "lock_scale")
+
+class BONE_PT_bone(BoneButtonsPanel):
+       __label__ = "Bone"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               bone = context.bone
+               arm = context.armature
+               
+               if not bone:
+                       bone = context.edit_bone
+                       pchan = None
+               else:
+                       pchan = ob.pose.pose_channels[context.bone.name]
+
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Parent:")
+               if context.bone:
+                       col.itemR(bone, "parent", text="")
+               else:
+                       col.item_pointerR(bone, "parent", arm, "edit_bones", text="")
+               
+               row = col.row()
+               row.active = bone.parent != None
+               row.itemR(bone, "connected")
+               
+               col.itemL(text="Layers:")
+               col.itemR(bone, "layer", text="")
+               
+               col = split.column()
+               col.itemL(text="Inherit:")
+               col.itemR(bone, "hinge", text="Rotation")
+               col.itemR(bone, "inherit_scale", text="Scale")
+               col.itemL(text="Display:")
+               col.itemR(bone, "draw_wire", text="Wireframe")
+               col.itemR(bone, "hidden", text="Hide")
+               
+               if ob and pchan:
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Bone Group:")
+                       col.item_pointerR(pchan, "bone_group", ob.pose, "bone_groups", text="")
+                       
+                       col = split.column()
+                       col.itemL(text="Custom Shape:")
+                       col.itemR(pchan, "custom_shape", text="")
+
+class BONE_PT_inverse_kinematics(BoneButtonsPanel):
+       __label__ = "Inverse Kinematics"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               ob = context.object
+               bone = context.bone
+
+               if ob and context.bone:
+                       pchan = ob.pose.pose_channels[context.bone.name]
+                       return pchan.has_ik
+               
+               return False
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               bone = context.bone
+               pchan = ob.pose.pose_channels[context.bone.name]
+
+               split = layout.split(percentage=0.25)
+               split.itemR(pchan, "ik_dof_x", text="X")
+               row = split.row()
+               row.itemR(pchan, "ik_stiffness_x", text="Stiffness")
+               row.active = pchan.ik_dof_x
+
+               split = layout.split(percentage=0.25)
+               row = split.row()
+               row.itemR(pchan, "ik_limit_x", text="Limit")
+               row.active = pchan.ik_dof_x
+               row = split.row(align=True)
+               row.itemR(pchan, "ik_min_x", text="")
+               row.itemR(pchan, "ik_max_x", text="")
+               row.active = pchan.ik_dof_x and pchan.ik_limit_x
+
+               split = layout.split(percentage=0.25)
+               split.itemR(pchan, "ik_dof_y", text="Y")
+               row = split.row()
+               row.itemR(pchan, "ik_stiffness_y", text="Stiffness")
+               row.active = pchan.ik_dof_y
+
+               split = layout.split(percentage=0.25)
+               row = split.row()
+               row.itemR(pchan, "ik_limit_y", text="Limit")
+               row.active = pchan.ik_dof_y
+               row = split.row(align=True)
+               row.itemR(pchan, "ik_min_y", text="")
+               row.itemR(pchan, "ik_max_y", text="")
+               row.active = pchan.ik_dof_y and pchan.ik_limit_y
+
+               split = layout.split(percentage=0.25)
+               split.itemR(pchan, "ik_dof_z", text="Z")
+               row = split.row()
+               row.itemR(pchan, "ik_stiffness_z", text="Stiffness")
+               row.active = pchan.ik_dof_z
+
+               split = layout.split(percentage=0.25)
+               row = split.row()
+               row.itemR(pchan, "ik_limit_z", text="Limit")
+               row.active = pchan.ik_dof_z
+               row = split.row(align=True)
+               row.itemR(pchan, "ik_min_z", text="")
+               row.itemR(pchan, "ik_max_z", text="")
+               row.active = pchan.ik_dof_z and pchan.ik_limit_z
+
+               split = layout.split()
+               split.itemR(pchan, "ik_stretch", text="Stretch")
+               split.itemL()
+
+class BONE_PT_deform(BoneButtonsPanel):
+       __label__ = "Deform"
+       __default_closed__ = True
+
+       def draw_header(self, context):
+               bone = context.bone
+               
+               if not bone:
+                       bone = context.edit_bone
+                       
+               self.layout.itemR(bone, "deform", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               bone = context.bone
+               
+               if not bone:
+                       bone = context.edit_bone
+       
+               layout.active = bone.deform
+                       
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Envelope:")
+               
+               sub = col.column(align=True)
+               sub.itemR(bone, "envelope_distance", text="Distance")
+               sub.itemR(bone, "envelope_weight", text="Weight")
+               col.itemR(bone, "multiply_vertexgroup_with_envelope", text="Multiply")
+
+               sub = col.column(align=True)
+               sub.itemL(text="Radius:")
+               sub.itemR(bone, "head_radius", text="Head")
+               sub.itemR(bone, "tail_radius", text="Tail")
+
+               col = split.column()
+               col.itemL(text="Curved Bones:")
+               
+               sub = col.column(align=True)
+               sub.itemR(bone, "bbone_segments", text="Segments")
+               sub.itemR(bone, "bbone_in", text="Ease In")
+               sub.itemR(bone, "bbone_out", text="Ease Out")
+               
+               col.itemL(text="Offset:")
+               col.itemR(bone, "cyclic_offset")
+
+bpy.types.register(BONE_PT_context_bone)
+bpy.types.register(BONE_PT_transform)
+bpy.types.register(BONE_PT_transform_locks)
+bpy.types.register(BONE_PT_bone)
+bpy.types.register(BONE_PT_deform)
+bpy.types.register(BONE_PT_inverse_kinematics)
diff --git a/release/ui/buttons_data_camera.py b/release/ui/buttons_data_camera.py
new file mode 100644 (file)
index 0000000..aa107d8
--- /dev/null
@@ -0,0 +1,97 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+
+       def poll(self, context):
+               return (context.camera)
+               
+class DATA_PT_context_camera(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               cam = context.camera
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif cam:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_camera(DataButtonsPanel):
+       __label__ = "Lens"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               cam = context.camera
+
+               layout.itemR(cam, "type", expand=True)
+                       
+               row = layout.row(align=True)
+               if cam.type == 'PERSP':
+                       row.itemR(cam, "lens_unit", text="")
+                       if cam.lens_unit == 'MILLIMETERS':
+                               row.itemR(cam, "lens", text="Angle")
+                       elif cam.lens_unit == 'DEGREES':
+                               row.itemR(cam, "angle")
+
+               elif cam.type == 'ORTHO':
+                       row.itemR(cam, "ortho_scale")
+
+               layout.itemR(cam, "panorama")
+                               
+               split = layout.split()
+                       
+               col = split.column(align=True)
+               col.itemL(text="Shift:")
+               col.itemR(cam, "shift_x", text="X")
+               col.itemR(cam, "shift_y", text="Y")
+                       
+               col = split.column(align=True)
+               col.itemL(text="Clipping:")
+               col.itemR(cam, "clip_start", text="Start")
+               col.itemR(cam, "clip_end", text="End")
+                       
+               layout.itemL(text="Depth of Field:")
+               
+               row = layout.row()
+               row.itemR(cam, "dof_object", text="")
+               row.itemR(cam, "dof_distance", text="Distance")
+               
+class DATA_PT_camera_display(DataButtonsPanel):
+       __label__ = "Display"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               cam = context.camera
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(cam, "show_limits", text="Limits")
+               col.itemR(cam, "show_mist", text="Mist")
+               col.itemR(cam, "show_title_safe", text="Title Safe")
+               col.itemR(cam, "show_name", text="Name")
+                       
+               col = split.column()
+               col.itemR(cam, "show_passepartout", text="Passepartout")
+               sub = col.column()
+               sub.active = cam.show_passepartout
+               sub.itemR(cam, "passepartout_alpha", text="Alpha", slider=True)
+               col.itemR(cam, "draw_size", text="Size")
+               
+bpy.types.register(DATA_PT_context_camera)
+bpy.types.register(DATA_PT_camera)
+bpy.types.register(DATA_PT_camera_display)
diff --git a/release/ui/buttons_data_curve.py b/release/ui/buttons_data_curve.py
new file mode 100644 (file)
index 0000000..010acd1
--- /dev/null
@@ -0,0 +1,225 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.object and context.object.type in ('CURVE', 'SURFACE') and context.curve)
+               
+class DataButtonsPanelCurve(DataButtonsPanel):
+       '''
+       Same as above but for curves only
+       '''
+       def poll(self, context):
+               return (context.object and context.object.type == 'CURVE' and context.curve)
+
+class DataButtonsPanelActive(DataButtonsPanel):
+       '''
+       Same as above but for curves only
+       '''
+       def poll(self, context):
+               curve = context.curve
+               return (curve and curve.active_spline)
+
+class DATA_PT_context_curve(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               curve = context.curve
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif curve:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_shape_curve(DataButtonsPanel):
+       __label__ = "Shape"
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               curve = context.curve
+               space = context.space_data
+               is_surf = (ob.type == 'SURFACE')
+
+               if not is_surf:
+                       row = layout.row()
+                       row.itemR(curve, "curve_2d")
+               
+               split = layout.split()
+               
+               col = split.column()
+               
+               if not is_surf:
+                       sub = col.column()
+                       sub.active = curve.curve_2d
+                       sub.itemL(text="Caps:")
+                       row = sub.row()
+                       row.itemR(curve, "front")
+                       row.itemR(curve, "back")
+                       
+               col.itemL(text="Textures:")
+#              col.itemR(curve, "uv_orco")
+               col.itemR(curve, "auto_texspace")
+                       
+               col = split.column()    
+               col.itemL(text="Resolution:")
+               sub = col.column(align=True)
+               sub.itemR(curve, "resolution_u", text="Preview U")
+               sub.itemR(curve, "render_resolution_u", text="Render U")
+
+               if is_surf:
+                       sub = col.column(align=True)
+                       sub.itemR(curve, "resolution_v", text="Preview V")
+                       sub.itemR(curve, "render_resolution_v", text="Render V")
+               
+               # XXX - put somewhere nicer.
+               row= layout.row()
+               row.itemR(curve, "twist_mode")
+               row.itemR(curve, "twist_smooth") # XXX - may not be kept
+
+
+#              col.itemL(text="Display:")
+#              col.itemL(text="HANDLES")
+#              col.itemL(text="NORMALS")
+#              col.itemR(curve, "vertex_normal_flip")
+
+class DATA_PT_geometry_curve(DataButtonsPanelCurve):
+       __label__ = "Geometry "
+
+       def draw(self, context):
+               layout = self.layout
+               
+               curve = context.curve
+               
+               split = layout.split()
+       
+               col = split.column()
+               col.itemL(text="Modification:")
+               col.itemR(curve, "width")
+               col.itemR(curve, "extrude")
+               col.itemR(curve, "taper_object", icon='ICON_OUTLINER_OB_CURVE')
+               
+               col = split.column()
+               col.itemL(text="Bevel:")
+               col.itemR(curve, "bevel_depth", text="Depth")
+               col.itemR(curve, "bevel_resolution", text="Resolution")
+               col.itemR(curve, "bevel_object", icon='ICON_OUTLINER_OB_CURVE')
+
+       
+class DATA_PT_pathanim(DataButtonsPanelCurve):
+       __label__ = "Path Animation"
+       
+       def draw_header(self, context):
+               curve = context.curve
+
+               self.layout.itemR(curve, "use_path", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               curve = context.curve
+               
+               layout.active = curve.use_path  
+               
+               split = layout.split()          
+               
+               col = split.column()
+               col.itemR(curve, "path_length", text="Frames")
+               col.itemR(curve, "use_path_follow")
+
+               col = split.column()
+               col.itemR(curve, "use_stretch")
+               col.itemR(curve, "use_time_offset", text="Offset Children")
+       
+class DATA_PT_active_spline(DataButtonsPanelActive):
+       __label__ = "Active Spline"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               curve = context.curve
+               act_spline = curve.active_spline
+               is_surf = (ob.type == 'SURFACE')
+               is_poly = (act_spline.type == 'POLY')
+               
+               split = layout.split()
+               
+               if is_poly:
+                       # These settings are below but its easier to have 
+                       # poly's set aside since they use so few settings
+                       col = split.column()
+                       col.itemL(text="Cyclic:")
+                       col.itemR(act_spline, "smooth")
+                       col = split.column()
+                       col.itemR(act_spline, "cyclic_u", text="U")
+               
+               else:
+                       col = split.column()
+                       col.itemL(text="Cyclic:")
+                       if act_spline.type == 'NURBS':
+                               col.itemL(text="Bezier:")
+                               col.itemL(text="Endpoint:")
+                               col.itemL(text="Order:")
+                       
+                       col.itemL(text="Resolution:")
+                                       
+                       col = split.column()
+                       col.itemR(act_spline, "cyclic_u", text="U")
+                       
+                       if act_spline.type == 'NURBS':
+                               sub = col.column()
+                               # sub.active = (not act_spline.cyclic_u)
+                               sub.itemR(act_spline, "bezier_u", text="U")
+                               sub.itemR(act_spline, "endpoint_u", text="U")
+                               
+                               sub = col.column()
+                               sub.itemR(act_spline, "order_u", text="U")
+                       col.itemR(act_spline, "resolution_u", text="U")
+                       
+                       if is_surf:
+                               col = split.column()
+                               col.itemR(act_spline, "cyclic_v", text="V")
+                               
+                               # its a surface, assume its a nurb.
+                               sub = col.column()
+                               sub.active = (not act_spline.cyclic_v)
+                               sub.itemR(act_spline, "bezier_v", text="V")
+                               sub.itemR(act_spline, "endpoint_v", text="V")
+                               sub = col.column()
+                               sub.itemR(act_spline, "order_v", text="V")
+                               sub.itemR(act_spline, "resolution_v", text="V")
+
+                       
+                       if not is_surf:
+                               split = layout.split()
+                               col = split.column()
+                               col.active = (not curve.curve_2d)
+                               
+                               col.itemL(text="Interpolation:")
+                               col.itemR(act_spline, "tilt_interpolation", text="Tilt")
+                               col.itemR(act_spline, "radius_interpolation", text="Radius")
+                       
+                       split = layout.split()
+                       col = split.column()
+                       col.itemR(act_spline, "smooth")
+
+
+bpy.types.register(DATA_PT_context_curve)
+bpy.types.register(DATA_PT_shape_curve)
+bpy.types.register(DATA_PT_geometry_curve)
+bpy.types.register(DATA_PT_pathanim)
+bpy.types.register(DATA_PT_active_spline)
diff --git a/release/ui/buttons_data_empty.py b/release/ui/buttons_data_empty.py
new file mode 100644 (file)
index 0000000..c07f313
--- /dev/null
@@ -0,0 +1,23 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.object and context.object.type == 'EMPTY')
+       
+class DATA_PT_empty(DataButtonsPanel):
+       __label__ = "Empty"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               layout.itemR(ob, "empty_draw_type", text="Draw Type")
+               layout.itemR(ob, "empty_draw_size", text="Draw Size")
+               
+bpy.types.register(DATA_PT_empty)
diff --git a/release/ui/buttons_data_lamp.py b/release/ui/buttons_data_lamp.py
new file mode 100644 (file)
index 0000000..808a205
--- /dev/null
@@ -0,0 +1,313 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.lamp)
+               
+class DATA_PT_preview(DataButtonsPanel):
+       __label__ = "Preview"
+
+       def draw(self, context):
+               self.layout.template_preview(context.lamp)
+       
+class DATA_PT_context_lamp(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               lamp = context.lamp
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif lamp:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_lamp(DataButtonsPanel):
+       __label__ = "Lamp"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lamp = context.lamp
+               
+               layout.itemR(lamp, "type", expand=True)
+               
+               split = layout.split()
+               
+               col = split.column()
+               sub = col.column()
+               sub.itemR(lamp, "color", text="")
+               sub.itemR(lamp, "energy")
+
+               if lamp.type in ('POINT', 'SPOT'):
+                       sub.itemL(text="Falloff:")
+                       sub.itemR(lamp, "falloff_type", text="")
+                       sub.itemR(lamp, "distance")
+
+                       if lamp.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
+                               col.itemL(text="Attenuation Factors:")
+                               sub = col.column(align=True)
+                               sub.itemR(lamp, "linear_attenuation", slider=True, text="Linear")
+                               sub.itemR(lamp, "quadratic_attenuation", slider=True, text="Quadratic")
+                       
+                       col.itemR(lamp, "sphere")
+                       
+               if lamp.type == 'AREA':
+                       col.itemR(lamp, "distance")
+                       col.itemR(lamp, "gamma")
+       
+               col = split.column()
+               col.itemR(lamp, "negative")
+               col.itemR(lamp, "layer", text="This Layer Only")
+               col.itemR(lamp, "specular")
+               col.itemR(lamp, "diffuse")      
+
+class DATA_PT_sunsky(DataButtonsPanel):
+       __label__ = "Sun/Sky"
+       
+       def poll(self, context):
+               lamp = context.lamp
+               return (lamp and lamp.type == 'SUN')
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lamp = context.lamp.sky
+
+               row = layout.row()
+               row.itemR(lamp, "sky")
+               row.itemR(lamp, "atmosphere")
+               
+               row = layout.row()
+               row.active = lamp.sky or lamp.atmosphere
+               row.itemR(lamp, "atmosphere_turbidity", text="Turbidity")
+                       
+               split = layout.split()
+               
+               col = split.column()
+               col.active = lamp.sky
+               col.itemL(text="Blend Mode:")
+               sub = col.column(align=True)
+               sub.itemR(lamp, "sky_blend_type", text="")
+               sub.itemR(lamp, "sky_blend", text="Factor")
+               
+               col.itemL(text="Color Space:")
+               sub = col.column(align=True)
+               sub.itemR(lamp, "sky_color_space", text="")
+               sub.itemR(lamp, "sky_exposure", text="Exposure")
+                       
+               col = split.column()
+               col.active = lamp.sky
+               col.itemL(text="Horizon:")
+               sub = col.column(align=True)
+               sub.itemR(lamp, "horizon_brightness", text="Brightness")
+               sub.itemR(lamp, "spread", text="Spread")
+               
+               col.itemL(text="Sun:")
+               sub = col.column(align=True)
+               sub.itemR(lamp, "sun_brightness", text="Brightness")
+               sub.itemR(lamp, "sun_size", text="Size")
+               sub.itemR(lamp, "backscattered_light", slider=True,text="Back Light")
+               
+               layout.itemS()
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.active = lamp.atmosphere
+               col.itemL(text="Sun:")
+               col.itemR(lamp, "sun_intensity", text="Intensity")
+               col.itemL(text="Scale Distance:")
+               col.itemR(lamp, "atmosphere_distance_factor", text="Distance")
+                       
+               col = split.column()
+               col.active = lamp.atmosphere
+               col.itemL(text="Scattering:")
+               sub = col.column(align=True)
+               sub.itemR(lamp, "atmosphere_inscattering", slider=True, text="Inscattering")
+               sub.itemR(lamp, "atmosphere_extinction", slider=True ,text="Extinction")
+               
+class DATA_PT_shadow(DataButtonsPanel):
+       __label__ = "Shadow"
+       
+       def poll(self, context):
+               lamp = context.lamp
+               return (lamp and lamp.type in ('POINT','SUN', 'SPOT', 'AREA'))
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lamp = context.lamp
+
+               layout.itemR(lamp, "shadow_method", expand=True)
+               
+               if lamp.shadow_method != 'NOSHADOW':
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemR(lamp, "shadow_color", text="")
+                       
+                       col = split.column()
+                       col.itemR(lamp, "shadow_layer", text="This Layer Only")
+                       col.itemR(lamp, "only_shadow")
+               
+               if lamp.shadow_method == 'RAY_SHADOW':
+                       col = layout.column()
+                       col.itemL(text="Sampling:")
+                       col.row().itemR(lamp, "shadow_ray_sampling_method", expand=True)
+                               
+                       if lamp.type in ('POINT', 'SUN', 'SPOT'):
+                               split = layout.split()
+                               
+                               col = split.column()
+                               col.itemR(lamp, "shadow_soft_size", text="Soft Size")
+                               
+                               col.itemR(lamp, "shadow_ray_samples", text="Samples")
+                               if lamp.shadow_ray_sampling_method == 'ADAPTIVE_QMC':
+                                       col.itemR(lamp, "shadow_adaptive_threshold", text="Threshold")
+                               col = split.column()
+                                               
+                       elif lamp.type == 'AREA':
+                               split = layout.split()
+                               
+                               col = split.column()
+                               sub = split.column(align=True)
+                               if lamp.shape == 'SQUARE':
+                                       col.itemR(lamp, "shadow_ray_samples_x", text="Samples")
+                               elif lamp.shape == 'RECTANGLE':
+                                       col.itemR(lamp, "shadow_ray_samples_x", text="Samples X")
+                                       col.itemR(lamp, "shadow_ray_samples_y", text="Samples Y")
+                                       
+                               if lamp.shadow_ray_sampling_method == 'ADAPTIVE_QMC':
+                                       col.itemR(lamp, "shadow_adaptive_threshold", text="Threshold")
+                                       
+                               elif lamp.shadow_ray_sampling_method == 'CONSTANT_JITTERED':
+                                       sub.itemR(lamp, "umbra")
+                                       sub.itemR(lamp, "dither")
+                                       sub.itemR(lamp, "jitter")       
+
+               if lamp.shadow_method == 'BUFFER_SHADOW':
+                       col = layout.column()
+                       col.itemL(text="Buffer Type:")
+                       col.row().itemR(lamp, "shadow_buffer_type", expand=True)
+
+                       if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY'):
+                               split = layout.split()
+                               
+                               col = split.column()
+                               col.itemL(text="Filter Type:")
+                               col.itemR(lamp, "shadow_filter_type", text="")
+                               sub = col.column(align=True)
+                               sub.itemR(lamp, "shadow_buffer_soft", text="Soft")
+                               sub.itemR(lamp, "shadow_buffer_bias", text="Bias")
+                               
+                               col = split.column()
+                               col.itemL(text="Sample Buffers:")
+                               col.itemR(lamp, "shadow_sample_buffers", text="")
+                               sub = col.column(align=True)
+                               sub.itemR(lamp, "shadow_buffer_size", text="Size")
+                               sub.itemR(lamp, "shadow_buffer_samples", text="Samples")
+                               
+                       elif lamp.shadow_buffer_type == 'IRREGULAR':
+                               layout.itemR(lamp, "shadow_buffer_bias", text="Bias")
+                       
+                       row = layout.row()
+                       row.itemR(lamp, "auto_clip_start", text="Autoclip Start")
+                       sub = row.row()
+                       sub.active = not lamp.auto_clip_start
+                       sub.itemR(lamp, "shadow_buffer_clip_start", text="Clip Start")
+
+                       row = layout.row()
+                       row.itemR(lamp, "auto_clip_end", text="Autoclip End")
+                       sub = row.row()
+                       sub.active = not lamp.auto_clip_end
+                       sub.itemR(lamp, "shadow_buffer_clip_end", text=" Clip End")
+
+class DATA_PT_area(DataButtonsPanel):
+       __label__ = "Area Shape"
+       
+       def poll(self, context):
+               lamp = context.lamp
+               return (lamp and lamp.type == 'AREA')
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lamp = context.lamp
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(lamp, "shape", text="")
+               
+               sub = col.column(align=True)
+               if (lamp.shape == 'SQUARE'):
+                       sub.itemR(lamp, "size")
+               elif (lamp.shape == 'RECTANGLE'):
+                       sub.itemR(lamp, "size", text="Size X")
+                       sub.itemR(lamp, "size_y", text="Size Y")
+               
+               col = split.column()
+
+class DATA_PT_spot(DataButtonsPanel):
+       __label__ = "Spot Shape"
+       
+       def poll(self, context):
+               lamp = context.lamp
+               return (lamp and lamp.type == 'SPOT')
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lamp = context.lamp
+
+               split = layout.split()
+               
+               col = split.column()
+               sub = col.column(align=True)
+               sub.itemR(lamp, "spot_size", text="Size")
+               sub.itemR(lamp, "spot_blend", text="Blend")
+               col.itemR(lamp, "square")
+               
+               col = split.column()
+               col.itemR(lamp, "halo")
+               sub = col.column(align=True)
+               sub.active = lamp.halo
+               sub.itemR(lamp, "halo_intensity", text="Intensity")
+               if lamp.shadow_method == 'BUFFER_SHADOW':
+                       sub.itemR(lamp, "halo_step", text="Step")
+
+class DATA_PT_falloff_curve(DataButtonsPanel):
+       __label__ = "Falloff Curve"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               lamp = context.lamp
+
+               return (lamp and lamp.type in ('POINT', 'SPOT') and lamp.falloff_type == 'CUSTOM_CURVE')
+
+       def draw(self, context):
+               lamp = context.lamp
+
+               self.layout.template_curve_mapping(lamp.falloff_curve)
+
+bpy.types.register(DATA_PT_context_lamp)
+bpy.types.register(DATA_PT_preview)
+bpy.types.register(DATA_PT_lamp)
+bpy.types.register(DATA_PT_falloff_curve)
+bpy.types.register(DATA_PT_area)
+bpy.types.register(DATA_PT_spot)
+bpy.types.register(DATA_PT_shadow)
+bpy.types.register(DATA_PT_sunsky)
diff --git a/release/ui/buttons_data_lattice.py b/release/ui/buttons_data_lattice.py
new file mode 100644 (file)
index 0000000..895c1a6
--- /dev/null
@@ -0,0 +1,56 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.lattice)
+       
+class DATA_PT_context_lattice(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               lat = context.lattice
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif lat:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_lattice(DataButtonsPanel):
+       __label__ = "Lattice"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               lat = context.lattice
+
+               row = layout.row()
+               row.itemR(lat, "points_u")
+               row.itemR(lat, "interpolation_type_u", expand=True)
+                       
+               row = layout.row()
+               row.itemR(lat, "points_v")
+               row.itemR(lat, "interpolation_type_v", expand=True)
+                       
+               row = layout.row()
+               row.itemR(lat, "points_w")
+               row.itemR(lat, "interpolation_type_w", expand=True)
+                       
+               row = layout.row()
+               row.itemO("lattice.make_regular")
+               row.itemR(lat, "outside")
+
+bpy.types.register(DATA_PT_context_lattice)
+bpy.types.register(DATA_PT_lattice)
diff --git a/release/ui/buttons_data_mesh.py b/release/ui/buttons_data_mesh.py
new file mode 100644 (file)
index 0000000..33b3960
--- /dev/null
@@ -0,0 +1,203 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.mesh)
+
+class DATA_PT_context_mesh(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               mesh = context.mesh
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif mesh:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_normals(DataButtonsPanel):
+       __label__ = "Normals"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mesh = context.mesh
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mesh, "autosmooth")
+               sub = col.column()
+               sub.active = mesh.autosmooth
+               sub.itemR(mesh, "autosmooth_angle", text="Angle")
+               
+               col = split.column()
+               col.itemR(mesh, "vertex_normal_flip")
+               col.itemR(mesh, "double_sided")
+
+class DATA_PT_vertex_groups(DataButtonsPanel):
+       __label__ = "Vertex Groups"
+       
+       def poll(self, context):
+               return (context.object and context.object.type in ('MESH', 'LATTICE'))
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               row = layout.row()
+               row.template_list(ob, "vertex_groups", ob, "active_vertex_group_index")
+
+               col = row.column(align=True)
+               col.itemO("object.vertex_group_add", icon='ICON_ZOOMIN', text="")
+               col.itemO("object.vertex_group_remove", icon='ICON_ZOOMOUT', text="")
+
+               col.itemO("object.vertex_group_copy", icon='ICON_BLANK1', text="")
+               if ob.data.users > 1:
+                       col.itemO("object.vertex_group_copy_to_linked", icon='ICON_BLANK1', text="")
+
+               group = ob.active_vertex_group
+               if group:
+                       row = layout.row()
+                       row.itemR(group, "name")
+
+               if ob.mode == 'EDIT':
+                       row = layout.row()
+                       
+                       sub = row.row(align=True)
+                       sub.itemO("object.vertex_group_assign", text="Assign")
+                       sub.itemO("object.vertex_group_remove_from", text="Remove")
+                       
+                       sub = row.row(align=True)
+                       sub.itemO("object.vertex_group_select", text="Select")
+                       sub.itemO("object.vertex_group_deselect", text="Deselect")
+
+                       layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight")
+
+class DATA_PT_shape_keys(DataButtonsPanel):
+       __label__ = "Shape Keys"
+       
+       def poll(self, context):
+               return (context.object and context.object.type in ('MESH', 'LATTICE'))
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               key = ob.data.shape_keys
+               kb = ob.active_shape_key
+
+               row = layout.row()
+               row.template_list(key, "keys", ob, "active_shape_key_index", rows=2)
+
+               col = row.column()
+
+               subcol = col.column(align=True)
+               subcol.itemO("object.shape_key_add", icon='ICON_ZOOMIN', text="")
+               subcol.itemO("object.shape_key_remove", icon='ICON_ZOOMOUT', text="")
+
+               if kb:
+                       col.itemS()
+
+                       subcol = col.column(align=True)
+                       subcol.itemR(ob, "shape_key_lock", icon='ICON_UNPINNED', text="")
+                       subcol.itemR(kb, "mute", icon='ICON_MUTE_IPO_ON', text="")
+
+                       if key.relative:
+                               row = layout.row()
+                               row.itemR(key, "relative")
+                               row.itemL()
+
+                               row = layout.row()
+                               row.itemR(kb, "name")
+
+                               if ob.active_shape_key_index != 0:
+                                       
+                                       row = layout.row()
+                                       row.enabled = ob.shape_key_lock == False
+                                       row.itemR(kb, "value", slider=True)
+                                       
+                                       split = layout.split()
+                                       sub = split.column(align=True)
+                                       sub.enabled = ob.shape_key_lock == False
+                                       sub.itemL(text="Range:")
+                                       sub.itemR(kb, "slider_min", text="Min")
+                                       sub.itemR(kb, "slider_max", text="Max")
+                                       
+                                       sub = split.column()
+                                       sub.itemL(text="Blend:")
+                                       sub.item_pointerR(kb, "vertex_group", ob, "vertex_groups", text="")
+                                       sub.item_pointerR(kb, "relative_key", key, "keys", text="")
+                                       
+                       else:
+                               row = layout.row()
+                               row.itemR(key, "relative")
+                               row.itemR(key, "slurph")
+
+                               layout.itemR(kb, "name")
+
+               if ob.mode == 'EDIT':
+                       layout.enabled = False
+
+class DATA_PT_uv_texture(DataButtonsPanel):
+       __label__ = "UV Texture"
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               me = context.mesh
+
+               row = layout.row()
+               col = row.column()
+               
+               col.template_list(me, "uv_textures", me, "active_uv_texture_index", rows=2)
+
+               col = row.column(align=True)
+               col.itemO("mesh.uv_texture_add", icon='ICON_ZOOMIN', text="")
+               col.itemO("mesh.uv_texture_remove", icon='ICON_ZOOMOUT', text="")
+
+               lay = me.active_uv_texture
+               if lay:
+                       layout.itemR(lay, "name")
+
+class DATA_PT_vertex_colors(DataButtonsPanel):
+       __label__ = "Vertex Colors"
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               me = context.mesh
+
+               row = layout.row()
+               col = row.column()
+
+               col.template_list(me, "vertex_colors", me, "active_vertex_color_index", rows=2)
+
+               col = row.column(align=True)
+               col.itemO("mesh.vertex_color_add", icon='ICON_ZOOMIN', text="")
+               col.itemO("mesh.vertex_color_remove", icon='ICON_ZOOMOUT', text="")
+
+               lay = me.active_vertex_color
+               if lay:
+                       layout.itemR(lay, "name")
+
+bpy.types.register(DATA_PT_context_mesh)
+bpy.types.register(DATA_PT_normals)
+bpy.types.register(DATA_PT_vertex_groups)
+bpy.types.register(DATA_PT_shape_keys)
+bpy.types.register(DATA_PT_uv_texture)
+bpy.types.register(DATA_PT_vertex_colors)
diff --git a/release/ui/buttons_data_metaball.py b/release/ui/buttons_data_metaball.py
new file mode 100644 (file)
index 0000000..88c0066
--- /dev/null
@@ -0,0 +1,112 @@
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.meta_ball)
+
+class DATA_PT_context_metaball(DataButtonsPanel):
+       __show_header__ = False
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               mball = context.meta_ball
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif mball:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_metaball(DataButtonsPanel):
+       __label__ = "Metaball"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mball = context.meta_ball
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Resolution:")
+               sub = col.column(align=True)
+               sub.itemR(mball, "wire_size", text="View")
+               sub.itemR(mball, "render_size", text="Render")  
+               
+               col = split.column()
+               col.itemL(text="Settings:")
+               col.itemR(mball, "threshold", text="Threshold")
+
+               layout.itemL(text="Update:")
+               layout.itemR(mball, "flag", expand=True)
+
+class DATA_PT_metaball_element(DataButtonsPanel):
+       __label__ = "Active Element"
+       
+       def poll(self, context):
+               return (context.meta_ball and context.meta_ball.active_element)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               metaelem = context.meta_ball.active_element
+               
+               split = layout.split(percentage=0.3)
+               split.itemL(text="Type:")       
+               split.itemR(metaelem, "type", text="")
+               
+               split = layout.split()
+                       
+               col = split.column()
+               col.itemL(text="Settings:")
+               col.itemR(metaelem, "stiffness", text="Stiffness")
+               col.itemR(metaelem, "negative", text="Negative")
+               col.itemR(metaelem, "hide", text="Hide")
+               
+               if metaelem.type == 'BALL':
+               
+                       col = split.column(align=True)
+                       
+               elif metaelem.type == 'CUBE':
+               
+                       col = split.column(align=True)
+                       col.itemL(text="Size:") 
+                       col.itemR(metaelem, "size_x", text="X")
+                       col.itemR(metaelem, "size_y", text="Y")
+                       col.itemR(metaelem, "size_z", text="Z")
+                       
+               elif metaelem.type == 'TUBE':
+               
+                       col = split.column(align=True)
+                       col.itemL(text="Size:") 
+                       col.itemR(metaelem, "size_x", text="X")
+                       
+               elif metaelem.type == 'PLANE':
+                       
+                       col = split.column(align=True)
+                       col.itemL(text="Size:") 
+                       col.itemR(metaelem, "size_x", text="X")
+                       col.itemR(metaelem, "size_y", text="Y")
+                       
+               elif metaelem.type == 'ELLIPSOID':
+                       
+                       col = split.column(align=True)
+                       col.itemL(text="Size:") 
+                       col.itemR(metaelem, "size_x", text="X")
+                       col.itemR(metaelem, "size_y", text="Y")
+                       col.itemR(metaelem, "size_z", text="Z")
+               
+
+bpy.types.register(DATA_PT_context_metaball)
+bpy.types.register(DATA_PT_metaball)
+bpy.types.register(DATA_PT_metaball_element)
diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py
new file mode 100644 (file)
index 0000000..754e8ce
--- /dev/null
@@ -0,0 +1,449 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "modifier"
+       
+class DATA_PT_modifiers(DataButtonsPanel):
+       __label__ = "Modifiers"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               row = layout.row()
+               row.item_menu_enumO("object.modifier_add", "type")
+               row.itemL()
+
+               for md in ob.modifiers:
+                       box = layout.template_modifier(md)
+                       if box:
+                               # match enum type to our functions, avoids a lookup table.
+                               getattr(self, md.type)(box, ob, md)
+       
+       # the mt.type enum is (ab)used for a lookup on function names
+       # ...to avoid lengthy if statements
+       # so each type must have a function here.
+
+       def ARMATURE(self, layout, ob, md):
+               layout.itemR(md, "object")
+               
+               split = layout.split(percentage=0.5)
+               split.itemL(text="Vertex Group:")
+               sub = split.split(percentage=0.7)
+               sub.item_pointerR(md, "vertex_group", ob, "vertex_groups", text="")
+               subsub = sub.row()
+               subsub.active = md.vertex_group
+               subsub.itemR(md, "invert")
+               
+               layout.itemS()
+               
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Bind To:")
+               col.itemR(md, "use_vertex_groups", text="Vertex Groups")
+               col.itemR(md, "use_bone_envelopes", text="Bone Envelopes")
+               
+               col = split.column()
+               col.itemL(text="Deformation:")
+               col.itemR(md, "quaternion")
+               col.itemR(md, "multi_modifier")
+               
+       def ARRAY(self, layout, ob, md):
+               layout.itemR(md, "fit_type")
+               if md.fit_type == 'FIXED_COUNT':
+                       layout.itemR(md, "count")
+               elif md.fit_type == 'FIT_LENGTH':
+                       layout.itemR(md, "length")
+               elif md.fit_type == 'FIT_CURVE':
+                       layout.itemR(md, "curve")
+
+               layout.itemS()
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(md, "constant_offset")
+               sub = col.column()
+               sub.active = md.constant_offset
+               sub.itemR(md, "constant_offset_displacement", text="")
+
+               col.itemS()
+
+               col.itemR(md, "merge_adjacent_vertices", text="Merge")
+               sub = col.column()
+               sub.active = md.merge_adjacent_vertices
+               sub.itemR(md, "merge_end_vertices", text="First Last")
+               sub.itemR(md, "merge_distance", text="Distance")
+               
+               col = split.column()
+               col.itemR(md, "relative_offset")
+               sub = col.column()
+               sub.active = md.relative_offset
+               sub.itemR(md, "relative_offset_displacement", text="")
+
+               col.itemS()
+
+               col.itemR(md, "add_offset_object")
+               sub = col.column()
+               sub.active = md.add_offset_object
+               sub.itemR(md, "offset_object", text="")
+
+               layout.itemS()
+               
+               col = layout.column()
+               col.itemR(md, "start_cap")
+               col.itemR(md, "end_cap")
+       
+       def BEVEL(self, layout, ob, md):
+               row = layout.row()
+               row.itemR(md, "width")
+               row.itemR(md, "only_vertices")
+               
+               layout.itemL(text="Limit Method:")
+               layout.row().itemR(md, "limit_method", expand=True)
+               if md.limit_method == 'ANGLE':
+                       layout.itemR(md, "angle")
+               elif md.limit_method == 'WEIGHT':
+                       layout.row().itemR(md, "edge_weight_method", expand=True)
+                       
+       def BOOLEAN(self, layout, ob, md):
+               layout.itemR(md, "operation")
+               layout.itemR(md, "object")
+               
+       def BUILD(self, layout, ob, md):
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(md, "start")
+               col.itemR(md, "length")
+
+               col = split.column()
+               col.itemR(md, "randomize")
+               sub = col.column()
+               sub.active = md.randomize
+               sub.itemR(md, "seed")
+
+       def CAST(self, layout, ob, md):
+               layout.itemR(md, "cast_type")
+               layout.itemR(md, "object")
+               if md.object:
+                       layout.itemR(md, "use_transform")
+               
+               flow = layout.column_flow()
+               flow.itemR(md, "x")
+               flow.itemR(md, "y")
+               flow.itemR(md, "z")
+               flow.itemR(md, "factor")
+               flow.itemR(md, "radius")
+               flow.itemR(md, "size")
+
+               layout.itemR(md, "from_radius")
+               
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               
+       def CLOTH(self, layout, ob, md):
+               layout.itemL(text="See Cloth panel.")
+               
+       def COLLISION(self, layout, ob, md):
+               layout.itemL(text="See Collision panel.")
+               
+       def CURVE(self, layout, ob, md):
+               layout.itemR(md, "object")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "deform_axis")
+               
+       def DECIMATE(self, layout, ob, md):
+               layout.itemR(md, "ratio")
+               layout.itemR(md, "face_count")
+               
+       def DISPLACE(self, layout, ob, md):
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "texture")
+               layout.itemR(md, "midlevel")
+               layout.itemR(md, "strength")
+               layout.itemR(md, "direction")
+               layout.itemR(md, "texture_coordinates")
+               if md.texture_coordinates == 'OBJECT':
+                       layout.itemR(md, "texture_coordinate_object", text="Object")
+               elif md.texture_coordinates == 'UV' and ob.type == 'MESH':
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
+       
+       def EDGE_SPLIT(self, layout, ob, md):
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(md, "use_edge_angle", text="Edge Angle")
+               sub = col.column()
+               sub.active = md.use_edge_angle
+               sub.itemR(md, "split_angle")
+               
+               col = split.column()
+               col.itemR(md, "use_sharp", text="Sharp Edges")
+               
+       def EXPLODE(self, layout, ob, md):
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "protect")
+
+               flow = layout.column_flow(2)
+               flow.itemR(md, "split_edges")
+               flow.itemR(md, "unborn")
+               flow.itemR(md, "alive")
+               flow.itemR(md, "dead")
+
+               layout.itemO("object.explode_refresh", text="Refresh");
+               
+       def FLUID_SIMULATION(self, layout, ob, md):
+               layout.itemL(text="See Fluid panel.")
+               
+       def HOOK(self, layout, ob, md):
+               col = layout.column()
+               col.itemR(md, "object")
+               if md.object and md.object.type == 'ARMATURE':
+                       layout.item_pointerR(md, "subtarget", md.object.data, "bones", text="Bone")
+               
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+
+               split = layout.split()
+               split.itemR(md, "falloff")
+               split.itemR(md, "force", slider=True)
+
+               layout.itemS()
+
+               row = layout.row()
+               row.itemO("object.hook_reset", text="Reset")
+               row.itemO("object.hook_recenter", text="Recenter")
+
+               if ob.mode == 'EDIT':
+                       row = layout.row()
+                       row.itemO("object.hook_select", text="Select")
+                       row.itemO("object.hook_assign", text="Assign")
+               
+       def LATTICE(self, layout, ob, md):
+               layout.itemR(md, "object")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               
+       def MASK(self, layout, ob, md):
+               layout.itemR(md, "mode")
+               if md.mode == 'ARMATURE':
+                       layout.itemR(md, "armature")
+               elif md.mode == 'VERTEX_GROUP':
+                       layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "inverse")
+               
+       def MESH_DEFORM(self, layout, ob, md):
+               layout.itemR(md, "object")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "invert")
+
+               layout.itemS()
+               
+               if md.is_bound:
+                       layout.itemO("object.meshdeform_bind", text="Unbind")
+               else:
+                       layout.itemO("object.meshdeform_bind", text="Bind")
+                       row = layout.row()
+                       row.itemR(md, "precision")
+                       row.itemR(md, "dynamic")
+               
+       def MIRROR(self, layout, ob, md):
+               layout.itemR(md, "merge_limit")
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(md, "x")
+               col.itemR(md, "y")
+               col.itemR(md, "z")
+               
+               col = split.column()
+               col.itemL(text="Textures:")
+               col.itemR(md, "mirror_u")
+               col.itemR(md, "mirror_v")
+               
+               col = split.column()
+               col.itemR(md, "clip", text="Do Clipping")
+               col.itemR(md, "mirror_vertex_groups", text="Vertex Group")
+               
+               layout.itemR(md, "mirror_object")
+               
+       def MULTIRES(self, layout, ob, md):
+               layout.itemR(md, "subdivision_type")
+               
+               row = layout.row()
+               row.itemO("object.multires_subdivide", text="Subdivide")
+               row.itemO("object.multires_higher_levels_delete", text="Delete Higher")
+
+               layout.itemR(md, "level")
+       
+       def PARTICLE_INSTANCE(self, layout, ob, md):
+               layout.itemR(md, "object")
+               layout.itemR(md, "particle_system_number")
+               
+               flow = layout.column_flow()
+               flow.itemR(md, "normal")
+               flow.itemR(md, "children")
+               flow.itemR(md, "size")
+               flow.itemR(md, "path")
+               if md.path:
+                       flow.itemR(md, "keep_shape")
+               flow.itemR(md, "unborn")
+               flow.itemR(md, "alive")
+               flow.itemR(md, "dead")
+               flow.itemL(md, "")
+               if md.path:
+                       flow.itemR(md, "axis", text="")
+               
+               if md.path:
+                       row = layout.row()
+                       row.itemR(md, "position", slider=True)
+                       row.itemR(md, "random_position", text = "Random", slider=True)
+               
+       def PARTICLE_SYSTEM(self, layout, ob, md):
+               layout.itemL(text="See Particle panel.")
+               
+       def SHRINKWRAP(self, layout, ob, md):
+               layout.itemR(md, "target")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "offset")
+               layout.itemR(md, "subsurf_levels")
+               layout.itemR(md, "mode")
+               if md.mode == 'PROJECT':
+                       layout.itemR(md, "subsurf_levels")
+                       layout.itemR(md, "auxiliary_target")
+               
+                       row = layout.row()
+                       row.itemR(md, "x")
+                       row.itemR(md, "y")
+                       row.itemR(md, "z")
+               
+                       flow = layout.column_flow()
+                       flow.itemR(md, "negative")
+                       flow.itemR(md, "positive")
+                       flow.itemR(md, "cull_front_faces")
+                       flow.itemR(md, "cull_back_faces")
+               elif md.mode == 'NEAREST_SURFACEPOINT':
+                       layout.itemR(md, "keep_above_surface")
+               
+       def SIMPLE_DEFORM(self, layout, ob, md):
+               layout.itemR(md, "mode")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "origin")
+               layout.itemR(md, "relative")
+               layout.itemR(md, "factor")
+               layout.itemR(md, "limits")
+               if md.mode in ('TAPER', 'STRETCH'):
+                       layout.itemR(md, "lock_x_axis")
+                       layout.itemR(md, "lock_y_axis")
+                       
+       def SMOKE(self, layout, ob, md):
+               layout.itemL(text="See Smoke panel.")
+       
+       def SMOOTH(self, layout, ob, md):
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(md, "x")
+               col.itemR(md, "y")
+               col.itemR(md, "z")
+               
+               col = split.column()
+               col.itemR(md, "factor")
+               col.itemR(md, "repeat")
+               
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               
+       def SOFT_BODY(self, layout, ob, md):
+               layout.itemL(text="See Soft Body panel.")
+       
+       def SUBSURF(self, layout, ob, md):
+               layout.row().itemR(md, "subdivision_type", expand=True)
+               
+               flow = layout.column_flow()
+               flow.itemR(md, "levels", text="Preview")
+               flow.itemR(md, "render_levels", text="Render")
+               flow.itemR(md, "optimal_draw", text="Optimal Display")
+               flow.itemR(md, "subsurf_uv")
+
+       def SURFACE(self, layout, ob, md):
+               layout.itemL(text="See Fields panel.")
+       
+       def UV_PROJECT(self, layout, ob, md):
+               if ob.type == 'MESH':
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
+                       layout.itemR(md, "image")
+                       layout.itemR(md, "override_image")
+
+                       split = layout.split()
+
+                       col = split.column()
+                       col.itemL(text="Aspect Ratio:")
+
+                       sub = col.column(align=True)
+                       sub.itemR(md, "horizontal_aspect_ratio", text="Horizontal")
+                       sub.itemR(md, "vertical_aspect_ratio", text="Vertical")
+
+                       col = split.column()
+                       col.itemL(text="Projectors:")
+
+                       sub = col.column(align=True)
+                       sub.itemR(md, "num_projectors", text="Number")
+                       for proj in md.projectors:
+                               sub.itemR(proj, "object", text="")
+               
+       def WAVE(self, layout, ob, md):
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Motion:")
+               col.itemR(md, "x")
+               col.itemR(md, "y")
+               col.itemR(md, "cyclic")
+               
+               col = split.column()
+               col.itemR(md, "normals")
+               sub = col.column()
+               sub.active = md.normals
+               sub.itemR(md, "x_normal", text="X")
+               sub.itemR(md, "y_normal", text="Y")
+               sub.itemR(md, "z_normal", text="Z")
+               
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Time:")
+               sub = col.column(align=True)
+               sub.itemR(md, "time_offset", text="Offset")
+               sub.itemR(md, "lifetime", text="Life")
+               col.itemR(md, "damping_time", text="Damping")
+               
+               col = split.column()
+               col.itemL(text="Position:")
+               sub = col.column(align=True)
+               sub.itemR(md, "start_position_x", text="X")
+               sub.itemR(md, "start_position_y", text="Y")
+               col.itemR(md, "falloff_radius", text="Falloff")
+               
+               layout.itemS()
+               
+               layout.itemR(md, "start_position_object")
+               layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
+               layout.itemR(md, "texture")
+               layout.itemR(md, "texture_coordinates")
+               if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
+               elif md.texture_coordinates == 'OBJECT':
+                       layout.itemR(md, "texture_coordinates_object")
+               
+               layout.itemS()
+               
+               flow = layout.column_flow()
+               flow.itemR(md, "speed", slider=True)
+               flow.itemR(md, "height", slider=True)
+               flow.itemR(md, "width", slider=True)
+               flow.itemR(md, "narrowness", slider=True)
+
+bpy.types.register(DATA_PT_modifiers)
diff --git a/release/ui/buttons_data_text.py b/release/ui/buttons_data_text.py
new file mode 100644 (file)
index 0000000..d0e7ea0
--- /dev/null
@@ -0,0 +1,183 @@
+
+import bpy
+
+class DataButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "data"
+       
+       def poll(self, context):
+               return (context.object and context.object.type == 'TEXT' and context.curve)
+
+class DATA_PT_context_text(DataButtonsPanel):
+       __show_header__ = False
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               curve = context.curve
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "data")
+                       split.itemS()
+               elif curve:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+class DATA_PT_shape_text(DataButtonsPanel):
+       __label__ = "Shape Text"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               curve = context.curve
+               space = context.space_data
+
+               layout.itemR(curve, "curve_2d")                 
+                                                       
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Caps:")
+               row = col.row()
+               row .itemR(curve, "front")
+               row .itemR(curve, "back")
+               # col = split.column()
+               col.itemL(text="Textures:")
+               col.itemR(curve, "uv_orco")
+               col.itemR(curve, "auto_texspace")
+                       
+               col = split.column()    
+               col.itemL(text="Resolution:")
+               sub = col.column(align=True)
+               sub.itemR(curve, "resolution_u", text="Preview U")
+               sub.itemR(curve, "render_resolution_u", text="Render U")
+               
+               # resolution_v is not used for text
+               
+               sub = col.column(align=True)
+               col.itemL(text="Display:")
+               col.itemR(curve, "fast", text="Fast Editing")
+
+class DATA_PT_geometry_text(DataButtonsPanel):
+       __label__ = "Geometry"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               curve = context.curve
+
+               split = layout.split()
+       
+               col = split.column()
+               col.itemL(text="Modification:")
+               col.itemR(curve, "width")
+               col.itemR(curve, "extrude")
+               col.itemL(text="Taper Object:")
+               col.itemR(curve, "taper_object", text="")
+               
+               col = split.column()
+               col.itemL(text="Bevel:")
+               col.itemR(curve, "bevel_depth", text="Depth")
+               col.itemR(curve, "bevel_resolution", text="Resolution")
+               col.itemL(text="Bevel Object:")
+               col.itemR(curve, "bevel_object", text="")
+
+class DATA_PT_font(DataButtonsPanel):
+       __label__ = "Font"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               text = context.curve
+               char = context.curve.edit_format
+
+               layout.itemR(text, "font")
+               
+               row = layout.row()
+               row.itemR(text, "text_size", text="Size")       
+               row.itemR(text, "shear")
+               
+               split = layout.split()
+               
+               col = split.column()    
+               col.itemL(text="Object Font:")
+               col.itemR(text, "family", text="")
+
+               col = split.column()
+               col.itemL(text="Text on Curve:")
+               col.itemR(text, "text_on_curve", text="")
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Character:")
+               col.itemR(char, "bold")
+               col.itemR(char, "italic")
+               col.itemR(char, "underline")
+#              col.itemR(char, "style")
+#              col.itemR(char, "wrap")
+
+               col = split.column(align=True)
+               col.itemL(text="Underline:")
+               col.itemR(text, "ul_position", text="Position")
+               col.itemR(text, "ul_height", text="Thickness")
+               
+
+class DATA_PT_paragraph(DataButtonsPanel):
+       __label__ = "Paragraph"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               text = context.curve
+
+               layout.itemL(text="Align:")
+               layout.itemR(text, "spacemode", expand=True)
+
+               split = layout.split()
+               
+               col = split.column(align=True)  
+               col.itemL(text="Spacing:")
+               col.itemR(text, "spacing", text="Character")
+               col.itemR(text, "word_spacing", text="Word")
+               col.itemR(text, "line_dist", text="Line")
+
+               col = split.column(align=True)
+               col.itemL(text="Offset:")
+               col.itemR(text, "offset_x", text="X")
+               col.itemR(text, "offset_y", text="Y")
+
+
+class DATA_PT_textboxes(DataButtonsPanel):
+       __label__ = "Text Boxes"
+
+       def draw(self, context):
+               layout = self.layout
+                       
+               text = context.curve
+               
+               for box in text.textboxes:
+                       split = layout.box().split()
+                       
+                       col = split.column(align=True)
+                       col.itemL(text="Dimensions:")
+                       col.itemR(box, "width", text="Width")
+                       col.itemR(box, "height", text="Height")
+               
+                       col = split.column(align=True)  
+                       col.itemL(text="Offset:")
+                       col.itemR(box, "x", text="X")
+                       col.itemR(box, "y", text="Y")
+
+bpy.types.register(DATA_PT_context_text)       
+bpy.types.register(DATA_PT_shape_text) 
+bpy.types.register(DATA_PT_geometry_text)
+bpy.types.register(DATA_PT_font)
+bpy.types.register(DATA_PT_paragraph)
+bpy.types.register(DATA_PT_textboxes)
diff --git a/release/ui/buttons_game.py b/release/ui/buttons_game.py
new file mode 100644 (file)
index 0000000..73ba566
--- /dev/null
@@ -0,0 +1,407 @@
+
+import bpy
+class PhysicsButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "physics"
+
+       def poll(self, context):
+               ob = context.active_object
+               rd = context.scene.render_data
+               return ob and ob.game and (rd.engine == 'BLENDER_GAME')
+
+class PHYSICS_PT_game_physics(PhysicsButtonsPanel):
+       __label__ = "Physics"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.active_object
+               game = ob.game
+               soft = ob.game.soft_body
+
+               layout.itemR(game, "physics_type")
+               layout.itemS()
+               
+               #if game.physics_type == 'DYNAMIC':
+               if game.physics_type in ('DYNAMIC', 'RIGID_BODY'):
+
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemR(game, "actor")
+                       col.itemR(game, "ghost")
+                       col.itemR(ob, "restrict_render", text="Invisible") # out of place but useful
+                       
+                       col = split.column()
+                       col.itemR(game, "material_physics")
+                       col.itemR(game, "rotate_from_normal")
+                       col.itemR(game, "no_sleeping")
+                       
+                       layout.itemS()
+                       
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Attributes:")
+                       col.itemR(game, "mass")
+                       col.itemR(game, "radius")
+                       col.itemR(game, "form_factor")
+                       
+                       col = split.column()
+                       sub = col.column()
+                       sub.active = (game.physics_type == 'RIGID_BODY')
+                       sub.itemR(game, "anisotropic_friction")
+                       subsub = sub.column()
+                       subsub.active = game.anisotropic_friction
+                       subsub.itemR(game, "friction_coefficients", text="", slider=True)
+                       
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Velocity:")
+                       sub = col.column(align=True)
+                       sub.itemR(game, "minimum_velocity", text="Minimum")
+                       sub.itemR(game, "maximum_velocity", text="Maximum")
+                       
+                       col = split.column()
+                       col.itemL(text="Damping:")
+                       sub = col.column(align=True)
+                       sub.itemR(game, "damping", text="Translation", slider=True)
+                       sub.itemR(game, "rotation_damping", text="Rotation", slider=True)
+                       
+                       layout.itemS()
+                       
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Lock Translation:")
+                       col.itemR(game, "lock_x_axis", text="X")
+                       col.itemR(game, "lock_y_axis", text="Y")
+                       col.itemR(game, "lock_z_axis", text="Z")
+                       
+                       col = split.column()
+                       col.itemL(text="Lock Rotation:")
+                       col.itemR(game, "lock_x_rot_axis", text="X")
+                       col.itemR(game, "lock_y_rot_axis", text="Y")
+                       col.itemR(game, "lock_z_rot_axis", text="Z")
+               
+               elif game.physics_type == 'SOFT_BODY':
+
+                       col = layout.column()
+                       col.itemR(game, "actor")
+                       col.itemR(game, "ghost")
+                       col.itemR(ob, "restrict_render", text="Invisible")
+                       
+                       layout.itemS()
+                       
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Attributes:")
+                       col.itemR(game, "mass")
+                       col.itemR(soft, "welding")
+                       col.itemR(soft, "position_iterations")
+                       col.itemR(soft, "linstiff", slider=True)
+                       col.itemR(soft, "dynamic_friction", slider=True)
+                       col.itemR(soft, "margin", slider=True)
+                       col.itemR(soft, "bending_const", text="Bending Constraints")
+
+                       col = split.column()
+                       col.itemR(soft, "shape_match")
+                       sub = col.column()
+                       sub.active = soft.shape_match
+                       sub.itemR(soft, "threshold", slider=True)
+                       
+                       col.itemS()
+                       
+                       col.itemL(text="Cluster Collision:")
+                       col.itemR(soft, "cluster_rigid_to_softbody")
+                       col.itemR(soft, "cluster_soft_to_softbody")
+                       sub  = col.column()
+                       sub.active = (soft.cluster_rigid_to_softbody or soft.cluster_soft_to_softbody)
+                       sub.itemR(soft, "cluster_iterations", text="Iterations")
+               
+               elif game.physics_type == 'STATIC':
+                       
+                       col = layout.column()
+                       col.itemR(game, "actor")
+                       col.itemR(game, "ghost")
+                       col.itemR(ob, "restrict_render", text="Invisible")
+                       
+               elif game.physics_type in ('SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'):
+                       
+                       layout.itemR(ob, "restrict_render", text="Invisible")
+                       
+class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel):
+       __label__ = "Collision Bounds"
+
+       def poll(self, context):
+               game = context.object.game
+               rd = context.scene.render_data
+               return (game.physics_type in ('DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC')) and (rd.engine == 'BLENDER_GAME')
+
+       def draw_header(self, context):
+               game = context.active_object.game
+
+               self.layout.itemR(game, "use_collision_bounds", text="")
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               game = context.active_object.game
+
+               layout.active = game.use_collision_bounds
+               layout.itemR(game, "collision_bounds", text="Bounds")
+               
+               row = layout.row()
+               row.itemR(game, "collision_compound", text="Compound")
+               row.itemR(game, "collision_margin", text="Margin", slider=True)
+
+bpy.types.register(PHYSICS_PT_game_physics)
+bpy.types.register(PHYSICS_PT_game_collision_bounds)
+
+class SceneButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "scene"
+
+       def poll(self, context):
+               rd = context.scene.render_data
+               return (rd.engine == 'BLENDER_GAME')
+
+class SCENE_PT_game(SceneButtonsPanel):
+       __label__ = "Game"
+
+       def draw(self, context):
+               layout = self.layout
+
+               row = layout.row()
+               row.itemO("view3d.game_start", text="Start")
+               row.itemL()
+
+class SCENE_PT_game_player(SceneButtonsPanel):
+       __label__ = "Standalone Player"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               gs = context.scene.game_data
+               
+               layout.itemR(gs, "fullscreen")
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Resolution:")
+               sub = col.column(align=True)
+               sub.itemR(gs, "resolution_x", slider=False, text="X")
+               sub.itemR(gs, "resolution_y", slider=False, text="Y")
+
+               col = split.column()
+               col.itemL(text="Quality:")
+               sub = col.column(align=True)
+               sub.itemR(gs, "depth", text="Bit Depth", slider=False)
+               sub.itemR(gs, "frequency", text="FPS", slider=False)
+
+               # framing:
+               col = layout.column()
+               col.itemL(text="Framing:")
+               col.row().itemR(gs, "framing_type", expand=True)
+               if gs.framing_type == 'LETTERBOX':
+                       col.itemR(gs, "framing_color", text="")
+
+class SCENE_PT_game_stereo(SceneButtonsPanel):
+       __label__ = "Stereo"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               gs = context.scene.game_data
+               stereo_mode = gs.stereo
+
+               # stereo options:
+               layout.itemR(gs, "stereo", expand=True)
+               # stereo:
+               if stereo_mode == 'STEREO':
+                       layout.itemR(gs, "stereo_mode")
+                       layout.itemL(text="To do: Focal Length")
+                       layout.itemL(text="To do: Eye Separation")
+
+               # dome:
+               elif stereo_mode == 'DOME':
+                       layout.itemR(gs, "dome_mode", text="Dome Type")
+
+                       dome_type = gs.dome_mode
+
+                       split=layout.split()
+
+                       if dome_type == 'FISHEYE' or \
+                          dome_type == 'TRUNCATED_REAR' or \
+                          dome_type == 'TRUNCATED_FRONT':
+                               
+                               col=split.column()
+                               col.itemR(gs, "dome_angle", slider=True)
+                               col.itemR(gs, "dome_tilt")
+
+                               col=split.column()
+                               col.itemR(gs, "dome_tesselation", text="Tesselation")
+                               col.itemR(gs, "dome_buffer_resolution", text="Resolution", slider=True)
+
+                       elif dome_type == 'PANORAM_SPH':
+                               col=split.column()
+                               col.itemR(gs, "dome_tesselation", text="Tesselation")
+                               col.itemR(gs, "dome_buffer_resolution", text="Resolution", slider=True)
+
+                       else: # cube map
+                               col=split.column()
+                               col.itemR(gs, "dome_buffer_resolution", text="Resolution", slider=True)
+               
+                       layout.itemR(gs, "dome_text")
+
+class SCENE_PT_game_shading(SceneButtonsPanel):
+       __label__ = "Shading"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               gs = context.scene.game_data
+               layout.itemR(gs, "material_mode", expand=True)
+               if gs.material_mode == 'GLSL':
+                       split = layout.split()
+
+                       col = split.column()
+                       col.itemR(gs, "glsl_lights", text="Lights")
+                       col.itemR(gs, "glsl_shaders", text="Shaders")
+                       col.itemR(gs, "glsl_shadows", text="Shadows")
+
+                       col = split.column()
+                       col.itemR(gs, "glsl_ramps", text="Ramps")
+                       col.itemR(gs, "glsl_nodes", text="Nodes")
+                       col.itemR(gs, "glsl_extra_textures", text="Extra Textures")
+
+class SCENE_PT_game_performance(SceneButtonsPanel):
+       __label__ = "Performance"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               gs = context.scene.game_data
+
+               split = layout.split()
+
+               col = split.column()
+               col.itemL(text="Show:")
+               col.itemR(gs, "show_debug_properties", text="Debug Properties")
+               col.itemR(gs, "show_framerate_profile", text="Framerate and Profile")
+               col.itemR(gs, "show_physics_visualization", text="Physics Visualization")
+               col.itemR(gs, "deprecation_warnings")
+               col = split.column()
+               col.itemL(text="Render:")
+               col.itemR(gs, "all_frames")
+               col.itemR(gs, "display_lists")
+
+bpy.types.register(SCENE_PT_game)
+bpy.types.register(SCENE_PT_game_player)
+bpy.types.register(SCENE_PT_game_stereo)
+bpy.types.register(SCENE_PT_game_shading)
+bpy.types.register(SCENE_PT_game_performance)
+
+class WorldButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "world"
+
+       def poll(self, context):
+               rd = context.scene.render_data
+               return (rd.engine == 'BLENDER_GAME')
+
+class WORLD_PT_game_context_world(WorldButtonsPanel):
+       __show_header__ = False
+
+       def poll(self, context):
+               rd = context.scene.render_data
+               return (context.scene) and (rd.use_game_engine)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               scene = context.scene
+               world = context.world
+               space = context.space_data
+
+               split = layout.split(percentage=0.65)
+
+               if scene:
+                       split.template_ID(scene, "world", new="world.new")
+               elif world:
+                       split.template_ID(space, "pin_id")
+
+class WORLD_PT_game_world(WorldButtonsPanel):
+       __label__ = "World"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               world = context.world
+
+               row = layout.row()
+               row.column().itemR(world, "horizon_color")
+               row.column().itemR(world, "ambient_color")
+
+               layout.itemR(world.mist, "enabled", text="Mist")
+
+               row = layout.column_flow()
+               row.active = world.mist.enabled
+               row.itemR(world.mist, "start")
+               row.itemR(world.mist, "depth")
+
+class WORLD_PT_game_physics(WorldButtonsPanel):
+       __label__ = "Physics"
+       def draw(self, context):
+               layout = self.layout
+               
+               gs = context.scene.game_data
+               
+               layout.itemR(gs, "physics_engine")
+               if gs.physics_engine != 'NONE':
+                       layout.itemR(gs, "physics_gravity", text="Gravity")
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Physics Steps:")
+                       sub = col.column(align=True)
+                       sub.itemR(gs, "physics_step_max", text="Max")
+                       sub.itemR(gs, "physics_step_sub", text="Substeps")
+                       col.itemR(gs, "fps", text="FPS")
+                       
+                       col = split.column()
+                       col.itemL(text="Logic Steps:")
+                       col.itemR(gs, "logic_step_max", text="Max")
+                       
+                       col = layout.column()
+                       col.itemR(gs, "use_occlusion_culling", text="Occlusion Culling")
+                       sub = col.column()
+                       sub.active = gs.use_occlusion_culling
+                       sub.itemR(gs, "occlusion_culling_resolution", text="Resolution")
+
+               else:
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Physics Steps:")
+                       col.itemR(gs, "fps", text="FPS")
+                       
+                       col = split.column()
+                       col.itemL(text="Logic Steps:")
+                       col.itemR(gs, "logic_step_max", text="Max")
+
+bpy.types.register(WORLD_PT_game_context_world)
+bpy.types.register(WORLD_PT_game_world)
+bpy.types.register(WORLD_PT_game_physics)
diff --git a/release/ui/buttons_material.py b/release/ui/buttons_material.py
new file mode 100644 (file)
index 0000000..dc11731
--- /dev/null
@@ -0,0 +1,713 @@
+       
+import bpy
+
+class MaterialButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "material"
+       # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (engine in self.COMPAT_ENGINES)
+
+class MATERIAL_PT_preview(MaterialButtonsPanel):
+       __label__ = "Preview"
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def draw(self, context):
+               self.layout.template_preview(context.material)
+               
+class MATERIAL_PT_context_material(MaterialButtonsPanel):
+       __show_header__ = False
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def poll(self, context):
+               # An exception, dont call the parent poll func because
+               # this manages materials for all engine types
+               
+               engine = context.scene.render_data.engine
+               return (context.object) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               ob = context.object
+               slot = context.material_slot
+               space = context.space_data
+
+               if ob:
+                       row = layout.row()
+
+                       row.template_list(ob, "materials", ob, "active_material_index", rows=2)
+
+                       col = row.column(align=True)
+                       col.itemO("object.material_slot_add", icon='ICON_ZOOMIN', text="")
+                       col.itemO("object.material_slot_remove", icon='ICON_ZOOMOUT', text="")
+
+                       if ob.mode == 'EDIT':
+                               row = layout.row(align=True)
+                               row.itemO("object.material_slot_assign", text="Assign")
+                               row.itemO("object.material_slot_select", text="Select")
+                               row.itemO("object.material_slot_deselect", text="Deselect")
+
+               split = layout.split(percentage=0.65)
+
+               if ob:
+                       split.template_ID(ob, "active_material", new="material.new")
+                       row = split.row()
+                       if slot:
+                               row.itemR(slot, "link", text="")
+                       else:
+                               row.itemL()
+               elif mat:
+                       split.template_ID(space, "pin_id")
+                       split.itemS()
+
+               layout.itemR(mat, "type", expand=True)
+       
+class MATERIAL_PT_shading(MaterialButtonsPanel):
+       __label__ = "Shading"
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+
+               if mat.type in ('SURFACE', 'WIRE'):
+                       split = layout.split()
+       
+                       col = split.column()
+                       sub = col.column()
+                       sub.active = not mat.shadeless
+                       sub.itemR(mat, "emit")
+                       sub.itemR(mat, "ambient")
+                       sub = col.column()
+                       sub.itemR(mat, "translucency")
+                               
+                       col = split.column()
+                       col.itemR(mat, "shadeless")     
+                       sub = col.column()
+                       sub.active = not mat.shadeless
+                       sub.itemR(mat, "tangent_shading")
+                       sub.itemR(mat, "cubic")
+                               
+               elif mat.type == 'HALO':
+                       layout.itemR(mat, "alpha")
+                       
+class MATERIAL_PT_strand(MaterialButtonsPanel):
+       __label__ = "Strand"
+       __default_closed__ = True
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               tan = mat.strand
+               
+               split = layout.split()
+               
+               col = split.column(align=True)
+               col.itemL(text="Size:")
+               col.itemR(tan, "root_size", text="Root")
+               col.itemR(tan, "tip_size", text="Tip")
+               col.itemR(tan, "min_size", text="Minimum")
+               col.itemR(tan, "blender_units")
+               sub = col.column()
+               sub.active = (not mat.shadeless)
+               sub.itemR(tan, "tangent_shading")
+               col.itemR(tan, "shape")
+               
+               col = split.column()
+               col.itemL(text="Shading:")
+               col.itemR(tan, "width_fade")
+               col.itemR(tan, "uv_layer")
+               col.itemS()
+               sub = col.column()
+               sub.active = (not mat.shadeless)
+               sub.itemR(tan, "surface_diffuse")
+               sub = col.column()
+               sub.active = tan.surface_diffuse
+               sub.itemR(tan, "blend_distance", text="Distance")
+               
+class MATERIAL_PT_physics(MaterialButtonsPanel):
+       __label__ = "Physics"
+       COMPAT_ENGINES = set(['BLENDER_GAME'])
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               phys = context.material.physics
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(phys, "distance")
+               col.itemR(phys, "friction")
+               col.itemR(phys, "align_to_normal")
+               
+               col = split.column()
+               col.itemR(phys, "force", slider=True)
+               col.itemR(phys, "elasticity", slider=True)
+               col.itemR(phys, "damp", slider=True)
+               
+class MATERIAL_PT_options(MaterialButtonsPanel):
+       __label__ = "Options"
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "traceable")
+               col.itemR(mat, "full_oversampling")
+               col.itemR(mat, "sky")
+               col.itemR(mat, "exclude_mist")
+               col.itemR(mat, "invert_z")
+               sub = col.column(align=True)
+               sub.itemL(text="Light Group:")
+               sub.itemR(mat, "light_group", text="")
+               row = sub.row()
+               row.active = mat.light_group
+               row.itemR(mat, "light_group_exclusive", text="Exclusive")
+
+               col = split.column()
+               col.itemR(mat, "face_texture")
+               sub = col.column()
+               sub.active = mat.face_texture
+               sub.itemR(mat, "face_texture_alpha")
+               col.itemS()
+               col.itemR(mat, "vertex_color_paint")
+               col.itemR(mat, "vertex_color_light")
+               col.itemR(mat, "object_color")
+
+class MATERIAL_PT_shadow(MaterialButtonsPanel):
+       __label__ = "Shadow"
+       __default_closed__ = True
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+       
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "shadows", text="Receive")
+               col.itemR(mat, "receive_transparent_shadows", text="Receive Transparent")
+               col.itemR(mat, "only_shadow", text="Shadows Only")
+               col.itemR(mat, "cast_shadows_only", text="Cast Only")
+               col.itemR(mat, "shadow_casting_alpha", text="Casting Alpha")
+               
+               col = split.column()
+               col.itemR(mat, "cast_buffer_shadows")
+               sub = col.column()
+               sub.active = mat.cast_buffer_shadows
+               sub.itemR(mat, "shadow_buffer_bias", text="Buffer Bias")
+               col.itemR(mat, "ray_shadow_bias", text="Auto Ray Bias")
+               sub = col.column()
+               sub.active = (not mat.ray_shadow_bias)
+               sub.itemR(mat, "shadow_ray_bias", text="Ray Bias")
+
+class MATERIAL_PT_diffuse(MaterialButtonsPanel):
+       __label__ = "Diffuse"
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material  
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "diffuse_color", text="")
+               sub = col.column()
+               sub.active = (not mat.shadeless)
+               sub.itemR(mat, "diffuse_intensity", text="Intensity")
+               
+               col = split.column()
+               col.active = (not mat.shadeless)
+               col.itemR(mat, "diffuse_shader", text="")
+               col.itemR(mat, "use_diffuse_ramp", text="Ramp")
+               
+               col = layout.column()
+               col.active = (not mat.shadeless)
+               if mat.diffuse_shader == 'OREN_NAYAR':
+                       col.itemR(mat, "roughness")
+               elif mat.diffuse_shader == 'MINNAERT':
+                       col.itemR(mat, "darkness")
+               elif mat.diffuse_shader == 'TOON':
+                       row = col.row()
+                       row.itemR(mat, "diffuse_toon_size", text="Size")
+                       row.itemR(mat, "diffuse_toon_smooth", text="Smooth")
+               elif mat.diffuse_shader == 'FRESNEL':
+                       row = col.row()
+                       row.itemR(mat, "diffuse_fresnel", text="Fresnel")
+                       row.itemR(mat, "diffuse_fresnel_factor", text="Factor")
+                       
+               if mat.use_diffuse_ramp:
+                       layout.itemS()
+                       layout.template_color_ramp(mat.diffuse_ramp, expand=True)
+                       layout.itemS()
+                       row = layout.row()
+                       split = row.split(percentage=0.3)
+                       split.itemL(text="Input:")
+                       split.itemR(mat, "diffuse_ramp_input", text="")
+                       split = row.split(percentage=0.3)
+                       split.itemL(text="Blend:")
+                       split.itemR(mat, "diffuse_ramp_blend", text="")
+
+class MATERIAL_PT_specular(MaterialButtonsPanel):
+       __label__ = "Specular"
+       COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               
+               layout.active = (not mat.shadeless)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "specular_color", text="")
+               col.itemR(mat, "specular_intensity", text="Intensity")
+
+               col = split.column()
+               col.itemR(mat, "specular_shader", text="")
+               col.itemR(mat, "use_specular_ramp", text="Ramp")
+
+               col = layout.column()
+               if mat.specular_shader in ('COOKTORR', 'PHONG'):
+                       col.itemR(mat, "specular_hardness", text="Hardness")
+               elif mat.specular_shader == 'BLINN':
+                       row = col.row()
+                       row.itemR(mat, "specular_hardness", text="Hardness")
+                       row.itemR(mat, "specular_ior", text="IOR")
+               elif mat.specular_shader == 'WARDISO':
+                       col.itemR(mat, "specular_slope", text="Slope")
+               elif mat.specular_shader == 'TOON':
+                       row = col.row()
+                       row.itemR(mat, "specular_toon_size", text="Size")
+                       row.itemR(mat, "specular_toon_smooth", text="Smooth")
+               
+               if mat.use_specular_ramp:
+                       layout.itemS()
+                       layout.template_color_ramp(mat.specular_ramp, expand=True)
+                       layout.itemS()
+                       row = layout.row()
+                       split = row.split(percentage=0.3)
+                       split.itemL(text="Input:")
+                       split.itemR(mat, "specular_ramp_input", text="")
+                       split = row.split(percentage=0.3)
+                       split.itemL(text="Blend:")
+                       split.itemR(mat, "specular_ramp_blend", text="")
+               
+class MATERIAL_PT_sss(MaterialButtonsPanel):
+       __label__ = "Subsurface Scattering"
+       __default_closed__ = True
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+       
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+
+       def draw_header(self, context):
+               sss = context.material.subsurface_scattering
+               mat = context.material
+               
+               self.layout.active = (not mat.shadeless)
+               self.layout.itemR(sss, "enabled", text="")
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               sss = context.material.subsurface_scattering
+
+               layout.active = sss.enabled     
+               
+               split = layout.split()
+               split.active = (not mat.shadeless)
+               
+               col = split.column()
+               col.itemR(sss, "ior")
+               col.itemR(sss, "scale")
+               col.itemR(sss, "color", text="")
+               col.itemR(sss, "radius", text="RGB Radius")
+               
+               col = split.column()
+               sub = col.column(align=True)
+               sub.itemL(text="Blend:")
+               sub.itemR(sss, "color_factor", text="Color")
+               sub.itemR(sss, "texture_factor", text="Texture")
+               sub.itemL(text="Scattering Weight:")
+               sub.itemR(sss, "front")
+               sub.itemR(sss, "back")
+               col.itemS()
+               col.itemR(sss, "error_tolerance", text="Error")
+
+class MATERIAL_PT_mirror(MaterialButtonsPanel):
+       __label__ = "Mirror"
+       __default_closed__ = True
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+       
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+       
+       def draw_header(self, context): 
+               raym = context.material.raytrace_mirror
+
+               self.layout.itemR(raym, "enabled", text="")
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               raym = context.material.raytrace_mirror
+               
+               layout.active = raym.enabled
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(raym, "reflect_factor")
+               col.itemR(mat, "mirror_color", text="")
+
+               col = split.column()
+               col.itemR(raym, "fresnel")
+               sub = col.column()
+               sub.active = raym.fresnel > 0
+               sub.itemR(raym, "fresnel_factor", text="Blend")
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemS()
+               col.itemR(raym, "distance", text="Max Dist")
+               col.itemR(raym, "depth")
+               col.itemS()
+               sub = col.split(percentage=0.4)
+               sub.itemL(text="Fade To:")
+               sub.itemR(raym, "fade_to", text="")
+               
+               col = split.column()
+               col.itemL(text="Gloss:")
+               col.itemR(raym, "gloss_factor", text="Amount")
+               sub = col.column()
+               sub.active = raym.gloss_factor < 1.0
+               sub.itemR(raym, "gloss_threshold", text="Threshold")
+               sub.itemR(raym, "gloss_samples", text="Samples")
+               sub.itemR(raym, "gloss_anisotropic", text="Anisotropic")
+
+class MATERIAL_PT_transp(MaterialButtonsPanel):
+       __label__= "Transparency"
+       __default_closed__ = True
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+               
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
+
+       def draw_header(self, context): 
+               mat = context.material
+               self.layout.itemR(mat, "transparency", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               rayt = context.material.raytrace_transparency
+               
+               row = layout.row()
+               row.active = mat.transparency and (not mat.shadeless)
+               row.itemR(mat, "transparency_method", expand=True)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "alpha")
+               row = col.row()
+               row.active = mat.transparency and (not mat.shadeless)
+               row.itemR(mat, "specular_alpha", text="Specular")
+
+               col = split.column()
+               col.active = (not mat.shadeless)
+               col.itemR(rayt, "fresnel")
+               sub = col.column()
+               sub.active = rayt.fresnel > 0
+               sub.itemR(rayt, "fresnel_factor", text="Blend")
+
+               if mat.transparency_method == 'RAYTRACE':
+                       layout.itemS()
+                       split = layout.split()
+                       split.active = mat.transparency
+
+                       col = split.column()
+                       col.itemR(rayt, "ior")
+                       col.itemR(rayt, "filter")
+                       col.itemR(rayt, "falloff")
+                       col.itemR(rayt, "limit")
+                       col.itemR(rayt, "depth")
+                       
+                       col = split.column()
+                       col.itemL(text="Gloss:")
+                       col.itemR(rayt, "gloss_factor", text="Amount")
+                       sub = col.column()
+                       sub.active = rayt.gloss_factor < 1.0
+                       sub.itemR(rayt, "gloss_threshold", text="Threshold")
+                       sub.itemR(rayt, "gloss_samples", text="Samples")
+
+class MATERIAL_PT_halo(MaterialButtonsPanel):
+       __label__= "Halo"
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+       
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type == 'HALO') and (engine in self.COMPAT_ENGINES)
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               halo = mat.halo
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(mat, "diffuse_color", text="")
+               col.itemR(halo, "size")
+               col.itemR(halo, "hardness")
+               col.itemR(halo, "add")
+               col.itemL(text="Options:")
+               col.itemR(halo, "texture")
+               col.itemR(halo, "vertex_normal")
+               col.itemR(halo, "xalpha")
+               col.itemR(halo, "shaded")
+               col.itemR(halo, "soft")
+
+               col = split.column()
+               col.itemR(halo, "ring")
+               sub = col.column()
+               sub.active = halo.ring
+               sub.itemR(halo, "rings")
+               sub.itemR(mat, "mirror_color", text="")
+               col.itemS()
+               col.itemR(halo, "lines")
+               sub = col.column()
+               sub.active = halo.lines
+               sub.itemR(halo, "line_number", text="Lines")
+               sub.itemR(mat, "specular_color", text="")
+               col.itemS()
+               col.itemR(halo, "star")
+               sub = col.column()
+               sub.active = halo.star
+               sub.itemR(halo, "star_tips")
+               
+class MATERIAL_PT_flare(MaterialButtonsPanel):
+       __label__= "Flare"
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+       
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type == 'HALO') and (engine in self.COMPAT_ENGINES)
+       
+       def draw_header(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               halo = mat.halo
+               layout.itemR(halo, "flare_mode", text="")
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               halo = mat.halo
+
+               layout.active = halo.flare_mode
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(halo, "flare_size", text="Size")
+               col.itemR(halo, "flare_boost", text="Boost")
+               col.itemR(halo, "flare_seed", text="Seed")
+               col = split.column()
+               col.itemR(halo, "flares_sub", text="Subflares")
+               col.itemR(halo, "flare_subsize", text="Subsize")
+               
+bpy.types.register(MATERIAL_PT_context_material)
+bpy.types.register(MATERIAL_PT_preview)
+bpy.types.register(MATERIAL_PT_diffuse)
+bpy.types.register(MATERIAL_PT_specular)
+bpy.types.register(MATERIAL_PT_shading)
+bpy.types.register(MATERIAL_PT_transp)
+bpy.types.register(MATERIAL_PT_mirror)
+bpy.types.register(MATERIAL_PT_sss)
+bpy.types.register(MATERIAL_PT_halo)
+bpy.types.register(MATERIAL_PT_flare)
+bpy.types.register(MATERIAL_PT_physics)
+bpy.types.register(MATERIAL_PT_strand)
+bpy.types.register(MATERIAL_PT_options)
+bpy.types.register(MATERIAL_PT_shadow)
+
+# Volumetrics
+class VolumeButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "material"
+
+       def poll(self, context):
+               mat = context.material
+               engine = context.scene.render_data.engine
+               return mat and (mat.type == 'VOLUME') and (engine in self.COMPAT_ENGINES)
+               
+class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
+       __label__ = "Shading"
+       __default_closed__ = False
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw(self, context):
+               layout = self.layout
+
+               mat = context.material
+               vol = context.material.volume
+               
+               row = layout.row()
+               row.itemR(vol, "density")
+               row.itemR(vol, "scattering")
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(vol, "absorption")
+               col.itemR(vol, "absorption_color", text="")
+
+               col = split.column()
+               col.itemR(vol, "emission")
+               col.itemR(vol, "emission_color", text="")
+
+class MATERIAL_PT_volume_scattering(VolumeButtonsPanel):
+       __label__ = "Scattering"
+       __default_closed__ = False
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw(self, context):
+               layout = self.layout
+               
+               vol = context.material.volume
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(vol, "scattering_mode", text="")
+               if vol.scattering_mode == 'SINGLE_SCATTERING':
+                       col.itemR(vol, "light_cache")
+                       sub = col.column()
+                       sub.active = vol.light_cache
+                       sub.itemR(vol, "cache_resolution")
+               elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'):
+                       col.itemR(vol, "cache_resolution")
+                       
+                       col = col.column(align=True)
+                       col.itemR(vol, "ms_diffusion")
+                       col.itemR(vol, "ms_spread")
+                       col.itemR(vol, "ms_intensity")
+               
+               col = split.column()
+               # col.itemL(text="Anisotropic Scattering:")
+               col.itemR(vol, "phase_function", text="")
+               if vol.phase_function in ('SCHLICK', 'HENYEY-GREENSTEIN'):
+                       col.itemR(vol, "asymmetry")
+
+class MATERIAL_PT_volume_transp(VolumeButtonsPanel):
+       __label__= "Transparency"
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               rayt = context.material.raytrace_transparency
+               
+               row= layout.row()
+               row.itemR(mat, "transparency_method", expand=True)
+               row.active = mat.transparency and (not mat.shadeless)
+               
+class MATERIAL_PT_volume_integration(VolumeButtonsPanel):
+       __label__ = "Integration"
+       __default_closed__ = False
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw(self, context):
+               layout = self.layout
+               
+               mat = context.material
+               vol = context.material.volume
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Step Calculation:")
+               col.itemR(vol, "step_calculation", text="")
+               col = col.column(align=True)
+               col.itemR(vol, "step_size")
+               col.itemR(vol, "shading_step_size")
+               
+               col = split.column()
+               col.itemL()
+               col.itemR(vol, "depth_cutoff")
+               col.itemR(vol, "density_scale")
+
+bpy.types.register(MATERIAL_PT_volume_shading)
+bpy.types.register(MATERIAL_PT_volume_scattering)
+bpy.types.register(MATERIAL_PT_volume_transp)
+bpy.types.register(MATERIAL_PT_volume_integration)
diff --git a/release/ui/buttons_object.py b/release/ui/buttons_object.py
new file mode 100644 (file)
index 0000000..af2c7cf
--- /dev/null
@@ -0,0 +1,181 @@
+
+import bpy
+
+class ObjectButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "object"
+
+class OBJECT_PT_context_object(ObjectButtonsPanel):
+       __show_header__ = False
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               
+               row = layout.row()
+               row.itemL(text="", icon='ICON_OBJECT_DATA')
+               row.itemR(ob, "name", text="")
+
+class OBJECT_PT_transform(ObjectButtonsPanel):
+       __label__ = "Transform"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               row = layout.row()
+               row.column().itemR(ob, "location")
+               row.column().itemR(ob, "rotation")
+               row.column().itemR(ob, "scale")
+
+class OBJECT_PT_relations(ObjectButtonsPanel):
+       __label__ = "Relations"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(ob, "layers")
+               col.itemS()
+               col.itemR(ob, "pass_index")
+
+               col = split.column()
+               col.itemL(text="Parent:")
+               col.itemR(ob, "parent", text="")
+
+               sub = col.column()
+               split = sub.split(percentage=0.3)
+               split.itemL(text="Type:")
+               split.itemR(ob, "parent_type", text="")
+               parent = ob.parent
+               if parent and ob.parent_type == 'BONE' and parent.type == 'ARMATURE':
+                       sub.item_pointerR(ob, "parent_bone", parent.data, "bones", text="")
+               sub.active = parent != None
+
+class OBJECT_PT_groups(ObjectButtonsPanel):
+       __label__ = "Groups"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               split = layout.split()
+               split.item_menu_enumO("object.group_add", "group", text="Add to Group")
+               split.itemL()
+
+               for group in bpy.data.groups:
+                       if ob.name in group.objects:
+                               col = layout.column(align=True)
+
+                               col.set_context_pointer("group", group)
+
+                               row = col.box().row()
+                               row.itemR(group, "name", text="")
+                               row.itemO("object.group_remove", text="", icon='VICON_X')
+
+                               split = col.box().split()
+                               split.column().itemR(group, "layer", text="Dupli")
+                               split.column().itemR(group, "dupli_offset", text="")
+
+class OBJECT_PT_display(ObjectButtonsPanel):
+       __label__ = "Display"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+                       
+               row = layout.row()
+               row.itemR(ob, "max_draw_type", text="Type")
+               row.itemR(ob, "draw_bounds_type", text="Bounds")
+
+               flow = layout.column_flow()
+               flow.itemR(ob, "draw_name", text="Name")
+               flow.itemR(ob, "draw_axis", text="Axis")
+               flow.itemR(ob, "draw_wire", text="Wire")
+               flow.itemR(ob, "draw_texture_space", text="Texture Space")
+               flow.itemR(ob, "x_ray", text="X-Ray")
+               flow.itemR(ob, "draw_transparent", text="Transparency")
+
+class OBJECT_PT_duplication(ObjectButtonsPanel):
+       __label__ = "Duplication"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+
+               layout.itemR(ob, "dupli_type", expand=True)
+
+               if ob.dupli_type == 'FRAMES':
+                       split = layout.split()
+                       
+                       col = split.column(align=True)
+                       col.itemR(ob, "dupli_frames_start", text="Start")
+                       col.itemR(ob, "dupli_frames_end", text="End")
+                       
+                       col = split.column(align=True)
+                       col.itemR(ob, "dupli_frames_on", text="On")
+                       col.itemR(ob, "dupli_frames_off", text="Off")
+                       
+                       layout.itemR(ob, "dupli_frames_no_speed", text="No Speed")
+
+               elif ob.dupli_type == 'VERTS':
+                       layout.itemR(ob, "dupli_verts_rotation", text="Rotation")
+
+               elif ob.dupli_type == 'FACES':
+                       row = layout.row()
+                       row.itemR(ob, "dupli_faces_scale", text="Scale")
+                       row.itemR(ob, "dupli_faces_inherit_scale", text="Inherit Scale")
+
+               elif ob.dupli_type == 'GROUP':
+                       layout.itemR(ob, "dupli_group", text="Group")
+
+class OBJECT_PT_animation(ObjectButtonsPanel):
+       __label__ = "Animation"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Time Offset:")
+               col.itemR(ob, "time_offset_edit", text="Edit")
+               row = col.row()
+               row.itemR(ob, "time_offset_particle", text="Particle")
+               row.active = len(ob.particle_systems) != 0
+               row = col.row()
+               row.itemR(ob, "time_offset_parent", text="Parent")
+               row.active = ob.parent != None
+               row = col.row()
+               row.itemR(ob, "slow_parent")
+               row.active = ob.parent != None
+               col.itemR(ob, "time_offset", text="Offset")
+
+               col = split.column()
+               col.itemL(text="Track:")
+               col.itemR(ob, "track", text="")
+               col.itemR(ob, "track_axis", text="Axis")
+               col.itemR(ob, "up_axis", text="Up Axis")
+               row = col.row()
+               row.itemR(ob, "track_override_parent", text="Override Parent")
+               row.active = ob.parent != None
+
+bpy.types.register(OBJECT_PT_context_object)
+bpy.types.register(OBJECT_PT_transform)
+bpy.types.register(OBJECT_PT_relations)
+bpy.types.register(OBJECT_PT_groups)
+bpy.types.register(OBJECT_PT_display)
+bpy.types.register(OBJECT_PT_duplication)
+bpy.types.register(OBJECT_PT_animation)
diff --git a/release/ui/buttons_object_constraint.py b/release/ui/buttons_object_constraint.py
new file mode 100644 (file)
index 0000000..ff3231a
--- /dev/null
@@ -0,0 +1,535 @@
+
+import bpy
+
+class ConstraintButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "constraint"
+
+       def draw_constraint(self, con):
+               layout = self.layout
+               
+               box = layout.template_constraint(con)
+
+               if box:
+                       # match enum type to our functions, avoids a lookup table.
+                       getattr(self, con.type)(box, con)
+       
+                       # show/key buttons here are most likely obsolete now, with
+                       # keyframing functionality being part of every button
+                       if con.type not in ('RIGID_BODY_JOINT', 'NULL'):
+                               box.itemR(con, "influence")
+       
+       def space_template(self, layout, con, target=True, owner=True):
+               if target or owner:
+                       row = layout.row()
+
+                       row.itemL(text="Convert:")
+
+                       if target:
+                               row.itemR(con, "target_space", text="")
+
+                       if target and owner:
+                               row.itemL(icon='ICON_ARROW_LEFTRIGHT')
+
+                       if owner:
+                               row.itemR(con, "owner_space", text="")
+                       
+       def target_template(self, layout, con, subtargets=True):
+               layout.itemR(con, "target") # XXX limiting settings for only 'curves' or some type of object
+               
+               if con.target and subtargets:
+                       if con.target.type == 'ARMATURE':
+                               layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone")
+                               
+                               if con.type == 'COPY_LOCATION':
+                                       row = layout.row()
+                                       row.itemL(text="Head/Tail:")
+                                       row.itemR(con, "head_tail", text="")
+                       elif con.target.type in ('MESH', 'LATTICE'):
+                               layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
+       
+       def CHILD_OF(self, layout, con):
+               self.target_template(layout, con)
+
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Location:")
+               col.itemR(con, "locationx", text="X")
+               col.itemR(con, "locationy", text="Y")
+               col.itemR(con, "locationz", text="Z")
+               
+               col = split.column()
+               col.itemL(text="Rotation:")
+               col.itemR(con, "rotationx", text="X")
+               col.itemR(con, "rotationy", text="Y")
+               col.itemR(con, "rotationz", text="Z")
+               
+               col = split.column()
+               col.itemL(text="Scale:")
+               col.itemR(con, "sizex", text="X")
+               col.itemR(con, "sizey", text="Y")
+               col.itemR(con, "sizez", text="Z")
+               
+               row = layout.row()
+               row.itemO("constraint.childof_set_inverse")
+               row.itemO("constraint.childof_clear_inverse")
+               
+       def TRACK_TO(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row()
+               row.itemL(text="To:")
+               row.itemR(con, "track", expand=True)
+               
+               row = layout.row()
+               #row.itemR(con, "up", text="Up", expand=True) # XXX: up and expand don't play nice together
+               row.itemR(con, "up", text="Up")
+               row.itemR(con, "target_z")
+               
+               self.space_template(layout, con)
+               
+       def IK(self, layout, con):
+               self.target_template(layout, con)
+               
+               layout.itemR(con, "pole_target")
+       
+               if con.pole_target and con.pole_target.type == 'ARMATURE':
+                       layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
+               
+               split = layout.split()
+       
+               col = split.column()
+               col.itemR(con, "iterations")
+               col.itemR(con, "chain_length")
+               sub = col.column()
+               sub.active = con.pole_target
+               sub.itemR(con, "pole_angle")
+               col.itemL(text="Weight:")
+               col.itemR(con, "weight", text="Position", slider=True)
+               sub = col.column()
+               sub.active = con.rotation
+               sub.itemR(con, "orient_weight", text="Rotation", slider=True)
+               
+               col = split.column()
+               col.itemR(con, "tail")
+               col.itemR(con, "rotation")
+               col.itemR(con, "targetless")
+               col.itemR(con, "stretch")
+               
+       def FOLLOW_PATH(self, layout, con):
+               self.target_template(layout, con)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(con, "curve_follow")
+               
+               col = split.column()
+               col.itemR(con, "fixed_position")
+               if con.fixed_position:
+                       col.itemR(con, "offset_percentage", text="Offset")
+               else:
+                       col.itemR(con, "offset")
+               
+               row = layout.row()
+               row.itemL(text="Forward:")
+               row.itemR(con, "forward", expand=True)
+               
+               row = layout.row()
+               row.itemR(con, "up", text="Up")
+               row.itemL()
+               
+       def LIMIT_ROTATION(self, layout, con):
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(con, "use_limit_x")
+               sub = col.column()
+               sub.active = con.use_limit_x
+               sub.itemR(con, "minimum_x", text="Min")
+               sub.itemR(con, "maximum_x", text="Max")
+               
+               col = split.column()
+               col.itemR(con, "use_limit_y")
+               sub = col.column()
+               sub.active = con.use_limit_y
+               sub.itemR(con, "minimum_y", text="Min")
+               sub.itemR(con, "maximum_y", text="Max")
+               
+               col = split.column()
+               col.itemR(con, "use_limit_z")
+               sub = col.column()
+               sub.active = con.use_limit_z
+               sub.itemR(con, "minimum_z", text="Min")
+               sub.itemR(con, "maximum_z", text="Max")
+               
+               row = layout.row()
+               row.itemR(con, "limit_transform")
+               row.itemL()
+               
+               row = layout.row()
+               row.itemL(text="Convert:")
+               row.itemR(con, "owner_space", text="")
+               
+       def LIMIT_LOCATION(self, layout, con):
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(con, "use_minimum_x")
+               sub = col.column()
+               sub.active = con.use_minimum_x
+               sub.itemR(con, "minimum_x", text="")
+               col.itemR(con, "use_maximum_x")
+               sub = col.column()
+               sub.active = con.use_maximum_x
+               sub.itemR(con, "maximum_x", text="")
+               
+               col = split.column()
+               col.itemR(con, "use_minimum_y")
+               sub = col.column()
+               sub.active = con.use_minimum_y
+               sub.itemR(con, "minimum_y", text="")
+               col.itemR(con, "use_maximum_y")
+               sub = col.column()
+               sub.active = con.use_maximum_y
+               sub.itemR(con, "maximum_y", text="")
+               
+               col = split.column()
+               col.itemR(con, "use_minimum_z")
+               sub = col.column()
+               sub.active = con.use_minimum_z
+               sub.itemR(con, "minimum_z", text="")
+               col.itemR(con, "use_maximum_z")
+               sub = col.column()
+               sub.active = con.use_maximum_z
+               sub.itemR(con, "maximum_z", text="")
+       
+               row = layout.row()
+               row.itemR(con, "limit_transform")
+               row.itemL()
+               
+               row = layout.row()
+               row.itemL(text="Convert:")
+               row.itemR(con, "owner_space", text="")
+               
+       def LIMIT_SCALE(self, layout, con):
+               split = layout.split()
+
+               col = split.column()
+               col.itemR(con, "use_minimum_x")
+               sub = col.column()
+               sub.active = con.use_minimum_x
+               sub.itemR(con, "minimum_x", text="")
+               col.itemR(con, "use_maximum_x")
+               sub = col.column()
+               sub.active = con.use_maximum_x
+               sub.itemR(con, "maximum_x", text="")
+               
+               col = split.column()
+               col.itemR(con, "use_minimum_y")
+               sub = col.column()
+               sub.active = con.use_minimum_y
+               sub.itemR(con, "minimum_y", text="")
+               col.itemR(con, "use_maximum_y")
+               sub = col.column()
+               sub.active = con.use_maximum_y
+               sub.itemR(con, "maximum_y", text="")
+               
+               col = split.column()
+               col.itemR(con, "use_minimum_z")
+               sub = col.column()
+               sub.active = con.use_minimum_z
+               sub.itemR(con, "minimum_z", text="")
+               col.itemR(con, "use_maximum_z")
+               sub = col.column()
+               sub.active = con.use_maximum_z
+               sub.itemR(con, "maximum_z", text="")
+               
+               row = layout.row()
+               row.itemR(con, "limit_transform")
+               row.itemL()
+               
+               row = layout.row()
+               row.itemL(text="Convert:")
+               row.itemR(con, "owner_space", text="")
+       
+       def COPY_ROTATION(self, layout, con):
+               self.target_template(layout, con)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(con, "rotate_like_x", text="X")
+               sub = col.column()
+               sub.active = con.rotate_like_x
+               sub.itemR(con, "invert_x", text="Invert")
+               
+               col = split.column()
+               col.itemR(con, "rotate_like_y", text="Y")
+               sub = col.column()
+               sub.active = con.rotate_like_y
+               sub.itemR(con, "invert_y", text="Invert")
+               
+               col = split.column()
+               col.itemR(con, "rotate_like_z", text="Z")
+               sub = col.column()
+               sub.active = con.rotate_like_z
+               sub.itemR(con, "invert_z", text="Invert")
+
+               layout.itemR(con, "offset")
+               
+               self.space_template(layout, con)
+               
+       def COPY_LOCATION(self, layout, con):
+               self.target_template(layout, con)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(con, "locate_like_x", text="X")
+               sub = col.column()
+               sub.active = con.locate_like_x
+               sub.itemR(con, "invert_x", text="Invert")
+               
+               col = split.column()
+               col.itemR(con, "locate_like_y", text="Y")
+               sub = col.column()
+               sub.active = con.locate_like_y
+               sub.itemR(con, "invert_y", text="Invert")
+               
+               col = split.column()
+               col.itemR(con, "locate_like_z", text="Z")
+               sub = col.column()
+               sub.active = con.locate_like_z
+               sub.itemR(con, "invert_z", text="Invert")
+
+               layout.itemR(con, "offset")
+                       
+               self.space_template(layout, con)
+               
+       def COPY_SCALE(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row(align=True)
+               row.itemR(con, "size_like_x", text="X")
+               row.itemR(con, "size_like_y", text="Y")
+               row.itemR(con, "size_like_z", text="Z")
+
+               layout.itemR(con, "offset")
+               
+               self.space_template(layout, con)
+               
+       #def SCRIPT(self, layout, con):
+       
+       def ACTION(self, layout, con):
+               self.target_template(layout, con)
+               
+               layout.itemR(con, "action")
+               layout.itemR(con, "transform_channel")
+
+               split = layout.split()
+       
+               col = split.column(align=True)
+               col.itemR(con, "start_frame", text="Start")
+               col.itemR(con, "end_frame", text="End")
+               
+               col = split.column(align=True)
+               col.itemR(con, "minimum", text="Min")
+               col.itemR(con, "maximum", text="Max")
+               
+               row = layout.row()
+               row.itemL(text="Convert:")
+               row.itemR(con, "owner_space", text="")
+       
+       def LOCKED_TRACK(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row()
+               row.itemL(text="To:")
+               row.itemR(con, "track", expand=True)
+               
+               row = layout.row()
+               row.itemL(text="Lock:")
+               row.itemR(con, "locked", expand=True)
+               
+       def LIMIT_DISTANCE(self, layout, con):
+               self.target_template(layout, con)
+               
+               col = layout.column(align=True);
+               col.itemR(con, "distance")
+               col.itemO("constraint.limitdistance_reset")
+               
+               row = layout.row()
+               row.itemL(text="Clamp Region:")
+               row.itemR(con, "limit_mode", text="")
+               
+       def STRETCH_TO(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row()
+               row.itemR(con, "original_length", text="Rest Length")
+               row.itemO("constraint.stretchto_reset", text="Reset")
+               
+               col = layout.column()
+               col.itemR(con, "bulge", text="Volume Variation")
+               
+               row = layout.row()
+               row.itemL(text="Volume:")
+               row.itemR(con, "volume", expand=True)
+               row.itemL(text="Plane:")
+               row.itemR(con, "keep_axis", expand=True)
+               
+       def FLOOR(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row()
+               row.itemR(con, "sticky")
+               row.itemR(con, "use_rotation")
+               
+               layout.itemR(con, "offset")
+               
+               row = layout.row()
+               row.itemL(text="Min/Max:")
+               row.itemR(con, "floor_location", expand=True)
+               
+       def RIGID_BODY_JOINT(self, layout, con):
+               self.target_template(layout, con)
+               
+               layout.itemR(con, "pivot_type")
+               layout.itemR(con, "child")
+               
+               row = layout.row()
+               row.itemR(con, "disable_linked_collision", text="No Collision")
+               row.itemR(con, "draw_pivot", text="Display Pivot")
+               
+               split = layout.split()
+               
+               col = split.column(align=True)
+               col.itemL(text="Pivot:")
+               col.itemR(con, "pivot_x", text="X")
+               col.itemR(con, "pivot_y", text="Y")
+               col.itemR(con, "pivot_z", text="Z")
+               
+               col = split.column(align=True)
+               col.itemL(text="Axis:")
+               col.itemR(con, "axis_x", text="X")
+               col.itemR(con, "axis_y", text="Y")
+               col.itemR(con, "axis_z", text="Z")
+               
+               #Missing: Limit arrays (not wrapped in RNA yet) 
+       
+       def CLAMP_TO(self, layout, con):
+               self.target_template(layout, con)
+               
+               row = layout.row()
+               row.itemL(text="Main Axis:")
+               row.itemR(con, "main_axis", expand=True)
+               
+               row = layout.row()
+               row.itemR(con, "cyclic")
+               
+       def TRANSFORM(self, layout, con):
+               self.target_template(layout, con)
+               
+               layout.itemR(con, "extrapolate_motion", text="Extrapolate")
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Source:")
+               col.row().itemR(con, "map_from", expand=True)
+               
+               sub = col.row(align=True)
+               sub.itemL(text="X:")
+               sub.itemR(con, "from_min_x", text="")
+               sub.itemR(con, "from_max_x", text="")
+               
+               sub = col.row(align=True)
+               sub.itemL(text="Y:")
+               sub.itemR(con, "from_min_y", text="")
+               sub.itemR(con, "from_max_y", text="")
+               
+               sub = col.row(align=True)
+               sub.itemL(text="Z:")
+               sub.itemR(con, "from_min_z", text="")
+               sub.itemR(con, "from_max_z", text="")
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Destination:")
+               col.row().itemR(con, "map_to", expand=True)
+
+               sub = col.row(align=True)
+               sub.itemR(con, "map_to_x_from", text="")
+               sub.itemR(con, "to_min_x", text="")
+               sub.itemR(con, "to_max_x", text="")
+               
+               sub = col.row(align=True)
+               sub.itemR(con, "map_to_y_from", text="")
+               sub.itemR(con, "to_min_y", text="")
+               sub.itemR(con, "to_max_y", text="")
+               
+               sub = col.row(align=True)
+               sub.itemR(con, "map_to_z_from", text="")
+               sub.itemR(con, "to_min_z", text="")
+               sub.itemR(con, "to_max_z", text="")
+               
+               self.space_template(layout, con)
+               
+       def SHRINKWRAP (self, layout, con):
+               self.target_template(layout, con)
+               
+               layout.itemR(con, "distance")
+               layout.itemR(con, "shrinkwrap_type")
+               
+               if con.shrinkwrap_type == 'PROJECT':
+                       row = layout.row(align=True)
+                       row.itemR(con, "axis_x")
+                       row.itemR(con, "axis_y")
+                       row.itemR(con, "axis_z")
+               
+class OBJECT_PT_constraints(ConstraintButtonsPanel):
+       __label__ = "Constraints"
+       __context__ = "constraint"
+
+       def poll(self, context):
+               return (context.object)
+               
+       def draw(self, context):
+               layout = self.layout
+               ob = context.object
+
+               row = layout.row()
+               row.item_menu_enumO("object.constraint_add", "type")
+               row.itemL();
+
+               for con in ob.constraints:
+                       self.draw_constraint(con)
+
+class BONE_PT_constraints(ConstraintButtonsPanel):
+       __label__ = "Constraints"
+       __context__ = "bone"
+
+       def poll(self, context):
+               ob = context.object
+               return (ob and ob.type == 'ARMATURE' and context.bone)
+               
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               pchan = ob.pose.pose_channels[context.bone.name]
+
+               row = layout.row()
+               row.item_menu_enumO("pose.constraint_add", "type")
+               row.itemL();
+
+               for con in pchan.constraints:
+                       self.draw_constraint(con)
+
+bpy.types.register(OBJECT_PT_constraints)
+bpy.types.register(BONE_PT_constraints)
diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py
new file mode 100644 (file)
index 0000000..1d496e1
--- /dev/null
@@ -0,0 +1,959 @@
+
+import bpy
+
+def particle_panel_enabled(psys):
+       return psys.point_cache.baked==False and psys.edited==False
+       
+def particle_panel_poll(context):
+       psys = context.particle_system
+       if psys==None:  return False
+       if psys.settings==None:  return False
+       return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
+       
+def point_cache_ui(self, cache, enabled, particles, smoke):
+       layout = self.layout
+       layout.set_context_pointer("PointCache", cache)
+       
+       row = layout.row()
+       row.template_list(cache, "point_cache_list", cache, "active_point_cache_index", rows=2 )
+       col = row.column(align=True)
+       col.itemO("ptcache.add_new", icon='ICON_ZOOMIN', text="")
+       col.itemO("ptcache.remove", icon='ICON_ZOOMOUT', text="")
+       
+       row = layout.row()
+       row.itemL(text="File Name:")
+       if particles:
+               row.itemR(cache, "external")
+       
+       if cache.external:
+               split = layout.split(percentage=0.80)
+               split.itemR(cache, "name", text="")
+               split.itemR(cache, "index", text="")
+               
+               layout.itemL(text="File Path:")
+               layout.itemR(cache, "filepath", text="")
+               
+               layout.itemL(text=cache.info)
+       else:
+               layout.itemR(cache, "name", text="")
+               
+               if not particles:
+                       row = layout.row()
+                       row.enabled = enabled
+                       row.itemR(cache, "start_frame")
+                       row.itemR(cache, "end_frame")
+               
+               row = layout.row()
+       
+               if cache.baked == True:
+                       row.itemO("ptcache.free_bake", text="Free Bake")
+               else:
+                       row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
+       
+               sub = row.row()
+               sub.enabled = (cache.frames_skipped or cache.outdated) and enabled
+               sub.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
+               
+               row = layout.row()
+               row.enabled = enabled
+               row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
+               row.itemR(cache, "step");
+       
+               if not smoke:
+                       row = layout.row()
+                       sub = row.row()
+                       sub.enabled = enabled
+                       sub.itemR(cache, "quick_cache")
+                       row.itemR(cache, "disk_cache")
+       
+               layout.itemL(text=cache.info)
+               
+               layout.itemS()
+               
+               row = layout.row()
+               row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
+               row.itemO("ptcache.free_bake_all", text="Free All Bakes")
+               layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
+       
+
+class ParticleButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "particle"
+
+       def poll(self, context):
+               return particle_panel_poll(context)
+
+class PARTICLE_PT_particles(ParticleButtonsPanel):
+       __show_header__ = False
+
+       def poll(self, context):
+               return (context.particle_system or context.object)
+
+       def draw(self, context):
+               layout = self.layout
+               ob = context.object
+               psys = context.particle_system
+
+               if ob:
+                       row = layout.row()
+
+                       row.template_list(ob, "particle_systems", ob, "active_particle_system_index", rows=2)
+
+                       col = row.column(align=True)
+                       col.itemO("object.particle_system_add", icon='ICON_ZOOMIN', text="")
+                       col.itemO("object.particle_system_remove", icon='ICON_ZOOMOUT', text="")
+
+               if psys and not psys.settings:
+                       split = layout.split(percentage=0.32)
+                       col = split.column()
+                       col.itemL(text="Name:")
+                       col.itemL(text="Settings:")
+                       
+                       col = split.column()
+                       col.itemR(psys, "name", text="")
+                       col.template_ID(psys, "settings", new="particle.new")
+               elif psys:
+                       part = psys.settings
+                       
+                       split = layout.split(percentage=0.32)
+                       col = split.column()
+                       col.itemL(text="Name:")
+                       if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
+                               col.itemL(text="Settings:")
+                               col.itemL(text="Type:")
+                       
+                       col = split.column()
+                       col.itemR(psys, "name", text="")
+                       if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
+                               col.template_ID(psys, "settings", new="particle.new")
+                       
+                       #row = layout.row()
+                       #row.itemL(text="Viewport")
+                       #row.itemL(text="Render")
+                       
+                       if part:
+                               if part.type not in ('EMITTER', 'REACTOR', 'HAIR'):
+                                       layout.itemL(text="No settings for fluid particles")
+                                       return
+                               
+                               row=col.row()
+                               row.enabled = particle_panel_enabled(psys)
+                               row.itemR(part, "type", text="")
+                               row.itemR(psys, "seed")
+                               
+                               split = layout.split(percentage=0.65)
+                               if part.type=='HAIR':
+                                       if psys.edited==True:
+                                               split.itemO("particle.edited_clear", text="Free Edit")
+                                       else:
+                                               split.itemL(text="")
+                                       row = split.row()
+                                       row.enabled = particle_panel_enabled(psys)
+                                       row.itemR(part, "hair_step")
+                                       if psys.edited==True:
+                                               if psys.global_hair:
+                                                       layout.itemO("particle.connect_hair")
+                                                       layout.itemL(text="Hair is disconnected.")
+                                               else:
+                                                       layout.itemO("particle.disconnect_hair")
+                                                       layout.itemL(text="")
+                               elif part.type=='REACTOR':
+                                       split.enabled = particle_panel_enabled(psys)
+                                       split.itemR(psys, "reactor_target_object")
+                                       split.itemR(psys, "reactor_target_particle_system", text="Particle System")
+               
+class PARTICLE_PT_emission(ParticleButtonsPanel):
+       __label__ = "Emission"
+       
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       return not context.particle_system.point_cache.external
+               else:
+                       return False
+       
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.enabled = particle_panel_enabled(psys) and not psys.multiple_caches
+               
+               row = layout.row()
+               row.itemR(part, "amount")
+               
+               split = layout.split()
+               
+               col = split.column(align=True)
+               col.itemR(part, "start")
+               col.itemR(part, "end")
+
+               col = split.column(align=True)
+               col.itemR(part, "lifetime")
+               col.itemR(part, "random_lifetime", slider=True)
+               
+               layout.row().itemL(text="Emit From:")
+               
+               row = layout.row()
+               row.itemR(part, "emit_from", expand=True)
+               row = layout.row()
+               row.itemR(part, "trand")
+               if part.distribution!='GRID':
+                       row.itemR(part, "even_distribution")
+               
+               if part.emit_from=='FACE' or part.emit_from=='VOLUME':
+                       row = layout.row()
+                       row.itemR(part, "distribution", expand=True)
+                       
+                       row = layout.row()
+
+                       if part.distribution=='JIT':
+                               row.itemR(part, "userjit", text="Particles/Face")
+                               row.itemR(part, "jitter_factor", text="Jittering Amount", slider=True)
+                       elif part.distribution=='GRID':
+                               row.itemR(part, "grid_resolution")
+
+class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel):
+       __label__ = "Hair dynamics"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               psys = context.particle_system
+               if psys==None:  return False
+               if psys.settings==None:  return False
+               return psys.settings.type == 'HAIR'
+               
+       def draw_header(self, context):
+               #cloth = context.cloth.collision_settings
+               
+               #self.layout.active = cloth_panel_enabled(context.cloth)
+               #self.layout.itemR(cloth, "enable_collision", text="")
+               psys = context.particle_system
+               self.layout.itemR(psys, "hair_dynamics", text="")
+               
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               cloth = psys.cloth.settings
+               
+               layout.enabled = psys.hair_dynamics
+               
+               split = layout.split()
+                       
+               col = split.column()
+               col.itemL(text="Quality:")
+               col.itemR(cloth, "quality", text="Steps",slider=True)
+               col.itemL(text="Gravity:")
+               col.itemR(cloth, "gravity", text="")
+               
+               col = split.column()
+               col.itemL(text="Material:")
+               sub = col.column(align=True)
+               sub.itemR(cloth, "pin_stiffness", text="Stiffness")
+               sub.itemR(cloth, "mass")
+               col.itemL(text="Damping:")
+               sub = col.column(align=True)
+               sub.itemR(cloth, "spring_damping", text="Spring")
+               sub.itemR(cloth, "air_damping", text="Air")
+               
+               layout.itemR(cloth, "internal_friction", slider="True")
+                               
+class PARTICLE_PT_cache(ParticleButtonsPanel):
+       __label__ = "Cache"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               psys = context.particle_system
+               if psys==None:  return False
+               if psys.settings==None:  return False
+               phystype = psys.settings.physics_type
+               if phystype == 'NO' or phystype == 'KEYED':
+                       return False
+               return psys.settings.type in ('EMITTER', 'REACTOR') or (psys.settings.type == 'HAIR' and psys.hair_dynamics)
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               
+               point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0)
+
+class PARTICLE_PT_initial(ParticleButtonsPanel):
+       __label__ = "Velocity"
+       
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       psys = context.particle_system
+                       return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
+               else:
+                       return False
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.enabled = particle_panel_enabled(psys)
+                               
+               layout.row().itemL(text="Direction:")
+       
+               split = layout.split()
+                       
+               sub = split.column()
+               sub.itemR(part, "normal_factor")
+               if part.emit_from=='PARTICLE':
+                       sub.itemR(part, "particle_factor")
+               else:
+                       sub.itemR(part, "object_factor", slider=True)
+               sub.itemR(part, "random_factor")
+               sub.itemR(part, "tangent_factor")
+               sub.itemR(part, "tangent_phase", slider=True)
+               
+               sub = split.column()
+               sub.itemL(text="TODO:")
+               sub.itemL(text="Object aligned")
+               sub.itemL(text="direction: X, Y, Z")
+               
+               if part.type=='REACTOR':
+                       sub.itemR(part, "reactor_factor")
+                       sub.itemR(part, "reaction_shape", slider=True)
+               else:
+                       sub.itemL(text="")
+               
+               layout.row().itemL(text="Rotation:")
+               split = layout.split()
+                       
+               sub = split.column()
+               
+               sub.itemR(part, "rotation_mode", text="Axis")
+               split = layout.split()
+                       
+               sub = split.column()
+               sub.itemR(part, "rotation_dynamic")
+               sub.itemR(part, "random_rotation_factor", slider=True)
+               sub = split.column()
+               sub.itemR(part, "phase_factor", slider=True)
+               sub.itemR(part, "random_phase_factor", text="Random", slider=True)
+
+               layout.row().itemL(text="Angular velocity:")
+               layout.row().itemR(part, "angular_velocity_mode", expand=True)
+               split = layout.split()
+                       
+               sub = split.column()
+               
+               sub.itemR(part, "angular_velocity_factor", text="")
+               
+class PARTICLE_PT_physics(ParticleButtonsPanel):
+       __label__ = "Physics"
+       
+       def poll(self, context):
+               if particle_panel_poll(context):
+                       return not context.particle_system.point_cache.external
+               else:
+                       return False
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.enabled = particle_panel_enabled(psys)
+
+               row = layout.row()
+               row.itemR(part, "physics_type", expand=True)
+               if part.physics_type != 'NO':
+                       row = layout.row()
+                       col = row.column(align=True)
+                       col.itemR(part, "particle_size")
+                       col.itemR(part, "random_size", slider=True)
+                       col = row.column(align=True)
+                       col.itemR(part, "mass")
+                       col.itemR(part, "sizemass", text="Multiply mass with size")
+                       
+               if part.physics_type == 'NEWTON':
+                       split = layout.split()
+                       sub = split.column()
+                       
+                       sub.itemL(text="Forces:")
+                       sub.itemR(part, "brownian_factor")
+                       sub.itemR(part, "drag_factor", slider=True)
+                       sub.itemR(part, "damp_factor", slider=True)
+                       sub.itemR(part, "integrator")
+                       sub = split.column()
+                       sub.itemR(part, "acceleration")
+                       
+               elif part.physics_type == 'KEYED':
+                       split = layout.split()
+                       sub = split.column()
+                       
+                       row = layout.row()
+                       col = row.column()
+                       col.active = not psys.keyed_timing
+                       col.itemR(part, "keyed_loops", text="Loops")
+                       row.itemR(psys, "keyed_timing", text="Use Timing")
+                       
+                       layout.itemL(text="Keys:")
+               elif part.physics_type=='BOIDS':
+                       boids = part.boids
+                       
+
+                       row = layout.row()
+                       row.itemR(boids, "allow_flight")
+                       row.itemR(boids, "allow_land")
+                       row.itemR(boids, "allow_climb")
+                       
+                       split = layout.split()
+                       
+                       sub = split.column()
+                       col = sub.column(align=True)
+                       col.active = boids.allow_flight
+                       col.itemR(boids, "air_max_speed")
+                       col.itemR(boids, "air_min_speed", slider="True")
+                       col.itemR(boids, "air_max_acc", slider="True")
+                       col.itemR(boids, "air_max_ave", slider="True")
+                       col.itemR(boids, "air_personal_space")
+                       row = col.row()
+                       row.active = (boids.allow_land or boids.allow_climb) and boids.allow_flight
+                       row.itemR(boids, "landing_smoothness")
+                       
+                       sub = split.column()
+                       col = sub.column(align=True)
+                       col.active = boids.allow_land or boids.allow_climb
+                       col.itemR(boids, "land_max_speed")
+                       col.itemR(boids, "land_jump_speed")
+                       col.itemR(boids, "land_max_acc", slider="True")
+                       col.itemR(boids, "land_max_ave", slider="True")
+                       col.itemR(boids, "land_personal_space")
+                       col.itemR(boids, "land_stick_force")
+                       
+                       row = layout.row()
+                       
+                       col = row.column(align=True)
+                       col.itemL(text="Battle:")
+                       col.itemR(boids, "health")
+                       col.itemR(boids, "strength")
+                       col.itemR(boids, "aggression")
+                       col.itemR(boids, "accuracy")
+                       col.itemR(boids, "range")
+                       
+                       col = row.column()
+                       col.itemL(text="Misc:")
+                       col.itemR(part, "gravity")
+                       col.itemR(boids, "banking", slider=True)
+                       col.itemR(boids, "height", slider=True)
+                       
+               if part.physics_type=='NEWTON':
+                       sub.itemR(part, "size_deflect")
+                       sub.itemR(part, "die_on_collision")
+               elif part.physics_type=='KEYED' or part.physics_type=='BOIDS':
+                       if part.physics_type=='BOIDS':
+                               layout.itemL(text="Relations:")
+                       
+                       row = layout.row()
+                       row.template_list(psys, "targets", psys, "active_particle_target_index")
+                       
+                       col = row.column()
+                       subrow = col.row()
+                       subcol = subrow.column(align=True)
+                       subcol.itemO("particle.new_target", icon='ICON_ZOOMIN', text="")
+                       subcol.itemO("particle.remove_target", icon='ICON_ZOOMOUT', text="")
+                       subrow = col.row()
+                       subcol = subrow.column(align=True)
+                       subcol.itemO("particle.target_move_up", icon='VICON_MOVE_UP', text="")
+                       subcol.itemO("particle.target_move_down", icon='VICON_MOVE_DOWN', text="")
+                       
+                       key = psys.active_particle_target
+                       if key:
+                               row = layout.row()
+                               if part.physics_type=='KEYED':
+                                       col = row.column()
+                                       #doesn't work yet
+                                       #col.red_alert = key.valid
+                                       col.itemR(key, "object", text="")
+                                       col.itemR(key, "system", text="System")
+                                       col = row.column();
+                                       col.active = psys.keyed_timing
+                                       col.itemR(key, "time")
+                                       col.itemR(key, "duration")
+                               else:
+                                       subrow = row.row()
+                                       #doesn't work yet
+                                       #subrow.red_alert = key.valid
+                                       subrow.itemR(key, "object", text="")
+                                       subrow.itemR(key, "system", text="System")
+                                       
+                                       layout.itemR(key, "mode", expand=True)
+
+class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
+       __label__ = "Boid Brain"
+
+       def poll(self, context):
+               psys = context.particle_system
+               if psys==None:  return False
+               if psys.settings==None:  return False
+               if psys.point_cache.external: return False
+               return psys.settings.physics_type=='BOIDS'
+       
+       def draw(self, context):
+               boids = context.particle_system.settings.boids
+               layout = self.layout
+               
+               layout.enabled = particle_panel_enabled(psys)
+               
+               # Currently boids can only use the first state so these are commented out for now.
+               #row = layout.row()
+               #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
+               #col = row.row()
+               #subrow = col.row(align=True)
+               #subrow.itemO("boid.boidstate_add", icon='ICON_ZOOMIN', text="")
+               #subrow.itemO("boid.boidstate_del", icon='ICON_ZOOMOUT', text="")
+               #subrow = row.row(align=True)
+               #subrow.itemO("boid.boidstate_move_up", icon='VICON_MOVE_UP', text="")
+               #subrow.itemO("boid.boidstate_move_down", icon='VICON_MOVE_DOWN', text="")
+               
+               state = boids.active_boid_state
+               
+               #layout.itemR(state, "name", text="State name")
+               
+               row = layout.row()
+               row.itemR(state, "ruleset_type")
+               if state.ruleset_type=='FUZZY':
+                       row.itemR(state, "rule_fuzziness", slider=True)
+               else:
+                       row.itemL(text="")
+               
+               row = layout.row()
+               row.template_list(state, "rules", state, "active_boid_rule_index")
+               
+               col = row.column()
+               subrow = col.row()
+               subcol = subrow.column(align=True)
+               subcol.item_menu_enumO("boid.boidrule_add", "type", icon='ICON_ZOOMIN', text="")
+               subcol.itemO("boid.boidrule_del", icon='ICON_ZOOMOUT', text="")
+               subrow = col.row()
+               subcol = subrow.column(align=True)
+               subcol.itemO("boid.boidrule_move_up", icon='VICON_MOVE_UP', text="")
+               subcol.itemO("boid.boidrule_move_down", icon='VICON_MOVE_DOWN', text="")
+               
+               rule = state.active_boid_rule
+               
+               if rule:
+                       row = layout.row()
+                       row.itemR(rule, "name", text="")
+                       #somebody make nice icons for boids here please! -jahka
+                       row.itemR(rule, "in_air", icon='VICON_MOVE_UP', text="")
+                       row.itemR(rule, "on_land", icon='VICON_MOVE_DOWN', text="")
+                       
+                       row = layout.row()
+
+                       if rule.type == 'GOAL':
+                               row.itemR(rule, "object")
+                               row = layout.row()
+                               row.itemR(rule, "predict")
+                       elif rule.type == 'AVOID':
+                               row.itemR(rule, "object")
+                               row = layout.row()
+                               row.itemR(rule, "predict")
+                               row.itemR(rule, "fear_factor")
+                       elif rule.type == 'FOLLOW_PATH':
+                               row.itemL(text="Not yet functional.")
+                       elif rule.type == 'AVOID_COLLISION':
+                               row.itemR(rule, "boids")
+                               row.itemR(rule, "deflectors")
+                               row.itemR(rule, "look_ahead")
+                       elif rule.type == 'FOLLOW_LEADER':
+                               row.itemR(rule, "object", text="")
+                               row.itemR(rule, "distance")
+                               row = layout.row()
+                               row.itemR(rule, "line")
+                               subrow = row.row()
+                               subrow.active = rule.line
+                               subrow.itemR(rule, "queue_size")
+                       elif rule.type == 'AVERAGE_SPEED':
+                               row.itemR(rule, "speed", slider=True)
+                               row.itemR(rule, "wander", slider=True)
+                               row.itemR(rule, "level", slider=True)
+                       elif rule.type == 'FIGHT':
+                               row.itemR(rule, "distance")
+                               row.itemR(rule, "flee_distance")
+               
+
+class PARTICLE_PT_render(ParticleButtonsPanel):
+       __label__ = "Render"
+       
+       def poll(self, context):
+               psys = context.particle_system
+               if psys==None: return False
+               if psys.settings==None: return False
+               return True;
+               
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+
+               row = layout.row()
+               row.itemR(part, "material")
+               row.itemR(psys, "parent");
+               
+               split = layout.split()
+                       
+               sub = split.column()
+               sub.itemR(part, "emitter");
+               sub.itemR(part, "parent");
+               sub = split.column()
+               sub.itemR(part, "unborn");
+               sub.itemR(part, "died");
+               
+               row = layout.row()
+               row.itemR(part, "ren_as", expand=True)
+               
+               split = layout.split()
+                       
+               sub = split.column()
+               
+               if part.ren_as == 'LINE':
+                       sub.itemR(part, "line_length_tail")
+                       sub.itemR(part, "line_length_head")
+                       sub = split.column()
+                       sub.itemR(part, "velocity_length")
+               elif part.ren_as == 'PATH':
+               
+                       if (part.type!='HAIR' and part.physics_type!='KEYED' and psys.point_cache.baked==False):
+                               box = layout.box()
+                               box.itemL(text="Baked or keyed particles needed for correct rendering.")
+                               return
+                               
+                       sub.itemR(part, "render_strand")
+                       colsub = sub.column()
+                       colsub.active = part.render_strand == False
+                       colsub.itemR(part, "render_adaptive")
+                       colsub = sub.column()
+                       colsub.active = part.render_adaptive or part.render_strand == True
+                       colsub.itemR(part, "adaptive_angle")
+                       colsub = sub.column()
+                       colsub.active = part.render_adaptive == True and part.render_strand == False
+                       colsub.itemR(part, "adaptive_pix")
+                       sub.itemR(part, "hair_bspline")
+                       sub.itemR(part, "render_step", text="Steps")
+                       sub = split.column()    
+
+                       sub.itemL(text="Timing:")
+                       sub.itemR(part, "abs_path_time")
+                       sub.itemR(part, "path_start", text="Start", slider= not part.abs_path_time)
+                       sub.itemR(part, "path_end", text="End", slider= not part.abs_path_time)         
+                       sub.itemR(part, "random_length", text="Random", slider=True)
+                       
+                       row = layout.row()
+                       col = row.column()
+                       
+                       if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
+                               layout.itemR(part, "enable_simplify")
+                               if part.enable_simplify==True:
+                                       row = layout.row()
+                                       row.itemR(part, "simplify_refsize")
+                                       row.itemR(part, "simplify_rate")
+                                       row.itemR(part, "simplify_transition")
+                                       row = layout.row()
+                                       row.itemR(part, "viewport")
+                                       subrow = row.row()
+                                       subrow.active = part.viewport==True
+                                       subrow.itemR(part, "simplify_viewport")
+                       
+
+               elif part.ren_as == 'OBJECT':
+                       sub.itemR(part, "dupli_object")
+               elif part.ren_as == 'GROUP':
+                       sub.itemR(part, "dupli_group")
+                       split = layout.split()
+                       sub = split.column()
+                       sub.itemR(part, "whole_group")
+                       sub = split.column()
+                       colsub = sub.column()
+                       colsub.active = part.whole_group == False
+                       colsub.itemR(part, "rand_group")
+                       
+               elif part.ren_as == 'BILLBOARD':
+                       sub.itemL(text="Align:")
+                       
+                       row = layout.row()
+                       row.itemR(part, "billboard_align", expand=True)
+                       row.itemR(part, "billboard_lock", text="Lock")
+                       row = layout.row()
+                       row.itemR(part, "billboard_object")
+               
+                       row = layout.row()
+                       col = row.column(align=True)
+                       col.itemL(text="Tilt:")
+                       col.itemR(part, "billboard_tilt", text="Angle", slider=True)
+                       col.itemR(part, "billboard_random_tilt", slider=True)
+                       col = row.column()
+                       col.itemR(part, "billboard_offset")
+                       
+                       row = layout.row()
+                       row.itemR(psys, "billboard_normal_uv")
+                       row = layout.row()
+                       row.itemR(psys, "billboard_time_index_uv")
+                       
+                       row = layout.row()
+                       row.itemL(text="Split uv's:")
+                       row.itemR(part, "billboard_uv_split", text="Number of splits")
+                       row = layout.row()
+                       row.itemR(psys, "billboard_split_uv")
+                       row = layout.row()
+                       row.itemL(text="Animate:")
+                       row.itemR(part, "billboard_animation", expand=True)
+                       row.itemL(text="Offset:")
+                       row.itemR(part, "billboard_split_offset", expand=True)
+               if part.ren_as == 'HALO' or part.ren_as == 'LINE' or part.ren_as=='BILLBOARD':
+                       row = layout.row()
+                       col = row.column()
+                       col.itemR(part, "trail_count")
+                       if part.trail_count > 1:
+                               col.itemR(part, "abs_path_time", text="Length in frames")
+                               col = row.column()
+                               col.itemR(part, "path_end", text="Length", slider=not part.abs_path_time)
+                               col.itemR(part, "random_length", text="Random", slider=True)
+                       else:
+                               col = row.column()
+                               col.itemL(text="")
+                               
+class PARTICLE_PT_draw(ParticleButtonsPanel):
+       __label__ = "Display"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               psys = context.particle_system
+               if psys==None: return False
+               if psys.settings==None: return False
+               return True;
+       
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               row = layout.row()
+               row.itemR(part, "draw_as", expand=True)
+               
+               if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
+                       return
+                       
+               path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
+                       
+               if path and part.type!='HAIR' and part.physics_type!='KEYED' and psys.point_cache.baked==False:
+                       box = layout.box()
+                       box.itemL(text="Baked or keyed particles needed for correct drawing.")
+                       return
+               
+               row = layout.row()
+               row.itemR(part, "display", slider=True)
+               if part.draw_as!='RENDER' or part.ren_as=='HALO':
+                       row.itemR(part, "draw_size")
+               else:
+                       row.itemL(text="")
+               
+               row = layout.row()
+               col = row.column()
+               col.itemR(part, "show_size")
+               col.itemR(part, "velocity")
+               col.itemR(part, "num")
+               if part.physics_type == 'BOIDS':
+                       col.itemR(part, "draw_health")
+               
+               col = row.column()
+               col.itemR(part, "material_color", text="Use material color")
+               
+               if (path):                      
+                       col.itemR(part, "draw_step")
+               else:
+                       subcol = col.column()
+                       subcol.active = part.material_color==False
+                       #subcol.itemL(text="color")
+                       #subcol.itemL(text="Override material color")
+
+class PARTICLE_PT_children(ParticleButtonsPanel):
+       __label__ = "Children"
+       __default_closed__ = True
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.row().itemR(part, "child_type", expand=True)
+               
+               if part.child_type=='NONE':
+                       return
+               
+               row = layout.row()
+               
+               col = row.column(align=True)
+               col.itemR(part, "child_nbr", text="Display")
+               col.itemR(part, "rendered_child_nbr", text="Render")
+               
+               col = row.column(align=True)
+               
+               if part.child_type=='FACES':
+                       col.itemR(part, "virtual_parents", slider=True)
+               else:
+                       col.itemR(part, "child_radius", text="Radius")
+                       col.itemR(part, "child_roundness", text="Roundness", slider=True)
+               
+                       col = row.column(align=True)
+                       col.itemR(part, "child_size", text="Size")
+                       col.itemR(part, "child_random_size", text="Random")
+               
+               layout.row().itemL(text="Effects:")
+               
+               row = layout.row()
+               
+               col = row.column(align=True)
+               col.itemR(part, "clump_factor", slider=True)
+               col.itemR(part, "clumppow", slider=True)
+               
+               col = row.column(align=True)
+               col.itemR(part, "rough_endpoint")
+               col.itemR(part, "rough_end_shape")
+
+               row = layout.row()
+               
+               col = row.column(align=True)
+               col.itemR(part, "rough1")
+               col.itemR(part, "rough1_size")
+
+               col = row.column(align=True)
+               col.itemR(part, "rough2")
+               col.itemR(part, "rough2_size")
+               col.itemR(part, "rough2_thres", slider=True)
+               
+               row = layout.row()
+               col = row.column(align=True)
+               col.itemR(part, "child_length", slider=True)
+               col.itemR(part, "child_length_thres", slider=True)
+               
+               col = row.column(align=True)
+               col.itemL(text="Space reserved for")
+               col.itemL(text="hair parting controls")
+               
+               layout.row().itemL(text="Kink:")
+               layout.row().itemR(part, "kink", expand=True)
+               
+               split = layout.split()
+               
+               sub = split.column()
+               sub.itemR(part, "kink_amplitude")
+               sub.itemR(part, "kink_frequency")
+               sub = split.column()
+               sub.itemR(part, "kink_shape", slider=True)
+
+class PARTICLE_PT_effectors(ParticleButtonsPanel):
+       __label__ = "Effectors"
+       __default_closed__ = True
+       
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.itemR(part, "effector_group")
+               
+               layout.itemR(part, "eweight_all", slider=True)
+               
+               layout.itemS()
+               layout.itemR(part, "eweight_spherical", slider=True)
+               layout.itemR(part, "eweight_vortex", slider=True)
+               layout.itemR(part, "eweight_magnetic", slider=True)
+               layout.itemR(part, "eweight_wind", slider=True)
+               layout.itemR(part, "eweight_curveguide", slider=True)
+               layout.itemR(part, "eweight_texture", slider=True)
+               layout.itemR(part, "eweight_harmonic", slider=True)
+               layout.itemR(part, "eweight_charge", slider=True)
+               layout.itemR(part, "eweight_lennardjones", slider=True)
+               
+class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
+       __label__ = "Vertexgroups"
+       __default_closed__ = True
+
+       def draw(self, context):
+               layout = self.layout
+
+               psys = context.particle_system
+               part = psys.settings
+               
+               layout.itemL(text="Nothing here yet.")
+
+               #row = layout.row()
+               #row.itemL(text="Vertex Group")
+               #row.itemL(text="Negate")
+
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_density")
+               #row.itemR(psys, "vertex_group_density_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_velocity")
+               #row.itemR(psys, "vertex_group_velocity_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_length")
+               #row.itemR(psys, "vertex_group_length_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_clump")
+               #row.itemR(psys, "vertex_group_clump_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_kink")
+               #row.itemR(psys, "vertex_group_kink_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_roughness1")
+               #row.itemR(psys, "vertex_group_roughness1_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_roughness2")
+               #row.itemR(psys, "vertex_group_roughness2_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_roughness_end")
+               #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
+
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_size")
+               #row.itemR(psys, "vertex_group_size_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_tangent")
+               #row.itemR(psys, "vertex_group_tangent_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_rotation")
+               #row.itemR(psys, "vertex_group_rotation_negate", text="")
+               
+               #row = layout.row()
+               #row.itemR(psys, "vertex_group_field")
+               #row.itemR(psys, "vertex_group_field_negate", text="")
+               
+bpy.types.register(PARTICLE_PT_particles)
+bpy.types.register(PARTICLE_PT_hair_dynamics)
+bpy.types.register(PARTICLE_PT_cache)
+bpy.types.register(PARTICLE_PT_emission)
+bpy.types.register(PARTICLE_PT_initial)
+bpy.types.register(PARTICLE_PT_physics)
+bpy.types.register(PARTICLE_PT_boidbrain)
+bpy.types.register(PARTICLE_PT_render)
+bpy.types.register(PARTICLE_PT_draw)
+bpy.types.register(PARTICLE_PT_children)
+bpy.types.register(PARTICLE_PT_effectors)
+bpy.types.register(PARTICLE_PT_vertexgroups)
diff --git a/release/ui/buttons_physics_cloth.py b/release/ui/buttons_physics_cloth.py
new file mode 100644 (file)
index 0000000..5cdca3c
--- /dev/null
@@ -0,0 +1,172 @@
+
+import bpy
+
+from buttons_particle import point_cache_ui
+
+def cloth_panel_enabled(md):
+       return md.point_cache.baked==False
+
+class PhysicButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "physics"
+
+       def poll(self, context):
+               ob = context.object
+               rd = context.scene.render_data
+               return (ob and ob.type == 'MESH') and (not rd.use_game_engine)
+               
+class PHYSICS_PT_cloth(PhysicButtonsPanel):
+       __label__ = "Cloth"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               md = context.cloth
+               ob = context.object
+
+               split = layout.split()
+               split.operator_context = 'EXEC_DEFAULT'
+
+               if md:
+                       # remove modifier + settings
+                       split.set_context_pointer("modifier", md)
+                       split.itemO("object.modifier_remove", text="Remove")
+
+                       row = split.row(align=True)
+                       row.itemR(md, "render", text="")
+                       row.itemR(md, "realtime", text="")
+               else:
+                       # add modifier
+                       split.item_enumO("object.modifier_add", "type", 'CLOTH', text="Add")
+                       split.itemL()
+
+               if md:
+                       cloth = md.settings
+                       
+                       layout.active = cloth_panel_enabled(md)
+
+                       split = layout.split()
+                       
+                       col = split.column()
+                       col.itemL(text="Quality:")
+                       col.itemR(cloth, "quality", text="Steps",slider=True)
+                       col.itemL(text="Gravity:")
+                       col.itemR(cloth, "gravity", text="")
+
+                       col.itemR(cloth, "pin_cloth", text="Pin")
+                       sub = col.column(align=True)
+                       sub.active = cloth.pin_cloth
+                       sub.itemR(cloth, "pin_stiffness", text="Stiffness")
+                       sub.item_pointerR(cloth, "mass_vertex_group", ob, "vertex_groups", text="")
+                       
+                       col = split.column()
+                       col.itemL(text="Presets...")
+                       col.itemL(text="TODO!")
+                       col.itemL(text="Material:")
+                       sub = col.column(align=True)
+                       sub.itemR(cloth, "mass")
+                       sub.itemR(cloth, "structural_stiffness", text="Structural")
+                       sub.itemR(cloth, "bending_stiffness", text="Bending")
+                       col.itemL(text="Damping:")
+                       sub = col.column(align=True)
+                       sub.itemR(cloth, "spring_damping", text="Spring")
+                       sub.itemR(cloth, "air_damping", text="Air")
+                       
+                       # Disabled for now
+                       """
+                       if cloth.mass_vertex_group:
+                               layout.itemL(text="Goal:")
+                       
+                               col = layout.column_flow()
+                               col.itemR(cloth, "goal_default", text="Default")
+                               col.itemR(cloth, "goal_spring", text="Stiffness")
+                               col.itemR(cloth, "goal_friction", text="Friction")
+                       """
+
+class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
+       __label__ = "Cloth Cache"
+       __default_closed__ = True
+
+       def poll(self, context):
+               return (context.cloth)
+
+       def draw(self, context):
+               md = context.cloth
+               point_cache_ui(self, md.point_cache, cloth_panel_enabled(md), 0, 0)
+               
+class PHYSICS_PT_cloth_collision(PhysicButtonsPanel):
+       __label__ = "Cloth Collision"
+       __default_closed__ = True
+
+       def poll(self, context):
+               return (context.cloth)
+       
+       def draw_header(self, context):
+               cloth = context.cloth.collision_settings
+               
+               self.layout.active = cloth_panel_enabled(context.cloth)
+               self.layout.itemR(cloth, "enable_collision", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               cloth = context.cloth.collision_settings
+               md = context.cloth
+               
+               layout.active = cloth.enable_collision and cloth_panel_enabled(md)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(cloth, "collision_quality", slider=True, text="Quality")
+               col.itemR(cloth, "min_distance", slider=True, text="Distance")
+               col.itemR(cloth, "friction")
+               
+               col = split.column()
+               col.itemR(cloth, "enable_self_collision", text="Self Collision")
+               sub = col.column()
+               sub.active = cloth.enable_self_collision
+               sub.itemR(cloth, "self_collision_quality", slider=True, text="Quality")
+               sub.itemR(cloth, "self_min_distance", slider=True, text="Distance")
+
+class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel):
+       __label__ = "Cloth Stiffness Scaling"
+       __default_closed__ = True
+
+       def poll(self, context):
+               return (context.cloth != None)
+       
+       def draw_header(self, context):
+               cloth = context.cloth.settings
+       
+               self.layout.active = cloth_panel_enabled(context.cloth)
+               self.layout.itemR(cloth, "stiffness_scaling", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               md = context.cloth
+               ob = context.object
+               cloth = context.cloth.settings
+               
+               layout.active = cloth.stiffness_scaling and cloth_panel_enabled(md)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemL(text="Structural Stiffness:")
+               sub = col.column(align=True)
+               sub.itemR(cloth, "structural_stiffness_max", text="Max")
+               sub.item_pointerR(cloth, "structural_stiffness_vertex_group", ob, "vertex_groups", text="")
+               
+               col = split.column()
+               col.itemL(text="Bending Stiffness:")
+               sub = col.column(align=True)
+               sub.itemR(cloth, "bending_stiffness_max", text="Max")
+               sub.item_pointerR(cloth, "bending_vertex_group", ob, "vertex_groups", text="")
+               
+bpy.types.register(PHYSICS_PT_cloth)
+bpy.types.register(PHYSICS_PT_cloth_cache)
+bpy.types.register(PHYSICS_PT_cloth_collision)
+bpy.types.register(PHYSICS_PT_cloth_stiffness)
diff --git a/release/ui/buttons_physics_field.py b/release/ui/buttons_physics_field.py
new file mode 100644 (file)
index 0000000..58033d2
--- /dev/null
@@ -0,0 +1,230 @@
+
+import bpy
+
+class PhysicButtonsPanel(bpy.types.Panel):
+       __space_type__ = 'PROPERTIES'
+       __region_type__ = 'WINDOW'
+       __context__ = "physics"
+
+       def poll(self, context):
+               rd = context.scene.render_data
+               return (context.object) and (not rd.use_game_engine)
+               
+class PHYSICS_PT_field(PhysicButtonsPanel):
+       __label__ = "Force Fields"
+       __default_closed__ = True
+
+       def draw(self, context):
+               layout = self.layout
+               
+               ob = context.object
+               field = ob.field
+
+               #layout.active = field.enabled
+               
+               split = layout.split(percentage=0.2)
+               
+               split.itemL(text="Type:")
+               split.itemR(field, "type",text="")
+                       
+               split = layout.split()
+               
+               if field.type == 'GUIDE':
+                       layout.itemR(field, "guide_path_add")
+                       
+               elif field.type == 'WIND':
+                       split.itemR(field, "strength")
+                       
+                       col = split.column()
+                       col.itemR(field, "noise")
+                       col.itemR(field, "seed")
+
+               elif field.type == 'VORTEX':
+                       split.itemR(field, "strength")
+                       split.itemL()
+                       
+               elif field.type in ('SPHERICAL', 'CHARGE', 'LENNARDJ'):
+                       split.itemR(field, "strength")
+                       
+                       col = split.column()
+                       col.itemR(field, "planar")
+                       col.itemR(field, "surface")
+                       
+               elif field.type == 'BOID':
+                       split.itemR(field, "strength")
+                       split.itemR(field, "surface")
+                       
+               elif field.type == 'MAGNET':
+                       split.itemR(field, "strength")
+                       split.itemR(field, "planar")
+                       
+               elif field.type == 'HARMONIC':
+                       col = split.column()
+                       col.itemR(field, "strength")
+                       col.itemR(field, "harmonic_damping", text="Damping")
+                       
+                       col = split.column()
+                       col.itemR(field, "planar")
+                       col.itemR(field, "surface")
+                       
+               elif field.type == 'TEXTURE':
+                       col = split.column()
+                       col.itemR(field, "strength")
+                       col.itemR(field, "texture", text="")
+                       col.itemR(field, "texture_mode", text="")
+                       col.itemR(field, "texture_nabla")
+                       
+                       col = split.column()
+                       col.itemR(field, "use_coordinates")
+                       col.itemR(field, "root_coordinates")
+                       col.itemR(field, "force_2d")
+                       
+               if field.type in ('HARMONIC', 'SPHERICAL', 'CHARGE', 'WIND', 'VORTEX', 'TEXTURE', 'MAGNET', 'BOID'):
+                       
+                       layout.itemL(text="Falloff:")
+                       layout.itemR(field, "falloff_type", expand=True)
+
+                       split = layout.split(percentage=0.35)
+                       
+                       col = split.column()
+                       col.itemR(field, "positive_z", text="Positive Z")
+                       col.itemR(field, "use_min_distance", text="Use Minimum")
+                       col.itemR(field, "use_max_distance", text="Use Maximum")
+
+                       col = split.column()
+                       col.itemR(field, "falloff_power", text="Power")
+                       
+                       sub = col.column()
+                       sub.active = field.use_min_distance
+                       sub.itemR(field, "minimum_distance", text="Distance")
+                       
+                       sub = col.column()
+                       sub.active = field.use_max_distance
+                       sub.itemR(field, "maximum_distance", text="Distance")
+                       
+                       if field.falloff_type == 'CONE':
+                               
+                               layout.itemS()
+                               
+                               split = layout.split(percentage=0.35)
+                               
+                               col = split.column()
+                               col.itemL(text="Angular:")
+                               col.itemR(field, "use_radial_min", text="Use Minimum")  
+                               col.itemR(field, "use_radial_max", text="Use Maximum")
+                               
+                               col = split.column()
+                               col.itemR(field, "radial_falloff", text="Power")
+                               
+                               sub = col.column()
+                               sub.active = field.use_radial_min
+                               sub.itemR(field, "radial_minimum", text="Angle")
+                               
+                               sub = col.column()
+                               sub.active = field.use_radial_max
+                               sub.itemR(field, "radial_maximum", text="Angle")
+                               
+                       elif field.falloff_type == 'TUBE':
+                               
+         &n