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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Letwory <nathan@letworyinteractive.com>2010-09-11 14:12:56 +0400
committerNathan Letwory <nathan@letworyinteractive.com>2010-09-11 14:12:56 +0400
commit75385297521cf6a195dede60793583b70bcb1ac7 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904
parent99b820b75a0312102ccae285c1cd85fdaf8753e7 (diff)
Remove for retag
[[Split portion of a mixed commit.]]
-rw-r--r--add_curve_aceous_galore.py1120
-rw-r--r--add_curve_torus_knots.py320
-rw-r--r--add_mesh_3d_function_surface.py636
-rw-r--r--add_mesh_BoltFactory/Boltfactory.py306
-rw-r--r--add_mesh_BoltFactory/__init__.py59
-rw-r--r--add_mesh_BoltFactory/createMesh.py2111
-rw-r--r--add_mesh_BoltFactory/preset_utils.py53
-rw-r--r--add_mesh_BoltFactory/presets/M10.py22
-rw-r--r--add_mesh_BoltFactory/presets/M12.py22
-rw-r--r--add_mesh_BoltFactory/presets/M3.py22
-rw-r--r--add_mesh_BoltFactory/presets/M4.py22
-rw-r--r--add_mesh_BoltFactory/presets/M5.py22
-rw-r--r--add_mesh_BoltFactory/presets/M6.py22
-rw-r--r--add_mesh_BoltFactory/presets/M8.py22
-rw-r--r--add_mesh_ant_landscape.py913
-rw-r--r--add_mesh_extras.py776
-rw-r--r--add_mesh_gears.py937
-rw-r--r--add_mesh_gemstones.py472
-rw-r--r--add_mesh_pipe_joint.py1306
-rw-r--r--add_mesh_solid.py902
-rw-r--r--add_mesh_twisted_torus.py363
-rw-r--r--curve_simplify.py597
-rw-r--r--io_anim_camera.py164
-rw-r--r--io_export_directx_x.py1154
-rw-r--r--io_export_unreal_psk_psa.py1593
-rw-r--r--io_import_images_as_planes.py525
-rw-r--r--io_import_scene_lwo.py1247
-rw-r--r--io_import_scene_mhx.py2245
-rw-r--r--io_import_scene_unreal_psk.py602
-rw-r--r--io_mesh_raw/__init__.py69
-rw-r--r--io_mesh_raw/export_raw.py112
-rw-r--r--io_mesh_raw/import_raw.py143
-rw-r--r--io_mesh_stl/__init__.py163
-rw-r--r--io_mesh_stl/blender_utils.py53
-rw-r--r--io_mesh_stl/stl_utils.py228
-rw-r--r--mesh_relax.py128
-rw-r--r--mesh_surface_sketch.py819
-rw-r--r--object_add_chain.py150
-rw-r--r--object_cloud_gen.py674
-rw-r--r--object_fracture/__init__.py80
-rw-r--r--object_fracture/data.blendbin232271 -> 0 bytes
-rw-r--r--object_fracture/fracture_ops.py490
-rw-r--r--object_fracture/fracture_setup.py74
-rw-r--r--render_povray/__init__.py131
-rw-r--r--render_povray/render.py790
-rw-r--r--render_povray/ui.py136
-rw-r--r--render_renderfarmfi.py820
-rw-r--r--space_view3d_align_tools.py338
-rw-r--r--space_view3d_materials_utils.py689
-rw-r--r--space_view3d_panel_measure.py1065
-rw-r--r--space_view3d_property_chart.py230
-rw-r--r--space_view3d_spacebar_menu.py1471
-rw-r--r--system_blend_info.py207
53 files changed, 0 insertions, 27615 deletions
diff --git a/add_curve_aceous_galore.py b/add_curve_aceous_galore.py
deleted file mode 100644
index 9de8c015..00000000
--- a/add_curve_aceous_galore.py
+++ /dev/null
@@ -1,1120 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- 'name': 'Curveaceous Galore!',
- 'author': 'Jimmy Hazevoet, testscreenings',
- 'version': (0,1),
- 'blender': (2, 5, 3),
- 'api': 31667,
- 'location': 'Add Curve menu',
- 'description': 'adds many types of curves',
- 'warning': '', # used for warning icon and text in addons panel
- 'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
- 'Scripts/Curve/Curves_Galore',
- 'tracker_url': 'https://projects.blender.org/tracker/index.php?'\
- 'func=detail&aid=22404&group_id=153&atid=469',
- 'category': 'Add Curve'}
-
-
-##------------------------------------------------------------
-#### import modules
-import bpy
-from bpy.props import *
-from mathutils import *
-from math import *
-###------------------------------------------------------------
-#### Some functions to use with others:
-###------------------------------------------------------------
-'''
-#------------------------------------------------------------
-# Generate random number:
-def randnum( low=0.0, high=1.0, seed=0 ):
- """
- randnum( low=0.0, high=1.0, seed=0 )
-
- Create random number
-
- Parameters:
- low - lower range
- (type=float)
- high - higher range
- (type=float)
- seed - the random seed number, if seed is 0, the current time will be used instead
- (type=int)
- Returns:
- a random number
- (type=float)
- """
-
- s = Noise.setRandomSeed( seed )
- rnum = Noise.random()
- rnum = rnum*(high-low)
- rnum = rnum+low
- return rnum
-
-
-
-#------------------------------------------------------------
-# Make some noise:
-def vTurbNoise((x,y,z), iScale=0.25, Size=1.0, Depth=6, Hard=0, Basis=0, Seed=0 ):
- """
- vTurbNoise((x,y,z), iScale=0.25, Size=1.0, Depth=6, Hard=0, Basis=0, Seed=0 )
-
- Create randomised vTurbulence noise
-
- Parameters:
- xyz - (x,y,z) float values.
- (type=3-float tuple)
- iScale - noise intensity scale
- (type=float)
- Size - noise size
- (type=float)
- Depth - number of noise values added.
- (type=int)
- Hard - noise hardness: 0 - soft noise; 1 - hard noise
- (type=int)
- basis - type of noise used for turbulence
- (type=int)
- Seed - the random seed number, if seed is 0, the current time will be used instead
- (type=int)
- Returns:
- the generated turbulence vector.
- (type=3-float list)
- """
-
- rand = randnum(-100,100,Seed)
- if Basis ==9: Basis = 14
- vTurb = Noise.vTurbulence(( x/Size+rand, y/Size+rand, z/Size+rand ), Depth, Hard, Basis )
- tx = vTurb[0]*iScale
- ty = vTurb[1]*iScale
- tz = vTurb[2]*iScale
- return tx,ty,tz
-
-
-
-#------------------------------------------------------------
-# Axis: ( used in 3DCurve Turbulence )
-def AxisFlip((x,y,z), x_axis=1, y_axis=1, z_axis=1, flip=0 ):
- if flip != 0:
- flip *= -1
- else: flip = 1
- x *= x_axis*flip
- y *= y_axis*flip
- z *= z_axis*flip
- return x,y,z
-'''
-
-###-------------------------------------------------------------------
-#### 2D Curve shape functions:
-###-------------------------------------------------------------------
-
-##------------------------------------------------------------
-# 2DCurve: Profile: L, H, T, U, Z
-def ProfileCurve(type=0, a=0.25, b=0.25):
- """
- ProfileCurve( type=0, a=0.25, b=0.25 )
-
- Create profile curve
-
- Parameters:
- type - select profile type, L, H, T, U, Z
- (type=int)
- a - a scaling parameter
- (type=float)
- b - b scaling parameter
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- if type ==1:
- ## H:
- a*=0.5
- b*=0.5
- newpoints = [ [ -1.0, 1.0, 0.0 ], [ -1.0+a, 1.0, 0.0 ],
- [ -1.0+a, b, 0.0 ], [ 1.0-a, b, 0.0 ], [ 1.0-a, 1.0, 0.0 ],
- [ 1.0, 1.0, 0.0 ], [ 1.0, -1.0, 0.0 ], [ 1.0-a, -1.0, 0.0 ],
- [ 1.0-a, -b, 0.0 ], [ -1.0+a, -b, 0.0 ], [ -1.0+a, -1.0, 0.0 ],
- [ -1.0, -1.0, 0.0 ] ]
- elif type ==2:
- ## T:
- a*=0.5
- newpoints = [ [ -1.0, 1.0, 0.0 ], [ 1.0, 1.0, 0.0 ],
- [ 1.0, 1.0-b, 0.0 ], [ a, 1.0-b, 0.0 ], [ a, -1.0, 0.0 ],
- [ -a, -1.0, 0.0 ], [ -a, 1.0-b, 0.0 ], [ -1.0, 1.0-b, 0.0 ] ]
- elif type ==3:
- ## U:
- a*=0.5
- newpoints = [ [ -1.0, 1.0, 0.0 ], [ -1.0+a, 1.0, 0.0 ],
- [ -1.0+a, -1.0+b, 0.0 ], [ 1.0-a, -1.0+b, 0.0 ], [ 1.0-a, 1.0, 0.0 ],
- [ 1.0, 1.0, 0.0 ], [ 1.0, -1.0, 0.0 ], [ -1.0, -1.0, 0.0 ] ]
- elif type ==4:
- ## Z:
- a*=0.5
- newpoints = [ [ -0.5, 1.0, 0.0 ], [ a, 1.0, 0.0 ],
- [ a, -1.0+b, 0.0 ], [ 1.0, -1.0+b, 0.0 ], [ 1.0, -1.0, 0.0 ],
- [ -a, -1.0, 0.0 ], [ -a, 1.0-b, 0.0 ], [ -1.0, 1.0-b, 0.0 ],
- [ -1.0, 1.0, 0.0 ] ]
- else:
- ## L:
- newpoints = [ [ -1.0, 1.0, 0.0 ], [ -1.0+a, 1.0, 0.0 ],
- [ -1.0+a, -1.0+b, 0.0 ], [ 1.0, -1.0+b, 0.0 ],
- [ 1.0, -1.0, 0.0 ], [ -1.0, -1.0, 0.0 ] ]
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: Miscellaneous.: Diamond, Arrow1, Arrow2, Square, ....
-def MiscCurve(type=1, a=1.0, b=0.5, c=90.0):
- """
- MiscCurve( type=1, a=1.0, b=0.5, c=90.0 )
-
- Create miscellaneous curves
-
- Parameters:
- type - select type, Diamond, Arrow1, Arrow2, Square
- (type=int)
- a - a scaling parameter
- (type=float)
- b - b scaling parameter
- (type=float)
- c - c scaling parameter
- (type=float)
- doesn't seem to do anything
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- a*=0.5
- b*=0.5
- if type ==1:
- ## diamond:
- newpoints = [ [ 0.0, b, 0.0 ], [ a, 0.0, 0.0 ], [ 0.0, -b, 0.0 ], [ -a, 0.0, 0.0 ] ]
- elif type ==2:
- ## Arrow1:
- newpoints = [ [ -a, b, 0.0 ], [ a, 0.0, 0.0 ], [ -a, -b, 0.0 ], [ 0.0, 0.0, 0.0 ] ]
- elif type ==3:
- ## Arrow2:
- newpoints = [ [ -1.0, b, 0.0 ], [ -1.0+a, b, 0.0 ],
- [ -1.0+a, 1.0, 0.0 ], [ 1.0, 0.0, 0.0 ],
- [ -1.0+a, -1.0, 0.0 ], [ -1.0+a, -b, 0.0 ],
- [ -1.0, -b, 0.0 ] ]
- elif type ==4:
- ## Rounded square:
- newpoints = [ [ -a, b-b*0.2, 0.0 ], [ -a+a*0.05, b-b*0.05, 0.0 ], [ -a+a*0.2, b, 0.0 ],
- [ a-a*0.2, b, 0.0 ], [ a-a*0.05, b-b*0.05, 0.0 ], [ a, b-b*0.2, 0.0 ],
- [ a, -b+b*0.2, 0.0 ], [ a-a*0.05, -b+b*0.05, 0.0 ], [ a-a*0.2, -b, 0.0 ],
- [ -a+a*0.2, -b, 0.0 ], [ -a+a*0.05, -b+b*0.05, 0.0 ], [ -a, -b+b*0.2, 0.0 ] ]
-
- #elif type ==15:
- ## :
- #newpoints = [ [ x,y,z ] ]
- else:
- ## Square:
- newpoints = [ [ -a, b, 0.0 ], [ a, b, 0.0 ], [ a, -b, 0.0 ], [ -a, -b, 0.0 ] ]
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: Star:
-def StarCurve(starpoints=8, innerradius=0.5, outerradius=1.0, twist=0.0):
- """
- StarCurve( starpoints=8, innerradius=0.5, outerradius=1.0, twist=0.0 )
-
- Create star shaped curve
-
- Parameters:
- starpoints - the number of points
- (type=int)
- innerradius - innerradius
- (type=float)
- outerradius - outerradius
- (type=float)
- twist - twist amount
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- step = (2.0/(starpoints))
- i = 0
- while i < starpoints:
- t = (i*step)
- x1 = cos(t*pi)*outerradius
- y1 = sin(t*pi)*outerradius
- newpoints.append([x1,y1,0])
- x2 = cos(t*pi+(pi/starpoints+twist))*innerradius
- y2 = sin(t*pi+(pi/starpoints+twist))*innerradius
- newpoints.append([x2,y2,0])
- i+=1
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: Flower:
-def FlowerCurve(petals=8, innerradius=0.5, outerradius=1.0, petalwidth=2.0):
- """
- FlowerCurve( petals=8, innerradius=0.5, outerradius=1.0, petalwidth=2.0 )
-
- Create flower shaped curve
-
- Parameters:
- petals - the number of petals
- (type=int)
- innerradius - innerradius
- (type=float)
- outerradius - outerradius
- (type=float)
- petalwidth - width of petals
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- step = (2.0/(petals))
- pet = (step/pi*2)*petalwidth
- i = 0
- while i < petals:
- t = (i*step)
- x1 = cos(t*pi-(pi/petals))*innerradius
- y1 = sin(t*pi-(pi/petals))*innerradius
- newpoints.append([x1,y1,0])
- x2 = cos(t*pi-pet)*outerradius
- y2 = sin(t*pi-pet)*outerradius
- newpoints.append([x2,y2,0])
- x3 = cos(t*pi+pet)*outerradius
- y3 = sin(t*pi+pet)*outerradius
- newpoints.append([x3,y3,0])
- i+=1
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: Arc,Sector,Segment,Ring:
-def ArcCurve(sides=6, startangle=0.0, endangle=90.0, innerradius=0.5, outerradius=1.0, type=3):
- """
- ArcCurve( sides=6, startangle=0.0, endangle=90.0, innerradius=0.5, outerradius=1.0, type=3 )
-
- Create arc shaped curve
-
- Parameters:
- sides - number of sides
- (type=int)
- startangle - startangle
- (type=float)
- endangle - endangle
- (type=float)
- innerradius - innerradius
- (type=float)
- outerradius - outerradius
- (type=float)
- type - select type Arc,Sector,Segment,Ring
- (type=int)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- sides += 1
- angle = (2.0*(1.0/360.0))
- endangle-=startangle
- step = ((angle*endangle)/(sides-1))
- i = 0
- while i < sides:
- t = (i*step) + angle*startangle
- x1 = sin(t*pi)*outerradius
- y1 = cos(t*pi)*outerradius
- newpoints.append([x1,y1,0])
- i+=1
-
- #if type ==0:
- # Arc: turn cyclic curve flag off!
-
- # Segment:
- if type ==2:
- newpoints.append([0,0,0])
- # Ring:
- elif type ==3:
- j=sides-1
- while j > -1:
- t = (j*step) + angle*startangle
- x2 = sin(t*pi)*innerradius
- y2 = cos(t*pi)*innerradius
- newpoints.append([x2,y2,0])
- j-=1
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: Cog wheel:
-def CogCurve(theeth=8, innerradius=0.8, middleradius=0.95, outerradius=1.0, bevel=0.5):
- """
- CogCurve( theeth=8, innerradius=0.8, middleradius=0.95, outerradius=1.0, bevel=0.5 )
-
- Create cog wheel shaped curve
-
- Parameters:
- theeth - number of theeth
- (type=int)
- innerradius - innerradius
- (type=float)
- middleradius - middleradius
- (type=float)
- outerradius - outerradius
- (type=float)
- bevel - bevel amount
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- step = (2.0/(theeth))
- pet = (step/pi*2)
- bevel = 1.0-bevel
- i = 0
- while i < theeth:
- t = (i*step)
- x1 = cos(t*pi-(pi/theeth)-pet)*innerradius
- y1 = sin(t*pi-(pi/theeth)-pet)*innerradius
- newpoints.append([x1,y1,0])
- x2 = cos(t*pi-(pi/theeth)+pet)*innerradius
- y2 = sin(t*pi-(pi/theeth)+pet)*innerradius
- newpoints.append([x2,y2,0])
- x3 = cos(t*pi-pet)*middleradius
- y3 = sin(t*pi-pet)*middleradius
- newpoints.append([x3,y3,0])
- x4 = cos(t*pi-(pet*bevel))*outerradius
- y4 = sin(t*pi-(pet*bevel))*outerradius
- newpoints.append([x4,y4,0])
- x5 = cos(t*pi+(pet*bevel))*outerradius
- y5 = sin(t*pi+(pet*bevel))*outerradius
- newpoints.append([x5,y5,0])
- x6 = cos(t*pi+pet)*middleradius
- y6 = sin(t*pi+pet)*middleradius
- newpoints.append([x6,y6,0])
- i+=1
- return newpoints
-
-##------------------------------------------------------------
-# 2DCurve: nSide:
-def nSideCurve(sides=6, radius=1.0):
- """
- nSideCurve( sides=6, radius=1.0 )
-
- Create n-sided curve
-
- Parameters:
- sides - number of sides
- (type=int)
- radius - radius
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- step = (2.0/(sides))
- i = 0
- while i < sides:
- t = (i*step)
- x = sin(t*pi)*radius
- y = cos(t*pi)*radius
- newpoints.append([x,y,0])
- i+=1
- return newpoints
-
-'''
-##------------------------------------------------------------
-# 2DCurve: Splat:
-def SplatCurve(sides=24, scale=1.0, seed=0, basis=0, radius=1.0):
- """
- SplatCurve( sides=24, scale=1.0, seed=0, basis=0, radius=1.0 )
-
- Create splat curve
-
- Parameters:
- sides - number of sides
- (type=int)
- scale - noise size
- (type=float)
- seed - noise random seed
- (type=int)
- basis - noise basis
- (type=int)
- radius - radius
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- step = (2.0/(sides))
- i = 0
- while i < sides:
- t = (i*step)
- turb = vTurbNoise(t, 1.0, scale, 6, 0, basis, seed )
- turb = turb[2] * 0.5 + 0.5
- x = sin(t*pi)*radius * turb
- y = cos(t*pi)*radius * turb
- newpoints.append([x,y,0])
- i+=1
- return newpoints
-'''
-###-----------------------------------------------------------
-#### 3D curve shape functions:
-###-----------------------------------------------------------
-
-###------------------------------------------------------------
-# 3DCurve: Helix:
-def HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 ):
- """
- HelixCurve( number=100, height=2.0, startangle=0.0, endangle=360.0, width=1.0, a=0.0, b=0.0 )
-
- Create helix curve
-
- Parameters:
- number - the number of points
- (type=int)
- height - height
- (type=float)
- startangle - startangle
- (type=float)
- endangle - endangle
- (type=float)
- width - width
- (type=float)
- a - a
- (type=float)
- b - b
- (type=float)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- angle = (2.0/360.0)*(endangle-startangle)
- step = angle/(number-1)
- h = height/angle
- start = (startangle*2.0/360.0)
- a/=angle
- i = 0
- while i < number:
- t = ( i*step+start )
- x = sin( (t*pi) ) * ( 1.0 + cos( t * pi * a - ( b * pi ) ) ) * ( 0.25 * width )
- y = cos( (t*pi) ) * ( 1.0 + cos( t * pi * a - ( b * pi ) ) ) * ( 0.25 * width )
- z = ( t * h ) -h*start
- newpoints.append([x,y,z])
- i+=1
- return newpoints
-
-###------------------------------------------------------------ ?
-# 3DCurve: Cycloid: Cycloid, Epicycloid, Hypocycloid
-def CycloidCurve( number=24, length=2.0, type=0, a=1.0, b=1.0, startangle=0.0, endangle=360.0 ):
- """
- CycloidCurve( number=24, length=2.0, type=0, a=1.0, b=1.0, startangle=0.0, endangle=360.0 )
-
- Create a Cycloid, Epicycloid or Hypocycloid curve
-
- Parameters:
- number - the number of points
- (type=int)
- length - length of curve
- (type=float)
- type - types: Cycloid, Epicycloid, Hypocycloid
- (type=int)
- Returns:
- a list with lists of x,y,z coordinates for curve points, [[x,y,z],[x,y,z],...n]
- (type=list)
- """
-
- newpoints = []
- angle = (2.0/360.0)*(endangle-startangle)
- step = angle/(number-1)
- #h = height/angle
- d = length
- start = (startangle*2.0/360.0)
- a/=angle
- i = 0
- if type == 0: # Epitrochoid
- while i < number:
- t = ( i*step+start )
- x = ((a + b) * cos(t*pi)) - (d * cos(((a+b)/b)*t*pi))
- y = ((a + b) * sin(t*pi)) - (d * sin(((a+b)/b)*t*pi))
- z = 0 # ( t * h ) -h*start
- newpoints.append([x,y,z])
- i+=1
-
- else:
- newpoints = [[-1,-1,0], [-1,1,0], [1,1,0], [1,-1,0]]
- return newpoints
-
-##------------------------------------------------------------
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-##------------------------------------------------------------
-#### Curve creation functions
-# sets bezierhandles to auto
-def setBezierHandles(obj, mode = 'AUTOMATIC'):
- scene = bpy.context.scene
- if obj.type != 'CURVE':
- return
- scene.objects.active = obj
- bpy.ops.object.mode_set(mode='EDIT', toggle=True)
- bpy.ops.curve.select_all(action='SELECT')
- bpy.ops.curve.handle_type_set(type=mode)
- bpy.ops.object.mode_set(mode='OBJECT', toggle=True)
-
-# get array of vertcoordinates acording to splinetype
-def vertsToPoints(Verts, splineType):
- # main vars
- vertArray = []
-
- # array for BEZIER spline output (V3)
- if splineType == 'BEZIER':
- for v in Verts:
- vertArray += v
-
- # array for nonBEZIER output (V4)
- else:
- for v in Verts:
- vertArray += v
- if splineType == 'NURBS':
- vertArray.append(1) #for nurbs w=1
- else: #for poly w=0
- vertArray.append(0)
- return vertArray
-
-# create new CurveObject from vertarray and splineType
-def createCurve(vertArray, props, align_matrix):
- # options to vars
- splineType = props.outputType # output splineType 'POLY' 'NURBS' 'BEZIER'
- name = props.GalloreType # GalloreType as name
-
- # create curve
- scene = bpy.context.scene
- newCurve = bpy.data.curves.new(name, type = 'CURVE') # curvedatablock
- newSpline = newCurve.splines.new(type = splineType) # spline
-
- # create spline from vertarray
- if splineType == 'BEZIER':
- newSpline.bezier_points.add(int(len(vertArray)*0.33))
- newSpline.bezier_points.foreach_set('co', vertArray)
- else:
- newSpline.points.add(int(len(vertArray)*0.25 - 1))
- newSpline.points.foreach_set('co', vertArray)
- newSpline.use_endpoint_u = True
-
- # set curveOptions
- newCurve.dimensions = props.shape
- newSpline.use_cyclic_u = props.use_cyclic_u
- newSpline.use_endpoint_u = props.endp_u
- newSpline.order_u = props.order_u
-
- # create object with newCurve
- new_obj = bpy.data.objects.new(name, newCurve) # object
- scene.objects.link(new_obj) # place in active scene
- new_obj.select = True # set as selected
- scene.objects.active = new_obj # set as active
- new_obj.matrix_world = align_matrix # apply matrix
-
- # set bezierhandles
- if splineType == 'BEZIER':
- setBezierHandles(new_obj, props.handleType)
-
- return
-
-##------------------------------------------------------------
-# Main Function
-def main(context, props, align_matrix):
- # deselect all objects
- bpy.ops.object.select_all(action='DESELECT')
-
- # options
- galType = props.GalloreType
- splineType = props.outputType
- innerRadius = props.innerRadius
- middleRadius = props.middleRadius
- outerRadius = props.outerRadius
-
- # get verts
- if galType == 'Profile':
- verts = ProfileCurve(props.ProfileCurveType,
- props.ProfileCurvevar1,
- props.ProfileCurvevar2)
- if galType == 'Miscellaneous':
- verts = MiscCurve(props.MiscCurveType,
- props.MiscCurvevar1,
- props.MiscCurvevar2,
- props.MiscCurvevar3)
- if galType == 'Flower':
- verts = FlowerCurve(props.petals,
- innerRadius,
- outerRadius,
- props.petalWidth)
- if galType == 'Star':
- verts = StarCurve(props.starPoints,
- innerRadius,
- outerRadius,
- props.starTwist)
- if galType == 'Arc':
- verts = ArcCurve(props.arcSides,
- props.startAngle,
- props.endAngle,
- innerRadius,
- outerRadius,
- props.arcType)
- if galType == 'Cogwheel':
- verts = CogCurve(props.teeth,
- innerRadius,
- middleRadius,
- outerRadius,
- props.bevel)
- if galType == 'Nsided':
- verts = nSideCurve(props.Nsides,
- outerRadius)
- '''
- if galType == 'Splat':
- verts = SplatCurve(props.splatSides,
- props.splatScale,
- props.seed,
- props.basis,
- outerRadius)
- '''
- if galType == 'Helix':
- verts = HelixCurve(props.helixPoints,
- props.helixHeight,
- props.helixStart,
- props.helixEnd,
- props.helixWidth,
- props.helix_a,
- props.helix_b)
- if galType == 'Cycloid':
- verts = CycloidCurve(props.cycloPoints,
- props.cyclo_d,
- props.cycloType,
- props.cyclo_a,
- props.cyclo_b,
- props.cycloStart,
- props.cycloEnd)
-
- # turn verts into array
- vertArray = vertsToPoints(verts, splineType)
-
- # create object
- createCurve(vertArray, props, align_matrix)
-
- return
-
-class Curveaceous_galore(bpy.types.Operator):
- ''''''
- bl_idname = "curveaceous_galore"
- bl_label = "Curveaceous galore"
- bl_options = {'REGISTER', 'UNDO'}
- bl_description = "adds many types of curves"
-
- # align_matrix for the invoke
- align_matrix = Matrix()
-
- #### general properties
- GalloreTypes = [
- ('Profile', 'Profile', 'Profile'),
- ('Miscellaneous', 'Miscellaneous', 'Miscellaneous'),
- ('Flower', 'Flower', 'Flower'),
- ('Star', 'Star', 'Star'),
- ('Arc', 'Arc', 'Arc'),
- ('Cogwheel', 'Cogwheel', 'Cogwheel'),
- ('Nsided', 'Nsided', 'Nsided'),
-# ('Splat', 'Splat', 'Splat'),
- ('Cycloid', 'Cycloid', 'Cycloid'),
- ('Helix', 'Helix (3D)', 'Helix')]
- GalloreType = EnumProperty(name="Type",
- description="Form of Curve to create",
- items=GalloreTypes)
- SplineTypes = [
- ('POLY', 'Poly', 'POLY'),
- ('NURBS', 'Nurbs', 'NURBS'),
- ('BEZIER', 'Bezier', 'BEZIER')]
- outputType = EnumProperty(name="Output splines",
- description="Type of splines to output",
- items=SplineTypes)
-
- #### Curve Options
- shapeItems = [
- ('2D', '2D', '2D'),
- ('3D', '3D', '3D')]
- shape = EnumProperty(name="2D / 3D",
- items=shapeItems,
- description="2D or 3D Curve")
- use_cyclic_u = BoolProperty(name="Cyclic",
- default=True,
- description="make curve closed")
- endp_u = BoolProperty(name="use_endpoint_u",
- default=True,
- description="stretch to endpoints")
- order_u = IntProperty(name="order_u",
- default=4,
- min=2, soft_min=2,
- max=6, soft_max=6,
- description="Order of nurbs spline")
- bezHandles = [
- ('VECTOR', 'Vector', 'VECTOR'),
- ('AUTOMATIC', 'Auto', 'AUTOMATIC')]
- handleType = EnumProperty(name="Handle type",
- description="bezier handles type",
- items=bezHandles)
-
- #### ProfileCurve properties
- ProfileCurveType = IntProperty(name="Type",
- min=1, soft_min=1,
- max=5, soft_max=5,
- default=1,
- description="Type of ProfileCurve")
- ProfileCurvevar1 = FloatProperty(name="var_1",
- default=0.25,
- description="var1 of ProfileCurve")
- ProfileCurvevar2 = FloatProperty(name="var_2",
- default=0.25,
- description="var2 of ProfileCurve")
-
- #### MiscCurve properties
- MiscCurveType = IntProperty(name="Type",
- min=1, soft_min=1,
- max=5, soft_max=5,
- default=1,
- description="Type of ProfileCurve")
- MiscCurvevar1 = FloatProperty(name="var_1",
- default=1.0,
- description="var1 of ProfileCurve")
- MiscCurvevar2 = FloatProperty(name="var_2",
- default=0.5,
- description="var2 of ProfileCurve")
- MiscCurvevar3 = FloatProperty(name="var_3", # doesn't seem to do anything
- default=90.0,
- description="var3 of ProfileCurve")
-
- #### Common properties
- innerRadius = FloatProperty(name="Inner radius",
- default=0.5,
- min=0, soft_min=0,
- description="Inner radius")
- middleRadius = FloatProperty(name="Middle radius",
- default=0.95,
- min=0, soft_min=0,
- description="Middle radius")
- outerRadius = FloatProperty(name="Outer radius",
- default=1.0,
- min=0, soft_min=0,
- description="Outer radius")
-
- #### Flower properties
- petals = IntProperty(name="Petals",
- default=8,
- min=2, soft_min=2,
- description="Number of petals")
- petalWidth = FloatProperty(name="Petal width",
- default=2.0,
- min=0.01, soft_min=0.01,
- description="Petal width")
-
- #### Star properties
- starPoints = IntProperty(name="Star points",
- default=8,
- min=2, soft_min=2,
- description="Number of star points")
- starTwist = FloatProperty(name="Twist",
- default=0.0,
- description="Twist")
-
- #### Arc properties
- arcSides = IntProperty(name="Arc sides",
- default=6,
- min=1, soft_min=1,
- description="Sides of arc")
- startAngle = FloatProperty(name="Start angle",
- default=0.0,
- description="Start angle")
- endAngle = FloatProperty(name="End angle",
- default=90.0,
- description="End angle")
- arcType = IntProperty(name="Arc type",
- default=3,
- min=1, soft_min=1,
- max=3, soft_max=3,
- description="Sides of arc")
-
- #### Cogwheel properties
- teeth = IntProperty(name="Teeth",
- default=8,
- min=2, soft_min=2,
- description="number of teeth")
- bevel = FloatProperty(name="Bevel",
- default=0.5,
- min=0, soft_min=0,
- max=1, soft_max=1,
- description="Bevel")
-
- #### Nsided property
- Nsides = IntProperty(name="Sides",
- default=8,
- min=3, soft_min=3,
- description="Number of sides")
-
- #### Splat properties
- splatSides = IntProperty(name="Splat sides",
- default=24,
- min=3, soft_min=3,
- description="Splat sides")
- splatScale = FloatProperty(name="Splat scale",
- default=1.0,
- min=0, soft_min=0,
- description="Splat scale")
- seed = IntProperty(name="Seed",
- default=0,
- min=0, soft_min=0,
- description="Seed")
- basis = IntProperty(name="Basis",
- default=0,
- min=0, soft_min=0,
- description="Basis")
-
- #### Helix properties
- helixPoints = IntProperty(name="resolution",
- default=100,
- min=3, soft_min=3,
- description="resolution")
- helixHeight = FloatProperty(name="Height",
- default=2.0,
- min=0, soft_min=0,
- description="Helix height")
- helixStart = FloatProperty(name="Start angle",
- default=0.0,
- description="Helix start angle")
- helixEnd = FloatProperty(name="Endangle",
- default=360.0,
- description="Helix end angle")
- helixWidth = FloatProperty(name="Width",
- default=1.0,
- description="Helix width")
- helix_a = FloatProperty(name="var_1",
- default=0.0,
- description="Helix var1")
- helix_b = FloatProperty(name="var_2",
- default=0.0,
- description="Helix var2")
-
- #### Cycloid properties
- cycloPoints = IntProperty(name="Resolution",
- default=100,
- min=3, soft_min=3,
- description="Resolution")
- cyclo_d = FloatProperty(name="var_3",
- default=1.5,
- description="Cycloid var3")
- cycloType = IntProperty(name="Type",
- default=0,
- min=0, soft_min=0,
- max=0, soft_max=0,
- description="resolution")
- cyclo_a = FloatProperty(name="var_1",
- default=5.0,
- min=0.01, soft_min=0.01,
- description="Cycloid var1")
- cyclo_b = FloatProperty(name="var_2",
- default=0.5,
- min=0.01, soft_min=0.01,
- description="Cycloid var2")
- cycloStart = FloatProperty(name="Start angle",
- default=0.0,
- description="Cycloid start angle")
- cycloEnd = FloatProperty(name="End angle",
- default=360.0,
- description="Cycloid end angle")
-
- ##### DRAW #####
- def draw(self, context):
- props = self.properties
- layout = self.layout
-
- # general options
- col = layout.column()
- col.prop(props, 'GalloreType')
- col.label(text=props.GalloreType+" Options")
-
- # options per GalloreType
- box = layout.box()
- if props.GalloreType == 'Profile':
- box.prop(props, 'ProfileCurveType')
- box.prop(props, 'ProfileCurvevar1')
- box.prop(props, 'ProfileCurvevar2')
- if props.GalloreType == 'Miscellaneous':
- box.prop(props, 'MiscCurveType')
- box.prop(props, 'MiscCurvevar1')
- box.prop(props, 'MiscCurvevar2')
- #box.prop(props, 'MiscCurvevar3') # doesn't seem to do anything
- if props.GalloreType == 'Flower':
- box.prop(props, 'petals')
- box.prop(props, 'petalWidth')
- box.prop(props, 'innerRadius')
- box.prop(props, 'outerRadius')
- if props.GalloreType == 'Star':
- box.prop(props, 'starPoints')
- box.prop(props, 'starTwist')
- box.prop(props, 'innerRadius')
- box.prop(props, 'outerRadius')
- if props.GalloreType == 'Arc':
- box.prop(props, 'arcSides')
- box.prop(props, 'arcType') # has only one Type?
- box.prop(props, 'startAngle')
- box.prop(props, 'endAngle')
- box.prop(props, 'innerRadius') # doesn't seem to do anything
- box.prop(props, 'outerRadius')
- if props.GalloreType == 'Cogwheel':
- box.prop(props, 'teeth')
- box.prop(props, 'bevel')
- box.prop(props, 'innerRadius')
- box.prop(props, 'middleRadius')
- box.prop(props, 'outerRadius')
- if props.GalloreType == 'Nsided':
- box.prop(props, 'Nsides')
- box.prop(props, 'outerRadius', text='Radius')
- '''
- if props.GalloreType == 'Splat':
- box.prop(props, 'splatSides')
- box.prop(props, 'outerRadius')
- box.prop(props, 'splatScale')
- box.prop(props, 'seed')
- box.prop(props, 'basis')
- '''
- if props.GalloreType == 'Helix':
- box.prop(props, 'helixPoints')
- box.prop(props, 'helixHeight')
- box.prop(props, 'helixWidth')
- box.prop(props, 'helixStart')
- box.prop(props, 'helixEnd')
- box.prop(props, 'helix_a')
- box.prop(props, 'helix_b')
- if props.GalloreType == 'Cycloid':
- box.prop(props, 'cycloPoints')
- #box.prop(props, 'cycloType') # needs the other types first
- box.prop(props, 'cycloStart')
- box.prop(props, 'cycloEnd')
- box.prop(props, 'cyclo_a')
- box.prop(props, 'cyclo_b')
- box.prop(props, 'cyclo_d')
-
- col = layout.column()
- col.label(text="Output Curve Type")
- row = layout.row()
- row.prop(props, 'outputType', expand=True)
- col = layout.column()
- col.label(text="Curve Options")
-
- # output options
- box = layout.box()
- if props.outputType == 'NURBS':
- box.row().prop(props, 'shape', expand=True)
- #box.prop(props, 'use_cyclic_u')
- #box.prop(props, 'endp_u')
- box.prop(props, 'order_u')
-
- if props.outputType == 'POLY':
- box.row().prop(props, 'shape', expand=True)
- #box.prop(props, 'use_cyclic_u')
-
- if props.outputType == 'BEZIER':
- box.row().prop(props, 'shape', expand=True)
- box.row().prop(props, 'handleType', expand=True)
- #box.prop(props, 'use_cyclic_u')
-
-
- ##### POLL #####
- @classmethod
- def poll(cls, context):
- return context.scene != None
-
- ##### EXECUTE #####
- def execute(self, context):
- # turn off undo
- undo = bpy.context.user_preferences.edit.use_global_undo
- bpy.context.user_preferences.edit.use_global_undo = False
-
- # deal with 2D - 3D curve differences
- props = self.properties
- if props.GalloreType in ['Helix', 'Cycloid']:
- props.shape = '3D'
- #else:
- #props.shape = '2D' # someone decide if we want this
-
- if props.GalloreType in ['Helix']:
- props.use_cyclic_u = False
- else:
- props.use_cyclic_u = True
-
-
- # main function
- main(context, props, self.align_matrix)
-
- # restore pre operator undo state
- bpy.context.user_preferences.edit.use_global_undo = undo
-
- return {'FINISHED'}
-
- ##### INVOKE #####
- def invoke(self, context, event):
- # store creation_matrix
- self.align_matrix = align_matrix(context)
- self.execute(context)
-
- return {'FINISHED'}
-
-################################################################################
-##### REGISTER #####
-
-def Curveaceous_galore_button(self, context):
- self.layout.operator(Curveaceous_galore.bl_idname, text="curvatures gallore", icon="PLUGIN")
-
-
-def register():
- bpy.types.INFO_MT_curve_add.append(Curveaceous_galore_button)
-
-def unregister():
- bpy.types.INFO_MT_curve_add.remove(Curveaceous_galore_button)
-
-if __name__ == "__main__":
- register()
diff --git a/add_curve_torus_knots.py b/add_curve_torus_knots.py
deleted file mode 100644
index 2f13ac84..00000000
--- a/add_curve_torus_knots.py
+++ /dev/null
@@ -1,320 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-
-bl_addon_info = {
- "name": "Torus Knots",
- "author": "testscreenings",
- "version": (0,1),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "View3D > Add > Curve",
- "description": "Adds many types of knots",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Curve/Torus_Knot",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22403&group_id=153&atid=469",
- "category": "Add Curve"}
-
-
-##------------------------------------------------------------
-#### import modules
-import bpy
-from bpy.props import *
-from mathutils import *
-from math import *
-
-##------------------------------------------------------------
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-##------------------------------------------------------------
-#### Curve creation functions
-
-# get array of vertcoordinates acording to splinetype
-def vertsToPoints(Verts):
- vertArray = []
-
- for v in Verts:
- vertArray += v
- vertArray.append(1) #for nurbs w=1
-
- return vertArray
-
-# create new CurveObject from vertarray and splineType
-def createCurve(vertArray, props, align_matrix):
- # options to vars
- splineType = 'NURBS'
- name = 'Torus_Knot'
-
- # create curve
- scene = bpy.context.scene
- newCurve = bpy.data.curves.new(name, type = 'CURVE') # curvedatablock
- newSpline = newCurve.splines.new(type = splineType) # spline
-
- # create spline from vertarray
- newSpline.points.add(int(len(vertArray)*0.25 - 1))
- newSpline.points.foreach_set('co', vertArray)
- newSpline.use_endpoint_u = True
-
- # Curve settings
- newCurve.dimensions = '3D'
- newSpline.use_cyclic_u = True
- newSpline.use_endpoint_u = True
- newSpline.order_u = 4
-
- if props.geo_surf:
- newCurve.bevel_depth = props.geo_bDepth
- newCurve.bevel_resolution = props.geo_bRes
- newCurve.use_fill_front = False
- newCurve.use_fill_back = False
- newCurve.extrude = props.geo_extrude
- newCurve.offset = props.geo_width
- newCurve.resolution_u = props.geo_res
-
- # create object with newCurve
- new_obj = bpy.data.objects.new(name, newCurve) # object
- scene.objects.link(new_obj) # place in active scene
- new_obj.select = True # set as selected
- scene.objects.active = new_obj # set as active
- new_obj.matrix_world = align_matrix # apply matrix
-
- return
-
-########################################################################
-####################### Knot Definitions ###############################
-########################################################################
-
-#### TORUS KNOT
-def Torus_Knot_Curve(p=2, q=3, w=1, res=24, formula=0, h=1, u=1 ,v=1, rounds=2):
- newPoints = []
- angle = 2*rounds
- step = angle/(res-1)
- scale = h
- height = w
-
- for i in range(res-1):
- t = ( i*step*pi)
-
- x = (2 * scale + cos((q*t)/p*v)) * cos(t * u)
- y = (2 * scale + cos((q*t)/p*v)) * sin(t * u)
- z = sin(q*t/p) * height
-
- newPoints.append([x,y,z])
-
- return newPoints
-
-##------------------------------------------------------------
-# Main Function
-def main(context, props, align_matrix):
- # deselect all objects
- bpy.ops.object.select_all(action='DESELECT')
-
- # get verts
- verts = Torus_Knot_Curve(props.torus_p,
- props.torus_q,
- props.torus_w,
- props.torus_res,
- props.torus_formula,
- props.torus_h,
- props.torus_u,
- props.torus_v,
- props.torus_rounds)
-
- # turn verts into array
- vertArray = vertsToPoints(verts)
-
- # create object
- createCurve(vertArray, props, align_matrix)
-
- return
-
-class torus_knot_plus(bpy.types.Operator):
- ''''''
- bl_idname = "torus_knot_plus"
- bl_label = "Torus Knot +"
- bl_options = {'REGISTER', 'UNDO'}
- bl_description = "adds many types of knots"
-
- # align_matrix for the invoke
- align_matrix = Matrix()
-
- #### general options
- options_plus = BoolProperty(name="plus options",
- default=False,
- description="Show more options (the plus part).")
-
- #### GEO Options
- geo_surf = BoolProperty(name="Surface",
- default=True)
- geo_bDepth = FloatProperty(name="bevel",
- default=0.08,
- min=0, soft_min=0)
- geo_bRes = IntProperty(name="bevel res",
- default=2,
- min=0, soft_min=0,
- max=4, soft_max=4)
- geo_extrude = FloatProperty(name="extrude",
- default=0.0,
- min=0, soft_min=0)
- geo_width = FloatProperty(name="width",
- default=1.0,
- min=0, soft_min=0)
- geo_res = IntProperty(name="resolution",
- default=12,
- min=1, soft_min=1)
-
-
- #### Parameters
- torus_res = IntProperty(name="Resoulution",
- default=200,
- min=3, soft_min=3,
- description='Resolution, Number of controlverticies.')
- torus_p = IntProperty(name="p",
- default=2,
- min=1, soft_min=1,
- #max=1, soft_max=1,
- description="p")
- torus_q = IntProperty(name="q",
- default=3,
- min=1, soft_min=1,
- #max=1, soft_max=1,
- description="q")
- torus_w = FloatProperty(name="Height",
- default=1,
- #min=0, soft_min=0,
- #max=1, soft_max=1,
- description="Height in Z")
- torus_h = FloatProperty(name="Scale",
- default=1,
- #min=0, soft_min=0,
- #max=1, soft_max=1,
- description="Scale, in XY")
- torus_u = IntProperty(name="u",
- default=1,
- min=1, soft_min=1,
- #max=1, soft_max=1,
- description="u")
- torus_v = IntProperty(name="v",
- default=1,
- min=1, soft_min=1,
- #max=1, soft_max=1,
- description="v")
- torus_formula = IntProperty(name="Variation",
- default=0,
- min=0, soft_min=0,
- max=10, soft_max=10)
- torus_rounds = IntProperty(name="Rounds",
- default=2,
- min=1, soft_min=1,
- #max=1, soft_max=1,
- description="Rounds")
-
- ##### DRAW #####
- def draw(self, context):
- props = self.properties
- layout = self.layout
-
- # general options
- col = layout.column()
- #col.prop(props, 'KnotType') waits for more knottypes
- col.label(text="Torus Knot Parameters")
-
- # Parameters
- box = layout.box()
- box.prop(props, 'torus_res')
- box.prop(props, 'torus_w')
- box.prop(props, 'torus_h')
- box.prop(props, 'torus_p')
- box.prop(props, 'torus_q')
- box.prop(props, 'options_plus')
- if props.options_plus:
- box.prop(props, 'torus_u')
- box.prop(props, 'torus_v')
- box.prop(props, 'torus_rounds')
-
- # surface Options
- col = layout.column()
- col.label(text="Geometry Options")
- box = layout.box()
- box.prop(props, 'geo_surf')
- if props.geo_surf:
- box.prop(props, 'geo_bDepth')
- box.prop(props, 'geo_bRes')
- box.prop(props, 'geo_extrude')
- #box.prop(props, 'geo_width') # not really good
- box.prop(props, 'geo_res')
-
- ##### POLL #####
- @classmethod
- def poll(cls, context):
- return context.scene != None
-
- ##### EXECUTE #####
- def execute(self, context):
- # turn off undo
- undo = bpy.context.user_preferences.edit.use_global_undo
- bpy.context.user_preferences.edit.use_global_undo = False
-
- props = self.properties
-
- if not props.options_plus:
- props.torus_rounds = props.torus_p
-
- # main function
- main(context, props, self.align_matrix)
-
- # restore pre operator undo state
- bpy.context.user_preferences.edit.use_global_undo = undo
-
- return {'FINISHED'}
-
- ##### INVOKE #####
- def invoke(self, context, event):
- # store creation_matrix
- self.align_matrix = align_matrix(context)
- self.execute(context)
-
- return {'FINISHED'}
-
-################################################################################
-##### REGISTER #####
-
-def torus_knot_plus_button(self, context):
- self.layout.operator(torus_knot_plus.bl_idname, text="Torus Knot +", icon="PLUGIN")
-
-
-def register():
- bpy.types.INFO_MT_curve_add.append(torus_knot_plus_button)
-
-def unregister():
- bpy.types.INFO_MT_curve_add.remove(torus_knot_plus_button)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_3d_function_surface.py b/add_mesh_3d_function_surface.py
deleted file mode 100644
index 0b1db521..00000000
--- a/add_mesh_3d_function_surface.py
+++ /dev/null
@@ -1,636 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "3D Function Surfaces",
- "author": "Buerbaum Martin (Pontiac)",
- "version": (0,3,5),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Z Function Surface & XYZ Function Surface",
- "description": "Create Objects using Math Formulas",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_3d_Function_Surface",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21444&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-"""
-Z Function Surface
-
-This script lets the user create a surface where the z coordinate
-is a function of the x and y coordinates.
-
- z = f(x,y)
-
-X,Y,Z Function Surface
-
-This script lets the user create a surface where the x, y and z
-coordinates are defiend by a function.
-
- x = f(u,v)
- y = f(u,v)
- z = f(u,v)
-
-Usage:
-You have to activated the script in the "Add-Ons" tab (user preferences).
-The functionality can then be accessed via the
-"Add Mesh" -> "Z Function Surface"
-and
-"Add Mesh" -> "X,Y,Z Function Surface"
-menu.
-
-Version history:
-v0.3.5 - createFaces can now "Flip" faces and create fan/star like faces.
-v0.3.4 - Updated store_recall_properties, apply_object_align
- and create_mesh_object.
- Changed how recall data is stored.
-v0.3.3 - API change Mathutils -> mathutils (r557)
-v0.3.2 - Various fixes&streamlining by ideasman42/Campbell Barton.
- r544 Compile expressions for faster execution
- r544 Use operator reports for errors too
- r544 Avoid type checks by converting to a float, errors
- converting to a float are reported too.
- Fixed an error Campbell overlooked (appending tuples to an
- array, not single values) Thamnks for the report wild_doogy.
- Added 'description' field, updated 'wiki_url'.
- Made the script PEP8 compatible again.
-v0.3.1 - Use hidden "edit" property for "recall" operator.
- Bugfix: Z Function was mixing up div_x and div_y
-v0.3 - X,Y,Z Function Surface (by Ed Mackey & tuga3d).
- Renamed old function to "Z Function Surface".
- Align the geometry to the view if the user preference says so.
- Store recall properties in newly created object.
-v0.2.3 - Use bl_addon_info for Add-On information.
-v0.2.2 - Fixed Add-On registration text.
-v0.2.1 - Fixed some new API stuff.
- Mainly we now have the register/unregister functions.
- Also the new() function for objects now accepts a mesh object.
- Changed the script so it can be managed from the "Add-Ons" tab
- in the user preferences.
- Added dummy "PLUGIN" icon.
- Corrected FSF address.
- Clean up of tooltips.
-v0.2 - Added security check for eval() function
- Check return value of eval() for complex numbers.
-v0.1.1 - Use 'CANCELLED' return value when failing.
- Updated web links.
-v0.1 - Initial revision.
-
-More Links:
-http://gitorious.org/blender-scripts/blender-3d-function-surface
-http://blenderartists.org/forum/showthread.php?t=179043
-"""
-
-
-import bpy
-from mathutils import *
-from math import *
-from bpy.props import *
-
-# List of safe functions for eval()
-safe_list = ['math', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
- 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot',
- 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians',
- 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
-
-# Use the list to filter the local namespace
-safe_dict = dict([(k, globals().get(k, None)) for k in safe_list])
-
-
-# Stores the values of a list of properties and the
-# operator id in a property group ('recall_op') inside the object.
-# Could (in theory) be used for non-objects.
-# Note: Replaces any existing property group with the same name!
-# ob ... Object to store the properties in.
-# op ... The operator that should be used.
-# op_args ... A dictionary with valid Blender
-# properties (operator arguments/parameters).
-
-
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-class AddZFunctionSurface(bpy.types.Operator):
- '''Add a surface defined defined by a function z=f(x,y)'''
- bl_idname = "mesh.primitive_z_function_surface"
- bl_label = "Add Z Function Surface"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- equation = StringProperty(name="Z Equation",
- description="Equation for z=f(x,y)",
- default="1 - ( x**2 + y**2 )")
-
- div_x = IntProperty(name="X Subdivisions",
- description="Number of vertices in x direction.",
- default=16,
- min=3,
- max=256)
- div_y = IntProperty(name="Y Subdivisions",
- description="Number of vertices in y direction.",
- default=16,
- min=3,
- max=256)
-
- size_x = FloatProperty(name="X Size",
- description="Size of the x axis.",
- default=2.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- size_y = FloatProperty(name="Y Size",
- description="Size of the y axis.",
- default=2.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
- equation = self.properties.equation
- div_x = self.properties.div_x
- div_y = self.properties.div_y
- size_x = self.properties.size_x
- size_y = self.properties.size_y
-
- verts = []
- faces = []
-
- delta_x = size_x / float(div_x - 1)
- delta_y = size_y / float(div_y - 1)
- start_x = -(size_x / 2.0)
- start_y = -(size_y / 2.0)
-
- edgeloop_prev = []
-
- try:
- expr_args = (
- compile(equation, __file__, 'eval'),
- {"__builtins__": None},
- safe_dict)
- except:
- import traceback
- self.report({'ERROR'}, "Error parsing expression: "
- + traceback.format_exc(limit=1))
- return {'CANCELLED'}
-
- for row_x in range(div_x):
- edgeloop_cur = []
- x = start_x + row_x * delta_x
-
- for row_y in range(div_y):
- y = start_y + row_y * delta_y
- z = 0.0
-
- safe_dict['x'] = x
- safe_dict['y'] = y
-
- # Try to evaluate the equation.
- try:
- z = float(eval(*expr_args))
- except:
- import traceback
- self.report({'ERROR'}, "Error evaluating expression: "
- + traceback.format_exc(limit=1))
- return {'CANCELLED'}
-
- edgeloop_cur.append(len(verts))
- verts.append((x, y, z))
-
- if len(edgeloop_prev) > 0:
- faces_row = createFaces(edgeloop_prev, edgeloop_cur)
- faces.extend(faces_row)
-
- edgeloop_prev = edgeloop_cur
-
- obj = create_mesh_object(context, verts, [], faces, "Z Function", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-def xyz_function_surface_faces(self, x_eq, y_eq, z_eq,
- range_u_min, range_u_max, range_u_step, wrap_u,
- range_v_min, range_v_max, range_v_step, wrap_v):
-
- verts = []
- faces = []
-
- uStep = (range_u_max - range_u_min) / range_u_step
- vStep = (range_v_max - range_v_min) / range_v_step
-
- uRange = range_u_step
- if range_u_step == 0:
- uRange = uRange + 1
-
- vRange = range_v_step
- if range_v_step == 0:
- vRange = vRange + 1
-
- try:
- expr_args_x = (
- compile(x_eq, __file__.replace(".py", "_x.py"), 'eval'),
- {"__builtins__": None},
- safe_dict)
- expr_args_y = (
- compile(y_eq, __file__.replace(".py", "_y.py"), 'eval'),
- {"__builtins__": None},
- safe_dict)
- expr_args_z = (
- compile(z_eq, __file__.replace(".py", "_z.py"), 'eval'),
- {"__builtins__": None},
- safe_dict)
- except:
- import traceback
- self.report({'ERROR'}, "Error parsing expression: "
- + traceback.format_exc(limit=1))
- return [], []
-
- for vN in range(vRange):
- v = range_v_min + (vN * vStep)
-
- for uN in range(uRange):
- u = range_u_min + (uN * uStep)
-
- safe_dict['u'] = u
- safe_dict['v'] = v
-
- # Try to evaluate the equation.
- try:
- verts.append((
- float(eval(*expr_args_x)),
- float(eval(*expr_args_y)),
- float(eval(*expr_args_z))))
-
- except:
- import traceback
- self.report({'ERROR'}, "Error evaluating expression: "
- + traceback.format_exc(limit=1))
- return [], []
-
- for vN in range(1, range_v_step + 1):
- vThis = vN
-
- if (vThis >= vRange):
- if wrap_v:
- vThis = 0
- else:
- continue
-
- for uN in range(1, range_u_step + 1):
- uThis = uN
-
- if (uThis >= uRange):
- if wrap_u:
- uThis = 0
- else:
- continue
-
- faces.append([(vThis * uRange) + uThis,
- (vThis * uRange) + uN - 1,
- ((vN - 1) * uRange) + uN - 1,
- ((vN - 1) * uRange) + uThis])
-
- return verts, faces
-
-
-# Original Script "Parametric.py" by Ed Mackey.
-# -> http://www.blinken.com/blender-plugins.php
-# Partly converted for Blender 2.5 by tuga3d.
-#
-# Sphere:
-# x = sin(2*pi*u)*sin(pi*v)
-# y = cos(2*pi*u)*sin(pi*v)
-# z = cos(pi*v)
-# u_min = v_min = 0
-# u_max = v_max = 1
-#
-# "Snail shell"
-# x = 1.2**v*(sin(u)**2 *sin(v))
-# y = 1.2**v*(sin(u)*cos(u))
-# z = 1.2**v*(sin(u)**2 *cos(v))
-# u_min = 0
-# u_max = pi
-# v_min = -pi/4,
-# v max = 5*pi/2
-class AddXYZFunctionSurface(bpy.types.Operator):
- '''Add a surface defined defined by 3 functions:''' \
- + ''' x=f(u,v), y=f(u,v) and z=f(u,v)'''
- bl_idname = "mesh.primitive_xyz_function_surface"
- bl_label = "Add X,Y,Z Function Surface"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- x_eq = StringProperty(name="X Equation",
- description="Equation for x=f(u,v)",
- default="1.2**v*(sin(u)**2 *sin(v))")
-
- y_eq = StringProperty(name="Y Equation",
- description="Equation for y=f(u,v)",
- default="1.2**v*(sin(u)*cos(u))")
-
- z_eq = StringProperty(name="Z Equation",
- description="Equation for z=f(u,v)",
- default="1.2**v*(sin(u)**2 *cos(v))")
-
- range_u_min = FloatProperty(name="U min",
- description="Minimum U value. Lower boundary of U range.",
- min=-100.00,
- max=0.00,
- default=0.00)
-
- range_u_max = FloatProperty(name="U max",
- description="Maximum U value. Upper boundary of U range.",
- min=0.00,
- max=100.00,
- default=pi)
-
- range_u_step = IntProperty(name="U step",
- description="U Subdivisions",
- min=1,
- max=1024,
- default=32)
-
- wrap_u = BoolProperty(name="U wrap",
- description="U Wrap around",
- default=True)
-
- range_v_min = FloatProperty(name="V min",
- description="Minimum V value. Lower boundary of V range.",
- min=-100.00,
- max=0.00,
- default=-pi / 4)
-
- range_v_max = FloatProperty(name="V max",
- description="Maximum V value. Upper boundary of V range.",
- min=0.00,
- max=100.00,
- default=5 * pi / 2)
-
- range_v_step = IntProperty(name="V step",
- description="V Subdivisions",
- min=1,
- max=1024,
- default=32)
-
- wrap_v = BoolProperty(name="V wrap",
- description="V Wrap around",
- default=False)
-
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- verts, faces = xyz_function_surface_faces(
- self,
- props.x_eq,
- props.y_eq,
- props.z_eq,
- props.range_u_min,
- props.range_u_max,
- props.range_u_step,
- props.wrap_u,
- props.range_v_min,
- props.range_v_max,
- props.range_v_step,
- props.wrap_v)
-
- if not verts:
- return {'CANCELLED'}
-
- obj = create_mesh_object(context, verts, [], faces,
- "XYZ Function", props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-################################
-import space_info
-
-# Define "3D Function Surface" menu
-def menu_func_z(self, context):
- self.layout.operator(AddZFunctionSurface.bl_idname, text="Z Function Surface", icon="PLUGIN")
-
-def menu_func_xyz(self, context):
- self.layout.operator(AddXYZFunctionSurface.bl_idname, text="X,Y,Z Function Surface", icon="PLUGIN")
-
-
-def register():
- # Add menus to the "Add Mesh" menu
- space_info.INFO_MT_mesh_add.append(menu_func_z)
- space_info.INFO_MT_mesh_add.append(menu_func_xyz)
-
-
-def unregister():
- # Remove menus from the "Add Mesh" menu.
- space_info.INFO_MT_mesh_add.remove(menu_func_z)
- space_info.INFO_MT_mesh_add.remove(menu_func_xyz)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_BoltFactory/Boltfactory.py b/add_mesh_BoltFactory/Boltfactory.py
deleted file mode 100644
index 27c0d8cc..00000000
--- a/add_mesh_BoltFactory/Boltfactory.py
+++ /dev/null
@@ -1,306 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-
-import bpy
-import mathutils
-from bpy.props import *
-from add_mesh_BoltFactory.createMesh import *
-from add_mesh_BoltFactory.preset_utils import *
-
-
-
-##------------------------------------------------------------
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = mathutils.Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = mathutils.Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-
-
-class add_mesh_bolt(bpy.types.Operator):
- ''''''
- bl_idname = 'add_mesh_bolt'
- bl_label = "Add Bolt"
- bl_options = {'REGISTER', 'UNDO'}
- bl_description = "adds many types of Bolts"
-
- align_matrix = mathutils.Matrix()
- MAX_INPUT_NUMBER = 50
-
- #Model Types
- Model_Type_List = [('bf_Model_Bolt','BOLT','Bolt Model'),
- ('bf_Model_Nut','NUT','Nut Model')]
- bf_Model_Type = EnumProperty( attr='bf_Model_Type',
- name='Model',
- description='Choose the type off model you would like',
- items = Model_Type_List, default = 'bf_Model_Bolt')
-
- #Head Types
- Model_Type_List = [('bf_Head_Hex','HEX','Hex Head'),
- ('bf_Head_Cap','CAP','Cap Head'),
- ('bf_Head_Dome','DOME','Dome Head'),
- ('bf_Head_Pan','PAN','Pan Head'),
- ('bf_Head_CounterSink','COUNTER SINK','Counter Sink Head')]
- bf_Head_Type = EnumProperty( attr='bf_Head_Type',
- name='Head',
- description='Choose the type off Head you would like',
- items = Model_Type_List, default = 'bf_Head_Hex')
-
- #Bit Types
- Bit_Type_List = [('bf_Bit_None','NONE','No Bit Type'),
- ('bf_Bit_Allen','ALLEN','Allen Bit Type'),
- ('bf_Bit_Philips','PHILLIPS','Phillips Bit Type')]
- bf_Bit_Type = EnumProperty( attr='bf_Bit_Type',
- name='Bit Type',
- description='Choose the type of bit to you would like',
- items = Bit_Type_List, default = 'bf_Bit_None')
-
- #Nut Types
- Nut_Type_List = [('bf_Nut_Hex','HEX','Hex Nut'),
- ('bf_Nut_Lock','LOCK','Lock Nut')]
- bf_Nut_Type = EnumProperty( attr='bf_Nut_Type',
- name='Nut Type',
- description='Choose the type of nut you would like',
- items = Nut_Type_List, default = 'bf_Nut_Hex')
-
- #Shank Types
- bf_Shank_Length = FloatProperty(attr='bf_Shank_Length',
- name='Shank Length', default = 0,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Length of the unthreaded shank')
-
- bf_Shank_Dia = FloatProperty(attr='bf_Shank_Dia',
- name='Shank Dia', default = 3,
- min = 0, soft_min = 0,max = MAX_INPUT_NUMBER,
- description='Diameter of the shank')
-
- bf_Phillips_Bit_Depth = FloatProperty(attr='bf_Phillips_Bit_Depth',
- name='Bit Depth', default = 0, #set in execute
- options = {'HIDDEN'}, #gets calculated in execute
- min = 0, soft_min = 0,max = MAX_INPUT_NUMBER,
- description='Depth of the Phillips Bit')
-
- bf_Allen_Bit_Depth = FloatProperty(attr='bf_Allen_Bit_Depth',
- name='Bit Depth', default = 1.5,
- min = 0, soft_min = 0,max = MAX_INPUT_NUMBER,
- description='Depth of the Allen Bit')
-
- bf_Allen_Bit_Flat_Distance = FloatProperty( attr='bf_Allen_Bit_Flat_Distance',
- name='Flat Dist', default = 2.5,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Flat Distance of the Allen Bit')
-
- bf_Hex_Head_Height = FloatProperty( attr='bf_Hex_Head_Height',
- name='Head Height', default = 2,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Height of the Hex Head')
-
- bf_Hex_Head_Flat_Distance = FloatProperty( attr='bf_Hex_Head_Flat_Distance',
- name='Flat Dist', default = 5.5,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Flat Distance of the Hex Head')
-
- bf_CounterSink_Head_Dia = FloatProperty( attr='bf_CounterSink_Head_Dia',
- name='Head Dia', default = 5.5,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Diameter of the Counter Sink Head')
-
- bf_Cap_Head_Height = FloatProperty( attr='bf_Cap_Head_Height',
- name='Head Height', default = 5.5,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Height of the Cap Head')
-
- bf_Cap_Head_Dia = FloatProperty( attr='bf_Cap_Head_Dia',
- name='Head Dia', default = 3,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Diameter of the Cap Head')
-
- bf_Dome_Head_Dia = FloatProperty( attr='bf_Dome_Head_Dia',
- name='Dome Head Dia', default = 5.6,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Length of the unthreaded shank')
-
- bf_Pan_Head_Dia = FloatProperty( attr='bf_Pan_Head_Dia',
- name='Pan Head Dia', default = 5.6,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Diameter of the Pan Head')
-
- bf_Philips_Bit_Dia = FloatProperty(attr='bf_Philips_Bit_Dia',
- name='Bit Dia', default = 0, #set in execute
- options = {'HIDDEN'}, #gets calculated in execute
- min = 0, soft_min = 0,max = MAX_INPUT_NUMBER,
- description='Diameter of the Philips Bit')
-
- bf_Thread_Length = FloatProperty( attr='bf_Thread_Length',
- name='Thread Length', default = 6,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Length of the Thread')
-
- bf_Major_Dia = FloatProperty( attr='bf_Major_Dia',
- name='Major Dia', default = 3,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Outside diameter of the Thread')
-
- bf_Pitch = FloatProperty( attr='bf_Pitch',
- name='Pitch', default = 0.35,
- min = 0.1, soft_min = 0.1, max = 7.0,
- description='Pitch if the thread')
-
- bf_Minor_Dia = FloatProperty( attr='bf_Minor_Dia',
- name='Minor Dia', default = 0, #set in execute
- options = {'HIDDEN'}, #gets calculated in execute
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Inside diameter of the Thread')
-
- bf_Crest_Percent = IntProperty( attr='bf_Crest_Percent',
- name='Crest Percent', default = 10,
- min = 1, soft_min = 1, max = 90,
- description='Percent of the pitch that makes up the Crest')
-
- bf_Root_Percent = IntProperty( attr='bf_Root_Percent',
- name='Root Percent', default = 10,
- min = 1, soft_min = 1, max = 90,
- description='Percent of the pitch that makes up the Root')
-
- bf_Hex_Nut_Height = FloatProperty( attr='bf_Hex_Nut_Height',
- name='Hex Nut Height', default = 2.4,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Height of the Hex Nut')
-
- bf_Hex_Nut_Flat_Distance = FloatProperty( attr='bf_Hex_Nut_Flat_Distance',
- name='Hex Nut Flat Dist', default = 5.5,
- min = 0, soft_min = 0, max = MAX_INPUT_NUMBER,
- description='Flat distance of the Hex Nut')
-
- presets, presetsPath = getPresets()
-
- bf_presets = EnumProperty(attr='bf_presets',
- name='Preset',
- description="Use Preset from File",
- default='M3.py',
- items=presets)
-
- last_preset = None
-
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- col = layout.column()
-
- #ENUMS
- col.prop(props, 'bf_Model_Type')
- col.prop(props, 'bf_presets')
- col.separator()
-
- #Bit
- if props.bf_Model_Type == 'bf_Model_Bolt':
- col.prop(props, 'bf_Bit_Type')
- if props.bf_Bit_Type == 'bf_Bit_None':
- DoNothing = 1;
- elif props.bf_Bit_Type == 'bf_Bit_Allen':
- col.prop(props,'bf_Allen_Bit_Depth')
- col.prop(props,'bf_Allen_Bit_Flat_Distance')
- elif props.bf_Bit_Type == 'bf_Bit_Philips':
- col.prop(props,'bf_Phillips_Bit_Depth')
- col.prop(props,'bf_Philips_Bit_Dia')
- col.separator()
-
- #Head
- if props.bf_Model_Type == 'bf_Model_Bolt':
- col.prop(props, 'bf_Head_Type')
- if props.bf_Head_Type == 'bf_Head_Hex':
- col.prop(props, 'bf_Hex_Head_Height')
- col.prop(props, 'bf_Hex_Head_Flat_Distance')
- elif props.bf_Head_Type == 'bf_Head_Cap':
- col.prop(props,'bf_Cap_Head_Height')
- col.prop(props,'bf_Cap_Head_Dia')
- elif props.bf_Head_Type == 'bf_Head_Dome':
- col.prop(props,'bf_Dome_Head_Dia')
- elif props.bf_Head_Type == 'bf_Head_Pan':
- col.prop(props,'bf_Pan_Head_Dia')
- elif props.bf_Head_Type == 'bf_Head_CounterSink':
- col.prop(props,'bf_CounterSink_Head_Dia')
- col.separator()
- #Shank
- if props.bf_Model_Type == 'bf_Model_Bolt':
- col.label(text='Shank')
- col.prop(props, 'bf_Shank_Length')
- col.prop(props, 'bf_Shank_Dia')
- col.separator()
- #Nut
- if props.bf_Model_Type == 'bf_Model_Nut':
- col.prop(props, 'bf_Nut_Type')
- col.prop(props,'bf_Hex_Nut_Height')
- col.prop(props,'bf_Hex_Nut_Flat_Distance')
- #Thread
- col.label(text='Thread')
- if props.bf_Model_Type == 'bf_Model_Bolt':
- col.prop(props,'bf_Thread_Length')
- col.prop(props,'bf_Major_Dia')
- col.prop(props,'bf_Minor_Dia')
- col.prop(props,'bf_Pitch')
- col.prop(props,'bf_Crest_Percent')
- col.prop(props,'bf_Root_Percent')
-
-
-
- ##### POLL #####
- @classmethod
- def poll(cls, context):
- return context.scene != None
-
- ##### EXECUTE #####
- def execute(self, context):
-
- #print('EXECUTING...')
- props = self.properties
-
- if not self.last_preset or props.bf_presets != self.last_preset:
- #print('setting Preset', props.bf_presets)
- setProps(props, props.bf_presets, self.presetsPath)
- props.bf_Phillips_Bit_Depth = float(Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia))
-
- self.last_preset = props.bf_presets
-
-
- #props.bf_Phillips_Bit_Depth = float(Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia))
- #props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
- #props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-
- Create_New_Mesh(props, context, self.align_matrix)
-
- return {'FINISHED'}
-
- ##### INVOKE #####
- def invoke(self, context, event):
- #print('\n___________START_____________')
- # store creation_matrix
- self.align_matrix = align_matrix(context)
- self.execute(context)
-
- return {'FINISHED'}
diff --git a/add_mesh_BoltFactory/__init__.py b/add_mesh_BoltFactory/__init__.py
deleted file mode 100644
index 6e8e1ef1..00000000
--- a/add_mesh_BoltFactory/__init__.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "BoltFactory",
- "author": "Aaron Keith",
- "version": (3,9),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "add Mesh",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/BoltFactory",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22842&group_id=153&atid=468",
- "category": "Add Mesh"}
-
-import bpy
-
-try:
- init_data
-
- reload(Boltfactory)
-except:
- from add_mesh_BoltFactory import Boltfactory
-
-init_data = True
-
-################################################################################
-##### REGISTER #####
-
-def add_mesh_bolt_button(self, context):
- self.layout.operator(Boltfactory.add_mesh_bolt.bl_idname, text="BOLT", icon="PLUGIN")
-
-
-def register():
- bpy.types.INFO_MT_mesh_add.append(add_mesh_bolt_button)
- #bpy.types.VIEW3D_PT_tools_objectmode.prepend(add_mesh_bolt_button) #just for testing
-
-def unregister():
- bpy.types.INFO_MT_mesh_add.remove(add_mesh_bolt_button)
- #bpy.types.VIEW3D_PT_tools_objectmode.remove(add_mesh_bolt_button) #just for testing
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_BoltFactory/createMesh.py b/add_mesh_BoltFactory/createMesh.py
deleted file mode 100644
index f6562072..00000000
--- a/add_mesh_BoltFactory/createMesh.py
+++ /dev/null
@@ -1,2111 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-
-import os #remove this
-import bpy
-
-try:
- import mathutils
- MATHUTILS = mathutils
-except:
- import Mathutils
- MATHUTILS = Mathutils
-
-
-
-from math import *
-from bpy.props import IntProperty, FloatProperty ,EnumProperty
-from itertools import *
-
-NARROW_UI = 180
-MAX_INPUT_NUMBER = 50
-
-#Global_Scale = 0.001 #1 blender unit = X mm
-GLOBAL_SCALE = 0.1 #1 blender unit = X mm
-#Global_Scale = 1.0 #1 blender unit = X mm
-
-
-
-
-# next two utility functions are stolen from import_obj.py
-
-def unpack_list(list_of_tuples):
- l = []
- for t in list_of_tuples:
- l.extend(t)
- return l
-
-def unpack_face_list(list_of_tuples):
- l = []
- for t in list_of_tuples:
- face = [i for i in t]
-
- if len(face) != 3 and len(face) != 4:
- raise RuntimeError("{0} vertices in face.".format(len(face)))
-
- # rotate indices if the 4th is 0
- if len(face) == 4 and face[3] == 0:
- face = [face[3], face[0], face[1], face[2]]
-
- if len(face) == 3:
- face.append(0)
-
- l.extend(face)
-
- return l
-
-'''
-Remove Doubles takes a list on Verts and a list of Faces and
-removes the doubles, much like Blender does in edit mode.
-It doesn’t have the range function but it will round the corrdinates
-and remove verts that are very close togther. The function
-is useful because you can perform a “Remove Doubles” with out
-having to enter Edit Mode. Having to enter edit mode has the
-disadvantage of not being able to interactively change the properties.
-'''
-
-
-def RemoveDoubles(verts,faces,Decimal_Places = 4):
-
- new_verts = []
- new_faces = []
- dict_verts = {}
- Rounded_Verts = []
-
- for v in verts:
- Rounded_Verts.append([round(v[0],Decimal_Places),round(v[1],Decimal_Places),round(v[2],Decimal_Places)])
-
- for face in faces:
- new_face = []
- for vert_index in face:
- Real_co = tuple(verts[vert_index])
- Rounded_co = tuple(Rounded_Verts[vert_index])
-
- if Rounded_co not in dict_verts:
- dict_verts[Rounded_co] = len(dict_verts)
- new_verts.append(Real_co)
- if dict_verts[Rounded_co] not in new_face:
- new_face.append(dict_verts[Rounded_co])
- if len(new_face) == 3 or len(new_face) == 4:
- new_faces.append(new_face)
-
- return new_verts,new_faces
-
-
-
-
-def Scale_Mesh_Verts(verts,scale_factor):
- Ret_verts = []
- for v in verts:
- Ret_verts.append([v[0]*scale_factor,v[1]*scale_factor,v[2]*scale_factor])
- return Ret_verts
-
-
-
-
-
-#Create a matrix representing a rotation.
-#
-#Parameters:
-#
-# * angle (float) - The angle of rotation desired.
-# * matSize (int) - The size of the rotation matrix to construct. Can be 2d, 3d, or 4d.
-# * axisFlag (string (optional)) - Possible values:
-# o "x - x-axis rotation"
-# o "y - y-axis rotation"
-# o "z - z-axis rotation"
-# o "r - arbitrary rotation around vector"
-# * axis (Vector object. (optional)) - The arbitrary axis of rotation used with "R"
-#
-#Returns: Matrix object.
-# A new rotation matrix.
-def Simple_RotationMatrix(angle, matSize, axisFlag):
- if matSize != 4 :
- print ("Simple_RotationMatrix can only do 4x4")
-
- q = radians(angle) #make the rotation go clockwise
-
- if axisFlag == 'x':
- matrix = MATHUTILS.Matrix([1,0,0,0],[0,cos(q),sin(q),0],[0,-sin(q),cos(q),0],[0,0,0,1])
- elif axisFlag == 'y':
- matrix = MATHUTILS.Matrix([cos(q),0,-sin(q),0],[0,1,0,0],[sin(q),0,cos(q),0],[0,0,0,1])
- elif axisFlag == 'z':
- matrix = MATHUTILS.Matrix([cos(q),sin(q),0,0],[-sin(q),cos(q),0,0],[0,0,1,0],[0,0,0,1])
- else:
- print ("Simple_RotationMatrix can only do x y z axis")
- return matrix
-
-
-##########################################################################################
-##########################################################################################
-## Converter Functions For Bolt Factory
-##########################################################################################
-##########################################################################################
-
-
-def Flat_To_Radius(FLAT):
- h = (float(FLAT)/2)/cos(radians(30))
- return h
-
-def Get_Phillips_Bit_Height(Bit_Dia):
- Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0
- Bit_Rad = Bit_Dia / 2.0
- x = Bit_Rad - Flat_Width_half
- y = tan(radians(60))*x
- return float(y)
-
-
-##########################################################################################
-##########################################################################################
-## Miscellaneous Utilities
-##########################################################################################
-##########################################################################################
-
-# Returns a list of verts rotated by the given matrix. Used by SpinDup
-def Rot_Mesh(verts,matrix):
- ret = []
- #print ("rot mat",matrix)
- for v in verts:
- vec = MATHUTILS.Vector(v) * matrix
- ret.append([vec.x,vec.y,vec.z])
- return ret
-
-# Returns a list of faces that has there index incremented by offset
-def Copy_Faces(faces,offset):
- ret = []
- for f in faces:
- fsub = []
- for i in range(len(f)):
- fsub.append(f[i]+ offset)
- ret.append(fsub)
- return ret
-
-
-# Much like Blenders built in SpinDup.
-def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS):
- verts=[]
- faces=[]
-
- if DIVISIONS == 0:
- DIVISIONS = 1
-
- step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc
-
- for i in range(int(DIVISIONS)):
- rotmat = Simple_RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis.
- Rot = Rot_Mesh(VERTS,rotmat)
- faces.extend(Copy_Faces(FACES,len(verts)))
- verts.extend(Rot)
- return verts,faces
-
-
-
-# Returns a list of verts that have been moved up the z axis by DISTANCE
-def Move_Verts_Up_Z(VERTS,DISTANCE):
- ret = []
- for v in VERTS:
- ret.append([v[0],v[1],v[2]+DISTANCE])
- return ret
-
-
-# Returns a list of verts and faces that has been mirrored in the AXIS
-def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0):
- ret_vert = []
- ret_face = []
- offset = len(VERTS)
- if AXIS == 'y':
- for v in VERTS:
- Delta = v[0] - FLIP_POINT
- ret_vert.append([FLIP_POINT-Delta,v[1],v[2]])
- if AXIS == 'x':
- for v in VERTS:
- Delta = v[1] - FLIP_POINT
- ret_vert.append([v[0],FLIP_POINT-Delta,v[2]])
- if AXIS == 'z':
- for v in VERTS:
- Delta = v[2] - FLIP_POINT
- ret_vert.append([v[0],v[1],FLIP_POINT-Delta])
-
- for f in FACES:
- fsub = []
- for i in range(len(f)):
- fsub.append(f[i]+ offset)
- fsub.reverse() # flip the order to make norm point out
- ret_face.append(fsub)
-
- return ret_vert,ret_face
-
-
-
-# Returns a list of faces that
-# make up an array of 4 point polygon.
-def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0):
- Ret =[]
- RowStart = 0;
- for j in range(ROW):
- for i in range(COLUM):
- Res1 = RowStart + i;
- Res2 = RowStart + i + (COLUM +1)
- Res3 = RowStart + i + (COLUM +1) +1
- Res4 = RowStart+i+1
- if FLIP:
- Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4])
- else:
- Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1])
- RowStart += COLUM+1
- return Ret
-
-
-# Returns a list of faces that makes up a fill pattern for a
-# circle
-def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0):
- Ret =[]
- Face = [1,2,0]
- TempFace = [0,0,0]
- A = 0
- B = 1
- C = 2
- if NUM < 3:
- return None
- for i in range(NUM-2):
- if (i%2):
- TempFace[0] = Face[C];
- TempFace[1] = Face[C] + 1;
- TempFace[2] = Face[B];
- if FACE_DOWN:
- Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
- else:
- Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
- else:
- TempFace[0] =Face[C];
- if Face[C] == 0:
- TempFace[1] = NUM-1;
- else:
- TempFace[1] = Face[C] - 1;
- TempFace[2] = Face[B];
- if FACE_DOWN:
- Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
- else:
- Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
-
- Face[0] = TempFace[0]
- Face[1] = TempFace[1]
- Face[2] = TempFace[2]
- return Ret
-
-######################################################################################
-##########################################################################################
-##########################################################################################
-## Create Allen Bit
-##########################################################################################
-##########################################################################################
-
-
-def Allen_Fill(OFFSET,FLIP= 0):
- faces = []
- Lookup = [[19,1,0],
- [19,2,1],
- [19,3,2],
- [19,20,3],
- [20,4,3],
- [20,5,4],
- [20,6,5],
- [20,7,6],
- [20,8,7],
- [20,9,8],
-
- [20,21,9],
-
- [21,10,9],
- [21,11,10],
- [21,12,11],
- [21,13,12],
- [21,14,13],
- [21,15,14],
-
- [21,22,15],
- [22,16,15],
- [22,17,16],
- [22,18,17]
- ]
- for i in Lookup:
- if FLIP:
- faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
-
- return faces
-
-def Allen_Bit_Dia(FLAT_DISTANCE):
- Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
- return (Flat_Radius * 1.05) * 2.0
-
-def Allen_Bit_Dia_To_Flat(DIA):
- Flat_Radius = (DIA/2.0)/1.05
- return (Flat_Radius * cos (radians(30)))* 2.0
-
-
-
-def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT):
- Div = 36
- verts = []
- faces = []
-
- Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
- OUTTER_RADIUS = Flat_Radius * 1.05
- Outter_Radius_Height = Flat_Radius * (0.1/5.77)
- FaceStart_Outside = len(verts)
- Deg_Step = 360.0 /float(Div)
-
- for i in range(int(Div/2)+1): # only do half and mirror later
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,0])
-
- FaceStart_Inside = len(verts)
-
- Deg_Step = 360.0 /float(6)
- for i in range(int(6/2)+1):
- x = sin(radians(i*Deg_Step))* Flat_Radius
- y = cos(radians(i*Deg_Step))* Flat_Radius
- verts.append([x,y,0-Outter_Radius_Height])
-
- faces.extend(Allen_Fill(FaceStart_Outside,0))
-
-
- FaceStart_Bottom = len(verts)
-
- Deg_Step = 360.0 /float(6)
- for i in range(int(6/2)+1):
- x = sin(radians(i*Deg_Step))* Flat_Radius
- y = cos(radians(i*Deg_Step))* Flat_Radius
- verts.append([x,y,0-HEIGHT])
-
- faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,True))
- faces.extend(Fill_Ring_Face(FaceStart_Bottom,4))
-
-
- M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(M_Verts)
- faces.extend(M_Faces)
-
- return verts,faces,OUTTER_RADIUS * 2.0
-
-
-##########################################################################################
-##########################################################################################
-## Create Phillips Bit
-##########################################################################################
-##########################################################################################
-
-
-def Phillips_Fill(OFFSET,FLIP= 0):
- faces = []
- Lookup = [[0,1,10],
- [1,11,10],
- [1,2,11],
- [2,12,11],
-
- [2,3,12],
- [3,4,12],
- [4,5,12],
- [5,6,12],
- [6,7,12],
-
- [7,13,12],
- [7,8,13],
- [8,14,13],
- [8,9,14],
-
-
- [10,11,16,15],
- [11,12,16],
- [12,13,16],
- [13,14,17,16],
- [15,16,17,18]
-
-
- ]
- for i in Lookup:
- if FLIP:
- if len(i) == 3:
- faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
- else:
- if len(i) == 3:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
- else:
- faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]])
- return faces
-
-
-
-def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT):
- Div = 36
- verts = []
- faces = []
-
- FLAT_RADIUS = FLAT_DIA * 0.5
- OUTTER_RADIUS = FLAT_RADIUS * 1.05
-
- Flat_Half = float(FLAT_WIDTH)/2.0
-
- FaceStart_Outside = len(verts)
- Deg_Step = 360.0 /float(Div)
- for i in range(int(Div/4)+1): # only do half and mirror later
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,0])
-
-
- FaceStart_Inside = len(verts)
- verts.append([0,FLAT_RADIUS,0]) #10
- verts.append([Flat_Half,FLAT_RADIUS,0]) #11
- verts.append([Flat_Half,Flat_Half,0]) #12
- verts.append([FLAT_RADIUS,Flat_Half,0]) #13
- verts.append([FLAT_RADIUS,0,0]) #14
-
-
- verts.append([0,Flat_Half,0-HEIGHT]) #15
- verts.append([Flat_Half,Flat_Half,0-HEIGHT]) #16
- verts.append([Flat_Half,0,0-HEIGHT]) #17
-
- verts.append([0,0,0-HEIGHT]) #18
-
- faces.extend(Phillips_Fill(FaceStart_Outside,True))
-
- Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z')
-
- return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2
-
-
-##########################################################################################
-##########################################################################################
-## Create Head Types
-##########################################################################################
-##########################################################################################
-
-def Max_Pan_Bit_Dia(HEAD_DIA):
- HEAD_RADIUS = HEAD_DIA * 0.5
- XRad = HEAD_RADIUS * 1.976
- return (sin(radians(10))*XRad) * 2.0
-
-
-def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
-
- DIV = 36
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
- #Dome_Rad = HEAD_RADIUS * (1.0/1.75)
-
- Dome_Rad = HEAD_RADIUS * 1.12
- RAD_Offset = HEAD_RADIUS * 0.96
- OtherRad = HEAD_RADIUS * 0.16
- OtherRad_X_Offset = HEAD_RADIUS * 0.84
- OtherRad_Z_Offset = HEAD_RADIUS * 0.504
- XRad = HEAD_RADIUS * 1.976
- ZRad = HEAD_RADIUS * 1.768
- EndRad = HEAD_RADIUS * 0.284
- EndZOffset = HEAD_RADIUS * 0.432
- HEIGHT = HEAD_RADIUS * 0.59
-
-# Dome_Rad = 5.6
-# RAD_Offset = 4.9
-# OtherRad = 0.8
-# OtherRad_X_Offset = 4.2
-# OtherRad_Z_Offset = 2.52
-# XRad = 9.88
-# ZRad = 8.84
-# EndRad = 1.42
-# EndZOffset = 2.16
-# HEIGHT = 2.95
-
- FaceStart = FACE_OFFSET
-
- z = cos(radians(10))*ZRad
- verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z])
- Start_Height = 0 - ((0.0-ZRad)+z)
- Row += 1
-
- #for i in range(0,30,10): was 0 to 30 more work needed to make this look good.
- for i in range(10,30,10):
- x = sin(radians(i))*XRad
- z = cos(radians(i))*ZRad
- verts.append([x,0.0,(0.0-ZRad)+z])
- Row += 1
-
- for i in range(20,140,10):
- x = sin(radians(i))*EndRad
- z = cos(radians(i))*EndRad
- if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT):
- verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT])
- else:
- verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z])
- Row += 1
-
-
- verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)])
- Row += 1
-
- verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- Global_Head_Height = HEIGHT ;
-
-
- return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT
-
-
-
-def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
- DIV = 36
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
- #Dome_Rad = HEAD_RADIUS * (1.0/1.75)
-
- Dome_Rad = HEAD_RADIUS * 1.12
- #Head_Height = HEAD_RADIUS * 0.78
- RAD_Offset = HEAD_RADIUS * 0.98
- Dome_Height = HEAD_RADIUS * 0.64
- OtherRad = HEAD_RADIUS * 0.16
- OtherRad_X_Offset = HEAD_RADIUS * 0.84
- OtherRad_Z_Offset = HEAD_RADIUS * 0.504
-
-
-# Dome_Rad = 5.6
-# RAD_Offset = 4.9
-# Dome_Height = 3.2
-# OtherRad = 0.8
-# OtherRad_X_Offset = 4.2
-# OtherRad_Z_Offset = 2.52
-#
-
- FaceStart = FACE_OFFSET
-
- verts.append([HOLE_RADIUS,0.0,0.0])
- Row += 1
-
-
- for i in range(0,60,10):
- x = sin(radians(i))*Dome_Rad
- z = cos(radians(i))*Dome_Rad
- if ((0.0-RAD_Offset)+z) <= 0:
- verts.append([x,0.0,(0.0-RAD_Offset)+z])
- Row += 1
-
-
- for i in range(60,160,10):
- x = sin(radians(i))*OtherRad
- z = cos(radians(i))*OtherRad
- z = (0.0-OtherRad_Z_Offset)+z
- if z < (0.0-Dome_Height):
- z = (0.0-Dome_Height)
- verts.append([OtherRad_X_Offset+x,0.0,z])
- Row += 1
-
- verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- return sVerts,faces,Dome_Height
-
-
-
-def Create_CounterSink_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1):
- DIV = 36
-
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
-
-
-
-# HEAD_RADIUS = (HEIGHT/tan(radians(60))) + SHANK_RADIUS
- HEIGHT = tan(radians(60)) * (HEAD_RADIUS - SHANK_RADIUS)
- #print (RAD1)
-
- FaceStart = len(verts)
-
- verts.append([HOLE_RADIUS,0.0,0.0])
- Row += 1
-
- #rad
-
- for i in range(0,100,10):
- x = sin(radians(i))*RAD1
- z = cos(radians(i))*RAD1
- verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
- Row += 1
-
-
- verts.append([SHANK_RADIUS,0.0,0.0-HEIGHT])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
-
- return sVerts,faces,HEIGHT
-
-
-
-
-def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2):
- DIV = 36
-
- HOLE_RADIUS = HOLE_DIA * 0.5
- HEAD_RADIUS = HEAD_DIA * 0.5
- SHANK_RADIUS = SHANK_DIA * 0.5
-
- verts = []
- faces = []
- Row = 0
- BEVEL = HEIGHT * 0.01
-
-
- FaceStart = len(verts)
-
- verts.append([HOLE_RADIUS,0.0,0.0])
- Row += 1
-
- #rad
-
- for i in range(0,100,10):
- x = sin(radians(i))*RAD1
- z = cos(radians(i))*RAD1
- verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
- Row += 1
-
-
- verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL])
- Row += 1
-
- verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT])
- Row += 1
-
- #rad2
-
- for i in range(0,100,10):
- x = sin(radians(i))*RAD2
- z = cos(radians(i))*RAD2
- verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z])
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- return sVerts,faces,HEIGHT+RAD2
-
-
-def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT):
-
- verts = []
- faces = []
- HOLE_RADIUS = HOLE_DIA * 0.5
- Half_Flat = FLAT/2
- TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8))
- Undercut_Height = (Half_Flat* (0.05/8))
- Shank_Bevel = (Half_Flat* (0.05/8))
- Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel
- #Undercut_Height = 5
- SHANK_RADIUS = SHANK_DIA/2
- Row = 0;
-
- verts.append([0.0,0.0,0.0])
-
-
- FaceStart = len(verts)
- #inner hole
-
- x = sin(radians(0))*HOLE_RADIUS
- y = cos(radians(0))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*HOLE_RADIUS
- y = cos(radians(60/6))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*HOLE_RADIUS
- y = cos(radians(60/3))*HOLE_RADIUS
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*HOLE_RADIUS
- y = cos(radians(60/2))*HOLE_RADIUS
- verts.append([x,y,0.0])
- Row += 1
-
- #bevel
-
- x = sin(radians(0))*TopBevelRadius
- y = cos(radians(0))*TopBevelRadius
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*TopBevelRadius
- y = cos(radians(60/6))*TopBevelRadius
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*TopBevelRadius
- y = cos(radians(60/3))*TopBevelRadius
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*TopBevelRadius
- y = cos(radians(60/2))*TopBevelRadius
- vec4 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
- Row += 1
-
- #Flats
-
- x = tan(radians(0))*Half_Flat
- dvec = vec1 - MATHUTILS.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/6))*Half_Flat
- dvec = vec2 - MATHUTILS.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/3))*Half_Flat
- dvec = vec3 - MATHUTILS.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
-
-
- x = tan(radians(60/2))*Half_Flat
- dvec = vec4 - MATHUTILS.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Row += 1
-
- #down Bits Tri
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
- Row += 1
-
- #down Bits
-
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,-Flat_Height])
- Row += 1
-
-
- #under cut
-
- x = sin(radians(0))*Half_Flat
- y = cos(radians(0))*Half_Flat
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/6))*Half_Flat
- y = cos(radians(60/6))*Half_Flat
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/3))*Half_Flat
- y = cos(radians(60/3))*Half_Flat
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
-
- x = sin(radians(60/2))*Half_Flat
- y = cos(radians(60/2))*Half_Flat
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height])
- Row += 1
-
- #under cut down bit
- x = sin(radians(0))*Half_Flat
- y = cos(radians(0))*Half_Flat
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/6))*Half_Flat
- y = cos(radians(60/6))*Half_Flat
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/3))*Half_Flat
- y = cos(radians(60/3))*Half_Flat
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/2))*Half_Flat
- y = cos(radians(60/2))*Half_Flat
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
- Row += 1
-
- #under cut to Shank BEVEAL
- x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel)
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
-
- x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
- y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height])
- Row += 1
-
- #under cut to Shank BEVEAL
- x = sin(radians(0))*SHANK_RADIUS
- y = cos(radians(0))*SHANK_RADIUS
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/6))*SHANK_RADIUS
- y = cos(radians(60/6))*SHANK_RADIUS
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/3))*SHANK_RADIUS
- y = cos(radians(60/3))*SHANK_RADIUS
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
-
- x = sin(radians(60/2))*SHANK_RADIUS
- y = cos(radians(60/2))*SHANK_RADIUS
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
- Row += 1
-
-
- #Global_Head_Height = 0 - (-HEIGHT-0.1)
- faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
-
-
- Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(Mirror_Verts)
- faces.extend(Mirror_Faces)
-
- Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z')
-
-
- return Spin_Verts,Spin_Faces,0 - (-HEIGHT)
-
-
-##########################################################################################
-##########################################################################################
-## Create External Thread
-##########################################################################################
-##########################################################################################
-
-
-
-def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Half_Pitch = float(PITCH)/2
- Height_Start = Height_Offset - PITCH
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-#theard start
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
- for j in range(4):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
- return Ret_Row,Height_Offset
-
-
-def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0):
-
- verts = []
- DIV = 36
-
- START_RADIUS = START_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Opp = abs(START_RADIUS - OUTTER_RADIUS)
- Taper_Lentgh = Opp/tan(radians(31));
-
- if Taper_Lentgh > LENGTH:
- Taper_Lentgh = 0
-
- Stright_Length = LENGTH - Taper_Lentgh
-
- Deg_Step = 360.0 /float(DIV)
-
- Row = 0
-
- Lowest_Z_Vert = 0;
-
- Height_Offset = Z_LOCATION
-
-
- #ring
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*START_RADIUS
- y = cos(radians(i*Deg_Step))*START_RADIUS
- z = Height_Offset - 0
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Stright_Length
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*START_RADIUS
- y = cos(radians(i*Deg_Step))*START_RADIUS
- z = Height_Offset - 0
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Taper_Lentgh
- Row += 1
-
-
- return verts,Row,Height_Offset
-
-
-def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
-
- verts = []
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Row = 0
-
- Lowest_Z_Vert = 0;
-
- Height_Offset = Z_LOCATION
-
- Height_Start = Height_Offset
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
-
- Height_Offset = Z_LOCATION + PITCH
- Cut_off = Z_LOCATION
-
-
- for j in range(1):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- if z > Cut_off : z = Cut_off
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- for j in range(2):
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- return verts,Row,Height_Offset
-
-
-
-def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
- verts = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- NUM_OF_START_THREADS = 4.0
- NUM_OF_END_THREADS = 3.0
- Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH)
- Row = 0
-
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
- Height_Offset = Z_LOCATION
-
- Lowest_Z_Vert = 0;
- FaceStart = len(verts)
-
-
- for j in range(Num):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- z = Height_Offset - (Height_Step*i)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
- return verts,Row,Height_Offset
-
-
-
-def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
- verts = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Col = 0
- Row = 0
-
- Height_Offset = Z_LOCATION
-
- Tapper_Height_Start = Height_Offset - PITCH - PITCH
-
- Max_Height = Tapper_Height_Start - PITCH
-
- Lowest_Z_Vert = 0;
-
- FaceStart = len(verts)
- for j in range(4):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS
- if z < Tapper_Height_Start:
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS
- if z < Tapper_Height_Start:
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
- if Tapper_Radius > INNER_RADIUS:
- Tapper_Radius = INNER_RADIUS
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- z = max(z,Max_Height)
- Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
- if Tapper_Radius > INNER_RADIUS:
- Tapper_Radius = INNER_RADIUS
-
- x = sin(radians(i*Deg_Step))*(Tapper_Radius)
- y = cos(radians(i*Deg_Step))*(Tapper_Radius)
- verts.append([x,y,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
- return verts,Row,Height_Offset,Lowest_Z_Vert
-
-
-
-
-def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT):
-
- verts = []
- faces = []
-
- DIV = 36
-
- Total_Row = 0
- Thread_Len = 0;
-
- Face_Start = len(verts)
- Offset = 0.0;
-
-
- Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset)
- Total_Row += Shank_Row
-
- Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset)
- Total_Row += Thread_Start_Row
-
-
- Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset)
- Total_Row += Thread_Row
-
-
- Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset )
- Total_Row += Thread_End_Row
-
-
- verts.extend(Shank_Verts)
- verts.extend(Thread_Start_Verts)
- verts.extend(Thread_Verts)
- verts.extend(Thread_End_Verts)
-
- faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0))
- faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
-
- return verts,faces,0.0 - Lowest_Z_Vert
-
-
-##########################################################################################
-##########################################################################################
-## Create Nut
-##########################################################################################
-##########################################################################################
-
-def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT):
- global Global_Head_Height
- global Global_NutRad
-
- verts = []
- faces = []
- HOLE_RADIUS = HOLE_DIA * 0.5
- Half_Flat = FLAT/2
- Half_Height = HEIGHT/2
- TopBevelRadius = Half_Flat - 0.05
-
- Global_NutRad = TopBevelRadius
-
- Row = 0;
- Lowest_Z_Vert = 0.0;
-
- verts.append([0.0,0.0,0.0])
-
-
- FaceStart = len(verts)
- #inner hole
-
- x = sin(radians(0))*HOLE_RADIUS
- y = cos(radians(0))*HOLE_RADIUS
- #print ("rad 0 x;", x, "y:" ,y )
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*HOLE_RADIUS
- y = cos(radians(60/6))*HOLE_RADIUS
- #print ("rad 60/6x;", x, "y:" ,y )
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*HOLE_RADIUS
- y = cos(radians(60/3))*HOLE_RADIUS
- #print ("rad 60/3x;", x, "y:" ,y )
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*HOLE_RADIUS
- y = cos(radians(60/2))*HOLE_RADIUS
- #print ("rad 60/2x;", x, "y:" ,y )
- verts.append([x,y,0.0])
- Row += 1
-
-
- #bevel
-
- x = sin(radians(0))*TopBevelRadius
- y = cos(radians(0))*TopBevelRadius
- vec1 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/6))*TopBevelRadius
- y = cos(radians(60/6))*TopBevelRadius
- vec2 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/3))*TopBevelRadius
- y = cos(radians(60/3))*TopBevelRadius
- vec3 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
-
-
- x = sin(radians(60/2))*TopBevelRadius
- y = cos(radians(60/2))*TopBevelRadius
- vec4 = MATHUTILS.Vector([x,y,0.0])
- verts.append([x,y,0.0])
- Row += 1
-
- #Flats
-
- x = tan(radians(0))*Half_Flat
- dvec = vec1 - MATHUTILS.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
-
- x = tan(radians(60/6))*Half_Flat
- dvec = vec2 - MATHUTILS.Vector([x,Half_Flat,0.0])
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
-
- x = tan(radians(60/3))*Half_Flat
- dvec = vec3 - MATHUTILS.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
-
- x = tan(radians(60/2))*Half_Flat
- dvec = vec4 - MATHUTILS.Vector([x,Half_Flat,0.0])
- Lowest_Point = -dvec.length
- verts.append([x,Half_Flat,-dvec.length])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
- Row += 1
-
- #down Bits Tri
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,Lowest_Point])
- Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point)
- Row += 1
-
- #down Bits
-
- x = tan(radians(0))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/6))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/3))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
-
- x = tan(radians(60/2))*Half_Flat
- verts.append([x,Half_Flat,-Half_Height])
- Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height)
- Row += 1
-
- faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
-
- Global_Head_Height = HEIGHT
-
- Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert)
- verts.extend(Tvert)
- faces.extend(tface)
-
-
- Tvert,tface = Mirror_Verts_Faces(verts,faces,'y')
- verts.extend(Tvert)
- faces.extend(tface)
-
- S_verts,S_faces = SpinDup(verts,faces,360,6,'z')
-
- #return verts,faces,TopBevelRadius
- return S_verts,S_faces,TopBevelRadius
-
-
-
-def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0):
- DIV = 36
- verts = []
- faces = []
- Row = 0
-
- INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75))
- EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
- RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
- OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
-
-
- FaceStart = len(verts)
-
- Start_Height = 0 - 3
- Height_Offset = Z_LOCATION
- Lowest_Z_Vert = 0
-
- x = INNER_HOLE
- z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = INNER_HOLE
- z = (Height_Offset - OVER_ALL_HEIGTH)
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- for i in range(180,80,-10):
- x = sin(radians(i))*RAD1
- z = cos(radians(i))*RAD1
- verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- x = OUTSIDE_RADIUS - 0
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
-
- return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert
-
-
-
-def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0):
- DIV = 36
- verts = []
- faces = []
- Row = 0
-
- INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
- EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
- RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
- OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
- PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
- PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
-
- FaceStart = len(verts)
-
- Start_Height = 0 - 3
- Height_Offset = Z_LOCATION
- Lowest_Z_Vert = 0
-
-
- x = INNER_HOLE + EDGE_THICKNESS
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = PART_INNER_HOLE
- z = Height_Offset
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = PART_INNER_HOLE
- z = Height_Offset - PART_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
- x = INNER_HOLE + EDGE_THICKNESS
- z = Height_Offset - PART_THICKNESS
- verts.append([x,0.0,z])
- Lowest_Z_Vert = min(Lowest_Z_Vert,z)
- Row += 1
-
-
- sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
- sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop
-
- faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1))
-
- return sVerts,faces,0 - Lowest_Z_Vert
-
-
-##########################################################################################
-##########################################################################################
-## Create Internal Thread
-##########################################################################################
-##########################################################################################
-
-
-def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Height_Offset = Height_Offset + PITCH #Move the offset up so that the verts start at
- #at the correct place (Height_Start)
-
- Half_Pitch = float(PITCH)/2
- Height_Start = Height_Offset - PITCH
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
- for j in range(1):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z > Height_Start:
- z = Height_Start
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == 0:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
- return Ret_Row,Height_Offset
-
-
-def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
-
-
- Ret_Row = 0;
-
- Half_Pitch = float(PITCH)/2
- #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH
- Height_End = Height_Offset - PITCH
- #Height_End = -2.1
- Height_Step = float(PITCH)/float(DIV)
- Deg_Step = 360.0 /float(DIV)
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
-
- Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
-
- Num = 0
-
- for j in range(2):
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z])
- Height_Offset -= Crest_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,z ])
- Height_Offset -= Crest_to_Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- if j == Num:
- x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- if j > Num:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS)
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
-
- verts.append([x,y,z ])
- Height_Offset -= Root_Height
- Ret_Row += 1
-
-
- for i in range(DIV+1):
- z = Height_Offset - (Height_Step*i)
- if z < Height_End:
- z = Height_End
-
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
-
- if j == Num:
- x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
- if j > Num:
- x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS )
- y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
-
- verts.append([x,y,z ])
- Height_Offset -= Root_to_Crest_Height
- Ret_Row += 1
-
-
- return Ret_Row,Height_End # send back Height End as this is the lowest point
-
-
-def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1):
- verts = []
- faces = []
-
- DIV = 36
-
- INNER_RADIUS = INNER_DIA/2
- OUTTER_RADIUS = OUTTER_DIA/2
-
- Half_Pitch = float(PITCH)/2
- Deg_Step = 360.0 /float(DIV)
- Height_Step = float(PITCH)/float(DIV)
-
- Num = int(round((HEIGHT- PITCH)/PITCH)) # less one pitch for the start and end that is 1/2 pitch high
-
- Col = 0
- Row = 0
-
-
- Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
- Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
- Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
-
- Height_Offset = 0
- FaceStart = len(verts)
-
- Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
- Row += Row_Inc
-
- for j in range(Num):
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Crest_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
- y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Crest_to_Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Root_Height
- Row += 1
-
- for i in range(DIV+1):
- x = sin(radians(i*Deg_Step))*INNER_RADIUS
- y = cos(radians(i*Deg_Step))*INNER_RADIUS
- verts.append([x,y,Height_Offset - (Height_Step*i) ])
- Height_Offset -= Root_to_Crest_Height
- Row += 1
-
-
- Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
- Row += Row_Inc
-
- faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL))
-
- return verts,faces,0 - Height_Offset
-
-
-def Nut_Mesh(props, context):
-
- verts = []
- faces = []
- Head_Verts = []
- Head_Faces= []
- #sc = context.scene
-
- New_Nut_Height = 5
-
- Face_Start = len(verts)
- Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(props.bf_Minor_Dia,props.bf_Major_Dia,props.bf_Pitch,props.bf_Hex_Nut_Height,props.bf_Crest_Percent,props.bf_Root_Percent,1)
- verts.extend(Thread_Verts)
- faces.extend(Copy_Faces(Thread_Faces,Face_Start))
-
- Face_Start = len(verts)
- Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(props.bf_Hex_Nut_Flat_Distance,props.bf_Major_Dia,New_Nut_Height)
- verts.extend((Head_Verts))
- faces.extend(Copy_Faces(Head_Faces,Face_Start))
-
- LowZ = 0 - New_Nut_Height
-
- if props.bf_Nut_Type == 'bf_Nut_Lock':
- Face_Start = len(verts)
- Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height)
- verts.extend((Nylon_Head_Verts))
- faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start))
-
- Face_Start = len(verts)
- Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height)
- verts.extend((Nylon_Verts))
- faces.extend(Copy_Faces(Nylon_faces,Face_Start))
-
-
- return Move_Verts_Up_Z(verts,0 - LowZ),faces
-
-
-
-##########################################################################################
-##########################################################################################
-##########################################################################################
-## Create Bolt
-##########################################################################################
-##########################################################################################
-
-
-
-def Bolt_Mesh(props, context):
-
-
- verts = []
- faces = []
- Bit_Verts = []
- Bit_Faces = []
- Bit_Dia = 0.001
- Head_Verts = []
- Head_Faces= []
- Head_Height = 0.0
- #sc = context.scene
-
- ReSized_Allen_Bit_Flat_Distance = props.bf_Allen_Bit_Flat_Distance # set default
-
-
- Head_Height = props.bf_Hex_Head_Height # will be changed by the Head Functions
-
-
- if props.bf_Bit_Type == 'bf_Bit_Allen' and props.bf_Head_Type == 'bf_Head_Pan':
- #need to size Allen bit if it is too big.
- if Allen_Bit_Dia(props.bf_Allen_Bit_Flat_Distance) > Max_Pan_Bit_Dia(props.bf_Pan_Head_Dia):
- ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(props.bf_Pan_Head_Dia)) * 1.05
- #print ("Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance)
-
- #bit Mesh
- if props.bf_Bit_Type == 'bf_Bit_Allen':
- Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,props.bf_Allen_Bit_Depth)
-
- if props.bf_Bit_Type == 'bf_Bit_Philips':
- Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(props.bf_Philips_Bit_Dia,props.bf_Philips_Bit_Dia*(0.5/1.82),props.bf_Phillips_Bit_Depth)
-
-
- #Head Mesh
-
- if props.bf_Head_Type =='bf_Head_Hex':
- Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(props.bf_Hex_Head_Flat_Distance,Bit_Dia,props.bf_Shank_Dia,props.bf_Hex_Head_Height)
-
- elif props.bf_Head_Type == 'bf_Head_Cap':
- Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,props.bf_Cap_Head_Dia,props.bf_Shank_Dia,props.bf_Cap_Head_Height,props.bf_Cap_Head_Dia*(1.0/19.0),props.bf_Cap_Head_Dia*(1.0/19.0))
-
- elif props.bf_Head_Type =='bf_Head_Dome':
- Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,props.bf_Dome_Head_Dia,props.bf_Shank_Dia,props.bf_Hex_Head_Height,1,1,0)
-
- elif props.bf_Head_Type == 'bf_Head_Pan':
- Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,props.bf_Pan_Head_Dia,props.bf_Shank_Dia,props.bf_Hex_Head_Height,1,1,0)
-
- elif props.bf_Head_Type == 'bf_Head_CounterSink':
- Head_Verts,Head_Faces,Head_Height = Create_CounterSink_Head(Bit_Dia,props.bf_CounterSink_Head_Dia,props.bf_Shank_Dia,props.bf_CounterSink_Head_Dia,props.bf_CounterSink_Head_Dia*(0.09/6.31))
-#Head_Verts,Head_Faces,Head_Height = Create_CounterSink_Head(Bit_Dia,props.bf_CounterSink_Head_Dia,props.bf_Shank_Dia,props.bf_CounterSink_Head_Dia,props.bf_CounterSink_Head_Dia*(1.0/19.0))
-
- Face_Start = len(verts)
- verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height))
- faces.extend(Copy_Faces(Bit_Faces,Face_Start))
-
- Face_Start = len(verts)
- verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height))
- faces.extend(Copy_Faces(Head_Faces,Face_Start))
-
- Face_Start = len(verts)
- Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(props.bf_Shank_Dia,props.bf_Shank_Length,props.bf_Minor_Dia,props.bf_Major_Dia,props.bf_Pitch,props.bf_Thread_Length,props.bf_Crest_Percent,props.bf_Root_Percent)
-
- verts.extend(Move_Verts_Up_Z(Thread_Verts,00))
- faces.extend(Copy_Faces(Thread_Faces,Face_Start))
-
- return Move_Verts_Up_Z(verts,Thread_Height),faces
-
-
-def Create_New_Mesh(props, context, align_matrix):
-
- verts = []
- faces = []
- sMeshName =''
- sObjName =''
-
- if props.bf_Model_Type == 'bf_Model_Bolt':
- #print('Create Bolt')
- verts, faces = Bolt_Mesh(props, context)
- sMeshName = 'Bolt'
- sObjName = 'Bolt'
-
- if props.bf_Model_Type == 'bf_Model_Nut':
- #print('Create Nut')
- verts, faces = Nut_Mesh(props, context)
- sMeshName = 'Nut'
- sObjName = 'Nut'
-
-
- verts, faces = RemoveDoubles(verts, faces)
-
- verts = Scale_Mesh_Verts(verts,GLOBAL_SCALE)
-
-
- mesh = bpy.data.meshes.new(sMeshName)
-
- mesh.vertices.add(len(verts))
- mesh.faces.add(len(faces))
-
- mesh.vertices.foreach_set("co", unpack_list(verts))
- mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces))
-
-
- scene = context.scene
-
- bpy.ops.object.select_all(action='DESELECT')
-
- mesh.update()
- ob_new = bpy.data.objects.new(sObjName, mesh)
- scene.objects.link(ob_new)
- ob_new.select = True
- scene.objects.active = ob_new
-
- #ob_new.location = scene.cursor_location
- ob_new.matrix_world = align_matrix
-
- #print("Created_Object")
- return
-
-
diff --git a/add_mesh_BoltFactory/preset_utils.py b/add_mesh_BoltFactory/preset_utils.py
deleted file mode 100644
index d477b94a..00000000
--- a/add_mesh_BoltFactory/preset_utils.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-
-import bpy
-import os, sys
-
-
-def getPresets():
-
- scriptPath = os.path.join(bpy.utils.script_paths()[0], "addons" , "add_mesh_BoltFactory")
- presetPath = os.path.join(scriptPath, "presets")
- presetFiles = os.listdir(presetPath)
- #presetFiles.sort()
-
- presets = [(presetFile, presetFile.rpartition(".")[0], presetFile)
- for i, presetFile in enumerate(presetFiles)]
-
- #print(presets)
- return presets, presetPath
-
-
-#presets = getPresets()
-
-
-
-def setProps(props, preset, presetsPath):
-
- #bpy.ops.script.python_file_run(filepath=presetsPath + '\\' + preset)
-
- file = open(os.path.join(presetsPath, preset))
-
- for line in file:
- exec(line)
-
- file.close()
-
- return
diff --git a/add_mesh_BoltFactory/presets/M10.py b/add_mesh_BoltFactory/presets/M10.py
deleted file mode 100644
index f2ea9c8d..00000000
--- a/add_mesh_BoltFactory/presets/M10.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 10.0
-#props.bf_Pitch = 1.5 #Coarse
-props.bf_Pitch = 1.25 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 10.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 17.0
-props.bf_Hex_Head_Height = 6.4
-props.bf_Cap_Head_Dia = 16.0
-props.bf_Cap_Head_Height = 10.0
-props.bf_CounterSink_Head_Dia = 20.0
-props.bf_Allen_Bit_Flat_Distance = 8.0
-props.bf_Allen_Bit_Depth = 5.0
-props.bf_Pan_Head_Dia = 20.0
-props.bf_Dome_Head_Dia = 20.0
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 8.0
-props.bf_Hex_Nut_Flat_Distance = 17.0
-props.bf_Thread_Length = 20
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_BoltFactory/presets/M12.py b/add_mesh_BoltFactory/presets/M12.py
deleted file mode 100644
index 44f3876f..00000000
--- a/add_mesh_BoltFactory/presets/M12.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#props.bf_Pitch = 1.75 #Coarse
-props.bf_Pitch = 1.50 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 12.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 19.0
-props.bf_Hex_Head_Height = 7.5
-props.bf_Cap_Head_Dia = 18.5
-props.bf_Cap_Head_Height = 12.0
-props.bf_CounterSink_Head_Dia = 22.0
-props.bf_Allen_Bit_Flat_Distance = 10.0
-props.bf_Allen_Bit_Depth = 6.0
-props.bf_Pan_Head_Dia = 24.0
-props.bf_Dome_Head_Dia = 24.0
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 10.0
-props.bf_Hex_Nut_Flat_Distance = 19.0
-props.bf_Shank_Dia = 12.0
-props.bf_Shank_Length = 33.0
-props.bf_Thread_Length = 32.0
diff --git a/add_mesh_BoltFactory/presets/M3.py b/add_mesh_BoltFactory/presets/M3.py
deleted file mode 100644
index 3e970468..00000000
--- a/add_mesh_BoltFactory/presets/M3.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 3.0
-#props.bf_Pitch = 0.5 #Coarse
-props.bf_Pitch = 0.35 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 3.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 5.5
-props.bf_Hex_Head_Height = 2.0
-props.bf_Cap_Head_Dia = 5.5
-props.bf_Cap_Head_Height = 3.0
-props.bf_CounterSink_Head_Dia = 6.3
-props.bf_Allen_Bit_Flat_Distance = 2.5
-props.bf_Allen_Bit_Depth = 1.5
-props.bf_Pan_Head_Dia = 5.6
-props.bf_Dome_Head_Dia = 5.6
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 2.4
-props.bf_Hex_Nut_Flat_Distance = 5.5
-props.bf_Thread_Length = 6
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_BoltFactory/presets/M4.py b/add_mesh_BoltFactory/presets/M4.py
deleted file mode 100644
index 5682b442..00000000
--- a/add_mesh_BoltFactory/presets/M4.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 4.0
-#props.bf_Pitch = 0.7 #Coarse
-props.bf_Pitch = 0.5 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 4.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 7.0
-props.bf_Hex_Head_Height = 2.8
-props.bf_Cap_Head_Dia = 7.0
-props.bf_Cap_Head_Height = 4.0
-props.bf_CounterSink_Head_Dia = 9.4
-props.bf_Allen_Bit_Flat_Distance = 3.0
-props.bf_Allen_Bit_Depth = 2.0
-props.bf_Pan_Head_Dia = 8.0
-props.bf_Dome_Head_Dia = 8.0
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 3.2
-props.bf_Hex_Nut_Flat_Distance = 7.0
-props.bf_Thread_Length = 8
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_BoltFactory/presets/M5.py b/add_mesh_BoltFactory/presets/M5.py
deleted file mode 100644
index b889f349..00000000
--- a/add_mesh_BoltFactory/presets/M5.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 5.0
-#props.bf_Pitch = 0.8 #Coarse
-props.bf_Pitch = 0.5 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 5.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 8.0
-props.bf_Hex_Head_Height = 3.5
-props.bf_Cap_Head_Dia = 8.5
-props.bf_Cap_Head_Height = 5.0
-props.bf_CounterSink_Head_Dia = 10.4
-props.bf_Allen_Bit_Flat_Distance = 4.0
-props.bf_Allen_Bit_Depth = 2.5
-props.bf_Pan_Head_Dia = 9.5
-props.bf_Dome_Head_Dia = 9.5
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 4.0
-props.bf_Hex_Nut_Flat_Distance = 8.0
-props.bf_Thread_Length = 10
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_BoltFactory/presets/M6.py b/add_mesh_BoltFactory/presets/M6.py
deleted file mode 100644
index 2b11a43d..00000000
--- a/add_mesh_BoltFactory/presets/M6.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 6.0
-#bf_Pitch = 1.0 #Coarse
-props.bf_Pitch = 0.75 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 6.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 10.0
-props.bf_Hex_Head_Height = 4.0
-props.bf_Cap_Head_Dia = 10.0
-props.bf_Cap_Head_Height = 6.0
-props.bf_CounterSink_Head_Dia = 12.6
-props.bf_Allen_Bit_Flat_Distance = 5.0
-props.bf_Allen_Bit_Depth = 3.0
-props.bf_Pan_Head_Dia = 12.0
-props.bf_Dome_Head_Dia = 12.0
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 5.0
-props.bf_Hex_Nut_Flat_Distance = 10.0
-props.bf_Thread_Length = 12
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_BoltFactory/presets/M8.py b/add_mesh_BoltFactory/presets/M8.py
deleted file mode 100644
index 77cbb497..00000000
--- a/add_mesh_BoltFactory/presets/M8.py
+++ /dev/null
@@ -1,22 +0,0 @@
-props.bf_Shank_Dia = 8.0
-#props.bf_Pitch = 1.25 #Coarse
-props.bf_Pitch = 1.00 #Fine
-props.bf_Crest_Percent = 10
-props.bf_Root_Percent = 10
-props.bf_Major_Dia = 8.0
-props.bf_Minor_Dia = props.bf_Major_Dia - (1.082532 * props.bf_Pitch)
-props.bf_Hex_Head_Flat_Distance = 13.0
-props.bf_Hex_Head_Height = 5.3
-props.bf_Cap_Head_Dia = 13.5
-props.bf_Cap_Head_Height = 8.0
-props.bf_CounterSink_Head_Dia = 17.3
-props.bf_Allen_Bit_Flat_Distance = 6.0
-props.bf_Allen_Bit_Depth = 4.0
-props.bf_Pan_Head_Dia = 16.0
-props.bf_Dome_Head_Dia = 16.0
-props.bf_Philips_Bit_Dia = props.bf_Pan_Head_Dia*(1.82/5.6)
-#props.bf_Phillips_Bit_Depth = Get_Phillips_Bit_Height(props.bf_Philips_Bit_Dia)
-props.bf_Hex_Nut_Height = 6.5
-props.bf_Hex_Nut_Flat_Distance = 13.0
-props.bf_Thread_Length = 16
-props.bf_Shank_Length = 0.0
diff --git a/add_mesh_ant_landscape.py b/add_mesh_ant_landscape.py
deleted file mode 100644
index b1b42612..00000000
--- a/add_mesh_ant_landscape.py
+++ /dev/null
@@ -1,913 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "ANT Landscape",
- "author": "Jimmy Hazevoet",
- "version": (0,1,0),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "Add Mesh menu",
- "description": "Adds a landscape primitive",
- "warning": "", # used for warning icon and text in addons panel
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/ANT_Landscape",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=23130&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-'''
-Another Noise Tool: Landscape mesh generator
-
-MESH OPTIONS:
-Mesh update: Turn this on for interactive mesh update.
-Sphere: Generate sphere or a grid mesh. (Turn height falloff off for sphere mesh)
-Smooth: Generate smooth shaded mesh.
-Subdivision: Number of mesh subdivisions, higher numbers gives more detail but also slows down the script.
-Mesh size: X,Y size of the grid mesh (in blender units).
-
-NOISE OPTIONS: ( Most of these options are the same as in blender textures. )
-Random seed: Use this to randomise the origin of the noise function.
-Noise size: Size of the noise.
-Noise type: Available noise types: multiFractal, ridgedMFractal, hybridMFractal, heteroTerrain, Turbulence, Distorted Noise, Cellnoise, Shattered_hTerrain, Marble
-Noise basis: Blender, Perlin, NewPerlin, Voronoi_F1, Voronoi_F2, Voronoi_F3, Voronoi_F4, Voronoi_F2-F1, Voronoi Crackle, Cellnoise
-VLNoise basis: Blender, Perlin, NewPerlin, Voronoi_F1, Voronoi_F2, Voronoi_F3, Voronoi_F4, Voronoi_F2-F1, Voronoi Crackle, Cellnoise
-Distortion: Distortion amount.
-Hard: Hard/Soft turbulence noise.
-Depth: Noise depth, number of frequencies in the fBm.
-Dimension: Musgrave: Fractal dimension of the roughest areas.
-Lacunarity: Musgrave: Gap between successive frequencies.
-Offset: Musgrave: Raises the terrain from sea level.
-Gain: Musgrave: Scale factor.
-Marble Bias: Sin, Tri, Saw
-Marble Sharpnes: Soft, Sharp, Sharper
-Marble Shape: Shape of the marble function: Default, Ring, Swirl, X, Y
-
-HEIGHT OPTIONS:
-Invert: Invert terrain height.
-Height: Scale terrain height.
-Offset: Terrain height offset.
-Falloff: Terrain height falloff: Type 1, Type 2, X, Y
-Sealevel: Flattens terrain below sealevel.
-Platlevel: Flattens terrain above plateau level.
-Strata: Strata amount, number of strata/terrace layers.
-Strata type: Strata types, Smooth, Sharp-sub, Sharp-add
-'''
-
-# import modules
-import bpy
-from bpy.props import *
-from mathutils import *
-from noise import *
-from math import *
-
-
-###------------------------------------------------------------
-# calculates the matrix for the new object depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-###------------------------------------------------------------
-###------------------------------------------------------------
-# some functions for marble_noise
-def sin_bias(a):
- return 0.5 + 0.5 * sin(a)
-
-def tri_bias(a):
- b = 2 * pi
- a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b)))
- return a
-
-def saw_bias(a):
- b = 2 * pi
- n = int(a/b)
- a -= n * b
- if a < 0: a += b
- return a / b
-
-def soft(a):
- return a
-
-def sharp(a):
- return a**0.5
-
-def sharper(a):
- return sharp(sharp(a))
-
-def shapes(x,y,shape=0):
- if shape == 1:
- # ring
- x = x*2
- y = y*2
- s = (-cos(x**2+y**2)/(x**2+y**2+0.5))
- elif shape == 2:
- # swirl
- x = x*2
- y = y*2
- s = (( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ) / (x**2+y**2+0.5))
- elif shape == 3:
- # bumps
- x = x*2
- y = y*2
- s = ((cos( x*pi ) + cos( y*pi ))-0.5)
- elif shape == 4:
- # y grad.
- s = (y*pi)
- elif shape == 5:
- # x grad.
- s = (x*pi)
- else:
- # marble
- s = ((x+y)*5)
- return s
-
-# marble_noise
-def marble_noise(x,y,z, origin, size, shape, bias, sharpnes, turb, depth, hard, basis ):
- x = x / size
- y = y / size
- z = z / size
- s = shapes(x,y,shape)
-
- x += origin[0]
- y += origin[1]
- z += origin[2]
- value = s + turb * turbulence_vector((x,y,z), depth, hard, basis )[0]
-
- if bias == 1:
- value = tri_bias( value )
- elif bias == 2:
- value = saw_bias( value )
- else:
- value = sin_bias( value )
-
- if sharpnes == 1:
- value = sharp( value )
- elif sharpnes == 2:
- value = sharper( value )
- else:
- value = soft( value )
-
- return value
-
-###------------------------------------------------------------
-# custom noise types
-
-# shattered_hterrain:
-def shattered_hterrain( x,y,z, H, lacunarity, octaves, offset, distort, basis ):
- d = ( turbulence_vector( ( x, y, z ), 6, 0, 0 )[0] * 0.5 + 0.5 )*distort*0.5
- t1 = ( turbulence_vector( ( x+d, y+d, z ), 0, 0, 7 )[0] + 0.5 )
- t2 = ( hetero_terrain(( x*2, y*2, z*2 ), H, lacunarity, octaves, offset, basis )*0.5 )
- return (( t1*t2 )+t2*0.5) * 0.5
-
-# strata_hterrain
-def strata_hterrain( x,y,z, H, lacunarity, octaves, offset, distort, basis ):
- value = hetero_terrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5
- steps = ( sin( value*(distort*5)*pi ) * ( 0.1/(distort*5)*pi ) )
- return ( value * (1.0-0.5) + steps*0.5 )
-
-###------------------------------------------------------------
-# landscape_gen
-def landscape_gen(x,y,z,falloffsize,options=[0,1.0,1, 0,0,1.0,0,6,1.0,2.0,1.0,2.0,0,0,0, 1.0,0.0,1,0.0,1.0,0,0,0]):
-
- # options
- rseed = options[0]
- nsize = options[1]
- ntype = int( options[2][0] )
- nbasis = int( options[3][0] )
- vlbasis = int( options[4][0] )
- distortion = options[5]
- hardnoise = options[6]
- depth = options[7]
- dimension = options[8]
- lacunarity = options[9]
- offset = options[10]
- gain = options[11]
- marblebias = int( options[12][0] )
- marblesharpnes = int( options[13][0] )
- marbleshape = int( options[14][0] )
- invert = options[15]
- height = options[16]
- heightoffset = options[17]
- falloff = int( options[18][0] )
- sealevel = options[19]
- platlevel = options[20]
- strata = options[21]
- stratatype = options[22]
- sphere = options[23]
-
- # origin
- if rseed == 0:
- origin = 0.0,0.0,0.0
- origin_x = 0.0
- origin_y = 0.0
- origin_z = 0.0
- else:
- # randomise origin
- seed_set( rseed )
- origin = random_unit_vector()
- origin_x = ( 0.5 - origin[0] ) * 1000.0
- origin_y = ( 0.5 - origin[1] ) * 1000.0
- origin_z = ( 0.5 - origin[2] ) * 1000.0
-
- # adjust noise size and origin
- ncoords = ( x / nsize + origin_x, y / nsize + origin_y, z / nsize + origin_z )
-
- # noise basis type's
- if nbasis == 9: nbasis = 14 # to get cellnoise basis you must set 14 instead of 9
- if vlbasis ==9: vlbasis = 14
- # noise type's
- if ntype == 0: value = multi_fractal( ncoords, dimension, lacunarity, depth, nbasis ) * 0.5
- elif ntype == 1: value = ridged_multi_fractal( ncoords, dimension, lacunarity, depth, offset, gain, nbasis ) * 0.5
- elif ntype == 2: value = hybrid_multi_fractal( ncoords, dimension, lacunarity, depth, offset, gain, nbasis ) * 0.5
- elif ntype == 3: value = hetero_terrain( ncoords, dimension, lacunarity, depth, offset, nbasis ) * 0.25
- elif ntype == 4: value = fractal( ncoords, dimension, lacunarity, depth, nbasis )
- elif ntype == 5: value = turbulence_vector( ncoords, depth, hardnoise, nbasis )[0]
- elif ntype == 6: value = vl_vector( ncoords, distortion, nbasis, vlbasis ) + 0.5
- elif ntype == 7: value = marble_noise( x*2.0/falloffsize,y*2.0/falloffsize,z*2/falloffsize, origin, nsize, marbleshape, marblebias, marblesharpnes, distortion, depth, hardnoise, nbasis )
- elif ntype == 8: value = shattered_hterrain( ncoords[0], ncoords[1], ncoords[2], dimension, lacunarity, depth, offset, distortion, nbasis )
- elif ntype == 9: value = strata_hterrain( ncoords[0], ncoords[1], ncoords[2], dimension, lacunarity, depth, offset, distortion, nbasis )
- else:
- value = 0.0
-
- # adjust height
- if invert !=0:
- value = (1-value) * height + heightoffset
- else:
- value = value * height + heightoffset
-
- # edge falloff
- if sphere == 0: # no edge falloff if spherical
- if falloff != 0:
- fallofftypes = [ 0, sqrt((x*x)**2+(y*y)**2), sqrt(x*x+y*y), sqrt(y*y), sqrt(x*x) ]
- dist = fallofftypes[ falloff]
- if falloff ==1:
- radius = (falloffsize/2)**2
- else:
- radius = falloffsize/2
- value = value - sealevel
- if( dist < radius ):
- dist = dist / radius
- dist = ( (dist) * (dist) * ( 3-2*(dist) ) )
- value = ( value - value * dist ) + sealevel
- else:
- value = sealevel
-
- # strata / terrace / layered
- if stratatype !='0':
- strata = strata / height
- if stratatype == '1':
- strata *= 2
- steps = ( sin( value*strata*pi ) * ( 0.1/strata*pi ) )
- value = ( value * (1.0-0.5) + steps*0.5 ) * 2.0
- elif stratatype == '2':
- steps = -abs( sin( value*(strata)*pi ) * ( 0.1/(strata)*pi ) )
- value =( value * (1.0-0.5) + steps*0.5 ) * 2.0
- elif stratatype == '3':
- steps = abs( sin( value*(strata)*pi ) * ( 0.1/(strata)*pi ) )
- value =( value * (1.0-0.5) + steps*0.5 ) * 2.0
- else:
- value = value
-
- # clamp height
- if ( value < sealevel ): value = sealevel
- if ( value > platlevel ): value = platlevel
-
- return value
-
-
-# generate grid
-def grid_gen( sub_d, size_me, options ):
-
- verts = []
- faces = []
- edgeloop_prev = []
-
- delta = size_me / float(sub_d - 1)
- start = -(size_me / 2.0)
-
- for row_x in range(sub_d):
- edgeloop_cur = []
- x = start + row_x * delta
- for row_y in range(sub_d):
- y = start + row_y * delta
- z = landscape_gen(x,y,0.0,size_me,options)
-
- edgeloop_cur.append(len(verts))
- verts.append((x,y,z))
-
- if len(edgeloop_prev) > 0:
- faces_row = createFaces(edgeloop_prev, edgeloop_cur)
- faces.extend(faces_row)
-
- edgeloop_prev = edgeloop_cur
-
- return verts, faces
-
-
-# generate sphere
-def sphere_gen( sub_d, size_me, options ):
-
- verts = []
- faces = []
- edgeloop_prev = []
-
- for row_x in range(sub_d):
- edgeloop_cur = []
- for row_y in range(sub_d):
- u = sin(row_y*pi*2/(sub_d-1)) * cos(-pi/2+row_x*pi/(sub_d-1)) * size_me/2
- v = cos(row_y*pi*2/(sub_d-1)) * cos(-pi/2+row_x*pi/(sub_d-1)) * size_me/2
- w = sin(-pi/2+row_x*pi/(sub_d-1)) * size_me/2
- h = landscape_gen(u,v,w,size_me,options) / size_me
- u,v,w = u+u*h, v+v*h, w+w*h
-
- edgeloop_cur.append(len(verts))
- verts.append((u, v, w))
-
- if len(edgeloop_prev) > 0:
- faces_row = createFaces(edgeloop_prev, edgeloop_cur)
- faces.extend(faces_row)
-
- edgeloop_prev = edgeloop_cur
-
- return verts, faces
-
-
-###------------------------------------------------------------
-# Add landscape
-class landscape_add(bpy.types.Operator):
- '''Add a landscape mesh'''
- bl_idname = "Add_landscape"
- bl_label = "Landscape"
- bl_options = {'REGISTER', 'UNDO'}
- bl_description = "Add landscape mesh"
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- # align_matrix for the invoke
- align_matrix = Matrix()
-
- # properties
- AutoUpdate = BoolProperty(name="Mesh update",
- default=True,
- description="Update mesh")
-
- SphereMesh = BoolProperty(name="Sphere",
- default=False,
- description="Generate Sphere mesh")
-
- SmoothMesh = BoolProperty(name="Smooth",
- default=True,
- description="Shade smooth")
-
- Subdivision = IntProperty(name="Subdivisions",
- min=4,
- max=6400,
- default=64,
- description="Mesh x y subdivisions")
-
- MeshSize = FloatProperty(name="Mesh Size",
- min=0.01,
- max=100000.0,
- default=2.0,
- description="Mesh size")
-
- RandomSeed = IntProperty(name="Random Seed",
- min=0,
- max=9999,
- default=0,
- description="Randomize noise origin")
-
- NoiseSize = FloatProperty(name="Noise Size",
- min=0.01,
- max=10000.0,
- default=1.0,
- description="Noise size")
-
- NoiseTypes = [
- ("0","multiFractal","multiFractal"),
- ("1","ridgedMFractal","ridgedMFractal"),
- ("2","hybridMFractal","hybridMFractal"),
- ("3","heteroTerrain","heteroTerrain"),
- ("4","fBm","fBm"),
- ("5","Turbulence","Turbulence"),
- ("6","Distorted Noise","Distorted Noise"),
- ("7","Marble","Marble"),
- ("8","Shattered_hTerrain","Shattered_hTerrain"),
- ("9","Strata_hTerrain","Strata_hTerrain")]
-
- NoiseType = EnumProperty(name="Type",
- description="Noise type",
- items=NoiseTypes)
-
- BasisTypes = [
- ("0","Blender","Blender"),
- ("1","Perlin","Perlin"),
- ("2","NewPerlin","NewPerlin"),
- ("3","Voronoi_F1","Voronoi_F1"),
- ("4","Voronoi_F2","Voronoi_F2"),
- ("5","Voronoi_F3","Voronoi_F3"),
- ("6","Voronoi_F4","Voronoi_F4"),
- ("7","Voronoi_F2-F1","Voronoi_F2-F1"),
- ("8","Voronoi Crackle","Voronoi Crackle"),
- ("9","Cellnoise","Cellnoise")]
- BasisType = EnumProperty(name="Basis",
- description="Noise basis",
- items=BasisTypes)
-
- VLBasisTypes = [
- ("0","Blender","Blender"),
- ("1","Perlin","Perlin"),
- ("2","NewPerlin","NewPerlin"),
- ("3","Voronoi_F1","Voronoi_F1"),
- ("4","Voronoi_F2","Voronoi_F2"),
- ("5","Voronoi_F3","Voronoi_F3"),
- ("6","Voronoi_F4","Voronoi_F4"),
- ("7","Voronoi_F2-F1","Voronoi_F2-F1"),
- ("8","Voronoi Crackle","Voronoi Crackle"),
- ("9","Cellnoise","Cellnoise")]
- VLBasisType = EnumProperty(name="VLBasis",
- description="VLNoise basis",
- items=VLBasisTypes)
-
- Distortion = FloatProperty(name="Distortion",
- min=0.01,
- max=1000.0,
- default=1.0,
- description="Distortion amount")
-
- HardNoise = BoolProperty(name="Hard",
- default=True,
- description="Hard noise")
-
- NoiseDepth = IntProperty(name="Depth",
- min=1,
- max=16,
- default=6,
- description="Noise Depth - number of frequencies in the fBm.")
-
- mDimension = FloatProperty(name="Dimension",
- min=0.01,
- max=2.0,
- default=1.0,
- description="H - fractal dimension of the roughest areas.")
-
- mLacunarity = FloatProperty(name="Lacunarity",
- min=0.01,
- max=6.0,
- default=2.0,
- description="Lacunarity - gap between successive frequencies.")
-
- mOffset = FloatProperty(name="Offset",
- min=0.01,
- max=6.0,
- default=1.0,
- description="Offset - raises the terrain from sea level.")
-
- mGain = FloatProperty(name="Gain",
- min=0.01,
- max=6.0,
- default=1.0,
- description="Gain - scale factor.")
-
- BiasTypes = [
- ("0","Sin","Sin"),
- ("1","Tri","Tri"),
- ("2","Saw","Saw")]
- MarbleBias = EnumProperty(name="Bias",
- description="Marble bias",
- items=BiasTypes)
-
- SharpTypes = [
- ("0","Soft","Soft"),
- ("1","Sharp","Sharp"),
- ("2","Sharper","Sharper")]
- MarbleSharp = EnumProperty(name="Sharp",
- description="Marble sharp",
- items=SharpTypes)
-
- ShapeTypes = [
- ("0","Default","Default"),
- ("1","Ring","Ring"),
- ("2","Swirl","Swirl"),
- ("3","Bump","Bump"),
- ("4","Y","Y"),
- ("5","X","X")]
- MarbleShape = EnumProperty(name="Shape",
- description="Marble shape",
- items=ShapeTypes)
-
- Invert = BoolProperty(name="Invert",
- default=False,
- description="Invert noise input")
-
- Height = FloatProperty(name="Height",
- min=0.01,
- max=10000.0,
- default=0.5,
- description="Height scale")
-
- Offset = FloatProperty(name="Offset",
- min=-10000.0,
- max=10000.0,
- default=0.0,
- description="Height offset")
-
- fallTypes = [
- ("0","None","None"),
- ("1","Type 1","Type 1"),
- ("2","Type 2","Type 2"),
- ("3","Y","Y"),
- ("4","X","X")]
- Falloff = EnumProperty(name="Falloff",
- description="Edge falloff",
- default="1",
- items=fallTypes)
-
- Sealevel = FloatProperty(name="Sealevel",
- min=-10000.0,
- max=10000.0,
- default=0.0,
- description="Sealevel")
-
- Plateaulevel = FloatProperty(name="Plateau",
- min=-10000.0,
- max=10000.0,
- default=1.0,
- description="Plateau level")
-
- Strata = FloatProperty(name="Strata",
- min=0.01,
- max=1000.0,
- default=3.0,
- description="Strata amount")
-
- StrataTypes = [
- ("0","None","None"),
- ("1","Type 1","Type 1"),
- ("2","Type 2","Type 2"),
- ("3","Type 3","Type 3")]
- StrataType = EnumProperty(name="Strata",
- description="Strata type",
- default="0",
- items=StrataTypes)
-
- ###------------------------------------------------------------
- # Draw
- def draw(self, context):
- props = self.properties
- layout = self.layout
-
- box = layout.box()
- box.prop(props, 'AutoUpdate')
- box.prop(props, 'SphereMesh')
- box.prop(props, 'SmoothMesh')
- box.prop(props, 'Subdivision')
- box.prop(props, 'MeshSize')
-
- box = layout.box()
- box.prop(props, 'NoiseType')
- if props.NoiseType != '7':
- box.prop(props, 'BasisType')
- box.prop(props, 'RandomSeed')
- box.prop(props, 'NoiseSize')
- if props.NoiseType == '0':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- if props.NoiseType == '1':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- box.prop(props, 'mOffset')
- box.prop(props, 'mGain')
- if props.NoiseType == '2':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- box.prop(props, 'mOffset')
- box.prop(props, 'mGain')
- if props.NoiseType == '3':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- box.prop(props, 'mOffset')
- if props.NoiseType == '4':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- if props.NoiseType == '5':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'HardNoise')
- if props.NoiseType == '6':
- box.prop(props, 'VLBasisType')
- box.prop(props, 'Distortion')
- if props.NoiseType == '7':
- box.prop(props, 'MarbleShape')
- box.prop(props, 'MarbleBias')
- box.prop(props, 'MarbleSharp')
- box.prop(props, 'Distortion')
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'HardNoise')
- if props.NoiseType == '8':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- box.prop(props, 'mOffset')
- box.prop(props, 'Distortion')
- if props.NoiseType == '9':
- box.prop(props, 'NoiseDepth')
- box.prop(props, 'mDimension')
- box.prop(props, 'mLacunarity')
- box.prop(props, 'mOffset')
- box.prop(props, 'Distortion')
-
- box = layout.box()
- box.prop(props, 'Invert')
- box.prop(props, 'Height')
- box.prop(props, 'Offset')
- box.prop(props, 'Plateaulevel')
- box.prop(props, 'Sealevel')
- if props.SphereMesh == False:
- box.prop(props, 'Falloff')
- box.prop(props, 'StrataType')
- if props.StrataType != '0':
- box.prop(props, 'Strata')
-
- ###------------------------------------------------------------
- # Execute
- def execute(self, context):
-
- props = self.properties
- edit = props.edit
-
- #mesh update
- if props.AutoUpdate != 0:
-
- # turn off undo
- undo = bpy.context.user_preferences.edit.use_global_undo
- bpy.context.user_preferences.edit.use_global_undo = False
-
- # deselect all objects
- bpy.ops.object.select_all(action='DESELECT')
-
- # options
- options = [
- props.RandomSeed, #0
- props.NoiseSize, #1
- props.NoiseType, #2
- props.BasisType, #3
- props.VLBasisType, #4
- props.Distortion, #5
- props.HardNoise, #6
- props.NoiseDepth, #7
- props.mDimension, #8
- props.mLacunarity, #9
- props.mOffset, #10
- props.mGain, #11
- props.MarbleBias, #12
- props.MarbleSharp, #13
- props.MarbleShape, #14
- props.Invert, #15
- props.Height, #16
- props.Offset, #17
- props.Falloff, #18
- props.Sealevel, #19
- props.Plateaulevel, #20
- props.Strata, #21
- props.StrataType, #22
- props.SphereMesh #23
- ]
-
- # Main function
- if props.SphereMesh !=0:
- # sphere
- verts, faces = sphere_gen( props.Subdivision, props.MeshSize, options )
- else:
- # grid
- verts, faces = grid_gen( props.Subdivision, props.MeshSize, options )
-
- # create mesh object
- obj = create_mesh_object(context, verts, [], faces, "Landscape", edit, self.align_matrix)
-
- # sphere, remove doubles
- if props.SphereMesh !=0:
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.remove_doubles(limit=0.0001)
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Shade smooth
- if props.SmoothMesh !=0:
- bpy.ops.object.shade_smooth()
-
- # restore pre operator undo state
- bpy.context.user_preferences.edit.use_global_undo = undo
-
- return {'FINISHED'}
- else:
- return {'PASS_THROUGH'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-###------------------------------------------------------------
-# Register
-import space_info
-
- # Define "Landscape" menu
-def menu_func_landscape(self, context):
- self.layout.operator(landscape_add.bl_idname, text="Landscape", icon="PLUGIN")
-
-def register():
- space_info.INFO_MT_mesh_add.append(menu_func_landscape)
-
-def unregister():
- space_info.INFO_MT_mesh_add.remove(menu_func_landscape)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_extras.py b/add_mesh_extras.py
deleted file mode 100644
index 1df801b2..00000000
--- a/add_mesh_extras.py
+++ /dev/null
@@ -1,776 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Extras",
- "author": "Pontiac, Fourmadmen, meta-androcto",
- "version": (0,3),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Extras",
- "description": "Adds Star, Wedge, Sqorus & Spindle objects.",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Extra",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22457&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-import bpy
-from mathutils import *
-from math import *
-from bpy.props import *
-
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-# @todo Clean up vertex&face creation process a bit.
-def add_sqorus(hole_size, subdivide):
- verts = []
- faces = []
-
- size = 2.0
-
- thickness = (size - hole_size) / 2.0
- distances = [
- -size / 2.0,
- -size / 2.0 + thickness,
- size / 2.0 - thickness,
- size / 2.0]
-
- if subdivide:
- for i in range(4):
- y = distances[i]
-
- for j in range(4):
- x = distances[j]
-
- verts.append(Vector((x, y, size / 2.0)))
- verts.append(Vector((x, y, -size / 2.0)))
-
- # Top outer loop (vertex indices)
- vIdx_out_up = [0, 2, 4, 6, 14, 22, 30, 28, 26, 24, 16, 8]
- # Lower outer loop (vertex indices)
- vIdx_out_low = [i + 1 for i in vIdx_out_up]
-
- faces_outside = createFaces(vIdx_out_up, vIdx_out_low, closed=True)
- faces.extend(faces_outside)
-
- # Top inner loop (vertex indices)
- vIdx_inner_up = [10, 12, 20, 18]
-
- # Lower inner loop (vertex indices)
- vIdx_inner_low = [i + 1 for i in vIdx_inner_up]
-
- faces_inside = createFaces(vIdx_inner_up, vIdx_inner_low,
- closed=True, flipped=True)
- faces.extend(faces_inside)
-
- row1_top = [0, 8, 16, 24]
- row2_top = [i + 2 for i in row1_top]
- row3_top = [i + 2 for i in row2_top]
- row4_top = [i + 2 for i in row3_top]
-
- faces_top1 = createFaces(row1_top, row2_top)
- faces.extend(faces_top1)
- faces_top2_side1 = createFaces(row2_top[:2], row3_top[:2])
- faces.extend(faces_top2_side1)
- faces_top2_side2 = createFaces(row2_top[2:], row3_top[2:])
- faces.extend(faces_top2_side2)
- faces_top3 = createFaces(row3_top, row4_top)
- faces.extend(faces_top3)
-
- row1_bot = [1, 9, 17, 25]
- row2_bot = [i + 2 for i in row1_bot]
- row3_bot = [i + 2 for i in row2_bot]
- row4_bot = [i + 2 for i in row3_bot]
-
- faces_bot1 = createFaces(row1_bot, row2_bot, flipped=True)
- faces.extend(faces_bot1)
- faces_bot2_side1 = createFaces(row2_bot[:2], row3_bot[:2],
- flipped=True)
- faces.extend(faces_bot2_side1)
- faces_bot2_side2 = createFaces(row2_bot[2:], row3_bot[2:],
- flipped=True)
- faces.extend(faces_bot2_side2)
- faces_bot3 = createFaces(row3_bot, row4_bot, flipped=True)
- faces.extend(faces_bot3)
-
- else:
- # Do not subdivde outer faces
-
- vIdx_out_up = []
- vIdx_out_low = []
- vIdx_in_up = []
- vIdx_in_low = []
-
- for i in range(4):
- y = distances[i]
-
- for j in range(4):
- x = distances[j]
-
- append = False
- inner = False
- # Outer
- if (i in [0, 3] and j in [0, 3]):
- append = True
-
- # Inner
- if (i in [1, 2] and j in [1, 2]):
- append = True
- inner = True
-
- if append:
- vert_up = len(verts)
- verts.append(Vector((x, y, size / 2.0)))
- vert_low = len(verts)
- verts.append(Vector((x, y, -size / 2.0)))
-
- if inner:
- vIdx_in_up.append(vert_up)
- vIdx_in_low.append(vert_low)
-
- else:
- vIdx_out_up.append(vert_up)
- vIdx_out_low.append(vert_low)
-
- # Flip last two vertices
- vIdx_out_up = vIdx_out_up[:2] + list(reversed(vIdx_out_up[2:]))
- vIdx_out_low = vIdx_out_low[:2] + list(reversed(vIdx_out_low[2:]))
- vIdx_in_up = vIdx_in_up[:2] + list(reversed(vIdx_in_up[2:]))
- vIdx_in_low = vIdx_in_low[:2] + list(reversed(vIdx_in_low[2:]))
-
- # Create faces
- faces_top = createFaces(vIdx_in_up, vIdx_out_up, closed=True)
- faces.extend(faces_top)
- faces_bottom = createFaces(vIdx_out_low, vIdx_in_low, closed=True)
- faces.extend(faces_bottom)
- faces_inside = createFaces(vIdx_in_low, vIdx_in_up, closed=True)
- faces.extend(faces_inside)
- faces_outside = createFaces(vIdx_out_up, vIdx_out_low, closed=True)
- faces.extend(faces_outside)
-
- return verts, faces
-
-
-def add_wedge(size_x, size_y, size_z):
- verts = []
- faces = []
-
- size_x /= 2.0
- size_y /= 2.0
- size_z /= 2.0
-
- vIdx_top = []
- vIdx_bot = []
-
- vIdx_top.append(len(verts))
- verts.append(Vector((-size_x, -size_y, size_z)))
- vIdx_bot.append(len(verts))
- verts.append(Vector((-size_x, -size_y, -size_z)))
-
- vIdx_top.append(len(verts))
- verts.append(Vector((size_x, -size_y, size_z)))
- vIdx_bot.append(len(verts))
- verts.append(Vector((size_x, -size_y, -size_z)))
-
- vIdx_top.append(len(verts))
- verts.append(Vector((-size_x, size_y, size_z)))
- vIdx_bot.append(len(verts))
- verts.append(Vector((-size_x, size_y, -size_z)))
-
- faces.append(vIdx_top)
- faces.append(vIdx_bot)
- faces_outside = createFaces(vIdx_top, vIdx_bot, closed=True)
- faces.extend(faces_outside)
-
- return verts, faces
-
-def add_spindle(segments, radius, height, cap_height):
- verts = []
- faces = []
-
- tot_verts = segments * 2 + 2
-
- half_height = height / 2.0
-
- # Upper tip
- idx_upper_tip = len(verts)
- verts.append(Vector((0, 0, half_height + cap_height)))
-
- # Lower tip
- idx_lower_tip = len(verts)
- verts.append(Vector((0.0, 0.0, -half_height - cap_height)))
-
- upper_edgeloop = []
- lower_edgeloop = []
- for index in range(segments):
- mtx = Matrix.Rotation(2.0 * pi * float(index) / segments, 3, 'Z')
-
- # Calculate index & location of upper verte4x tip.
- idx_up = len(verts)
- upper_edgeloop.append(idx_up)
- verts.append(Vector((radius, 0.0, half_height)) * mtx)
-
- if height > 0:
- idx_low = len(verts)
- lower_edgeloop.append(idx_low)
- verts.append(Vector((radius, 0.0, -half_height)) * mtx)
-
- # Create faces for the upper tip.
- tip_up_faces = createFaces([idx_upper_tip], upper_edgeloop,
- closed=True, flipped=True)
- faces.extend(tip_up_faces)
-
- if height > 0:
- # Create faces for the middle cylinder.
- cyl_faces = createFaces(lower_edgeloop, upper_edgeloop, closed=True)
- faces.extend(cyl_faces)
-
- # Create faces for the lower tip.
- tip_low_faces = createFaces([idx_lower_tip], lower_edgeloop,
- closed=True)
- faces.extend(tip_low_faces)
-
- else:
- # Skipping middle part/cylinder (height=0).
-
- # Create faces for the lower tip.
- tip_low_faces = createFaces([idx_lower_tip], upper_edgeloop,
- closed=True)
- faces.extend(tip_low_faces)
-
- return verts, faces
-
-def add_star(points, outer_radius, inner_radius, height):
- PI_2 = pi * 2
- z_axis = (0, 0, 1)
-
- verts = []
- faces = []
-
- segments = points * 2
-
- half_height = height / 2.0
-
- vert_idx_top = len(verts)
- verts.append(Vector((0.0, 0.0, half_height)))
-
- vert_idx_bottom = len(verts)
- verts.append(Vector((0.0, 0.0, -half_height)))
-
- edgeloop_top = []
- edgeloop_bottom = []
-
- for index in range(segments):
- quat = Quaternion(z_axis, (index / segments) * PI_2)
-
- if index % 2:
- # Uneven
- radius = outer_radius
- else:
- # Even
- radius = inner_radius
-
- edgeloop_top.append(len(verts))
- vec = Vector((radius, 0, half_height)) * quat
- verts.append(vec)
-
- edgeloop_bottom.append(len(verts))
- vec = Vector((radius, 0, -half_height)) * quat
- verts.append(vec)
-
-
-
- faces_top = createFaces([vert_idx_top], edgeloop_top, closed=True)
- faces_outside = createFaces(edgeloop_top, edgeloop_bottom, closed=True)
- faces_bottom = createFaces([vert_idx_bottom], edgeloop_bottom,
- flipped=True, closed=True)
-
- faces.extend(faces_top)
- faces.extend(faces_outside)
- faces.extend(faces_bottom)
-
- return verts, faces
-
-def trapezohedron(s,r,h):
- """
- s = segments
- r = base radius
- h = tip height
- """
-
- # calculate constants
- a = 2*pi/(2*s) # angle between points along the equator
- l = r*cos(a) # helper for e
- e = h*(r-l)/(l+r) # the z offset for each vector along the equator so faces are planar
-
- # rotation for the points
- quat = Quaternion((0,0,1),a)
-
- # first 3 vectors, every next one is calculated from the last, and the z-value is negated
- verts = [Vector(i) for i in [(0,0,h),(0,0,-h),(r,0,e)]]
- for i in range(2*s-1):
- verts.append(verts[-1]*quat) # rotate further "a" radians around the z-axis
- verts[-1].z *= -1 # negate last z-value to account for the zigzag
-
- faces = []
- for i in range(2,2+2*s,2):
- n = [i+1,i+2,i+3] # vertices in current section
- for j in range(3): # check whether the numbers dont go over len(verts)
- if n[j]>=2*s+2: n[j]-=2*s # if so, subtract len(verts)-2
-
- # add faces of current section
- faces.append([0,i]+n[:2])
- faces.append([1,n[2],n[1],n[0]])
-
- return verts,faces
-
-class AddSqorus(bpy.types.Operator):
- '''Add a sqorus mesh.'''
- bl_idname = "mesh.primitive_sqorus_add"
- bl_label = "Add Sqorus"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- hole_size = FloatProperty(name="Hole Size",
- description="Size of the Hole",
- min=0.01,
- max=1.99,
- default=2.0 / 3.0)
- subdivide = BoolProperty(name="Subdivide Outside",
- description="Enable to subdivide the faces on the outside." \
- " This results in equally spaced vertices.",
- default=True)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- # Create mesh geometry
- verts, faces = add_sqorus(
- props.hole_size,
- props.subdivide)
-
- # Create mesh object (and meshdata)
- obj = create_mesh_object(context, verts, [], faces, "Sqorus",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddWedge(bpy.types.Operator):
- '''Add a wedge mesh.'''
- bl_idname = "mesh.primitive_wedge_add"
- bl_label = "Add Wedge"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- size_x = FloatProperty(name="Size X",
- description="Size along the X axis",
- min=0.01,
- max=9999.0,
- default=2.0)
- size_y = FloatProperty(name="Size Y",
- description="Size along the Y axis",
- min=0.01,
- max=9999.0,
- default=2.0)
- size_z = FloatProperty(name="Size Z",
- description="Size along the Z axis",
- min=0.01,
- max=9999.0,
- default=2.00)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- verts, faces = add_wedge(
- props.size_x,
- props.size_y,
- props.size_z)
-
- obj = create_mesh_object(context, verts, [], faces, "Wedge",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddSpindle(bpy.types.Operator):
- '''Add a spindle mesh.'''
- bl_idname = "mesh.primitive_spindle_add"
- bl_label = "Add Spindle"
- bl_description = "Create a spindle mesh."
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- segments = IntProperty(name="Segments",
- description="Number of segments of the spindle",
- min=3,
- max=512,
- default=32)
- radius = FloatProperty(name="Radius",
- description="Radius of the spindle",
- min=0.01,
- max=9999.0,
- default=1.0)
- height = FloatProperty(name="Height",
- description="Height of the spindle",
- min=0.0,
- max=100.0,
- default=1.0)
- cap_height = FloatProperty(name="Cap Height",
- description="Cap height of the spindle",
- min=-9999.0,
- max=9999.0,
- default=0.5)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- verts, faces = add_spindle(
- props.segments,
- props.radius,
- props.height,
- props.cap_height)
-
- obj = create_mesh_object(context, verts, [], faces, "Spindle",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddStar(bpy.types.Operator):
- '''Add a star mesh.'''
- bl_idname = "mesh.primitive_star_add"
- bl_label = "Add Star"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- points = IntProperty(name="Points",
- description="Number of points for the star",
- min=2,
- max=256,
- default=5)
- outer_radius = FloatProperty(name="Outer Radius",
- description="Outer radius of the star",
- min=0.01,
- max=9999.0,
- default=1.0)
- innter_radius = FloatProperty(name="Inner Radius",
- description="Inner radius of the star",
- min=0.01,
- max=9999.0,
- default=0.5)
- height = FloatProperty(name="Height",
- description="Height of the star",
- min=0.01,
- max=9999.0,
- default=0.5)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- verts, faces = add_star(
- props.points,
- props.outer_radius,
- props.innter_radius,
- props.height)
-
- obj = create_mesh_object(context, verts, [], faces, "Star",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddTrapezohedron(bpy.types.Operator):
- """Add a trapezohedron"""
- bl_idname = "mesh.primitive_trapezohedron_add"
- bl_label = "Add trapezohedron"
- bl_description = "Create one of the regular solids"
- bl_options = {'REGISTER', 'UNDO'}
-
- segments = IntProperty(name = "Segments",
- description = "Number of repeated segments",
- default = 4, min = 2, max = 256)
- radius = FloatProperty(name = "Base radius",
- description = "Radius of the middle",
- default = 1.0, min = 0.01, max = 100.0)
- height = FloatProperty(name = "Tip height",
- description = "Height of the tip",
- default = 1, min = 0.01, max = 100.0)
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- align_matrix = Matrix()
- def execute(self,context):
- props = self.properties
- # generate mesh
- verts,faces = trapezohedron(props.segments,
- props.radius,
- props.height)
-
- obj = create_mesh_object(context, verts, [], faces, "Trapazohedron",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
-class INFO_MT_mesh_extras_add(bpy.types.Menu):
- # Define the "Extras" menu
- bl_idname = "INFO_MT_mesh_extras_add"
- bl_label = "Extras"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.primitive_sqorus_add",
- text="Sqorus")
- layout.operator("mesh.primitive_wedge_add",
- text="Wedge")
- layout.operator("mesh.primitive_spindle_add",
- text="Spindle")
- layout.operator("mesh.primitive_star_add",
- text="Star")
- layout.operator("mesh.primitive_trapezohedron_add",
- text="Trapezohedron")
-
-
-# Register all operators and panels
-import space_info
-
-# Define "Gemstones" menu
-def menu_func(self, context):
- self.layout.menu("INFO_MT_mesh_extras_add", icon="PLUGIN")
-
-
-def register():
- # Add "Gemstones" menu to the "Add Mesh" menu
- space_info.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- # Remove "Gemstones" menu from the "Add Mesh" menu.
- space_info.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_gears.py b/add_mesh_gears.py
deleted file mode 100644
index 6063b035..00000000
--- a/add_mesh_gears.py
+++ /dev/null
@@ -1,937 +0,0 @@
-# add_mesh_gear.py (c) 2009, 2010 Michel J. Anders (varkenvarken)
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Gears",
- "author": "Michel J. Anders (varkenvarken)",
- "version": (2,4,1),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Gears ",
- "description": "Adds a mesh Gear to the Add Mesh menu",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Gear",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21732&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-"""
-What was needed to port it from 2.49 -> 2.50 alpha 0?
-
-The basic functions that calculate the geometry (verts and faces) are mostly
-unchanged (add_tooth, add_spoke, add_gear)
-
-Also, the vertex group API is changed a little bit but the concepts
-are the same:
-=========
-vertexgroup = ob.vertex_groups.new('NAME_OF_VERTEXGROUP')
-ob.vertex_groups.assign(vertexgroup_vertex_indices, vertexgroup, weight, 'ADD')
-=========
-
-Now for some reason the name does not 'stick' and we have to set it this way:
-vertexgroup.name = 'NAME_OF_VERTEXGROUP'
-
-Conversion to 2.50 also meant we could simply do away with our crude user
-interface.
-Just definining the appropriate properties in the AddGear() operator will
-display the properties in the Blender GUI with the added benefit of making
-it interactive: changing a property will redo the AddGear() operator providing
-the user with instant feedback.
-
-Finally we had to convert/throw away some print statements to print functions
-as Blender nows uses Python 3.x
-
-The code to actually implement the AddGear() function is mostly copied from
-add_mesh_torus() (distributed with Blender).
-"""
-
-import bpy
-import mathutils
-from math import *
-from bpy.props import *
-
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = mathutils.Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = mathutils.Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-# Calculate the vertex coordinates for a single
-# section of a gear tooth.
-# Returns 4 lists of vertex coords (list of tuples):
-# *-*---*---* (1.) verts_inner_base
-# | | | |
-# *-*---*---* (2.) verts_outer_base
-# | | |
-# *---*---* (3.) verts_middle_tooth
-# \ | /
-# *-*-* (4.) verts_tip_tooth
-#
-# a
-# t
-# d
-# radius
-# Ad
-# De
-# base
-# p_angle
-# rack
-# crown
-def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
- A = [a, a + t / 4, a + t / 2, a + 3 * t / 4]
- C = [cos(i) for i in A]
- S = [sin(i) for i in A]
-
- Ra = radius + Ad
- Rd = radius - De
- Rb = Rd - base
-
- # Pressure angle calc
- O = Ad * tan(p_angle)
- p_angle = atan(O / Ra)
-
- if radius < 0:
- p_angle = -p_angle
-
- if rack:
- S = [sin(t / 4) * I for I in range(-2, 3)]
- Sp = [0, sin(-t / 4 + p_angle), 0, sin(t / 4 - p_angle)]
-
- verts_inner_base = [(Rb, radius * S[I], d) for I in range(4)]
- verts_outer_base = [(Rd, radius * S[I], d) for I in range(4)]
- verts_middle_tooth = [(radius, radius * S[I], d) for I in range(1, 4)]
- verts_tip_tooth = [(Ra, radius * Sp[I], d) for I in range(1, 4)]
-
- else:
- Cp = [
- 0,
- cos(a + t / 4 + p_angle),
- cos(a + t / 2),
- cos(a + 3 * t / 4 - p_angle)]
- Sp = [0,
- sin(a + t / 4 + p_angle),
- sin(a + t / 2),
- sin(a + 3 * t / 4 - p_angle)]
-
- verts_inner_base = [(Rb * C[I], Rb * S[I], d)
- for I in range(4)]
- verts_outer_base = [(Rd * C[I], Rd * S[I], d)
- for I in range(4)]
- verts_middle_tooth = [(radius * C[I], radius * S[I], d + crown / 3)
- for I in range(1, 4)]
- verts_tip_tooth = [(Ra * Cp[I], Ra * Sp[I], d + crown)
- for I in range(1, 4)]
-
- return (verts_inner_base, verts_outer_base,
- verts_middle_tooth, verts_tip_tooth)
-
-
-# EXPERIMENTAL Calculate the vertex coordinates for a single
-# section of a gearspoke.
-# Returns them as a list of tuples.
-#
-# a
-# t
-# d
-# radius
-# De
-# base
-# s
-# w
-# l
-# gap
-# width
-#
-# @todo Finish this.
-def add_spoke(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
- Rd = radius - De
- Rb = Rd - base
- Rl = Rb
-
- verts = []
- edgefaces = []
- edgefaces2 = []
- sf = []
-
- if not gap:
- for N in range(width, 1, -2):
- edgefaces.append(len(verts))
- ts = t / 4
- tm = a + 2 * ts
- te = asin(w / Rb)
- td = te - ts
- t4 = ts + td * (width - N) / (width - 3.0)
- A = [tm + (i - int(N / 2)) * t4 for i in range(N)]
- C = [cos(i) for i in A]
- S = [sin(i) for i in A]
-
- verts.extend([(Rb * I, Rb * J, d) for (I, J) in zip(C, S)])
- edgefaces2.append(len(verts) - 1)
-
- Rb = Rb - s
-
- n = 0
- for N in range(width, 3, -2):
- sf.extend([(i + n, i + 1 + n, i + 2 + n, i + N + n)
- for i in range(0, N - 1, 2)])
- sf.extend([(i + 2 + n, i + N + n, i + N + 1 + n, i + N + 2 + n)
- for i in range(0, N - 3, 2)])
-
- n = n + N
-
- return verts, edgefaces, edgefaces2, sf
-
-
-# Create gear geometry.
-# Returns:
-# * A list of vertices (list of tuples)
-# * A list of faces (list of lists)
-# * A list (group) of vertices of the tip (list of vertex indices).
-# * A list (group) of vertices of the valley (list of vertex indices).
-#
-# teethNum ... Number of teeth on the gear.
-# radius ... Radius of the gear, negative for crown gear
-# Ad ... Addendum, extent of tooth above radius.
-# De ... Dedendum, extent of tooth below radius.
-# base ... Base, extent of gear below radius.
-# p_angle ... Pressure angle. Skewness of tooth tip. (radiant)
-# width ... Width, thickness of gear.
-# skew ... Skew of teeth. (radiant)
-# conangle ... Conical angle of gear. (radiant)
-# rack
-# crown ... Inward pointing extend of crown teeth.
-#
-# inner radius = radius - (De + base)
-def add_gear(teethNum, radius, Ad, De, base, p_angle,
- width=1, skew=0, conangle=0, rack=0, crown=0.0):
-
- if teethNum < 2:
- return None, None, None, None
-
- t = 2 * pi / teethNum
-
- if rack:
- teethNum = 1
-
- scale = (radius - 2 * width * tan(conangle)) / radius
-
- verts = []
- faces = []
- vgroup_top = [] # Vertex group of top/tip? vertices.
- vgroup_valley = [] # Vertex group of valley vertices
-
- verts_bridge_prev = []
- for toothCnt in range(teethNum):
- a = toothCnt * t
-
- verts_bridge_start = []
- verts_bridge_end = []
-
- verts_outside_top = []
- verts_outside_bottom = []
- for (s, d, c, top) \
- in [(0, -width, 1, True), \
- (skew, width, scale, False)]:
-
- verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
- radius * c, Ad * c, De * c, base * c, p_angle,
- rack, crown)
-
- vertsIdx1 = list(range(len(verts), len(verts) + len(verts1)))
- verts.extend(verts1)
- vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
- verts.extend(verts2)
- vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
- verts.extend(verts3)
- vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
- verts.extend(verts4)
-
- verts_outside = []
- verts_outside.extend(vertsIdx2[:2])
- verts_outside.append(vertsIdx3[0])
- verts_outside.extend(vertsIdx4)
- verts_outside.append(vertsIdx3[-1])
- verts_outside.append(vertsIdx2[-1])
-
- if top:
- #verts_inside_top = vertsIdx1
- verts_outside_top = verts_outside
-
- verts_bridge_start.append(vertsIdx1[0])
- verts_bridge_start.append(vertsIdx2[0])
- verts_bridge_end.append(vertsIdx1[-1])
- verts_bridge_end.append(vertsIdx2[-1])
-
- else:
- #verts_inside_bottom = vertsIdx1
- verts_outside_bottom = verts_outside
-
- verts_bridge_start.append(vertsIdx2[0])
- verts_bridge_start.append(vertsIdx1[0])
- verts_bridge_end.append(vertsIdx2[-1])
- verts_bridge_end.append(vertsIdx1[-1])
-
- # Valley = first 2 vertices of outer base:
- vgroup_valley.extend(vertsIdx2[:1])
- # Top/tip vertices:
- vgroup_top.extend(vertsIdx4)
-
- faces_tooth_middle_top = createFaces(vertsIdx2[1:], vertsIdx3,
- flipped=top)
- faces_tooth_outer_top = createFaces(vertsIdx3, vertsIdx4,
- flipped=top)
-
- faces_base_top = createFaces(vertsIdx1, vertsIdx2, flipped=top)
- faces.extend(faces_base_top)
-
- faces.extend(faces_tooth_middle_top)
- faces.extend(faces_tooth_outer_top)
-
- #faces_inside = createFaces(verts_inside_top, verts_inside_bottom)
- #faces.extend(faces_inside)
-
- faces_outside = createFaces(verts_outside_top, verts_outside_bottom,
- flipped=True)
- faces.extend(faces_outside)
-
- if toothCnt == 0:
- verts_bridge_first = verts_bridge_start
-
- # Bridge one tooth to the next
- if verts_bridge_prev:
- faces_bridge = createFaces(verts_bridge_prev, verts_bridge_start)
- #, closed=True (for "inside" faces)
- faces.extend(faces_bridge)
-
- # Remember "end" vertices for next tooth.
- verts_bridge_prev = verts_bridge_end
-
- # Bridge the first to the last tooth.
- faces_bridge_f_l = createFaces(verts_bridge_prev, verts_bridge_first)
- #, closed=True (for "inside" faces)
- faces.extend(faces_bridge_f_l)
-
- return verts, faces, vgroup_top, vgroup_valley
-
-
-# Create spokes geometry.
-# Returns:
-# * A list of vertices (list of tuples)
-# * A list of faces (list of lists)
-#
-# teethNum ... Number of teeth on the gear.
-# radius ... Radius of the gear, negative for crown gear
-# De ... Dedendum, extent of tooth below radius.
-# base ... Base, extent of gear below radius.
-# width ... Width, thickness of gear.
-# conangle ... Conical angle of gear. (radiant)
-# rack
-# spoke
-# spbevel
-# spwidth
-# splength
-# spresol
-#
-# @todo Finish this
-# @todo Create a function that takes a "Gear" and creates a
-# matching "Gear Spokes" object.
-def add_spokes(teethNum, radius, De, base, width=1, conangle=0, rack=0,
- spoke=3, spbevel=0.1, spwidth=0.2, splength=1.0, spresol=9):
-
- if teethNum < 2:
- return None, None, None, None
-
- if spoke < 2:
- return None, None, None, None
-
- t = 2 * pi / teethNum
-
- if rack:
- teethNum = 1
-
- scale = (radius - 2 * width * tan(conangle)) / radius
-
- verts = []
- faces = []
-
- c = scale # debug
-
- fl = len(verts)
- for toothCnt in range(teethNum):
- a = toothCnt * t
- s = 0 # For test
-
- if toothCnt % spoke == 0:
- for d in (-width, width):
- sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
- radius * c, De * c, base * c,
- spbevel, spwidth, splength, 0, spresol)
- verts.extend(sv)
- faces.extend([[j + fl for j in i] for i in sf])
- fl += len(sv)
-
- d1 = fl - len(sv)
- d2 = fl - 2 * len(sv)
-
- faces.extend([(i + d2, j + d2, j + d1, i + d1)
- for (i, j) in zip(edgefaces[:-1], edgefaces[1:])])
- faces.extend([(i + d2, j + d2, j + d1, i + d1)
- for (i, j) in zip(edgefaces2[:-1], edgefaces2[1:])])
-
- else:
- for d in (-width, width):
- sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
- radius * c, De * c, base * c,
- spbevel, spwidth, splength, 1, spresol)
-
- verts.extend(sv)
- fl += len(sv)
-
- d1 = fl - len(sv)
- d2 = fl - 2 * len(sv)
-
- faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
- for (i) in range(0, 3)])
- faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
- for (i) in range(5, 8)])
-
- return verts, faces
-
-
-# Create worm geometry.
-# Returns:
-# * A list of vertices
-# * A list of faces
-# * A list (group) of vertices of the tip
-# * A list (group) of vertices of the valley
-#
-# teethNum ... Number of teeth on the worm
-# radius ... Radius of the gear, negative for crown gear
-# Ad ... Addendum, extent of tooth above radius.
-# De ... Dedendum, extent of tooth below radius.
-# p_angle ... Pressure angle. Skewness of tooth tip. (radiant)
-# width ... Width, thickness of gear.
-# crown ... Inward pointing extend of crown teeth.
-#
-# @todo: Fix teethNum. Some numbers are not possible yet.
-# @todo: Create start & end geoemtry (closing faces)
-def add_worm(teethNum, rowNum, radius, Ad, De, p_angle,
- width=1, skew=radians(11.25), crown=0.0):
-
- worm = teethNum
- teethNum = 24
-
- t = 2 * pi / teethNum
-
- verts = []
- faces = []
- vgroup_top = [] # Vertex group of top/tip? vertices.
- vgroup_valley = [] # Vertex group of valley vertices
-
- #width = width / 2.0
-
- edgeloop_prev = []
- for Row in range(rowNum):
- edgeloop = []
-
- for toothCnt in range(teethNum):
- a = toothCnt * t
-
- s = Row * skew
- d = Row * width
- c = 1
-
- isTooth = False
- if toothCnt % (teethNum / worm) != 0:
- # Flat
- verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
- radius - De, 0.0, 0.0, 0, p_angle)
-
- # Ignore other verts than the "other base".
- verts1 = verts3 = verts4 = []
-
- else:
- # Tooth
- isTooth = True
- verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
- radius * c, Ad * c, De * c, 0 * c, p_angle, 0, crown)
-
- # Remove various unneeded verts (if we are "inside" the tooth)
- del(verts2[2]) # Central vertex in the base of the tooth.
- del(verts3[1]) # Central vertex in the middle of the tooth.
-
- vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
- verts.extend(verts2)
- vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
- verts.extend(verts3)
- vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
- verts.extend(verts4)
-
- if isTooth:
- verts_current = []
- verts_current.extend(vertsIdx2[:2])
- verts_current.append(vertsIdx3[0])
- verts_current.extend(vertsIdx4)
- verts_current.append(vertsIdx3[-1])
- verts_current.append(vertsIdx2[-1])
-
- # Valley = first 2 vertices of outer base:
- vgroup_valley.extend(vertsIdx2[:1])
- # Top/tip vertices:
- vgroup_top.extend(vertsIdx4)
-
- else:
- # Flat
- verts_current = vertsIdx2
-
- # Valley - all of them.
- vgroup_valley.extend(vertsIdx2)
-
- edgeloop.extend(verts_current)
-
- # Create faces between rings/rows.
- if edgeloop_prev:
- faces_row = createFaces(edgeloop, edgeloop_prev, closed=True)
- faces.extend(faces_row)
-
- # Remember last ring/row of vertices for next ring/row iteration.
- edgeloop_prev = edgeloop
-
- return verts, faces, vgroup_top, vgroup_valley
-
-
-class AddGear(bpy.types.Operator):
- '''Add a gear mesh.'''
- bl_idname = "mesh.primitive_gear"
- bl_label = "Add Gear"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- number_of_teeth = IntProperty(name="Number of Teeth",
- description="Number of teeth on the gear",
- min=2,
- max=265,
- default=12)
- radius = FloatProperty(name="Radius",
- description="Radius of the gear, negative for crown gear",
- min=-100.0,
- max=100.0,
- default=1.0)
- addendum = FloatProperty(name="Addendum",
- description="Addendum, extent of tooth above radius",
- min=0.01,
- max=100.0,
- default=0.1)
- dedendum = FloatProperty(name="Dedendum",
- description="Dedendum, extent of tooth below radius",
- min=0.0,
- max=100.0,
- default=0.1)
- angle = FloatProperty(name="Pressure Angle",
- description="Pressure angle, skewness of tooth tip (degrees)",
- min=0.0,
- max=45.0,
- default=20.0)
- base = FloatProperty(name="Base",
- description="Base, extent of gear below radius",
- min=0.0,
- max=100.0,
- default=0.2)
- width = FloatProperty(name="Width",
- description="Width, thickness of gear",
- min=0.05,
- max=100.0,
- default=0.2)
- skew = FloatProperty(name="Skewness",
- description="Skew of teeth (degrees)",
- min=-90.0,
- max=90.0,
- default=0.0)
- conangle = FloatProperty(name="Conical angle",
- description="Conical angle of gear (degrees)",
- min=0.0,
- max=90.0,
- default=0.0)
- crown = FloatProperty(name="Crown",
- description="Inward pointing extend of crown teeth",
- min=0.0,
- max=100.0,
- default=0.0)
- align_matrix = mathutils.Matrix()
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- box = layout.box()
- box.prop(props, 'number_of_teeth')
- box = layout.box()
- box.prop(props, 'radius')
- box.prop(props, 'width')
- box.prop(props, 'base')
- box = layout.box()
- box.prop(props, 'dedendum')
- box.prop(props, 'addendum')
- box = layout.box()
- box.prop(props, 'angle')
- box.prop(props, 'skew')
- box.prop(props, 'conangle')
- box.prop(props, 'crown')
-
-
- def execute(self, context):
- props = self.properties
-
- verts, faces, verts_tip, verts_valley = add_gear(
- props.number_of_teeth,
- props.radius,
- props.addendum,
- props.dedendum,
- props.base,
- radians(props.angle),
- width=props.width,
- skew=radians(props.skew),
- conangle=radians(props.conangle),
- crown=props.crown)
-
- # Actually create the mesh object from this geometry data.
- obj = create_mesh_object(context, verts, [], faces, "Gear", props.edit, self.align_matrix)
-
- # Create vertex groups from stored vertices.
- tipGroup = obj.vertex_groups.new('Tips')
- obj.vertex_groups.assign(verts_tip, tipGroup, 1.0, 'ADD')
-
- valleyGroup = obj.vertex_groups.new('Valleys')
- obj.vertex_groups.assign(verts_valley, valleyGroup, 1.0, 'ADD')
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddWormGear(bpy.types.Operator):
- '''Add a worm gear mesh.'''
- bl_idname = "mesh.primitive_worm_gear"
- bl_label = "Add Worm Gear"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- number_of_teeth = IntProperty(name="Number of Teeth",
- description="Number of teeth on the gear",
- min=2,
- max=265,
- default=12)
- number_of_rows = IntProperty(name="Number of Rows",
- description="Number of rows on the worm gear",
- min=2,
- max=265,
- default=32)
- radius = FloatProperty(name="Radius",
- description="Radius of the gear, negative for crown gear",
- min=-100.0,
- max=100.0,
- default=1.0)
- addendum = FloatProperty(name="Addendum",
- description="Addendum, extent of tooth above radius",
- min=0.01,
- max=100.0,
- default=0.1)
- dedendum = FloatProperty(name="Dedendum",
- description="Dedendum, extent of tooth below radius",
- min=0.0,
- max=100.0,
- default=0.1)
- angle = FloatProperty(name="Pressure Angle",
- description="Pressure angle, skewness of tooth tip (degrees)",
- min=0.0,
- max=45.0,
- default=20.0)
- row_height = FloatProperty(name="Row Height",
- description="Height of each Row",
- min=0.05,
- max=100.0,
- default=0.2)
- skew = FloatProperty(name="Skewness per Row",
- description="Skew of each row (degrees)",
- min=-90.0,
- max=90.0,
- default=11.25)
- crown = FloatProperty(name="Crown",
- description="Inward pointing extend of crown teeth",
- min=0.0,
- max=100.0,
- default=0.0)
- align_matrix = mathutils.Matrix()
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- box = layout.box()
- box.prop(props, 'number_of_teeth')
- box.prop(props, 'number_of_rows')
- box.prop(props, 'radius')
- box.prop(props, 'row_height')
- box = layout.box()
- box.prop(props, 'addendum')
- box.prop(props, 'dedendum')
- box = layout.box()
- box.prop(props, 'angle')
- box.prop(props, 'skew')
- box.prop(props, 'crown')
-
- def execute(self, context):
- props = self.properties
-
- verts, faces, verts_tip, verts_valley = add_worm(
- props.number_of_teeth,
- props.number_of_rows,
- props.radius,
- props.addendum,
- props.dedendum,
- radians(props.angle),
- width=props.row_height,
- skew=radians(props.skew),
- crown=props.crown)
-
- # Actually create the mesh object from this geometry data.
- obj = create_mesh_object(context, verts, [], faces, "Worm Gear",
- props.edit, self.align_matrix)
-
- # Create vertex groups from stored vertices.
- tipGroup = obj.vertex_groups.new('Tips')
- obj.vertex_groups.assign(verts_tip, tipGroup, 1.0, 'ADD')
-
- valleyGroup = obj.vertex_groups.new('Valleys')
- obj.vertex_groups.assign(verts_valley, valleyGroup, 1.0, 'ADD')
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class INFO_MT_mesh_gears_add(bpy.types.Menu):
- # Define the "Gears" menu
- bl_idname = "INFO_MT_mesh_gears_add"
- bl_label = "Gears"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.primitive_gear",
- text="Gear")
- layout.operator("mesh.primitive_worm_gear",
- text="Worm")
-
-
-# Define "Gears" menu
-def menu_func(self, context):
- self.layout.menu("INFO_MT_mesh_gears_add", icon="PLUGIN")
-
-
-def register():
- # Add "Gears" entry to the "Add Mesh" menu.
- bpy.types.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- # Remove "Gears" entry from the "Add Mesh" menu.
- bpy.types.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_gemstones.py b/add_mesh_gemstones.py
deleted file mode 100644
index 984734e6..00000000
--- a/add_mesh_gemstones.py
+++ /dev/null
@@ -1,472 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Gemstones",
- "author": "Pontiac, Fourmadmen, Dreampainter",
- "version": (0,3),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Gemstones",
- "description": "Adds various gemstone (Diamond & Gem) meshes.",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Gemstones",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21432&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-import bpy
-from mathutils import *
-from math import *
-from bpy.props import *
-
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-# @todo Clean up vertex&face creation process a bit.
-def add_gem(r1, r2, seg, h1, h2):
- """
- r1 = pavilion radius
- r2 = crown radius
- seg = number of segments
- h1 = pavilion height
- h2 = crown height
- Generates the vertices and faces of the gem
- """
-
- verts = []
-
- a = 2.0 * pi / seg # Angle between segments
- offset = a / 2.0 # Middle between segments
-
- r3 = ((r1 + r2) / 2.0) / cos(offset) # Middle of crown
- r4 = (r1 / 2.0) / cos(offset) # Middle of pavilion
- h3 = h2 / 2.0 # Middle of crown height
- h4 = -h1 / 2.0 # Middle of pavilion height
-
- # Tip
- vert_tip = len(verts)
- verts.append(Vector((0.0, 0.0, -h1)))
-
- # Middle vertex of the flat side (crown)
- vert_flat = len(verts)
- verts.append(Vector((0.0, 0.0, h2)))
-
- edgeloop_flat = []
- for i in range(seg):
- s1 = sin(i * a)
- s2 = sin(offset + i * a)
- c1 = cos(i * a)
- c2 = cos(offset + i * a)
-
- verts.append((r4 * s1, r4 * c1, h4)) # Middle of pavilion
- verts.append((r1 * s2, r1 * c2, 0.0)) # Pavilion
- verts.append((r3 * s1, r3 * c1, h3)) # Middle crown
- edgeloop_flat.append(len(verts))
- verts.append((r2 * s2, r2 * c2, h2)) # Crown
-
- faces = []
-
- for index in range(seg):
- i = index * 4
- j = ((index + 1) % seg) * 4
-
- faces.append([j + 2, vert_tip, i + 2, i + 3]) # Tip -> Middle of pav
- faces.append([j + 2, i + 3, j + 3]) # Middle of pav -> pav
- faces.append([j + 3, i + 3, j + 4]) # Pav -> Middle crown
- faces.append([j + 4, i + 3, i + 4, i + 5]) # Crown quads
- faces.append([j + 4, i + 5, j + 5]) # Middle crown -> crown
-
- faces_flat = createFaces([vert_flat], edgeloop_flat, closed=True)
- faces.extend(faces_flat)
-
- return verts, faces
-
-
-def add_diamond(segments, girdle_radius, table_radius,
- crown_height, pavilion_height):
-
- PI_2 = pi * 2.0
- z_axis = (0.0, 0.0, -1.0)
-
- verts = []
- faces = []
-
- height_flat = crown_height
- height_middle = 0.0
- height_tip = -pavilion_height
-
- # Middle vertex of the flat side (crown)
- vert_flat = len(verts)
- verts.append(Vector((0.0, 0.0, height_flat)))
-
- # Tip
- vert_tip = len(verts)
- verts.append(Vector((0.0, 0.0, height_tip)))
-
- verts_flat = []
- verts_girdle = []
-
- for index in range(segments):
- quat = Quaternion(z_axis, (index / segments) * PI_2)
-
- angle = PI_2 * index / segments
-
- # Row for flat side
- verts_flat.append(len(verts))
- vec = Vector((table_radius, 0.0, height_flat)) * quat
- verts.append(vec)
-
- # Row for the middle/girdle
- verts_girdle.append(len(verts))
- vec = Vector((girdle_radius, 0.0, height_middle)) * quat
- verts.append(vec)
-
- # Flat face
- faces_flat = createFaces([vert_flat], verts_flat, closed=True,
- flipped=True)
- # Side face
- faces_side = createFaces(verts_girdle, verts_flat, closed=True)
- # Tip faces
- faces_tip = createFaces([vert_tip], verts_girdle, closed=True)
-
- faces.extend(faces_tip)
- faces.extend(faces_side)
- faces.extend(faces_flat)
-
- return verts, faces
-
-
-class AddDiamond(bpy.types.Operator):
- '''Add a diamond mesh.'''
- bl_idname = "mesh.primitive_diamond_add"
- bl_label = "Add Diamond"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- segments = IntProperty(name="Segments",
- description="Number of segments for the diamond",
- min=3,
- max=256,
- default=32)
- girdle_radius = FloatProperty(name="Girdle Radius",
- description="Girdle radius of the diamond",
- min=0.01,
- max=9999.0,
- default=1.0)
- table_radius = FloatProperty(name="Table Radius",
- description="Girdle radius of the diamond",
- min=0.01,
- max=9999.0,
- default=0.6)
- crown_height = FloatProperty(name="Crown Height",
- description="Crown height of the diamond",
- min=0.01,
- max=9999.0,
- default=0.35)
- pavilion_height = FloatProperty(name="Pavilion Height",
- description="Pavilion height of the diamond",
- min=0.01,
- max=9999.0,
- default=0.8)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
- verts, faces = add_diamond(props.segments,
- props.girdle_radius,
- props.table_radius,
- props.crown_height,
- props.pavilion_height)
-
- obj = create_mesh_object(context, verts, [], faces,
- "Diamond", props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class AddGem(bpy.types.Operator):
- """Add a diamond gem"""
- bl_idname = "mesh.primitive_gem_add"
- bl_label = "Add Gem"
- bl_description = "Create an offset faceted gem."
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- segments = IntProperty(name="Segments",
- description="Longitudial segmentation",
- min=3,
- max=265,
- default=8,)
- pavilion_radius = FloatProperty(name="Radius",
- description="Radius of the gem",
- min=0.01,
- max=9999.0,
- default=1.0)
- crown_radius = FloatProperty(name="Table Radius",
- description="Radius of the table(top).",
- min=0.01,
- max=9999.0,
- default=0.6)
- crown_height = FloatProperty(name="Table height",
- description="Height of the top half.",
- min=0.01,
- max=9999.0,
- default=0.35)
- pavilion_height = FloatProperty(name="Pavilion height",
- description="Height of bottom half.",
- min=0.01,
- max=9999.0,
- default=0.8)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- # create mesh
- verts, faces = add_gem(
- props.pavilion_radius,
- props.crown_radius,
- props.segments,
- props.pavilion_height,
- props.crown_height)
-
- obj = create_mesh_object(context, verts, [], faces, "Gem", props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-class INFO_MT_mesh_gemstones_add(bpy.types.Menu):
- # Define the "Gemstones" menu
- bl_idname = "INFO_MT_mesh_gemstones_add"
- bl_label = "Gemstones"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.primitive_diamond_add",
- text="Diamond")
- layout.operator("mesh.primitive_gem_add",
- text="Gem")
-
-
-# Register all operators and panels
-import space_info
-
-
-# Define "Gemstones" menu
-def menu_func(self, context):
- self.layout.menu("INFO_MT_mesh_gemstones_add", icon="PLUGIN")
-
-
-def register():
- # Add "Gemstones" menu to the "Add Mesh" menu
- space_info.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- # Remove "Gemstones" menu from the "Add Mesh" menu.
- space_info.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_pipe_joint.py b/add_mesh_pipe_joint.py
deleted file mode 100644
index 76650814..00000000
--- a/add_mesh_pipe_joint.py
+++ /dev/null
@@ -1,1306 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Pipe Joints",
- "author": "Buerbaum Martin (Pontiac)",
- "version": (0, 10, 6),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Pipe Joint",
- "description": "Adds 5 pipe Joint types to the Add Mesh menu",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Pipe_Joints",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21443&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-"""
-Pipe Joints
-This script lets the user create various types of pipe joints.
-
-Usage:
-You have to activated the script in the "Add-Ons" tab (user preferences).
-The functionality can then be accessed via the
-"Add Mesh" -> "Pipe Joints" menu.
-Note: Currently only the "Elbow" type supports odd number of vertices.
-
-Version history:
-v0.10.6 - Removed "recall properties" from all functions.
- Updated various code for new API.
- API: mathutils.RotationMatrix -> mathutils.Matrix.Rotation
- API: xxx.selected -> xxx.select
- API: "invoke" function for each operator.
- Updated for new bl_addon_info structure.
- New code for the "align_matrix".
- made script PEP8 compatible.
-v0.10.5 - createFaces can now create fan/star like faces.
-v0.10.4 - Updated the function "createFaces" a bit. No functional changes.
-v0.10.3 - Updated store_recall_properties, apply_object_align
- and create_mesh_object.
- Changed how recall data is stored.
- Added 'description'.
-v0.10.2 - API change Mathutils -> mathutils (r557)
- Fixed wiki url.
-v0.10.1 - Use hidden "edit" property for "recall" operator.
-v0.10 - Store "recall" properties in the created objects.
- Align the geometry to the view if the user preference says so.
-v0.9.10 - Use bl_addon_info for Add-On information.
-v0.9.9 - Changed the script so it can be managed from the "Add-Ons" tab in
- the user preferences.
- Added dummy "PLUGIN" icon.
-v0.9.8 - Fixed some new API stuff.
- Mainly we now have the register/unregister functions.
- Also the new() function for objects now accepts a mesh object.
- Corrected FSF address.
- Clean up of tooltips.
-v0.9.7 - Use "unit" settings for angles as well.
- This also lets me use radiant for all internal values..
-v0.9.6 - Use "unit" settings (i.e. none/metric/imperial).
-v0.9.5 - Use mesh.from_pydata() for geometry creation.
- So we can remove unpack_list and unpack_face_list again.
-v0.9.4 - Creating of the pipe now works in mesh edit mode too.
- Thanks to ideasman42 (Campbell Barton) for his nice work
- on the torus script code :-).
-v0.9.3 - Changed to a saner vertex/polygon creation process (previously
- my usage of mesh.faces.add could only do quads)
- For this I've copied the functions unpack_list and unpack_face_list
- from import_scene_obj.py.
- Elbow joint actually supports 3 vertices per circle.
- Various comments.
- Script _should_ now be PEP8 compatible.
-v0.9.2 - Converted from tabs to spaces (4 spaces per tab).
-v0.9.1 - Converted add_mesh and add_object to their new counterparts
- "bpy.data.meshes.new() and "bpy.data.objects.new()"
-v0.9 - Converted to 2.5. Made mostly pep8 compatible (exept for tabs and
- stuff the check-script didn't catch).
-v0.8.5 - Fixed bug in Elbow joint. Same problem as in 0.8.1
-v0.8.4 - Fixed bug in Y joint. Same problem as in 0.8.1
-v0.8.3 - Fixed bug in N joint. Same problem as in 0.8.1
-v0.8.2 - Fixed bug in X (cross) joint. Same problem as in 0.8.1
-v0.8.1 - Fixed bug in T joint. Angles greater than 90 deg combined with a
- radius != 1 resulted in bad geometry (the radius was not taken into
- account when calculating the joint vertices).
-v0.8 - Added N-Joint.
- Removed all uses of baseJointLocZ. It just clutters the code.
-v0.7 - Added cross joint
-v0.6 - No visible changes. Lots of internal ones though
- (complete redesign of face creation process).
- As a bonus the code is a bit easier to read now.
- Added a nice&simple little "bridge" function
- (createFaces) for these changes.
-v0.5.1 - Made it possible to create asymmetric Y joints.
- Renamed the 2 Wye Joints to something more fitting and unique.
- One is now the Tee joint, the second one remains the Wye joint.
-v0.5 - Added real Y joint.
-v0.4.3 - Added check for odd vertex numbers. They are not (yet) supported.
-v0.4.2 - Added pipe length to the GUI.
-v0.4.1 - Removed the unfinished menu entries for now.
-v0.4 - Tried to clean up the face creation in addTeeJoint
-v0.3 - Code for wye (Y) shape (straight pipe with "branch" for now)
-v0.2 - Restructured to allow different types of pipe (joints).
-v0.1 - Initial revision.
-
-More links:
-http://gitorious.org/blender-scripts/blender-pipe-joint-script
-http://blenderartists.org/forum/showthread.php?t=154394
-
-TODO:
-
-Use a rotation matrix for rotating the circle vertices:
-rotation_matrix = mathutils.Matrix.Rotation(-math.pi/2, 4, 'x')
-mesh.transform(rotation_matrix)
-"""
-
-import bpy
-import mathutils
-from math import *
-from bpy.props import *
-
-
-# Apply view rotation to objects if "Align To" for
-# new objects was set to "VIEW" in the User Preference.
-# Is now handled in the invoke functions
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = mathutils.Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- view_mat = context.space_data.region_3d.view_matrix
- rot = view_mat.rotation_part().invert().resize4x4()
- else:
- rot = mathutils.Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-class AddElbowJoint(bpy.types.Operator):
- # Create the vertices and polygons for a simple elbow (bent pipe).
- '''Add an Elbow pipe mesh'''
- bl_idname = "mesh.primitive_elbow_joint_add"
- bl_label = "Add Pipe Elbow"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- radius = FloatProperty(name="Radius",
- description="The radius of the pipe.",
- default=1.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- div = IntProperty(name="Divisions",
- description="Number of vertices (divisions).",
- default=32, min=3, max=256)
-
- angle = FloatProperty(name="Angle",
- description="The angle of the branching pipe (i.e. the 'arm')." \
- " Measured from the center line of the main pipe.",
- default=radians(45.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
-
- startLength = FloatProperty(name="Length Start",
- description="Length of the beginning of the pipe.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- endLength = FloatProperty(name="End Length",
- description="Length of the end of the pipe.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = mathutils.Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
-
- radius = self.properties.radius
- div = self.properties.div
-
- angle = self.properties.angle
-
- startLength = self.properties.startLength
- endLength = self.properties.endLength
-
- verts = []
- faces = []
-
- loop1 = [] # The starting circle
- loop2 = [] # The elbow circle
- loop3 = [] # The end circle
-
- # Create start circle
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = -startLength
- loop1.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- # Create deformed joint circle
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = locX * tan(angle / 2.0)
- loop2.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- # Create end circle
- baseEndLocX = -endLength * sin(angle)
- baseEndLocZ = endLength * cos(angle)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 - angle)
- locX = locX * sin(pi / 2.0 - angle)
-
- loop3.append(len(verts))
- # Translate and add circle vertices to the list.
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create faces
- faces.extend(createFaces(loop1, loop2, closed=True))
- faces.extend(createFaces(loop2, loop3, closed=True))
-
- obj = create_mesh_object(context, verts, [], faces,
- "Elbow Joint", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-class AddTeeJoint(bpy.types.Operator):
- # Create the vertices and polygons for a simple tee (T) joint.
- # The base arm of the T can be positioned in an angle if needed though.
- '''Add a Tee-Joint mesh'''
- bl_idname = "mesh.primitive_tee_joint_add"
- bl_label = "Add Pipe Tee-Joint"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- radius = FloatProperty(name="Radius",
- description="The radius of the pipe.",
- default=1.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- div = IntProperty(name="Divisions",
- description="Number of vertices (divisions).",
- default=32,
- min=4,
- max=256)
-
- angle = FloatProperty(name="Angle",
- description="The angle of the branching pipe (i.e. the 'arm')." \
- " Measured from the center line of the main pipe.",
- default=radians(90.0),
- min=radians(0.1),
- max=radians(179.9),
- unit="ROTATION")
-
- startLength = FloatProperty(name="Length Start",
- description="Length of the beginning of the" \
- " main pipe (the straight one).",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- endLength = FloatProperty(name="End Length",
- description="Length of the end of the" \
- " main pipe (the straight one).",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branchLength = FloatProperty(name="Arm Length",
- description="Length of the arm pipe (the bent one).",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = mathutils.Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
-
- radius = self.properties.radius
- div = self.properties.div
-
- angle = self.properties.angle
-
- startLength = self.properties.startLength
- endLength = self.properties.endLength
- branchLength = self.properties.branchLength
-
- if (div % 2):
- # Odd vertice number not supported (yet).
- return {'CANCELLED'}
-
- verts = []
- faces = []
-
- # List of vert indices of each cross section
- loopMainStart = [] # Vert indices for the
- # beginning of the main pipe.
- loopJoint1 = [] # Vert indices for joint that is used
- # to connect the joint & loopMainStart.
- loopJoint2 = [] # Vert indices for joint that is used
- # to connect the joint & loopArm.
- loopJoint3 = [] # Vert index for joint that is used
- # to connect the joint & loopMainEnd.
- loopArm = [] # Vert indices for the end of the arm.
- loopMainEnd = [] # Vert indices for the
- # end of the main pipe.
-
- # Create start circle (main pipe)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = -startLength
- loopMainStart.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- # Create deformed joint circle
- vertTemp1 = None
- vertTemp2 = None
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
-
- if vertIdx == 0:
- vertTemp1 = len(verts)
- if vertIdx == div / 2:
- # @todo: This will possibly break if we
- # ever support odd divisions.
- vertTemp2 = len(verts)
-
- loopJoint1.append(len(verts))
- if (vertIdx < div / 2):
- # Straight side of main pipe.
- locZ = 0
- loopJoint3.append(len(verts))
- else:
- # Branching side
- locZ = locX * tan(angle / 2.0)
- loopJoint2.append(len(verts))
-
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- # Create 2. deformed joint (half-)circle
- loopTemp = []
- for vertIdx in range(div):
- if (vertIdx > div / 2):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = -cos(curVertAngle)
- locZ = -(radius * locX * tan((pi - angle) / 2.0))
- loopTemp.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- loopTemp2 = loopTemp[:]
-
- # Finalise 2. loop
- loopTemp.reverse()
- loopTemp.append(vertTemp1)
- loopJoint2.reverse()
- loopJoint2.extend(loopTemp)
- loopJoint2.reverse()
-
- # Finalise 3. loop
- loopTemp2.append(vertTemp2)
- loopTemp2.reverse()
- loopJoint3.extend(loopTemp2)
-
- # Create end circle (branching pipe)
- baseEndLocX = -branchLength * sin(angle)
- baseEndLocZ = branchLength * cos(angle)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 - angle)
- locX = locX * sin(pi / 2.0 - angle)
-
- loopArm.append(len(verts))
-
- # Add translated circle.
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create end circle (main pipe)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = endLength
- loopMainEnd.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- # Create faces
- faces.extend(createFaces(loopMainStart, loopJoint1, closed=True))
- faces.extend(createFaces(loopJoint2, loopArm, closed=True))
- faces.extend(createFaces(loopJoint3, loopMainEnd, closed=True))
-
- obj = create_mesh_object(context, verts, [], faces,
- "Tee Joint", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-class AddWyeJoint(bpy.types.Operator):
- '''Add a Wye-Joint mesh'''
- bl_idname = "mesh.primitive_wye_joint_add"
- bl_label = "Add Pipe Wye-Joint"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- radius = FloatProperty(name="Radius",
- description="The radius of the pipe.",
- default=1.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- div = IntProperty(name="Divisions",
- description="Number of vertices (divisions).",
- default=32,
- min=4,
- max=256)
-
- angle1 = FloatProperty(name="Angle 1",
- description="The angle of the 1. branching pipe." \
- " Measured from the center line of the main pipe.",
- default=radians(45.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
- angle2 = FloatProperty(name="Angle 2",
- description="The angle of the 2. branching pipe." \
- " Measured from the center line of the main pipe.",
- default=radians(45.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
-
- startLength = FloatProperty(name="Length Start",
- description="Length of the beginning of the" \
- " main pipe (the straight one).",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branch1Length = FloatProperty(name="Length Arm 1",
- description="Length of the 1. arm.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branch2Length = FloatProperty(name="Length Arm 2",
- description="Length of the 2. arm.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = mathutils.Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
-
- radius = self.properties.radius
- div = self.properties.div
-
- angle1 = self.properties.angle1
- angle2 = self.properties.angle2
-
- startLength = self.properties.startLength
- branch1Length = self.properties.branch1Length
- branch2Length = self.properties.branch2Length
-
- if (div % 2):
- # Odd vertice number not supported (yet).
- return {'CANCELLED'}
-
- verts = []
- faces = []
-
- # List of vert indices of each cross section
- loopMainStart = [] # Vert indices for
- # the beginning of the main pipe.
- loopJoint1 = [] # Vert index for joint that is used
- # to connect the joint & loopMainStart.
- loopJoint2 = [] # Vert index for joint that
- # is used to connect the joint & loopArm1.
- loopJoint3 = [] # Vert index for joint that is
- # used to connect the joint & loopArm2.
- loopArm1 = [] # Vert idxs for end of the 1. arm.
- loopArm2 = [] # Vert idxs for end of the 2. arm.
-
- # Create start circle
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = -startLength
- loopMainStart.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- # Create deformed joint circle
- vertTemp1 = None
- vertTemp2 = None
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
-
- if vertIdx == 0:
- vertTemp2 = len(verts)
- if vertIdx == div / 2:
- # @todo: This will possibly break if we
- # ever support odd divisions.
- vertTemp1 = len(verts)
-
- loopJoint1.append(len(verts))
- if (vertIdx > div / 2):
- locZ = locX * tan(angle1 / 2.0)
- loopJoint2.append(len(verts))
- else:
- locZ = locX * tan(-angle2 / 2.0)
- loopJoint3.append(len(verts))
-
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- # Create 2. deformed joint (half-)circle
- loopTemp = []
- angleJoint = (angle2 - angle1) / 2.0
- for vertIdx in range(div):
- if (vertIdx > div / 2):
- curVertAngle = vertIdx * (2.0 * pi / div)
-
- locX = (-sin(curVertAngle) * sin(angleJoint)
- / sin(angle2 - angleJoint))
- locY = -cos(curVertAngle)
- locZ = (-(sin(curVertAngle) * cos(angleJoint)
- / sin(angle2 - angleJoint)))
-
- loopTemp.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- loopTemp2 = loopTemp[:]
-
- # Finalise 2. loop
- loopTemp.append(vertTemp1)
- loopTemp.reverse()
- loopTemp.append(vertTemp2)
- loopJoint2.reverse()
- loopJoint2.extend(loopTemp)
- loopJoint2.reverse()
-
- # Finalise 3. loop
- loopTemp2.reverse()
- loopJoint3.extend(loopTemp2)
-
- # Create end circle (1. branching pipe)
- baseEndLocX = -branch1Length * sin(angle1)
- baseEndLocZ = branch1Length * cos(angle1)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 - angle1)
- locX = locX * sin(pi / 2.0 - angle1)
-
- loopArm1.append(len(verts))
- # Add translated circle.
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create end circle (2. branching pipe)
- baseEndLocX = branch2Length * sin(angle2)
- baseEndLocZ = branch2Length * cos(angle2)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 + angle2)
- locX = locX * sin(pi / 2.0 + angle2)
-
- loopArm2.append(len(verts))
- # Add translated circle
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create faces
- faces.extend(createFaces(loopMainStart, loopJoint1, closed=True))
- faces.extend(createFaces(loopJoint2, loopArm1, closed=True))
- faces.extend(createFaces(loopJoint3, loopArm2, closed=True))
-
- obj = create_mesh_object(context, verts, [], faces,
- "Wye Joint", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-class AddCrossJoint(bpy.types.Operator):
- '''Add a Cross-Joint mesh'''
- # Create the vertices and polygons for a coss (+ or X) pipe joint.
- bl_idname = "mesh.primitive_cross_joint_add"
- bl_label = "Add Pipe Cross-Joint"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- radius = FloatProperty(name="Radius",
- description="The radius of the pipe.",
- default=1.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- div = IntProperty(name="Divisions",
- description="Number of vertices (divisions).",
- default=32,
- min=4,
- max=256)
-
- angle1 = FloatProperty(name="Angle 1",
- description="The angle of the 1. arm (from the main axis).",
- default=radians(90.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
- angle2 = FloatProperty(name="Angle 2",
- description="The angle of the 2. arm (from the main axis).",
- default=radians(90.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
- angle3 = FloatProperty(name="Angle 3 (center)",
- description="The angle of the center arm (from the main axis).",
- default=radians(0.0),
- min=radians(-179.9),
- max=radians(179.9),
- unit="ROTATION")
-
- startLength = FloatProperty(name="Length Start",
- description="Length of the beginning of the " \
- "main pipe (the straight one).",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branch1Length = FloatProperty(name="Length Arm 1",
- description="Length of the 1. arm.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branch2Length = FloatProperty(name="Length Arm 2",
- description="Length of the 2. arm.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- branch3Length = FloatProperty(name="Length Arm 3 (center)",
- description="Length of the center arm.",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = mathutils.Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
-
- radius = self.properties.radius
- div = self.properties.div
-
- angle1 = self.properties.angle1
- angle2 = self.properties.angle2
- angle3 = self.properties.angle3
-
- startLength = self.properties.startLength
- branch1Length = self.properties.branch1Length
- branch2Length = self.properties.branch2Length
- branch3Length = self.properties.branch3Length
- if (div % 2):
- # Odd vertice number not supported (yet).
- return {'CANCELLED'}
-
- verts = []
- faces = []
-
- # List of vert indices of each cross section
- loopMainStart = [] # Vert indices for the
- # beginning of the main pipe.
- loopJoint1 = [] # Vert index for joint that is used
- # to connect the joint & loopMainStart.
- loopJoint2 = [] # Vert index for joint that is used
- # to connect the joint & loopArm1.
- loopJoint3 = [] # Vert index for joint that is used
- # to connect the joint & loopArm2.
- loopJoint4 = [] # Vert index for joint that is used
- # to connect the joint & loopArm3.
- loopArm1 = [] # Vert idxs for the end of the 1. arm.
- loopArm2 = [] # Vert idxs for the end of the 2. arm.
- loopArm3 = [] # Vert idxs for the center arm end.
-
- # Create start circle
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
- locZ = -startLength
- loopMainStart.append(len(verts))
- verts.append([locX * radius, locY * radius, locZ])
-
- # Create 1. deformed joint circle
- vertTemp1 = None
- vertTemp2 = None
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
-
- if vertIdx == 0:
- vertTemp2 = len(verts)
- if vertIdx == div / 2:
- # @todo: This will possibly break if we
- # ever support odd divisions.
- vertTemp1 = len(verts)
-
- loopJoint1.append(len(verts))
- if (vertIdx > div / 2):
- locZ = locX * tan(angle1 / 2.0)
- loopJoint2.append(len(verts))
- else:
- locZ = locX * tan(-angle2 / 2.0)
- loopJoint3.append(len(verts))
-
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- loopTemp2 = loopJoint2[:]
-
- # Create 2. deformed joint circle
- loopTempA = []
- loopTempB = []
- angleJoint1 = (angle1 - angle3) / 2.0
- angleJoint2 = (angle2 + angle3) / 2.0
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
-
- # Skip pole vertices
- # @todo: This will possibly break if
- # we ever support odd divisions.
- if not (vertIdx == 0) and not (vertIdx == div / 2):
-
- if (vertIdx > div / 2):
- angleJoint = angleJoint1
- angle = angle1
- Z = -1.0
- loopTempA.append(len(verts))
-
- else:
- angleJoint = angleJoint2
- angle = angle2
- Z = 1.0
- loopTempB.append(len(verts))
-
- locX = (sin(curVertAngle) * sin(angleJoint)
- / sin(angle - angleJoint))
- locY = -cos(curVertAngle)
- locZ = (Z * (sin(curVertAngle) * cos(angleJoint)
- / sin(angle - angleJoint)))
-
- verts.append([locX * radius, locY * radius, locZ * radius])
-
- loopTempA2 = loopTempA[:]
- loopTempB2 = loopTempB[:]
- loopTempB3 = loopTempB[:]
-
- # Finalise 2. loop
- loopTempA.append(vertTemp1)
- loopTempA.reverse()
- loopTempA.append(vertTemp2)
- loopJoint2.reverse()
- loopJoint2.extend(loopTempA)
- loopJoint2.reverse()
-
- # Finalise 3. loop
- loopJoint3.extend(loopTempB3)
-
- # Finalise 4. loop
- loopTempA2.append(vertTemp1)
- loopTempA2.reverse()
- loopTempB2.append(vertTemp2)
- loopJoint4.extend(reversed(loopTempB2))
- loopJoint4.extend(loopTempA2)
-
- # Create end circle (1. branching pipe)
- baseEndLocX = -branch1Length * sin(angle1)
- baseEndLocZ = branch1Length * cos(angle1)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 - angle1)
- locX = locX * sin(pi / 2.0 - angle1)
-
- loopArm1.append(len(verts))
- # Add translated circle.
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create end circle (2. branching pipe)
- baseEndLocX = branch2Length * sin(angle2)
- baseEndLocZ = branch2Length * cos(angle2)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 + angle2)
- locX = locX * sin(pi / 2.0 + angle2)
-
- loopArm2.append(len(verts))
- # Add translated circle
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create end circle (center pipe)
- baseEndLocX = branch3Length * sin(angle3)
- baseEndLocZ = branch3Length * cos(angle3)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 + angle3)
- locX = locX * sin(pi / 2.0 + angle3)
-
- loopArm3.append(len(verts))
- # Add translated circle
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- # Create faces
- faces.extend(createFaces(loopMainStart, loopJoint1, closed=True))
- faces.extend(createFaces(loopJoint2, loopArm1, closed=True))
- faces.extend(createFaces(loopJoint3, loopArm2, closed=True))
- faces.extend(createFaces(loopJoint4, loopArm3, closed=True))
-
- obj = create_mesh_object(context, verts, [], faces,
- "Cross Joint", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-class AddNJoint(bpy.types.Operator):
- '''Add a N-Joint mesh'''
- # Create the vertices and polygons for a regular n-joint.
- bl_idname = "mesh.primitive_n_joint_add"
- bl_label = "Add Pipe N-Joint"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- radius = FloatProperty(name="Radius",
- description="The radius of the pipe.",
- default=1.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- div = IntProperty(name="Divisions",
- description="Number of vertices (divisions).",
- default=32,
- min=4,
- max=256)
- number = IntProperty(name="Arms/Joints",
- description="Number of joints/arms",
- default=5,
- min=2,
- max=99999)
- length = FloatProperty(name="Length",
- description="Length of each joint/arm",
- default=3.0,
- min=0.01,
- max=100.0,
- unit="LENGTH")
- align_matrix = mathutils.Matrix()
-
- def execute(self, context):
- edit = self.properties.edit
- radius = self.properties.radius
- div = self.properties.div
- number = self.properties.number
- length = self.properties.length
-
- if (div % 2):
- # Odd vertice number not supported (yet).
- return {'CANCELLED'}
-
- if (number < 2):
- return {'CANCELLED'}
-
- verts = []
- faces = []
-
- loopsEndCircles = []
- loopsJointsTemp = []
- loopsJoints = []
-
- vertTemp1 = None
- vertTemp2 = None
-
- angleDiv = (2.0 * pi / number)
-
- # Create vertices for the end circles.
- for num in range(number):
- circle = []
- # Create start circle
- angle = num * angleDiv
-
- baseEndLocX = length * sin(angle)
- baseEndLocZ = length * cos(angle)
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- # Create circle
- locX = sin(curVertAngle) * radius
- locY = cos(curVertAngle) * radius
- locZ = 0.0
-
- # Rotate circle
- locZ = locX * cos(pi / 2.0 + angle)
- locX = locX * sin(pi / 2.0 + angle)
-
- circle.append(len(verts))
- # Add translated circle
- verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])
-
- loopsEndCircles.append(circle)
-
- # Create vertices for the joint circles.
- loopJoint = []
- for vertIdx in range(div):
- curVertAngle = vertIdx * (2.0 * pi / div)
- locX = sin(curVertAngle)
- locY = cos(curVertAngle)
-
- skipVert = False
- # Store pole vertices
- if vertIdx == 0:
- if (num == 0):
- vertTemp2 = len(verts)
- else:
- skipVert = True
- elif vertIdx == div / 2:
- # @todo: This will possibly break if we
- # ever support odd divisions.
- if (num == 0):
- vertTemp1 = len(verts)
- else:
- skipVert = True
-
- if not skipVert:
- if (vertIdx > div / 2):
- locZ = -locX * tan((pi - angleDiv) / 2.0)
- loopJoint.append(len(verts))
-
- # Rotate the vert
- cosAng = cos(-angle)
- sinAng = sin(-angle)
- LocXnew = locX * cosAng - locZ * sinAng
- LocZnew = locZ * cosAng + locX * sinAng
- locZ = LocZnew
- locX = LocXnew
-
- verts.append([
- locX * radius,
- locY * radius,
- locZ * radius])
- else:
- # These two vertices will only be
- # added the very first time.
- if vertIdx == 0 or vertIdx == div / 2:
- verts.append([locX * radius, locY * radius, locZ])
-
- loopsJointsTemp.append(loopJoint)
-
- # Create complete loops (loopsJoints) out of the
- # double number of half loops in loopsJointsTemp.
- for halfLoopIdx in range(len(loopsJointsTemp)):
- if (halfLoopIdx == len(loopsJointsTemp) - 1):
- idx1 = halfLoopIdx
- idx2 = 0
- else:
- idx1 = halfLoopIdx
- idx2 = halfLoopIdx + 1
-
- loopJoint = []
- loopJoint.append(vertTemp2)
- loopJoint.extend(reversed(loopsJointsTemp[idx2]))
- loopJoint.append(vertTemp1)
- loopJoint.extend(loopsJointsTemp[idx1])
-
- loopsJoints.append(loopJoint)
-
- # Create faces from the two
- # loop arrays (loopsJoints -> loopsEndCircles).
- for loopIdx in range(len(loopsEndCircles)):
- faces.extend(
- createFaces(loopsJoints[loopIdx],
- loopsEndCircles[loopIdx], closed=True))
-
- obj = create_mesh_object(context, verts, [], faces,
- "N Joint", edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-
-class INFO_MT_mesh_pipe_joints_add(bpy.types.Menu):
- # Define the "Pipe Joints" menu
- bl_idname = "INFO_MT_mesh_pipe_joints_add"
- bl_label = "Pipe Joints"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("mesh.primitive_elbow_joint_add",
- text="Pipe Elbow")
- layout.operator("mesh.primitive_tee_joint_add",
- text="Pipe T-Joint")
- layout.operator("mesh.primitive_wye_joint_add",
- text="Pipe Y-Joint")
- layout.operator("mesh.primitive_cross_joint_add",
- text="Pipe Cross-Joint")
- layout.operator("mesh.primitive_n_joint_add",
- text="Pipe N-Joint")
-
-################################
-
-import space_info
-
-
-# Define "Pipe Joints" menu
-def menu_func(self, context):
- self.layout.menu("INFO_MT_mesh_pipe_joints_add", icon="PLUGIN")
-
-
-def register():
- # Add "Pipe Joints" menu to the "Add Mesh" menu
- space_info.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- # Remove "Pipe Joints" menu from the "Add Mesh" menu.
- space_info.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_solid.py b/add_mesh_solid.py
deleted file mode 100644
index 0822250a..00000000
--- a/add_mesh_solid.py
+++ /dev/null
@@ -1,902 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Regular Solids",
- "author": "DreamPainter",
- "version": (1,),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh > Regular Solids",
- "description": "Add a Regular Solid mesh.",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Solid",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22405&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-
-import bpy
-from bpy.props import FloatProperty,EnumProperty,BoolProperty
-from math import sqrt
-from mathutils import Vector,Matrix
-#from rawMeshUtils import *
-from functools import reduce
-
-# Apply view rotation to objects if "Align To" for
-# new objects was set to "VIEW" in the User Preference.
-def apply_object_align(context, ob):
- obj_align = bpy.context.user_preferences.edit.object_align
-
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- view3d = context.space_data
- region = view3d.region_3d
- viewMatrix = region.view_matrix
- rot = viewMatrix.rotation_part()
- ob.rotation_euler = rot.invert().to_euler()
-
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- ob_new.location = scene.cursor_location
-
- apply_object_align(context, ob_new)
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-# this function creates a chain of quads and, when necessary, a remaining tri
-# for each polygon created in this script. be aware though, that this function
-# assumes each polygon is convex.
-# poly: list of faces, or a single face, like those
-# needed for mesh.from_pydata.
-# returns the tesselated faces.
-def createPolys(poly):
- # check for faces
- if len(poly) == 0:
- return []
- # one or more faces
- if type(poly[0]) == type(1):
- poly = [poly] # if only one, make it a list of one face
- faces = []
- for i in poly:
- l = len(i)
- # let all faces of 3 or 4 verts be
- if l < 5:
- faces.append(i)
- # split all polygons in half and bridge the two halves
- else:
- half = int(l/2)
- f = createFaces(i[:half],[i[-1-j] for j in range(half)])
- faces.extend(f)
- # if the polygon has an odd number of verts, add the last tri
- if l%2 == 1:
- faces.append([i[half-1],i[half],i[half+1]])
- return faces
-
-# function to make the reduce function work as a workaround to sum a list of vectors
-def Asum(list):
- return reduce(lambda a,b: a+b, list)
-
-# creates the 5 platonic solids as a base for the rest
-# plato: should be one of {"4","6","8","12","20"}. decides what solid the
-# outcome will be.
-# returns a list of vertices and faces and the appropriate name
-def source(plato):
- verts = []
- faces = []
-
- # Tetrahedron
- if plato == "4":
- # Calculate the necessary constants
- s = sqrt(2)/3.0
- t = -1/3
- u = sqrt(6)/3
-
- # create the vertices and faces
- v = [(0,0,1),(2*s,0,t),(-s,u,t),(-s,-u,t)]
- faces = [[0,1,2],[0,2,3],[0,3,1],[1,3,2]]
-
- # Hexahedron (cube)
- elif plato == "6":
- # Calculate the necessary constants
- s = 1/sqrt(3)
-
- # create the vertices and faces
- v = [(-s,-s,-s),(s,-s,-s),(s,s,-s),(-s,s,-s),(-s,-s,s),(s,-s,s),(s,s,s),(-s,s,s)]
- faces = [[0,3,2,1],[0,1,5,4],[0,4,7,3],[6,5,1,2],[6,2,3,7],[6,7,4,5]]
-
- # Octahedron
- elif plato == "8":
- # create the vertices and faces
- v = [(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)]
- faces = [[4,0,2],[4,2,1],[4,1,3],[4,3,0],[5,2,0],[5,1,2],[5,3,1],[5,0,3]]
-
- # Dodecahedron
- elif plato == "12":
- # Calculate the necessary constants
- s = 1/sqrt(3)
- t = sqrt((3-sqrt(5))/6)
- u = sqrt((3+sqrt(5))/6)
-
- # create the vertices and faces
- v = [(s,s,s),(s,s,-s),(s,-s,s),(s,-s,-s),(-s,s,s),(-s,s,-s),(-s,-s,s),(-s,-s,-s),
- (t,u,0),(-t,u,0),(t,-u,0),(-t,-u,0),(u,0,t),(u,0,-t),(-u,0,t),(-u,0,-t),(0,t,u),
- (0,-t,u),(0,t,-u),(0,-t,-u)]
- faces = [[0,8,9,4,16],[0,12,13,1,8],[0,16,17,2,12],[8,1,18,5,9],[12,2,10,3,13],
- [16,4,14,6,17],[9,5,15,14,4],[6,11,10,2,17],[3,19,18,1,13],[7,15,5,18,19],
- [7,11,6,14,15],[7,19,3,10,11]]
-
- # Icosahedron
- elif plato == "20":
- # Calculate the necessary constants
- s = (1+sqrt(5))/2
- t = sqrt(1+s*s)
- s = s/t
- t = 1/t
-
- # create the vertices and faces
- v = [(s,t,0),(-s,t,0),(s,-t,0),(-s,-t,0),(t,0,s),(t,0,-s),(-t,0,s),(-t,0,-s),
- (0,s,t),(0,-s,t),(0,s,-t),(0,-s,-t)]
- faces = [[0,8,4],[0,5,10],[2,4,9],[2,11,5],[1,6,8],[1,10,7],[3,9,6],[3,7,11],
- [0,10,8],[1,8,10],[2,9,11],[3,11,9],[4,2,0],[5,0,2],[6,1,3],[7,3,1],
- [8,6,4],[9,4,6],[10,5,7],[11,7,5]]
-
- # handles faulty values of plato
- else:
- print("Choose keyword 'plato' from {'4','6','8','12','20'}")
- return None
-
- # convert the tuples to Vectors
- verts = [Vector(i) for i in v]
-
- return verts,faces
-
-# processes the raw data from source
-def createSolid(plato,vtrunc,etrunc,dual,snub):
- verts = []
- faces = []
- edges = []
- # the duals from each platonic solid
- dualSource = {"4":"4",
- "6":"8",
- "8":"6",
- "12":"20",
- "20":"12"}
-
- # constants saving space and readability
- vtrunc *= 0.5
- etrunc *= 0.5
- supposed_size = 0
- noSnub = (snub == "0") or (etrunc == 0.5) or (etrunc == 0)
- lSnub = (snub == "L") and (0 < etrunc < 0.5)
- rSnub = (snub == "R") and (0 < etrunc < 0.5)
-
- # no truncation
- if vtrunc == 0:
- if dual: # dual is as simple as another, but mirrored platonic solid
- vInput,fInput = source(dualSource[plato])
- supposed_size = Asum([vInput[i] for i in fInput[0]]).length/len(fInput[0])
- vInput = [-i*supposed_size for i in vInput] # mirror it
- return vInput,fInput
- return source(plato)
- # simple truncation of the source
- elif 0.5 >= vtrunc > 0:
- vInput,fInput = source(plato)
- # truncation is now equal to simple truncation of the dual of the source
- elif vtrunc > 0.5:
- vInput,fInput = source(dualSource[plato])
- supposed_size = Asum([vInput[i] for i in fInput[0]]).length/len(fInput[0])
- # account for the source being a dual
- vtrunc = 1-vtrunc
- if vtrunc == 0: # no truncation
- if dual:
- vInput,fInput = source(plato)
- vInput = [i*supposed_size for i in vInput]
- return vInput,fInput,sourceName
- vInput = [-i*supposed_size for i in vInput]
- return vInput,fInput
-
- # generate a database for creating the faces. this exists out of a list for
- # every vertex in the source
- # 0 : vertex id
- # 1 : vertices connected to this vertex, listed ccw(Counter Clock Wise)
- # 2 : vertices generated to form the faces of this vertex
- # 3 : faces connected to this vertex, listed ccw
- # 4 : dictionairy containing the verts used by the connected faces
- # 5 : list of edges that use this vertex, listed ccw
- # 6 : dictionairy containing the verts used by the connected edges
- v = [[i,[],[],[],{},[],{}] for i in range(len(vInput))]
-
- # this piece of code, generates the database and the lists in ccw order
- for x in range(len(fInput)):
- i = fInput[x]
- # in every faces, check which vertices connect the each vert and sort
- # in ccw order
- for j in range(-1,len(i)-1):
- # only generate an edge dict, if edge truncation is needed
- if etrunc:
- # list edges as [min,max], to evade confusion
- first = min([i[j-1],i[j]])
- last = max([i[j-1],i[j]])
- # if an edge is not allready in, add it and give the index
- try:
- y = edges.index([first,last])
- except:
- edges.append([first,last])
- y = len(edges)-1
- # add a dict item
- v[i[j]][6][str(y)] = [0,0]
- # the vertex before and after the current vertex, check whether they
- # are allready in the database
- after = i[j+1] not in v[i[j]][1]
- before = i[j-1] not in v[i[j]][1]
- # sort them and add faces and, when necessary, edges in the database
- if after:
- if before:
- v[i[j]][1].append(i[j+1])
- v[i[j]][1].append(i[j-1])
- v[i[j]][3].append(x)
- if etrunc: v[i[j]][5].append(y)
- else:
- z = v[i[j]][1].index(i[j-1])
- v[i[j]][1].insert(z,i[j+1])
- v[i[j]][3].insert(z,x)
- if etrunc: v[i[j]][5].insert(z,y)
- else:
- z = v[i[j]][1].index(i[j+1])
- v[i[j]][3].insert(z,x)
- if etrunc: v[i[j]][5].insert(z,y)
- if before:
- v[i[j]][1].insert(z+1,i[j-1])
- # add the current face to the current vertex in the dict
- v[i[j]][4][str(x)] = [0,0]
-
- # generate vert-only truncated vertices by linear interpolation
- for i in v:
- for j in range(len(i[1])):
- verts.append(vInput[i[0]]*(1-vtrunc)+vInput[i[1][j]]*vtrunc)
- l = len(verts)-1
- # face resulting from truncating this vertex
- i[2].append(l)
- # this vertex is used by both faces using this edge
- i[4][str(i[3][j])][1] = l
- i[4][str(i[3][j-1])][0] = l
-
- # only truncate edges when needed
- vert_faces = []
- if etrunc:
- # generate a new list of vertices, by linear interpolating each vert-face
- nVerts = []
- for i in v:
- f = []
- # weird range so we dont run out of array bounds
- for j in range(-1,len(i[2])-1):
- # making use of the fact that the snub operation takes only
- # one of the two vertices per edge. so rSnub only takes the
- # first, lSnub only takes the second, and noSnub takes both
- if rSnub or noSnub:
- # interpolate
- nVerts.append((1-etrunc)*verts[i[2][j]] + etrunc*verts[i[2][j-1]])
- # add last vertex to the vert-face, face-face and edge-face
- l = len(nVerts)-1
- f.append(l)
- i[4][str(i[3][j-1])][0] = l
- i[6][str(i[5][j-1])][1] = l
- if lSnub or noSnub:
- # interpolate
- nVerts.append((1-etrunc)*verts[i[2][j]] + etrunc*verts[i[2][j+1]])
- # add last vertex to the vert-face, face-face and edge-face
- l = len(nVerts)-1
- f.append(l)
- i[4][str(i[3][j])][1] = l
- i[6][str(i[5][j-1])][0] = l
- # add vert-face
- vert_faces.append(f)
-
- # snub operator creates 2 tri's instead of a planar quad, needing the
- # next piece of code. making use of the dictionairy to create them.
- if lSnub or rSnub:
- edge_faces = []
- for x in range(len(edges)):
- one = v[edges[x][0]] # the first vertex of this edge
- two = v[edges[x][1]] # the second
- # using max() since the dict consists of one filled spot and one
- # empty('cause only one vert is created)
- f = [max(two[6][str(x)]),max(one[6][str(x)])]
- index = one[5].index(x)
- # create this tri from the middle line and the the previous edge
- # on this vertex
- if lSnub:
- f.append(max(one[6][str(one[5][index-1])]))
- else: # or in this case, the next
- if index+1 >= len(one[5]): index = -1
- f.append(max(one[6][str(one[5][index+1])]))
- edge_faces.append(f)
-
- # do the same for the other end of the edge
- f = [max(one[6][str(x)]),max(two[6][str(x)])]
- index = two[5].index(x)
- if lSnub:
- f.append(max(two[6][str(two[5][index-1])]))
- else:
- if index+1 >= len(one[5]): index = -1
- f.append(max(two[6][str(two[5][index+1])]))
- edge_faces.append(f)
- else:
- # generate edge-faces from the dictionairy, simple quads for noSnub
- edge_faces = []
- for i in range(len(edges)):
- f = []
- for j in edges[i]:
- f.extend(v[j][6][str(i)])
- edge_faces.append(f)
- verts = nVerts
- else:
- # generate vert-faces for non-edge-truncation
- vert_faces = [i[2] for i in v]
-
- # calculate supposed vertex length to ensure continuity
- if supposed_size:
- supposed_size *= len(vert_faces[0])/Asum([verts[i] for i in vert_faces[0]]).length
- verts = [-i*supposed_size for i in verts]
-
- # generate face-faces by looking up the old verts and replacing them with
- # the vertices in the dictionairy
- face_faces = []
- for x in range(len(fInput)):
- f = []
- for j in fInput[x]:
- # again using the fact, that only one of the two verts is used
- # for snub operation
- if rSnub and etrunc:
- f.append(v[j][4][str(x)][0])
- elif lSnub and etrunc:
- f.append(v[j][4][str(x)][1])
- else:
- # for cool graphics, comment the first line and uncomment the second line
- # then work the vTrunc property, leave the other properties at 0
- # (can also change 0 to 1 in second line to change from ccw to cw)
- f.extend(v[j][4][str(x)]) # first
- #f.append(v[j][4][str(x)][0]) # second
- face_faces.append(f)
-
- if dual:
- # create verts by taking the average of all vertices that make up each
- # face. do it in this order to ease the following face creation
- nVerts = []
- for i in vert_faces:
- nVerts.append(Asum([verts[j] for j in i])/len(i))
- if etrunc:
- eStart = len(nVerts)
- for i in edge_faces:
- nVerts.append(Asum([verts[j] for j in i])/len(i))
- fStart = len(nVerts)
- for i in face_faces:
- nVerts.append(Asum([verts[j] for j in i])/len(i))
- # the special face generation for snub duals, it sucks, even i dont get it
- if lSnub or rSnub:
- for x in range(len(fInput)):
- i = fInput[x]
- for j in range(-1,len(i)-1):
-
- if i[j] > i[j+1]:
- eNext = edges.index([i[j+1],i[j]])
- [a,b] = [1,0]
- else:
- eNext = edges.index([i[j],i[j+1]])
- [a,b] = [0,1]
- if i[j] > i[j-1]:
- ePrev = edges.index([i[j-1],i[j]])
- [c,d] = [0,1]
- else:
- ePrev = edges.index([i[j],i[j-1]])
- [c,d] = [1,0]
- if lSnub:
- f = [eStart+2*eNext+b,eStart+2*eNext+a,i[j]]
- f.append(eStart+2*ePrev+d)
- f.append(fStart + x)
- else:
- f = [eStart+2*ePrev+c,eStart+2*ePrev+d,i[j]]
- f.append(eStart+2*eNext+a)
- f.append(fStart + x)
- if supposed_size: faces.append(f)
- else: faces.append(f[2:]+f[:2])
- else:
- # for noSnub situations, the face generation is somewhat easier.
- # first calculate what order faces must be added to ensure convex solids
- # this by calculating the angle between the middle of the four vertices
- # and the first face. if the face is above the middle, use that diagonal
- # otherwise use the other diagonal
- if etrunc:
- f = [v[0][0],eStart+v[0][5][-1],fStart+v[0][3][0],eStart+v[0][5][0]]
- else:
- f = [v[0][0],fStart+v[0][3][0],v[0][1][0],fStart+v[0][3][-1]]
- p = [nVerts[i] for i in f]
- mid = 0.25*Asum(p)
- norm = (p[1]-p[0]).cross(p[2]-p[0])
- dot = norm.dot(mid-p[0])/(norm.length*(mid-p[0]).length)
- tollerance = 0.001 # ~ cos(0.06 degrees)
- if ((dot > tollerance) and (not supposed_size)) or ((dot < -tollerance) and (supposed_size)):
- direction = 1 # first diagonal
- elif ((dot < -tollerance) and (not supposed_size)) or ((dot > tollerance) and (supposed_size)):
- direction = -1 # second diagonal
- else:
- direction = 0 # no diagonal, face is planar (somewhat)
-
- if etrunc: # for every vertex
- for i in v: # add the face, consisting of the vert,edge,next
- # edge and face between those edges
- for j in range(len(i[1])):
- f = [i[0],eStart+i[5][j-1],fStart+i[3][j],eStart+i[5][j]]
- if direction == 1: # first diagonal
- faces.extend([[f[0],f[1],f[3]],[f[1],f[2],f[3]]])
- elif direction == -1: # first diagonal
- faces.extend([[f[0],f[1],f[2]],[f[0],f[2],f[3]]])
- else:
- faces.append(f) # no diagonal
- else:
- for i in v: # for every vertex
- for j in range(len(i[1])):
- if i[0] < i[1][j]: # face consists of vert, vert on other
- # end of edge and both faces using that
- # edge, so exclude verts allready used
- f = [i[0],fStart+i[3][j], i[1][j],fStart+i[3][j-1]]
- if direction == -1: # secong diagonal
- faces.extend([[f[0],f[1],f[3]],[f[1],f[2],f[3]]])
- elif direction == 1: # first diagonal
- faces.extend([[f[0],f[1],f[2]],[f[0],f[2],f[3]]])
- else:
- faces.append(f) # no diagonal
- verts = nVerts # use new vertices
- else:
- # concatenate all faces, since they dont have to be used sepperately anymore
- faces = face_faces
- if etrunc: faces += edge_faces
- faces += vert_faces
-
- return verts,faces
-
-
-class Solids(bpy.types.Operator):
- """Add one of the (regular) solids (mesh)"""
- bl_idname = "mesh.primitive_solid_add"
- bl_label = "(Regular) solids"
- bl_description = "Add one of the platoic or archimedean solids"
- bl_options = {'REGISTER', 'UNDO'}
-
- source = EnumProperty(items = (("4","Tetrahedron",""),
- ("6","Hexahedron",""),
- ("8","Octahedron",""),
- ("12","Dodecahedron",""),
- ("20","Icosahedron","")),
- name = "Source",
- description = "Starting point of your solid")
- size = FloatProperty(name = "Size",
- description = "Radius of the sphere through the vertices",
- min = 0.01,
- soft_min = 0.01,
- max = 100,
- soft_max = 100,
- default = 1.0)
- vTrunc = FloatProperty(name = "Vertex Truncation",
- description = "Ammount of vertex truncation",
- min = 0.0,
- soft_min = 0.0,
- max = 2.0,
- soft_max = 2.0,
- default = 0.0,
- precision = 3,
- step = 0.5)
- eTrunc = FloatProperty(name = "Edge Truncation",
- description = "Ammount of edge truncation",
- min = 0.0,
- soft_min = 0.0,
- max = 1.0,
- soft_max = 1.0,
- default = 0.0,
- precision = 3,
- step = 0.2)
- snub = EnumProperty(items = (("0","No Snub",""),
- ("L","Left Snub",""),
- ("R","Right Snub","")),
- name = "Snub",
- description = "Create the snub version")
- dual = BoolProperty(name="Dual",
- description="Create the dual of the current solid",
- default=False)
- keepSize = BoolProperty(name="Keep Size",
- description="Keep the whole solid at a constant size",
- default=False)
- preset = EnumProperty(items = (("0","Custom",""),
- ("t4","Truncated Tetrahedron",""),
- ("r4","Cuboctahedron",""),
- ("t6","Truncated Cube",""),
- ("t8","Truncated Octahedron",""),
- ("b6","Rhombicuboctahedron",""),
- ("c6","Truncated Cuboctahedron",""),
- ("s6","Snub Cube",""),
- ("r12","Icosidodecahedron",""),
- ("t12","Truncated Dodecahedron",""),
- ("t20","Truncated Icosahedron",""),
- ("b12","Rhombicosidodecahedron",""),
- ("c12","Truncated Icosidodecahedron",""),
- ("s12","Snub Dodecahedron",""),
- ("dt4","Triakis Tetrahedron",""),
- ("dr4","Rhombic Dodecahedron",""),
- ("dt6","Triakis Octahedron",""),
- ("dt8","Triakis Hexahedron",""),
- ("db6","Deltoidal Icositetrahedron",""),
- ("dc6","Disdyakis Dodecahedron",""),
- ("ds6","Pentagonal Icositetrahedron",""),
- ("dr12","Rhombic Triacontahedron",""),
- ("dt12","Triakis Icosahedron",""),
- ("dt20","Pentakis Dodecahedron",""),
- ("db12","Deltoidal Hexecontahedron",""),
- ("dc12","Disdyakis Triacontahedron",""),
- ("ds12","Pentagonal Hexecontahedron",""),
- ("c","Cube",""),
- ("sb","Soccer ball","")),
- name = "Presets",
- description = "Parameters for some hard names")
-
- # actual preset values
- p = {"t4":["4",2/3,0,0,"0"],
- "r4":["4",1,1,0,"0"],
- "t6":["6",2/3,0,0,"0"],
- "t8":["8",2/3,0,0,"0"],
- "b6":["6",1.0938,1,0,"0"],
- "c6":["6",1.0572,0.585786,0,"0"],
- "s6":["6",1.0875,0.704,0,"L"],
- "r12":["12",1,0,0,"0"],
- "t12":["12",2/3,0,0,"0"],
- "t20":["20",2/3,0,0,"0"],
- "b12":["12",1.1338,1,0,"0"],
- "c12":["20",0.921,0.553,0,"0"],
- "s12":["12",1.1235,0.68,0,"L"],
- "dt4":["4",2/3,0,1,"0"],
- "dr4":["4",1,2/3,1,"0"],
- "dt6":["6",4/3,0,1,"0"],
- "dt8":["8",1,0,1,"0"],
- "db6":["6",1.0938,0.756,1,"0"],
- "dc6":["6",1,1,1,"0"],
- "ds6":["6",1.0875,0.704,1,"L"],
- "dr12":["12",1.54,0,1,"0"],
- "dt12":["12",5/3,0,1,"0"],
- "dt20":["20",2/3,0,1,"0"],
- "db12":["12",1,0.912,1,"0"],
- "dc12":["20",0.921,1,1,"0"],
- "ds12":["12",1.1235,0.68,1,"L"],
- "c":["6",0,0,0,"0"],
- "sb":["20",2/3,0,0,"0"]}
-
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
-
- def execute(self,context):
- # turn off undo for better performance (3 - 5x faster), also makes sure
- # that mesh ops are undoable and entire script acts as one operator
- bpy.context.user_preferences.edit.use_global_undo = False
-
- props = self.properties
-
- #if preset, set preset
- if props.preset != "0":
- using = self.p[props.preset]
- props.source = using[0]
- props.vTrunc = using[1]
- props.eTrunc = using[2]
- props.dual = using[3]
- props.snub = using[4]
- props.preset = "0"
-
- # generate mesh
- verts,faces = createSolid(props.source,
- props.vTrunc,
- props.eTrunc,
- props.dual,
- props.snub)
-
- # turn n-gons in quads and tri's
- faces = createPolys(faces)
-
- # resize to normal size, or if keepSize, make sure all verts are of length 'size'
- if props.keepSize:
- rad = props.size/verts[0].length
- else: rad = props.size
- verts = [i*rad for i in verts]
-
- # generate object
- obj = create_mesh_object(context,verts,[],faces,"Solid",props.edit)
-
- # vertices will be on top of each other in some cases,
- # so remove doubles then
- if ((props.vTrunc == 1) and (props.eTrunc == 0)) or (props.eTrunc == 1):
- current_mode = obj.mode
- if current_mode == 'OBJECT':
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.remove_doubles()
- bpy.ops.object.mode_set(mode=current_mode)
-
- # snub duals suck, so make all normals point outwards
- if props.dual and (props.snub != "0"):
- current_mode = obj.mode
- if current_mode == 'OBJECT':
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.normals_make_consistent()
- bpy.ops.object.mode_set(mode=current_mode)
-
- # turn undo back on
- bpy.context.user_preferences.edit.use_global_undo = True
-
- return {'FINISHED'}
-
-class Solids_add_menu(bpy.types.Menu):
- """Define the menu with presets"""
- bl_idname = "Solids_add_menu"
- bl_label = "Solids"
-
- def draw(self,context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator(Solids.bl_idname, text = "Solid")
- layout.menu(PlatonicMenu.bl_idname, text = "Platonic")
- layout.menu(ArchiMenu.bl_idname, text = "Archimeadean")
- layout.menu(CatalanMenu.bl_idname, text = "Catalan")
- layout.menu(OtherMenu.bl_idname, text = "Others")
-
-class PlatonicMenu(bpy.types.Menu):
- """Define Platonic menu"""
- bl_idname = "Platonic_calls"
- bl_label = "Platonic"
-
- def draw(self,context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator(Solids.bl_idname, text = "Tetrahedron").source = "4"
- layout.operator(Solids.bl_idname, text = "Hexahedron").source = "6"
- layout.operator(Solids.bl_idname, text = "Octahedron").source = "8"
- layout.operator(Solids.bl_idname, text = "Dodecahedron").source = "12"
- layout.operator(Solids.bl_idname, text = "Icosahedron").source = "20"
-
-class ArchiMenu(bpy.types.Menu):
- """Defines Achimedean preset menu"""
- bl_idname = "Achimedean_calls"
- bl_label = "Archimedean"
-
- def draw(self,context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator(Solids.bl_idname, text = "Truncated Tetrahedron").preset = "t4"
- layout.operator(Solids.bl_idname, text = "Cuboctahedron").preset = "r4"
- layout.operator(Solids.bl_idname, text = "Truncated Cube").preset = "t6"
- layout.operator(Solids.bl_idname, text = "Truncated Octahedron").preset = "t8"
- layout.operator(Solids.bl_idname, text = "Rhombicuboctahedron").preset = "b6"
- layout.operator(Solids.bl_idname, text = "Truncated Cuboctahedron").preset = "c6"
- layout.operator(Solids.bl_idname, text = "Snub Cube").preset = "s6"
- layout.operator(Solids.bl_idname, text = "Icosidodecahedron").preset = "r12"
- layout.operator(Solids.bl_idname, text = "Truncated Dodecahedron").preset = "t12"
- layout.operator(Solids.bl_idname, text = "Truncated Icosahedron").preset = "t20"
- layout.operator(Solids.bl_idname, text = "Rhombicosidodecahedron").preset = "b12"
- layout.operator(Solids.bl_idname, text = "Truncated Icosidodecahedron").preset = "c12"
- layout.operator(Solids.bl_idname, text = "Snub Dodecahedron").preset = "s12"
-
-class CatalanMenu(bpy.types.Menu):
- """Defines Catalan preset menu"""
- bl_idname = "Catalan_calls"
- bl_label = "Catalan"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator(Solids.bl_idname, text = "Triakis Tetrahedron").preset = "dt4"
- layout.operator(Solids.bl_idname, text = "Rhombic Dodecahedron").preset = "dr4"
- layout.operator(Solids.bl_idname, text = "Triakis Octahedron").preset = "dt6"
- layout.operator(Solids.bl_idname, text = "Triakis Hexahedron").preset = "dt8"
- layout.operator(Solids.bl_idname, text = "Deltoidal Icositetrahedron").preset = "db6"
- layout.operator(Solids.bl_idname, text = "Disdyakis Dodecahedron").preset = "dc6"
- layout.operator(Solids.bl_idname, text = "Pentagonal Icositetrahedron").preset = "ds6"
- layout.operator(Solids.bl_idname, text = "Rhombic Triacontahedron").preset = "dr12"
- layout.operator(Solids.bl_idname, text = "Triakis Icosahedron").preset = "dt12"
- layout.operator(Solids.bl_idname, text = "Pentakis Dodecahedron").preset = "dt20"
- layout.operator(Solids.bl_idname, text = "Deltoidal Hexecontahedron").preset = "dt20"
- layout.operator(Solids.bl_idname, text = "Disdyakis Triacontahedron").preset = "db12"
- layout.operator(Solids.bl_idname, text = "Pentagonal Hexecontahedron").preset = "ds12"
-
-class OtherMenu(bpy.types.Menu):
- """Defines Others preset menu"""
- bl_idname = "Others_calls"
- bl_label = "Others"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator(Solids.bl_idname, text = "Cube").preset = "c"
- layout.operator(Solids.bl_idname, text = "Soccer ball").preset = "sb"
-
-
-import space_info
-
-
-def menu_func(self, context):
- self.layout.menu(Solids_add_menu.bl_idname, icon="PLUGIN")
-
-
-def register():
- space_info.INFO_MT_mesh_add.append(menu_func)
-
-def unregister():
- space_info.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/add_mesh_twisted_torus.py b/add_mesh_twisted_torus.py
deleted file mode 100644
index c2a598ec..00000000
--- a/add_mesh_twisted_torus.py
+++ /dev/null
@@ -1,363 +0,0 @@
-# add_mesh_twisted_torus.py Copyright (C) 2009-2010, Paulo Gomes
-# tuga3d {at} gmail {dot} com
-# add twisted torus to the blender 2.50 add->mesh menu
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Twisted Torus",
- "author": "Paulo_Gomes",
- "version": (0,11),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Add > Mesh ",
- "description": "Adds a mesh Twisted Torus to the Add Mesh menu",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Add_Twisted_Torus",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21622&group_id=153&atid=469",
- "category": "Add Mesh"}
-
-"""
-Usage:
-
-* Launch from Add Mesh menu
-
-* Modify parameters as desired or keep defaults
-"""
-
-
-import bpy
-from bpy.props import *
-
-import mathutils
-from mathutils import *
-from math import cos, sin, pi
-
-# calculates the matrix for the new object
-# depending on user pref
-def align_matrix(context):
- loc = Matrix.Translation(context.scene.cursor_location)
- obj_align = context.user_preferences.edit.object_align
- if (context.space_data.type == 'VIEW_3D'
- and obj_align == 'VIEW'):
- rot = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
- else:
- rot = Matrix()
- align_matrix = loc * rot
- return align_matrix
-
-
-# Create a new mesh (object) from verts/edges/faces.
-# verts/edges/faces ... List of vertices/edges/faces for the
-# new mesh (as used in from_pydata).
-# name ... Name of the new mesh (& object).
-# edit ... Replace existing mesh data.
-# Note: Using "edit" will destroy/delete existing mesh data.
-def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix):
- scene = context.scene
- obj_act = scene.objects.active
-
- # Can't edit anything, unless we have an active obj.
- if edit and not obj_act:
- return None
-
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Make a mesh from a list of verts/edges/faces.
- mesh.from_pydata(verts, edges, faces)
-
- # Update mesh geometry after adding stuff.
- mesh.update()
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- if edit:
- # Replace geometry of existing object
-
- # Use the active obj and select it.
- ob_new = obj_act
- ob_new.select = True
-
- if obj_act.mode == 'OBJECT':
- # Get existing mesh datablock.
- old_mesh = ob_new.data
-
- # Set object data to nothing
- ob_new.data = None
-
- # Clear users of existing mesh datablock.
- old_mesh.user_clear()
-
- # Remove old mesh datablock if no users are left.
- if (old_mesh.users == 0):
- bpy.data.meshes.remove(old_mesh)
-
- # Assign new mesh datablock.
- ob_new.data = mesh
-
- else:
- # Create new object
- ob_new = bpy.data.objects.new(name, mesh)
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- # Place the object at the 3D cursor location.
- # apply viewRotaion
- ob_new.matrix_world = align_matrix
-
- if obj_act and obj_act.mode == 'EDIT':
- if not edit:
- # We are in EditMode, switch to ObjectMode.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Select the active object as well.
- obj_act.select = True
-
- # Apply location of new object.
- scene.update()
-
- # Join new object into the active.
- bpy.ops.object.join()
-
- # Switching back to EditMode.
- bpy.ops.object.mode_set(mode='EDIT')
-
- ob_new = obj_act
-
- else:
- # We are in ObjectMode.
- # Make the new object the active one.
- scene.objects.active = ob_new
-
- return ob_new
-
-
-# A very simple "bridge" tool.
-# Connects two equally long vertex rows with faces.
-# Returns a list of the new faces (list of lists)
-#
-# vertIdx1 ... First vertex list (list of vertex indices).
-# vertIdx2 ... Second vertex list (list of vertex indices).
-# closed ... Creates a loop (first & last are closed).
-# flipped ... Invert the normal of the face(s).
-#
-# Note: You can set vertIdx1 to a single vertex index to create
-# a fan/star of faces.
-# Note: If both vertex idx list are the same length they have
-# to have at least 2 vertices.
-def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
- faces = []
-
- if not vertIdx1 or not vertIdx2:
- return None
-
- if len(vertIdx1) < 2 and len(vertIdx2) < 2:
- return None
-
- fan = False
- if (len(vertIdx1) != len(vertIdx2)):
- if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
- fan = True
- else:
- return None
-
- total = len(vertIdx2)
-
- if closed:
- # Bridge the start with the end.
- if flipped:
- face = [
- vertIdx1[0],
- vertIdx2[0],
- vertIdx2[total - 1]]
- if not fan:
- face.append(vertIdx1[total - 1])
- faces.append(face)
-
- else:
- face = [vertIdx2[0], vertIdx1[0]]
- if not fan:
- face.append(vertIdx1[total - 1])
- face.append(vertIdx2[total - 1])
- faces.append(face)
-
- # Bridge the rest of the faces.
- for num in range(total - 1):
- if flipped:
- if fan:
- face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
- else:
- face = [vertIdx2[num], vertIdx1[num],
- vertIdx1[num + 1], vertIdx2[num + 1]]
- faces.append(face)
- else:
- if fan:
- face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
- else:
- face = [vertIdx1[num], vertIdx2[num],
- vertIdx2[num + 1], vertIdx1[num + 1]]
- faces.append(face)
-
- return faces
-
-
-def add_twisted_torus(major_rad, minor_rad, major_seg, minor_seg, twists):
- PI_2 = pi * 2.0
- z_axis = (0.0, 0.0, 1.0)
-
- verts = []
- faces = []
-
- edgeloop_prev = []
- for major_index in range(major_seg):
- quat = Quaternion(z_axis, (major_index / major_seg) * PI_2)
- rot_twists = PI_2 * major_index / major_seg * twists
-
- edgeloop = []
-
- # Create section ring
- for minor_index in range(minor_seg):
- angle = (PI_2 * minor_index / minor_seg) + rot_twists
-
- vec = Vector((
- major_rad + (cos(angle) * minor_rad),
- 0.0,
- sin(angle) * minor_rad))
- vec = vec * quat
-
- edgeloop.append(len(verts))
- verts.append(vec)
-
- # Remember very first edgeloop.
- if major_index == 0:
- edgeloop_first = edgeloop
-
- # Bridge last with current ring
- if edgeloop_prev:
- f = createFaces(edgeloop_prev, edgeloop, closed=True)
- faces.extend(f)
-
- edgeloop_prev = edgeloop
-
- # Bridge first and last ring
- f = createFaces(edgeloop_prev, edgeloop_first, closed=True)
- faces.extend(f)
-
- return verts, faces
-
-
-class AddTwistedTorus(bpy.types.Operator):
- '''Add a torus mesh'''
- bl_idname = "mesh.primitive_twisted_torus_add"
- bl_label = "Add Torus"
- bl_options = {'REGISTER', 'UNDO'}
-
- # edit - Whether to add or update.
- edit = BoolProperty(name="",
- description="",
- default=False,
- options={'HIDDEN'})
- major_radius = FloatProperty(name="Major Radius",
- description="Radius from the origin to the" \
- " center of the cross section",
- min=0.01,
- max=100.0,
- default=1.0)
- minor_radius = FloatProperty(name="Minor Radius",
- description="Radius of the torus' cross section",
- min=0.01,
- max=100.0,
- default=0.25)
- major_segments = IntProperty(name="Major Segments",
- description="Number of segments for the main ring of the torus",
- min=3,
- max=256,
- default=48)
- minor_segments = IntProperty(name="Minor Segments",
- description="Number of segments for the minor ring of the torus",
- min=3,
- max=256,
- default=12)
- twists = IntProperty(name="Twists",
- description="Number of twists of the torus",
- min=0,
- max=256,
- default=1)
-
- use_abso = BoolProperty(name="Use Int+Ext Controls",
- description="Use the Int / Ext controls for torus dimensions",
- default=False)
- abso_major_rad = FloatProperty(name="Exterior Radius",
- description="Total Exterior Radius of the torus",
- min=0.01,
- max=100.0,
- default=1.0)
- abso_minor_rad = FloatProperty(name="Inside Radius",
- description="Total Interior Radius of the torus",
- min=0.01,
- max=100.0,
- default=0.5)
- align_matrix = Matrix()
-
- def execute(self, context):
- props = self.properties
-
- if props.use_abso == True:
- extra_helper = (props.abso_major_rad - props.abso_minor_rad) * 0.5
- props.major_radius = props.abso_minor_rad + extra_helper
- props.minor_radius = extra_helper
-
- verts, faces = add_twisted_torus(
- props.major_radius,
- props.minor_radius,
- props.major_segments,
- props.minor_segments,
- props.twists)
-
- # Actually create the mesh object from this geometry data.
- obj = create_mesh_object(context, verts, [], faces, "TwistedTorus",
- props.edit, self.align_matrix)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.align_matrix = align_matrix(context)
- self.execute(context)
- return {'FINISHED'}
-
-# Add to the menu
-def menu_func(self, context):
- self.layout.operator(AddTwistedTorus.bl_idname, text="Twisted Torus", icon='MESH_TORUS')
-
-
-def register():
- bpy.types.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/curve_simplify.py b/curve_simplify.py
deleted file mode 100644
index f723b99d..00000000
--- a/curve_simplify.py
+++ /dev/null
@@ -1,597 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Simplify curves",
- "author": "testscreenings",
- "version": (1,),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Toolshelf > search > simplify curves",
- "description": "This script simplifies 3D curves and fcurves",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Curve/Curve_Simplify",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22327&group_id=153&atid=468",
- "category": "Add Curve"}
-
-"""
-This script simplifies Curves.
-"""
-
-####################################################
-import bpy
-from bpy.props import *
-import mathutils
-import math
-
-##############################
-#### simplipoly algorithm ####
-##############################
-# get SplineVertIndicies to keep
-def simplypoly(splineVerts, options):
- # main vars
- newVerts = [] # list of vertindices to keep
- points = splineVerts # list of 3dVectors
- pointCurva = [] # table with curvatures
- curvatures = [] # averaged curvatures per vert
- for p in points:
- pointCurva.append([])
- order = options[3] # order of sliding beziercurves
- k_thresh = options[2] # curvature threshold
- dis_error = options[6] # additional distance error
-
- # get curvatures per vert
- for i, point in enumerate(points[:-(order-1)]):
- BVerts = points[i:i+order]
- for b, BVert in enumerate(BVerts[1:-1]):
- deriv1 = getDerivative(BVerts, 1/(order-1), order-1)
- deriv2 = getDerivative(BVerts, 1/(order-1), order-2)
- curva = getCurvature(deriv1, deriv2)
- pointCurva[i+b+1].append(curva)
-
- # average the curvatures
- for i in range(len(points)):
- avgCurva = sum(pointCurva[i]) / (order-1)
- curvatures.append(avgCurva)
-
- # get distancevalues per vert - same as Ramer-Douglas-Peucker
- # but for every vert
- distances = [0.0] #first vert is always kept
- for i, point in enumerate(points[1:-1]):
- dist = altitude(points[i], points[i+2], points[i+1])
- distances.append(dist)
- distances.append(0.0) # last vert is always kept
-
- # generate list of vertindicies to keep
- # tested against averaged curvatures and distances of neighbour verts
- newVerts.append(0) # first vert is always kept
- for i, curv in enumerate(curvatures):
- if (curv >= k_thresh*0.01
- or distances[i] >= dis_error*0.1):
- newVerts.append(i)
- newVerts.append(len(curvatures)-1) # last vert is always kept
-
- return newVerts
-
-# get binomial coefficient
-def binom(n, m):
- b = [0] * (n+1)
- b[0] = 1
- for i in range(1, n+1):
- b[i] = 1
- j = i-1
- while j > 0:
- b[j] += b[j-1]
- j-= 1
- return b[m]
-
-# get nth derivative of order(len(verts)) bezier curve
-def getDerivative(verts, t, nth):
- order = len(verts) - 1 - nth
- QVerts = []
-
- if nth:
- for i in range(nth):
- if QVerts:
- verts = QVerts
- derivVerts = []
- for i in range(len(verts)-1):
- derivVerts.append(verts[i+1] - verts[i])
- QVerts = derivVerts
- else:
- QVerts = verts
-
- if len(verts[0]) == 3:
- point = mathutils.Vector((0, 0, 0))
- if len(verts[0]) == 2:
- point = mathutils.Vector((0, 0))
-
- for i, vert in enumerate(QVerts):
- point += binom(order, i) * math.pow(t, i) * math.pow(1-t, order-i) * vert
- deriv = point
-
- return deriv
-
-# get curvature from first, second derivative
-def getCurvature(deriv1, deriv2):
- if deriv1.length == 0: # in case of points in straight line
- curvature = 0
- return curvature
- curvature = (deriv1.cross(deriv2)).length / math.pow(deriv1.length, 3)
- return curvature
-
-#########################################
-#### Ramer-Douglas-Peucker algorithm ####
-#########################################
-# get altitude of vert
-def altitude(point1, point2, pointn):
- edge1 = point2 - point1
- edge2 = pointn - point1
- if edge2.length == 0:
- altitude = 0
- return altitude
- if edge1.length == 0:
- altitude = edge2.length
- return altitude
- alpha = edge1.angle(edge2)
- altitude = math.sin(alpha) * edge2.length
- return altitude
-
-# iterate through verts
-def iterate(points, newVerts, error):
- new = []
- for newIndex in range(len(newVerts)-1):
- bigVert = 0
- alti_store = 0
- for i, point in enumerate(points[newVerts[newIndex]+1:newVerts[newIndex+1]]):
- alti = altitude(points[newVerts[newIndex]], points[newVerts[newIndex+1]], point)
- if alti > alti_store:
- alti_store = alti
- if alti_store >= error:
- bigVert = i+1+newVerts[newIndex]
- if bigVert:
- new.append(bigVert)
- if new == []:
- return False
- return new
-
-#### get SplineVertIndicies to keep
-def simplify_RDP(splineVerts, options):
- #main vars
- error = options[4]
-
- # set first and last vert
- newVerts = [0, len(splineVerts)-1]
-
- # iterate through the points
- new = 1
- while new != False:
- new = iterate(splineVerts, newVerts, error)
- if new:
- newVerts += new
- newVerts.sort()
- return newVerts
-
-##########################
-#### CURVE GENERATION ####
-##########################
-# set bezierhandles to auto
-def setBezierHandles(newCurve):
- scene = bpy.context.scene
- bpy.ops.object.mode_set(mode='EDIT', toggle=True)
- bpy.ops.curve.select_all(action='SELECT')
- bpy.ops.curve.handle_type_set(type='AUTOMATIC')
- bpy.ops.object.mode_set(mode='OBJECT', toggle=True)
-
-# get array of new coords for new spline from vertindices
-def vertsToPoints(newVerts, splineVerts, splineType):
- # main vars
- newPoints = []
-
- # array for BEZIER spline output
- if splineType == 'BEZIER':
- for v in newVerts:
- newPoints += splineVerts[v].to_tuple()
-
- # array for nonBEZIER output
- else:
- for v in newVerts:
- newPoints += (splineVerts[v].to_tuple())
- if splineType == 'NURBS':
- newPoints.append(1) #for nurbs w=1
- else: #for poly w=0
- newPoints.append(0)
- return newPoints
-
-#########################
-#### MAIN OPERATIONS ####
-#########################
-
-def main(context, obj, options):
- #print("\n_______START_______")
- # main vars
- mode = options[0]
- output = options[1]
- degreeOut = options[5]
- keepShort = options[7]
- bpy.ops.object.select_all(action='DESELECT')
- scene = context.scene
- splines = obj.data.splines.values()
-
- # create curvedatablock
- curve = bpy.data.curves.new("simple_"+obj.name, type = 'CURVE')
-
- # go through splines
- for spline_i, spline in enumerate(splines):
- # test if spline is a long enough
- if len(spline.points) >= 7 or keepShort:
- #check what type of spline to create
- if output == 'INPUT':
- splineType = spline.type
- else:
- splineType = output
-
- # get vec3 list to simplify
- if spline.type == 'BEZIER': # get bezierverts
- splineVerts = [splineVert.co.copy()
- for splineVert in spline.bezier_points.values()]
-
- else: # verts from all other types of curves
- splineVerts = [splineVert.co.copy().resize3D()
- for splineVert in spline.points.values()]
-
- # simplify spline according to mode
- if mode == 'distance':
- newVerts = simplify_RDP(splineVerts, options)
-
- if mode == 'curvature':
- newVerts = simplypoly(splineVerts, options)
-
- # convert indicies into vectors3D
- newPoints = vertsToPoints(newVerts, splineVerts, splineType)
-
- # create new spline
- newSpline = curve.splines.new(type = splineType)
-
- # put newPoints into spline according to type
- if splineType == 'BEZIER':
- newSpline.bezier_points.add(int(len(newPoints)*0.33))
- newSpline.bezier_points.foreach_set('co', newPoints)
- else:
- newSpline.points.add(int(len(newPoints)*0.25 - 1))
- newSpline.points.foreach_set('co', newPoints)
-
- # set degree of outputNurbsCurve
- if output == 'NURBS':
- newSpline.order_u = degreeOut
-
- # splineoptions
- newSpline.use_endpoint_u = spline.use_endpoint_u
-
- # create ne object and put into scene
- newCurve = bpy.data.objects.new("simple_"+obj.name, curve)
- scene.objects.link(newCurve)
- newCurve.select = True
- scene.objects.active = newCurve
- newCurve.matrix_world = obj.matrix_world
-
- # set bezierhandles to auto
- setBezierHandles(newCurve)
-
- #print("________END________\n")
- return
-
-##################
-## get preoperator fcurves
-def getFcurveData(obj):
- fcurves = []
- for fc in obj.animation_data.action.fcurves:
- if fc.select:
- fcVerts = [vcVert.co.copy().resize3D()
- for vcVert in fc.keyframe_points.values()]
- fcurves.append(fcVerts)
- return fcurves
-
-def selectedfcurves(obj):
- fcurves_sel = []
- for i, fc in enumerate(obj.animation_data.action.fcurves):
- if fc.select:
- fcurves_sel.append(fc)
- return fcurves_sel
-
-###########################################################
-## fCurves Main
-def fcurves_simplify(context, obj, options, fcurves):
- # main vars
- mode = options[0]
- scene = context.scene
- fcurves_obj = obj.animation_data.action.fcurves
-
- #get indicies of selected fcurves
- fcurve_sel = selectedfcurves(obj)
-
- # go through fcurves
- for fcurve_i, fcurve in enumerate(fcurves):
- # test if fcurve is long enough
- if len(fcurve) >= 7:
-
- # simplify spline according to mode
- if mode == 'distance':
- newVerts = simplify_RDP(fcurve, options)
-
- if mode == 'curvature':
- newVerts = simplypoly(fcurve, options)
-
- # convert indicies into vectors3D
- newPoints = []
-
- #this is different from the main() function for normal curves, different api...
- for v in newVerts:
- newPoints.append(fcurve[v])
-
- #remove all points from curve first
- for i in range(len(fcurve)-1,0,-1):
- fcurve_sel[fcurve_i].keyframe_points.remove(fcurve_sel[fcurve_i].keyframe_points[i])
- # put newPoints into fcurve
- for v in newPoints:
- fcurve_sel[fcurve_i].keyframe_points.add(frame=v[0],value=v[1])
- #fcurve.points.foreach_set('co', newPoints)
- return
-
-#################################################
-#### ANIMATION CURVES OPERATOR ##################
-#################################################
-class GRAPH_OT_simplify(bpy.types.Operator):
- ''''''
- bl_idname = "graph.simplify"
- bl_label = "simplifiy f-curves"
- bl_description = "simplify selected f-curves"
- bl_options = {'REGISTER', 'UNDO'}
-
- ## Properties
- opModes = [
- ('distance', 'distance', 'distance'),
- ('curvature', 'curvature', 'curvature')]
- mode = EnumProperty(name="Mode",
- description="choose algorithm to use",
- items=opModes)
- k_thresh = FloatProperty(name="k",
- min=0, soft_min=0,
- default=0, precision=3,
- description="threshold")
- pointsNr = IntProperty(name="n",
- min=5, soft_min=5,
- max=16, soft_max=9,
- default=5,
- description="degree of curve to get averaged curvatures")
- error = FloatProperty(name="error",
- description="maximum error to allow - distance",
- min=0.0, soft_min=0.0,
- default=0, precision=3)
- degreeOut = IntProperty(name="degree",
- min=3, soft_min=3,
- max=7, soft_max=7,
- default=5,
- description="degree of new curve")
- dis_error = FloatProperty(name="distance error",
- description="maximum error in Blenderunits to allow - distance",
- min=0, soft_min=0,
- default=0.0, precision=3)
- fcurves = []
-
- ''' Remove curvature mode as long as it isnn't significantly improved
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- col = layout.column()
- col.label('Mode:')
- col.prop(props, 'mode', expand=True)
- if self.properties.mode == 'distance':
- box = layout.box()
- box.label(props.mode, icon='ARROW_LEFTRIGHT')
- box.prop(props, 'error', expand=True)
- if self.properties.mode == 'curvature':
- box = layout.box()
- box.label('degree', icon='SMOOTHCURVE')
- box.prop(props, 'pointsNr', expand=True)
- box.label('threshold', icon='PARTICLE_PATH')
- box.prop(props, 'k_thresh', expand=True)
- box.label('distance', icon='ARROW_LEFTRIGHT')
- box.prop(props, 'dis_error', expand=True)
- col = layout.column()
- '''
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- col = layout.column()
- col.prop(props, 'error', expand=True)
-
- ## Check for animdata
- @classmethod
- def poll(cls, context):
- obj = context.active_object
- fcurves = False
- if obj:
- animdata = obj.animation_data
- if animdata:
- act = animdata.action
- if act:
- fcurves = act.fcurves
- return (obj and fcurves)
-
- ## execute
- def execute(self, context):
- #print("------START------")
-
- options = [
- self.properties.mode, #0
- self.properties.mode, #1
- self.properties.k_thresh, #2
- self.properties.pointsNr, #3
- self.properties.error, #4
- self.properties.degreeOut, #6
- self.properties.dis_error] #7
-
- obj = context.active_object
-
- if not self.fcurves:
- self.fcurves = getFcurveData(obj)
-
- fcurves_simplify(context, obj, options, self.fcurves)
-
- #print("-------END-------")
- return {'FINISHED'}
-
-###########################
-##### Curves OPERATOR #####
-###########################
-class CURVE_OT_simplify(bpy.types.Operator):
- ''''''
- bl_idname = "curve.simplify"
- bl_label = "simplifiy curves"
- bl_description = "simplify curves"
- bl_options = {'REGISTER', 'UNDO'}
-
- ## Properties
- opModes = [
- ('distance', 'distance', 'distance'),
- ('curvature', 'curvature', 'curvature')]
- mode = EnumProperty(name="Mode",
- description="choose algorithm to use",
- items=opModes)
- SplineTypes = [
- ('INPUT', 'Input', 'same type as input spline'),
- ('NURBS', 'Nurbs', 'NURBS'),
- ('BEZIER', 'Bezier', 'BEZIER'),
- ('POLY', 'Poly', 'POLY')]
- output = EnumProperty(name="Output splines",
- description="Type of splines to output",
- items=SplineTypes)
- k_thresh = FloatProperty(name="k",
- min=0, soft_min=0,
- default=0, precision=3,
- description="threshold")
- pointsNr = IntProperty(name="n",
- min=5, soft_min=5,
- max=9, soft_max=9,
- default=5,
- description="degree of curve to get averaged curvatures")
- error = FloatProperty(name="error in Bu",
- description="maximum error in Blenderunits to allow - distance",
- min=0, soft_min=0,
- default=0.0, precision=3)
- degreeOut = IntProperty(name="degree",
- min=3, soft_min=3,
- max=7, soft_max=7,
- default=5,
- description="degree of new curve")
- dis_error = FloatProperty(name="distance error",
- description="maximum error in Blenderunits to allow - distance",
- min=0, soft_min=0,
- default=0.0)
- keepShort = BoolProperty(name="keep short Splines",
- description="keep short splines (less then 7 points)",
- default=True)
-
- ''' Remove curvature mode as long as it isnn't significantly improved
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- col = layout.column()
- col.label('Mode:')
- col.prop(props, 'mode', expand=True)
- if self.properties.mode == 'distance':
- box = layout.box()
- box.label(props.mode, icon='ARROW_LEFTRIGHT')
- box.prop(props, 'error', expand=True)
- if self.properties.mode == 'curvature':
- box = layout.box()
- box.label('degree', icon='SMOOTHCURVE')
- box.prop(props, 'pointsNr', expand=True)
- box.label('threshold', icon='PARTICLE_PATH')
- box.prop(props, 'k_thresh', expand=True)
- box.label('distance', icon='ARROW_LEFTRIGHT')
- box.prop(props, 'dis_error', expand=True)
- col = layout.column()
- col.separator()
- col.prop(props, 'output', text='Output', icon='OUTLINER_OB_CURVE')
- if props.output == 'NURBS':
- col.prop(props, 'degreeOut', expand=True)
- col.prop(props, 'keepShort', expand=True)
- '''
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- col = layout.column()
- col.prop(props, 'error', expand=True)
- col.prop(props, 'output', text='Output', icon='OUTLINER_OB_CURVE')
- if props.output == 'NURBS':
- col.prop(props, 'degreeOut', expand=True)
- col.prop(props, 'keepShort', expand=True)
-
-
- ## Check for curve
- @classmethod
- def poll(cls, context):
- obj = context.active_object
- return (obj and obj.type == 'CURVE')
-
- ## execute
- def execute(self, context):
- #print("------START------")
-
- options = [
- self.properties.mode, #0
- self.properties.output, #1
- self.properties.k_thresh, #2
- self.properties.pointsNr, #3
- self.properties.error, #4
- self.properties.degreeOut, #5
- self.properties.dis_error, #6
- self.properties.keepShort] #7
-
-
- bpy.context.user_preferences.edit.use_global_undo = False
-
- bpy.ops.object.mode_set(mode='OBJECT', toggle=True)
- obj = context.active_object
-
- main(context, obj, options)
-
- bpy.context.user_preferences.edit.use_global_undo = True
-
- #print("-------END-------")
- return {'FINISHED'}
-
-#################################################
-#### REGISTER ###################################
-#################################################
-def register():
- pass
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()
diff --git a/io_anim_camera.py b/io_anim_camera.py
deleted file mode 100644
index 50951226..00000000
--- a/io_anim_camera.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-bl_addon_info = {
- "name": "Export Camera Animation",
- "author": "Campbell Barton",
- "version": (0,1),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Export > Camera Animation",
- "description": "Export Cameras & Markers",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File_I-O/Camera_Animation",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22835&group_id=153&atid=469",
- "category": "Import/Export"}
-
-
-import bpy
-
-
-def writeCameras(context, filepath, frame_start, frame_end, only_selected=False):
-
- data_attrs = ['lens', 'shift_x', 'shift_y', 'dof_distance', 'clip_start', 'clip_end', 'draw_size']
- obj_attrs = ['hide_render']
-
- fw = open(filepath, 'w').write
-
- scene = bpy.context.scene
-
- cameras = []
-
- for obj in scene.objects:
- if only_selected and not obj.select:
- continue
- if obj.type != 'CAMERA':
- continue
-
- cameras.append((obj, obj.data))
-
- frame_range = range(frame_start, frame_end + 1)
-
- fw("cameras = {}\n")
- fw("scene = bpy.context.scene\n")
- fw("frame = scene.frame_current - 1\n")
- fw("\n")
-
- for obj, obj_data in cameras:
- fw("data = bpy.data.cameras.new('%s')\n" % obj.name)
- for attr in data_attrs:
- fw("data.%s = %s\n" % (attr, repr(getattr(obj_data, attr))))
-
- fw("obj = bpy.data.objects.new('%s', data)\n" % obj.name)
-
- for attr in obj_attrs:
- fw("obj.%s = %s\n" % (attr, repr(getattr(obj, attr))))
-
- fw("scene.objects.link(obj)\n")
- fw("cameras['%s'] = obj\n" % obj.name)
- fw("\n")
-
-
- for f in frame_range:
- scene.frame_set(f)
- fw("# new frame\n")
- fw("scene.frame_set(%d + frame)\n" % f)
-
- for obj, obj_data in cameras:
- fw("obj = cameras['%s']\n" % obj.name)
-
- matrix = obj.matrix_world.copy()
- fw("obj.location = %s\n" % repr(tuple(matrix.translation_part())))
- fw("obj.scale = %s\n" % repr(tuple(matrix.scale_part())))
- fw("obj.rotation_euler = %s\n" % repr(tuple(matrix.to_euler())))
-
- fw("obj.keyframe_insert('location')\n")
- fw("obj.keyframe_insert('scale')\n")
- fw("obj.keyframe_insert('rotation_euler')\n")
-
- # only key the angle
- fw("data = obj.data\n")
- fw("data.lens = %s\n" % obj_data.lens)
- fw("data.keyframe_insert('lens')\n")
-
- fw("\n")
-
- # now markers
- fw("# markers\n")
- for marker in scene.timeline_markers:
- fw("marker = scene.timeline_markers.new('%s')\n" % marker.name)
- fw("marker.frame = %d + frame\n" % marker.frame)
-
- # will fail if the cameras not selected
- if marker.camera:
- fw("marker.camera = cameras.get('%s')\n" % marker.camera.name)
- fw("\n")
-
-
-from bpy.props import *
-
-
-class CameraExporter(bpy.types.Operator):
- '''Save a python script which re-creartes cameras and markers elsewhere'''
- bl_idname = "export_animation.cameras"
- bl_label = "Export Camera & Markers"
-
- filepath = StringProperty(name="File Path", description="File path used for importing the RAW file", maxlen=1024, default="")
-
- frame_start = IntProperty(name="Start Frame",
- description="Start frame for export",
- default=1, min=1, max=300000)
- frame_end = IntProperty(name="End Frame",
- description="End frame for export",
- default=250, min=1, max=300000)
- only_selected = BoolProperty(name="Only Selected",
- default=True)
-
- def execute(self, context):
- writeCameras(context, self.properties.filepath, self.properties.frame_start, self.properties.frame_end, self.properties.show_only_selected)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.properties.frame_start = context.scene.frame_start
- self.properties.frame_end = context.scene.frame_end
-
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-def menu_export(self, context):
- import os
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".py"
- self.layout.operator(CameraExporter.bl_idname, text="Cameras & Markers (.py)").filepath = default_path
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_export)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_export)
-
-
-if __name__ == "__main__":
- register()
diff --git a/io_export_directx_x.py b/io_export_directx_x.py
deleted file mode 100644
index e32f542a..00000000
--- a/io_export_directx_x.py
+++ /dev/null
@@ -1,1154 +0,0 @@
-# ***** GPL LICENSE BLOCK *****
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-# All rights reserved.
-# ***** GPL LICENSE BLOCK *****
-
-bl_addon_info = {
- "name": "Export DirectX Model Format (.x)",
- "author": "Chris Foster (Kira Vakaan)",
- "version": (1,6),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Export",
- "description": "Export to the DirectX Model Format (.x)",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File_I-O/DirectX_Exporter",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22795&group_id=153&atid=469",
- "category": "Import/Export"}
-
-import os
-from math import radians
-
-import bpy
-from mathutils import *
-
-#Container for the exporter settings
-class DirectXExporterSettings:
- def __init__(self,
- context,
- FilePath,
- CoordinateSystem=1,
- RotateX=True,
- FlipNormals=False,
- ApplyModifiers=False,
- IncludeFrameRate=False,
- ExportTextures=True,
- ExportArmatures=False,
- ExportAnimation=0,
- ExportMode=1,
- Verbose=False):
- self.context = context
- self.FilePath = FilePath
- self.CoordinateSystem = int(CoordinateSystem)
- self.RotateX = RotateX
- self.FlipNormals = FlipNormals
- self.ApplyModifiers = ApplyModifiers
- self.IncludeFrameRate = IncludeFrameRate
- self.ExportTextures = ExportTextures
- self.ExportArmatures = ExportArmatures
- self.ExportAnimation = int(ExportAnimation)
- self.ExportMode = int(ExportMode)
- self.Verbose = Verbose
-
-
-def LegalName(Name):
- NewName = Name.replace(".", "_")
- NewName = NewName.replace(" ", "_")
- if NewName[0].isdigit() or NewName in ["ARRAY",
- "DWORD",
- "UCHAR",
- "BINARY",
- "FLOAT",
- "ULONGLONG",
- "BINARY_RESOURCE",
- "SDWORD",
- "UNICODE",
- "CHAR",
- "STRING",
- "WORD",
- "CSTRING",
- "SWORD",
- "DOUBLE",
- "TEMPLATE"]:
- NewName = "_" + NewName
- return NewName
-
-
-def ExportDirectX(Config):
- print("----------\nExporting to {}".format(Config.FilePath))
- if Config.Verbose:
- print("Opening File...", end=" ")
- Config.File = open(Config.FilePath, "w")
- if Config.Verbose:
- print("Done")
-
- if Config.Verbose:
- print("Generating Object list for export...", end=" ")
- if Config.ExportMode == 1:
- Config.ExportList = [Object for Object in Config.context.scene.objects
- if Object.type in ("ARMATURE", "EMPTY", "MESH")
- and Object.parent == None]
- else:
- ExportList = [Object for Object in Config.context.selected_objects
- if Object.type in ("ARMATURE", "EMPTY", "MESH")]
- Config.ExportList = [Object for Object in ExportList
- if Object.parent not in ExportList]
- if Config.Verbose:
- print("Done")
-
- if Config.Verbose:
- print("Setting up...", end=" ")
- Config.SystemMatrix = Matrix()
- if Config.RotateX:
- Config.SystemMatrix *= Matrix.Rotation(radians(-90), 4, "X")
- if Config.CoordinateSystem == 1:
- Config.SystemMatrix *= Matrix.Scale(-1, 4, Vector((0, 1, 0)))
- Config.InverseSystemMatrix = Config.SystemMatrix.copy().invert()
-
- #Used for animating rotations
- Config.SystemQuaternion = Quaternion((1,0,0,0))
- if Config.RotateX:
- Config.SystemQuaternion = Matrix.Rotation(radians(-90), 3, "X").to_quat()
- Config.InverseSystemQuaternion = Config.SystemQuaternion.copy().inverse()
- Config.FlipZ = -1 if Config.CoordinateSystem == 1 else 1
-
- if Config.ExportAnimation:
- CurrentFrame = bpy.context.scene.frame_current
- bpy.context.scene.frame_current = bpy.context.scene.frame_current
- if Config.Verbose:
- print("Done")
-
- if Config.Verbose:
- print("Writing Header...", end=" ")
- WriteHeader(Config)
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace = 0
- Config.ObjectList = []
- if Config.Verbose:
- print("Writing Objects...")
- WriteObjects(Config, Config.ExportList)
- if Config.Verbose:
- print("Done")
-
- if Config.ExportAnimation:
- if Config.IncludeFrameRate:
- if Config.Verbose:
- print("Writing Frame Rate...", end=" ")
- Config.File.write("{}AnimTicksPerSecond {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, int(bpy.context.scene.render.fps / bpy.context.scene.render.fps_base)))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
- if Config.Verbose:
- print("Writing Animation...")
- if Config.ExportAnimation==1:
- WriteKeyedAnimationSet(Config)
- else:
- WriteFullAnimationSet(Config)
- bpy.context.scene.frame_current = CurrentFrame
- if Config.Verbose:
- print("Done")
-
- CloseFile(Config)
- print("Finished")
-
-
-def GetObjectChildren(Parent):
- return [Object for Object in Parent.children
- if Object.type in ("ARMATURE", "EMPTY", "MESH")]
-
-#Returns the vertex count of Mesh, counting each vertex for every face.
-def GetMeshVertexCount(Mesh):
- VertexCount = 0
- for Face in Mesh.faces:
- VertexCount += len(Face.vertices)
- return VertexCount
-
-#Returns the file path of first image texture from Material.
-def GetMaterialTexture(Material):
- if Material:
- #Create a list of Textures that have type "IMAGE"
- ImageTextures = [Material.texture_slots[TextureSlot].texture for TextureSlot in Material.texture_slots.keys() if Material.texture_slots[TextureSlot].texture.type == "IMAGE"]
- #Refine a new list with only image textures that have a file source
- ImageFiles = [os.path.basename(Texture.image.filepath) for Texture in ImageTextures if Texture.image.source == "FILE"]
- if ImageFiles:
- return ImageFiles[0]
- return None
-
-
-def WriteHeader(Config):
- Config.File.write("xof 0303txt 0032\n\n")
- if Config.ExportArmatures:
- Config.File.write("template XSkinMeshHeader {\n\
- <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n\
- WORD nMaxSkinWeightsPerVertex;\n\
- WORD nMaxSkinWeightsPerFace;\n\
- WORD nBones;\n\
-}\n\n\
-template SkinWeights {\n\
- <6f0d123b-bad2-4167-a0d0-80224f25fabb>\n\
- STRING transformNodeName;\n\
- DWORD nWeights;\n\
- array DWORD vertexIndices[nWeights];\n\
- array float weights[nWeights];\n\
- Matrix4x4 matrixOffset;\n\
-}\n\n")
-
-
-def WriteObjects(Config, ObjectList):
- Config.ObjectList += ObjectList
-
- for Object in ObjectList:
- if Config.Verbose:
- print(" Writing Object: {}...".format(Object.name))
- Config.File.write("{}Frame {} {{\n".format(" " * Config.Whitespace, LegalName(Object.name)))
-
- Config.Whitespace += 1
- if Config.Verbose:
- print(" Writing Local Matrix...", end=" ")
- WriteLocalMatrix(Config, Object)
- if Config.Verbose:
- print("Done")
-
- if Config.ExportArmatures and Object.type == "ARMATURE":
- Armature = Object.data
- ParentList = [Bone for Bone in Armature.bones if Bone.parent == None]
- if Config.Verbose:
- print(" Writing Armature Bones...")
- WriteArmatureBones(Config, Object, ParentList)
- if Config.Verbose:
- print(" Done")
-
- ChildList = GetObjectChildren(Object)
- if Config.Verbose:
- print(" Writing Children...")
- WriteObjects(Config, ChildList)
- if Config.Verbose:
- print(" Done Writing Children")
-
- if Object.type == "MESH":
- if Config.Verbose:
- print(" Generating Mesh...", end=" ")
- if Config.ApplyModifiers:
- if Config.ExportArmatures:
- #Create a copy of the object and remove all armature modifiers so an unshaped
- #mesh can be created from it.
- Object2 = Object.copy()
- for Modifier in [Modifier for Modifier in Object2.modifiers if Modifier.type == "ARMATURE"]:
- Object2.modifiers.remove(Modifier)
- Mesh = Object2.create_mesh(bpy.context.scene, True, "PREVIEW")
- else:
- Mesh = Object.create_mesh(bpy.context.scene, True, "PREVIEW")
- else:
- Mesh = Object.create_mesh(bpy.context.scene, False, "PREVIEW")
- if Config.Verbose:
- print("Done")
- print(" Writing Mesh...")
- WriteMesh(Config, Object, Mesh)
- if Config.Verbose:
- print(" Done")
- if Config.ApplyModifiers and Config.ExportArmatures:
- bpy.data.objects.remove(Object2)
- bpy.data.meshes.remove(Mesh)
-
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
- if Config.Verbose:
- print(" Done Writing Object: {}".format(Object.name))
-
-
-def WriteLocalMatrix(Config, Object):
- LocalMatrix = Config.SystemMatrix * Object.matrix_local * Config.InverseSystemMatrix
-
- Config.File.write("{}FrameTransformMatrix {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[0][0], LocalMatrix[0][1], LocalMatrix[0][2], LocalMatrix[0][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[1][0], LocalMatrix[1][1], LocalMatrix[1][2], LocalMatrix[1][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[2][0], LocalMatrix[2][1], LocalMatrix[2][2], LocalMatrix[2][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, LocalMatrix[3][0], LocalMatrix[3][1], LocalMatrix[3][2], LocalMatrix[3][3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
-
-
-def WriteArmatureBones(Config, Object, ChildList):
- PoseBones = Object.pose.bones
- for Bone in ChildList:
- if Config.Verbose:
- print(" Writing Bone: {}...".format(Bone.name), end=" ")
- Config.File.write("{}Frame {} {{\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
- Config.Whitespace += 1
-
- PoseBone = PoseBones[Bone.name]
-
- if Bone.parent:
- BoneMatrix = (PoseBone.parent.matrix *
- Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- BoneMatrix = Matrix()
-
- BoneMatrix *= PoseBone.matrix * Matrix.Rotation(radians(-90), 4, "X")
- BoneMatrix = Config.SystemMatrix * BoneMatrix * Config.InverseSystemMatrix
-
- Config.File.write("{}FrameTransformMatrix {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[0][0], BoneMatrix[0][1], BoneMatrix[0][2], BoneMatrix[0][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[1][0], BoneMatrix[1][1], BoneMatrix[1][2], BoneMatrix[1][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[2][0], BoneMatrix[2][1], BoneMatrix[2][2], BoneMatrix[2][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, BoneMatrix[3][0], BoneMatrix[3][1], BoneMatrix[3][2], BoneMatrix[3][3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
-
- if Config.Verbose:
- print("Done")
- WriteArmatureBones(Config, Object, Bone.children)
- Config.Whitespace -= 1
-
- Config.File.write("{}}} //End of {}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
-
-
-def WriteMesh(Config, Object, Mesh):
- Config.File.write("{}Mesh {{ //{} Mesh\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
- Config.Whitespace += 1
-
- if Config.Verbose:
- print(" Writing Mesh Vertices...", end=" ")
- WriteMeshVertices(Config, Mesh)
- if Config.Verbose:
- print("Done\n Writing Mesh Normals...", end=" ")
- WriteMeshNormals(Config, Mesh)
- if Config.Verbose:
- print("Done\n Writing Mesh Materials...", end=" ")
- WriteMeshMaterials(Config, Mesh)
- if Config.Verbose:
- print("Done")
- if Mesh.uv_textures:
- if Config.Verbose:
- print(" Writing Mesh UV Coordinates...", end=" ")
- WriteMeshUVCoordinates(Config, Mesh)
- if Config.Verbose:
- print("Done")
- if Config.ExportArmatures:
- if Config.Verbose:
- print(" Writing Mesh Skin Weights...", end=" ")
- WriteMeshSkinWeights(Config, Object, Mesh)
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {} Mesh\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
-
-
-def WriteMeshVertices(Config, Mesh):
- Index = 0
- VertexCount = GetMeshVertexCount(Mesh)
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
-
- for Face in Mesh.faces:
- Vertices = list(Face.vertices)
-
- if Config.CoordinateSystem == 1:
- Vertices = Vertices[::-1]
- for Vertex in [Mesh.vertices[Vertex] for Vertex in Vertices]:
- Position = Config.SystemMatrix * Vertex.co
- Config.File.write("{}{:9f};{:9f};{:9f};".format(" " * Config.Whitespace, Position[0], Position[1], Position[2]))
- Index += 1
- if Index == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
-
- Index = 0
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, len(Mesh.faces)))
-
- for Face in Mesh.faces:
- Config.File.write("{}{};".format(" " * Config.Whitespace, len(Face.vertices)))
- for Vertex in Face.vertices:
- Config.File.write("{};".format(Index))
- Index += 1
- if Index == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
-
-
-def WriteMeshNormals(Config, Mesh):
- Config.File.write("{}MeshNormals {{ //{} Normals\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
- Config.Whitespace += 1
-
- Index = 0
- VertexCount = GetMeshVertexCount(Mesh)
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
-
- for Face in Mesh.faces:
- Vertices = list(Face.vertices)
-
- if Config.CoordinateSystem == 1:
- Vertices = Vertices[::-1]
- for Vertex in [Mesh.vertices[Vertex] for Vertex in Vertices]:
- if Face.use_smooth:
- Normal = Config.SystemMatrix * Vertex.normal
- else:
- Normal = Config.SystemMatrix * Face.normal
- if Config.FlipNormals:
- Normal = -Normal
- Config.File.write("{}{:9f};{:9f};{:9f};".format(" " * Config.Whitespace, Normal[0], Normal[1], Normal[2]))
- Index += 1
- if Index == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
-
- Index = 0
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, len(Mesh.faces)))
-
- for Face in Mesh.faces:
- Config.File.write("{}{};".format(" " * Config.Whitespace, len(Face.vertices)))
- for Vertex in Face.vertices:
- Config.File.write("{};".format(Index))
- Index += 1
- if Index == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {} Normals\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
-
-
-def WriteMeshMaterials(Config, Mesh):
- Config.File.write("{}MeshMaterialList {{ //{} Material List\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
- Config.Whitespace += 1
-
- Materials = Mesh.materials
- if Materials.keys():
- MaterialIndexes = {}
- for Face in Mesh.faces:
- if Materials[Face.material_index] not in MaterialIndexes:
- MaterialIndexes[Materials[Face.material_index]] = len(MaterialIndexes)
-
- FaceCount = len(Mesh.faces)
- Index = 0
- Config.File.write("{}{};\n{}{};\n".format(" " * Config.Whitespace, len(MaterialIndexes), " " * Config.Whitespace, FaceCount))
- for Face in Mesh.faces:
- Config.File.write("{}{}".format(" " * Config.Whitespace, MaterialIndexes[Materials[Face.material_index]]))
- Index += 1
- if Index == FaceCount:
- Config.File.write(";;\n")
- else:
- Config.File.write(",\n")
-
- Materials = [Item[::-1] for Item in MaterialIndexes.items()]
- Materials.sort()
- for Material in Materials:
- WriteMaterial(Config, Material[1])
- else:
- Config.File.write("{}1;\n{}1;\n{}0;;\n".format(" " * Config.Whitespace, " " * Config.Whitespace, " " * Config.Whitespace))
- WriteMaterial(Config)
-
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {} Material List\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
-
-
-def WriteMaterial(Config, Material=None):
- if Material:
- Config.File.write("{}Material {} {{\n".format(" " * Config.Whitespace, LegalName(Material.name)))
- Config.Whitespace += 1
-
- Diffuse = list(Material.diffuse_color)
- Diffuse.append(Material.alpha)
- Specularity = Material.specular_intensity
- Specular = list(Material.specular_color)
-
- Config.File.write("{}{:9f};{:9f};{:9f};{:9f};;\n".format(" " * Config.Whitespace, Diffuse[0], Diffuse[1], Diffuse[2], Diffuse[3]))
- Config.File.write("{}{:9f};\n".format(" " * Config.Whitespace, 2 * (1.0 - Specularity)))
- Config.File.write("{}{:9f};{:9f};{:9f};;\n".format(" " * Config.Whitespace, Specular[0], Specular[1], Specular[2]))
- else:
- Config.File.write("{}Material Default_Material {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{} 1.000000; 1.000000; 1.000000; 1.000000;;\n".format(" " * Config.Whitespace))
- Config.File.write("{} 1.500000;\n".format(" " * Config.Whitespace))
- Config.File.write("{} 1.000000; 1.000000; 1.000000;;\n".format(" " * Config.Whitespace))
- Config.File.write("{} 0.000000; 0.000000; 0.000000;;\n".format(" " * Config.Whitespace))
- if Config.ExportTextures:
- Texture = GetMaterialTexture(Material)
- if Texture:
- Config.File.write("{}TextureFilename {{\"{}\";}}\n".format(" " * Config.Whitespace, Texture))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
-
-
-def WriteMeshUVCoordinates(Config, Mesh):
- Config.File.write("{}MeshTextureCoords {{ //{} UV Coordinates\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
- Config.Whitespace += 1
-
- UVCoordinates = None
- for UV in Mesh.uv_textures:
- if UV.active_render:
- UVCoordinates = UV.data
- break
-
- Index = 0
- VertexCount = GetMeshVertexCount(Mesh)
- Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
-
- for Face in UVCoordinates:
- Vertices = []
- for Vertex in Face.uv:
- Vertices.append(tuple(Vertex))
- if Config.CoordinateSystem == 1:
- Vertices = Vertices[::-1]
- for Vertex in Vertices:
- Config.File.write("{}{:9f};{:9f};".format(" " * Config.Whitespace, Vertex[0], 1 - Vertex[1]))
- Index += 1
- if Index == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {} UV Coordinates\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
-
-
-def WriteMeshSkinWeights(Config, Object, Mesh):
- ArmatureList = [Modifier for Modifier in Object.modifiers if Modifier.type == "ARMATURE"]
- if ArmatureList:
- ArmatureObject = ArmatureList[0].object
- ArmatureBones = ArmatureObject.data.bones
-
- PoseBones = ArmatureObject.pose.bones
-
- MaxInfluences = 0
- UsedBones = set()
- #Maps bones to a list of vertices they affect
- VertexGroups = {}
-
- for Vertex in Mesh.vertices:
- #BoneInfluences contains the bones of the armature that affect the current vertex
- BoneInfluences = [PoseBones[Object.vertex_groups[Group.group].name] for Group in Vertex.groups if Object.vertex_groups[Group.group].name in PoseBones]
- if len(BoneInfluences) > MaxInfluences:
- MaxInfluences = len(BoneInfluences)
- for Bone in BoneInfluences:
- UsedBones.add(Bone)
- if Bone not in VertexGroups:
- VertexGroups[Bone] = [Vertex]
- else:
- VertexGroups[Bone].append(Vertex)
- BoneCount = len(UsedBones)
-
- Config.File.write("{}XSkinMeshHeader {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{};\n{}{};\n{}{};\n".format(" " * Config.Whitespace, MaxInfluences, " " * Config.Whitespace, MaxInfluences * 3, " " * Config.Whitespace, BoneCount))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
-
- for Bone in UsedBones:
- VertexCount = 0
- VertexIndexes = [Vertex.index for Vertex in VertexGroups[Bone]]
- for Face in Mesh.faces:
- for Vertex in Face.vertices:
- if Vertex in VertexIndexes:
- VertexCount += 1
-
- Config.File.write("{}SkinWeights {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}\"{}\";\n{}{};\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name), " " * Config.Whitespace, VertexCount))
-
- VertexWeights = []
- Index = 0
- WrittenIndexes = 0
- for Face in Mesh.faces:
- FaceVertices = list(Face.vertices)
- if Config.CoordinateSystem == 1:
- FaceVertices = FaceVertices[::-1]
- for Vertex in FaceVertices:
- if Vertex in VertexIndexes:
- Config.File.write("{}{}".format(" " * Config.Whitespace, Index))
-
- GroupIndexes = {Object.vertex_groups[Group.group].name: Index for Index, Group in enumerate(Mesh.vertices[Vertex].groups) if Object.vertex_groups[Group.group].name in PoseBones}
-
- WeightTotal = 0.0
- for Weight in [Group.weight for Group in Mesh.vertices[Vertex].groups if Object.vertex_groups[Group.group].name in PoseBones]:
- WeightTotal += Weight
-
- if WeightTotal:
- VertexWeights.append(Mesh.vertices[Vertex].groups[GroupIndexes[Bone.name]].weight / WeightTotal)
- else:
- VertexWeights.append(0.0)
-
- WrittenIndexes += 1
- if WrittenIndexes == VertexCount:
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
- Index += 1
-
- for Index, Weight in enumerate(VertexWeights):
- Config.File.write("{}{:8f}".format(" " * Config.Whitespace, Weight))
- if Index == (VertexCount - 1):
- Config.File.write(";\n")
- else:
- Config.File.write(",\n")
-
- RestBone = ArmatureBones[Bone.name]
-
- #BoneMatrix transforms mesh vertices into the space of the bone.
- #Here are the final transformations in order:
- # - Object Space to World Space
- # - World Space to Armature Space
- # - Armature Space to Bone Space (The bone matrix needs to be rotated 90 degrees to align with Blender's world axes)
- #This way, when BoneMatrix is transformed by the bone's Frame matrix, the vertices will be in their final world position.
-
- BoneMatrix = (RestBone.matrix_local * Matrix.Rotation(radians(-90), 4, "X")).invert()
- BoneMatrix *= ArmatureObject.matrix_world.copy().invert()
- BoneMatrix *= Object.matrix_world
-
- BoneMatrix = Config.SystemMatrix * BoneMatrix * Config.InverseSystemMatrix
-
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[0][0], BoneMatrix[0][1], BoneMatrix[0][2], BoneMatrix[0][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[1][0], BoneMatrix[1][1], BoneMatrix[1][2], BoneMatrix[1][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[2][0], BoneMatrix[2][1], BoneMatrix[2][2], BoneMatrix[2][3]))
- Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, BoneMatrix[3][0], BoneMatrix[3][1], BoneMatrix[3][2], BoneMatrix[3][3]))
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of {} Skin Weights\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name)))
-
-
-def WriteKeyedAnimationSet(Config):
- Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- for Object in [Object for Object in Config.ObjectList if Object.animation_data]:
- if Config.Verbose:
- print(" Writing Animation Data for Object: {}".format(Object.name))
- Action = Object.animation_data.action
- if Action:
- PositionFCurves = [None, None, None]
- RotationFCurves = [None, None, None]
- ScaleFCurves = [None, None, None]
- for FCurve in Action.fcurves:
- if FCurve.data_path == "location":
- PositionFCurves[FCurve.array_index] = FCurve
- elif FCurve.data_path == "rotation_euler":
- RotationFCurves[FCurve.array_index] = FCurve
- elif FCurve.data_path == "scale":
- ScaleFCurves[FCurve.array_index] = FCurve
- if [FCurve for FCurve in PositionFCurves + RotationFCurves + ScaleFCurves if FCurve]:
- Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
-
- #Position
- if Config.Verbose:
- print(" Writing Position...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(PositionFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- PositionFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if len(AllKeyframes):
- Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
- Position = Vector()
- Position[0] = ((PositionFCurves[0][Keyframe] if Keyframe in PositionFCurves[0] else Object.location[0]) if PositionFCurves[0] else Object.location[0])
- Position[1] = ((PositionFCurves[1][Keyframe] if Keyframe in PositionFCurves[1] else Object.location[1]) if PositionFCurves[1] else Object.location[1])
- Position[2] = ((PositionFCurves[2][Keyframe] if Keyframe in PositionFCurves[2] else Object.location[2]) if PositionFCurves[2] else Object.location[2])
- Position = Config.SystemMatrix * Position
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
- else:
- Config.File.write("{}2;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
- bpy.context.scene.frame_set(bpy.context.scene.frame_start)
- Position = Config.SystemMatrix * Object.location
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, ("0;3;").ljust(8), Position[0], Position[1], Position[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Rotation
- if Config.Verbose:
- print(" Writing Rotation...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(RotationFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- RotationFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if len(AllKeyframes):
- Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
- Rotation = Euler()
- Rotation[0] = ((RotationFCurves[0][Keyframe] if Keyframe in RotationFCurves[0] else Object.rotation_euler[0]) if RotationFCurves[0] else Object.rotation_euler[0])
- Rotation[1] = ((RotationFCurves[1][Keyframe] if Keyframe in RotationFCurves[1] else Object.rotation_euler[1]) if RotationFCurves[1] else Object.rotation_euler[1])
- Rotation[2] = ((RotationFCurves[2][Keyframe] if Keyframe in RotationFCurves[2] else Object.rotation_euler[2]) if RotationFCurves[2] else Object.rotation_euler[2])
- Rotation = (Config.SystemMatrix * (Rotation.to_matrix().to_4x4()) * Config.InverseSystemMatrix).to_quat()
- Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";4;").ljust(8), - Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
- else:
- Config.File.write("{}0;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
- bpy.context.scene.frame_set(bpy.context.scene.frame_start)
- Rotation = (Config.SystemMatrix * (Object.rotation_euler.to_matrix().to_4x4()) * Config.InverseSystemMatrix).to_quat()
- Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, ("0;4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Scale
- if Config.Verbose:
- print(" Writing Scale...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(ScaleFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- ScaleFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if len(AllKeyframes):
- Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
- Scale = Vector()
- Scale[0] = ((ScaleFCurves[0][Keyframe] if Keyframe in ScaleFCurves[0] else Object.scale[0]) if ScaleFCurves[0] else Object.scale[0])
- Scale[1] = ((ScaleFCurves[1][Keyframe] if Keyframe in ScaleFCurves[1] else Object.scale[1]) if ScaleFCurves[1] else Object.scale[1])
- Scale[2] = ((ScaleFCurves[2][Keyframe] if Keyframe in ScaleFCurves[2] else Object.scale[2]) if ScaleFCurves[2] else Object.scale[2])
- Scale = Config.SystemMatrix * Scale
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
- else:
- Config.File.write("{}1;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
- bpy.context.scene.frame_set(bpy.context.scene.frame_start)
- Scale = Config.SystemMatrix * Object.scale
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, ("0;3;").ljust(8), Scale[0], Scale[1], Scale[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- else:
- if Config.Verbose:
- print(" Object has no useable animation data.")
-
- if Config.ExportArmatures and Object.type == "ARMATURE":
- if Config.Verbose:
- print(" Writing Armature Bone Animation Data...")
- PoseBones = Object.pose.bones
- for Bone in PoseBones:
- if Config.Verbose:
- print(" Writing Bone: {}...".format(Bone.name))
- PositionFCurves = [None, None, None]
- RotationFCurves = [None, None, None, None]
- ScaleFCurves = [None, None, None]
- for FCurve in Action.fcurves:
- if FCurve.data_path == "pose.bones[\"{}\"].location".format(Bone.name):
- PositionFCurves[FCurve.array_index] = FCurve
- elif FCurve.data_path == "pose.bones[\"{}\"].rotation_quaternion".format(Bone.name):
- RotationFCurves[FCurve.array_index] = FCurve
- elif FCurve.data_path == "pose.bones[\"{}\"].scale".format(Bone.name):
- ScaleFCurves[FCurve.array_index] = FCurve
- if not [FCurve for FCurve in PositionFCurves + RotationFCurves + ScaleFCurves if FCurve]:
- if Config.Verbose:
- print(" Bone has no useable animation data.\n Done")
- continue
-
- Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
-
- #Position
- if Config.Verbose:
- print(" Writing Position...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(PositionFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- PositionFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if not len(AllKeyframes):
- AllKeyframes = [bpy.context.scene.frame_start]
- Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
-
- if Bone.parent:
- PoseMatrix = (Bone.parent.matrix * Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- PoseMatrix = Matrix()
- PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
-
- PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
-
- Position = PoseMatrix.translation_part()
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Rotation
- if Config.Verbose:
- print(" Writing Rotation...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(RotationFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- RotationFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if not len(AllKeyframes):
- AllKeyframes = [bpy.context.scene.frame_start]
- Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
-
- if Bone.parent:
- PoseMatrix = (Bone.parent.matrix * Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- PoseMatrix = Matrix()
- PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
-
- PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
-
- Rotation = PoseMatrix.rotation_part().to_quat()
- Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Scale
- if Config.Verbose:
- print(" Writing Scale...", end=" ")
- AllKeyframes = set()
- for Index, FCurve in enumerate(ScaleFCurves):
- if FCurve:
- Keyframes = []
- for Keyframe in FCurve.keyframe_points:
- Keyframes.append(Keyframe.co)
- AllKeyframes.add(int(Keyframe.co[0]))
- ScaleFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
- Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- AllKeyframes = list(AllKeyframes)
- AllKeyframes.sort()
- if not len(AllKeyframes):
- AllKeyframes = [bpy.context.scene.frame_start]
- Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
- for Keyframe in AllKeyframes:
- bpy.context.scene.frame_set(Keyframe)
-
- if Bone.parent:
- PoseMatrix = (Bone.parent.matrix * Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- PoseMatrix = Matrix()
- PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
-
- PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
-
- Scale = PoseMatrix.scale_part()
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print(" Done") #Done with Armature Bone
- if Config.Verbose:
- print(" Done") #Done with Armature Bone data
- if Config.Verbose:
- print(" Done") #Done with Object
-
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
-
-
-def WriteFullAnimationSet(Config):
- Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
-
- KeyframeCount = bpy.context.scene.frame_end - bpy.context.scene.frame_start + 1
-
- for Object in Config.ObjectList:
- if Config.Verbose:
- print(" Writing Animation Data for Object: {}".format(Object.name))
-
- Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
-
- #Position
- if Config.Verbose:
- print(" Writing Position...", end=" ")
- Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
- Position = Config.SystemMatrix * Object.location
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Rotation
- if Config.Verbose:
- print(" Writing Rotation...", end=" ")
- Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
- Rotation = Config.SystemQuaternion.cross(Object.rotation_euler.to_quat().cross(Config.InverseSystemQuaternion))
- Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";4;").ljust(8), Rotation[0], Rotation[1], Rotation[2], Config.FlipZ * Rotation[3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Scale
- if Config.Verbose:
- print(" Writing Scale...", end=" ")
- Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
- Scale = Config.SystemMatrix * Object.scale
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
-
- if Config.ExportArmatures and Object.type == "ARMATURE":
- if Config.Verbose:
- print(" Writing Armature Bone Animation Data...")
- PoseBones = Object.pose.bones
- for Bone in PoseBones:
- if Config.Verbose:
- print(" Writing Bone: {}...".format(Bone.name))
-
- Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
-
- #Position
- if Config.Verbose:
- print(" Writing Position...", end=" ")
- Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
-
- if Bone.parent:
- PoseMatrix = (Bone.parent.matrix * Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- PoseMatrix = Matrix()
- PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
-
- PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
-
- Position = PoseMatrix.translation_part()
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Rotation
- if Config.Verbose:
- print(" Writing Rotation...", end=" ")
- Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
- Config.Whitespace += 1
- Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
- #Whew! I'm sure this could be simplified.
- Rotation = Config.SystemQuaternion.cross(Matrix.Rotation(radians(90), 4, "X").to_quat().cross(Bone.rotation_quaternion.cross(Matrix.Rotation(radians(-90), 4, "X").to_quat().cross(Config.InverseSystemQuaternion))))
- Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";4;").ljust(8), Rotation[0], Rotation[1], Rotation[2], Config.FlipZ * Rotation[3]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- #Scale
- if Config.Verbose:
- print(" Writing Scale...", end=" ")
- Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace, KeyframeCount))
- Config.Whitespace += 1
- Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
- for Frame in range(0, KeyframeCount):
- bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
-
- if Bone.parent:
- PoseMatrix = (Bone.parent.matrix * Matrix.Rotation(radians(-90), 4, "X")).invert()
- else:
- PoseMatrix = Matrix()
- PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
-
- PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
-
- Scale = PoseMatrix.scale_part()
- Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print("Done")
-
- Config.Whitespace -= 1
- Config.File.write("{}}}\n".format(" " * Config.Whitespace))
- if Config.Verbose:
- print(" Done") #Done with Armature Bone
- if Config.Verbose:
- print(" Done") #Done with Armature Bone data
- if Config.Verbose:
- print(" Done") #Done with Object
-
- Config.Whitespace -= 1
- Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
-
-
-def CloseFile(Config):
- if Config.Verbose:
- print("Closing File...", end=" ")
- Config.File.close()
- if Config.Verbose:
- print("Done")
-
-CoordinateSystems = []
-CoordinateSystems.append(("1", "Left-Handed", ""))
-CoordinateSystems.append(("2", "Right-Handed", ""))
-
-AnimationModes = []
-AnimationModes.append(("0", "None", ""))
-AnimationModes.append(("1", "Keyframes Only", ""))
-AnimationModes.append(("2", "Full Animation", ""))
-
-ExportModes = []
-ExportModes.append(("1", "All Objects", ""))
-ExportModes.append(("2", "Selected Objects", ""))
-
-from bpy.props import *
-
-
-class DirectXExporter(bpy.types.Operator):
- """Export to the DirectX model format (.x)"""
-
- bl_idname = "export.directx"
- bl_label = "Export DirectX"
-
- filepath = StringProperty()
- filename = StringProperty()
- directory = StringProperty()
-
- #Coordinate System
- CoordinateSystem = EnumProperty(name="System", description="Select a coordinate system to export to", items=CoordinateSystems, default="1")
-
- #General Options
- RotateX = BoolProperty(name="Rotate X 90 Degrees", description="Rotate the entire scene 90 degrees around the X axis so Y is up.", default=True)
- FlipNormals = BoolProperty(name="Flip Normals", description="", default=False)
- ApplyModifiers = BoolProperty(name="Apply Modifiers", description="Apply object modifiers before export.", default=False)
- IncludeFrameRate = BoolProperty(name="Include Frame Rate", description="Include the AnimTicksPerSecond template which is used by some engines to control animation speed.", default=False)
- ExportTextures = BoolProperty(name="Export Textures", description="Reference external image files to be used by the model.", default=True)
- ExportArmatures = BoolProperty(name="Export Armatures", description="Export the bones of any armatures to deform meshes.", default=False)
- ExportAnimation = EnumProperty(name="Animations", description="Select the type of animations to export. Only object and armature bone animations can be exported. Full Animation exports every frame.", items=AnimationModes, default="0")
-
- #Export Mode
- ExportMode = EnumProperty(name="Export", description="Select which objects to export. Only Mesh, Empty, and Armature objects will be exported.", items=ExportModes, default="1")
-
- Verbose = BoolProperty(name="Verbose", description="Run the exporter in debug mode. Check the console for output.", default=False)
-
- def execute(self, context):
- #Append .x if needed
- FilePath = self.properties.filepath
- if not FilePath.lower().endswith(".x"):
- FilePath += ".x"
-
- Config = DirectXExporterSettings(context,
- FilePath,
- CoordinateSystem=self.properties.CoordinateSystem,
- RotateX=self.properties.RotateX,
- FlipNormals=self.properties.FlipNormals,
- ApplyModifiers=self.properties.ApplyModifiers,
- IncludeFrameRate=self.properties.IncludeFrameRate,
- ExportTextures=self.properties.ExportTextures,
- ExportArmatures=self.properties.ExportArmatures,
- ExportAnimation=self.properties.ExportAnimation,
- ExportMode=self.properties.ExportMode,
- Verbose=self.properties.Verbose)
- ExportDirectX(Config)
- return {"FINISHED"}
-
- def invoke(self, context, event):
- WindowManager = context.window_manager
- WindowManager.add_fileselect(self)
- return {"RUNNING_MODAL"}
-
-
-def menu_func(self, context):
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".x"
- self.layout.operator(DirectXExporter.bl_idname, text="DirectX (.x)").filepath = default_path
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-
-if __name__ == "__main__":
- register()
diff --git a/io_export_unreal_psk_psa.py b/io_export_unreal_psk_psa.py
deleted file mode 100644
index 46cb0ae5..00000000
--- a/io_export_unreal_psk_psa.py
+++ /dev/null
@@ -1,1593 +0,0 @@
- # ***** GPL LICENSE BLOCK *****
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- # All rights reserved.
- # ***** GPL LICENSE BLOCK *****
-
-bl_addon_info = {
- "name": "Export Skeleletal Mesh/Animation Data",
- "author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft",
- "version": (2,0),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Export > Skeletal Mesh/Animation Data (.psk/.psa)",
- "description": "Export Unreal Engine (.psk)",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File_I-O/Unreal_psk_psa",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21366&group_id=153&atid=469",
- "category": "Import/Export"}
-
-"""
--- Unreal Skeletal Mesh and Animation Export (.psk and .psa) export script v0.0.1 --<br>
-
-- NOTES:
-- This script Exports To Unreal's PSK and PSA file formats for Skeletal Meshes and Animations. <br>
-- This script DOES NOT support vertex animation! These require completely different file formats. <br>
-
-- v0.0.1
-- Initial version
-
-- v0.0.2
-- This version adds support for more than one material index!
-
-[ - Edit by: Darknet
-- v0.0.3 - v0.0.12
-- This will work on UT3 and it is a stable version that work with vehicle for testing.
-- Main Bone fix no dummy needed to be there.
-- Just bone issues position, rotation, and offset for psk.
-- The armature bone position, rotation, and the offset of the bone is fix. It was to deal with skeleton mesh export for psk.
-- Animation is fix for position, offset, rotation bone support one rotation direction when armature build.
-- It will convert your mesh into triangular when exporting to psk file.
-- Did not work with psa export yet.
-
-- v0.0.13
-- The animatoin will support different bone rotations when export the animation.
-
-- v0.0.14
-- Fixed Action set keys frames when there is no pose keys and it will ignore it.
-
-- v0.0.15
-- Fixed multiple objects when exporting to psk. Select one mesh to export to psk.
-- ]
-
-- v0.1.1
-- Blender 2.50 svn (Support)
-
-Credit to:
-- export_cal3d.py (Position of the Bones Format)
-- blender2md5.py (Animation Translation Format)
-- export_obj.py (Blender 2.5/Pyhton 3.x Format)
-
-- freenode #blendercoder -> user -> ideasman42
-
-- Give Credit to those who work on this script.
-
-- http://sinsoft.com
-"""
-
-import os
-import time
-import datetime
-import bpy
-import mathutils
-import operator
-
-from struct import pack, calcsize
-
-
-# REFERENCE MATERIAL JUST IN CASE:
-#
-# U = x / sqrt(x^2 + y^2 + z^2)
-# V = y / sqrt(x^2 + y^2 + z^2)
-#
-# Triangles specifed counter clockwise for front face
-#
-#defines for sizeofs
-SIZE_FQUAT = 16
-SIZE_FVECTOR = 12
-SIZE_VJOINTPOS = 44
-SIZE_ANIMINFOBINARY = 168
-SIZE_VCHUNKHEADER = 32
-SIZE_VMATERIAL = 88
-SIZE_VBONE = 120
-SIZE_FNAMEDBONEBINARY = 120
-SIZE_VRAWBONEINFLUENCE = 12
-SIZE_VQUATANIMKEY = 32
-SIZE_VVERTEX = 16
-SIZE_VPOINT = 12
-SIZE_VTRIANGLE = 12
-
-########################################################################
-# Generic Object->Integer mapping
-# the object must be usable as a dictionary key
-class ObjMap:
- def __init__(self):
- self.dict = {}
- self.next = 0
- def get(self, obj):
- if obj in self.dict:
- return self.dict[obj]
- else:
- id = self.next
- self.next = self.next + 1
- self.dict[obj] = id
- return id
-
- def items(self):
- getval = operator.itemgetter(0)
- getkey = operator.itemgetter(1)
- return map(getval, sorted(self.dict.items(), key=getkey))
-
-########################################################################
-# RG - UNREAL DATA STRUCTS - CONVERTED FROM C STRUCTS GIVEN ON UDN SITE
-# provided here: http://udn.epicgames.com/Two/BinaryFormatSpecifications.html
-# updated UDK (Unreal Engine 3): http://udn.epicgames.com/Three/BinaryFormatSpecifications.html
-class FQuat:
- def __init__(self):
- self.X = 0.0
- self.Y = 0.0
- self.Z = 0.0
- self.W = 1.0
-
- def dump(self):
- data = pack('ffff', self.X, self.Y, self.Z, self.W)
- return data
-
- def __cmp__(self, other):
- return cmp(self.X, other.X) \
- or cmp(self.Y, other.Y) \
- or cmp(self.Z, other.Z) \
- or cmp(self.W, other.W)
-
- def __hash__(self):
- return hash(self.X) ^ hash(self.Y) ^ hash(self.Z) ^ hash(self.W)
-
- def __str__(self):
- return "[%f,%f,%f,%f](FQuat)" % (self.X, self.Y, self.Z, self.W)
-
-class FVector(object):
- def __init__(self, X=0.0, Y=0.0, Z=0.0):
- self.X = X
- self.Y = Y
- self.Z = Z
-
- def dump(self):
- data = pack('fff', self.X, self.Y, self.Z)
- return data
-
- def __cmp__(self, other):
- return cmp(self.X, other.X) \
- or cmp(self.Y, other.Y) \
- or cmp(self.Z, other.Z)
-
- def _key(self):
- return (type(self).__name__, self.X, self.Y, self.Z)
-
- def __hash__(self):
- return hash(self._key())
-
- def __eq__(self, other):
- if not hasattr(other, '_key'):
- return False
- return self._key() == other._key()
-
- def dot(self, other):
- return self.X * other.X + self.Y * other.Y + self.Z * other.Z
-
- def cross(self, other):
- return FVector(self.Y * other.Z - self.Z * other.Y,
- self.Z * other.X - self.X * other.Z,
- self.X * other.Y - self.Y * other.X)
-
- def sub(self, other):
- return FVector(self.X - other.X,
- self.Y - other.Y,
- self.Z - other.Z)
-
-class VJointPos:
- def __init__(self):
- self.Orientation = FQuat()
- self.Position = FVector()
- self.Length = 0.0
- self.XSize = 0.0
- self.YSize = 0.0
- self.ZSize = 0.0
-
- def dump(self):
- data = self.Orientation.dump() + self.Position.dump() + pack('4f', self.Length, self.XSize, self.YSize, self.ZSize)
- return data
-
-class AnimInfoBinary:
- def __init__(self):
- self.Name = "" # length=64
- self.Group = "" # length=64
- self.TotalBones = 0
- self.RootInclude = 0
- self.KeyCompressionStyle = 0
- self.KeyQuotum = 0
- self.KeyPrediction = 0.0
- self.TrackTime = 0.0
- self.AnimRate = 0.0
- self.StartBone = 0
- self.FirstRawFrame = 0
- self.NumRawFrames = 0
-
- def dump(self):
- data = pack('64s64siiiifffiii', self.Name, self.Group, self.TotalBones, self.RootInclude, self.KeyCompressionStyle, self.KeyQuotum, self.KeyPrediction, self.TrackTime, self.AnimRate, self.StartBone, self.FirstRawFrame, self.NumRawFrames)
- return data
-
-class VChunkHeader:
- def __init__(self, name, type_size):
- self.ChunkID = name # length=20
- self.TypeFlag = 1999801 # special value
- self.DataSize = type_size
- self.DataCount = 0
-
- def dump(self):
- data = pack('20siii', self.ChunkID, self.TypeFlag, self.DataSize, self.DataCount)
- return data
-
-class VMaterial:
- def __init__(self):
- self.MaterialName = "" # length=64
- self.TextureIndex = 0
- self.PolyFlags = 0 # DWORD
- self.AuxMaterial = 0
- self.AuxFlags = 0 # DWORD
- self.LodBias = 0
- self.LodStyle = 0
-
- def dump(self):
- data = pack('64siLiLii', self.MaterialName, self.TextureIndex, self.PolyFlags, self.AuxMaterial, self.AuxFlags, self.LodBias, self.LodStyle)
- return data
-
-class VBone:
- def __init__(self):
- self.Name = "" # length = 64
- self.Flags = 0 # DWORD
- self.NumChildren = 0
- self.ParentIndex = 0
- self.BonePos = VJointPos()
-
- def dump(self):
- data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
- return data
-
-#same as above - whatever - this is how Epic does it...
-class FNamedBoneBinary:
- def __init__(self):
- self.Name = "" # length = 64
- self.Flags = 0 # DWORD
- self.NumChildren = 0
- self.ParentIndex = 0
- self.BonePos = VJointPos()
-
- self.IsRealBone = 0 # this is set to 1 when the bone is actually a bone in the mesh and not a dummy
-
- def dump(self):
- data = pack('64sLii', self.Name, self.Flags, self.NumChildren, self.ParentIndex) + self.BonePos.dump()
- return data
-
-class VRawBoneInfluence:
- def __init__(self):
- self.Weight = 0.0
- self.PointIndex = 0
- self.BoneIndex = 0
-
- def dump(self):
- data = pack('fii', self.Weight, self.PointIndex, self.BoneIndex)
- return data
-
-class VQuatAnimKey:
- def __init__(self):
- self.Position = FVector()
- self.Orientation = FQuat()
- self.Time = 0.0
-
- def dump(self):
- data = self.Position.dump() + self.Orientation.dump() + pack('f', self.Time)
- return data
-
-class VVertex(object):
- def __init__(self):
- self.PointIndex = 0 # WORD
- self.U = 0.0
- self.V = 0.0
- self.MatIndex = 0 #BYTE
- self.Reserved = 0 #BYTE
-
- def dump(self):
- data = pack('HHffBBH', self.PointIndex, 0, self.U, self.V, self.MatIndex, self.Reserved, 0)
- return data
-
- def __cmp__(self, other):
- return cmp(self.PointIndex, other.PointIndex) \
- or cmp(self.U, other.U) \
- or cmp(self.V, other.V) \
- or cmp(self.MatIndex, other.MatIndex) \
- or cmp(self.Reserved, other.Reserved)
-
- def _key(self):
- return (type(self).__name__,self.PointIndex, self.U, self.V,self.MatIndex,self.Reserved)
-
- def __hash__(self):
- return hash(self._key())
-
- def __eq__(self, other):
- if not hasattr(other, '_key'):
- return False
- return self._key() == other._key()
-
-class VPoint(object):
- def __init__(self):
- self.Point = FVector()
-
- def dump(self):
- return self.Point.dump()
-
- def __cmp__(self, other):
- return cmp(self.Point, other.Point)
-
- def _key(self):
- return (type(self).__name__, self.Point)
-
- def __hash__(self):
- return hash(self._key())
-
- def __eq__(self, other):
- if not hasattr(other, '_key'):
- return False
- return self._key() == other._key()
-
-class VTriangle:
- def __init__(self):
- self.WedgeIndex0 = 0 # WORD
- self.WedgeIndex1 = 0 # WORD
- self.WedgeIndex2 = 0 # WORD
- self.MatIndex = 0 # BYTE
- self.AuxMatIndex = 0 # BYTE
- self.SmoothingGroups = 0 # DWORD
-
- def dump(self):
- data = pack('HHHBBL', self.WedgeIndex0, self.WedgeIndex1, self.WedgeIndex2, self.MatIndex, self.AuxMatIndex, self.SmoothingGroups)
- return data
-
-# END UNREAL DATA STRUCTS
-########################################################################
-
-########################################################################
-#RG - helper class to handle the normal way the UT files are stored
-#as sections consisting of a header and then a list of data structures
-class FileSection:
- def __init__(self, name, type_size):
- self.Header = VChunkHeader(name, type_size)
- self.Data = [] # list of datatypes
-
- def dump(self):
- data = self.Header.dump()
- for i in range(len(self.Data)):
- data = data + self.Data[i].dump()
- return data
-
- def UpdateHeader(self):
- self.Header.DataCount = len(self.Data)
-
-class PSKFile:
- def __init__(self):
- self.GeneralHeader = VChunkHeader("ACTRHEAD", 0)
- self.Points = FileSection("PNTS0000", SIZE_VPOINT) #VPoint
- self.Wedges = FileSection("VTXW0000", SIZE_VVERTEX) #VVertex
- self.Faces = FileSection("FACE0000", SIZE_VTRIANGLE) #VTriangle
- self.Materials = FileSection("MATT0000", SIZE_VMATERIAL) #VMaterial
- self.Bones = FileSection("REFSKELT", SIZE_VBONE) #VBone
- self.Influences = FileSection("RAWWEIGHTS", SIZE_VRAWBONEINFLUENCE) #VRawBoneInfluence
-
- #RG - this mapping is not dumped, but is used internally to store the new point indices
- # for vertex groups calculated during the mesh dump, so they can be used again
- # to dump bone influences during the armature dump
- #
- # the key in this dictionary is the VertexGroup/Bone Name, and the value
- # is a list of tuples containing the new point index and the weight, in that order
- #
- # Layout:
- # { groupname : [ (index, weight), ... ], ... }
- #
- # example:
- # { 'MyVertexGroup' : [ (0, 1.0), (5, 1.0), (3, 0.5) ] , 'OtherGroup' : [(2, 1.0)] }
-
- self.VertexGroups = {}
-
- def AddPoint(self, p):
- #print ('AddPoint')
- self.Points.Data.append(p)
-
- def AddWedge(self, w):
- #print ('AddWedge')
- self.Wedges.Data.append(w)
-
- def AddFace(self, f):
- #print ('AddFace')
- self.Faces.Data.append(f)
-
- def AddMaterial(self, m):
- #print ('AddMaterial')
- self.Materials.Data.append(m)
-
- def AddBone(self, b):
- #print ('AddBone [%s]: Position: (x=%f, y=%f, z=%f) Rotation=(%f,%f,%f,%f)' % (b.Name, b.BonePos.Position.X, b.BonePos.Position.Y, b.BonePos.Position.Z, b.BonePos.Orientation.X,b.BonePos.Orientation.Y,b.BonePos.Orientation.Z,b.BonePos.Orientation.W))
- self.Bones.Data.append(b)
-
- def AddInfluence(self, i):
- #print ('AddInfluence')
- self.Influences.Data.append(i)
-
- def UpdateHeaders(self):
- self.Points.UpdateHeader()
- self.Wedges.UpdateHeader()
- self.Faces.UpdateHeader()
- self.Materials.UpdateHeader()
- self.Bones.UpdateHeader()
- self.Influences.UpdateHeader()
-
- def dump(self):
- self.UpdateHeaders()
- data = self.GeneralHeader.dump() + self.Points.dump() + self.Wedges.dump() + self.Faces.dump() + self.Materials.dump() + self.Bones.dump() + self.Influences.dump()
- return data
-
- def GetMatByIndex(self, mat_index):
- if mat_index >= 0 and len(self.Materials.Data) > mat_index:
- return self.Materials.Data[mat_index]
- else:
- m = VMaterial()
- m.MaterialName = "Mat%i" % mat_index
- self.AddMaterial(m)
- return m
-
- def PrintOut(self):
- print ("--- PSK FILE EXPORTED ---")
- print ('point count: %i' % len(self.Points.Data))
- print ('wedge count: %i' % len(self.Wedges.Data))
- print ('face count: %i' % len(self.Faces.Data))
- print ('material count: %i' % len(self.Materials.Data))
- print ('bone count: %i' % len(self.Bones.Data))
- print ('inlfuence count: %i' % len(self.Influences.Data))
- print ('-------------------------')
-
-# PSA FILE NOTES FROM UDN:
-#
-# The raw key array holds all the keys for all the bones in all the specified sequences,
-# organized as follows:
-# For each AnimInfoBinary's sequence there are [Number of bones] times [Number of frames keys]
-# in the VQuatAnimKeys, laid out as tracks of [numframes] keys for each bone in the order of
-# the bones as defined in the array of FnamedBoneBinary in the PSA.
-#
-# Once the data from the PSK (now digested into native skeletal mesh) and PSA (digested into
-# a native animation object containing one or more sequences) are associated together at runtime,
-# bones are linked up by name. Any bone in a skeleton (from the PSK) that finds no partner in
-# the animation sequence (from the PSA) will assume its reference pose stance ( as defined in
-# the offsets & rotations that are in the VBones making up the reference skeleton from the PSK)
-
-class PSAFile:
- def __init__(self):
- self.GeneralHeader = VChunkHeader("ANIMHEAD", 0)
- self.Bones = FileSection("BONENAMES", SIZE_FNAMEDBONEBINARY) #FNamedBoneBinary
- self.Animations = FileSection("ANIMINFO", SIZE_ANIMINFOBINARY) #AnimInfoBinary
- self.RawKeys = FileSection("ANIMKEYS", SIZE_VQUATANIMKEY) #VQuatAnimKey
-
- # this will take the format of key=Bone Name, value = (BoneIndex, Bone Object)
- # THIS IS NOT DUMPED
- self.BoneLookup = {}
-
- def dump(self):
- data = self.Generalheader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
- return data
-
- def AddBone(self, b):
- #LOUD
- #print "AddBone: " + b.Name
- self.Bones.Data.append(b)
-
- def AddAnimation(self, a):
- #LOUD
- #print "AddAnimation: %s, TotalBones: %i, AnimRate: %f, NumRawFrames: %i, TrackTime: %f" % (a.Name, a.TotalBones, a.AnimRate, a.NumRawFrames, a.TrackTime)
- self.Animations.Data.append(a)
-
- def AddRawKey(self, k):
- #LOUD
- #print "AddRawKey [%i]: Time: %f, Quat: x=%f, y=%f, z=%f, w=%f, Position: x=%f, y=%f, z=%f" % (len(self.RawKeys.Data), k.Time, k.Orientation.X, k.Orientation.Y, k.Orientation.Z, k.Orientation.W, k.Position.X, k.Position.Y, k.Position.Z)
- self.RawKeys.Data.append(k)
-
- def UpdateHeaders(self):
- self.Bones.UpdateHeader()
- self.Animations.UpdateHeader()
- self.RawKeys.UpdateHeader()
-
- def GetBoneByIndex(self, bone_index):
- if bone_index >= 0 and len(self.Bones.Data) > bone_index:
- return self.Bones.Data[bone_index]
-
- def IsEmpty(self):
- return (len(self.Bones.Data) == 0 or len(self.Animations.Data) == 0)
-
- def StoreBone(self, b):
- self.BoneLookup[b.Name] = [-1, b]
-
- def UseBone(self, bone_name):
- if bone_name in self.BoneLookup:
- bone_data = self.BoneLookup[bone_name]
-
- if bone_data[0] == -1:
- bone_data[0] = len(self.Bones.Data)
- self.AddBone(bone_data[1])
- #self.Bones.Data.append(bone_data[1])
-
- return bone_data[0]
-
- def GetBoneByName(self, bone_name):
- if bone_name in self.BoneLookup:
- bone_data = self.BoneLookup[bone_name]
- return bone_data[1]
-
- def GetBoneIndex(self, bone_name):
- if bone_name in self.BoneLookup:
- bone_data = self.BoneLookup[bone_name]
- return bone_data[0]
-
- def dump(self):
- self.UpdateHeaders()
- data = self.GeneralHeader.dump() + self.Bones.dump() + self.Animations.dump() + self.RawKeys.dump()
- return data
-
- def PrintOut(self):
- print ('--- PSA FILE EXPORTED ---')
- print ('bone count: %i' % len(self.Bones.Data))
- print ('animation count: %i' % len(self.Animations.Data))
- print ('rawkey count: %i' % len(self.RawKeys.Data))
- print ('-------------------------')
-
-####################################
-# helpers to create bone structs
-def make_vbone(name, parent_index, child_count, orientation_quat, position_vect):
- bone = VBone()
- bone.Name = name
- bone.ParentIndex = parent_index
- bone.NumChildren = child_count
- bone.BonePos.Orientation = orientation_quat
- bone.BonePos.Position.X = position_vect.x
- bone.BonePos.Position.Y = position_vect.y
- bone.BonePos.Position.Z = position_vect.z
-
- #these values seem to be ignored?
- #bone.BonePos.Length = tail.length
- #bone.BonePos.XSize = tail.x
- #bone.BonePos.YSize = tail.y
- #bone.BonePos.ZSize = tail.z
-
- return bone
-
-def make_namedbonebinary(name, parent_index, child_count, orientation_quat, position_vect, is_real):
- bone = FNamedBoneBinary()
- bone.Name = name
- bone.ParentIndex = parent_index
- bone.NumChildren = child_count
- bone.BonePos.Orientation = orientation_quat
- bone.BonePos.Position.X = position_vect.x
- bone.BonePos.Position.Y = position_vect.y
- bone.BonePos.Position.Z = position_vect.z
- bone.IsRealBone = is_real
- return bone
-
-##################################################
-#RG - check to make sure face isnt a line
-#The face has to be triangle not a line
-def is_1d_face(blender_face,mesh):
- #ID Vertex of id point
- v0 = blender_face.vertices[0]
- v1 = blender_face.vertices[1]
- v2 = blender_face.vertices[2]
-
- return (mesh.vertices[v0].co == mesh.vertices[v1].co or \
- mesh.vertices[v1].co == mesh.vertices[v2].co or \
- mesh.vertices[v2].co == mesh.vertices[v0].co)
- return False
-
-##################################################
-# http://en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python/Cookbook#Triangulate_NMesh
-
-#blender 2.50 format using the Operators/command convert the mesh to tri mesh
-def triangulateNMesh(object):
- bneedtri = False
- scene = bpy.context.scene
- bpy.ops.object.mode_set(mode='OBJECT')
- for i in scene.objects: i.select = False #deselect all objects
- object.select = True
- scene.objects.active = object #set the mesh object to current
- bpy.ops.object.mode_set(mode='OBJECT')
- print("Checking mesh if needs to convert quad to Tri...")
- for face in object.data.faces:
- if (len(face.vertices) > 3):
- bneedtri = True
- break
-
- bpy.ops.object.mode_set(mode='OBJECT')
- if bneedtri == True:
- print("Converting quad to tri mesh...")
- me_da = object.data.copy() #copy data
- me_ob = object.copy() #copy object
- #note two copy two types else it will use the current data or mesh
- me_ob.data = me_da
- bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
- for i in scene.objects: i.select = False #deselect all objects
- me_ob.select = True
- scene.objects.active = me_ob #set the mesh object to current
- bpy.ops.object.mode_set(mode='EDIT') #Operators
- bpy.ops.mesh.select_all(action='SELECT')#select all the face/vertex/edge
- bpy.ops.mesh.quads_convert_to_tris() #Operators
- bpy.context.scene.update()
- bpy.ops.object.mode_set(mode='OBJECT') # set it in object
- bpy.context.scene.unrealtriangulatebool = True
- print("Triangulate Mesh Done!")
- else:
- print("No need to convert tri mesh.")
- me_ob = object
- return me_ob
-
-#Blender Bone Index
-class BBone:
- def __init__(self):
- self.bone = ""
- self.index = 0
-bonedata = []
-BBCount = 0
-#deal with mesh bones groups vertex point
-def BoneIndex(bone):
- global BBCount, bonedata
- #print("//==============")
- #print(bone.name , "ID:",BBCount)
- BB = BBone()
- BB.bone = bone.name
- BB.index = BBCount
- bonedata.append(BB)
- BBCount += 1
- for current_child_bone in bone.children:
- BoneIndex(current_child_bone)
-
-def BoneIndexArmature(blender_armature):
- global BBCount
- #print("\n Buildng bone before mesh \n")
- #objectbone = blender_armature.pose #Armature bone
- #print(blender_armature)
- objectbone = blender_armature[0].pose
- #print(dir(ArmatureData))
-
- for bone in objectbone.bones:
- if(bone.parent == None):
- BoneIndex(bone)
- #BBCount += 1
- break
-
-# Actual object parsing functions
-def parse_meshes(blender_meshes, psk_file):
- #this is use to call the bone name and the index array for group index matches
- global bonedata
- #print("BONE DATA",len(bonedata))
- print ("----- parsing meshes -----")
- print("Number of Object Meshes:",len(blender_meshes))
- for current_obj in blender_meshes: #number of mesh that should be one mesh here
-
- current_obj = triangulateNMesh(current_obj)
- #print(dir(current_obj))
- print("Mesh Name:",current_obj.name)
- current_mesh = current_obj.data
-
- #if len(current_obj.materials) > 0:
- # object_mat = current_obj.materials[0]
- object_material_index = current_obj.active_material_index
-
- points = ObjMap()
- wedges = ObjMap()
-
- discarded_face_count = 0
- print (" -- Dumping Mesh Faces -- LEN:", len(current_mesh.faces))
- for current_face in current_mesh.faces:
- #print ' -- Dumping UVs -- '
- #print current_face.uv_textures
-
- if len(current_face.vertices) != 3:
- raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
-
- #No Triangulate Yet
- # if len(current_face.vertices) != 3:
- # raise RuntimeError("Non-triangular face (%i)" % len(current_face.vertices))
- # #TODO: add two fake faces made of triangles?
-
- #RG - apparently blender sometimes has problems when you do quad to triangle
- # conversion, and ends up creating faces that have only TWO points -
- # one of the points is simply in the vertex list for the face twice.
- # This is bad, since we can't get a real face normal for a LINE, we need
- # a plane for this. So, before we add the face to the list of real faces,
- # ensure that the face is actually a plane, and not a line. If it is not
- # planar, just discard it and notify the user in the console after we're
- # done dumping the rest of the faces
-
- if not is_1d_face(current_face,current_mesh):
- #print("faces")
- wedge_list = []
- vect_list = []
-
- #get or create the current material
- m = psk_file.GetMatByIndex(object_material_index)
-
- face_index = current_face.index
- has_UV = False
- faceUV = None
-
- if len(current_mesh.uv_textures) > 0:
- has_UV = True
- #print("face index: ",face_index)
- #faceUV = current_mesh.uv_textures.active.data[face_index]#UVs for current face
- #faceUV = current_mesh.uv_textures.active.data[0]#UVs for current face
- #print(face_index,"<[FACE NUMBER")
- uv_layer = current_mesh.uv_textures.active
- faceUV = uv_layer.data[face_index]
- #print("============================")
- #size(data) is number of texture faces. Each face has UVs
- #print("DATA face uv: ",len(faceUV.uv), " >> ",(faceUV.uv[0][0]))
-
- for i in range(3):
- vert_index = current_face.vertices[i]
- vert = current_mesh.vertices[vert_index]
- uv = []
- #assumes 3 UVs Per face (for now).
- if (has_UV):
- if len(faceUV.uv) != 3:
- print ("WARNING: Current face is missing UV coordinates - writing 0,0...")
- print ("WARNING: Face has more than 3 UVs - writing 0,0...")
- uv = [0.0, 0.0]
- else:
- #uv.append(faceUV.uv[i][0])
- #uv.append(faceUV.uv[i][1])
- uv = [faceUV.uv[i][0],faceUV.uv[i][1]] #OR bottom works better # 24 for cube
- #uv = list(faceUV.uv[i]) #30 just cube
- else:
- print ("No UVs?")
- uv = [0.0, 0.0]
- #print("UV >",uv)
- #uv = [0.0, 0.0] #over ride uv that is not fixed
- #print(uv)
- #flip V coordinate because UEd requires it and DOESN'T flip it on its own like it
- #does with the mesh Y coordinates.
- #this is otherwise known as MAGIC-2
- uv[1] = 1.0 - uv[1]
-
- #deal with the min and max value
- #if value is over the set limit it will null the uv texture
- if (uv[0] > 1):
- uv[0] = 1
- if (uv[0] < 0):
- uv[0] = 0
- if (uv[1] > 1):
- uv[1] = 1
- if (uv[1] < 0):
- uv[1] = 0
-
-
- # RE - Append untransformed vector (for normal calc below)
- # TODO: convert to Blender.Mathutils
- vect_list.append(FVector(vert.co.x, vert.co.y, vert.co.z))
-
- # Transform position for export
- #vpos = vert.co * object_material_index
- vpos = vert.co * current_obj.matrix_local
- # Create the point
- p = VPoint()
- p.Point.X = vpos.x
- p.Point.Y = vpos.y
- p.Point.Z = vpos.z
-
- # Create the wedge
- w = VVertex()
- w.MatIndex = object_material_index
- w.PointIndex = points.get(p) # get index from map
- #Set UV TEXTURE
- w.U = uv[0]
- w.V = uv[1]
- index_wedge = wedges.get(w)
- wedge_list.append(index_wedge)
-
- #print results
- #print 'result PointIndex=%i, U=%f, V=%f, wedge_index=%i' % (
- # w.PointIndex,
- # w.U,
- # w.V,
- # wedge_index)
-
- # Determine face vertex order
- # get normal from blender
- no = current_face.normal
-
- # TODO: convert to Blender.Mathutils
- # convert to FVector
- norm = FVector(no[0], no[1], no[2])
-
- # Calculate the normal of the face in blender order
- tnorm = vect_list[1].sub(vect_list[0]).cross(vect_list[2].sub(vect_list[1]))
-
- # RE - dot the normal from blender order against the blender normal
- # this gives the product of the two vectors' lengths along the blender normal axis
- # all that matters is the sign
- dot = norm.dot(tnorm)
-
- # print results
- #print 'face norm: (%f,%f,%f), tnorm=(%f,%f,%f), dot=%f' % (
- # norm.X, norm.Y, norm.Z,
- # tnorm.X, tnorm.Y, tnorm.Z,
- # dot)
-
- tri = VTriangle()
- # RE - magic: if the dot product above > 0, order the vertices 2, 1, 0
- # if the dot product above < 0, order the vertices 0, 1, 2
- # if the dot product is 0, then blender's normal is coplanar with the face
- # and we cannot deduce which side of the face is the outside of the mesh
- if (dot > 0):
- (tri.WedgeIndex2, tri.WedgeIndex1, tri.WedgeIndex0) = wedge_list
- elif (dot < 0):
- (tri.WedgeIndex0, tri.WedgeIndex1, tri.WedgeIndex2) = wedge_list
- else:
- dindex0 = current_face.vertices[0];
- dindex1 = current_face.vertices[1];
- dindex2 = current_face.vertices[2];
- raise RuntimeError("normal vector coplanar with face! points:", current_mesh.vertices[dindex0].co, current_mesh.vertices[dindex1].co, current_mesh.vertices[dindex2].co)
-
- tri.MatIndex = object_material_index
- #print(tri)
- psk_file.AddFace(tri)
-
- else:
- discarded_face_count = discarded_face_count + 1
-
- print (" -- Dumping Mesh Points -- LEN:",len(points.dict))
- for point in points.items():
- psk_file.AddPoint(point)
- print (" -- Dumping Mesh Wedge -- LEN:",len(wedges.dict))
- for wedge in wedges.items():
- psk_file.AddWedge(wedge)
-
- #RG - if we happend upon any non-planar faces above that we've discarded,
- # just let the user know we discarded them here in case they want
- # to investigate
-
- if discarded_face_count > 0:
- print ("INFO: Discarded %i non-planar faces." % (discarded_face_count))
-
- #RG - walk through the vertex groups and find the indexes into the PSK points array
- #for them, then store that index and the weight as a tuple in a new list of
- #verts for the group that we can look up later by bone name, since Blender matches
- #verts to bones for influences by having the VertexGroup named the same thing as
- #the bone
-
- #vertex group.
- for bonegroup in bonedata:
- #print("bone gourp build:",bonegroup.bone)
- vert_list = []
- for current_vert in current_mesh.vertices:
- #print("INDEX V:",current_vert.index)
- vert_index = current_vert.index
- for vgroup in current_vert.groups:#vertex groupd id
- vert_weight = vgroup.weight
- if(bonegroup.index == vgroup.group):
- p = VPoint()
- vpos = current_vert.co * current_obj.matrix_local
- p.Point.X = vpos.x
- p.Point.Y = vpos.y
- p.Point.Z = vpos.z
- #print(current_vert.co)
- point_index = points.get(p) #point index
- v_item = (point_index, vert_weight)
- vert_list.append(v_item)
- #bone name, [point id and wieght]
- #print("Add Vertex Group:",bonegroup.bone, " No. Points:",len(vert_list))
- psk_file.VertexGroups[bonegroup.bone] = vert_list
-
- #unrealtriangulatebool #this will remove the mesh from the scene
- if (bpy.context.scene.unrealtriangulatebool == True):
- print("Remove tmp Mesh [ " ,current_obj.name, " ] from scene >" ,(bpy.context.scene.unrealtriangulatebool ))
- bpy.ops.object.mode_set(mode='OBJECT') # set it in object
- bpy.context.scene.objects.unlink(current_obj)
-
-def make_fquat(bquat):
- quat = FQuat()
-
- #flip handedness for UT = set x,y,z to negative (rotate in other direction)
- quat.X = -bquat.x
- quat.Y = -bquat.y
- quat.Z = -bquat.z
-
- quat.W = bquat.w
- return quat
-
-def make_fquat_default(bquat):
- quat = FQuat()
-
- quat.X = bquat.x
- quat.Y = bquat.y
- quat.Z = bquat.z
-
- quat.W = bquat.w
- return quat
-
-# =================================================================================================
-# TODO: remove this 1am hack
-nbone = 0
-def parse_bone(blender_bone, psk_file, psa_file, parent_id, is_root_bone, parent_matrix, parent_root):
- global nbone # look it's evil!
- #print '-------------------- Dumping Bone ---------------------- '
-
- #If bone does not have parent that mean it the root bone
- if blender_bone.parent == None:
- parent_root = blender_bone
-
-
- child_count = len(blender_bone.children)
- #child of parent
- child_parent = blender_bone.parent
-
- if child_parent != None:
- print ("--Bone Name:",blender_bone.name ," parent:" , blender_bone.parent.name, "ID:", nbone)
- else:
- print ("--Bone Name:",blender_bone.name ," parent: None" , "ID:", nbone)
-
- if child_parent != None:
- quat_root = blender_bone.matrix
- quat = make_fquat(quat_root.to_quat())
-
- quat_parent = child_parent.matrix.to_quat().inverse()
- parent_head = child_parent.head * quat_parent
- parent_tail = child_parent.tail * quat_parent
-
- set_position = (parent_tail - parent_head) + blender_bone.head
- else:
- # ROOT BONE
- #This for root
- set_position = blender_bone.head * parent_matrix #ARMATURE OBJECT Locction
- rot_mat = blender_bone.matrix * parent_matrix.rotation_part() #ARMATURE OBJECT Rotation
- #print(dir(rot_mat))
-
- quat = make_fquat_default(rot_mat.to_quat())
-
- print ("[[======= FINAL POSITION:", set_position)
- final_parent_id = parent_id
-
- #RG/RE -
- #if we are not seperated by a small distance, create a dummy bone for the displacement
- #this is only needed for root bones, since UT assumes a connected skeleton, and from here
- #down the chain we just use "tail" as an endpoint
- #if(head.length > 0.001 and is_root_bone == 1):
- if(0):
- pb = make_vbone("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail)
- psk_file.AddBone(pb)
- pbb = make_namedbonebinary("dummy_" + blender_bone.name, parent_id, 1, FQuat(), tail, 0)
- psa_file.StoreBone(pbb)
- final_parent_id = nbone
- nbone = nbone + 1
- #tail = tail-head
-
- my_id = nbone
-
- pb = make_vbone(blender_bone.name, final_parent_id, child_count, quat, set_position)
- psk_file.AddBone(pb)
- pbb = make_namedbonebinary(blender_bone.name, final_parent_id, child_count, quat, set_position, 1)
- psa_file.StoreBone(pbb)
-
- nbone = nbone + 1
-
- #RG - dump influences for this bone - use the data we collected in the mesh dump phase
- # to map our bones to vertex groups
- #print("///////////////////////")
- #print("set influence")
- if blender_bone.name in psk_file.VertexGroups:
- vertex_list = psk_file.VertexGroups[blender_bone.name]
- #print("vertex list:", len(vertex_list), " of >" ,blender_bone.name )
- for vertex_data in vertex_list:
- #print("set influence vettex")
- point_index = vertex_data[0]
- vertex_weight = vertex_data[1]
- influence = VRawBoneInfluence()
- influence.Weight = vertex_weight
- #influence.BoneIndex = my_id
- influence.BoneIndex = my_id
- influence.PointIndex = point_index
- #print(influence)
- #print ('Adding Bone Influence for [%s] = Point Index=%i, Weight=%f' % (blender_bone.name, point_index, vertex_weight))
- #print("adding influence")
- psk_file.AddInfluence(influence)
-
- #blender_bone.matrix_local
- #recursively dump child bones
- mainparent = parent_matrix
- #if len(blender_bone.children) > 0:
- for current_child_bone in blender_bone.children:
- parse_bone(current_child_bone, psk_file, psa_file, my_id, 0, mainparent, parent_root)
-
-def parse_armature(blender_armature, psk_file, psa_file):
- print ("----- parsing armature -----")
- print ('blender_armature length: %i' % (len(blender_armature)))
-
- #magic 0 sized root bone for UT - this is where all armature dummy bones will attach
- #dont increment nbone here because we initialize it to 1 (hackity hackity hack)
-
- #count top level bones first. NOT EFFICIENT.
- child_count = 0
- for current_obj in blender_armature:
- current_armature = current_obj.data
- bones = [x for x in current_armature.bones if not x.parent == None]
- child_count += len(bones)
-
- for current_obj in blender_armature:
- print ("Current Armature Name: " + current_obj.name)
- current_armature = current_obj.data
- #armature_id = make_armature_bone(current_obj, psk_file, psa_file)
-
- #we dont want children here - only the top level bones of the armature itself
- #we will recursively dump the child bones as we dump these bones
- """
- bones = [x for x in current_armature.bones if not x.parent == None]
- #will ingore this part of the ocde
- """
- for current_bone in current_armature.bones: #list the bone. #note this will list all the bones.
- if(current_bone.parent == None):
- parse_bone(current_bone, psk_file, psa_file, 0, 0, current_obj.matrix_local, None)
- break
-
-# get blender objects by type
-def get_blender_objects(objects, intype):
- return [x for x in objects if x.type == intype]
-
-#strips current extension (if any) from filename and replaces it with extension passed in
-def make_filename_ext(filename, extension):
- new_filename = ''
- extension_index = filename.find('.')
-
- if extension_index == -1:
- new_filename = filename + extension
- else:
- new_filename = filename[0:extension_index] + extension
-
- return new_filename
-
-# returns the quaternion Grassman product a*b
-# this is the same as the rotation a(b(x))
-# (ie. the same as B*A if A and B are matrices representing
-# the rotations described by quaternions a and b)
-def grassman(a, b):
- return mathutils.Quaternion(
- a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z,
- a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y,
- a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x,
- a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w)
-
-def parse_animation(blender_scene, blender_armatures, psa_file):
- #to do list:
- #need to list the action sets
- #need to check if there animation
- #need to check if animation is has one frame then exit it
- print ('\n----- parsing animation -----')
- ##print(dir(blender_scene))
-
- #print(dir(blender_armatures))
-
- render_data = blender_scene.render
- bHaveAction = True
-
- anim_rate = render_data.fps
-
- #print("dir:",dir(blender_scene))
- #print(dir(bpy.data.actions))
- #print("dir:",dir(bpy.data.actions[0]))
-
-
- print("==== Blender Settings ====")
- print ('Scene: %s Start Frame: %i, End Frame: %i' % (blender_scene.name, blender_scene.frame_start, blender_scene.frame_end))
- print ('Frames Per Sec: %i' % anim_rate)
- print ("Default FPS: 24" )
-
- cur_frame_index = 0
-
- #print(dir(bpy.data.actions))
- #print(dir(bpy.context.scene.background_set))
-
- #list of armature objects
- for arm in blender_armatures:
- #check if there animation data from armature or something
- #print(dir(arm.animation_data))
- #print("[["+dir(arm.animation_data.action))
- if not arm.animation_data:
- print("======================================")
- print("Check Animation Data: None")
- print("Armature has no animation, skipping...")
- print("======================================")
- break
-
- if not arm.animation_data.action:
- print("======================================")
- print("Check Action: None")
- print("Armature has no animation, skipping...")
- print("======================================")
- break
- act = arm.animation_data.action
- #print(dir(act))
- action_name = act.name
-
- if not len(act.fcurves):
- print("//===========================================================")
- print("// None bone pose set keys for this action set... skipping...")
- print("//===========================================================")
- bHaveAction = False
-
- #this deal with action export control
- if bHaveAction == True:
- print("")
- print("==== Action Set ====")
- print("Action Name:",action_name)
- #look for min and max frame that current set keys
- framemin, framemax = act.frame_range
- #print("max frame:",framemax)
- start_frame = int(framemin)
- end_frame = int(framemax)
- scene_frames = range(start_frame, end_frame+1)
- frame_count = len(scene_frames)
- #===================================================
- anim = AnimInfoBinary()
- anim.Name = action_name
- anim.Group = "" #what is group?
- anim.NumRawFrames = frame_count
- anim.AnimRate = anim_rate
- anim.FirstRawFrame = cur_frame_index
- #===================================================
- count_previous_keys = len(psa_file.RawKeys.Data)
- print("Frame Key Set Count:",frame_count, "Total Frame:",frame_count)
- #print("init action bones...")
- unique_bone_indexes = {}
- # bone lookup table
- bones_lookup = {}
-
- #build bone node for animation keys needed to be set
- for bone in arm.data.bones:
- bones_lookup[bone.name] = bone
- #print("bone name:",bone.name)
- frame_count = len(scene_frames)
- #print ('Frame Count: %i' % frame_count)
- pose_data = arm.pose
-
- #these must be ordered in the order the bones will show up in the PSA file!
- ordered_bones = {}
- ordered_bones = sorted([(psa_file.UseBone(x.name), x) for x in pose_data.bones], key=operator.itemgetter(0))
-
- #############################
- # ORDERED FRAME, BONE
- #for frame in scene_frames:
-
- for i in range(frame_count):
- frame = scene_frames[i]
- #LOUD
- #print ("==== outputting frame %i ===" % frame)
-
- if frame_count > i+1:
- next_frame = scene_frames[i+1]
- #print "This Frame: %i, Next Frame: %i" % (frame, next_frame)
- else:
- next_frame = -1
- #print "This Frame: %i, Next Frame: NONE" % frame
-
- #frame start from 1 as number one from blender
- blender_scene.frame_set(frame)
-
- cur_frame_index = cur_frame_index + 1
- for bone_data in ordered_bones:
- bone_index = bone_data[0]
- pose_bone = bone_data[1]
- #print("[=====POSE NAME:",pose_bone.name)
-
- #print("LENG >>.",len(bones_lookup))
- blender_bone = bones_lookup[pose_bone.name]
-
- #just need the total unique bones used, later for this AnimInfoBinary
- unique_bone_indexes[bone_index] = bone_index
- #LOUD
- #print ("-------------------", pose_bone.name)
- head = pose_bone.head
-
- posebonemat = mathutils.Matrix(pose_bone.matrix)
- parent_pose = pose_bone.parent
- if parent_pose != None:
- parentposemat = mathutils.Matrix(parent_pose.matrix)
- #blender 2.4X it been flip around with new 2.50 (mat1 * mat2) should now be (mat2 * mat1)
- posebonemat = parentposemat.invert() * posebonemat
- head = posebonemat.translation_part()
- quat = posebonemat.to_quat().normalize()
- vkey = VQuatAnimKey()
- vkey.Position.X = head.x
- vkey.Position.Y = head.y
- vkey.Position.Z = head.z
-
- if parent_pose != None:
- quat = make_fquat(quat)
- else:
- quat = make_fquat_default(quat)
-
- vkey.Orientation = quat
- #print("Head:",head)
- #print("Orientation",quat)
-
- #time from now till next frame = diff / framesPerSec
- if next_frame >= 0:
- diff = next_frame - frame
- else:
- diff = 1.0
-
- #print ("Diff = ", diff)
- vkey.Time = float(diff)/float(anim_rate)
-
- psa_file.AddRawKey(vkey)
-
- #done looping frames
- #done looping armatures
- #continue adding animInfoBinary counts here
-
- anim.TotalBones = len(unique_bone_indexes)
- print("Bones Count:",anim.TotalBones)
- anim.TrackTime = float(frame_count) / anim.AnimRate
- print("Time Track Frame:",anim.TrackTime)
- psa_file.AddAnimation(anim)
- print("==== Finish Action Build(s) ====")
-
-exportmessage = "Export Finish"
-
-def fs_callback(filename, context, user_setting):
- #this deal with repeat export and the reset settings
- global bonedata, BBCount, nbone, exportmessage
- bonedata = []#clear array
- BBCount = 0
- nbone = 0
-
- start_time = time.clock()
-
- print ("========EXPORTING TO UNREAL SKELETAL MESH FORMATS========\r\n")
- print("Blender Version:", bpy.app.version_string)
-
- psk = PSKFile()
- psa = PSAFile()
-
- #sanity check - this should already have the extension, but just in case, we'll give it one if it doesn't
- psk_filename = make_filename_ext(filename, '.psk')
-
- #make the psa filename
- psa_filename = make_filename_ext(filename, '.psa')
-
- print ('PSK File: ' + psk_filename)
- print ('PSA File: ' + psa_filename)
-
- barmature = True
- bmesh = True
- blender_meshes = []
- blender_armature = []
- selectmesh = []
- selectarmature = []
-
- current_scene = context.scene
- cur_frame = current_scene.frame_current #store current frame before we start walking them during animation parse
- objects = current_scene.objects
-
- print("Checking object count...")
- for next_obj in objects:
- if next_obj.type == 'MESH':
- blender_meshes.append(next_obj)
- if (next_obj.select):
- #print("mesh object select")
- selectmesh.append(next_obj)
- if next_obj.type == 'ARMATURE':
- blender_armature.append(next_obj)
- if (next_obj.select):
- #print("armature object select")
- selectarmature.append(next_obj)
-
- print("Mesh Count:",len(blender_meshes)," Armature Count:",len(blender_armature))
- print("====================================")
- print("Checking Mesh Condtion(s):")
- if len(blender_meshes) == 1:
- print(" - One Mesh Scene")
- elif (len(blender_meshes) > 1) and (len(selectmesh) == 1):
- print(" - One Mesh [Select]")
- else:
- print(" - Too Many Meshes!")
- print(" - Select One Mesh Object!")
- bmesh = False
- print("====================================")
- print("Checking Armature Condtion(s):")
- if len(blender_armature) == 1:
- print(" - One Armature Scene")
- elif (len(blender_armature) > 1) and (len(selectarmature) == 1):
- print(" - One Armature [Select]")
- else:
- print(" - Too Armature Meshes!")
- print(" - Select One Armature Object Only!")
- barmature = False
-
- if (bmesh == False) or (barmature == False):
- exportmessage = "Export Fail! Check Log."
- print("=================================")
- print("= Export Fail! =")
- print("=================================")
- else:
- exportmessage = "Export Finish!"
- #need to build a temp bone index for mesh group vertex
- BoneIndexArmature(blender_armature)
-
- try:
- #######################
- # STEP 1: MESH DUMP
- # we build the vertexes, wedges, and faces in here, as well as a vertexgroup lookup table
- # for the armature parse
- print("//===============================")
- print("// STEP 1")
- print("//===============================")
- parse_meshes(blender_meshes, psk)
- except:
- context.scene.frame_set(cur_frame) #set frame back to original frame
- print ("Exception during Mesh Parse")
- raise
-
- try:
- #######################
- # STEP 2: ARMATURE DUMP
- # IMPORTANT: do this AFTER parsing meshes - we need to use the vertex group data from
- # the mesh parse in here to generate bone influences
- print("//===============================")
- print("// STEP 2")
- print("//===============================")
- parse_armature(blender_armature, psk, psa)
-
- except:
- context.scene.frame_set(cur_frame) #set frame back to original frame
- print ("Exception during Armature Parse")
- raise
-
- try:
- #######################
- # STEP 3: ANIMATION DUMP
- # IMPORTANT: do AFTER parsing bones - we need to do bone lookups in here during animation frames
- print("//===============================")
- print("// STEP 3")
- print("//===============================")
- parse_animation(current_scene, blender_armature, psa)
-
- except:
- context.scene.frame_set(cur_frame) #set frame back to original frame
- print ("Exception during Animation Parse")
- raise
-
- # reset current frame
-
- context.scene.frame_set(cur_frame) #set frame back to original frame
-
- ##########################
- # FILE WRITE
- print("//===========================================")
- print("// bExportPsk:",bpy.context.scene.unrealexportpsk," bExportPsa:",bpy.context.scene.unrealexportpsa)
- print("//===========================================")
- if bpy.context.scene.unrealexportpsk == True:
- print("Writing Skeleton Mesh Data...")
- #RG - dump psk file
- psk.PrintOut()
- file = open(psk_filename, "wb")
- file.write(psk.dump())
- file.close()
- print ("Successfully Exported File: " + psk_filename)
- if bpy.context.scene.unrealexportpsa == True:
- print("Writing Animaiton Data...")
- #RG - dump psa file
- if not psa.IsEmpty():
- psa.PrintOut()
- file = open(psa_filename, "wb")
- file.write(psa.dump())
- file.close()
- print ("Successfully Exported File: " + psa_filename)
- else:
- print ("No Animations (.psa file) to Export")
-
- print ('PSK/PSA Export Script finished in %.2f seconds' % (time.clock() - start_time))
-
- #MSG BOX EXPORT COMPLETE
- #...
-
- #DONE
- print ("PSK/PSA Export Complete")
-
-def write_data(path, context, user_setting):
- print("//============================")
- print("// running psk/psa export...")
- print("//============================")
- fs_callback(path, context, user_setting)
- pass
-
-from bpy.props import *
-
-exporttypedata = []
-
-# [index,text field,0] #or something like that
-exporttypedata.append(("0","PSK","Export PSK"))
-exporttypedata.append(("1","PSA","Export PSA"))
-exporttypedata.append(("2","ALL","Export ALL"))
-
-bpy.types.Scene.unrealfpsrate = IntProperty(
- name="fps rate",
- description="Set the frame per second (fps) for unreal.",
- default=24,min=1,max=100)
-
-bpy.types.Scene.unrealexport_settings = EnumProperty(
- name="Export:",
- description="Select a export settings (psk/psa/all)...",
- items = exporttypedata, default = '0')
-
-bpy.types.Scene.unrealtriangulatebool = BoolProperty(
- name="Triangulate Mesh",
- description="Convert Quad to Tri Mesh Boolean...",
- default=False)
-
-bpy.types.Scene.unrealactionexportall = BoolProperty(
- name="All Actions",
- description="This let you export all actions from current armature.[Not Build Yet]",
- default=False)
-
-bpy.types.Scene.unrealexportpsk = BoolProperty(
- name="bool export psa",
- description="bool for exporting this psk format",
- default=False)
-
-bpy.types.Scene.unrealexportpsa = BoolProperty(
- name="bool export psa",
- description="bool for exporting this psa format",
- default=False)
-
-class ExportUDKAnimData(bpy.types.Operator):
- global exportmessage
- '''Export Skeleton Mesh / Animation Data file(s)'''
- bl_idname = "export.udk_anim_data" # this is important since its how bpy.ops.export.udk_anim_data is constructed
- bl_label = "Export PSK/PSA"
- __doc__ = "One mesh and one armature else select one mesh or armature to be exported."
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- filepath = StringProperty(name="File Path", description="Filepath used for exporting the PSA file", maxlen= 1024, default= "")
- use_setting = BoolProperty(name="No Options Yet", description="No Options Yet", default= True)
- pskexportbool = BoolProperty(name="Export PSK", description="Export Skeletal Mesh", default= True)
- psaexportbool = BoolProperty(name="Export PSA", description="Export Action Set (Animation Data)", default= True)
- actionexportall = BoolProperty(name="All Actions", description="This will export all the actions that matches the current armature.", default=False)
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- #check if skeleton mesh is needed to be exported
- if (self.properties.pskexportbool):
- bpy.context.scene.unrealexportpsk = True
- else:
- bpy.context.scene.unrealexportpsk = False
- #check if animation data is needed to be exported
- if (self.properties.psaexportbool):
- bpy.context.scene.unrealexportpsa = True
- else:
- bpy.context.scene.unrealexportpsa = False
-
- write_data(self.properties.filepath, context, self.properties.use_setting)
-
- self.report({'WARNING', 'INFO'}, exportmessage)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-class VIEW3D_PT_unrealtools_objectmode(bpy.types.Panel):
- bl_space_type = "VIEW_3D"
- bl_region_type = "TOOLS"
- bl_label = "Unreal Tools"
-
- @classmethod
- def poll(cls, context):
- return context.active_object
-
- def draw(self, context):
- layout = self.layout
- #layout.label(text="Unreal Tools")
- rd = context.scene
- #drop box
- layout.prop(rd, "unrealexport_settings",expand=True)
- #layout.prop(rd, "unrealexport_settings")
- #button
- layout.operator("object.UnrealExport")
- #FPS #it use the real data from your scene
- layout.prop(rd.render, "fps")
-
- layout.prop(rd, "unrealactionexportall")
- #row = layout.row()
- #row.label(text="Action Set(s)(not build)")
- #for action in bpy.data.actions:
- #print(dir( action))
- #print(action.frame_range)
- #row = layout.row()
- #row.prop(action, "name")
-
- #print(dir(action.groups[0]))
- #for g in action.groups:#those are bones
- #print("group...")
- #print(dir(g))
- #print("////////////")
- #print((g.name))
- #print("////////////")
-
- #row.label(text="Active:" + action.select)
- btrimesh = False
-
-class OBJECT_OT_UnrealExport(bpy.types.Operator):
- global exportmessage
- bl_idname = "OBJECT_OT_UnrealExport"
- bl_label = "Unreal Export"
- __doc__ = "Select export setting for .psk/.psa or both."
-
- def invoke(self, context, event):
- #path = StringProperty(name="File Path", description="File path used for exporting the PSA file", maxlen= 1024, default= "")
- print("Init Export Script:")
- if(int(bpy.context.scene.unrealexport_settings) == 0):
- bpy.context.scene.unrealexportpsk = True
- bpy.context.scene.unrealexportpsa = False
- print("Exporting PSK...")
- if(int(bpy.context.scene.unrealexport_settings) == 1):
- bpy.context.scene.unrealexportpsk = False
- bpy.context.scene.unrealexportpsa = True
- print("Exporting PSA...")
- if(int(bpy.context.scene.unrealexport_settings) == 2):
- bpy.context.scene.unrealexportpsk = True
- bpy.context.scene.unrealexportpsa = True
- print("Exporting ALL...")
-
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
- fs_callback(default_path, bpy.context, False)
-
- #self.report({'WARNING', 'INFO'}, exportmessage)
- self.report({'INFO'}, exportmessage)
- return{'FINISHED'}
-
-
-def menu_func(self, context):
- bpy.context.scene.unrealexportpsk = True
- bpy.context.scene.unrealexportpsa = True
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
- self.layout.operator("export.udk_anim_data", text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
-
-
-def register():
- bpy.types.INFO_MT_file_export.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/io_import_images_as_planes.py b/io_import_images_as_planes.py
deleted file mode 100644
index 50dd2cff..00000000
--- a/io_import_images_as_planes.py
+++ /dev/null
@@ -1,525 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Import Images as Planes",
- "author": "Florian Meyer (testscreenings)",
- "version": (0,7),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Import > Images as Planes",
- "description": "Imports images and creates planes with the appropriate aspect ratio. The images are mapped to the planes.",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Add_Mesh/Planes_from_Images",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21751&group_id=153&atid=469",
- "category": "Import/Export"}
-
-"""
-This script imports images and creates Planes with them as textures.
-At the moment the naming for objects, materials, textures and meshes
-is derived from the imagename.
-
-One can either import a single image, or all images in one directory.
-When imporing a directory one can either check the checkbox or leave
-the filename empty.
-
-As a bonus one can choose to import images of only one type.
-Atm this is the list of possible extensions:
-extList =
- ('jpeg', 'jpg', 'png', 'tga', 'tiff', 'tif', 'exr',
- 'hdr', 'avi', 'mov', 'mp4', 'ogg', 'bmp', 'cin', 'dpx', 'psd')
-
-If someone knows a better way of telling if a file is an image which
-Blender can read, please tell so ;)
-
-when importing images that are allready referenced they are not
-reimported but the old ones reused as not to clutter the materials,
-textures and image lists.
-Instead the plane gets linked against an existing material.
-
-If one reimports images but chooses different material/texture mapping
-new materials are created.
-So one doesn't has to go through everything if one decides differently
-after importing 236 images.
-
-It also has an option to translate pixeldimensions into Blenderunits.
-"""
-
-import bpy
-from bpy.props import *
-from os import listdir
-from mathutils import Vector
-
-
-EXT_LIST = {
- 'jpeg': ['jpeg', 'jpg', 'jpe'],
- 'png': ['png'],
- 'tga': ['tga', 'tpic'],
- 'tiff': ['tiff', 'tif'],
- 'exr': ['exr'],
- 'hdr': ['hdr'],
- 'avi': ['avi'],
- 'mov': ['mov', 'qt'],
- 'mp4': ['mp4'],
- 'ogg': ['ogg', 'ogv'],
- 'bmp': ['bmp', 'dib'],
- 'cin': ['cin'],
- 'dpx': ['dpx'],
- 'psd': ['psd']}
-
-
-# Apply view rotation to objects if "Align To" for new objects
-# was set to "VIEW" in the User Preference.
-def apply_view_rotation(ob):
- context = bpy.context
- align = bpy.context.user_preferences.edit.object_align
-
- if (context.space_data.type == 'VIEW_3D'
- and align == 'VIEW'):
- view3d = context.space_data
- region = view3d.region_3d
- viewMatrix = region.view_matrix
- rot = viewMatrix.rotation_part()
- ob.rotation_euler = rot.invert().to_euler()
-
-
-# Create plane mesh
-def createPlaneMesh(dimension, img):
- # x is the x-aspectRatio.
- x = img.size[0] / img.size[1]
- y = 1
-
- if dimension[0]:
- x = (img.size[0] * (1.0 / dimension[1])) * 0.5
- y = (img.size[1] * (1.0 / dimension[1])) * 0.5
-
- verts = []
- faces = []
-
- v1 = (-x, -y, 0)
- v2 = (x, -y, 0)
- v3 = (x, y, 0)
- v4 = (-x, y, 0)
-
- verts.append(v1)
- verts.append(v2)
- verts.append(v3)
- verts.append(v4)
-
- faces.append([0, 1, 2, 3])
-
- return verts, faces
-
-
-# Create plane object
-def createPlaneObj(img, dimension):
- scene = bpy.context.scene
-
- verts, faces = createPlaneMesh(dimension, img)
-
- me = bpy.data.meshes.new(img.name)
- me.from_pydata(verts, [], faces)
- me.update()
-
- plane = bpy.data.objects.new(img.name, me)
- plane.data.uv_textures.new()
-
- scene.objects.link(plane)
- plane.location = scene.cursor_location
- apply_view_rotation(plane)
-
- return plane
-
-
-# Check if a file extension matches any
-# valid (i.e. recognized) image/movie format.
-def isImageFile(extension):
- for ext, ext_list in EXT_LIST.items():
- if extension in ext_list:
- return True
-
- return False
-
-
-# Get imagepaths from directory
-def getImageFilesInDirectory(directory, extension):
- import os
-
- # Get all files in the directory.
- allFiles = listdir(directory)
- allImages = []
-
- extensions = []
-
- # Import all images files?
- if extension == '*':
- all = True
-
- else:
- all = False
- # Get the possible extensions
- extensions = EXT_LIST[extension]
-
- # Put all image files in the list.
- for file in allFiles:
- # Get the file extension (includes the ".")
- e = os.path.splitext(file)[1]
-
- # Separate by "." and get the last list-entry.
- e = e.rpartition(".")[-1]
-
- # Convert to lower case
- e = e.lower()
-
- if (e in extensions
- or (all and isImageFile(e))):
- allImages.append(file)
-
- return allImages
-
-
-# Get image datablock from the (image's) filepath.
-def getImage(path):
- img = []
-
- # Check every Image if it is already there.
- for image in bpy.data.images:
- # If image with same path exists take that one.
- if image.filepath == path:
- img = image
-
- # Else create new Image and load from path.
- if not img:
- name = path.rpartition('\\')[2].rpartition('.')[0]
- img = bpy.data.images.new(name)
- img.source = 'FILE'
- img.filepath = path
-
- return img
-
-
-# Create/get Material
-def getMaterial(tex, mapping):
- mat = []
-
- # Check all existing materials.
- for material in bpy.data.materials:
- # If a material with name and mapping
- # texture with image exists, take that one...
- if (material.name == tex.image.name
- and tex.name in material.texture_slots
- and material.mapping == mapping):
- mat = material
-
- # ... otherwise create new one and apply mapping.
- if not mat:
- mat = bpy.data.materials.new(name=tex.name)
- mtex = mat.texture_slots.add()
- mtex.texture = tex
- mtex.texture_coords = 'UV'
- mtex.use_map_color_diffuse = True
-
- mat.mapping = mapping
- mat.name = tex.name
-
- return mat
-
-
-# Create/get Texture
-def getTexture(path, img):
- tex = []
-
- # Check all existing textures.
- for texture in bpy.data.textures:
- # If an (image)texture with image exists, take that one...
- if (texture.type == 'IMAGE'
- and texture.image
- and texture.image.filepath == path):
- tex = texture
-
- # ... otherwise create a new one and apply mapping.
- if not tex:
- name = path.rpartition('\\')[2].rpartition('.')[0]
- tex = bpy.data.textures.new(name=name, type='IMAGE')
- tex.image = img
-
- return tex
-
-
-# Custom material property - get
-def mapget(self):
- """Custom property of the images_as_planes addon."""
- mapping = []
- mapping.append(self.use_shadeless)
- mapping.append(self.use_transparency)
- mapping.append(self.alpha)
- mapping.append(self.specular_alpha)
- mapping.append(self.transparency_method)
-
- if (self.texture_slots[0]
- and self.texture_slots[0].texture.type == 'IMAGE'
- and self.texture_slots[0].texture.image):
- mapping.append(self.texture_slots[0].texture.image.use_premultiply)
-
- else:
- mapping.append("no image")
-
- return mapping
-
-
-# Custom material property - set
-def mapset(self, value):
- self.use_shadeless = value[0]
- self.use_transparency = value[1]
- self.alpha = float(value[2])
- self.specular_alpha = float(value[3])
- self.transparency_method = value[4]
-
- if (self.texture_slots[0]
- and self.texture_slots[0].texture.type == 'IMAGE'
- and self.texture_slots[0].texture.image):
- self.texture_slots[0].texture.image.use_premultiply = value[5]
- if self.alpha:
- self.texture_slots[0].use_map_alpha=True
-
-
-bpy.types.Material.mapping = property(mapget, mapset)
-
-
-def main(filePath, options, mapping, dimension):
- images = []
- scene = bpy.context.scene
-
- # If "Create from Directory" (no filepath or checkbox) ####
- if options['dir'] or not filePath[1]:
- imageFiles = getImageFilesInDirectory(filePath[2], options['ext'])
-
- # Check if images are loaded and put them in the list.
- for imageFile in imageFiles:
- img = getImage(str(filePath[2]) + "\\" + str(imageFile))
- images.append(img)
-
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- # Assign/get all things.
- for img in images:
- # Create/get Texture
- tex = getTexture(img.filepath, img)
-
- # Create/get Material
- mat = getMaterial(tex, mapping)
-
- # Create Plane
- plane = createPlaneObj(img, dimension)
-
- # Assign Material
- plane.data.materials.append(mat)
-
- # Put Image into UVTextureLayer
- plane.data.uv_textures[0].data[0].image = img
- plane.data.uv_textures[0].data[0].use_image = True
- plane.data.uv_textures[0].data[0].blend_type = 'ALPHA'
- plane.data.uv_textures[0].data[0].use_twoside = True
-
- plane.select = True
- scene.objects.active = plane
-
- # If "Create Single Plane" (filepath and is image)
- else:
- # Deselect all objects.
- bpy.ops.object.select_all(action='DESELECT')
-
- # Check if image is loaded.
- img = getImage(filePath[0])
-
- # Create/get Texture
- tex = getTexture(filePath[0], img)
-
- # Create/get Material
- mat = getMaterial(tex, mapping)
-
- # Create Plane
- plane = createPlaneObj(img, dimension)
-
- # Assign Material
- plane.data.materials.append(mat)
-
- # Put image into UVTextureLayer
- plane.data.uv_textures[0].data[0].image = img
- plane.data.uv_textures[0].data[0].use_image = True
- plane.data.uv_textures[0].data[0].blend_type = 'ALPHA'
- plane.data.uv_textures[0].data[0].use_twoside = True
-
- plane.select = True
- scene.objects.active = plane
-
-
-# Operator
-class ImportImagesAsPlanes(bpy.types.Operator):
- ''''''
- bl_idname = "import.images_as_planes"
- bl_label = "Import Images as Planes"
- bl_description = "Create mesh plane(s) from image files" \
- " with the appropiate aspect ratio."
- bl_options = {'REGISTER', 'UNDO'}
-
- filepath = StringProperty(name="File Path",
- description="Filepath used for importing the file",
- maxlen=1024,
- default="")
- filename = StringProperty(name="File Name",
- description="Name of the file.")
- directory = StringProperty(name="Directory",
- description="Directory of the file.")
- fromDirectory = BoolProperty(name="All in directory",
- description="Import all image files (of the selected type)" \
- " in this directory.",
- default=False)
-
- extEnum = [
- ('*', 'All image formats',
- 'Import all know image (or movie) formats.'),
- ('jpeg', 'JPEG (.jpg, .jpeg, .jpe)',
- 'Joint Photographic Experts Group'),
- ('png', 'PNG (.png)', 'Portable Network Graphics'),
- ('tga', 'Truevision TGA (.tga, tpic)', ''),
- ('tiff', 'TIFF (.tif, .tiff)', 'Tagged Image File Format'),
- ('exr', 'OpenEXR (.exr)', 'OpenEXR HDR imaging image file format'),
- ('hdr', 'Radiance HDR (.hdr, .pic)', ''),
- ('avi', 'AVI (.avi)', 'Audio Video Interleave'),
- ('mov', 'QuickTime (.mov, .qt)', ''),
- ('mp4', 'MPEG-4 (.mp4)', ' MPEG-4 Part 14'),
- ('ogg', 'OGG Theora (.ogg, .ogv)', ''),
- ('bmp', 'BMP (.bmp, .dib)', 'Windows Bitmap'),
- ('cin', 'CIN (.cin)', ''),
- ('dpx', 'DPX (.dpx)', 'DPX (Digital Picture Exchange)'),
- ('psd', 'PSD (.psd)', 'Photoshop Document')]
- extension = EnumProperty(name="Extension",
- description="Only import files of this type.",
- items=extEnum)
-
- shadeless = BoolProperty(name="Shadeless",
- description="Set material to shadeless",
- default=False)
- transp = BoolProperty(name="Use alpha",
- description="Use alphachannel for transparency.",
- default=False)
- premultiply = BoolProperty(name="Premultiply",
- description="Premultiply image",
- default=False)
-
- tEnum = [
- ('Z_TRANSPARENCY',
- 'Z Transparency',
- 'Use alpha buffer for transparent faces'),
- ('RAYTRACE',
- 'Raytrace',
- 'Use raytracing for transparent refraction rendering.')]
- transp_method = EnumProperty(name="Transp. Method",
- description="Transparency Method",
- items=tEnum)
- useDim = BoolProperty(name="Use image dimensions",
- description="Use the images pixels to derive the size of the plane.",
- default=False)
- factor = IntProperty(name="Pixels/BU",
- description="Number of pixels per Blenderunit.",
- min=1,
- default=500)
-
- def draw(self, context):
- props = self.properties
- layout = self.layout
- box = layout.box()
- box.label('Filter:', icon='FILTER')
- box.prop(props, 'fromDirectory')
- box.prop(props, 'extension', icon='FILE_IMAGE')
- box = layout.box()
- box.label('Material mappings:', icon='MATERIAL')
- box.prop(props, 'use_shadeless')
- box.prop(props, 'transp')
- box.prop(props, 'use_premultiply')
- box.prop(props, 'transp_method', expand=True)
- box = layout.box()
- box.label('Plane dimensions:', icon='ARROW_LEFTRIGHT')
- box.prop(props, 'useDim')
- box.prop(props, 'factor', expand=True)
-
- def execute(self, context):
- # File Path
- filepath = self.properties.filepath
- filename = self.properties.filename
- directory = self.properties.directory
- filePath = (filepath, filename, directory)
-
- # General Options
- fromDirectory = self.properties.fromDirectory
- extension = self.properties.extension
- options = {'dir': fromDirectory, 'ext': extension}
-
- # Mapping
- alphavalue = 1
- transp = self.properties.transp
- if transp:
- alphavalue = 0
-
- shadeless = self.properties.use_shadeless
- transp_method = self.properties.transp_method
- premultiply = self.properties.use_premultiply
-
- mapping = ([shadeless,
- transp,
- alphavalue,
- alphavalue,
- transp_method,
- premultiply])
-
- # Use Pixelsdimensions
- useDim = self.properties.useDim
- factor = self.properties.factor
- dimension = (useDim, factor)
-
- # Call Main Function
- main(filePath, options, mapping, dimension)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = bpy.context.window_manager
- wm.add_fileselect(self)
-
- return {'RUNNING_MODAL'}
-
-
-# Registering / Unregister
-def menu_func(self, context):
- self.layout.operator(ImportImagesAsPlanes.bl_idname, text="Images as Planes", icon='PLUGIN')
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-
-if __name__ == "__main__":
- register()
diff --git a/io_import_scene_lwo.py b/io_import_scene_lwo.py
deleted file mode 100644
index c2d75f97..00000000
--- a/io_import_scene_lwo.py
+++ /dev/null
@@ -1,1247 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-bl_addon_info= {
- "name": "Import LightWave Objects",
- "author": "Ken Nign (Ken9)",
- "version": (1, 2),
- "blender": (2, 5, 3),
- "api": 31744,
- "location": "File > Import > LightWave Object (.lwo)",
- "description": "Imports a LWO file including any UV, Morph and Color maps. Can convert Skelegons to an Armature.",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File_I-O/LightWave_Object",
- "tracker_url": "",
- "category": "Import/Export"}
-
-# Copyright (c) Ken Nign 2010
-# ken@virginpi.com
-#
-# Version 1.2 - Sep 7, 2010
-#
-# Loads a LightWave .lwo object file, including the vertex maps such as
-# UV, Morph, Color and Weight maps.
-#
-# Will optionally create an Armature from an embedded Skelegon rig.
-#
-# Point orders are maintained so that .mdds can exchanged with other
-# 3D programs.
-#
-#
-# Notes:
-# NGons, polygons with more than 4 points are supported, but are
-# added (as triangles) after the vertex maps have been applied. Thus they
-# won't contain all the vertex data that the original ngon had.
-#
-# Blender is limited to only 8 UV Texture and 8 Vertex Color maps,
-# thus only the first 8 of each can be imported.
-#
-# History:
-#
-# 1.2 Added Absolute Morph and CC Edge Weight support.
-# Made edge creation safer.
-# 1.0 First Release
-
-
-import os
-import io
-import time
-import struct
-import chunk
-
-import bpy
-import mathutils
-from geometry import PolyFill
-
-
-class _obj_layer(object):
- __slots__ = (
- "name",
- "index",
- "parent_index",
- "pivot",
- "pols",
- "bones",
- "bone_names",
- "bone_rolls",
- "pnts",
- "wmaps",
- "colmaps",
- "uvmaps",
- "morphs",
- "edge_weights",
- "surf_tags",
- "has_subds",
- )
- def __init__(self):
- self.name= ""
- self.index= -1
- self.parent_index= -1
- self.pivot= [0, 0, 0]
- self.pols= []
- self.bones= []
- self.bone_names= {}
- self.bone_rolls= {}
- self.pnts= []
- self.wmaps= {}
- self.colmaps= {}
- self.uvmaps= {}
- self.morphs= {}
- self.edge_weights= {}
- self.surf_tags= {}
- self.has_subds= False
-
-
-class _obj_surf(object):
- __slots__ = (
- "bl_mat",
- "name",
- "source_name",
- "colr",
- "diff",
- "lumi",
- "spec",
- "refl",
- "rblr",
- "tran",
- "rind",
- "tblr",
- "trnl",
- "glos",
- "shrp",
- "smooth",
- )
-
- def __init__(self):
- self.bl_mat= None
- self.name= "Default"
- self.source_name= ""
- self.colr= [1.0, 1.0, 1.0]
- self.diff= 1.0 # Diffuse
- self.lumi= 0.0 # Luminosity
- self.spec= 0.0 # Specular
- self.refl= 0.0 # Reflectivity
- self.rblr= 0.0 # Reflection Bluring
- self.tran= 0.0 # Transparency (the opposite of Blender's Alpha value)
- self.rind= 1.0 # RT Transparency IOR
- self.tblr= 0.0 # Refraction Bluring
- self.trnl= 0.0 # Translucency
- self.glos= 0.4 # Glossiness
- self.shrp= 0.0 # Diffuse Sharpness
- self.smooth= False # Surface Smoothing
-
-
-def load_lwo(filename,
- context,
- ADD_SUBD_MOD=True,
- LOAD_HIDDEN=False,
- SKEL_TO_ARM=True):
- '''Read the LWO file, hand off to version specific function.'''
- name, ext= os.path.splitext(os.path.basename(filename))
- file= open(filename, 'rb')
-
- try:
- header, chunk_size, chunk_name = struct.unpack(">4s1L4s", file.read(12))
- except:
- print("Error parsing file header!")
- file.close()
- return
-
- layers= []
- surfs= {}
- tags= []
- # Gather the object data using the version specific handler.
- if chunk_name == b'LWO2':
- read_lwo2(file, filename, layers, surfs, tags, ADD_SUBD_MOD, LOAD_HIDDEN, SKEL_TO_ARM)
- elif chunk_name == b'LWOB' or chunk_name == b'LWLO':
- # LWOB and LWLO are the old format, LWLO is a layered object.
- read_lwob(file, filename, layers, surfs, tags, ADD_SUBD_MOD)
- else:
- print("Not a supported file type!")
- file.close()
- return
-
- file.close()
-
- # With the data gathered, build the object(s).
- build_objects(layers, surfs, tags, name, ADD_SUBD_MOD, SKEL_TO_ARM)
-
- layers= None
- surfs.clear()
- tags= None
-
-
-def read_lwo2(file, filename, layers, surfs, tags, add_subd_mod, load_hidden, skel_to_arm):
- '''Read version 2 file, LW 6+.'''
- handle_layer= True
- last_pols_count= 0
- just_read_bones= False
- print("Importing LWO: " + filename + "\nLWO v2 Format")
-
- while True:
- try:
- rootchunk = chunk.Chunk(file)
- except EOFError:
- break
-
- if rootchunk.chunkname == b'TAGS':
- read_tags(rootchunk.read(), tags)
- elif rootchunk.chunkname == b'LAYR':
- handle_layer= read_layr(rootchunk.read(), layers, load_hidden)
- elif rootchunk.chunkname == b'PNTS' and handle_layer:
- read_pnts(rootchunk.read(), layers)
- elif rootchunk.chunkname == b'VMAP' and handle_layer:
- vmap_type = rootchunk.read(4)
-
- if vmap_type == b'WGHT':
- read_weightmap(rootchunk.read(), layers)
- elif vmap_type == b'MORF':
- read_morph(rootchunk.read(), layers, False)
- elif vmap_type == b'SPOT':
- read_morph(rootchunk.read(), layers, True)
- elif vmap_type == b'TXUV':
- read_uvmap(rootchunk.read(), layers)
- elif vmap_type == b'RGB ' or vmap_type == b'RGBA':
- read_colmap(rootchunk.read(), layers)
- else:
- rootchunk.skip()
-
- elif rootchunk.chunkname == b'VMAD' and handle_layer:
- vmad_type= rootchunk.read(4)
-
- if vmad_type == b'TXUV':
- read_uv_vmad(rootchunk.read(), layers, last_pols_count)
- elif vmad_type == b'RGB ' or vmad_type == b'RGBA':
- read_color_vmad(rootchunk.read(), layers, last_pols_count)
- elif vmad_type == b'WGHT':
- # We only read the Edge Weight map if it's there.
- read_weight_vmad(rootchunk.read(), layers)
- else:
- rootchunk.skip()
-
- elif rootchunk.chunkname == b'POLS' and handle_layer:
- face_type = rootchunk.read(4)
- just_read_bones= False
- # PTCH is LW's Subpatches, SUBD is CatmullClark.
- if (face_type == b'FACE' or face_type == b'PTCH' or
- face_type == b'SUBD') and handle_layer:
- last_pols_count= read_pols(rootchunk.read(), layers)
- if face_type != b'FACE':
- layers[-1].has_subds= True
- elif face_type == b'BONE' and handle_layer:
- read_bones(rootchunk.read(), layers)
- just_read_bones= True
- else:
- rootchunk.skip()
-
- elif rootchunk.chunkname == b'PTAG' and handle_layer:
- tag_type,= struct.unpack("4s", rootchunk.read(4))
- if tag_type == b'SURF' and not just_read_bones:
- # Ignore the surface data if we just read a bones chunk.
- read_surf_tags(rootchunk.read(), layers, last_pols_count)
-
- elif skel_to_arm:
- if tag_type == b'BNUP':
- read_bone_tags(rootchunk.read(), layers, tags, 'BNUP')
- elif tag_type == b'BONE':
- read_bone_tags(rootchunk.read(), layers, tags, 'BONE')
- else:
- rootchunk.skip()
- else:
- rootchunk.skip()
- elif rootchunk.chunkname == b'SURF':
- read_surf(rootchunk.read(), surfs)
- else:
- #if handle_layer:
- #print("Skipping Chunk:", rootchunk.chunkname)
- rootchunk.skip()
-
-
-def read_lwob(file, filename, layers, surfs, tags, add_subd_mod):
- '''Read version 1 file, LW < 6.'''
- last_pols_count= 0
- print("Importing LWO: " + filename + "\nLWO v1 Format")
-
- while True:
- try:
- rootchunk = chunk.Chunk(file)
- except EOFError:
- break
-
- if rootchunk.chunkname == b'SRFS':
- read_tags(rootchunk.read(), tags)
- elif rootchunk.chunkname == b'LAYR':
- read_layr_5(rootchunk.read(), layers)
- elif rootchunk.chunkname == b'PNTS':
- if len(layers) == 0:
- # LWOB files have no LAYR chunk to set this up.
- nlayer= _obj_layer()
- nlayer.name= "Layer 1"
- layers.append(nlayer)
- read_pnts(rootchunk.read(), layers)
- elif rootchunk.chunkname == b'POLS':
- last_pols_count= read_pols_5(rootchunk.read(), layers)
- elif rootchunk.chunkname == b'PCHS':
- last_pols_count= read_pols_5(rootchunk.read(), layers)
- layers[-1].has_subds= True
- elif rootchunk.chunkname == b'PTAG':
- tag_type,= struct.unpack("4s", rootchunk.read(4))
- if tag_type == b'SURF':
- read_surf_tags_5(rootchunk.read(), layers, last_pols_count)
- else:
- rootchunk.skip()
- elif rootchunk.chunkname == b'SURF':
- read_surf_5(rootchunk.read(), surfs)
- else:
- # For Debugging \/.
- #if handle_layer:
- #print("Skipping Chunk: ", rootchunk.chunkname)
- rootchunk.skip()
-
-
-def read_lwostring(raw_name):
- '''Parse a zero-padded string.'''
-
- i = raw_name.find(b'\0')
- name_len = i + 1
- if name_len % 2 == 1: # Test for oddness.
- name_len += 1
-
- if i > 0:
- # Some plugins put non-text strings in the tags chunk.
- name = raw_name[0:i].decode("utf-8", "ignore")
- else:
- name = ""
-
- return name, name_len
-
-
-def read_vx(pointdata):
- '''Read a variable-length index.'''
- if pointdata[0] != 255:
- index= pointdata[0]*256 + pointdata[1]
- size= 2
- else:
- index= pointdata[1]*65536 + pointdata[2]*256 + pointdata[3]
- size= 4
-
- return index, size
-
-
-def read_tags(tag_bytes, object_tags):
- '''Read the object's Tags chunk.'''
- offset= 0
- chunk_len= len(tag_bytes)
-
- while offset < chunk_len:
- tag, tag_len= read_lwostring(tag_bytes[offset:])
- offset+= tag_len
- object_tags.append(tag)
-
-
-def read_layr(layr_bytes, object_layers, load_hidden):
- '''Read the object's layer data.'''
- new_layr= _obj_layer()
- new_layr.index, flags= struct.unpack(">HH", layr_bytes[0:4])
-
- if flags > 0 and not load_hidden:
- return False
-
- print("Reading Object Layer")
- offset= 4
- pivot= struct.unpack(">fff", layr_bytes[offset:offset+12])
- # Swap Y and Z to match Blender's pitch.
- new_layr.pivot= [pivot[0], pivot[2], pivot[1]]
- offset+= 12
- layr_name, name_len = read_lwostring(layr_bytes[offset:])
- offset+= name_len
-
- if layr_name:
- new_layr.name= layr_name
- else:
- new_layr.name= "Layer %d" % (new_layr.index + 1)
-
- if len(layr_bytes) == offset+2:
- new_layr.parent_index,= struct.unpack(">h", layr_bytes[offset:offset+2])
-
- object_layers.append(new_layr)
- return True
-
-
-def read_layr_5(layr_bytes, object_layers):
- '''Read the object's layer data.'''
- # XXX: Need to check what these two exactly mean for a LWOB/LWLO file.
- new_layr= _obj_layer()
- new_layr.index, flags= struct.unpack(">HH", layr_bytes[0:4])
-
- print("Reading Object Layer")
- offset= 4
- layr_name, name_len = read_lwostring(layr_bytes[offset:])
- offset+= name_len
-
- if name_len > 2 and layr_name != 'noname':
- new_layr.name= layr_name
- else:
- new_layr.name= "Layer %d" % new_layr.index
-
- object_layers.append(new_layr)
-
-
-def read_pnts(pnt_bytes, object_layers):
- '''Read the layer's points.'''
- print("\tReading Layer ("+object_layers[-1].name+") Points")
- offset= 0
- chunk_len= len(pnt_bytes)
-
- while offset < chunk_len:
- pnts= struct.unpack(">fff", pnt_bytes[offset:offset+12])
- offset+= 12
- # Re-order the points so that the mesh has the right pitch,
- # the pivot already has the correct order.
- pnts= [pnts[0] - object_layers[-1].pivot[0],\
- pnts[2] - object_layers[-1].pivot[1],\
- pnts[1] - object_layers[-1].pivot[2]]
- object_layers[-1].pnts.append(pnts)
-
-
-def read_weightmap(weight_bytes, object_layers):
- '''Read a weight map's values.'''
- chunk_len= len(weight_bytes)
- offset= 2
- name, name_len= read_lwostring(weight_bytes[offset:])
- offset+= name_len
- weights= []
-
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(weight_bytes[offset:offset+4])
- offset+= pnt_id_len
- value,= struct.unpack(">f", weight_bytes[offset:offset+4])
- offset+= 4
- weights.append([pnt_id, value])
-
- object_layers[-1].wmaps[name]= weights
-
-
-def read_morph(morph_bytes, object_layers, is_abs):
- '''Read an endomorph's relative or absolute displacement values.'''
- chunk_len= len(morph_bytes)
- offset= 2
- name, name_len= read_lwostring(morph_bytes[offset:])
- offset+= name_len
- deltas= []
-
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(morph_bytes[offset:offset+4])
- offset+= pnt_id_len
- pos= struct.unpack(">fff", morph_bytes[offset:offset+12])
- offset+= 12
- pnt= object_layers[-1].pnts[pnt_id]
-
- if is_abs:
- deltas.append([pnt_id, pos[0], pos[2], pos[1]])
- else:
- # Swap the Y and Z to match Blender's pitch.
- deltas.append([pnt_id, pnt[0]+pos[0], pnt[1]+pos[2], pnt[2]+pos[1]])
-
- object_layers[-1].morphs[name]= deltas
-
-
-def read_colmap(col_bytes, object_layers):
- '''Read the RGB or RGBA color map.'''
- chunk_len= len(col_bytes)
- dia,= struct.unpack(">H", col_bytes[0:2])
- offset= 2
- name, name_len= read_lwostring(col_bytes[offset:])
- offset+= name_len
- colors= {}
-
- if dia == 3:
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pnt_id_len
- col= struct.unpack(">fff", col_bytes[offset:offset+12])
- offset+= 12
- colors[pnt_id]= (col[0], col[1], col[2])
- elif dia == 4:
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pnt_id_len
- col= struct.unpack(">ffff", col_bytes[offset:offset+16])
- offset+= 16
- colors[pnt_id]= (col[0], col[1], col[2])
-
- if name in object_layers[-1].colmaps:
- if "PointMap" in object_layers[-1].colmaps[name]:
- object_layers[-1].colmaps[name]["PointMap"].update(colors)
- else:
- object_layers[-1].colmaps[name]["PointMap"]= colors
- else:
- object_layers[-1].colmaps[name]= dict(PointMap=colors)
-
-
-def read_color_vmad(col_bytes, object_layers, last_pols_count):
- '''Read the Discontinous (per-polygon) RGB values.'''
- chunk_len= len(col_bytes)
- dia,= struct.unpack(">H", col_bytes[0:2])
- offset= 2
- name, name_len= read_lwostring(col_bytes[offset:])
- offset+= name_len
- colors= {}
- abs_pid= len(object_layers[-1].pols) - last_pols_count
-
- if dia == 3:
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pnt_id_len
- pol_id, pol_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pol_id_len
-
- # The PolyID in a VMAD can be relative, this offsets it.
- pol_id+= abs_pid
- col= struct.unpack(">fff", col_bytes[offset:offset+12])
- offset+= 12
- if pol_id in colors:
- colors[pol_id][pnt_id]= (col[0], col[1], col[2])
- else:
- colors[pol_id]= dict({pnt_id: (col[0], col[1], col[2])})
- elif dia == 4:
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pnt_id_len
- pol_id, pol_id_len= read_vx(col_bytes[offset:offset+4])
- offset+= pol_id_len
-
- pol_id+= abs_pid
- col= struct.unpack(">ffff", col_bytes[offset:offset+16])
- offset+= 16
- if pol_id in colors:
- colors[pol_id][pnt_id]= (col[0], col[1], col[2])
- else:
- colors[pol_id]= dict({pnt_id: (col[0], col[1], col[2])})
-
- if name in object_layers[-1].colmaps:
- if "FaceMap" in object_layers[-1].colmaps[name]:
- object_layers[-1].colmaps[name]["FaceMap"].update(colors)
- else:
- object_layers[-1].colmaps[name]["FaceMap"]= colors
- else:
- object_layers[-1].colmaps[name]= dict(FaceMap=colors)
-
-
-def read_uvmap(uv_bytes, object_layers):
- '''Read the simple UV coord values.'''
- chunk_len= len(uv_bytes)
- offset= 2
- name, name_len= read_lwostring(uv_bytes[offset:])
- offset+= name_len
- uv_coords= {}
-
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(uv_bytes[offset:offset+4])
- offset+= pnt_id_len
- pos= struct.unpack(">ff", uv_bytes[offset:offset+8])
- offset+= 8
- uv_coords[pnt_id]= (pos[0], pos[1])
-
- if name in object_layers[-1].uvmaps:
- if "PointMap" in object_layers[-1].uvmaps[name]:
- object_layers[-1].uvmaps[name]["PointMap"].update(uv_coords)
- else:
- object_layers[-1].uvmaps[name]["PointMap"]= uv_coords
- else:
- object_layers[-1].uvmaps[name]= dict(PointMap=uv_coords)
-
-
-def read_uv_vmad(uv_bytes, object_layers, last_pols_count):
- '''Read the Discontinous (per-polygon) uv values.'''
- chunk_len= len(uv_bytes)
- offset= 2
- name, name_len= read_lwostring(uv_bytes[offset:])
- offset+= name_len
- uv_coords= {}
- abs_pid= len(object_layers[-1].pols) - last_pols_count
-
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(uv_bytes[offset:offset+4])
- offset+= pnt_id_len
- pol_id, pol_id_len= read_vx(uv_bytes[offset:offset+4])
- offset+= pol_id_len
-
- pol_id+= abs_pid
- pos= struct.unpack(">ff", uv_bytes[offset:offset+8])
- offset+= 8
- if pol_id in uv_coords:
- uv_coords[pol_id][pnt_id]= (pos[0], pos[1])
- else:
- uv_coords[pol_id]= dict({pnt_id: (pos[0], pos[1])})
-
- if name in object_layers[-1].uvmaps:
- if "FaceMap" in object_layers[-1].uvmaps[name]:
- object_layers[-1].uvmaps[name]["FaceMap"].update(uv_coords)
- else:
- object_layers[-1].uvmaps[name]["FaceMap"]= uv_coords
- else:
- object_layers[-1].uvmaps[name]= dict(FaceMap=uv_coords)
-
-
-def read_weight_vmad(ew_bytes, object_layers):
- '''Read the VMAD Weight values.'''
- chunk_len= len(ew_bytes)
- offset= 2
- name, name_len= read_lwostring(ew_bytes[offset:])
- if name != "Edge Weight":
- return # We just want the Catmull-Clark edge weights
-
- offset+= name_len
- prev_pol= -1
- prev_pnt= -1
- prev_weight= 0.0
- first_pnt= -1
- poly_pnts= 0
- while offset < chunk_len:
- pnt_id, pnt_id_len= read_vx(ew_bytes[offset:offset+4])
- offset+= pnt_id_len
- pol_id, pol_id_len= read_vx(ew_bytes[offset:offset+4])
- offset+= pol_id_len
-
- weight,= struct.unpack(">f", ew_bytes[offset:offset+4])
- offset+= 4
- if prev_pol == pol_id:
- # Points on the same poly should define an edge.
- object_layers[-1].edge_weights["{0} {1}".format(prev_pnt, pnt_id)]= weight
- poly_pnts += 1
- else:
- if poly_pnts > 2:
- # Make an edge from the first and last points.
- object_layers[-1].edge_weights["{0} {1}".format(first_pnt, prev_pnt)]= prev_weight
- first_pnt= pnt_id
- prev_pol= pol_id
- poly_pnts= 1
-
- prev_pnt= pnt_id
- prev_weight= weight
-
- if poly_pnts > 2:
- object_layers[-1].edge_weights["{0} {1}".format(first_pnt, prev_pnt)]= prev_weight
-
-
-def read_pols(pol_bytes, object_layers):
- '''Read the layer's polygons, each one is just a list of point indexes.'''
- print("\tReading Layer ("+object_layers[-1].name+") Polygons")
- offset= 0
- pols_count = len(pol_bytes)
- old_pols_count= len(object_layers[-1].pols)
-
- while offset < pols_count:
- pnts_count,= struct.unpack(">H", pol_bytes[offset:offset+2])
- offset+= 2
- all_face_pnts= []
- for j in range(pnts_count):
- face_pnt, data_size= read_vx(pol_bytes[offset:offset+4])
- offset+= data_size
- all_face_pnts.append(face_pnt)
-
- object_layers[-1].pols.append(all_face_pnts)
-
- return len(object_layers[-1].pols) - old_pols_count
-
-
-def read_pols_5(pol_bytes, object_layers):
- '''
- Read the polygons, each one is just a list of point indexes.
- But it also includes the surface index.
- '''
- print("\tReading Layer ("+object_layers[-1].name+") Polygons")
- offset= 0
- chunk_len= len(pol_bytes)
- old_pols_count= len(object_layers[-1].pols)
- poly= 0
-
- while offset < chunk_len:
- pnts_count,= struct.unpack(">H", pol_bytes[offset:offset+2])
- offset+= 2
- all_face_pnts= []
- for j in range(pnts_count):
- face_pnt,= struct.unpack(">H", pol_bytes[offset:offset+2])
- offset+= 2
- all_face_pnts.append(face_pnt)
-
- object_layers[-1].pols.append(all_face_pnts)
- sid,= struct.unpack(">h", pol_bytes[offset:offset+2])
- offset+= 2
- sid= abs(sid) - 1
- if sid not in object_layers[-1].surf_tags:
- object_layers[-1].surf_tags[sid]= []
- object_layers[-1].surf_tags[sid].append(poly)
- poly+= 1
-
- return len(object_layers[-1].pols) - old_pols_count
-
-
-def read_bones(bone_bytes, object_layers):
- '''Read the layer's skelegons.'''
- print("\tReading Layer ("+object_layers[-1].name+") Bones")
- offset= 0
- bones_count = len(bone_bytes)
-
- while offset < bones_count:
- pnts_count,= struct.unpack(">H", bone_bytes[offset:offset+2])
- offset+= 2
- all_bone_pnts= []
- for j in range(pnts_count):
- bone_pnt, data_size= read_vx(bone_bytes[offset:offset+4])
- offset+= data_size
- all_bone_pnts.append(bone_pnt)
-
- object_layers[-1].bones.append(all_bone_pnts)
-
-
-def read_bone_tags(tag_bytes, object_layers, object_tags, type):
- '''Read the bone name or roll tags.'''
- offset= 0
- chunk_len= len(tag_bytes)
-
- if type == 'BONE':
- bone_dict= object_layers[-1].bone_names
- elif type == 'BNUP':
- bone_dict= object_layers[-1].bone_rolls
- else:
- return
-
- while offset < chunk_len:
- pid, pid_len= read_vx(tag_bytes[offset:offset+4])
- offset+= pid_len
- tid,= struct.unpack(">H", tag_bytes[offset:offset+2])
- offset+= 2
- bone_dict[pid]= object_tags[tid]
-
-
-def read_surf_tags(tag_bytes, object_layers, last_pols_count):
- '''Read the list of PolyIDs and tag indexes.'''
- print("\tReading Layer ("+object_layers[-1].name+") Surface Assignments")
- offset= 0
- chunk_len= len(tag_bytes)
-
- # Read in the PolyID/Surface Index pairs.
- abs_pid= len(object_layers[-1].pols) - last_pols_count
- while offset < chunk_len:
- pid, pid_len= read_vx(tag_bytes[offset:offset+4])
- offset+= pid_len
- sid,= struct.unpack(">H", tag_bytes[offset:offset+2])
- offset+=2
- if sid not in object_layers[-1].surf_tags:
- object_layers[-1].surf_tags[sid]= []
- object_layers[-1].surf_tags[sid].append(pid + abs_pid)
-
-
-def read_surf(surf_bytes, object_surfs):
- '''Read the object's surface data.'''
- if len(object_surfs) == 0:
- print("Reading Object Surfaces")
-
- surf= _obj_surf()
- name, name_len= read_lwostring(surf_bytes)
- if len(name) != 0:
- surf.name = name
-
- # We have to read this, but we won't use it...yet.
- s_name, s_name_len= read_lwostring(surf_bytes[name_len:])
- offset= name_len+s_name_len
- block_size= len(surf_bytes)
- while offset < block_size:
- subchunk_name,= struct.unpack("4s", surf_bytes[offset:offset+4])
- offset+= 4
- subchunk_len,= struct.unpack(">H", surf_bytes[offset:offset+2])
- offset+= 2
-
- # Now test which subchunk it is.
- if subchunk_name == b'COLR':
- surf.colr= struct.unpack(">fff", surf_bytes[offset:offset+12])
- # Don't bother with any envelopes for now.
-
- elif subchunk_name == b'DIFF':
- surf.diff,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'LUMI':
- surf.lumi,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'SPEC':
- surf.spec,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'REFL':
- surf.refl,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'RBLR':
- surf.rblr,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'TRAN':
- surf.tran,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'RIND':
- surf.rind,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'TBLR':
- surf.tblr,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'TRNL':
- surf.trnl,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'GLOS':
- surf.glos,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'SHRP':
- surf.shrp,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'SMAN':
- s_angle,= struct.unpack(">f", surf_bytes[offset:offset+4])
- if s_angle > 0.0:
- surf.smooth = True
-
- offset+= subchunk_len
-
- object_surfs[surf.name]= surf
-
-
-def read_surf_5(surf_bytes, object_surfs):
- '''Read the object's surface data.'''
- if len(object_surfs) == 0:
- print("Reading Object Surfaces")
-
- surf= _obj_surf()
- name, name_len= read_lwostring(surf_bytes)
- if len(name) != 0:
- surf.name = name
-
- offset= name_len
- chunk_len= len(surf_bytes)
- while offset < chunk_len:
- subchunk_name,= struct.unpack("4s", surf_bytes[offset:offset+4])
- offset+= 4
- subchunk_len,= struct.unpack(">H", surf_bytes[offset:offset+2])
- offset+= 2
-
- # Now test which subchunk it is.
- if subchunk_name == b'COLR':
- color= struct.unpack(">BBBB", surf_bytes[offset:offset+4])
- surf.colr= [color[0] / 255.0, color[1] / 255.0, color[2] / 255.0]
-
- elif subchunk_name == b'DIFF':
- surf.diff,= struct.unpack(">h", surf_bytes[offset:offset+2])
- surf.diff/= 256.0 # Yes, 256 not 255.
-
- elif subchunk_name == b'LUMI':
- surf.lumi,= struct.unpack(">h", surf_bytes[offset:offset+2])
- surf.lumi/= 256.0
-
- elif subchunk_name == b'SPEC':
- surf.spec,= struct.unpack(">h", surf_bytes[offset:offset+2])
- surf.spec/= 256.0
-
- elif subchunk_name == b'REFL':
- surf.refl,= struct.unpack(">h", surf_bytes[offset:offset+2])
- surf.refl/= 256.0
-
- elif subchunk_name == b'TRAN':
- surf.tran,= struct.unpack(">h", surf_bytes[offset:offset+2])
- surf.tran/= 256.0
-
- elif subchunk_name == b'RIND':
- surf.rind,= struct.unpack(">f", surf_bytes[offset:offset+4])
-
- elif subchunk_name == b'GLOS':
- surf.glos,= struct.unpack(">h", surf_bytes[offset:offset+2])
-
- elif subchunk_name == b'SMAN':
- s_angle,= struct.unpack(">f", surf_bytes[offset:offset+4])
- if s_angle > 0.0:
- surf.smooth = True
-
- offset+= subchunk_len
-
- object_surfs[surf.name]= surf
-
-
-def create_mappack(data, map_name, map_type):
- '''Match the map data to faces.'''
- pack= {}
-
- def color_pointmap(map):
- for fi in range(len(data.pols)):
- if fi not in pack:
- pack[fi]= []
- for pnt in data.pols[fi]:
- if pnt in map:
- pack[fi].append(map[pnt])
- else:
- pack[fi].append((1.0, 1.0, 1.0))
-
- def color_facemap(map):
- for fi in range(len(data.pols)):
- if fi not in pack:
- pack[fi]= []
- for p in data.pols[fi]:
- pack[fi].append((1.0, 1.0, 1.0))
- if fi in map:
- for po in range(len(data.pols[fi])):
- if data.pols[fi][po] in map[fi]:
- pack[fi].insert(po, map[fi][data.pols[fi][po]])
- del pack[fi][po+1]
-
- def uv_pointmap(map):
- for fi in range(len(data.pols)):
- if fi not in pack:
- pack[fi]= []
- for p in data.pols[fi]:
- pack[fi].append((-0.1,-0.1))
- for po in range(len(data.pols[fi])):
- pnt_id= data.pols[fi][po]
- if pnt_id in map:
- pack[fi].insert(po, map[pnt_id])
- del pack[fi][po+1]
-
- def uv_facemap(map):
- for fi in range(len(data.pols)):
- if fi not in pack:
- pack[fi]= []
- for p in data.pols[fi]:
- pack[fi].append((-0.1,-0.1))
- if fi in map:
- for po in range(len(data.pols[fi])):
- pnt_id= data.pols[fi][po]
- if pnt_id in map[fi]:
- pack[fi].insert(po, map[fi][pnt_id])
- del pack[fi][po+1]
-
- if map_type == "COLOR":
- # Look at the first map, is it a point or face map
- if "PointMap" in data.colmaps[map_name]:
- color_pointmap(data.colmaps[map_name]["PointMap"])
-
- if "FaceMap" in data.colmaps[map_name]:
- color_facemap(data.colmaps[map_name]["FaceMap"])
- elif map_type == "UV":
- if "PointMap" in data.uvmaps[map_name]:
- uv_pointmap(data.uvmaps[map_name]["PointMap"])
-
- if "FaceMap" in data.uvmaps[map_name]:
- uv_facemap(data.uvmaps[map_name]["FaceMap"])
-
- return pack
-
-
-def build_armature(layer_data, bones):
- '''Build an armature from the skelegon data in the mesh.'''
- print("Building Armature")
-
- # New Armatures include a default bone, remove it.
- bones.remove(bones[0])
-
- # Now start adding the bones at the point locations.
- prev_bone= None
- for skb_idx in range(len(layer_data.bones)):
- if skb_idx in layer_data.bone_names:
- nb= bones.new(layer_data.bone_names[skb_idx])
- else:
- nb= bones.new("Bone")
-
- nb.head= layer_data.pnts[layer_data.bones[skb_idx][0]]
- nb.tail= layer_data.pnts[layer_data.bones[skb_idx][1]]
-
- if skb_idx in layer_data.bone_rolls:
- xyz= layer_data.bone_rolls[skb_idx].split(' ')
- vec= mathutils.Vector()
- vec.x= float(xyz[0])
- vec.y= float(xyz[1])
- vec.z= float(xyz[2])
- quat= vec.to_track_quat('Y', 'Z')
- nb.roll= quat.to_euler('XYZ')[2] * -1
- # XXX: This code may need a second look and test.
- else:
- nb.roll= 0.0
-
- if prev_bone != None:
- if nb.head == prev_bone.tail:
- nb.parent= prev_bone
-
- nb.use_connect= True
- prev_bone= nb
-
-
-def build_objects(object_layers, object_surfs, object_tags, object_name, add_subd_mod, skel_to_arm):
- '''Using the gathered data, create the objects.'''
- ob_dict= {} # Used for the parenting setup.
- print("Adding %d Materials" % len(object_surfs))
-
- for surf_key in object_surfs:
- surf_data= object_surfs[surf_key]
- surf_data.bl_mat= bpy.data.materials.new(surf_data.name)
- surf_data.bl_mat.diffuse_color= (surf_data.colr[:])
- surf_data.bl_mat.diffuse_intensity= surf_data.diff
- surf_data.bl_mat.emit= surf_data.lumi
- surf_data.bl_mat.specular_intensity= surf_data.spec
- if surf_data.refl != 0.0:
- surf_data.bl_mat.raytrace_mirror.use= True
- surf_data.bl_mat.raytrace_mirror.reflect_factor= surf_data.refl
- surf_data.bl_mat.raytrace_mirror.gloss_factor= 1.0-surf_data.rblr
- if surf_data.tran != 0.0:
- surf_data.bl_mat.use_transparency= True
- surf_data.bl_mat.transparency_method= 'RAYTRACE'
- surf_data.bl_mat.alpha= 1.0 - surf_data.tran
- surf_data.bl_mat.raytrace_transparency.ior= surf_data.rind
- surf_data.bl_mat.raytrace_transparency.gloss_factor= 1.0 - surf_data.tblr
- surf_data.bl_mat.translucency= surf_data.trnl
- surf_data.bl_mat.specular_hardness= int(4*((10*surf_data.glos)*(10*surf_data.glos)))+4
- # The Gloss is as close as possible given the differences.
-
- # Single layer objects use the object file's name instead.
- if len(object_layers) and object_layers[-1].name == 'Layer 1':
- object_layers[-1].name= object_name
- print("Building '%s' Object" % object_name)
- else:
- print("Building %d Objects" % len(object_layers))
-
- for layer_data in object_layers:
- me= bpy.data.meshes.new(layer_data.name)
- me.vertices.add(len(layer_data.pnts))
- me.faces.add(len(layer_data.pols))
- # for vi in range(len(layer_data.pnts)):
- # me.vertices[vi].co= layer_data.pnts[vi]
-
- # faster, would be faster again to use an array
- me.vertices.foreach_set("co", [axis for co in layer_data.pnts for axis in co])
-
- ngons= {} # To keep the FaceIdx consistant, handle NGons later.
- edges= [] # Holds the FaceIdx of the 2-point polys.
- for fi, fpol in enumerate(layer_data.pols):
- fpol.reverse() # Reversing gives correct normal directions
- # PointID 0 in the last element causes Blender to think it's un-used.
- if fpol[-1] == 0:
- fpol.insert(0, fpol[-1])
- del fpol[-1]
-
- vlen= len(fpol)
- if vlen == 3 or vlen == 4:
- for i in range(vlen):
- me.faces[fi].vertices_raw[i]= fpol[i]
- elif vlen == 2:
- edges.append(fi)
- elif vlen != 1:
- ngons[fi]= fpol # Deal with them later
-
- ob= bpy.data.objects.new(layer_data.name, me)
- bpy.context.scene.objects.link(ob)
- ob_dict[layer_data.index]= [ob, layer_data.parent_index]
-
- # Move the object so the pivot is in the right place.
- ob.location= layer_data.pivot
-
- # Create the Material Slots and assign the MatIndex to the correct faces.
- mat_slot= 0
- for surf_key in layer_data.surf_tags:
- if object_tags[surf_key] in object_surfs:
- me.materials.append(object_surfs[object_tags[surf_key]].bl_mat)
-
- for fi in layer_data.surf_tags[surf_key]:
- me.faces[fi].material_index= mat_slot
- me.faces[fi].use_smooth= object_surfs[object_tags[surf_key]].smooth
-
- mat_slot+=1
-
- # Create the Vertex Groups (LW's Weight Maps).
- if len(layer_data.wmaps) > 0:
- print("Adding %d Vertex Groups" % len(layer_data.wmaps))
- for wmap_key in layer_data.wmaps:
- vgroup= ob.vertex_groups.new()
- vgroup.name= wmap_key
- wlist= layer_data.wmaps[wmap_key]
- for pvp in wlist:
- ob.vertex_groups.assign([pvp[0]], vgroup, pvp[1], 'REPLACE')
-
- # Create the Shape Keys (LW's Endomorphs).
- if len(layer_data.morphs) > 0:
- print("Adding %d Shapes Keys" % len(layer_data.morphs))
- ob.add_shape_key('Basis') # Got to have a Base Shape.
- for morph_key in layer_data.morphs:
- skey= ob.add_shape_key(morph_key)
- dlist= layer_data.morphs[morph_key]
- for pdp in dlist:
- me.shape_keys.keys[skey.name].data[pdp[0]].co= [pdp[1], pdp[2], pdp[3]]
-
- # Create the Vertex Color maps.
- if len(layer_data.colmaps) > 0:
- print("Adding %d Vertex Color Maps" % len(layer_data.colmaps))
- for cmap_key in layer_data.colmaps:
- map_pack= create_mappack(layer_data, cmap_key, "COLOR")
- vcol= me.vertex_colors.new(cmap_key)
- if not vcol:
- break
- for fi in map_pack:
- if fi > len(vcol.data):
- continue
- face= map_pack[fi]
- colf= vcol.data[fi]
-
- if len(face) > 2:
- colf.color1= face[0]
- colf.color2= face[1]
- colf.color3= face[2]
- if len(face) == 4:
- colf.color4= face[3]
-
- # Create the UV Maps.
- if len(layer_data.uvmaps) > 0:
- print("Adding %d UV Textures" % len(layer_data.uvmaps))
- for uvmap_key in layer_data.uvmaps:
- map_pack= create_mappack(layer_data, uvmap_key, "UV")
- uvm= me.uv_textures.new(uvmap_key)
- if not uvm:
- break
- for fi in map_pack:
- if fi > len(uvm.data):
- continue
- face= map_pack[fi]
- uvf= uvm.data[fi]
-
- if len(face) > 2:
- uvf.uv1= face[0]
- uvf.uv2= face[1]
- uvf.uv3= face[2]
- if len(face) == 4:
- uvf.uv4= face[3]
-
- # Now add the NGons.
- if len(ngons) > 0:
- for ng_key in ngons:
- face_offset= len(me.faces)
- ng= ngons[ng_key]
- v_locs= []
- for vi in range(len(ng)):
- v_locs.append(mathutils.Vector(layer_data.pnts[ngons[ng_key][vi]]))
- tris= PolyFill([v_locs])
- me.faces.add(len(tris))
- for tri in tris:
- face= me.faces[face_offset]
- face.vertices_raw[0]= ng[tri[0]]
- face.vertices_raw[1]= ng[tri[1]]
- face.vertices_raw[2]= ng[tri[2]]
- face.material_index= me.faces[ng_key].material_index
- face.use_smooth= me.faces[ng_key].use_smooth
- face_offset+= 1
-
- # FaceIDs are no longer a concern, so now update the mesh.
- has_edges= len(edges) > 0 or len(layer_data.edge_weights) > 0
- me.update(calc_edges=has_edges)
-
- # Add the edges.
- edge_offset= len(me.edges)
- me.edges.add(len(edges))
- for edge_fi in edges:
- me.edges[edge_offset].vertices[0]= layer_data.pols[edge_fi][0]
- me.edges[edge_offset].vertices[1]= layer_data.pols[edge_fi][1]
- edge_offset+= 1
-
- # Apply the Edge Weighting.
- if len(layer_data.edge_weights) > 0:
- for edge in me.edges:
- edge_sa= "{0} {1}".format(edge.vertices[0], edge.vertices[1])
- edge_sb= "{0} {1}".format(edge.vertices[1], edge.vertices[0])
- if edge_sa in layer_data.edge_weights:
- edge.crease= layer_data.edge_weights[edge_sa]
- elif edge_sb in layer_data.edge_weights:
- edge.crease= layer_data.edge_weights[edge_sb]
-
- # Unfortunately we can't exlude certain faces from the subdivision.
- if layer_data.has_subds and add_subd_mod:
- ob.modifiers.new(name="Subsurf", type='SUBSURF')
-
- # Should we build an armature from the embedded rig?
- if len(layer_data.bones) > 0 and skel_to_arm:
- bpy.ops.object.armature_add()
- arm_object= bpy.context.active_object
- arm_object.name= "ARM_" + layer_data.name
- arm_object.data.name= arm_object.name
- arm_object.location= layer_data.pivot
- bpy.ops.object.mode_set(mode='EDIT')
- build_armature(layer_data, arm_object.data.edit_bones)
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Clear out the dictionaries for this layer.
- layer_data.bone_names.clear()
- layer_data.bone_rolls.clear()
- layer_data.wmaps.clear()
- layer_data.colmaps.clear()
- layer_data.uvmaps.clear()
- layer_data.morphs.clear()
- layer_data.surf_tags.clear()
-
- # With the objects made, setup the parents and re-adjust the locations.
- for ob_key in ob_dict:
- if ob_dict[ob_key][1] != -1 and ob_dict[ob_key][1] in ob_dict:
- parent_ob = ob_dict[ob_dict[ob_key][1]]
- ob_dict[ob_key][0].parent= parent_ob[0]
- ob_dict[ob_key][0].location-= parent_ob[0].location
-
- bpy.context.scene.update()
-
- print("Done Importing LWO File")
-
-
-from bpy.props import *
-
-
-class IMPORT_OT_lwo(bpy.types.Operator):
- '''Import LWO Operator.'''
- bl_idname= "import_scene.lwo"
- bl_label= "Import LWO"
- bl_description= "Import a LightWave Object file."
- bl_options= {'REGISTER', 'UNDO'}
-
- filepath= StringProperty(name="File Path", description="Filepath used for importing the LWO file", maxlen=1024, default="")
-
- ADD_SUBD_MOD= BoolProperty(name="Apply SubD Modifier", description="Apply the Subdivision Surface modifier to layers with Subpatches", default=True)
- LOAD_HIDDEN= BoolProperty(name="Load Hidden Layers", description="Load object layers that have been marked as hidden", default=False)
- SKEL_TO_ARM= BoolProperty(name="Create Armature", description="Create an armature from an embedded Skelegon rig", default=True)
-
- def execute(self, context):
- load_lwo(self.properties.filepath,
- context,
- self.properties.ADD_SUBD_MOD,
- self.properties.LOAD_HIDDEN,
- self.properties.SKEL_TO_ARM)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm= context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_lwo.bl_idname, text="LightWave Object (.lwo)")
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py
deleted file mode 100644
index bc637c9e..00000000
--- a/io_import_scene_mhx.py
+++ /dev/null
@@ -1,2245 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Import MakeHuman (.mhx)",
- "author": "Thomas Larsson",
- "version": (0,9,5),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Import",
- "description": "Import files in the MakeHuman eXchange format (.mhx)",
- "warning": "Alpha version",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
- "Scripts/File_I-O/Make_Human",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"
- "func=detail&aid=21872&group_id=153&atid=469",
- "category": "Import/Export"}
-
-"""
-**Project Name:** MakeHuman
-
-**Product Home Page:** http://www.makehuman.org/
-
-**Code Home Page:** http://code.google.com/p/makehuman/
-
-**Authors:** Thomas Larsson
-
-**Copyright(c):** MakeHuman Team 2001-2010
-
-**Licensing:** GPL3 (see also http://sites.google.com/site/makehumandocs/licensing)
-
-**Coding Standards:** See http://sites.google.com/site/makehumandocs/developers-guide
-
-Abstract
-MHX (MakeHuman eXchange format) importer for Blender 2.5x.
-Version 0.9
-
-"""
-
-"""
-Place this file in the .blender/scripts/addons dir
-You have to activated the script in the "Add-Ons" tab (user preferences).
-Access from the File > Import menu.
-"""
-
-#
-#
-#
-
-import bpy
-import os
-import time
-import mathutils
-from mathutils import *
-import geometry
-import string
-
-MAJOR_VERSION = 0
-MINOR_VERSION = 9
-MHX249 = False
-Blender24 = False
-Blender25 = True
-TexDir = "~/makehuman/exports"
-
-#
-#
-#
-
-theScale = 1.0
-useMesh = 1
-doSmash = 1
-verbosity = 2
-warnedTextureDir = False
-warnedVersion = False
-
-true = True
-false = False
-Epsilon = 1e-6
-nErrors = 0
-theTempDatum = None
-
-todo = []
-
-#
-# toggle flags
-#
-
-T_ArmIK = 0x01
-T_LegIK = 0x02
-T_Replace = 0x20
-T_Face = 0x40
-T_Shape = 0x80
-T_Mesh = 0x100
-T_Armature = 0x200
-T_Proxy = 0x400
-T_Panel = 0x800
-
-T_Rigify = 0x1000
-T_Preset = 0x2000
-T_Symm = 0x4000
-T_MHX = 0x8000
-
-toggle = T_Replace + T_ArmIK + T_LegIK + T_Mesh + T_Armature + T_Face
-
-#
-# setFlagsAndFloats(rigFlags):
-#
-# Global floats
-fLegIK = 0.0
-fArmIK = 0.0
-fFingerPanel = 0.0
-fFingerIK = 0.0
-fFingerCurl = 0.0
-
-# rigLeg and rigArm flags
-T_Toes = 0x0001
-T_GoboFoot = 0x0002
-T_InvFoot = 0x0004
-
-T_FingerPanel = 0x100
-T_FingerCurl = 0x0200
-T_FingerIK = 0x0400
-
-
-T_LocalFKIK = 0x8000
-
-rigLeg = 0
-rigArm = 0
-
-def setFlagsAndFloats(rigFlags):
- global toggle, rigLeg, rigArm
-
- (footRig, fingerRig) = rigFlags
- rigLeg = 0
- rigArm = 0
- if footRig == 'Reverse foot': rigLeg |= T_InvFoot
- elif footRig == 'Gobo': rigLeg |= T_GoboFoot
-
- if fingerRig == 'Panel': rigArm |= T_FingerPanel
- elif fingerRig == 'IK': rigArm |= T_FingerIK
- elif fingerRig == 'Curl': rigArm |= T_FingerCurl
-
- toggle |= T_Panel
-
- # Global floats, used as influences
- global fFingerCurl, fLegIK, fArmIK, fFingerIK
-
- fFingerCurl = 1.0 if rigArm&T_FingerCurl else 0.0
- fLegIK = 1.0 if toggle&T_LegIK else 0.0
- fArmIK = 1.0 if toggle&T_ArmIK else 0.0
- fFingerIK = 1.0 if rigArm&T_FingerIK else 0.0
-
- return
-
-
-#
-# Dictionaries
-#
-
-loadedData = {
- 'NONE' : {},
-
- 'Object' : {},
- 'Mesh' : {},
- 'Armature' : {},
- 'Lamp' : {},
- 'Camera' : {},
- 'Lattice' : {},
- 'Curve' : {},
-
- 'Material' : {},
- 'Image' : {},
- 'MaterialTextureSlot' : {},
- 'Texture' : {},
-
- 'Bone' : {},
- 'BoneGroup' : {},
- 'Rigify' : {},
-
- 'Action' : {},
- 'Group' : {},
-
- 'MeshTextureFaceLayer' : {},
- 'MeshColorLayer' : {},
- 'VertexGroup' : {},
- 'ShapeKey' : {},
- 'ParticleSystem' : {},
-
- 'ObjectConstraints' : {},
- 'ObjectModifiers' : {},
- 'MaterialSlot' : {},
-}
-
-Plural = {
- 'Object' : 'objects',
- 'Mesh' : 'meshes',
- 'Lattice' : 'lattices',
- 'Curve' : 'curves',
- 'Group' : 'groups',
- 'Empty' : 'empties',
- 'Armature' : 'armatures',
- 'Bone' : 'bones',
- 'BoneGroup' : 'bone_groups',
- 'Pose' : 'poses',
- 'PoseBone' : 'pose_bones',
- 'Material' : 'materials',
- 'Texture' : 'textures',
- 'Image' : 'images',
- 'Camera' : 'cameras',
- 'Lamp' : 'lamps',
- 'World' : 'worlds',
-}
-
-#
-# Creators
-#
-
-def uvtexCreator(me, name):
- print("uvtexCreator", me, name)
- return me.uv_textures.new(name)
-
-
-def vertcolCreator(me, name):
- print("vertcolCreator", me, name)
- return me.vertex_colors.new(name)
-
-
-#
-# loadMhx(filePath, context, flags):
-#
-
-def loadMhx(filePath, context, flags):
- global toggle
- toggle = flags
- readMhxFile(filePath)
- return
-
-#
-# readMhxFile(filePath, rigFlags):
-#
-
-def readMhxFile(filePath, rigFlags):
- global todo, nErrors
-
- fileName = os.path.expanduser(filePath)
- (shortName, ext) = os.path.splitext(fileName)
- if ext != ".mhx":
- print("Error: Not a mhx file: " + fileName)
- return
- print( "Opening MHX file "+ fileName )
- time1 = time.clock()
-
- ignore = False
- stack = []
- tokens = []
- key = "toplevel"
- level = 0
- nErrors = 0
-
- setFlagsAndFloats(rigFlags)
-
- file= open(fileName, "rU")
- print( "Tokenizing" )
- lineNo = 0
- for line in file:
- # print(line)
- lineSplit= line.split()
- lineNo += 1
- if len(lineSplit) == 0:
- pass
- elif lineSplit[0] == '#':
- pass
- elif lineSplit[0] == 'end':
- try:
- sub = tokens
- tokens = stack.pop()
- if tokens:
- tokens[-1][2] = sub
- level -= 1
- except:
- print( "Tokenizer error at or before line %d" % lineNo )
- print( line )
- dummy = stack.pop()
- elif lineSplit[-1] == ';':
- if lineSplit[0] == '\\':
- key = lineSplit[1]
- tokens.append([key,lineSplit[2:-1],[]])
- else:
- key = lineSplit[0]
- tokens.append([key,lineSplit[1:-1],[]])
- else:
- key = lineSplit[0]
- tokens.append([key,lineSplit[1:],[]])
- stack.append(tokens)
- level += 1
- tokens = []
- file.close()
-
- if level != 0:
- raise NameError("Tokenizer out of kilter %d" % level)
- clearScene()
- print( "Parsing" )
- parse(tokens)
-
- for (expr, glbals, lcals) in todo:
- try:
- # print("Doing %s" % expr)
- exec(expr, glbals, lcals)
- except:
- msg = "Failed: "+expr
- print( msg )
- nErrors += 1
- #raise NameError(msg)
-
- print("Postprocess")
- postProcess()
- print("HideLayers")
- hideLayers()
- time2 = time.clock()
- print("toggle = %x" % toggle)
- msg = "File %s loaded in %g s" % (fileName, time2-time1)
- if nErrors:
- msg += " but there where %d errors. " % (nErrors)
- print(msg)
- return # loadMhx
-
-#
-# getObject(name, var, glbals, lcals):
-#
-
-def getObject(name, var, glbals, lcals):
- try:
- ob = loadedData['Object'][name]
- except:
- if name != "None":
- expr = "%s = loadedData['Object'][name]" % var
- print("Todo ", expr)
- todo.append((expr, glbals, lcals))
- ob = None
- return ob
-
-#
-# parse(tokens):
-#
-
-ifResult = False
-
-def parse(tokens):
- global warnedVersion, MHX249, ifResult
-
- for (key, val, sub) in tokens:
- # print("Parse %s" % key)
- data = None
- if key == 'MHX':
- if int(val[0]) != MAJOR_VERSION and int(val[1]) != MINOR_VERSION and not warnedVersion:
- print("Warning: \nThis file was created with another version of MHX\n")
- warnedVersion = True
-
- elif key == 'MHX249':
- MHX249 = eval(val[0])
- print("Blender 2.49 compatibility mode is %s\n" % MHX249)
-
- elif key == 'if':
- try:
- ifResult = eval(val[0])
- except:
- ifResult = False
- if ifResult:
- parse(sub)
-
- elif key == 'elif':
- if not ifResult:
- try:
- ifResult = eval(val[0])
- except:
- ifResult = False
- if ifResult:
- parse(sub)
-
- elif key == 'else':
- if not ifResult:
- parse(sub)
-
-
- elif MHX249:
- pass
-
- elif key == 'print':
- msg = concatList(val)
- print(msg)
- elif key == 'warn':
- msg = concatList(val)
- print(msg)
- elif key == 'error':
- msg = concatList(val)
- raise NameError(msg)
- elif key == "Object":
- parseObject(val, sub)
- elif key == "Mesh":
- data = parseMesh(val, sub)
- elif key == "Curve":
- data = parseCurve(val, sub)
- elif key == "Lattice":
- data = parseLattice(val, sub)
- elif key == "Group":
- data = parseGroup(val, sub)
- elif key == "Armature":
- data = parseArmature(val, sub)
- elif key == "Pose":
- data = parsePose(val, sub)
- elif key == "Action":
- data = parseAction(val, sub)
- elif key == "Material":
- data = parseMaterial(val, sub)
- elif key == "Texture":
- data = parseTexture(val, sub)
- elif key == "Image":
- data = parseImage(val, sub)
- elif key == "Process":
- parseProcess(val, sub)
- elif key == 'AnimationData':
- try:
- ob = loadedData['Object'][val[0]]
- except:
- ob = None
- if ob:
- bpy.context.scene.objects.active = ob
- parseAnimationData(ob, sub)
- elif key == 'ShapeKeys':
- try:
- ob = loadedData['Object'][val[0]]
- except:
- ob = None
- if ob:
- bpy.context.scene.objects.active = ob
- parseShapeKeys(ob, ob.data, val, sub)
- else:
- data = parseDefaultType(key, val, sub)
-
- if data and key != 'Mesh':
- print( data )
- return
-
-#
-# parseDefaultType(typ, args, tokens):
-#
-
-def parseDefaultType(typ, args, tokens):
- global todo
-
- name = args[0]
- data = None
- expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
- print(expr)
- data = eval(expr)
- print(" ok", data)
-
- bpyType = typ.capitalize()
- print(bpyType, name, data)
- loadedData[bpyType][name] = data
- if data == None:
- return None
-
- for (key, val, sub) in tokens:
- #print("%s %s" % (key, val))
- defaultKey(key, val, sub, 'data', [], globals(), locals())
- print("Done ", data)
- return data
-
-#
-# concatList(elts)
-#
-
-def concatList(elts):
- string = ""
- for elt in elts:
- string += " %s" % elt
- return string
-
-#
-# parseAction(args, tokens):
-# parseFCurve(fcu, args, tokens):
-# parseKeyFramePoint(pt, args, tokens):
-#
-
-def parseAction(args, tokens):
- name = args[0]
- if invalid(args[1]):
- return
-
- ob = bpy.context.object
- bpy.ops.object.mode_set(mode='POSE')
- if ob.animation_data:
- ob.animation_data.action = None
- created = {}
- for (key, val, sub) in tokens:
- if key == 'FCurve':
- prepareActionFCurve(ob, created, val, sub)
-
- act = ob.animation_data.action
- loadedData['Action'][name] = act
- if act == None:
- print("Ignoring action %s" % name)
- return act
- act.name = name
- print("Action", name, act, ob)
-
- for (key, val, sub) in tokens:
- if key == 'FCurve':
- fcu = parseActionFCurve(act, ob, val, sub)
- else:
- defaultKey(key, val, sub, 'act', [], globals(), locals())
- ob.animation_data.action = None
- bpy.ops.object.mode_set(mode='OBJECT')
- return act
-
-def prepareActionFCurve(ob, created, args, tokens):
- dataPath = args[0]
- index = args[1]
- (expr, channel) = channelFromDataPath(dataPath, index)
- try:
- if channel in created[expr]:
- return
- else:
- created[expr].append(channel)
- except:
- created[expr] = [channel]
-
- times = []
- for (key, val, sub) in tokens:
- if key == 'kp':
- times.append(int(val[0]))
-
- try:
- data = eval(expr)
- except:
- print("Ignoring illegal expression: %s" % expr)
- return
-
- n = 0
- for t in times:
- #bpy.context.scene.current_frame = t
- bpy.ops.anim.change_frame(frame = t)
- try:
- data.keyframe_insert(channel)
- n += 1
- except:
- pass
- #print("failed", data, expr, channel)
- if n != len(times):
- print("Mismatch", n, len(times), expr, channel)
- return
-
-def channelFromDataPath(dataPath, index):
- words = dataPath.split(']')
- if len(words) == 1:
- # location
- expr = "ob"
- channel = dataPath
- elif len(words) == 2:
- # pose.bones["tongue"].location
- expr = "ob.%s]" % (words[0])
- cwords = words[1].split('.')
- channel = cwords[1]
- elif len(words) == 3:
- # pose.bones["brow.R"]["mad"]
- expr = "ob.%s]" % (words[0])
- cwords = words[1].split('"')
- channel = cwords[1]
- # print(expr, channel, index)
- return (expr, channel)
-
-def parseActionFCurve(act, ob, args, tokens):
- dataPath = args[0]
- index = args[1]
- (expr, channel) = channelFromDataPath(dataPath, index)
- index = int(args[1])
-
- success = False
- for fcu in act.fcurves:
- (expr1, channel1) = channelFromDataPath(fcu.data_path, fcu.array_index)
- if expr1 == expr and channel1 == channel and fcu.array_index == index:
- success = True
- break
- if not success:
- return None
-
- n = 0
- for (key, val, sub) in tokens:
- if key == 'kp':
- try:
- pt = fcu.keyframe_points[n]
- pt.use_interpolation = 'LINEAR'
- pt = parseKeyFramePoint(pt, val, sub)
- n += 1
- except:
- pass
- #print(tokens)
- #raise NameError("kp", fcu, n, len(fcu.keyframe_points), val)
- else:
- defaultKey(key, val, sub, 'fcu', [], globals(), locals())
- return fcu
-
-def parseKeyFramePoint(pt, args, tokens):
- pt.co = (float(args[0]), float(args[1]))
- if len(args) > 2:
- pt.handle_left = (float(args[2]), float(args[3]))
- pt.handle_right = (float(args[3]), float(args[5]))
- return pt
-
-#
-# parseAnimationData(rna, tokens):
-# parseDriver(drv, args, tokens):
-# parseDriverVariable(var, args, tokens):
-#
-
-def parseAnimationData(rna, tokens):
- if 0 and toggle & T_MHX:
- return
- if rna.animation_data == None:
- rna.animation_data_create()
- adata = rna.animation_data
- for (key, val, sub) in tokens:
- if key == 'FCurve':
- fcu = parseAnimDataFCurve(adata, rna, val, sub)
- else:
- defaultKey(key, val, sub, 'adata', [], globals(), locals())
- return adata
-
-def parseAnimDataFCurve(adata, rna, args, tokens):
- if invalid(args[2]):
- return
- dataPath = args[0]
- index = int(args[1])
- # print("parseAnimDataFCurve", adata, dataPath, index)
- for (key, val, sub) in tokens:
- if key == 'Driver':
- fcu = parseDriver(adata, dataPath, index, rna, val, sub)
- elif key == 'FModifier':
- parseFModifier(fcu, val, sub)
- else:
- defaultKey(key, val, sub, 'fcu', [], globals(), locals())
- return fcu
-
-"""
- fcurve = con.driver_add("influence", 0)
- driver = fcurve.driver
- driver.type = 'AVERAGE'
-"""
-def parseDriver(adata, dataPath, index, rna, args, tokens):
- if dataPath[-1] == ']':
- words = dataPath.split(']')
- expr = "rna." + words[0] + ']'
- pwords = words[1].split('"')
- prop = pwords[1]
- # print("prop", expr, prop)
- bone = eval(expr)
- return None
- else:
- words = dataPath.split('.')
- channel = words[-1]
- expr = "rna"
- for n in range(len(words)-1):
- expr += "." + words[n]
- expr += ".driver_add('%s', index)" % channel
-
- # print("expr", rna, expr)
- fcu = eval(expr)
- drv = fcu.driver
- drv.type = args[0]
- for (key, val, sub) in tokens:
- if key == 'DriverVariable':
- var = parseDriverVariable(drv, rna, val, sub)
- else:
- defaultKey(key, val, sub, 'drv', [], globals(), locals())
- return fcu
-
-def parseDriverVariable(drv, rna, args, tokens):
- var = drv.variables.new()
- var.name = args[0]
- var.type = args[1]
- nTarget = 0
- # print("var", var, var.name, var.type)
- for (key, val, sub) in tokens:
- if key == 'Target':
- parseDriverTarget(var, nTarget, rna, val, sub)
- nTarget += 1
- else:
- defaultKey(key, val, sub, 'var', [], globals(), locals())
- return var
-
-def parseFModifier(fcu, args, tokens):
- #fmod = fcu.modifiers.new()
- fmod = fcu.modifiers[0]
- #fmod.type = args[0]
- #print("fmod", fmod, fmod.type)
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, 'fmod', [], globals(), locals())
- return fmod
-
-"""
- var = driver.variables.new()
- var.name = target_bone
- var.targets[0].id_type = 'OBJECT'
- var.targets[0].id = obj
- var.targets[0].rna_path = driver_path
-"""
-def parseDriverTarget(var, nTarget, rna, args, tokens):
- targ = var.targets[nTarget]
- # targ.rna_path = args[0]
- # targ.id_type = args[1]
- targ.id = loadedData['Object'][args[0]]
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, 'targ', [], globals(), locals())
- #print("Targ", targ, targ.id, targ.data_path, targ.id_type, targ.bone_target, targ.use_local_space_transform)
- return targ
-
-
-#
-# parseMaterial(args, ext, tokens):
-# parseMTex(mat, args, tokens):
-# parseTexture(args, tokens):
-#
-
-def parseMaterial(args, tokens):
- global todo
- name = args[0]
- #print("Parse material "+name)
- mat = bpy.data.materials.new(name)
- if mat == None:
- return None
- loadedData['Material'][name] = mat
- #print("Material %s %s %s" % (mat, name, loadedData['Material'][name]))
- for (key, val, sub) in tokens:
- if key == 'MTex':
- parseMTex(mat, val, sub)
- elif key == 'Ramp':
- parseRamp(mat, val, sub)
- elif key == 'SSS':
- parseSSS(mat, val, sub)
- elif key == 'Strand':
- parseStrand(mat, val, sub)
- else:
- exclude = ['specular_intensity', 'use_tangent_shading']
- defaultKey(key, val, sub, 'mat', [], globals(), locals())
- #print("Done ", mat)
-
- return mat
-
-def parseMTex(mat, args, tokens):
- global todo
- index = int(args[0])
- texname = args[1]
- texco = args[2]
- mapto = args[3]
-
- mtex = mat.texture_slots.add()
- mtex.texture = loadedData['Texture'][texname]
- mtex.texture_coords = texco
- mtex.use_map_color_diffuse = True # XXX, fixme, mapto not used
-
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "mtex", [], globals(), locals())
-
- return mtex
-
-def parseTexture(args, tokens):
- global todo
- if verbosity > 2:
- print( "Parsing texture %s" % args )
- tex = bpy.data.textures.new(name=args[0], type=args[1])
- loadedData['Texture'][name] = tex
-
- for (key, val, sub) in tokens:
- if key == 'Image':
- try:
- imgName = val[0]
- img = loadedData['Image'][imgName]
- tex.image = img
- except:
- msg = "Unable to load image '%s'" % val[0]
- elif key == 'Ramp':
- parseRamp(tex, val, sub)
- else:
- defaultKey(key, val, sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
-
- return tex
-
-def parseRamp(data, args, tokens):
- nvar = "data.%s" % args[0]
- use = "data.use_%s = True" % args[0]
- exec(use)
- ramp = eval(nvar)
- elts = ramp.elements
- n = 0
- for (key, val, sub) in tokens:
- # print("Ramp", key, val)
- if key == 'Element':
- elts[n].color = eval(val[0])
- elts[n].position = eval(val[1])
- n += 1
- else:
- defaultKey(key, val, sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
-
-def parseSSS(mat, args, tokens):
- sss = mat.subsurface_scattering
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "sss", [], globals(), locals())
-
-def parseStrand(mat, args, tokens):
- strand = mat.strand
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "strand", [], globals(), locals())
-
-#
-# doLoadImage(filepath):
-# loadImage(filepath):
-# parseImage(args, tokens):
-#
-
-def doLoadImage(filepath):
- path1 = os.path.expanduser(filepath)
- file1 = os.path.realpath(path1)
- if os.path.isfile(file1):
- print( "Found file "+file1 )
- try:
- img = bpy.data.images.load(file1)
- return img
- except:
- print( "Cannot read image" )
- return None
- else:
- print( "No file "+file1 )
- return None
-
-
-def loadImage(filepath):
- global TexDir, warnedTextureDir, loadedData
-
- texDir = os.path.expanduser(TexDir)
- path1 = os.path.expanduser(filepath)
- file1 = os.path.realpath(path1)
- (path, filename) = os.path.split(file1)
- (name, ext) = os.path.splitext(filename)
- print( "Loading ", filepath, " = ", filename )
-
- # img = doLoadImage(texDir+"/"+name+".png")
- # if img:
- # return img
-
- img = doLoadImage(texDir+"/"+filename)
- if img:
- return img
-
- # img = doLoadImage(path+"/"+name+".png")
- # if img:
- # return img
-
- img = doLoadImage(path+"/"+filename)
- if img:
- return img
-
- if warnedTextureDir:
- return None
- warnedTextureDir = True
- return None
- TexDir = Draw.PupStrInput("TexDir? ", path, 100)
-
- texDir = os.path.expanduser(TexDir)
- img = doLoadImage(texDir+"/"+name+".png")
- if img:
- return img
-
- img = doLoadImage(TexDir+"/"+filename)
- return img
-
-def parseImage(args, tokens):
- global todo
- imgName = args[0]
- img = None
- for (key, val, sub) in tokens:
- if key == 'Filename':
- filename = val[0]
- for n in range(1,len(val)):
- filename += " " + val[n]
- img = loadImage(filename)
- if img == None:
- return None
- img.name = imgName
- else:
- defaultKey(key, val, sub, "img", ['depth', 'is_dirty', 'has_data', 'size', 'type'], globals(), locals())
- print ("Image %s" % img )
- loadedData['Image'][imgName] = img
- return img
-
-#
-# parseObject(args, tokens):
-# createObject(type, name, data, datName):
-# createObjectAndData(args, typ):
-#
-
-def parseObject(args, tokens):
- if verbosity > 2:
- print( "Parsing object %s" % args )
- name = args[0]
- typ = args[1]
- datName = args[2]
- try:
- data = loadedData[typ.capitalize()][datName]
- except:
- data = None
-
- if data == None and typ != 'EMPTY':
- print("Failed to find data: %s %s %s" % (name, typ, datName))
- return
-
- try:
- ob = loadedData['Object'][name]
- bpy.context.scene.objects.active = ob
- #print("Found data")
- except:
- ob = createObject(typ, name, data, datName)
- if bpy.context.object != ob:
- print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
- # ob = foo
-
- for (key, val, sub) in tokens:
- if key == 'Modifier':
- parseModifier(ob, val, sub)
- elif key == 'Constraint':
- parseConstraint(ob.constraints, val, sub)
- elif key == 'AnimationData':
- if eval(val[0]):
- parseAnimationData(ob, sub)
- elif key == 'ParticleSystem':
- parseParticleSystem(ob, val, sub)
- else:
- defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
-
- # Needed for updating layers
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.object.mode_set(mode='OBJECT')
- return
-
-def createObject(typ, name, data, datName):
- #print( "Creating object %s %s %s" % (typ, name, data) )
- ob = bpy.data.objects.new(name, data)
- loadedData[typ][datName] = data
- loadedData['Object'][name] = ob
- return ob
-
-def linkObject(ob, data):
- #print("Data", data, ob.data)
- if data and ob.data == None:
- ob.data = data
- scn = bpy.context.scene
- scn.objects.link(ob)
- scn.objects.active = ob
- #print("Linked object", ob)
- #print("Scene", scn)
- #print("Active", scn.objects.active)
- #print("Context", bpy.context.object)
- return ob
-
-def createObjectAndData(args, typ):
- datName = args[0]
- obName = args[1]
- bpy.ops.object.add(type=typ.upper())
- ob = bpy.context.object
- ob.name = obName
- ob.data.name = datName
- loadedData[typ][datName] = ob.data
- loadedData['Object'][obName] = ob
- return ob.data
-
-
-#
-# parseModifier(ob, args, tokens):
-#
-
-def parseModifier(ob, args, tokens):
- name = args[0]
- typ = args[1]
- if typ == 'PARTICLE_SYSTEM':
- return None
- mod = ob.modifiers.new(name, typ)
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, 'mod', [], globals(), locals())
- return mod
-
-#
-# parseParticleSystem(ob, args, tokens):
-# parseParticles(particles, args, tokens):
-# parseParticle(par, args, tokens):
-#
-
-def parseParticleSystem(ob, args, tokens):
- print(ob, bpy.context.object)
- pss = ob.particle_systems
- print(pss, pss.values())
- name = args[0]
- typ = args[1]
- #psys = pss.new(name, typ)
- bpy.ops.object.particle_system_add()
- print(pss, pss.values())
- psys = pss[-1]
- psys.name = name
- psys.settings.type = typ
- loadedData['ParticleSystem'][name] = psys
- print("Psys", psys)
-
- for (key, val, sub) in tokens:
- if key == 'Particles':
- parseParticles(psys, val, sub)
- else:
- defaultKey(key, val, sub, 'psys', [], globals(), locals())
- return psys
-
-def parseParticles(psys, args, tokens):
- particles = psys.particles
- bpy.ops.particle.particle_edit_toggle()
- n = 0
- for (key, val, sub) in tokens:
- if key == 'Particle':
- parseParticle(particles[n], val, sub)
- n += 1
- else:
- for par in particles:
- defaultKey(key, val, sub, 'par', [], globals(), locals())
- bpy.ops.particle.particle_edit_toggle()
- return particles
-
-def parseParticle(par, args, tokens):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'h':
- h = par.is_hair[n]
- h.location = eval(val[0])
- h.time = int(val[1])
- h.weight = float(val[2])
- n += 1
- elif key == 'location':
- par.location = eval(val[0])
- return
-
-#
-# unpackList(list_of_tuples):
-#
-
-def unpackList(list_of_tuples):
- l = []
- for t in list_of_tuples:
- l.extend(t)
- return l
-
-#
-# parseMesh (args, tokens):
-#
-
-def parseMesh (args, tokens):
- global todo
- if verbosity > 2:
- print( "Parsing mesh %s" % args )
-
- mename = args[0]
- obname = args[1]
- me = bpy.data.meshes.new(mename)
- ob = createObject('Mesh', obname, me, mename)
-
- verts = []
- edges = []
- faces = []
- vertsTex = []
- texFaces = []
-
- for (key, val, sub) in tokens:
- if key == 'Verts':
- verts = parseVerts(sub)
- elif key == 'Edges':
- edges = parseEdges(sub)
- elif key == 'Faces':
- faces = parseFaces(sub)
-
- if faces:
- #x = me.from_pydata(verts, [], faces)
- me.vertices.add(len(verts))
- me.faces.add(len(faces))
- me.vertices.foreach_set("co", unpackList(verts))
- me.faces.foreach_set("vertices_raw", unpackList(faces))
- else:
- #x = me.from_pydata(verts, edges, [])
- me.vertices.add(len(verts))
- me.edges.add(len(edges))
- me.vertices.foreach_set("co", unpackList(verts))
- me.edges.foreach_set("vertices", unpackList(edges))
- #print(x)
- me.update()
- #print(me)
- linkObject(ob, me)
-
- mats = []
- for (key, val, sub) in tokens:
- if key in ('Verts', 'Edges'):
- pass
- elif key == 'Faces':
- parseFaces2(sub, me)
- elif key == 'MeshTextureFaceLayer':
- parseUvTexture(val, sub, me)
- elif key == 'MeshColorLayer':
- parseVertColorLayer(val, sub, me)
- elif key == 'VertexGroup':
- parseVertexGroup(ob, me, val, sub)
- elif key == 'ShapeKeys':
- parseShapeKeys(ob, me, val, sub)
- elif key == 'Material':
- try:
- me.materials.append(loadedData['Material'][val[0]])
- except:
- print("Could not add material", val[0])
- else:
- defaultKey(key, val, sub, "me", [], globals(), locals())
-
- return me
-
-#
-# parseVerts(tokens):
-# parseEdges(tokens):
-# parseFaces(tokens):
-# parseFaces2(tokens, me):
-#
-
-def parseVerts(tokens):
- verts = []
- for (key, val, sub) in tokens:
- if key == 'v':
- verts.append( (float(val[0]), float(val[1]), float(val[2])) )
- return verts
-
-def parseEdges(tokens):
- edges = []
- for (key, val, sub) in tokens:
- if key == 'e':
- edges.append((int(val[0]), int(val[1])))
- return edges
-
-def parseFaces(tokens):
- faces = []
- for (key, val, sub) in tokens:
- if key == 'f':
- if len(val) == 3:
- face = [int(val[0]), int(val[1]), int(val[2]), 0]
- elif len(val) == 4:
- face = [int(val[0]), int(val[1]), int(val[2]), int(val[3])]
- faces.append(face)
- return faces
-
-def parseFaces2(tokens, me):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'ft':
- f = me.faces[n]
- f.material_index = int(val[0])
- f.use_smooth = int(val[1])
- n += 1
- elif key == 'ftall':
- mat = int(val[0])
- smooth = int(val[1])
- for f in me.faces:
- f.material_index = mat
- f.use_smooth = smooth
- return
-
-
-#
-# parseUvTexture(args, tokens, me):
-# parseUvTexData(args, tokens, uvdata):
-#
-
-def parseUvTexture(args, tokens, me):
- name = args[0]
- uvtex = me.uv_textures.new(name)
- loadedData['MeshTextureFaceLayer'][name] = uvtex
- for (key, val, sub) in tokens:
- if key == 'Data':
- parseUvTexData(val, sub, uvtex.data)
- else:
- defaultKey(key, val, sub, "uvtex", [], globals(), locals())
- return
-
-def parseUvTexData(args, tokens, data):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'vt':
- data[n].uv1 = (float(val[0]), float(val[1]))
- data[n].uv2 = (float(val[2]), float(val[3]))
- data[n].uv3 = (float(val[4]), float(val[5]))
- if len(val) > 6:
- data[n].uv4 = (float(val[6]), float(val[7]))
- n += 1
- else:
- pass
- #for i in range(n):
- # defaultKey(key, val, sub, "data[i]", [], globals(), locals())
- return
-
-#
-# parseVertColorLayer(args, tokens, me):
-# parseVertColorData(args, tokens, data):
-#
-
-def parseVertColorLayer(args, tokens, me):
- name = args[0]
- print("VertColorLayer", name)
- vcol = me.vertex_colors.new(name)
- loadedData['MeshColorLayer'][name] = vcol
- for (key, val, sub) in tokens:
- if key == 'Data':
- parseVertColorData(val, sub, vcol.data)
- else:
- defaultKey(key, val, sub, "vcol", [], globals(), locals())
- return
-
-def parseVertColorData(args, tokens, data):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'cv':
- data[n].color1 = eval(val[0])
- data[n].color2 = eval(val[1])
- data[n].color3 = eval(val[2])
- data[n].color4 = eval(val[3])
- n += 1
- return
-
-
-#
-# parseVertexGroup(ob, me, args, tokens):
-#
-
-def parseVertexGroup(ob, me, args, tokens):
- global toggle
- if verbosity > 2:
- print( "Parsing vertgroup %s" % args )
- grpName = args[0]
- try:
- res = eval(args[1])
- except:
- res = True
- if not res:
- return
-
- if (toggle & T_Armature) or (grpName in ['Eye_L', 'Eye_R', 'Gums', 'Head', 'Jaw', 'Left', 'Middle', 'Right', 'Scalp']):
- group = ob.vertex_groups.new(grpName)
- group.name = grpName
- loadedData['VertexGroup'][grpName] = group
- ob.vertex_groups.assign([int(val[0]) for (key, val, sub) in tokens if key == 'wv'], group, float(val[1]), 'REPLACE')
- return
-
-
-#
-# parseShapeKeys(ob, me, args, tokens):
-# parseShapeKey(ob, me, args, tokens):
-# addShapeKey(ob, name, vgroup, tokens):
-# doShape(name):
-#
-
-def doShape(name):
- if (toggle & T_Shape+T_Face) and (name == 'Basis'):
- return True
- else:
- return (toggle & T_Face)
-
-def parseShapeKeys(ob, me, args, tokens):
- if bpy.context.object == None:
- return
- for (key, val, sub) in tokens:
- if key == 'ShapeKey':
- parseShapeKey(ob, me, val, sub)
- elif key == 'AnimationData':
- if me.shape_keys:
- parseAnimationData(me.shape_keys, sub)
- return
-
-
-def parseShapeKey(ob, me, args, tokens):
- if verbosity > 0:
- print( "Parsing ob %s shape %s" % (bpy.context.object, args[0] ))
- name = args[0]
- lr = args[1]
- if invalid(args[2]):
- return
-
- if lr == 'Sym' or toggle & T_Symm:
- addShapeKey(ob, name, None, tokens)
- elif lr == 'LR':
- addShapeKey(ob, name+'_L', 'Left', tokens)
- addShapeKey(ob, name+'_R', 'Right', tokens)
- else:
- raise NameError("ShapeKey L/R %s" % lr)
- return
-
-def addShapeKey(ob, name, vgroup, tokens):
- bpy.ops.object.shape_key_add(False)
- skey = ob.active_shape_key
- if name != 'Basis':
- skey.relative_key = loadedData['ShapeKey']['Basis']
- skey.name = name
- if vgroup:
- skey.vertex_group = vgroup
- loadedData['ShapeKey'][name] = skey
-
- for (key, val, sub) in tokens:
- if key == 'sv':
- index = int(val[0])
- pt = skey.data[index].co
- pt[0] += float(val[1])
- pt[1] += float(val[2])
- pt[2] += float(val[3])
- else:
- defaultKey(key, val, sub, "skey", [], globals(), locals())
-
- return
-
-
-#
-# parseArmature (obName, args, tokens)
-#
-
-def parseArmature (args, tokens):
- global toggle, theScale
- if verbosity > 2:
- print( "Parsing armature %s" % args )
-
- amtname = args[0]
- obname = args[1]
- mode = args[2]
-
- if mode == 'Rigify':
- toggle |= T_Rigify
- theScale = 0.1
- return parseRigify(amtname, obname, tokens)
-
- toggle &= ~T_Rigify
- theScale = 1.0
- amt = bpy.data.armatures.new(amtname)
- ob = createObject('Armature', obname, amt, amtname)
-
- linkObject(ob, amt)
- print("Linked")
-
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='EDIT')
-
- heads = {}
- tails = {}
- for (key, val, sub) in tokens:
- if key == 'Bone':
- bname = val[0]
- if not invalid(val[1]):
- bone = amt.edit_bones.new(bname)
- parseBone(bone, amt.edit_bones, sub, heads, tails)
- loadedData['Bone'][bname] = bone
- else:
- defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
- bpy.ops.object.mode_set(mode='OBJECT')
- return amt
-
-#
-# parseRigify(amtname, obname, tokens):
-#
-
-def parseRigify(amtname, obname, tokens):
- (key,val,sub) = tokens[0]
- if key != 'MetaRig':
- raise NameError("Expected MetaRig")
- typ = val[0]
- if typ == "human":
- bpy.ops.object.armature_human_advanced_add()
- else:
- bpy.ops.pose.metarig_sample_add(type = typ)
- ob = bpy.context.scene.objects.active
- amt = ob.data
- loadedData['Rigify'][obname] = ob
- loadedData['Armature'][amtname] = amt
- loadedData['Object'][obname] = ob
- print("Rigify object", ob, amt)
-
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='EDIT')
-
- heads = {}
- tails = {}
- for (bname, bone) in amt.edit_bones.items():
- heads[bname] = 10*theScale*bone.head
- tails[bname] = 10*theScale*bone.tail
-
- for (key, val, sub) in tokens:
- if key == 'Bone':
- bname = val[0]
- print("Bone", bname)
- try:
- bone = amt.edit_bones[bname]
- except:
- print("Did not find bone %s" % bname)
- bone = None
- print(" -> ", bone)
- if bone:
- parseBone(bone, amt.edit_bones, sub, heads, tails)
- else:
- defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
- bpy.ops.object.mode_set(mode='OBJECT')
- return amt
-
-#
-# parseBone(bone, bones, tokens, heads, tails):
-#
-
-def parseBone(bone, bones, tokens, heads, tails):
- global todo
-
- for (key, val, sub) in tokens:
- if key == "head":
- bone.head = (float(val[0]), float(val[1]), float(val[2]))
- elif key == "tail":
- bone.tail = (float(val[0]), float(val[1]), float(val[2]))
- elif key == "head-as":
- target = val[0]
- if val[1] == 'head':
- bone.head = heads[bone.name] + bones[target].head - heads[target]
- elif val[1] == 'tail':
- bone.head = heads[bone.name] + bones[target].tail - tails[target]
- else:
- raise NameError("head-as %s" % val)
- elif key == "tail-as":
- target = val[0]
- if val[1] == 'head':
- bone.tail = tails[bone.name] + bones[target].head - heads[target]
- elif val[1] == 'tail':
- bone.tail = tails[bone.name] + bones[target].tail - tails[target]
- else:
- raise NameError("tail-as %s" % val)
- elif key == 'hide_select':
- pass
- else:
- defaultKey(key, val, sub, "bone", [], globals(), locals())
-
- return bone
-
-#
-# parsePose (args, tokens):
-#
-
-def parsePose (args, tokens):
- global todo
- if toggle & T_Rigify:
- return
- name = args[0]
- ob = loadedData['Object'][name]
- bpy.context.scene.objects.active = ob
- bpy.ops.object.mode_set(mode='POSE')
- pbones = ob.pose.bones
- nGrps = 0
- for (key, val, sub) in tokens:
- if key == 'Posebone':
- parsePoseBone(pbones, ob, val, sub)
- elif key == 'BoneGroup':
- parseBoneGroup(ob.pose, nGrps, val, sub)
- nGrps += 1
- elif key == 'SetProp':
- bone = val[0]
- prop = val[1]
- value = eval(val[2])
- pb = pbones[bone]
- print("Setting", pb, prop, val)
- pb[prop] = value
- print("Prop set", pb[prop])
- else:
- defaultKey(key, val, sub, "ob.pose", [], globals(), locals())
- bpy.ops.object.mode_set(mode='OBJECT')
- return ob
-
-
-#
-# parsePoseBone(pbones, args, tokens):
-# parseArray(data, exts, args):
-#
-
-def parseBoneGroup(pose, nGrps, args, tokens):
- global todo
- return
- print( "Parsing bonegroup %s" % args )
- name = args[0]
- print(dir(pose.bone_groups))
- bg = pose.bone_groups.add()
- print("Created", bg)
- loadedData['BoneGroup'][name] = bg
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "bg", [], globals(), locals())
- return
-
-def parsePoseBone(pbones, ob, args, tokens):
- global todo
- #print( "Parsing posebone %s" % args )
- if invalid(args[1]):
- return
- name = args[0]
- pb = pbones[name]
-
- # Make posebone active - don't know how to do this in pose mode
- bpy.ops.object.mode_set(mode='OBJECT')
- ob.data.bones.active = pb.bone
- bpy.ops.object.mode_set(mode='POSE')
-
- for (key, val, sub) in tokens:
- if key == 'Constraint':
- cns = parseConstraint(pb.constraints, val, sub)
- elif key == 'bpyops':
- expr = "bpy.ops.%s" % val[0]
- print(expr)
- print("ob", bpy.context.active_object)
- print("b", bpy.context.active_bone)
- print("pb", bpy.context.active_pose_bone)
- print("md", bpy.context.mode)
- exec(expr)
- print("show_alive")
- elif key == 'ik_dof':
- parseArray(pb, ["lock_ik_x", "lock_ik_y", "lock_ik_z"], val)
- elif key == 'ik_limit':
- parseArray(pb, ["use_ik_limit_x", "use_ik_limit_y", "use_ik_limit_z"], val)
- elif key == 'ik_max':
- parseArray(pb, ["ik_max_x", "ik_max_y", "ik_max_z"], val)
- elif key == 'ik_min':
- parseArray(pb, ["ik_min_x", "ik_min_y", "ik_min_z"], val)
- elif key == 'ik_stiffness':
- parseArray(pb, ["ik_stiffness_x", "ik_stiffness_y", "ik_stiffness_z"], val)
- else:
- defaultKey(key, val, sub, "pb", [], globals(), locals())
- #print("pb %s done" % name)
- return
-
-def parseArray(data, exts, args):
- n = 1
- for ext in exts:
- expr = "data.%s = %s" % (ext, args[n])
- # print(expr)
- exec(expr)
- n += 1
- return
-
-#
-# parseConstraint(constraints, args, tokens)
-#
-
-def parseConstraint(constraints, args, tokens):
- if invalid(args[2]):
- return None
- cns = constraints.new(args[1])
- #bpy.ops.pose.constraint_add(type=args[1])
- #cns = pb.constraints[-1]
-
- cns.name = args[0]
- #print("cns", cns.name)
- for (key,val,sub) in tokens:
- if key == 'invert':
- parseArray(cns, ["invert_x", "invert_y", "invert_z"], val)
- elif key == 'use':
- parseArray(cns, ["use_x", "use_y", "use_z"], val)
- elif key == 'pos_lock':
- parseArray(cns, ["lock_location_x", "lock_location_y", "lock_location_z"], val)
- elif key == 'rot_lock':
- parseArray(cns, ["lock_rotation_x", "lock_rotation_y", "lock_rotation_z"], val)
- else:
- defaultKey(key, val, sub, "cns", [], globals(), locals())
- #print("cns %s done" % cns.name)
- return cns
-
-def insertInfluenceIpo(cns, bone):
- global todo
- if bone != 'PArmIK_L' and bone != 'PArmIK_R' and bone != 'PLegIK_L' and bone != 'PLegIK_R':
- return False
-
- if (toggle & T_FKIK):
- fcurve = cns.driver_add("influence", 0)
- fcurve.driver.type = 'AVERAGE'
-
- var = fcurve.driver.variables.new()
- var.name = bone
- var.targets[0].id_type = 'OBJECT'
- var.targets[0].id = getObject('HumanRig', 'var.targets[0].id', globals(), locals())
- var.targets[0].bone_target = bone
- var.targets[0].transform_type = 'LOC_X'
- # controller_path = fk_chain.arm_p.path_to_id()
- #var.targets[0].data_path = controller_path + '["use_hinge"]'
-
- mod = fcurve.modifiers[0]
- mod.poly_order = 2
- mod.coefficients[0] = 0.0
- mod.coefficients[1] = 1.0
- elif bone == 'PArmIK_L' or bone == 'PArmIK_R':
- if toggle & T_ArmIK:
- cns.influence = 1.0
- else:
- cns.influence = 0.0
- elif bone == 'PLegIK_L' or bone == 'PLegIK_R':
- if toggle & T_LegIK:
- cns.influence = 1.0
- else:
- cns.influence = 0.0
-
- return True
-
-#
-# parseCurve (args, tokens):
-# parseNurb(cu, nNurbs, args, tokens):
-# parseBezier(nurb, n, args, tokens):
-#
-
-def parseCurve (args, tokens):
- global todo
- if verbosity > 2:
- print( "Parsing curve %s" % args )
- cu = createObjectAndData(args, 'Curve')
-
- nNurbs = 0
- for (key, val, sub) in tokens:
- if key == 'Nurb':
- parseNurb(cu, nNurbs, val, sub)
- nNurbs += 1
- else:
- defaultKey(key, val, sub, "cu", [], globals(), locals())
- return
-
-def parseNurb(cu, nNurbs, args, tokens):
- if nNurbs > 0:
- bpy.ops.object.curve_add(type='BEZIER_CURVE')
- print(cu.splines, list(cu.splines), nNurbs)
- nurb = cu.splines[nNurbs]
- nPoints = int(args[0])
- print(nurb, nPoints)
- for n in range(2, nPoints):
- bpy.ops.curve.extrude(mode=1)
-
- n = 0
- for (key, val, sub) in tokens:
- if key == 'bz':
- parseBezier(nurb, n, val, sub)
- n += 1
- elif key == 'pt':
- parsePoint(nurb, n, val, sub)
- n += 1
- else:
- defaultKey(key, val, sub, "nurb", [], globals(), locals())
- return
-
-def parseBezier(nurb, n, args, tokens):
- bez = nurb[n]
- bez.co = eval(args[0])
- bez.handle_left = eval(args[1])
- bez.handle_left_type = args[2]
- bez.handle_right = eval(args[3])
- bez.handle_right_type = args[4]
- return
-
-def parsePoint(nurb, n, args, tokens):
- pt = nurb[n]
- pt.co = eval(args[0])
- return
-
-#
-# parseLattice (args, tokens):
-#
-
-def parseLattice (args, tokens):
- global todo
- if verbosity > 2:
- print( "Parsing lattice %s" % args )
- lat = createObjectAndData(args, 'Lattice')
- for (key, val, sub) in tokens:
- if key == 'Points':
- parseLatticePoints(val, sub, lat.points)
- else:
- defaultKey(key, val, sub, "lat", [], globals(), locals())
- return
-
-def parseLatticePoints(args, tokens, points):
- global todo
- n = 0
- for (key, val, sub) in tokens:
- if key == 'pt':
- v = points[n].co
- (x,y,z) = eval(val[0])
- v.x = x
- v.y = y
- v.z = z
-
- v = points[n].co_deform
- (x,y,z) = eval(val[1])
- v.x = x
- v.y = y
- v.z = z
-
- n += 1
- return
-
-#
-# parseGroup (args, tokens):
-#
-
-def parseGroup (args, tokens):
- global todo
- if verbosity > 2:
- print( "Parsing group %s" % args )
-
- grpName = args[0]
- grp = bpy.data.groups.new(grpName)
- loadedData['Group'][grpName] = grp
- for (key, val, sub) in tokens:
- if key == 'Objects':
- parseGroupObjects(val, sub, grp)
- else:
- defaultKey(key, val, sub, "grp", [], globals(), locals())
- return
-
-def parseGroupObjects(args, tokens, grp):
- global todo
- for (key, val, sub) in tokens:
- if key == 'ob':
- try:
- ob = loadedData['Object'][val[0]]
- grp.objects.link(ob)
- except:
- pass
- return
-
-#
-# postProcess()
-# setInfluence(bones, cnsName, w):
-#
-
-def postProcess():
- if not toggle & T_MHX:
- return
- if toggle & T_Rigify:
- return
- for rig in loadedData['Rigify'].values():
- bpy.context.scene.objects.active = rig
- print("Rigify", rig)
- bpy.ops.pose.metarig_generate()
- print("Metarig generated")
- #bpy.context.scene.objects.unlink(rig)
- rig = bpy.context.scene.objects.active
- print("Rigged", rig, bpy.context.object)
- ob = loadedData['Object']['Human']
- mod = ob.modifiers[0]
- print(ob, mod, mod.object)
- mod.object = rig
- print("Rig changed", mod.object)
- return
-
-#
-# parseProcess(args, tokens):
-#
-
-def parseProcess(args, tokens):
- return
- rig = loadedData['Object'][args[0]]
- parents = {}
- objects = []
-
- for (key, val, sub) in tokens:
- if key == 'Reparent':
- bname = val[0]
- try:
- eb = ebones[bname]
- parents[bname] = eb.parent.name
- eb.parent = ebones[val[1]]
- except:
- pass
- elif key == 'Bend':
- print(val)
- axis = val[1]
- angle = float(val[2])
- mat = mathutils.Matrix.Rotation(angle, 4, axis)
- try:
- pb = pbones[val[0]]
- prod = pb.matrix_local * mat
- for i in range(4):
- for j in range(4):
- pb.matrix_local[i][j] = prod[i][j]
- print("Done", pb.matrix_local)
- except:
- pass
- elif key == 'Pose':
- bpy.context.scene.objects.active = rig
- bpy.ops.object.mode_set(mode='POSE')
- pbones = rig.pose.bones
- elif key == 'Edit':
- bpy.context.scene.objects.active = rig
- bpy.ops.object.mode_set(mode='EDIT')
- ebones = rig.data.edit_bones
- elif key == 'Object':
- bpy.ops.object.mode_set(mode='OBJECT')
- try:
- ob = loadedData['Object'][val[0]]
- objects.append((ob,sub))
- except:
- ob = None
- if ob:
- bpy.context.scene.objects.active = ob
- mod = ob.modifiers[0]
- ob.modifiers.remove(mod)
- for (key1, val1, sub1) in sub:
- if key1 == 'Modifier':
- parseModifier(ob, val1, sub1)
-
- for (ob,tokens) in objects:
- bpy.context.scene.objects.active = ob
- bpy.ops.object.visual_transform_apply()
- #print("vis", list(ob.modifiers))
- bpy.ops.object.modifier_apply(apply_as='DATA', modifier='Armature')
- #print("app", list(ob.modifiers))
-
- bpy.context.scene.objects.active = rig
- bpy.ops.object.mode_set(mode='POSE')
- bpy.ops.pose.armature_apply()
- bpy.ops.object.mode_set(mode='EDIT')
- ebones = rig.data.edit_bones
- for (bname, pname) in parents.items():
- eb = ebones[bname]
- par = ebones[pname]
- if eb.use_connect:
- par.tail = eb.head
- eb.parent = par
- bpy.ops.object.mode_set(mode='OBJECT')
-
- for (ob,tokens) in objects:
- bpy.context.scene.objects.active = ob
- for (key, val, sub) in tokens:
- if key == 'Modifier':
- parseModifier(ob, val, sub)
-
- return
-
-#
-# defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
-#
-
-def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
- global todo
-
- if ext == 'Property':
- expr = "%s['%s'] = %s" % (var, args[0], args[1])
- print("Property", expr)
- exec(expr, glbals, lcals)
- #print("execd")
- return
-
- nvar = "%s.%s" % (var, ext)
- # print(ext)
- if ext in exclude:
- return
- #print("D", nvar)
-
- if len(args) == 0:
- raise NameError("Key length 0: %s" % ext)
-
- rnaType = args[0]
- if rnaType == 'Add':
- print("*** Cannot Add yet ***")
- return
-
- elif rnaType == 'Refer':
- typ = args[1]
- name = args[2]
- data = "loadedData['%s']['%s']" % (typ, name)
-
- elif rnaType == 'Struct' or rnaType == 'Define':
- typ = args[1]
- name = args[2]
- try:
- data = eval(nvar, glbals, lcals)
- except:
- data = None
- # print("Old structrna", nvar, data)
-
- if data == None:
- try:
- creator = args[3]
- except:
- creator = None
- # print("Creator", creator, eval(var,glbals,lcals))
-
- try:
- rna = eval(var,glbals,lcals)
- data = eval(creator)
- except:
- data = None
- # print("New struct", nvar, typ, data)
-
- if rnaType == 'Define':
- loadedData[typ][name] = data
-
- if data:
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "data", [], globals(), locals())
-
- print("Struct done", nvar)
- return
-
- elif rnaType == 'PropertyRNA':
- raise NameError("PropertyRNA!")
- #print("PropertyRNA ", ext, var)
- for (key, val, sub) in tokens:
- defaultKey(ext, val, sub, nvar, [], glbals, lcals)
- return
-
- elif rnaType == 'Array':
- for n in range(1, len(args)):
- expr = "%s[%d] = %s" % (nvar, n-1, args[n])
- exec(expr, glbals, lcals)
- if len(args) > 0:
- expr = "%s[0] = %s" % (nvar, args[1])
- exec(expr, glbals, lcals)
- return
-
- elif rnaType == 'List':
- data = []
- for (key, val, sub) in tokens:
- elt = eval(val[1], glbals, lcals)
- data.append(elt)
-
- elif rnaType == 'Matrix':
- return
- i = 0
- n = len(tokens)
- for (key, val, sub) in tokens:
- if key == 'row':
- for j in range(n):
- expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j]))
- exec(expr, glbals, lcals)
- i += 1
- return
-
- else:
- try:
- data = loadedData[rnaType][args[1]]
- #print("From loaded", rnaType, args[1], data)
- return data
- except:
- data = rnaType
-
- #print(var, ext, data)
- expr = "%s = %s" % (nvar, data)
- try:
- exec(expr, glbals, lcals)
- except:
- #print("Failed ",expr)
- todo.append((expr, glbals, lcals))
- return
-
-#
-# parseBoolArray(mask):
-#
-
-def parseBoolArray(mask):
- list = []
- for c in mask:
- if c == '0':
- list.append(False)
- else:
- list.append(True)
- return list
-
-# parseMatrix(args, tokens)
-#
-
-def parseMatrix(args, tokens):
- matrix = Matrix( [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] )
- i = 0
- for (key, val, sub) in tokens:
- if key == 'row':
- matrix[i][0] = float(val[0])
- matrix[i][1] = float(val[1])
- matrix[i][2] = float(val[2])
- matrix[i][3] = float(val[3])
- i += 1
- return matrix
-
-#
-# parseDefault(data, tokens, exclude):
-#
-
-def parseDefault(data, tokens):
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, "data", exclude, globals(), locals())
-
-
-#
-# Utilities
-#
-
-#
-# extractBpyType(data):
-#
-
-def extractBpyType(data):
- typeSplit = str(type(data)).split("'")
- if typeSplit[0] != '<class ':
- return None
- classSplit = typeSplit[1].split(".")
- if classSplit[0] == 'bpy' and classSplit[1] == 'types':
- return classSplit[2]
- elif classSplit[0] == 'bpy_types':
- return classSplit[1]
- else:
- return None
-
-#
-# Bool(string):
-#
-
-def Bool(string):
- if string == 'True':
- return True
- elif string == 'False':
- return False
- else:
- raise NameError("Bool %s?" % string)
-
-#
-# invalid(condition):
-#
-
-def invalid(condition):
- global rigLeg, rigArm, toggle
- res = eval(condition, globals())
- try:
- res = eval(condition, globals())
- #print("%s = %s" % (condition, res))
- return not res
- except:
- #print("%s invalid!" % condition)
- return True
-
-#
-# clearScene(context):
-# hideLayers():
-#
-
-def clearScene():
- global toggle
- scn = bpy.context.scene
- for n in range(len(scn.layers)):
- scn.layers[n] = True
- print("clearScene %s %s" % (toggle & T_Replace, scn))
- if not toggle & T_Replace:
- return scn
-
- for ob in scn.objects:
- if ob.type == "MESH" or ob.type == "ARMATURE":
- scn.objects.active = ob
- bpy.ops.object.mode_set(mode='OBJECT')
- scn.objects.unlink(ob)
- del ob
- #print(scn.objects)
- return scn
-
-def hideLayers():
- scn = bpy.context.scene
- for n in range(len(scn.layers)):
- if n < 3:
- scn.layers[n] = True
- else:
- scn.layers[n] = False
- return
-
-#
-# User interface
-#
-
-DEBUG= False
-from bpy.props import *
-
-class IMPORT_OT_makehuman_mhx(bpy.types.Operator):
- '''Import from MHX file format (.mhx)'''
- bl_idname = "import_scene.makehuman_mhx"
- bl_description = 'Import from MHX file format (.mhx)'
- bl_label = "Import MHX"
- bl_space_type = "PROPERTIES"
- bl_region_type = "WINDOW"
-
- filepath = StringProperty(name="File Path", description="Filepath used for importing the MHX file", maxlen= 1024, default= "")
-
- #preset = BoolProperty(name="Use rig preset", description="Use rig preset (Classic/Gobo)?", default=True)
- #presetRig = EnumProperty(name="Rig", description="Choose preset rig",
- # items = [('Classic','Classic','Classic'), ('Gobo','Gobo','Gobo')], default = '1')
- footRig = EnumProperty(name="Foot rig", description="Foot rig",
- items = [('Reverse foot','Reverse foot','Reverse foot'), ('Gobo','Gobo','Gobo')], default = '1')
- fingerRig = EnumProperty(name="Finger rig", description="Finger rig",
- items = [('Panel','Panel','Panel'), ('Curl','Curl','Curl'), ('IK','IK','IK')], default = '1')
-
- mesh = BoolProperty(name="Mesh", description="Use main mesh", default=toggle&T_Mesh)
- armature = BoolProperty(name="Armature", description="Use armature", default=toggle&T_Armature)
- proxy = BoolProperty(name="Proxy", description="Use proxy object", default=toggle&T_Proxy)
- replace = BoolProperty(name="Replace scene", description="Replace scene", default=toggle&T_Replace)
- face = BoolProperty(name="Face shapes", description="Include facial shapekeys", default=toggle&T_Face)
- shape = BoolProperty(name="Body shapes", description="Include body shapekeys", default=toggle&T_Shape)
- symm = BoolProperty(name="Symmetric shapes", description="Keep shapekeys symmetric", default=toggle&T_Symm)
-
- def execute(self, context):
- global toggle
- O_Mesh = T_Mesh if self.properties.mesh else 0
- O_Armature = T_Armature if self.properties.armature else 0
- O_Proxy = T_Proxy if self.properties.proxy else 0
- O_Replace = T_Replace if self.properties.replace else 0
- O_Face = T_Face if self.properties.face else 0
- O_Shape = T_Shape if self.properties.shape else 0
- O_Symm = T_Symm if self.properties.symm else 0
- #O_Preset = T_Preset if self.properties.preset else 0
- toggle = O_Mesh | O_Armature | O_Proxy | T_ArmIK | T_LegIK | O_Replace | O_Face | O_Shape | O_Symm | T_MHX
-
-
- readMhxFile(self.properties.filepath,
- (self.properties.footRig,
- self.properties.fingerRig))
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-'''
-class MakeHumanFKIKPanel(bpy.types.Panel):
- bl_label = "MakeHuman FK/IK"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
-
- def draw(self, context):
- layout = self.layout
- ob = bpy.context.active_object
- if ob.type == 'ARMATURE':
- layout.row().prop(ob, "PArmIK_L")
- layout.row().prop(ob, "PArmIK_R")
- layout.row().prop(ob, "PLegIK_L")
- layout.row().prop(ob, "PLegIK_R")
-
- layout.row().prop(ob, "PHandLocal_L")
- layout.row().prop(ob, "PHandLocal_R")
- layout.row().prop(ob, "PFootLocal_L")
- layout.row().prop(ob, "PFootLocal_R")
- return
-
-class MakeHumanFingerPanel(bpy.types.Panel):
- bl_label = "MakeHuman Fingers"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
-
- def draw(self, context):
- layout = self.layout
- pb = bpy.context.active_pose_bone
- layout.row().prop(pb, "MHRelax")
- layout.row().prop(pb, "MHCurl")
- layout.row().prop(pb, "MHCone")
- layout.row().prop(pb, "MHSpread")
- layout.row().prop(pb, "MHScrunch")
- layout.row().prop(pb, "MHLean")
- return
-
-
-def registerPanels():
- bpy.types.Object.FloatProperty(attr="PArmIK_L", name="L arm - IK", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PArmIK_R", name="R arm - IK", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PLegIK_L", name="L leg - IK", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PLegIK_R", name="R leg - IK", default = 0, min = 0.0, max = 1.0)
-
- bpy.types.Object.FloatProperty(attr="PHandLocal_L", name="L hand - Loc", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PHandLocal_R", name="R hand - Loc", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PFootLocal_L", name="L foot - Loc", default = 0, min = 0.0, max = 1.0)
- bpy.types.Object.FloatProperty(attr="PFootLocal_R", name="R foot - Loc", default = 0, min = 0.0, max = 1.0)
-
- bpy.types.PoseBone.FloatProperty(attr="MHCone", name="Cone", default = 0, min = -0.5, max = 1.0)
- bpy.types.PoseBone.FloatProperty(attr="MHRelax", name="Relax", default = 0, min = -0.5, max = 1.0)
- bpy.types.PoseBone.FloatProperty(attr="MHCurl", name="Curl", default = 0, min = -0.5, max = 1.0)
- bpy.types.PoseBone.FloatProperty(attr="MHLean", name="Lean", default = 0, min = -1.0, max = 1.0)
- bpy.types.PoseBone.FloatProperty(attr="MHScrunch", name="Scrunch", default = 0, min = -0.5, max = 1.0)
- bpy.types.PoseBone.FloatProperty(attr="MHSpread", name="Spread", default = 0, min = -0.5, max = 1.0)
-
- bpy.types.register(MakeHumanFKIKPanel)
- bpy.types.register(MakeHumanFingerPanel)
-
-def unregisterPanels():
- bpy.types.unregister(MakeHumanFKIKPanel)
- bpy.types.unregister(MakeHumanFingerPanel)
- '''
-
-
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_makehuman_mhx.bl_idname, text="MakeHuman (.mhx)...")
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-if __name__ == "__main__":
- register()
-
-#
-# Testing
-#
-"""
-theScale = 1.0
-
-toggle = T_Replace + T_Mesh + T_Armature + T_MHX + T_ArmIK + T_LegIK
-#rigLeg = T_Toes + T_GoboFoot
-#rigArm = T_ElbowPT + T_FingerCurl
-
-#readMhxFile("/home/thomas/makehuman/exports/foo-25.mhx")
-
-#toggle = T_Replace + T_Armature
-#readMhxFile("/home/thomas/makehuman/exports/foo-sintel-25.mhx")
-
-readMhxFile("C:/Documents and Settings/xxxxxxxxxxxxxxxxxxxx/Mina dokument/makehuman/exports/foo-25.mhx", 'Classic')
-#readMhxFile("/home/thomas/mhx5/test1.mhx")
-#readMhxFile("/home/thomas/myblends/gobo/gobo.mhx")
-#readMhxFile("/home/thomas/myblends/sintel/simple.mhx")
-"""
diff --git a/io_import_scene_unreal_psk.py b/io_import_scene_unreal_psk.py
deleted file mode 100644
index 0c2e878b..00000000
--- a/io_import_scene_unreal_psk.py
+++ /dev/null
@@ -1,602 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Import Unreal Skeleton Mesh(.psk)",
- "author": "Darknet",
- "version": (2,0),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Import ",
- "description": "Import Unreal Engine (.psk)",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
- "Scripts/File_I-O/Unreal_psk_psa",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21366&group_id=153&atid=469",
- "category": "Import/Export"}
-
-"""
-Version': '2.0' ported by Darknet
-
-Unreal Tournament PSK file to Blender mesh converter V1.0
-Author: D.M. Sturgeon (camg188 at the elYsium forum), ported by Darknet
-Imports a *psk file to a new mesh
-
--No UV Texutre
--No Weight
--No Armature Bones
--No Material ID
--Export Text Log From Current Location File (Bool )
-"""
-
-import bpy
-import mathutils
-import os
-import sys
-import string
-import math
-import re
-from string import *
-from struct import *
-from math import *
-
-#from bpy.props import *
-
-import mathutils
-
-#output log in to txt file
-DEBUGLOG = False
-
-scale = 1.0
-bonesize = 1.0
-md5_bones=[]
-
-def unpack_list(list_of_tuples):
- l = []
- for t in list_of_tuples:
- l.extend(t)
- return l
-"""
-class md5_bone:
- bone_index=0
- name=""
- bindpos=[]
- bindmat = mathutils.Quaternion()
- parent=""
- parent_index=0
- blenderbone=None
- roll=0
-
- def __init__(self):
- self.bone_index=0
- self.name=""
- self.bindpos=[0.0]*3
- self.bindmat=[None]*3 #is this how you initilize a 2d-array
- for i in range(3): self.bindmat[i] = [0.0]*3
- self.parent=""
- self.parent_index=0
- self.blenderbone=None
-
- def dump(self):
- print ("bone index: ", self.bone_index)
- print ("name: ", self.name)
- print ("bind position: ", self.bindpos)
- print ("bind translation matrix: ", self.bindmat)
- print ("parent: ", self.parent)
- print ("parent index: ", self.parent_index)
- print ("blenderbone: ", self.blenderbone)
-"""
-class md5_bone:
- bone_index=0
- name=""
- bindpos=[]
- bindmat=[]
- scale = []
- parent=""
- parent_index=0
- blenderbone=None
- roll=0
-
- def __init__(self):
- self.bone_index=0
- self.name=""
- self.bindpos=[0.0]*3
- self.scale=[0.0]*3
- self.bindmat=[None]*3 #is this how you initilize a 2d-array
- for i in range(3): self.bindmat[i] = [0.0]*3
- self.parent=""
- self.parent_index=0
- self.blenderbone=None
-
- def dump(self):
- print ("bone index: ", self.bone_index)
- print ("name: ", self.name)
- print ("bind position: ", self.bindpos)
- print ("bind translation matrix: ", self.bindmat)
- print ("parent: ", self.parent)
- print ("parent index: ", self.parent_index)
- print ("blenderbone: ", self.blenderbone)
-
-#http://www.blender.org/forum/viewtopic.php?t=13340&sid=8b17d5de07b17960021bbd72cac0495f
-def fixRollZ(b):
- v = (b.tail-b.head)/b.length
- b.roll -= math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[0]*v[0] + v[1]*v[2]*v[2]))
-def fixRoll(b):
- v = (b.tail-b.head)/b.length
- if v[2]*v[2] > .5:
- #align X-axis
- b.roll += math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[2]*v[2] + v[1]*v[0]*v[0]))
- else:
- #align Z-axis
- b.roll -= math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[0]*v[0] + v[1]*v[2]*v[2]))
-
-def pskimport(infile):
- global DEBUGLOG
- print ("--------------------------------------------------")
- print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------")
- print ("--------------------------------------------------")
- print ("Importing file: ", infile)
-
- md5_bones=[]
- pskfile = open(infile,'rb')
- if (DEBUGLOG):
- logpath = infile.replace(".psk", ".txt")
- print("logpath:",logpath)
- logf = open(logpath,'w')
-
- def printlog(strdata):
- if (DEBUGLOG):
- logf.write(strdata)
-
- objName = infile.split('\\')[-1].split('.')[0]
-
- me_ob = bpy.data.meshes.new(objName)
- print("objName:",objName)
- printlog(("New Mesh = " + me_ob.name + "\n"))
- #read general header
- indata = unpack('20s3i',pskfile.read(32))
- #not using the general header at this time
- #==================================================================================================
- # vertex point
- #==================================================================================================
- #read the PNTS0000 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog(( "Nbr of PNTS0000 records: " + str(recCount) + "\n"))
- counter = 0
- verts = []
- while counter < recCount:
- counter = counter + 1
- indata = unpack('3f',pskfile.read(12))
- #print(indata[0],indata[1],indata[2])
- verts.extend([(indata[0],indata[1],indata[2])])
- #Tmsh.vertices.append(NMesh.Vert(indata[0],indata[1],indata[2]))
-
- #==================================================================================================
- # UV
- #==================================================================================================
- #read the VTXW0000 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog( "Nbr of VTXW0000 records: " + str(recCount)+ "\n")
- counter = 0
- UVCoords = []
- #UVCoords record format = [index to PNTS, U coord, v coord]
- while counter < recCount:
- counter = counter + 1
- indata = unpack('hhffhh',pskfile.read(16))
- UVCoords.append([indata[0],indata[2],indata[3]])
- #print([indata[0],indata[2],indata[3]])
- #print([indata[1],indata[2],indata[3]])
-
- #==================================================================================================
- # Face
- #==================================================================================================
- #read the FACE0000 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog( "Nbr of FACE0000 records: "+ str(recCount) + "\n")
- #PSK FACE0000 fields: WdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp
- #associate MatIdx to an image, associate SmthGrp to a material
- SGlist = []
- counter = 0
- faces = []
- faceuv = []
- while counter < recCount:
- counter = counter + 1
- indata = unpack('hhhbbi',pskfile.read(12))
- #the psk values are: nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp
- #indata[0] = index of UVCoords
- #UVCoords[indata[0]]=[index to PNTS, U coord, v coord]
- #UVCoords[indata[0]][0] = index to PNTS
- PNTSA = UVCoords[indata[0]][0]
- PNTSB = UVCoords[indata[1]][0]
- PNTSC = UVCoords[indata[2]][0]
- #print(PNTSA,PNTSB,PNTSC) #face id vertex
- #faces.extend([0,1,2,0])
- faces.extend([PNTSA,PNTSB,PNTSC,0])
- uv = []
- u0 = UVCoords[indata[0]][1]
- v0 = UVCoords[indata[0]][2]
- uv.append([u0,v0])
- u1 = UVCoords[indata[1]][1]
- v1 = UVCoords[indata[1]][2]
- uv.append([u1,v1])
- u2 = UVCoords[indata[2]][1]
- v2 = UVCoords[indata[2]][2]
- uv.append([u2,v2])
- faceuv.append(uv)
- #print("UV: ",u0,v0)
- #update the uv var of the last item in the Tmsh.faces list
- # which is the face just added above
- ##Tmsh.faces[-1].uv = [(u0,v0),(u1,v1),(u2,v2)]
- #print("smooth:",indata[5])
- #collect a list of the smoothing groups
- if SGlist.count(indata[5]) == 0:
- SGlist.append(indata[5])
- print("smooth:",indata[5])
- #assign a material index to the face
- #Tmsh.faces[-1].materialIndex = SGlist.index(indata[5])
- printlog( "Using Materials to represent PSK Smoothing Groups...\n")
- #==========
- # skip something...
- #==========
-
- #==================================================================================================
- # Material
- #==================================================================================================
- ##
- #read the MATT0000 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog("Nbr of MATT0000 records: " + str(recCount) + "\n" )
- printlog(" - Not importing any material data now. PSKs are texture wrapped! \n")
- counter = 0
- while counter < recCount:
- counter = counter + 1
- indata = unpack('64s6i',pskfile.read(88))
- ##
-
- #==================================================================================================
- # Bones (Armature)
- #==================================================================================================
- #read the REFSKEL0 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog( "Nbr of REFSKEL0 records: " + str(recCount) + "\n")
- Bns = []
- bone = []
- nobone = 0
- #==================================================================================================
- # Bone Data
- #==================================================================================================
- counter = 0
- print ("---PRASE--BONES---")
- while counter < recCount:
- indata = unpack('64s3i11f',pskfile.read(120))
- #print( "DATA",str(indata))
- bone.append(indata)
-
- createbone = md5_bone()
- #temp_name = indata[0][:30]
- temp_name = indata[0]
-
- temp_name = bytes.decode(temp_name)
- temp_name = temp_name.lstrip(" ")
- temp_name = temp_name.rstrip(" ")
- temp_name = temp_name.strip()
- temp_name = temp_name.strip( bytes.decode(b'\x00'))
- print ("temp_name:", temp_name, "||")
- createbone.name = temp_name
- createbone.bone_index = counter
- createbone.parent_index = indata[3]
- createbone.bindpos[0] = indata[8]
- createbone.bindpos[1] = indata[9]
- createbone.bindpos[2] = indata[10]
- createbone.scale[0] = indata[12]
- createbone.scale[1] = indata[13]
- createbone.scale[2] = indata[14]
-
- #w,x,y,z
- if (counter == 0):#main parent
- print("no parent bone")
- createbone.bindmat = mathutils.Quaternion((indata[7],indata[4],indata[5],indata[6]))
- #createbone.bindmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6]))
- else:#parent
- print("parent bone")
- createbone.bindmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6]))
- #createbone.bindmat = mathutils.Quaternion((indata[7],indata[4],indata[5],indata[6]))
-
- md5_bones.append(createbone)
- counter = counter + 1
- bnstr = (str(indata[0]))
- Bns.append(bnstr)
-
- for pbone in md5_bones:
- pbone.parent = md5_bones[pbone.parent_index].name
-
- bonecount = 0
- for armbone in bone:
- temp_name = armbone[0][:30]
- #print ("BONE NAME: ",len(temp_name))
- temp_name=str((temp_name))
- #temp_name = temp_name[1]
- #print ("BONE NAME: ",temp_name)
- bonecount +=1
- print ("-------------------------")
- print ("----Creating--Armature---")
- print ("-------------------------")
-
- #================================================================================================
- #Check armature if exist if so create or update or remove all and addnew bone
- #================================================================================================
- #bpy.ops.object.mode_set(mode='OBJECT')
- meshname ="ArmObject"
- objectname = "armaturedata"
- bfound = False
- arm = None
- for obj in bpy.data.objects:
- if (obj.name == meshname):
- bfound = True
- arm = obj
- break
-
- if bfound == False:
- armdata = bpy.data.armatures.new(objectname)
- ob_new = bpy.data.objects.new(meshname, armdata)
- #ob_new = bpy.data.objects.new(meshname, 'ARMATURE')
- #ob_new.data = armdata
- bpy.context.scene.objects.link(ob_new)
- #bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
- ob_new.select = True
- #set current armature to edit the bone
- bpy.context.scene.objects.active = ob_new
- #set mode to able to edit the bone
- bpy.ops.object.mode_set(mode='EDIT')
- #newbone = ob_new.data.edit_bones.new('test')
- #newbone.tail.y = 1
- print("creating bone(s)")
- for bone in md5_bones:
- #print(dir(bone))
- newbone = ob_new.data.edit_bones.new(bone.name)
- #parent the bone
- parentbone = None
- print("bone name:",bone.name)
- #note bone location is set in the real space or global not local
- if bone.name != bone.parent:
-
- pos_x = bone.bindpos[0]
- pos_y = bone.bindpos[1]
- pos_z = bone.bindpos[2]
-
- #print( "LINKING:" , bone.parent ,"j")
- parentbone = ob_new.data.edit_bones[bone.parent]
- newbone.parent = parentbone
- rotmatrix = bone.bindmat.to_matrix().resize4x4().rotation_part()
-
- #parent_head = parentbone.head * parentbone.matrix.to_quat().inverse()
- #parent_tail = parentbone.tail * parentbone.matrix.to_quat().inverse()
- #location=Vector(pos_x,pos_y,pos_z)
- #set_position = (parent_tail - parent_head) + location
- #print("tmp head:",set_position)
-
- #pos_x = set_position.x
- #pos_y = set_position.y
- #pos_z = set_position.z
-
- newbone.head.x = parentbone.head.x + pos_x
- newbone.head.y = parentbone.head.y + pos_y
- newbone.head.z = parentbone.head.z + pos_z
- print("head:",newbone.head)
- newbone.tail.x = parentbone.head.x + (pos_x + bonesize * rotmatrix[1][0])
- newbone.tail.y = parentbone.head.y + (pos_y + bonesize * rotmatrix[1][1])
- newbone.tail.z = parentbone.head.z + (pos_z + bonesize * rotmatrix[1][2])
- else:
- rotmatrix = bone.bindmat.to_matrix().resize4x4().rotation_part()
- newbone.head.x = bone.bindpos[0]
- newbone.head.y = bone.bindpos[1]
- newbone.head.z = bone.bindpos[2]
- newbone.tail.x = bone.bindpos[0] + bonesize * rotmatrix[1][0]
- newbone.tail.y = bone.bindpos[1] + bonesize * rotmatrix[1][1]
- newbone.tail.z = bone.bindpos[2] + bonesize * rotmatrix[1][2]
- #print("no parent")
-
- bpy.context.scene.update()
-
- #==================================================================================================
- #END BONE DATA BUILD
- #==================================================================================================
- VtxCol = []
- for x in range(len(Bns)):
- #change the overall darkness of each material in a range between 0.1 and 0.9
- tmpVal = ((float(x)+1.0)/(len(Bns))*0.7)+0.1
- tmpVal = int(tmpVal * 256)
- tmpCol = [tmpVal,tmpVal,tmpVal,0]
- #Change the color of each material slightly
- if x % 3 == 0:
- if tmpCol[0] < 128: tmpCol[0] += 60
- else: tmpCol[0] -= 60
- if x % 3 == 1:
- if tmpCol[1] < 128: tmpCol[1] += 60
- else: tmpCol[1] -= 60
- if x % 3 == 2:
- if tmpCol[2] < 128: tmpCol[2] += 60
- else: tmpCol[2] -= 60
- #Add the material to the mesh
- VtxCol.append(tmpCol)
-
- #==================================================================================================
- # Bone Weight
- #==================================================================================================
- #read the RAWW0000 header
- indata = unpack('20s3i',pskfile.read(32))
- recCount = indata[3]
- printlog( "Nbr of RAWW0000 records: " + str(recCount) +"\n")
- #RAWW0000 fields: Weight|PntIdx|BoneIdx
- RWghts = []
- counter = 0
- while counter < recCount:
- counter = counter + 1
- indata = unpack('fii',pskfile.read(12))
- RWghts.append([indata[1],indata[2],indata[0]])
- #RWghts fields = PntIdx|BoneIdx|Weight
- RWghts.sort()
- printlog( "len(RWghts)=" + str(len(RWghts)) + "\n")
- #Tmsh.update()
-
- #set the Vertex Colors of the faces
- #face.v[n] = RWghts[0]
- #RWghts[1] = index of VtxCol
- """
- for x in range(len(Tmsh.faces)):
- for y in range(len(Tmsh.faces[x].v)):
- #find v in RWghts[n][0]
- findVal = Tmsh.faces[x].v[y].index
- n = 0
- while findVal != RWghts[n][0]:
- n = n + 1
- TmpCol = VtxCol[RWghts[n][1]]
- #check if a vertex has more than one influence
- if n != len(RWghts)-1:
- if RWghts[n][0] == RWghts[n+1][0]:
- #if there is more than one influence, use the one with the greater influence
- #for simplicity only 2 influences are checked, 2nd and 3rd influences are usually very small
- if RWghts[n][2] < RWghts[n+1][2]:
- TmpCol = VtxCol[RWghts[n+1][1]]
- Tmsh.faces[x].col.append(NMesh.Col(TmpCol[0],TmpCol[1],TmpCol[2],0))
- """
- if (DEBUGLOG):
- logf.close()
- #==================================================================================================
- #Building Mesh
- #==================================================================================================
- print("vertex:",len(verts),"faces:",len(faces))
- me_ob.vertices.add(len(verts))
- me_ob.faces.add(len(faces)//4)
-
- me_ob.vertices.foreach_set("co", unpack_list(verts))
-
- me_ob.faces.foreach_set("vertices_raw", faces)
- me_ob.faces.foreach_set("use_smooth", [False] * len(me_ob.faces))
- me_ob.update()
-
- #===================================================================================================
- #UV Setup
- #===================================================================================================
- texture = []
- texturename = "text1"
- #print(dir(bpy.data))
- if (len(faceuv) > 0):
- uvtex = me_ob.uv_textures.new() #add one uv texture
- for i, face in enumerate(me_ob.faces):
- blender_tface= uvtex.data[i] #face
- blender_tface.uv1 = faceuv[i][0] #uv = (0,0)
- blender_tface.uv2 = faceuv[i][1] #uv = (0,0)
- blender_tface.uv3 = faceuv[i][2] #uv = (0,0)
- texture.append(uvtex)
-
- #for tex in me_ob.uv_textures:
- #print("mesh tex:",dir(tex))
- #print((tex.name))
-
- #===================================================================================================
- #Material Setup
- #===================================================================================================
- materialname = "mat"
- materials = []
-
- matdata = bpy.data.materials.new(materialname)
- #color is 0 - 1 not in 0 - 255
- #matdata.mirror_color=(float(0.04),float(0.08),float(0.44))
- matdata.diffuse_color=(float(0.04),float(0.08),float(0.44))#blue color
- #print(dir(me_ob.uv_textures[0].data))
- texdata = None
- texdata = bpy.data.textures[len(bpy.data.textures)-1]
- if (texdata != None):
- #print(texdata.name)
- #print(dir(texdata))
- texdata.name = "texturelist1"
- matdata.active_texture = texdata
- materials.append(matdata)
- #matdata = bpy.data.materials.new(materialname)
- #materials.append(matdata)
- #= make sure the list isnt too big
- for material in materials:
- #add material to the mesh list of materials
- me_ob.materials.append(material)
- #===================================================================================================
- #
- #===================================================================================================
- obmesh = bpy.data.objects.new(objName,me_ob)
- #check if there is a material to set to
- if len(materials) > 0:
- obmesh.active_material = materials[0] #material setup tmp
-
- bpy.context.scene.objects.link(obmesh)
-
- bpy.context.scene.update()
-
- print ("PSK2Blender completed")
-#End of def pskimport#########################
-
-def getInputFilename(filename):
- checktype = filename.split('\\')[-1].split('.')[1]
- print ("------------",filename)
- if checktype.upper() != 'PSK':
- print (" Selected file = ",filename)
- raise (IOError, "The selected input file is not a *.psk file")
- pskimport(filename)
-
-from bpy.props import *
-
-class IMPORT_OT_psk(bpy.types.Operator):
- '''Load a skeleton mesh psk File'''
- bl_idname = "import_scene.psk"
- bl_label = "Import PSK"
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- filepath = StringProperty(name="File Path", description="Filepath used for importing the OBJ file", maxlen= 1024, default= "")
-
- def execute(self, context):
- getInputFilename(self.properties.filepath)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_psk.bl_idname, text="Skeleton Mesh (.psk)")
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-if __name__ == "__main__":
- register()
-
-#note this only read the data and will not be place in the scene
-#getInputFilename('C:\\blenderfiles\\BotA.psk')
-#getInputFilename('C:\\blenderfiles\\AA.PSK')
diff --git a/io_mesh_raw/__init__.py b/io_mesh_raw/__init__.py
deleted file mode 100644
index d52a5808..00000000
--- a/io_mesh_raw/__init__.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Raw mesh",
- "author": "Anthony D,Agostino (Scorpius), Aurel Wildfellner",
- "version": (0,2),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Import/Export > Raw faces ",
- "description": "Import Raw Faces (.raw format)",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File_I-O/Raw_Mesh_IO",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21733&group_id=153&atid=469",
- "category": "Import/Export"}
-
-import bpy
-
-
-try:
- init_data
-
- reload(import_raw)
- reload(export_raw)
-except:
- from io_mesh_raw import import_raw
- from io_mesh_raw import export_raw
-
-init_data = True
-
-def menu_import(self, context):
- from io_mesh_raw import import_raw
- self.layout.operator(import_raw.RawImporter.bl_idname, text="Raw Faces (.raw)").filepath = "*.raw"
-
-
-def menu_export(self, context):
- from io_mesh_raw import export_raw
- import os
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".raw"
- self.layout.operator(export_raw.RawExporter.bl_idname, text="Raw Faces (.raw)").filepath = default_path
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_import)
- bpy.types.INFO_MT_file_export.append(menu_export)
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_import)
- bpy.types.INFO_MT_file_export.remove(menu_export)
-
-if __name__ == "__main__":
- register()
diff --git a/io_mesh_raw/export_raw.py b/io_mesh_raw/export_raw.py
deleted file mode 100644
index 59f06f9d..00000000
--- a/io_mesh_raw/export_raw.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-__author__ = ["Aurel Wildfellner"]
-__version__ = '0.2'
-__bpydoc__ = """\
-This script exports a Mesh to a RAW triangle format file.
-
-The raw triangle format is very simple; it has no verts or faces lists.
-It's just a simple ascii text file with the vertices of each triangle
-listed on each line. In addition, also quads can be exported as a line
-of 12 values (this was the default before blender 2.5). Now default
-settings will triangulate the mesh.
-
-Usage:<br>
- Execute this script from the "File->Export" menu. You can select
-whether modifiers should be applied and if the mesh is triangulated.
-
-"""
-
-import bpy
-
-
-def faceToTriangles(face):
- triangles = []
- if (len(face) == 4): #quad
- triangles.append( [ face[0], face[1], face[2] ] )
- triangles.append( [ face[2], face[3], face[0] ] )
- else:
- triangles.append(face)
-
- return triangles
-
-
-def faceValues(face, mesh, matrix):
- fv = []
- for verti in face.vertices_raw:
- fv.append(matrix * mesh.vertices[verti].co)
- return fv
-
-
-def faceToLine(face):
- line = ""
- for v in face:
- line += str(v[0]) + " " + str(v[1]) + " " + str(v[2]) + " "
- return line[:-1] + "\n"
-
-
-def export_raw(filepath, applyMods, triangulate):
- faces = []
- for obj in bpy.context.selected_objects:
- if obj.type == 'MESH':
- matrix = obj.matrix_world
-
- if (applyMods):
- me = obj.create_mesh(bpy.context.scene, True, "PREVIEW")
- else:
- me = obj.data
-
- for face in me.faces:
- fv = faceValues(face, me, matrix)
- if triangulate:
- faces.extend(faceToTriangles(fv))
- else:
- faces.append(fv)
-
- # write the faces to a file
- file = open(filepath, "w")
- for face in faces:
- file.write(faceToLine(face))
- file.close()
-
-
-from bpy.props import *
-
-
-class RawExporter(bpy.types.Operator):
- '''Save Raw triangle mesh data'''
- bl_idname = "export_mesh.raw"
- bl_label = "Export RAW"
-
- filepath = StringProperty(name="File Path", description="Filepath used for exporting the RAW file", maxlen= 1024, default= "")
- check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
-
- apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
- triangulate = BoolProperty(name="Triangulate", description="Triangulate quads.", default=True)
-
- def execute(self, context):
- export_raw(self.properties.filepath, self.properties.apply_modifiers, self.properties.triangulate)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-# package manages registering
diff --git a/io_mesh_raw/import_raw.py b/io_mesh_raw/import_raw.py
deleted file mode 100644
index d6b70e0b..00000000
--- a/io_mesh_raw/import_raw.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-__author__ = ["Anthony D'Agostino (Scorpius)", "Aurel Wildfellner"]
-__version__ = '0.2'
-__bpydoc__ = """\
-This script imports Raw Triangle File format files to Blender.
-
-The raw triangle format is very simple; it has no verts or faces lists.
-It's just a simple ascii text file with the vertices of each triangle
-listed on each line. In addition, a line with 12 values will be
-imported as a quad. This may be in conflict with some other
-applications, which use a raw format, but this is how it was
-implemented back in blender 2.42.
-
-Usage:<br>
- Execute this script from the "File->Import" menu and choose a Raw file to
-open.
-
-Notes:<br>
- Generates the standard verts and faces lists, but without duplicate
-verts. Only *exact* duplicates are removed, there is no way to specify a
-tolerance.
-"""
-
-
-
-import bpy
-
-# move those to a utility modul
-from io_utils import unpack_face_list, unpack_list # TODO, make generic
-
-
-def readMesh(filename, objName):
- file = open(filename, "rb")
-
- def line_to_face(line):
- # Each triplet is an xyz float
- line_split = []
- try:
- line_split = list(map(float, line.split()))
- except:
- return None
-
- if len(line_split) == 9: # Tri
- f1, f2, f3, f4, f5, f6, f7, f8, f9 = line_split
- return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)]
- elif len(line_split) == 12: # Quad
- f1, f2, f3, f4, f5, f6, f7, f8, f9, A, B, C = line_split
- return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9), (A, B, C)]
- else:
- return None
-
-
- faces = []
- for line in file.readlines():
- face = line_to_face(line)
- if face:
- faces.append(face)
-
- file.close()
-
- # Generate verts and faces lists, without duplicates
- verts = []
- coords = {}
- index_tot = 0
-
- for f in faces:
- for i, v in enumerate(f):
- index = coords.get(v)
-
- if index is None:
- index = coords[v] = index_tot
- index_tot += 1
- verts.append(v)
-
- fi[i] = index
-
- mesh = bpy.data.meshes.new(objName)
- mesh.vertices.add(len(verts))
- mesh.faces.add(len(faces))
- mesh.vertices.foreach_set("co", unpack_list(verts))
- mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces))
-
- return mesh
-
-
-def addMeshObj(mesh, objName):
- scn = bpy.context.scene
-
- for o in scn.objects:
- o.select = False
-
- mesh.update()
- nobj = bpy.data.objects.new(objName, mesh)
- scn.objects.link(nobj)
- nobj.select = True
-
- if scn.objects.active == None or scn.objects.active.mode == 'OBJECT':
- scn.objects.active = nobj
-
-
-from bpy.props import *
-
-class RawImporter(bpy.types.Operator):
- '''Load Raw triangle mesh data'''
- bl_idname = "import_mesh.raw"
- bl_label = "Import RAW"
-
- filepath = StringProperty(name="File Path", description="Filepath used for importing the RAW file", maxlen=1024, default="")
- filename = StringProperty(name="File Name", description="Name of the file.")
-
- def execute(self, context):
-
- #convert the filename to an object name
- objName = bpy.path.display_name(self.properties.filename)
-
- mesh = readMesh(self.properties.filepath, objName)
- addMeshObj(mesh, objName)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-# package manages registering
diff --git a/io_mesh_stl/__init__.py b/io_mesh_stl/__init__.py
deleted file mode 100644
index 96e8fc32..00000000
--- a/io_mesh_stl/__init__.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "STL format",
- "author": "Guillaume Bouchard (Guillaum)",
- "version": (1,),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "File > Import/Export > Stl",
- "description": "Import/Export STL files",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/File I-O/STL",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"
- "func=detail&aid=22837&group_id=153&atid=469",
- "category": "Import/Export"}
-
-# @todo write the wiki page
-
-"""
-Import/Export STL files (binary or ascii)
-
-- Import automatically remove the doubles.
-- Export can export with/without modifiers applied
-
-Issues:
-
-Import:
- - Does not handle the normal of the triangles
- - Does not handle endien
-"""
-
-import itertools
-import os
-
-import bpy
-from bpy.props import *
-
-
-try:
- init_data
-
- reload(stl_utils)
- reload(blender_utils)
-except:
- from io_mesh_stl import stl_utils
- from io_mesh_stl import blender_utils
-
-init_data = True
-
-
-class StlImporter(bpy.types.Operator):
- '''
- Load STL triangle mesh data
- '''
- bl_idname = "import_mesh.stl"
- bl_label = "Import STL"
-
- files = CollectionProperty(name="File Path",
- description="File path used for importing "
- "the STL file",
- type=bpy.types.OperatorFileListElement)
-
- directory = StringProperty()
-
- def execute(self, context):
- paths = (os.path.join(self.properties.directory, name.name) for name in self.properties.files)
-
- for path in paths:
- objName = bpy.path.display_name(path.split("\\")[-1].split("/")[-1])
- tris, pts = stl_utils.read_stl(path)
-
- blender_utils.create_and_link_mesh(objName, tris, pts)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
-
- return {'RUNNING_MODAL'}
-
-
-class StlExporter(bpy.types.Operator):
- '''
- Save STL triangle mesh data from the active object
- '''
- bl_idname = "export_mesh.stl"
- bl_label = "Export STL"
-
- filepath = StringProperty(name="File Path",
- description="File path used for exporting "
- "the active object to STL file",
- maxlen=1024,
- default="")
- check_existing = BoolProperty(name="Check Existing",
- description="Check and warn on "
- "overwriting existing files",
- default=True,
- options={'HIDDEN'})
-
- ascii = BoolProperty(name="Ascii",
- description="Save the file in ASCII file format",
- default=False)
- apply_modifiers = BoolProperty(name="Apply Modifiers",
- description="Apply the modifiers "
- "before saving",
- default=True)
-
- def execute(self, context):
- faces = itertools.chain.from_iterable(
- blender_utils.faces_from_mesh(ob, self.properties.apply_modifiers)
- for ob in context.selected_objects)
-
- stl_utils.write_stl(self.properties.filepath, faces, self.properties.ascii)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-def menu_import(self, context):
- self.layout.operator(StlImporter.bl_idname,
- text="Stl (.stl)").filepath = "*.stl"
-
-
-def menu_export(self, context):
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".stl"
- self.layout.operator(StlExporter.bl_idname,
- text="Stl (.stl)").filepath = default_path
-
-
-def register():
- bpy.types.INFO_MT_file_import.append(menu_import)
- bpy.types.INFO_MT_file_export.append(menu_export)
-
-
-def unregister():
- bpy.types.INFO_MT_file_import.remove(menu_import)
- bpy.types.INFO_MT_file_export.remove(menu_export)
-
-
-if __name__ == "__main__":
- register()
diff --git a/io_mesh_stl/blender_utils.py b/io_mesh_stl/blender_utils.py
deleted file mode 100644
index 76dc86b9..00000000
--- a/io_mesh_stl/blender_utils.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import bpy
-
-
-def create_and_link_mesh(name, faces, points):
- '''
- Create a blender mesh and object called name from a list of
- *points* and *faces* and link it in the current scene.
- '''
-
- mesh = bpy.data.meshes.new(name)
- mesh.from_pydata(points, [], faces)
-
- ob = bpy.data.objects.new(name, mesh)
- bpy.context.scene.objects.link(ob)
-
- # update mesh to allow proper display
- mesh.update()
-
-
-def faces_from_mesh(ob, apply_modifier=False, triangulate=True):
- '''
- From an object, return a generator over a list of faces.
-
- Each faces is a list of his vertexes. Each vertex is a tuple of
- his coordinate.
-
- apply_modifier
- Apply the preview modifier to the returned liste
-
- triangulate
- Split the quad into two triangles
- '''
-
- # get the modifiers
- try:
- mesh = ob.create_mesh(bpy.context.scene,
- apply_modifier, "PREVIEW")
- except SystemError:
- return ()
-
- def iter_face_index():
- '''
- From a list of faces, return the face triangulated if needed.
- '''
- for face in mesh.faces:
- if triangulate and len(face.vertices) == 4:
- yield face.vertices[:3]
- yield face.vertices[2:] + [face.vertices[0]]
- else:
- yield list(face.vertices)
-
- return ([tuple(ob.matrix_world * mesh.vertices[index].co)
- for index in indexes] for indexes in iter_face_index())
diff --git a/io_mesh_stl/stl_utils.py b/io_mesh_stl/stl_utils.py
deleted file mode 100644
index 92723e98..00000000
--- a/io_mesh_stl/stl_utils.py
+++ /dev/null
@@ -1,228 +0,0 @@
-'''
-Import and export STL files
-
-Used as a blender script, it load all the stl files in the scene:
-
-blender -P stl_utils.py -- file1.stl file2.stl file3.stl ...
-'''
-
-import struct
-import mmap
-import contextlib
-import itertools
-
-# TODO: endien
-
-
-@contextlib.contextmanager
-def mmap_file(filename):
- '''
- Context manager over the data of an mmap'ed file (Read ONLY).
-
-
- Example:
-
- with mmap_file(filename) as m:
- m.read()
- print m[10:50]
- '''
- with open(filename, 'rb') as file:
- # check http://bugs.python.org/issue8046 to have mmap context
- # manager fixed in python
- map = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
- yield map
- map.close()
-
-
-class ListDict(dict):
- '''
- Set struct with order.
-
- You can:
- - insert data into without doubles
- - get the list of data in insertion order with self.list
-
- Like collections.OrderedDict, but quicker, can be replaced if
- ODict is optimised.
- '''
-
- def __init__(self):
- dict.__init__(self)
- self.list = []
- self._len = 0
-
- def add(self, item):
- '''
- Add a value to the Set, return its position in it.
- '''
- value = self.setdefault(item, self._len)
- if value == self._len:
- self.list.append(item)
- self._len += 1
-
- return value
-
-
-def _binary_read(data):
- # an stl binary file is
- # - 80 bytes of description
- # - 2 bytes of size (unsigned int)
- # - size triangles :
- #
- # - 12 bytes of normal
- # - 9 * 4 bytes of coordinate (3*3 floats)
- # - 2 bytes of garbage (usually 0)
-
- # OFFSET for the first byte of coordinate (headers + first normal bytes)
- # STRIDE between each triangle (first normal + coordinates + garbage)
- OFFSET, STRIDE = 84 + 12, 12 * 4 + 2
-
- # read header size, ignore description
- size = struct.unpack_from('<I', data, 80)[0]
- unpack = struct.Struct('<9f').unpack_from
-
- for i in range(size):
- # read the points coordinates of each triangle
- pt = unpack(data, OFFSET + STRIDE * i)
- yield pt[:3], pt[3:6], pt[6:]
-
-
-def _ascii_read(data):
- # an stl ascii file is like
- # HEADER: solid some name
- # for each face:
- #
- # facet normal x y z
- # outerloop
- # vertex x y z
- # vertex x y z
- # vertex x y z
- # endloop
- # endfacet
-
- # strip header
- data.readline()
-
- while True:
- # strip facet normal // or end
- data.readline()
-
- # strip outer loup, in case of ending, break the loop
- if not data.readline():
- break
-
- yield [tuple(map(float, data.readline().split()[1:]))
- for _ in range(3)]
-
- # strip facet normalend and outerloop end
- data.readline()
- data.readline()
-
-
-def _binary_write(filename, faces):
- with open(filename, 'wb') as data:
- # header
- # we write padding at header begginning to avoid to
- # call len(list(faces)) which may be expensive
- data.write(struct.calcsize('<80sI') * b'\0')
-
- # 3 vertex == 9f
- pack = struct.Struct('<9f').pack
- # pad is to remove normal, we do use them
- pad = b'\0' * struct.calcsize('<3f')
-
- nb = 0
- for verts in faces:
- # write pad as normal + vertexes + pad as attributes
- data.write(pad + pack(*itertools.chain.from_iterable(verts)))
- data.write(b'\0\0')
- nb += 1
-
- # header, with correct value now
- data.seek(0)
- data.write(struct.pack('<80sI', b"Exported from blender", nb))
-
-
-def _ascii_write(filename, faces):
- with open(filename, 'w') as data:
- data.write('solid Exported from blender\n')
-
- for face in faces:
- data.write('''facet normal 0 0 0\nouter loop\n''')
- for vert in face:
- data.write('vertex %f %f %f\n' % vert)
- data.write('endloop\nendfacet\n')
-
- data.write('endsolid Exported from blender\n')
-
-
-def write_stl(filename, faces, ascii=False):
- '''
- Write a stl file from faces,
-
- filename
- output filename
-
- faces
- iterable of tuple of 3 vertex, vertex is tuple of 3 coordinates as float
-
- ascii
- save the file in ascii format (very huge)
- '''
- (_ascii_write if ascii else _binary_write)(filename, faces)
-
-
-def read_stl(filename):
- '''
- Return the triangles and points of an stl binary file.
-
- Please note that this process can take lot of time if the file is
- huge (~1m30 for a 1 Go stl file on an quad core i7).
-
- - returns a tuple(triangles, points).
-
- triangles
- A list of triangles, each triangle as a tuple of 3 index of
- point in *points*.
-
- points
- An indexed list of points, each point is a tuple of 3 float
- (xyz).
-
- Example of use:
-
- >>> tris, pts = read_stl(filename, lambda x:)
- >>> pts = list(pts)
- >>>
- >>> # print the coordinate of the triangle n
- >>> print([pts[i] for i in tris[n]])
- '''
-
- tris, pts = [], ListDict()
-
- with mmap_file(filename) as data:
- # check for ascii or binary
- gen = _ascii_read if data.read(5) == b'solid' else _binary_read
-
- for pt in gen(data):
- # Add the triangle and the point.
- # If the point is allready in the list of points, the
- # index returned by pts.add() will be the one from the
- # first equal point inserted.
- tris.append([pts.add(p) for p in pt])
-
- return tris, pts.list
-
-
-if __name__ == '__main__':
- import sys
- import bpy
- from io_mesh_stl import blender_utils
-
- filenames = sys.argv[sys.argv.index('--') + 1:]
-
- for filename in filenames:
- objName = bpy.path.display_name(filename)
- tris, pts = read_stl(filename)
-
- blender_utils.create_and_link_mesh(objName, tris, pts)
diff --git a/mesh_relax.py b/mesh_relax.py
deleted file mode 100644
index 1a971a93..00000000
--- a/mesh_relax.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# mesh_relax.py Copyright (C) 2010, Fabian Fricke
-#
-# Relaxes selected vertices while retaining the shape as much as possible
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Relax",
- "author": "Fabian Fricke",
- "version": (1,1),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "View3D > Specials > Relax ",
- "description": "Relax the selected verts while retaining the shape",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Modeling/Relax",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21421&group_id=153&atid=469",
- "category": "Mesh"}
-
-"""
-Usage:
-
-Launch from "W-menu" or from "Mesh -> Vertices -> Relax"
-
-
-Additional links:
- Author Site: http://frigi.designdevil.de
- e-mail: frigi.f {at} gmail {dot} com
-"""
-
-
-import bpy
-from bpy.props import IntProperty
-
-def relax_mesh(context):
-
- # deselect everything that's not related
- for obj in context.selected_objects:
- obj.select = False
-
- # get active object
- obj = context.active_object
-
- # duplicate the object so it can be used for the shrinkwrap modifier
- obj.select = True # make sure the object is selected!
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.duplicate()
- target = context.active_object
-
- # remove all other modifiers from the target
- for m in range(0, len(target.modifiers)):
- target.modifiers.remove(target.modifiers[0])
-
- context.scene.objects.active = obj
-
- sw = obj.modifiers.new(type='SHRINKWRAP', name='relax_target')
- sw.target = target
-
- # run smooth operator to relax the mesh
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.vertices_smooth()
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # apply the modifier
- bpy.ops.object.modifier_apply(modifier='relax_target')
-
- # delete the target object
- obj.select = False
- target.select = True
- bpy.ops.object.delete()
-
- # go back to initial state
- obj.select = True
- bpy.ops.object.mode_set(mode='EDIT')
-
-class Relax(bpy.types.Operator):
- '''Relaxes selected vertices while retaining the shape as much as possible'''
- bl_idname = 'mesh.relax'
- bl_label = 'Relax'
- bl_options = {'REGISTER', 'UNDO'}
-
- iterations = IntProperty(name="Relax iterations",
- default=1, min=0, max=100, soft_min=0, soft_max=10)
-
- @classmethod
- def poll(cls, context):
- obj = context.active_object
- return (obj and obj.type == 'MESH')
-
- def execute(self, context):
- for i in range(0,self.properties.iterations):
- relax_mesh(context)
- return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(Relax.bl_idname, text="Relax")
-
-
-def register():
- bpy.types.VIEW3D_MT_edit_mesh_specials.append(menu_func)
- bpy.types.VIEW3D_MT_edit_mesh_vertices.append(menu_func)
-
-def unregister():
- bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
- bpy.types.VIEW3D_MT_edit_mesh_vertices.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/mesh_surface_sketch.py b/mesh_surface_sketch.py
deleted file mode 100644
index 41bc79c7..00000000
--- a/mesh_surface_sketch.py
+++ /dev/null
@@ -1,819 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Surface Sketch",
- "author": "Eclectiel",
- "version": (0,8),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "View3D > EditMode > ToolShelf",
- "description": "Draw meshes and re-topologies with Grease Pencil",
- "warning": "Beta",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Mesh/Surface_Sketch",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22062&group_id=153&atid=469",
- "category": "Mesh"}
-
-
-import bpy
-import math
-
-from math import *
-
-
-class VIEW3D_PT_tools_SURF_SKETCH(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
-
- bl_context = "mesh_edit"
- bl_label = "Surface Sketching"
-
- @classmethod
- def poll(cls, context):
- return context.active_object
-
- def draw(self, context):
- layout = self.layout
-
- scn = context.scene
- ob = context.object
-
- col = layout.column(align=True)
- row = layout.row()
- row.separator()
- col.operator("GPENCIL_OT_SURFSK_add_surface", text="Add Surface")
- col.prop(scn, "SURFSK_edges_U")
- col.prop(scn, "SURFSK_edges_V")
- row.separator()
- col.prop(scn, "SURFSK_keep_strokes")
- col.separator()
- row.separator()
- col.operator("GPENCIL_OT_SURFSK_strokes_to_curves", text="Strokes to curves")
-
-
-
-class GPENCIL_OT_SURFSK_add_surface(bpy.types.Operator):
- bl_idname = "GPENCIL_OT_SURFSK_add_surface"
- bl_label = "Surface generation from grease pencil strokes"
- bl_description = "Surface generation from grease pencil strokes"
-
-
- #### Get an ordered list of a chain of vertices.
- def get_ordered_verts(self, ob, all_selected_edges_idx, all_selected_verts_idx, first_vert_idx, middle_vertex_idx):
- # Order selected vertexes.
- verts_ordered = []
- verts_ordered.append(self.main_object.data.vertices[first_vert_idx])
- prev_v = first_vert_idx
- prev_ed = None
- finish_while = False
- while True:
- edges_non_matched = 0
- for i in all_selected_edges_idx:
- if ob.data.edges[i] != prev_ed and ob.data.edges[i].vertices[0] == prev_v and ob.data.edges[i].vertices[1] in all_selected_verts_idx:
- verts_ordered.append(self.main_object.data.vertices[ob.data.edges[i].vertices[1]])
- prev_v = ob.data.edges[i].vertices[1]
- prev_ed = ob.data.edges[i]
- elif ob.data.edges[i] != prev_ed and ob.data.edges[i].vertices[1] == prev_v and ob.data.edges[i].vertices[0] in all_selected_verts_idx:
- verts_ordered.append(self.main_object.data.vertices[ob.data.edges[i].vertices[0]])
- prev_v = ob.data.edges[i].vertices[0]
- prev_ed = ob.data.edges[i]
- else:
- edges_non_matched += 1
-
- if edges_non_matched == len(all_selected_edges_idx):
- finish_while = True
-
- if finish_while:
- break
-
- if middle_vertex_idx != None:
- verts_ordered.append(self.main_object.data.vertices[middle_vertex_idx])
- verts_ordered.reverse()
-
- return verts_ordered
-
-
- #### Calculates length of a chain of points.
- def get_chain_length(self, verts_ordered):
- edges_lengths = []
- edges_lengths_sum = 0
- for i in range(0, len(verts_ordered)):
- if i == 0:
- prev_v = verts_ordered[i]
- else:
- v = verts_ordered[i]
-
- v_difs = [prev_v.co[0] - v.co[0], prev_v.co[1] - v.co[1], prev_v.co[2] - v.co[2]]
- edge_length = abs(sqrt(v_difs[0] * v_difs[0] + v_difs[1] * v_difs[1] + v_difs[2] * v_difs[2]))
-
- edges_lengths.append(edge_length)
- edges_lengths_sum += edge_length
-
- prev_v = v
-
- return edges_lengths, edges_lengths_sum
-
-
- #### Calculates the proportion of the edges of a chain of edges, relative to the full chain length.
- def get_edges_proportions(self, edges_lengths, edges_lengths_sum, use_boundaries, fixed_edges_num):
- edges_proportions = []
- if use_boundaries:
- verts_count = 1
- for l in edges_lengths:
- edges_proportions.append(l / edges_lengths_sum)
- verts_count += 1
- else:
- verts_count = 1
- for n in range(0, fixed_edges_num):
- edges_proportions.append(1 / fixed_edges_num)
- verts_count += 1
-
- return edges_proportions
-
-
- #### Calculates the angle between two pairs of points in space.
- def orientation_difference(self, points_A_co, points_B_co): # each parameter should be a list with two elements, and each element should be a x,y,z coordinate.
- vec_A = points_A_co[0] - points_A_co[1]
- vec_B = points_B_co[0] - points_B_co[1]
-
- angle = vec_A.angle(vec_B)
-
- if angle > 0.5 * math.pi:
- angle = abs(angle - math.pi)
-
- return angle
-
-
- #### Calculate distance between two points
- def pts_distance(self, p1_co, p2_co):
- p_difs = [p1_co[0] - p2_co[0], p1_co[1] - p2_co[1], p1_co[2] - p2_co[2]]
- distance = abs(sqrt(p_difs[0] * p_difs[0] + p_difs[1] * p_difs[1] + p_difs[2] * p_difs[2]))
-
- return distance
-
-
- def execute(self, context):
- #### Selected edges.
- all_selected_edges_idx = []
- all_selected_verts = []
- all_verts_idx = []
- for ed in self.main_object.data.edges:
- if ed.select:
- all_selected_edges_idx.append(ed.index)
-
- # Selected vertexes.
- if not ed.vertices[0] in all_selected_verts:
- all_selected_verts.append(self.main_object.data.vertices[ed.vertices[0]])
- if not ed.vertices[1] in all_selected_verts:
- all_selected_verts.append(self.main_object.data.vertices[ed.vertices[1]])
-
- # All verts (both from each edge) to determine later which are at the tips (those not repeated twice).
- all_verts_idx.append(ed.vertices[0])
- all_verts_idx.append(ed.vertices[1])
-
-
- #### Identify the tips and "middle-vertex" that separates U from V, if there is one.
- all_chains_tips_idx = []
- for v_idx in all_verts_idx:
- if all_verts_idx.count(v_idx) < 2:
- all_chains_tips_idx.append(v_idx)
-
- edges_connected_to_tips = []
- for ed in self.main_object.data.edges:
- if (ed.vertices[0] in all_chains_tips_idx or ed.vertices[1] in all_chains_tips_idx) and not (ed.vertices[0] in all_verts_idx and ed.vertices[1] in all_verts_idx):
- edges_connected_to_tips.append(ed)
-
- middle_vertex_idx = None
- tips_to_discard_idx = []
- for ed_tips in edges_connected_to_tips:
- for ed_tips_b in edges_connected_to_tips:
- if (ed_tips != ed_tips_b):
- if ed_tips.vertices[0] in all_verts_idx and (((ed_tips.vertices[1] == ed_tips_b.vertices[0]) or ed_tips.vertices[1] == ed_tips_b.vertices[1])):
- middle_vertex_idx = ed_tips.vertices[1]
- tips_to_discard_idx.append(ed_tips.vertices[0])
- elif ed_tips.vertices[1] in all_verts_idx and (((ed_tips.vertices[0] == ed_tips_b.vertices[0]) or ed_tips.vertices[0] == ed_tips_b.vertices[1])):
- middle_vertex_idx = ed_tips.vertices[0]
- tips_to_discard_idx.append(ed_tips.vertices[1])
-
-
- #### List with pairs of verts that belong to the tips of each selection chain (row).
- verts_tips_same_chain_idx = []
- if len(all_chains_tips_idx) >= 2:
- checked_v = []
- for i in range(0, len(all_chains_tips_idx)):
- if all_chains_tips_idx[i] not in checked_v:
- v_chain = self.get_ordered_verts(self.main_object, all_selected_edges_idx, all_verts_idx, all_chains_tips_idx[i], middle_vertex_idx)
-
- verts_tips_same_chain_idx.append([v_chain[0].index, v_chain[len(v_chain) - 1].index])
-
- checked_v.append(v_chain[0].index)
- checked_v.append(v_chain[len(v_chain) - 1].index)
-
-
- #### Selection tips (vertices)
- verts_tips_parsed_idx = []
- if len(all_chains_tips_idx) >= 2:
- for spec_v_idx in all_chains_tips_idx:
- if (spec_v_idx not in tips_to_discard_idx):
- verts_tips_parsed_idx.append(spec_v_idx)
-
-
- #### Identify the type of selection made by the user.
- if middle_vertex_idx != None:
- if len(all_chains_tips_idx) == 4: # If there are 4 tips (two selection chains)
- selection_type = "TWO_CONNECTED"
- else:
- # The type of the selection was not identified, so the script stops.
- return
- else:
- if len(all_chains_tips_idx) == 2: # If there are 2 tips (one selection chain)
- selection_type = "SINGLE"
- elif len(all_chains_tips_idx) == 4: # If there are 4 tips (two selection chains)
- selection_type = "TWO_NOT_CONNECTED"
- elif len(all_chains_tips_idx) == 0:
- selection_type = "NO_SELECTION"
- else:
- # The type of the selection was not identified, so the script stops.
- return
-
-
- #### Check if it will be used grease pencil strokes or curves.
- selected_objs = bpy.context.selected_objects
- if len(selected_objs) > 1:
- for ob in selected_objs:
- if ob != bpy.context.scene.objects.active:
- ob_gp_strokes = ob
- using_external_curves = True
-
- bpy.ops.object.editmode_toggle()
- else:
- #### Convert grease pencil strokes to curve.
- bpy.ops.gpencil.convert(type='CURVE')
- ob_gp_strokes = bpy.context.object
- using_external_curves = False
-
- bpy.ops.object.editmode_toggle()
-
- ob_gp_strokes.name = "SURFSK_temp_strokes"
-
- bpy.ops.object.select_name(name = ob_gp_strokes.name)
- bpy.context.scene.objects.active = bpy.context.scene.objects[ob_gp_strokes.name]
-
-
- #### If "Keep strokes" is active make a duplicate of the original strokes, which will be intact
- if bpy.context.scene.SURFSK_keep_strokes:
- bpy.ops.object.duplicate_move()
- bpy.context.object.name = "SURFSK_used_strokes"
- bpy.ops.object.editmode_toggle()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.object.editmode_toggle()
-
- bpy.ops.object.select_name(name = ob_gp_strokes.name)
- bpy.context.scene.objects.active = bpy.context.scene.objects[ob_gp_strokes.name]
-
-
- #### Enter editmode for the new curve (converted from grease pencil strokes).
- bpy.ops.object.editmode_toggle()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.object.editmode_toggle()
-
-
- selection_U_exists = False
- selection_U2_exists = False
- selection_V_exists = False
- selection_V2_exists = False
- #### Define what vertexes are at the tips of each selection and are not the middle-vertex.
- if selection_type == "TWO_CONNECTED":
- selection_U_exists = True
- selection_V_exists = True
-
- # Determine which selection is Selection-U and which is Selection-V.
- points_A = []
- points_B = []
- points_first_stroke_tips = []
-
- points_A.append(self.main_object.data.vertices[verts_tips_parsed_idx[0]].co)
- points_A.append(self.main_object.data.vertices[middle_vertex_idx].co)
-
- points_B.append(self.main_object.data.vertices[verts_tips_parsed_idx[1]].co)
- points_B.append(self.main_object.data.vertices[middle_vertex_idx].co)
-
- points_first_stroke_tips.append(ob_gp_strokes.data.splines[0].bezier_points[0].co)
- points_first_stroke_tips.append(ob_gp_strokes.data.splines[0].bezier_points[len(ob_gp_strokes.data.splines[0].bezier_points) - 1].co)
-
- angle_A = self.orientation_difference(points_A, points_first_stroke_tips)
- angle_B = self.orientation_difference(points_B, points_first_stroke_tips)
-
- if angle_A < angle_B:
- first_vert_U_idx = verts_tips_parsed_idx[0]
- first_vert_V_idx = verts_tips_parsed_idx[1]
- else:
- first_vert_U_idx = verts_tips_parsed_idx[1]
- first_vert_V_idx = verts_tips_parsed_idx[0]
-
- elif selection_type == "SINGLE" or selection_type == "TWO_NOT_CONNECTED":
- first_sketched_point_first_stroke_co = ob_gp_strokes.data.splines[0].bezier_points[0].co
- last_sketched_point_first_stroke_co = ob_gp_strokes.data.splines[0].bezier_points[len(ob_gp_strokes.data.splines[0].bezier_points) - 1].co
-
- first_sketched_point_last_stroke_co = ob_gp_strokes.data.splines[len(ob_gp_strokes.data.splines) - 1].bezier_points[0].co
-
- # The tip of the selected vertices nearest to the first point of the first sketched stroke.
- prev_dist = 999999999999
- for i in range(0, len(verts_tips_same_chain_idx)):
- for v_idx in range(0, len(verts_tips_same_chain_idx[i])):
- dist = self.pts_distance(first_sketched_point_first_stroke_co, self.main_object.data.vertices[verts_tips_same_chain_idx[i][v_idx]].co)
- if dist < prev_dist:
- prev_dist = dist
-
- nearest_tip_first_st_first_pt_idx = i
-
- nearest_tip_first_pair_first_pt_idx = v_idx
-
- # Shortest distance to the first point of the first stroke
- shortest_distance_to_first_stroke = dist
-
-
- # The tip of the selected vertices nearest to the last point of the first sketched stroke.
- prev_dist = 999999999999
- for i in range(0, len(verts_tips_same_chain_idx)):
- for v_idx in range(0, len(verts_tips_same_chain_idx[i])):
- dist = self.pts_distance(last_sketched_point_first_stroke_co, self.main_object.data.vertices[verts_tips_same_chain_idx[i][v_idx]].co)
- if dist < prev_dist:
- prev_dist = dist
-
- nearest_tip_first_st_last_pt_pair_idx = i
- nearest_tip_first_st_last_pt_point_idx = v_idx
-
-
- # The tip of the selected vertices nearest to the first point of the last sketched stroke.
- prev_dist = 999999999999
- for i in range(0, len(verts_tips_same_chain_idx)):
- for v_idx in range(0, len(verts_tips_same_chain_idx[i])):
- dist = self.pts_distance(first_sketched_point_last_stroke_co, self.main_object.data.vertices[verts_tips_same_chain_idx[i][v_idx]].co)
- if dist < prev_dist:
- prev_dist = dist
-
- nearest_tip_last_st_first_pt_pair_idx = i
- nearest_tip_last_st_first_pt_point_idx = v_idx
-
-
- points_tips = []
- points_first_stroke_tips = []
-
- # Determine if the single selection will be treated as U or as V.
- edges_sum = 0
- for i in all_selected_edges_idx:
- edges_sum += self.pts_distance(self.main_object.data.vertices[self.main_object.data.edges[i].vertices[0]].co, self.main_object.data.vertices[self.main_object.data.edges[i].vertices[1]].co)
-
- average_edge_length = edges_sum / len(all_selected_edges_idx)
-
-
-
- # If the beginning of the first stroke is near enough to interpret things as an "extrude along strokes" instead of "extrude through strokes"
- if shortest_distance_to_first_stroke < average_edge_length / 3:
- selection_U_exists = False
- selection_V_exists = True
-
- first_vert_V_idx = verts_tips_same_chain_idx[nearest_tip_first_st_first_pt_idx][nearest_tip_first_pair_first_pt_idx]
-
- if selection_type == "TWO_NOT_CONNECTED":
- selection_V2_exists = True
-
- first_vert_V2_idx = verts_tips_same_chain_idx[nearest_tip_first_st_last_pt_pair_idx][nearest_tip_first_st_last_pt_point_idx]
-
- else:
- selection_V2_exists = False
-
- else:
- selection_U_exists = True
- selection_V_exists = False
-
- points_tips.append(self.main_object.data.vertices[verts_tips_same_chain_idx[nearest_tip_first_st_first_pt_idx][0]].co)
- points_tips.append(self.main_object.data.vertices[verts_tips_same_chain_idx[nearest_tip_first_st_first_pt_idx][1]].co)
-
- points_first_stroke_tips.append(ob_gp_strokes.data.splines[0].bezier_points[0].co)
- points_first_stroke_tips.append(ob_gp_strokes.data.splines[0].bezier_points[len(ob_gp_strokes.data.splines[0].bezier_points) - 1].co)
-
- vec_A = points_tips[0] - points_tips[1]
- vec_B = points_first_stroke_tips[0] - points_first_stroke_tips[1]
-
- # Compare the direction of the selection and the first grease pencil stroke to determine which is the "first" vertex of the selection.
- if vec_A.dot(vec_B) < 0:
- first_vert_U_idx = verts_tips_same_chain_idx[nearest_tip_first_st_first_pt_idx][1]
- else:
- first_vert_U_idx = verts_tips_same_chain_idx[nearest_tip_first_st_first_pt_idx][0]
-
- if selection_type == "TWO_NOT_CONNECTED":
- selection_U2_exists = True
-
- first_vert_U2_idx = verts_tips_same_chain_idx[nearest_tip_last_st_first_pt_pair_idx][nearest_tip_last_st_first_pt_point_idx]
- else:
- selection_U2_exists = False
-
- elif selection_type == "NO_SELECTION":
- selection_U_exists = False
- selection_V_exists = False
-
-
- #### Get an ordered list of the vertices of Selection-U.
- if selection_U_exists:
- verts_ordered_U = self.get_ordered_verts(self.main_object, all_selected_edges_idx, all_verts_idx, first_vert_U_idx, middle_vertex_idx)
-
- #### Get an ordered list of the vertices of Selection-U.
- if selection_U2_exists:
- verts_ordered_U2 = self.get_ordered_verts(self.main_object, all_selected_edges_idx, all_verts_idx, first_vert_U2_idx, middle_vertex_idx)
-
- #### Get an ordered list of the vertices of Selection-V.
- if selection_V_exists:
- verts_ordered_V = self.get_ordered_verts(self.main_object, all_selected_edges_idx, all_verts_idx, first_vert_V_idx, middle_vertex_idx)
-
- #### Get an ordered list of the vertices of Selection-U.
- if selection_V2_exists:
- verts_ordered_V2 = self.get_ordered_verts(self.main_object, all_selected_edges_idx, all_verts_idx, first_vert_V2_idx, middle_vertex_idx)
-
-
- #### Calculate edges U proportions.
-
- # Sum selected edges U lengths.
- edges_lengths_U = []
- edges_lengths_sum_U = 0
-
- if selection_U_exists:
- edges_lengths_U, edges_lengths_sum_U = self.get_chain_length(verts_ordered_U)
-
- # Sum selected edges V lengths.
- edges_lengths_V = []
- edges_lengths_sum_V = 0
-
- if selection_V_exists:
- edges_lengths_V, edges_lengths_sum_V = self.get_chain_length(verts_ordered_V)
-
- bpy.ops.object.editmode_toggle()
- for i in range(0, int(bpy.context.scene.SURFSK_precision)):
- bpy.ops.curve.subdivide()
- bpy.ops.object.editmode_toggle()
-
- # Proportions U.
- edges_proportions_U = []
- edges_proportions_U = self.get_edges_proportions(edges_lengths_U, edges_lengths_sum_U, selection_U_exists, bpy.context.scene.SURFSK_edges_U)
- verts_count_U = len(edges_proportions_U) + 1
-
- # Proportions V.
- edges_proportions_V = []
- edges_proportions_V = self.get_edges_proportions(edges_lengths_V, edges_lengths_sum_V, selection_V_exists, bpy.context.scene.SURFSK_edges_V)
- verts_count_V = len(edges_proportions_V) + 1
-
-
-
- #### Get ordered lists of points on each sketched curve that mimics the proportions of the edges in the vertex selection.
- sketched_splines = ob_gp_strokes.data.splines
- sketched_splines_lengths = []
- sketched_splines_parsed = []
- for sp_idx in range(0, len(sketched_splines)):
- # Calculate spline length
- sketched_splines_lengths.append(0)
- for i in range(0, len(sketched_splines[sp_idx].bezier_points)):
- if i == 0:
- prev_p = sketched_splines[sp_idx].bezier_points[i]
- else:
- p = sketched_splines[sp_idx].bezier_points[i]
-
- p_difs = [prev_p.co[0] - p.co[0], prev_p.co[1] - p.co[1], prev_p.co[2] - p.co[2]]
- edge_length = abs(sqrt(p_difs[0] * p_difs[0] + p_difs[1] * p_difs[1] + p_difs[2] * p_difs[2]))
-
- sketched_splines_lengths[sp_idx] += edge_length
-
- prev_p = p
-
- # Calculate vertex positions with apropriate edge proportions, and ordered, for each spline.
- sketched_splines_parsed.append([])
- partial_spline_length = 0
- related_edge_U = 0
- edges_proportions_sum_U = 0
- edges_lengths_sum_U = 0
- for i in range(0, len(sketched_splines[sp_idx].bezier_points)):
- if i == 0:
- prev_p = sketched_splines[sp_idx].bezier_points[i]
- sketched_splines_parsed[sp_idx].append(prev_p.co)
- elif i != len(sketched_splines[sp_idx].bezier_points) - 1:
- p = sketched_splines[sp_idx].bezier_points[i]
-
- p_difs = [prev_p.co[0] - p.co[0], prev_p.co[1] - p.co[1], prev_p.co[2] - p.co[2]]
- edge_length = abs(sqrt(p_difs[0] * p_difs[0] + p_difs[1] * p_difs[1] + p_difs[2] * p_difs[2]))
-
-
- if edges_proportions_sum_U + edges_proportions_U[related_edge_U] - ((edges_lengths_sum_U + partial_spline_length + edge_length) / sketched_splines_lengths[sp_idx]) > 0: # comparing proportions to see if the proportion in the selection is found in the spline.
- partial_spline_length += edge_length
- elif related_edge_U < len(edges_proportions_U) - 1:
- sketched_splines_parsed[sp_idx].append(prev_p.co)
-
- edges_proportions_sum_U += edges_proportions_U[related_edge_U]
- related_edge_U += 1
-
- edges_lengths_sum_U += partial_spline_length
- partial_spline_length = edge_length
-
- prev_p = p
- else: # last point of the spline for the last edge
- p = sketched_splines[sp_idx].bezier_points[len(sketched_splines[sp_idx].bezier_points) - 1]
- sketched_splines_parsed[sp_idx].append(p.co)
-
-
- #### If the selection type is "TWO_NOT_CONNECTED" replace the last point of each spline with the points in the "target" selection.
- if selection_type == "TWO_NOT_CONNECTED":
- if selection_U2_exists:
- for i in range(0, len(sketched_splines_parsed[len(sketched_splines_parsed) - 1])):
- sketched_splines_parsed[len(sketched_splines_parsed) - 1][i] = verts_ordered_U2[i].co
-
-
- #### Create temporary curves along the "control-points" found on the sketched curves and the mesh selection.
- mesh_ctrl_pts_name = "SURFSK_ctrl_pts"
- me = bpy.data.meshes.new(mesh_ctrl_pts_name)
- ob_ctrl_pts = bpy.data.objects.new(mesh_ctrl_pts_name, me)
- ob_ctrl_pts.data = me
- bpy.context.scene.objects.link(ob_ctrl_pts)
-
-
- for i in range(0, verts_count_U):
- vert_num_in_spline = 1
-
- if selection_U_exists:
- ob_ctrl_pts.data.vertices.add(1)
- last_v = ob_ctrl_pts.data.vertices[len(ob_ctrl_pts.data.vertices) - 1]
- last_v.co = verts_ordered_U[i].co
-
- vert_num_in_spline += 1
-
- for sp in sketched_splines_parsed:
- ob_ctrl_pts.data.vertices.add(1)
- v = ob_ctrl_pts.data.vertices[len(ob_ctrl_pts.data.vertices) - 1]
- v.co = sp[i]
-
- if vert_num_in_spline > 1:
- ob_ctrl_pts.data.edges.add(1)
- ob_ctrl_pts.data.edges[len(ob_ctrl_pts.data.edges) - 1].vertices[0] = len(ob_ctrl_pts.data.vertices) - 2
- ob_ctrl_pts.data.edges[len(ob_ctrl_pts.data.edges) - 1].vertices[1] = len(ob_ctrl_pts.data.vertices) - 1
-
- last_v = v
-
- vert_num_in_spline += 1
-
- bpy.ops.object.select_name(name = ob_ctrl_pts.name)
- bpy.context.scene.objects.active = bpy.data.objects[ob_ctrl_pts.name]
-
-
- # Create curves from control points.
- bpy.ops.object.convert(target='CURVE', keep_original=False)
- ob_curves_surf = bpy.context.scene.objects.active
- bpy.ops.object.editmode_toggle()
- bpy.ops.curve.spline_type_set(type='BEZIER')
- bpy.ops.curve.handle_type_set(type='AUTOMATIC')
- for i in range(0, int(bpy.context.scene.SURFSK_precision)):
- bpy.ops.curve.subdivide()
- bpy.ops.object.editmode_toggle()
-
-
- # Calculate the length of each final surface spline.
- surface_splines = ob_curves_surf.data.splines
- surface_splines_lengths = []
- surface_splines_parsed = []
- for sp_idx in range(0, len(surface_splines)):
- # Calculate spline length
- surface_splines_lengths.append(0)
- for i in range(0, len(surface_splines[sp_idx].bezier_points)):
- if i == 0:
- prev_p = surface_splines[sp_idx].bezier_points[i]
- else:
- p = surface_splines[sp_idx].bezier_points[i]
-
- edge_length = self.pts_distance(prev_p.co, p.co)
-
- surface_splines_lengths[sp_idx] += edge_length
-
- prev_p = p
-
- bpy.ops.object.editmode_toggle()
- for i in range(0, int(bpy.context.scene.SURFSK_precision)):
- bpy.ops.curve.subdivide()
- bpy.ops.object.editmode_toggle()
-
- for sp_idx in range(0, len(surface_splines)):
- # Calculate vertex positions with apropriate edge proportions, and ordered, for each spline.
- surface_splines_parsed.append([])
- partial_spline_length = 0
- related_edge_V = 0
- edges_proportions_sum_V = 0
- edges_lengths_sum_V = 0
- for i in range(0, len(surface_splines[sp_idx].bezier_points)):
- if i == 0:
- prev_p = surface_splines[sp_idx].bezier_points[i]
- surface_splines_parsed[sp_idx].append(prev_p.co)
- elif i != len(surface_splines[sp_idx].bezier_points) - 1:
- p = surface_splines[sp_idx].bezier_points[i]
-
- edge_length = self.pts_distance(prev_p.co, p.co)
-
- if edges_proportions_sum_V + edges_proportions_V[related_edge_V] - ((edges_lengths_sum_V + partial_spline_length + edge_length) / surface_splines_lengths[sp_idx]) > 0: # comparing proportions to see if the proportion in the selection is found in the spline.
- partial_spline_length += edge_length
- elif related_edge_V < len(edges_proportions_V) - 1:
- surface_splines_parsed[sp_idx].append(prev_p.co)
-
- edges_proportions_sum_V += edges_proportions_V[related_edge_V]
- related_edge_V += 1
-
- edges_lengths_sum_V += partial_spline_length
- partial_spline_length = edge_length
-
- prev_p = p
- else: # last point of the spline for the last edge
- p = surface_splines[sp_idx].bezier_points[len(surface_splines[sp_idx].bezier_points) - 1]
- surface_splines_parsed[sp_idx].append(p.co)
-
- # Set the first and last verts of each spline to the locations of the respective verts in the selections.
- if selection_V_exists:
- for i in range(0, len(surface_splines_parsed[0])):
- surface_splines_parsed[len(surface_splines_parsed) - 1][i] = verts_ordered_V[i].co
-
- if selection_type == "TWO_NOT_CONNECTED":
- if selection_V2_exists:
- for i in range(0, len(surface_splines_parsed[0])):
- surface_splines_parsed[0][i] = verts_ordered_V2[i].co
-
-
- #### Delete object with control points and object from grease pencil convertion.
- bpy.ops.object.select_name(name = ob_ctrl_pts.name)
- bpy.context.scene.objects.active = bpy.data.objects[ob_ctrl_pts.name]
- bpy.ops.object.delete()
-
- bpy.ops.object.select_name(name = ob_gp_strokes.name)
- bpy.context.scene.objects.active = bpy.data.objects[ob_gp_strokes.name]
- bpy.ops.object.delete()
-
-
-
- #### Generate surface.
-
- # Get all verts coords.
- all_surface_verts_co = []
- for i in range(0, len(surface_splines_parsed)):
- # Get coords of all verts and make a list with them
- for pt_co in surface_splines_parsed[i]:
- all_surface_verts_co.append(pt_co)
-
-
- # Define verts for each face.
- all_surface_faces = []
- for i in range(0, len(all_surface_verts_co) - len(surface_splines_parsed[0])):
- if ((i + 1) / len(surface_splines_parsed[0]) != int((i + 1) / len(surface_splines_parsed[0]))):
- all_surface_faces.append([i+1, i , i + len(surface_splines_parsed[0]), i + len(surface_splines_parsed[0]) + 1])
-
-
- # Build the mesh.
- surf_me_name = "SURFSK_surface"
- me_surf = bpy.data.meshes.new(surf_me_name)
-
- me_surf.from_pydata(all_surface_verts_co, [], all_surface_faces)
-
- me_surf.update()
-
- ob_surface = bpy.data.objects.new(surf_me_name, me_surf)
- bpy.context.scene.objects.link(ob_surface)
-
-
- #### Join the new mesh to the main object.
- ob_surface.select = True
- self.main_object.select = True
- bpy.context.scene.objects.active = bpy.data.objects[self.main_object.name]
- bpy.ops.object.join()
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.remove_doubles(limit=0.0001)
- bpy.ops.mesh.normals_make_consistent(inside=False)
- bpy.ops.mesh.select_all(action='DESELECT')
-
- #### Delete grease pencil strokes
- bpy.ops.gpencil.active_frame_delete()
-
-
- def invoke (self, context, event):
- bpy.ops.object.editmode_toggle()
- bpy.ops.object.editmode_toggle()
- self.main_object = bpy.context.scene.objects.active
-
- self.execute(context)
-
- return {"FINISHED"}
-
-
-
-
-class GPENCIL_OT_SURFSK_strokes_to_curves(bpy.types.Operator):
- bl_idname = "GPENCIL_OT_SURFSK_strokes_to_curves"
- bl_label = "Convert grease pencil strokes into curves and enter edit mode"
- bl_description = "Convert grease pencil strokes into curves and enter edit mode"
-
-
- def execute(self, context):
- #### Convert grease pencil strokes to curve.
- bpy.ops.gpencil.convert(type='CURVE')
- ob_gp_strokes = bpy.context.object
- ob_gp_strokes.name = "SURFSK_strokes"
-
- #### Delete grease pencil strokes.
- bpy.ops.object.select_name(name = self.main_object.name)
- bpy.context.scene.objects.active = bpy.data.objects[self.main_object.name]
- bpy.ops.gpencil.active_frame_delete()
-
-
- bpy.ops.object.select_name(name = ob_gp_strokes.name)
- bpy.context.scene.objects.active = bpy.data.objects[ob_gp_strokes.name]
-
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.object.editmode_toggle()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
- bpy.ops.curve.smooth()
-
- curve_crv = ob_gp_strokes.data
- bpy.ops.curve.spline_type_set(type="BEZIER")
- bpy.ops.curve.handle_type_set(type="AUTOMATIC")
- bpy.data.curves[curve_crv.name].show_handles = False
- bpy.data.curves[curve_crv.name].show_normal_face = False
-
-
- def invoke (self, context, event):
- self.main_object = bpy.context.object
-
-
- self.execute(context)
-
- return {"FINISHED"}
-
-
-def register():
- bpy.types.Scene.SURFSK_edges_U = bpy.props.IntProperty(name="Cross", description="Number of edge rings crossing the strokes (perpendicular to strokes direction)", default=10, min=0, max=100000)
- bpy.types.Scene.SURFSK_edges_V = bpy.props.IntProperty(name="Follow", description="Number of edge rings following the strokes (parallel to strokes direction)", default=10, min=0, max=100000)
- bpy.types.Scene.SURFSK_precision = bpy.props.IntProperty(name="Precision", description="Precision level of the surface calculation", default=4, min=0, max=100000)
- bpy.types.Scene.SURFSK_keep_strokes = bpy.props.BoolProperty(name="Keep strokes", description="Keeps the sketched strokes after adding the surface", default=False)
-
- keymap_item_add_surf = bpy.data.window_managers[0].keyconfigs.active.keymaps["3D View"].items.new("GPENCIL_OT_SURFSK_add_surface","E","PRESS", key_modifier="D")
- keymap_item_stroke_to_curve = bpy.data.window_managers[0].keyconfigs.active.keymaps["3D View"].items.new("GPENCIL_OT_SURFSK_strokes_to_curves","C","PRESS", key_modifier="D")
-
-
-def unregister():
- del bpy.types.Scene.SURFSK_edges_U
- del bpy.types.Scene.SURFSK_edges_V
- del bpy.types.Scene.SURFSK_precision
- del bpy.types.Scene.SURFSK_keep_strokes
-
- km = bpy.data.window_managers[0].keyconfigs.active.keymaps["3D View"]
- for kmi in km.items:
- if kmi.idname == 'wm.call_menu':
- if kmi.properties.name == "GPENCIL_OT_SURFSK_add_surface":
- km.items.remove(kmi)
- elif kmi.properties.name == "GPENCIL_OT_SURFSK_strokes_to_curves":
- km.items.remove(kmi)
- else:
- continue
-
-
-if __name__ == "__main__":
- register()
-
diff --git a/object_add_chain.py b/object_add_chain.py
deleted file mode 100644
index 0cc997b9..00000000
--- a/object_add_chain.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Add Chain",
- "author": "Brian Hinton (Nichod)",
- "version": (0,1),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "View3D > Add > Mesh > Chain",
- "description": "Adds Chain with curve guide for easy creation",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Object/Add_Chain",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22203&group_id=153&atid=469",
- "category": "Object"}
-
-import bpy
-
-def Add_Chain():
-
-
- ##Adds Empty to scene
- bpy.ops.object.add(type='EMPTY', view_align=False, enter_editmode=False, location=(0, 0, 0),
-rotation=(0, 0, 0), layers=(True, False, False, False, False, False,
-False, False, False, False, False, False, False, False, False, False, False, False, False,
-False))
-
- ##Changes name of Empty to rot_link adds variable emp
- emp = bpy.context.object
- emp.name = "rot_link"
-
- ##Rotate emp ~ 90 degrees
- emp.rotation_euler = [1.570796, 0, 0]
-
- ##Adds Curve Path to scene
- bpy.ops.curve.primitive_nurbs_path_add( view_align=False, enter_editmode=False, location=(0, 0, 0),
-rotation=(0, 0, 0), layers=(True, False, False, False, False, False,
-False, False, False, False, False, False, False, False, False, False, False, False, False,
-False))
-
- ##Change Curve name to deform adds variable curv
- curv = bpy.context.object
- curv.name = "deform"
-
- ##Inserts Torus primitive
- bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25,
-major_segments=12, minor_segments=4, use_abso=False, abso_major_rad=1,
-abso_minor_rad=0.5)
-
- ##Positions Torus primitive to center of scene
- bpy.context.active_object.location = [0, 0, 0]
-
- ##Changes Torus name to chain adds variable tor
- tor = bpy.context.object
- tor.name = "chain"
-
- ##Adds Array Modifier to tor
- bpy.ops.object.modifier_add(type='ARRAY')
-
- ##Adds subsurf modifier tor
- bpy.ops.object.modifier_add(type='SUBSURF')
-
- ##Smooths tor
- bpy.ops.object.shade_smooth()
-
- ##Select curv
- sce = bpy.context.scene
- sce.objects.active = curv
-
- ##Toggle into editmode
- bpy.ops.object.editmode_toggle()
-
- ##Translate curve object
- bpy.ops.transform.translate(value=(2, 0, 0), constraint_axis=(True, False, False),
-constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
-proportional_edit_falloff='SMOOTH', proportional_size=1, snap=False,
-snap_target='CLOSEST', snap_point=(0, 0, 0), snap_align=False, snap_normal=(0, 0, 0),
-release_confirm=False)
-
- ##Toggle into objectmode
- bpy.ops.object.editmode_toggle()
-
- ##Select tor or chain
- sce.objects.active = tor
-
- ##Selects Array Modifier for editing
- array = tor.modifiers['Array']
-
- ##Change Array Modifier Parameters
- array.fit_type = ('FIT_CURVE')
- array.curve = curv
- array.offset_object = emp
- array.use_object_offset = True
- array.relative_offset_displace = [ 0.549, 0, 0 ]
-
- ##Add curve modifier
- bpy.ops.object.modifier_add(type='CURVE')
-
- ##Selects Curve Modifier for editing
- cur = tor.modifiers['Curve']
-
- ##Change Curve Modifier Parameters
- cur.object = curv
-
-#makes AddChain an operator
-class AddChain(bpy.types.Operator):
- '''Add a Chain.'''
- bl_idname = "mesh.primitive_chain_add"
- bl_label = "Add Chain"
- bl_options = {'REGISTER', 'UNDO'}
-
-
- def execute(self, context):
- Add_Chain()
-
- return {'FINISHED'}
-
-# Register the operator
-def menu_func(self, context):
- self.layout.operator(AddChain.bl_idname, text="Chain", icon='PLUGIN')
-
-
-def register():
- # Add "Chain" menu to the "Add Mesh" menu.
- bpy.types.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- # Remove "Chain" menu from the "Add Mesh" menu.
- bpy.types.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/object_cloud_gen.py b/object_cloud_gen.py
deleted file mode 100644
index 9d9ee1e2..00000000
--- a/object_cloud_gen.py
+++ /dev/null
@@ -1,674 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Cloud Generator",
- "author": "Nick Keeline(nrk)",
- "version": (0,7),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Tool Shelf ",
- "description": "Creates Volumetric Clouds",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Object/Cloud_Gen",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22015&group_id=153&atid=469",
- "category": "Object"}
-
-"""
-Place this file in the .blender/scripts/addons dir
-You have to activated the script in the "Add-Ons" tab (user preferences).
-The functionality can then be accessed via the Tool shelf when objects
-are selected
-
-Rev 0 initial release
-Rev 0.1 added scene to create_mesh per python api change.
-Rev 0.2 Added Point Density turbulence and fixed degenerate
-Rev 0.3 Fixed bug in degenerate
-Rev 0.4 updated for api change/changed to new apply modifier technique
-Rev 0.5 made particle count equation with radius so radius increases with cloud volume
-Rev 0.6 added poll function to operator, fixing crash with no selected objects
-Rev 0.7 added particles option and Type of Cloud wanted selector
-"""
-
-import bpy
-import mathutils
-from math import *
-from bpy.props import *
-
-
-# This routine takes an object and deletes all of the geometry in it
-# and adds a bounding box to it.
-# It will add or subtract the bound box size by the variable sizeDifference.
-def makeObjectIntoBoundBox(object, sizeDifference):
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object
- object.select = True
-
- # Go into Edit Mode
- bpy.ops.object.mode_set(mode='EDIT')
-
- mesh = object.data
- verts = mesh.vertices
-
- #Set the max and min verts to the first vertex on the list
- maxVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
- minVert = [verts[0].co[0], verts[0].co[1], verts[0].co[2]]
-
- #Create Max and Min Vertex array for the outer corners of the box
- for vert in verts:
- #Max vertex
- if vert.co[0] > maxVert[0]:
- maxVert[0] = vert.co[0]
- if vert.co[1] > maxVert[1]:
- maxVert[1] = vert.co[1]
- if vert.co[2] > maxVert[2]:
- maxVert[2] = vert.co[2]
-
- #Min Vertex
- if vert.co[0] < minVert[0]:
- minVert[0] = vert.co[0]
- if vert.co[1] < minVert[1]:
- minVert[1] = vert.co[1]
- if vert.co[2] < minVert[2]:
- minVert[2] = vert.co[2]
-
- #Add the size difference to the max size of the box
- maxVert[0] = maxVert[0] + sizeDifference
- maxVert[1] = maxVert[1] + sizeDifference
- maxVert[2] = maxVert[2] + sizeDifference
-
- #subtract the size difference to the min size of the box
- minVert[0] = minVert[0] - sizeDifference
- minVert[1] = minVert[1] - sizeDifference
- minVert[2] = minVert[2] - sizeDifference
-
- #Create arrays of verts and faces to be added to the mesh
- addVerts = []
-
- #X high loop
- addVerts.append([maxVert[0], maxVert[1], maxVert[2]])
- addVerts.append([maxVert[0], maxVert[1], minVert[2]])
- addVerts.append([maxVert[0], minVert[1], minVert[2]])
- addVerts.append([maxVert[0], minVert[1], maxVert[2]])
-
- #x low loop
- addVerts.append([minVert[0], maxVert[1], maxVert[2]])
- addVerts.append([minVert[0], maxVert[1], minVert[2]])
- addVerts.append([minVert[0], minVert[1], minVert[2]])
- addVerts.append([minVert[0], minVert[1], maxVert[2]])
-
- # Make the faces of the bounding box.
- addFaces = []
-
- # Draw a box on paper and number the vertices.
- # Use right hand rule to come up with number orders for faces on
- # the box (with normals pointing out).
- addFaces.append([0, 3, 2, 1])
- addFaces.append([4, 5, 6, 7])
- addFaces.append([0, 1, 5, 4])
- addFaces.append([1, 2, 6, 5])
- addFaces.append([2, 3, 7, 6])
- addFaces.append([0, 4, 7, 3])
-
- # Delete all geometry from the object.
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.delete(type='ALL')
-
- # Must be in object mode for from_pydata to work
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Add the mesh data.
- mesh.from_pydata(addVerts, [], addFaces)
-
- # Update the mesh
- mesh.update()
-
-
-def applyScaleRotLoc(scene, obj):
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object
- obj.select = True
- scene.objects.active = obj
-
- #bpy.ops.object.rotation_apply()
- bpy.ops.object.location_apply()
- bpy.ops.object.scale_apply()
-
-
-def totallyDeleteObject(scene, obj):
- #To Do this section to be updated when
- #Ability to completely delet objects added to blender
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object and delete it.
- obj.select = True
- scene.objects.active = obj
-
- # Delete all material slots in obj
- for i in range(len(obj.material_slots)):
- #textureSlots = cloudMaterial.texture_slots
- obj.active_material_index = i - 1
- bpy.ops.object.material_slot_remove()
-
- #bpy.ops.object.parent_clear(type='CLEAR')
-
- # Delete the Main Object
- bpy.ops.object.delete()
- #bpy.data.objects.remove(obj)
-
-
-def makeParent(parentobj, childobj, scene):
-
- applyScaleRotLoc(scene, parentobj)
-
- applyScaleRotLoc(scene, childobj)
-
- childobj.parent = parentobj
-
- #childobj.location = childobj.location - parentobj.location
-
-
-def addNewObject(scene, name, copyobj):
- '''
- Add an object and do other silly stuff.
- '''
- # Create new mesh
- mesh = bpy.data.meshes.new(name)
-
- # Create a new object.
- ob_new = bpy.data.objects.new(name, mesh)
- tempme = copyobj.data
- ob_new.data = tempme.copy()
- ob_new.scale = copyobj.scale
- ob_new.location = copyobj.location
-
- # Link new object to the given scene and select it.
- scene.objects.link(ob_new)
- ob_new.select = True
-
- return ob_new
-
-
-def combineObjects(scene, combined, listobjs):
- # scene is the current scene
- # combined is the object we want to combine everything into
- # listobjs is the list of objects to stick into combined
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the new object.
- combined.select = True
- scene.objects.active = combined
-
- # Add data
- if (len(listobjs) > 0):
- for i in listobjs:
- # Add a modifier
- bpy.ops.object.modifier_add(type='BOOLEAN')
-
- union = combined.modifiers
- union[0].name = "AddEmUp"
- union[0].object = i
- union[0].operation = 'UNION'
-
- # Apply modifier
- bpy.ops.object.modifier_apply(apply_as='DATA', modifier=union[0].name)
-
-
-# Returns True if we want to degenerate
-# and False if we want to generate a new cloud.
-def degenerateCloud(obj):
- if not obj:
- return False
-
- if "CloudMember" in obj:
- if obj["CloudMember"] != None:
- if obj.parent:
- if "CloudMember" not in obj.parent:
- return False
-
- else:
- return True
-
- return False
-
-
-class VIEW3D_PT_tools_cloud(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
-
- bl_label = "Cloud Generator"
- bl_context = "objectmode"
-
- def draw(self, context):
- active_obj = context.active_object
- layout = self.layout
- col = layout.column(align=True)
-
- degenerate = degenerateCloud(active_obj)
-
- if active_obj and degenerate:
-
- col.operator("cloud.generate_cloud", text="DeGenerate")
-
- elif active_obj is None:
-
- col.label(text="Select one or more")
- col.label(text="objects to generate")
- col.label(text="a cloud.")
-
- elif "CloudMember" in active_obj:
-
- col.label(text="Must select")
- col.label(text="bound box")
-
- elif active_obj and active_obj.type == 'MESH':
-
- col.operator("cloud.generate_cloud", text="Generate Cloud")
-
- col.prop(context.scene, "cloudparticles")
- col.prop(context.scene, "cloud_type")
- else:
- col.label(text="Select one or more")
- col.label(text="objects to generate")
- col.label(text="a cloud.")
-
-cloudTypes = []
-
-cloudTypes.append(("0","Stratus","Generate Stratus_foggy Cloud"))
-cloudTypes.append(("1","Cumulous","Generate Cumulous_puffy Cloud"))
-cloudTypes.append(("2","Cirrus","Generate Cirrus_wispy Cloud"))
-#cloudTypes.append(("3","Nimbus","Generate Nimbus Cloud"))
-
-
-bpy.types.Scene.cloudparticles = BoolProperty(
- name="Particles",
- description="Generate Cloud as Particle System",
- default=False)
-
-bpy.types.Scene.cloud_type = EnumProperty(
- name="Type",
- description="Select the type of cloud to create with material settings",
- items = cloudTypes, default = '0')
-
-class GenerateCloud(bpy.types.Operator):
- bl_idname = "cloud.generate_cloud"
- bl_label = "Generate Cloud"
- bl_description = "Create a Cloud."
- bl_register = True
- bl_undo = True
-
- @classmethod
- def poll(cls, context):
- if not context.active_object:
- return False
- else:
- return (context.active_object.type=='MESH')
-
- def execute(self, context):
- # Make variable that is the current .blend file main data blocks
- blend_data = context.blend_data
-
- # Make variable that is the active object selected by user
- active_object = context.active_object
-
- # Make variable scene that is current scene
- scene = context.scene
-
- # Parameters the user may want to change:
- # Number of points this number is multiplied by the volume to get
- # the number of points the scripts will put in the volume.
- numOfPoints = 1.0
- maxNumOfPoints = 100000
- scattering = 2.5
- pointDensityRadiusFactor = 1.0
- densityScale = 1.5
-
- # Should we degnerate?
- degenerate = degenerateCloud(active_object)
-
- if degenerate:
- # Degenerate Cloud
- mainObj = active_object
-
- cloudMembers = active_object.children
-
- createdObjects = []
- definitionObjects = []
- for member in cloudMembers:
- applyScaleRotLoc(scene, member)
- if (member["CloudMember"] == "CreatedObj"):
- createdObjects.append(member)
- else:
- definitionObjects.append(member)
-
- for defObj in definitionObjects:
- #Delete cloudmember data from objects
- if "CloudMember" in defObj:
- del(defObj["CloudMember"])
-
- for createdObj in createdObjects:
- totallyDeleteObject(scene, createdObj)
-
- # Delete the blend_data object
- totallyDeleteObject(scene, mainObj)
-
- # Select all of the left over boxes so people can immediately
- # press generate again if they want.
- for eachMember in definitionObjects:
- eachMember.draw_type = 'SOLID'
- eachMember.select = True
- #scene.objects.active = eachMember
-
- #TODO Delete this when render bug caused by degenerate is fixed.
- self.report({'WARNING'}, "Please save file exit and reenter blender before rendering to clean memory and prevent crash")
-
- else:
- # Generate Cloud
-
- ###############Create Combined Object bounds##################
- # Make a list of all Selected objects.
- selectedObjects = bpy.context.selected_objects
- if not selectedObjects:
- selectedObjects = [bpy.context.active_object]
-
- # Create a new object bounds
- bounds = addNewObject(scene,
- "CloudBounds",
- selectedObjects[0])
-
- bounds.draw_type = 'BOUNDS'
- bounds.hide_render = False
-
- # Just add a Definition Property designating this
- # as the blend_data object.
- bounds["CloudMember"] = "MainObj"
-
- # Since we used iteration 0 to copy with object we
- # delete it off the list.
- firstObject = selectedObjects[0]
- del selectedObjects[0]
-
- # Apply location Rotation and Scale to all objects involved.
- applyScaleRotLoc(scene, bounds)
- for each in selectedObjects:
- applyScaleRotLoc(scene, each)
-
- # Let's combine all of them together.
- combineObjects(scene, bounds, selectedObjects)
-
- # Let's add some property info to the objects.
- for selObj in selectedObjects:
- selObj["CloudMember"] = "DefinitioinObj"
- selObj.name = "DefinitioinObj"
- selObj.draw_type = 'WIRE'
- selObj.hide_render = True
- makeParent(bounds, selObj, scene)
-
- # Do the same to the 1. object since it is no longer in list.
- firstObject["CloudMember"] = "DefinitioinObj"
- firstObject.name = "DefinitioinObj"
- firstObject.draw_type = 'WIRE'
- firstObject.hide_render = True
- makeParent(bounds, firstObject, scene)
-
- ###############Create Cloud for putting Cloud Mesh############
- # Create a new object cloud.
- cloud = addNewObject(scene, "CloudMesh", bounds)
- cloud["CloudMember"] = "CreatedObj"
- cloud.draw_type = 'WIRE'
- cloud.hide_render = True
-
- makeParent(bounds, cloud, scene)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.subdivide(number_cuts=2, fractal=0, smoothness=1)
- bpy.ops.object.location_apply()
- bpy.ops.mesh.vertices_smooth(repeat=20)
- bpy.ops.mesh.tris_convert_to_quads()
- bpy.ops.mesh.faces_shade_smooth()
- bpy.ops.object.editmode_toggle()
-
- ###############Create Particles in cloud obj##################
- # Turn off gravity.
- scene.use_gravity = False
-
- # Set time to 0.
- scene.frame_current = 0
-
- # Add a new particle system.
- bpy.ops.object.particle_system_add()
-
- #Particle settings setting it up!
- cloudParticles = cloud.particle_systems.active
- cloudParticles.name = "CloudParticles"
- cloudParticles.settings.frame_start = 0
- cloudParticles.settings.frame_end = 0
- cloudParticles.settings.emit_from = 'VOLUME'
- cloudParticles.settings.draw_method = 'DOT'
- cloudParticles.settings.render_type = 'NONE'
- cloudParticles.settings.normal_factor = 0
- cloudParticles.settings.distribution = 'RAND'
- cloudParticles.settings.physics_type = 'NO'
-
- ####################Create Volume Material####################
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object.
- bounds.select = True
- scene.objects.active = bounds
-
- # Turn bounds object into a box.
- makeObjectIntoBoundBox(bounds, .6)
-
- # Delete all material slots in bounds object.
- for i in range(len(bounds.material_slots)):
- bounds.active_material_index = i - 1
- bpy.ops.object.material_slot_remove()
-
- # Add a new material.
- cloudMaterial = blend_data.materials.new("CloudMaterial")
- bpy.ops.object.material_slot_add()
- bounds.material_slots[0].material = cloudMaterial
-
- # Set Up the Cloud Material
- cloudMaterial.name = "CloudMaterial"
- cloudMaterial.type = 'VOLUME'
- mVolume = cloudMaterial.volume
- mVolume.scattering = scattering
- mVolume.density = 0
- mVolume.density_scale = densityScale
- mVolume.transmission_color = [3, 3, 3]
- mVolume.step_size = 0.1
- mVolume.use_light_cache = True
- mVolume.cache_resolution = 75
-
- # Add a texture
- vMaterialTextureSlots = cloudMaterial.texture_slots
- cloudtex = blend_data.textures.new("CloudTex", type='CLOUDS')
- cloudtex.noise_type = 'HARD_NOISE'
- cloudtex.noise_scale = 2
- mtex = cloudMaterial.texture_slots.add()
- mtex.texture = cloudtex
- mtex.texture_coords = 'ORCO'
- mtex.use_map_color_diffuse = True
-
- # Add a force field to the points.
- cloudField = bounds.field
- cloudField.type = 'TEXTURE'
- cloudField.strength = 2
- cloudField.texture = cloudtex
-
- # Set time
- #for i in range(12):
- # scene.current_frame = i
- # scene.update()
- scene.frame_current = 1
-
- #bpy.ops.ptcache.bake(bake=False)
-
- # Add a Point Density texture
- pDensity = blend_data.textures.new("CloudPointDensity", 'POINT_DENSITY')
-
- mtex = cloudMaterial.texture_slots.add()
- mtex.texture = pDensity
- mtex.texture_coords = 'GLOBAL'
- mtex.use_map_density = True
- mtex.use_rgb_to_intensity = True
- mtex.texture_coords = 'GLOBAL'
-
- pDensity.point_density.vertex_cache_space = 'WORLD_SPACE'
- pDensity.point_density.use_turbulence = True
- pDensity.point_density.noise_basis = 'VORONOI_F2'
- pDensity.point_density.turbulence_depth = 3
-
- pDensity.use_color_ramp = True
- pRamp = pDensity.color_ramp
- #pRamp.use_interpolation = 'LINEAR'
- pRampElements = pRamp.elements
- #pRampElements[1].position = .9
- #pRampElements[1].color = [.18,.18,.18,.8]
- bpy.ops.texture.slot_move(type='UP')
-
-
- # Estimate the number of particles for the size of bounds.
- volumeBoundBox = (bounds.dimensions[0] * bounds.dimensions[1]* bounds.dimensions[2])
- numParticles = int((2.4462 * volumeBoundBox + 430.4) * numOfPoints)
- if numParticles > maxNumOfPoints:
- numParticles = maxNumOfPoints
- if numParticles < 10000:
- numParticles = int(numParticles + 15 * volumeBoundBox)
- print(numParticles)
-
- # Set the number of particles according to the volume
- # of bounds.
- cloudParticles.settings.count = numParticles
-
- pDensity.point_density.radius = (.00013764 * volumeBoundBox + .3989) * pointDensityRadiusFactor
-
- # Set time to 1.
- scene.frame_current = 1
-
- if not scene.cloudparticles:
- ###############Create CloudPnts for putting points in#########
- # Create a new object cloudPnts
- cloudPnts = addNewObject(scene, "CloudPoints", bounds)
- cloudPnts["CloudMember"] = "CreatedObj"
- cloudPnts.draw_type = 'WIRE'
- cloudPnts.hide_render = True
-
- makeParent(bounds, cloudPnts, scene)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='SELECT')
-
- bpy.ops.mesh.delete(type='ALL')
-
- meshPnts = cloudPnts.data
-
- listCloudParticles = cloudParticles.particles
-
- listMeshPnts = []
- for pTicle in listCloudParticles:
- listMeshPnts.append(pTicle.location)
-
- # Must be in object mode fro from_pydata to work.
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Add in the mesh data.
- meshPnts.from_pydata(listMeshPnts, [], [])
-
- # Update the mesh.
- meshPnts.update()
-
- # Add a modifier.
- bpy.ops.object.modifier_add(type='DISPLACE')
-
- cldPntsModifiers = cloudPnts.modifiers
- cldPntsModifiers[0].name = "CloudPnts"
- cldPntsModifiers[0].texture = cloudtex
- cldPntsModifiers[0].texture_coords = 'OBJECT'
- cldPntsModifiers[0].texture_coordinate_object = cloud
- cldPntsModifiers[0].strength = -1.4
-
- # Apply modifier
- bpy.ops.object.modifier_apply(apply_as='DATA', modifier=cldPntsModifiers[0].name)
-
- pDensity.point_density.point_source = 'OBJECT'
- pDensity.point_density.object = cloudPnts
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- # Select the object.
- cloud.select = True
- scene.objects.active = cloud
-
- bpy.ops.object.particle_system_remove()
-
- # Deselect All
- bpy.ops.object.select_all(action='DESELECT')
-
- else:
-
- pDensity.point_density.point_source = 'PARTICLE_SYSTEM'
- pDensity.point_density.object = cloud
- pDensity.point_density.particle_system = cloudParticles
-
- if scene.cloud_type == '1': # Cumulous
- print("Cumulous")
- mVolume.density_scale = 2.22
- pDensity.point_density.turbulence_depth = 10
- pDensity.point_density.turbulence_strength = 6.3
- pDensity.point_density.turbulence_scale = 2.9
- pRampElements[1].position = .606
- pDensity.point_density.radius = pDensity.point_density.radius + .1
-
- elif scene.cloud_type == '2': # Cirrus
- print("Cirrus")
- pDensity.point_density.turbulence_strength = 22
- mVolume.transmission_color = [3.5, 3.5, 3.5]
- mVolume.scattering = .13
-
- # Select the object.
- bounds.select = True
- scene.objects.active = bounds
-
- return {'FINISHED'}
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-
-if __name__ == "__main__":
- register()
diff --git a/object_fracture/__init__.py b/object_fracture/__init__.py
deleted file mode 100644
index 182298fa..00000000
--- a/object_fracture/__init__.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Fracture Tools",
- "author": "pildanovak",
- "version": (2,0),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Fracture tools (Search > Fracture Object & Add -> Fracture Helper Objects",
- "description": "Fractured Object, Bomb, Projectile, Recorder",
- "warning": "script is returning errors",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Object/Fracture",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21793&group_id=153&atid=469",
- "category": "Object"}
-
-
-import bpy
-
-try:
- init_data
-
- reload(fracture_ops)
- reload(fracture_setup)
-except:
- from object_fracture import fracture_ops
- from object_fracture import fracture_setup
-
-init_data = True
-
-class INFO_MT_add_fracture_objects(bpy.types.Menu):
- bl_idname = "INFO_MT_add_fracture_objects"
- bl_label = "Fracture Helper Objects"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.operator("object.import_fracture_bomb",
- text="Bomb")
- layout.operator("object.import_fracture_projectile",
- text="Projectile")
- layout.operator("object.import_fracture_recorder",
- text="Rigidbody Recorder")
-
-import space_info
-
-
-def menu_func(self, context):
- self.layout.menu("INFO_MT_add_fracture_objects", icon="PLUGIN")
-
-
-def register():
- # Add the "add fracture objects" menu to the "Add" menu
- space_info.INFO_MT_add.append(menu_func)
-
-
-def unregister():
- # Remove "add fracture objects" menu from the "Add" menu.
- space_info.INFO_MT_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/object_fracture/data.blend b/object_fracture/data.blend
deleted file mode 100644
index e0e72dcf..00000000
--- a/object_fracture/data.blend
+++ /dev/null
Binary files differ
diff --git a/object_fracture/fracture_ops.py b/object_fracture/fracture_ops.py
deleted file mode 100644
index 19cd4bce..00000000
--- a/object_fracture/fracture_ops.py
+++ /dev/null
@@ -1,490 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-import bpy
-from bpy.props import *
-import os
-import random
-import mathutils
-from mathutils import *
-
-
-def create_cutter(context, crack_type, scale, roughness):
- ncuts = 12
- if crack_type == 'FLAT' or crack_type == 'FLAT_ROUGH':
- bpy.ops.mesh.primitive_cube_add(
- view_align=False,
- enter_editmode=False,
- location=(0, 0, 0),
- rotation=(0, 0, 0),
- layers=(True, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False))
-
- for v in context.scene.objects.active.data.vertices:
- v.co[0] += 1
- v.co[0] *= scale
- v.co[1] *= scale
- v.co[2] *= scale
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.faces_shade_smooth()
- bpy.ops.uv.reset()
-
- if crack_type == 'FLAT_ROUGH':
- bpy.ops.mesh.subdivide(
- number_cuts=ncuts,
- fractal=roughness * 7 * scale,
- smoothness=0)
-
- bpy.ops.mesh.vertices_smooth(repeat=5)
-
- bpy.ops.object.editmode_toggle()
-
- if crack_type == 'SPHERE' or crack_type == 'SPHERE_ROUGH':
- bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4,
- size=1,
- view_align=False,
- enter_editmode=False,
- location=(0, 0, 0),
- rotation=(0, 0, 0),
- layers=(True, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False,
- False, False, False, False))
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.faces_shade_smooth()
- bpy.ops.uv.smart_project(angle_limit=66, island_margin=0)
-
- bpy.ops.object.editmode_toggle()
- for v in context.scene.objects.active.data.vertices:
- v.co[0] += 1
- v.co[0] *= scale
- v.co[1] *= scale
- v.co[2] *= scale
-
- if crack_type == 'SPHERE_ROUGH':
- for v in context.scene.objects.active.data.vertices:
- v.co[0] += roughness * scale * 0.2 * (random.random() - 0.5)
- v.co[1] += roughness * scale * 0.1 * (random.random() - 0.5)
- v.co[2] += roughness * scale * 0.1 * (random.random() - 0.5)
-
- bpy.context.scene.objects.active.select = True
-
- '''
- # Adding fracture material
- # @todo Doesn't work at all yet.
- sce = bpy.context.scene
- if bpy.data.materials.get('fracture')==None:
- bpy.ops.material.new()
- bpy.ops.object.material_slot_add()
- sce.objects.active.material_slots[0].material.name = 'fracture'
- else:
- bpy.ops.object.material_slot_add()
- sce.objects.active.material_slots[0].material
- = bpy.data.materials['fracture']
- '''
-
-
-#UNWRAP
-def getsizefrommesh(ob):
- bb = ob.bound_box
- return (
- bb[5][0] - bb[0][0],
- bb[3][1] - bb[0][1],
- bb[1][2] - bb[0][2])
-
-
-def getIslands(shard):
- sm = shard.data
- islands = []
- vgroups = []
- fgroups = []
-
- vgi = []
- for v in sm.vertices:
- vgi.append(-1)
-
- gindex = 0
- for i in range(len(vgi)):
- if vgi[i] == -1:
- gproc = [i]
- vgroups.append([i])
- fgroups.append([])
-
- while len(gproc) > 0:
- i = gproc.pop(0)
- for f in sm.faces:
- #if i in f.vertices:
- for v in f.vertices:
- if v == i:
- for v1 in f.vertices:
- if vgi[v1] == -1:
- vgi[v1] = gindex
- vgroups[gindex].append(v1)
- gproc.append(v1)
-
- fgroups[gindex].append(f.index)
-
- gindex += 1
-
- #print( gindex)
-
- if gindex == 1:
- shards = [shard]
-
- else:
- shards = []
- for gi in range(0, gindex):
- bpy.ops.object.select_all(action='DESELECT')
- bpy.context.scene.objects.active = shard
- shard.select = True
- bpy.ops.object.duplicate(linked=False, mode=1)
- a = bpy.context.scene.objects.active
- sm = a.data
- print (a.name)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.select_all(action='DESELECT')
- bpy.ops.object.editmode_toggle()
-
- for x in range(len(sm.vertices) - 1, -1, -1):
- if vgi[x] != gi:
- #print('getIslands: selecting')
- #print('getIslands: ' + str(x))
- a.data.vertices[x].select = True
-
- print(bpy.context.scene.objects.active.name)
-
- bpy.ops.object.editmode_toggle()
- bpy.ops.mesh.delete()
- bpy.ops.object.editmode_toggle()
-
- bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
-
- shards.append(a)
-
- bpy.context.scene.objects.unlink(shard)
-
- return shards
-
-
-def boolop(ob, cutter, op):
- sce = bpy.context.scene
-
- fault = 0
- new_shards = []
-
- sizex, sizey, sizez = getsizefrommesh(ob)
- gsize = sizex + sizey + sizez
-
- bpy.ops.object.select_all()
- ob.select = True
- sce.objects.active = ob
- cutter.select = False
-
- bpy.ops.object.modifier_add(type='BOOLEAN')
- a = sce.objects.active
- a.modifiers['Boolean'].object = cutter
- a.modifiers['Boolean'].operation = op
-
- nmesh = a.create_mesh(sce, apply_modifiers=True, settings='PREVIEW')
-
- if len(nmesh.vertices) > 0:
- a.modifiers.remove(a.modifiers['Boolean'])
- bpy.ops.object.duplicate(linked=False, mode=1)
-
- new_shard = sce.objects.active
- new_shard.data = nmesh
- #scene.objects.link(new_shard)
-
- new_shard.location = a.location
- bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
-
- sizex, sizey, sizez = getsizefrommesh(new_shard)
- gsize2 = sizex + sizey + sizez
-
- if gsize2 > gsize * 1.01: # Size check
- print (gsize2, gsize, ob.name, cutter.name)
- fault = 1
- #print ('boolop: sizeerror')
-
- elif min(nmesh.edge_face_count) < 2: # Manifold check
- fault = 1
-
- if not fault:
- new_shards = getIslands(new_shard)
-
- else:
- sce.objects.unlink(new_shard)
-
- else:
- fault = 2
-
- return fault, new_shards
-
-
-def splitobject(context, ob, crack_type, roughness):
- scene = context.scene
-
- size = getsizefrommesh(ob)
- shards = []
- scale = max(size) * 1.3
-
- create_cutter(context, crack_type, scale, roughness)
- cutter = context.active_object
- cutter.location = ob.location
-
- cutter.location[0] += random.random() * size[0] * 0.1
- cutter.location[1] += random.random() * size[1] * 0.1
- cutter.location[2] += random.random() * size[2] * 0.1
- cutter.rotation_euler = [
- random.random() * 5000.0,
- random.random() * 5000.0,
- random.random() * 5000.0]
-
- scene.objects.active = ob
- operations = ['INTERSECT', 'DIFFERENCE']
-
- for op in operations:
- fault, newshards = boolop(ob, cutter, op)
-
- shards.extend(newshards)
- if fault > 0:
- # Delete all shards in case of fault from previous operation.
- for s in shards:
- scene.objects.unlink(s)
-
- scene.objects.unlink(cutter)
- #print('splitobject: fault')
-
- return [ob]
-
- if shards[0] != ob:
- bpy.context.scene.objects.unlink(ob)
-
- bpy.context.scene.objects.unlink(cutter)
-
- return shards
-
-
-def fracture_basic(context, nshards, crack_type, roughness):
- tobesplit = []
- shards = []
-
- for ob in context.scene.objects:
- if ob.select:
- tobesplit.append(ob)
-
- i = 1 # I counts shards, starts with 1 - the original object
- iter = 0 # counts iterations, to prevent eternal loops in case
- # of boolean faults
-
- maxshards = nshards * len(tobesplit)
-
- while i < maxshards and len(tobesplit) > 0 and iter < maxshards * 10:
- ob = tobesplit.pop(0)
- newshards = splitobject(context, ob, crack_type, roughness)
-
- tobesplit.extend(newshards)
-
- if len(newshards) > 1:
- shards.extend(newshards)
- #shards.remove(ob)
-
- i += (len(newshards) - 1)
-
- #print('fracture_basic: ' + str(i))
- #print('fracture_basic: lenobs', len(context.scene.objects))
-
- iter += 1
-
-
-def fracture_group(context, group):
- tobesplit = []
- shards = []
-
- for ob in context.scene.objects:
- if (ob.select
- and (len(ob.users_group) == 0 or ob.users_group[0].name != group)):
- tobesplit.append(ob)
-
- cutters = bpy.data.groups[group].objects
-
- # @todo This can be optimized.
- # Avoid booleans on obs where bbox doesn't intersect.
- i = 0
- for ob in tobesplit:
- for cutter in cutters:
- fault, newshards = boolop(ob, cutter, 'INTERSECT')
- shards.extend(newshards)
-
- if fault == 1:
- # Delete all shards in case of fault from previous operation.
- for s in shards:
- bpy.context.scene.objects.unlink(s)
-
- #print('fracture_group: fault')
- #print('fracture_group: ' + str(i))
-
- return
-
- i += 1
-
-
-class FractureSimple(bpy.types.Operator):
- '''Split object with boolean operations for simulation, uses an object.'''
- bl_idname = "object.fracture_simple"
- bl_label = "Fracture Object"
- bl_options = {'REGISTER', 'UNDO'}
-
- exe = BoolProperty(name="Execute",
- description="If it shall actually run, for optimal performance...",
- default=False)
-
- hierarchy = BoolProperty(name="Generate hierarchy",
- description="Hierarchy is usefull for simulation of objects" \
- " breaking in motion.",
- default=False)
-
- nshards = IntProperty(name="Number of shards",
- description="Number of shards the object should be split into.",
- min=2,
- default=5)
-
- crack_type = EnumProperty(name='Crack type',
- items=(
- ('FLAT', 'Flat', 'a'),
- ('FLAT_ROUGH', 'Flat rough', 'a'),
- ('SPHERE', 'Spherical', 'a'),
- ('SPHERE_ROUGH', 'Spherical rough', 'a')),
- description='Look of the fracture surface',
- default='FLAT')
-
- roughness = FloatProperty(name="Roughness",
- description="Roughness of the fracture surface",
- min=0.0,
- max=3.0,
- default=0.5)
-
- def execute(self, context):
- #getIslands(context.object)
- if self.exe:
- fracture_basic(context,
- self.nshards,
- self.crack_type,
- self.roughness)
-
- return {'FINISHED'}
-
-
-class FractureGroup(bpy.types.Operator):
- '''Split object with boolean operations for simulation, uses a group.'''
- bl_idname = "object.fracture_group"
- bl_label = "Fracture Object (Group)"
- bl_options = {'REGISTER', 'UNDO'}
-
- exe = BoolProperty(name="Execute",
- description="If it shall actually run, for optimal performance...",
- default=False)
-
- e = []
- for i, g in enumerate(bpy.data.groups):
- e.append((g.name, g.name, ''))
-
- group = EnumProperty(name='Group (hit F8 to refresh list)',
- items=e,
- description='Specify the group used for fracturing')
-
- def execute(self, context):
- #getIslands(context.object)
-
- if self.properties.exe:
- fracture_group(context, self.properties.group)
-
- return {'FINISHED'}
-
-
-#####################################################################
-# Import Functions
-
-def import_object(obname):
- opath = "//data.blend\\Object\\" + obname
- s = os.sep
- dpath = bpy.utils.script_paths()[0] + \
- '%saddons%sobject_fracture%sdata.blend\\Object\\' % (s, s, s)
-
- # DEBUG
- #print('import_object: ' + opath)
-
- bpy.ops.wm.link_append(
- filepath=opath,
- filename=obname,
- directory=dpath,
- filemode=1,
- link=False,
- autoselect=True,
- active_layer=True,
- instance_groups=True,
- relative_path=True)
-
- for ob in bpy.context.selected_objects:
- ob.location = bpy.context.scene.cursor_location
-
-
-class ImportFractureRecorder(bpy.types.Operator):
- '''Imports a rigidbody recorder'''
- bl_idname = "object.import_fracture_recorder"
- bl_label = "Add Rigidbody Recorder (Fracture)"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, context):
- import_object("RECORDER")
-
- return {'FINISHED'}
-
-
-class ImportFractureBomb(bpy.types.Operator):
- '''Import a bomb'''
- bl_idname = "object.import_fracture_bomb"
- bl_label = "Add Bomb (Fracture)"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, context):
- import_object("BOMB")
-
- return {'FINISHED'}
-
-
-class ImportFractureProjectile(bpy.types.Operator, ):
- '''Imports a projectile'''
- bl_idname = "object.import_fracture_projectile"
- bl_label = "Add Projectile (Fracture)"
- bl_options = {'REGISTER', 'UNDO'}
-
- def execute(self, context):
- import_object("PROJECTILE")
-
- return {'FINISHED'}
diff --git a/object_fracture/fracture_setup.py b/object_fracture/fracture_setup.py
deleted file mode 100644
index 3ab93821..00000000
--- a/object_fracture/fracture_setup.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-import bpy
-from bpy.props import *
-
-
-def getsizefrommesh(ob):
- bb = ob.bound_box
- return(
- bb[5][0] - bb[0][0],
- bb[3][1] - bb[0][1],
- bb[1][2] - bb[0][2])
-
-
-def setupshards(context):
- sce = context.scene
- #print(dir(context))
- #bpy.data.scenes[0].game_settings.all_frames
-
- tobeprocessed = []
- for ob in sce.objects:
- if ob.select:
- tobeprocessed.append(ob)
-
- for ob in tobeprocessed:
- g = ob.game
-
- g.physics_type = 'RIGID_BODY'
- g.use_collision_bounds = 1
- g.collision_bounds_type = 'CONVEX_HULL'
- g.rotation_damping = 0.9
-
- sizex, sizey, sizez = getsizefrommesh(ob)
- approxvolume = sizex * sizey * sizez
- g.mass = approxvolume
-
- sce.objects.active = ob
-
- bpy.ops.object.game_property_new()
- g.properties['prop'].name = 'shard'
- #sm=FloatProperty(name='shard',description='shardprop',default=0.0)
- #print (sm)
- #np=bpy.types.GameFloatProperty(sm)
- #name='shard',type='BOOL', value=1
- #print(ob)
-
-
-class SetupFractureShards(bpy.types.Operator):
- ''''''
- bl_idname = "object.setup_fracture_shards"
- bl_label = "Setup Fracture Shards"
- bl_options = {'REGISTER', 'UNDO'}
-
- #def poll(self, context):
-
- def execute(self, context):
- setupshards(context)
- return {'FINISHED'}
diff --git a/render_povray/__init__.py b/render_povray/__init__.py
deleted file mode 100644
index 4adcbf07..00000000
--- a/render_povray/__init__.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "PovRay",
- "author": "Campbell Barton",
- "version": (0,1),
- "blender": (2, 5, 4),
- "api": 31667,
- "location": "Info Header (engine dropdown)",
- "description": "Basic povray integration for blender",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Render/PovRay",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=23145&group_id=153&atid=469",
- "category": "Render"}
-
-
-if "bpy" in locals():
- reload(render)
- reload(ui)
-
-else:
- import bpy
- from bpy.props import *
- from render_povray import render
- from render_povray import ui
-
-
-def register():
- Scene = bpy.types.Scene
-
- # Not a real pov option, just to know if we should write
- Scene.pov_radio_enable = BoolProperty(
- name="Enable Radiosity",
- description="Enable povrays radiosity calculation",
- default=False)
- Scene.pov_radio_display_advanced = BoolProperty(
- name="Advanced Options",
- description="Show advanced options",
- default=False)
-
- # Real pov options
- Scene.pov_radio_adc_bailout = FloatProperty(
- name="ADC Bailout", description="The adc_bailout for radiosity rays. Use adc_bailout = 0.01 / brightest_ambient_object for good results",
- min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default=0.01)
-
- Scene.pov_radio_always_sample = BoolProperty(
- name="Always Sample", description="Only use the data from the pretrace step and not gather any new samples during the final radiosity pass",
- default=True)
-
- Scene.pov_radio_brightness = FloatProperty(
- name="Brightness", description="Amount objects are brightened before being returned upwards to the rest of the system",
- min=0.0, max=1000.0, soft_min=0.0, soft_max=10.0, default=1.0)
-
- Scene.pov_radio_count = IntProperty(
- name="Ray Count", description="Number of rays that are sent out whenever a new radiosity value has to be calculated",
- min=1, max=1600, default=35)
-
- Scene.pov_radio_error_bound = FloatProperty(
- name="Error Bound", description="One of the two main speed/quality tuning values, lower values are more accurate",
- min=0.0, max=1000.0, soft_min=0.1, soft_max=10.0, default=1.8)
-
- Scene.pov_radio_gray_threshold = FloatProperty(
- name="Gray Threshold", description="One of the two main speed/quality tuning values, lower values are more accurate",
- min=0.0, max=1.0, soft_min=0, soft_max=1, default=0.0)
-
- Scene.pov_radio_low_error_factor = FloatProperty(
- name="Low Error Factor", description="If you calculate just enough samples, but no more, you will get an image which has slightly blotchy lighting",
- min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.5)
-
- # max_sample - not available yet
- Scene.pov_radio_media = BoolProperty(
- name="Media", description="Radiosity estimation can be affected by media",
- default=False)
-
- Scene.pov_radio_minimum_reuse = FloatProperty(
- name="Minimum Reuse", description="Fraction of the screen width which sets the minimum radius of reuse for each sample point (At values higher than 2% expect errors)",
- min=0.0, max=1.0, soft_min=0.1, soft_max=0.1, default=0.015)
-
- Scene.pov_radio_nearest_count = IntProperty(
- name="Nearest Count", description="Number of old ambient values blended together to create a new interpolated value",
- min=1, max=20, default=5)
-
- Scene.pov_radio_normal = BoolProperty(
- name="Normals", description="Radiosity estimation can be affected by normals",
- default=False)
-
- Scene.pov_radio_recursion_limit = IntProperty(
- name="Recursion Limit", description="how many recursion levels are used to calculate the diffuse inter-reflection",
- min=1, max=20, default=3)
-
-
-def unregister():
- import bpy
- Scene = bpy.types.Scene
-
- del Scene.pov_radio_enable
- del Scene.pov_radio_display_advanced
- del Scene.pov_radio_adc_bailout
- del Scene.pov_radio_always_sample
- del Scene.pov_radio_brightness
- del Scene.pov_radio_count
- del Scene.pov_radio_error_bound
- del Scene.pov_radio_gray_threshold
- del Scene.pov_radio_low_error_factor
- del Scene.pov_radio_media
- del Scene.pov_radio_minimum_reuse
- del Scene.pov_radio_nearest_count
- del Scene.pov_radio_normal
- del Scene.pov_radio_recursion_limit
-
-
-if __name__ == "__main__":
- register()
diff --git a/render_povray/render.py b/render_povray/render.py
deleted file mode 100644
index 936ddc3b..00000000
--- a/render_povray/render.py
+++ /dev/null
@@ -1,790 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-import bpy
-import subprocess
-import os
-import sys
-import time
-import math
-
-import platform as pltfrm
-if pltfrm.architecture()[0] == '64bit':
- bitness = 64
-else:
- bitness = 32
-
-
-def write_pov(filename, scene=None, info_callback=None):
- file = open(filename, 'w')
-
- # Only for testing
- if not scene:
- scene = bpy.data.scenes[0]
-
- render = scene.render
- world = scene.world
-
- def uniqueName(name, nameSeq):
-
- if name not in nameSeq:
- return name
-
- name_orig = name
- i = 1
- while name in nameSeq:
- name = '%s_%.3d' % (name_orig, i)
- i += 1
-
- return name
-
- def writeMatrix(matrix):
- file.write('\tmatrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n' %\
- (matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2], matrix[3][0], matrix[3][1], matrix[3][2]))
-
- def writeObjectMaterial(material):
- if material and material.transparency_method == 'RAYTRACE':
- file.write('\tinterior { ior %.6f }\n' % material.raytrace_transparency.ior)
-
- # Other interior args
- # fade_distance 2
- # fade_power [Value]
- # fade_color
-
- # dispersion
- # dispersion_samples
-
- materialNames = {}
- DEF_MAT_NAME = 'Default'
-
- def writeMaterial(material):
- # Assumes only called once on each material
-
- if material:
- name_orig = material.name
- else:
- name_orig = DEF_MAT_NAME
-
- name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames)
-
- file.write('#declare %s = finish {\n' % name)
-
- if material:
- file.write('\tdiffuse %.3g\n' % material.diffuse_intensity)
- file.write('\tspecular %.3g\n' % material.specular_intensity)
-
- file.write('\tambient %.3g\n' % material.ambient)
- #file.write('\tambient rgb <%.3g, %.3g, %.3g>\n' % tuple([c*material.ambient for c in world.ambient_color])) # povray blends the global value
-
- # map hardness between 0.0 and 1.0
- roughness = ((1.0 - ((material.specular_hardness - 1.0) / 510.0)))
- # scale from 0.0 to 0.1
- roughness *= 0.1
- # add a small value because 0.0 is invalid
- roughness += (1 / 511.0)
-
- file.write('\troughness %.3g\n' % roughness)
-
- # 'phong 70.0 '
-
- if material.raytrace_mirror.use:
- raytrace_mirror = material.raytrace_mirror
- if raytrace_mirror.reflect_factor:
- file.write('\treflection {\n')
- file.write('\t\trgb <%.3g, %.3g, %.3g>' % tuple(material.mirror_color))
- file.write('\t\tfresnel 1 falloff %.3g exponent %.3g metallic %.3g} ' % (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor, raytrace_mirror.reflect_factor))
-
- else:
- file.write('\tdiffuse 0.8\n')
- file.write('\tspecular 0.2\n')
-
-
- # This is written into the object
- '''
- if material and material.transparency_method=='RAYTRACE':
- 'interior { ior %.3g} ' % material.raytrace_transparency.ior
- '''
-
- #file.write('\t\t\tcrand 1.0\n') # Sand granyness
- #file.write('\t\t\tmetallic %.6f\n' % material.spec)
- #file.write('\t\t\tphong %.6f\n' % material.spec)
- #file.write('\t\t\tphong_size %.6f\n' % material.spec)
- #file.write('\t\t\tbrilliance %.6f ' % (material.specular_hardness/256.0) # Like hardness
-
- file.write('}\n')
-
- def exportCamera():
- camera = scene.camera
- matrix = camera.matrix_world
-
- # compute resolution
- Qsize = float(render.resolution_x) / float(render.resolution_y)
-
- file.write('camera {\n')
- file.write('\tlocation <0, 0, 0>\n')
- file.write('\tlook_at <0, 0, -1>\n')
- file.write('\tright <%s, 0, 0>\n' % - Qsize)
- file.write('\tup <0, 1, 0>\n')
- file.write('\tangle %f \n' % (360.0 * math.atan(16.0 / camera.data.lens) / math.pi))
-
- file.write('\trotate <%.6f, %.6f, %.6f>\n' % tuple([math.degrees(e) for e in matrix.rotation_part().to_euler()]))
- file.write('\ttranslate <%.6f, %.6f, %.6f>\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
- file.write('}\n')
-
- def exportLamps(lamps):
- # Get all lamps
- for ob in lamps:
- lamp = ob.data
-
- matrix = ob.matrix_world
-
- color = tuple([c * lamp.energy for c in lamp.color]) # Colour is modified by energy
-
- file.write('light_source {\n')
- file.write('\t< 0,0,0 >\n')
- file.write('\tcolor rgb<%.3g, %.3g, %.3g>\n' % color)
-
- if lamp.type == 'POINT': # Point Lamp
- pass
- elif lamp.type == 'SPOT': # Spot
- file.write('\tspotlight\n')
-
- # Falloff is the main radius from the centre line
- file.write('\tfalloff %.2f\n' % (math.degrees(lamp.spot_size) / 2.0)) # 1 TO 179 FOR BOTH
- file.write('\tradius %.6f\n' % ((math.degrees(lamp.spot_size) / 2.0) * (1.0 - lamp.spot_blend)))
-
- # Blender does not have a tightness equivilent, 0 is most like blender default.
- file.write('\ttightness 0\n') # 0:10f
-
- file.write('\tpoint_at <0, 0, -1>\n')
- elif lamp.type == 'SUN':
- file.write('\tparallel\n')
- file.write('\tpoint_at <0, 0, -1>\n') # *must* be after 'parallel'
-
- elif lamp.type == 'AREA':
-
- size_x = lamp.size
- samples_x = lamp.shadow_ray_samples_x
- if lamp.shape == 'SQUARE':
- size_y = size_x
- samples_y = samples_x
- else:
- size_y = lamp.size_y
- samples_y = lamp.shadow_ray_samples_y
-
- file.write('\tarea_light <%d,0,0>,<0,0,%d> %d, %d\n' % (size_x, size_y, samples_x, samples_y))
- if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
- if lamp.jitter:
- file.write('\tjitter\n')
- else:
- file.write('\tadaptive 1\n')
- file.write('\tjitter\n')
-
- if lamp.shadow_method == 'NOSHADOW':
- file.write('\tshadowless\n')
-
- file.write('\tfade_distance %.6f\n' % lamp.distance)
- file.write('\tfade_power %d\n' % 1) # Could use blenders lamp quad?
- writeMatrix(matrix)
-
- file.write('}\n')
-
- def exportMeta(metas):
-
- # TODO - blenders 'motherball' naming is not supported.
-
- for ob in metas:
- meta = ob.data
-
- file.write('blob {\n')
- file.write('\t\tthreshold %.4g\n' % meta.threshold)
-
- try:
- material = meta.materials[0] # lame! - blender cant do enything else.
- except:
- material = None
-
- for elem in meta.elements:
-
- if elem.type not in ('BALL', 'ELLIPSOID'):
- continue # Not supported
-
- loc = elem.co
-
- stiffness = elem.stiffness
- if elem.use_negative:
- stiffness = - stiffness
-
- if elem.type == 'BALL':
-
- file.write('\tsphere { <%.6g, %.6g, %.6g>, %.4g, %.4g ' % (loc.x, loc.y, loc.z, elem.radius, stiffness))
-
- # After this wecould do something simple like...
- # "pigment {Blue} }"
- # except we'll write the color
-
- elif elem.type == 'ELLIPSOID':
- # location is modified by scale
- file.write('\tsphere { <%.6g, %.6g, %.6g>, %.4g, %.4g ' % (loc.x / elem.size_x, loc.y / elem.size_y, loc.z / elem.size_z, elem.radius, stiffness))
- file.write('scale <%.6g, %.6g, %.6g> ' % (elem.size_x, elem.size_y, elem.size_z))
-
- if material:
- diffuse_color = material.diffuse_color
-
- if material.use_transparency and material.transparency_method == 'RAYTRACE':
- trans = 1.0 - material.raytrace_transparency.filter
- else:
- trans = 0.0
-
- file.write('pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} finish {%s} }\n' % \
- (diffuse_color[0], diffuse_color[1], diffuse_color[2], 1.0 - material.alpha, trans, materialNames[material.name]))
-
- else:
- file.write('pigment {rgb<1 1 1>} finish {%s} }\n' % DEF_MAT_NAME) # Write the finish last.
-
- writeObjectMaterial(material)
-
- writeMatrix(ob.matrix_world)
-
- file.write('}\n')
-
- def exportMeshs(scene, sel):
-
- ob_num = 0
-
- for ob in sel:
- ob_num += 1
-
- if ob.type in ('LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'):
- continue
-
- me = ob.data
- me_materials = me.materials
-
- me = ob.create_mesh(scene, True, 'RENDER')
-
- if not me or not me.faces:
- continue
-
- if info_callback:
- info_callback('Object %2.d of %2.d (%s)' % (ob_num, len(sel), ob.name))
-
- #if ob.type!='MESH':
- # continue
- # me = ob.data
-
- matrix = ob.matrix_world
- try:
- uv_layer = me.uv_textures.active.data
- except:
- uv_layer = None
-
- try:
- vcol_layer = me.vertex_colors.active.data
- except:
- vcol_layer = None
-
- faces_verts = [f.vertices[:] for f in me.faces]
- faces_normals = [tuple(f.normal) for f in me.faces]
- verts_normals = [tuple(v.normal) for v in me.vertices]
-
- # quads incur an extra face
- quadCount = len([f for f in faces_verts if len(f) == 4])
-
- file.write('mesh2 {\n')
- file.write('\tvertex_vectors {\n')
- file.write('\t\t%s' % (len(me.vertices))) # vert count
- for v in me.vertices:
- file.write(',\n\t\t<%.6f, %.6f, %.6f>' % tuple(v.co)) # vert count
- file.write('\n }\n')
-
-
- # Build unique Normal list
- uniqueNormals = {}
- for fi, f in enumerate(me.faces):
- fv = faces_verts[fi]
- # [-1] is a dummy index, use a list so we can modify in place
- if f.use_smooth: # Use vertex normals
- for v in fv:
- key = verts_normals[v]
- uniqueNormals[key] = [-1]
- else: # Use face normal
- key = faces_normals[fi]
- uniqueNormals[key] = [-1]
-
- file.write('\tnormal_vectors {\n')
- file.write('\t\t%d' % len(uniqueNormals)) # vert count
- idx = 0
- for no, index in uniqueNormals.items():
- file.write(',\n\t\t<%.6f, %.6f, %.6f>' % no) # vert count
- index[0] = idx
- idx += 1
- file.write('\n }\n')
-
-
- # Vertex colours
- vertCols = {} # Use for material colours also.
-
- if uv_layer:
- # Generate unique UV's
- uniqueUVs = {}
-
- for fi, uv in enumerate(uv_layer):
-
- if len(faces_verts[fi]) == 4:
- uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
- else:
- uvs = uv.uv1, uv.uv2, uv.uv3
-
- for uv in uvs:
- uniqueUVs[tuple(uv)] = [-1]
-
- file.write('\tuv_vectors {\n')
- #print unique_uvs
- file.write('\t\t%s' % (len(uniqueUVs))) # vert count
- idx = 0
- for uv, index in uniqueUVs.items():
- file.write(',\n\t\t<%.6f, %.6f>' % uv)
- index[0] = idx
- idx += 1
- '''
- else:
- # Just add 1 dummy vector, no real UV's
- file.write('\t\t1') # vert count
- file.write(',\n\t\t<0.0, 0.0>')
- '''
- file.write('\n }\n')
-
-
- if me.vertex_colors:
-
- for fi, f in enumerate(me.faces):
- material_index = f.material_index
- material = me_materials[material_index]
-
- if material and material.use_vertex_color_paint:
-
- col = vcol_layer[fi]
-
- if len(faces_verts[fi]) == 4:
- cols = col.color1, col.color2, col.color3, col.color4
- else:
- cols = col.color1, col.color2, col.color3
-
- for col in cols:
- key = col[0], col[1], col[2], material_index # Material index!
- vertCols[key] = [-1]
-
- else:
- if material:
- diffuse_color = tuple(material.diffuse_color)
- key = diffuse_color[0], diffuse_color[1], diffuse_color[2], material_index
- vertCols[key] = [-1]
-
-
- else:
- # No vertex colours, so write material colours as vertex colours
- for i, material in enumerate(me_materials):
-
- if material:
- diffuse_color = tuple(material.diffuse_color)
- key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
- vertCols[key] = [-1]
-
-
- # Vert Colours
- file.write('\ttexture_list {\n')
- file.write('\t\t%s' % (len(vertCols))) # vert count
- idx = 0
- for col, index in vertCols.items():
-
- if me_materials:
- material = me_materials[col[3]]
- material_finish = materialNames[material.name]
-
- if material.use_transparency and material.transparency_method == 'RAYTRACE':
- trans = 1.0 - material.raytrace_transparency.filter
- else:
- trans = 0.0
-
- else:
- material_finish = DEF_MAT_NAME # not working properly,
- trans = 0.0
-
- #print material.apl
- file.write(',\n\t\ttexture { pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} finish {%s}}' %
- (col[0], col[1], col[2], 1.0 - material.alpha, trans, material_finish))
-
- index[0] = idx
- idx += 1
-
- file.write('\n }\n')
-
- # Face indicies
- file.write('\tface_indices {\n')
- file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
- for fi, f in enumerate(me.faces):
- fv = faces_verts[fi]
- material_index = f.material_index
- if len(fv) == 4:
- indicies = (0, 1, 2), (0, 2, 3)
- else:
- indicies = ((0, 1, 2),)
-
- if vcol_layer:
- col = vcol_layer[fi]
-
- if len(fv) == 4:
- cols = col.color1, col.color2, col.color3, col.color4
- else:
- cols = col.color1, col.color2, col.color3
-
-
- if not me_materials or me_materials[material_index] == None: # No materials
- for i1, i2, i3 in indicies:
- file.write(',\n\t\t<%d,%d,%d>' % (fv[i1], fv[i2], fv[i3])) # vert count
- else:
- material = me_materials[material_index]
- for i1, i2, i3 in indicies:
- if me.vertex_colors and material.use_vertex_color_paint:
- # Colour per vertex - vertex colour
-
- col1 = cols[i1]
- col2 = cols[i2]
- col3 = cols[i3]
-
- ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
- ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
- ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
- else:
- # Colour per material - flat material colour
- diffuse_color = material.diffuse_color
- ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], diffuse_color[2], f.material_index][0]
-
- file.write(',\n\t\t<%d,%d,%d>, %d,%d,%d' % (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
-
-
- file.write('\n }\n')
-
- # normal_indices indicies
- file.write('\tnormal_indices {\n')
- file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
- for fi, fv in enumerate(faces_verts):
-
- if len(fv) == 4:
- indicies = (0, 1, 2), (0, 2, 3)
- else:
- indicies = ((0, 1, 2),)
-
- for i1, i2, i3 in indicies:
- if f.use_smooth:
- file.write(',\n\t\t<%d,%d,%d>' %\
- (uniqueNormals[verts_normals[fv[i1]]][0],\
- uniqueNormals[verts_normals[fv[i2]]][0],\
- uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
- else:
- idx = uniqueNormals[faces_normals[fi]][0]
- file.write(',\n\t\t<%d,%d,%d>' % (idx, idx, idx)) # vert count
-
- file.write('\n }\n')
-
- if uv_layer:
- file.write('\tuv_indices {\n')
- file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
- for fi, fv in enumerate(faces_verts):
-
- if len(fv) == 4:
- indicies = (0, 1, 2), (0, 2, 3)
- else:
- indicies = ((0, 1, 2),)
-
- uv = uv_layer[fi]
- if len(faces_verts[fi]) == 4:
- uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3), tuple(uv.uv4)
- else:
- uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3)
-
- for i1, i2, i3 in indicies:
- file.write(',\n\t\t<%d,%d,%d>' %\
- (uniqueUVs[uvs[i1]][0],\
- uniqueUVs[uvs[i2]][0],\
- uniqueUVs[uvs[i2]][0])) # vert count
- file.write('\n }\n')
-
- if me.materials:
- material = me.materials[0] # dodgy
- writeObjectMaterial(material)
-
- writeMatrix(matrix)
- file.write('}\n')
-
- bpy.data.meshes.remove(me)
-
- def exportWorld(world):
- if not world:
- return
-
- mist = world.mist_settings
-
- if mist.use_mist:
- file.write('fog {\n')
- file.write('\tdistance %.6f\n' % mist.depth)
- file.write('\tcolor rgbt<%.3g, %.3g, %.3g, %.3g>\n' % (tuple(world.horizon_color) + (1 - mist.intensity,)))
- #file.write('\tfog_offset %.6f\n' % mist.start)
- #file.write('\tfog_alt 5\n')
- #file.write('\tturbulence 0.2\n')
- #file.write('\tturb_depth 0.3\n')
- file.write('\tfog_type 1\n')
- file.write('}\n')
-
- def exportGlobalSettings(scene):
-
- file.write('global_settings {\n')
-
- if scene.pov_radio_enable:
- file.write('\tradiosity {\n')
- file.write("\t\tadc_bailout %.4g\n" % scene.pov_radio_adc_bailout)
- file.write("\t\talways_sample %d\n" % scene.pov_radio_always_sample)
- file.write("\t\tbrightness %.4g\n" % scene.pov_radio_brightness)
- file.write("\t\tcount %d\n" % scene.pov_radio_count)
- file.write("\t\terror_bound %.4g\n" % scene.pov_radio_error_bound)
- file.write("\t\tgray_threshold %.4g\n" % scene.pov_radio_gray_threshold)
- file.write("\t\tlow_error_factor %.4g\n" % scene.pov_radio_low_error_factor)
- file.write("\t\tmedia %d\n" % scene.pov_radio_media)
- file.write("\t\tminimum_reuse %.4g\n" % scene.pov_radio_minimum_reuse)
- file.write("\t\tnearest_count %d\n" % scene.pov_radio_nearest_count)
- file.write("\t\tnormal %d\n" % scene.pov_radio_normal)
- file.write("\t\trecursion_limit %d\n" % scene.pov_radio_recursion_limit)
- file.write('\t}\n')
-
- if world:
- file.write("\tambient_light rgb<%.3g, %.3g, %.3g>\n" % tuple(world.ambient_color))
-
- file.write('}\n')
-
-
- # Convert all materials to strings we can access directly per vertex.
- writeMaterial(None) # default material
-
- for material in bpy.data.materials:
- writeMaterial(material)
-
- exportCamera()
- #exportMaterials()
- sel = scene.objects
- exportLamps([l for l in sel if l.type == 'LAMP'])
- exportMeta([l for l in sel if l.type == 'META'])
- exportMeshs(scene, sel)
- exportWorld(scene.world)
- exportGlobalSettings(scene)
-
- file.close()
-
-
-
-def write_pov_ini(filename_ini, filename_pov, filename_image):
- scene = bpy.data.scenes[0]
- render = scene.render
-
- x = int(render.resolution_x * render.resolution_percentage * 0.01)
- y = int(render.resolution_y * render.resolution_percentage * 0.01)
-
- file = open(filename_ini, 'w')
-
- file.write('Input_File_Name="%s"\n' % filename_pov)
- file.write('Output_File_Name="%s"\n' % filename_image)
-
- file.write('Width=%d\n' % x)
- file.write('Height=%d\n' % y)
-
- # Needed for border render.
- '''
- file.write('Start_Column=%d\n' % part.x)
- file.write('End_Column=%d\n' % (part.x+part.w))
-
- file.write('Start_Row=%d\n' % (part.y))
- file.write('End_Row=%d\n' % (part.y+part.h))
- '''
-
- file.write('Display=0\n')
- file.write('Pause_When_Done=0\n')
- file.write('Output_File_Type=T\n') # TGA, best progressive loading
- file.write('Output_Alpha=1\n')
-
- if render.use_antialiasing:
- aa_mapping = {'5': 2, '8': 3, '11': 4, '16': 5} # method 1 assumed
- file.write('Antialias=1\n')
- file.write('Antialias_Depth=%d\n' % aa_mapping[render.antialiasing_samples])
- else:
- file.write('Antialias=0\n')
-
- file.close()
-
-
-class PovrayRender(bpy.types.RenderEngine):
- bl_idname = 'POVRAY_RENDER'
- bl_label = "Povray"
- DELAY = 0.02
-
- def _export(self, scene):
- import tempfile
-
- self._temp_file_in = tempfile.mktemp(suffix='.pov')
- self._temp_file_out = tempfile.mktemp(suffix='.tga')
- self._temp_file_ini = tempfile.mktemp(suffix='.ini')
- '''
- self._temp_file_in = '/test.pov'
- self._temp_file_out = '/test.tga'
- self._temp_file_ini = '/test.ini'
- '''
-
- def info_callback(txt):
- self.update_stats("", "POVRAY: " + txt)
-
- write_pov(self._temp_file_in, scene, info_callback)
-
- def _render(self):
-
- try:
- os.remove(self._temp_file_out) # so as not to load the old file
- except:
- pass
-
- write_pov_ini(self._temp_file_ini, self._temp_file_in, self._temp_file_out)
-
- print ("***-STARTING-***")
-
- pov_binary = "povray"
-
- if sys.platform == 'win32':
- import winreg
- regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\POV-Ray\\v3.6\\Windows')
-
- if bitness == 64:
- pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine64'
- else:
- pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine'
-
- if 1:
- # TODO, when povray isnt found this gives a cryptic error, would be nice to be able to detect if it exists
- try:
- self._process = subprocess.Popen([pov_binary, self._temp_file_ini]) # stdout=subprocess.PIPE, stderr=subprocess.PIPE
- except OSError:
- # TODO, report api
- print("POVRAY: could not execute '%s', possibly povray isn't installed" % pov_binary)
- import traceback
- traceback.print_exc()
- print ("***-DONE-***")
- return False
-
- else:
- # This works too but means we have to wait until its done
- os.system('%s %s' % (pov_binary, self._temp_file_ini))
-
- print ("***-DONE-***")
- return True
-
- def _cleanup(self):
- for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
- try:
- os.remove(f)
- except:
- pass
-
- self.update_stats("", "")
-
- def render(self, scene):
-
- self.update_stats("", "POVRAY: Exporting data from Blender")
- self._export(scene)
- self.update_stats("", "POVRAY: Parsing File")
-
- if not self._render():
- self.update_stats("", "POVRAY: Not found")
- return
-
- r = scene.render
-
- # compute resolution
- x = int(r.resolution_x * r.resolution_percentage * 0.01)
- y = int(r.resolution_y * r.resolution_percentage * 0.01)
-
- # Wait for the file to be created
- while not os.path.exists(self._temp_file_out):
- if self.test_break():
- try:
- self._process.terminate()
- except:
- pass
- break
-
- if self._process.poll() != None:
- self.update_stats("", "POVRAY: Failed")
- break
-
- time.sleep(self.DELAY)
-
- if os.path.exists(self._temp_file_out):
-
- self.update_stats("", "POVRAY: Rendering")
-
- prev_size = -1
-
- def update_image():
- result = self.begin_result(0, 0, x, y)
- lay = result.layers[0]
- # possible the image wont load early on.
- try:
- lay.load_from_file(self._temp_file_out)
- except:
- pass
- self.end_result(result)
-
- # Update while povray renders
- while True:
-
- # test if povray exists
- if self._process.poll() is not None:
- update_image()
- break
-
- # user exit
- if self.test_break():
- try:
- self._process.terminate()
- except:
- pass
-
- break
-
- # Would be nice to redirect the output
- # stdout_value, stderr_value = self._process.communicate() # locks
-
-
- # check if the file updated
- new_size = os.path.getsize(self._temp_file_out)
-
- if new_size != prev_size:
- update_image()
- prev_size = new_size
-
- time.sleep(self.DELAY)
-
- self._cleanup()
-
-
diff --git a/render_povray/ui.py b/render_povray/ui.py
deleted file mode 100644
index 2d2a6d62..00000000
--- a/render_povray/ui.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-import bpy
-
-# Use some of the existing buttons.
-import properties_render
-properties_render.RENDER_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_render.RENDER_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
-del properties_render
-
-# Use only a subset of the world panels
-import properties_world
-properties_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_world.WORLD_PT_context_world.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER')
-properties_world.WORLD_PT_mist.COMPAT_ENGINES.add('POVRAY_RENDER')
-del properties_world
-
-# Example of wrapping every class 'as is'
-import properties_material
-for member in dir(properties_material):
- subclass = getattr(properties_material, member)
- try:
- subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
- except:
- pass
-del properties_material
-
-import properties_data_mesh
-for member in dir(properties_data_mesh):
- subclass = getattr(properties_data_mesh, member)
- try:
- subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
- except:
- pass
-del properties_data_mesh
-
-import properties_texture
-for member in dir(properties_texture):
- subclass = getattr(properties_texture, member)
- try:
- subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
- except:
- pass
-del properties_texture
-
-import properties_data_camera
-for member in dir(properties_data_camera):
- subclass = getattr(properties_data_camera, member)
- try:
- subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
- except:
- pass
-del properties_data_camera
-
-
-
-class RenderButtonsPanel():
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "render"
- # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine == False) and (rd.engine in cls.COMPAT_ENGINES)
-
-
-class RENDER_PT_povray_radiosity(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Radiosity"
- COMPAT_ENGINES = {'POVRAY_RENDER'}
-
- def draw_header(self, context):
- scene = context.scene
-
- self.layout.prop(scene, "pov_radio_enable", text="")
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
-
- layout.active = scene.pov_radio_enable
-
- split = layout.split()
-
- col = split.column()
- col.prop(scene, "pov_radio_count", text="Rays")
- col.prop(scene, "pov_radio_recursion_limit", text="Recursions")
- col = split.column()
- col.prop(scene, "pov_radio_error_bound", text="Error")
-
- layout.prop(scene, "pov_radio_display_advanced")
-
- if scene.pov_radio_display_advanced:
- split = layout.split()
-
- col = split.column()
- col.prop(scene, "pov_radio_adc_bailout", slider=True)
- col.prop(scene, "pov_radio_gray_threshold", slider=True)
- col.prop(scene, "pov_radio_low_error_factor", slider=True)
-
- col = split.column()
- col.prop(scene, "pov_radio_brightness")
- col.prop(scene, "pov_radio_minimum_reuse", text="Min Reuse")
- col.prop(scene, "pov_radio_nearest_count")
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Estimation Influence:")
- col.prop(scene, "pov_radio_media")
- col.prop(scene, "pov_radio_normal")
-
- col = split.column()
- col.prop(scene, "pov_radio_always_sample")
diff --git a/render_renderfarmfi.py b/render_renderfarmfi.py
deleted file mode 100644
index 34998a8e..00000000
--- a/render_renderfarmfi.py
+++ /dev/null
@@ -1,820 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Renderfarm.fi",
- "author": "Nathan Letwory <nathan@letworyinteractive.com>, Jesse Kaukonen <jesse.kaukonen@gmail.com>",
- "version": (3,),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Render > Engine > Renderfarm.fi",
- "description": "Send .blend as session to http://www.renderfarm.fi to render",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/Render/Renderfarm.fi",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22927&group_id=153&atid=469",
- "category": "Render"}
-
-"""
-Copyright 2009-2010 Laurea University of Applied Sciences
-Authors: Nathan Letwory, Jesse Kaukonen
-"""
-
-import bpy
-import hashlib
-import http.client
-import xmlrpc.client
-import math
-from os.path import abspath, isabs, join, isfile
-
-from bpy.props import PointerProperty, StringProperty, BoolProperty, EnumProperty, IntProperty, CollectionProperty
-
-bpy.CURRENT_VERSION = bl_addon_info["version"][0]
-bpy.found_newer_version = False
-bpy.up_to_date = False
-bpy.download_location = 'http://www.renderfarm.fi/blender'
-
-bpy.errorMessages = {
- 'missing_desc': 'You need to enter a title, short and long description',
- 'missing_creds': 'You haven\'t entered your credentials yet'
-}
-
-bpy.statusMessage = {
- 'title': 'TRIA_RIGHT',
- 'shortdesc': 'TRIA_RIGHT',
- 'longdesc': 'TRIA_RIGHT',
- 'username': 'TRIA_RIGHT',
- 'password': 'TRIA_RIGHT'
-}
-
-bpy.errors = []
-bpy.ore_sessions = []
-bpy.queue_selected = -1
-
-def renderEngine(render_engine):
- bpy.types.register(render_engine)
- return render_engine
-
-
-class ORESession(bpy.types.IDPropertyGroup):
- pass
-
-class ORESettings(bpy.types.IDPropertyGroup):
- pass
-
-# entry point for settings collection
-bpy.types.Scene.ore_render = PointerProperty(type=ORESettings, name='ORE Render', description='ORE Render Settings')
-
-# fill the new struct
-ORESettings.username = StringProperty(name='E-mail', description='E-mail for Renderfarm.fi', maxlen=256, default='')
-ORESettings.password = StringProperty(name='Password', description='Renderfarm.fi password', maxlen=256, default='')
-ORESettings.hash = StringProperty(name='Hash', description='hash calculated out of credentials', maxlen=33, default='')
-
-ORESettings.shortdesc = StringProperty(name='Short description', description='A short description of the scene (100 characters)', maxlen=101, default='')
-ORESettings.longdesc = StringProperty(name='Long description', description='A more elaborate description of the scene (2k)', maxlen=2048, default='')
-ORESettings.title = StringProperty(name='Title', description='Title for this session (128 characters)', maxlen=128, default='')
-ORESettings.url = StringProperty(name='Project URL', description='Project URL. Leave empty if not applicable', maxlen=256, default='')
-
-ORESettings.parts = IntProperty(name='Parts/Frame', description='', min=1, max=1000, soft_min=1, soft_max=64, default=1)
-ORESettings.resox = IntProperty(name='Resolution X', description='X of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1920)
-ORESettings.resoy = IntProperty(name='Resolution Y', description='Y of render', min=1, max=10000, soft_min=1, soft_max=10000, default=1080)
-ORESettings.memusage = IntProperty(name='Memory Usage', description='Estimated maximum memory usage during rendering in MB', min=1, max=6*1024, soft_min=1, soft_max=3*1024, default=256)
-ORESettings.start = IntProperty(name='Start Frame', description='Start Frame', default=1)
-ORESettings.end = IntProperty(name='End Frame', description='End Frame', default=250)
-ORESettings.fps = IntProperty(name='FPS', description='FPS', min=1, max=256, default=25)
-
-ORESettings.prepared = BoolProperty(name='Prepared', description='Set to True if preparation has been run', default=False)
-ORESettings.debug = BoolProperty(name='Debug', description='Verbose output in console', default=False)
-ORESettings.selected_session = IntProperty(name='Selected Session', description='The selected session', default=0)
-
-# session struct
-ORESession.name = StringProperty(name='Name', description='Name of the session', maxlen=128, default='[session]')
-
-licenses = (
- ('1', 'CC by-nc-nd', 'Creative Commons: Attribution Non-Commercial No Derivatives'),
- ('2', 'CC by-nc-sa', 'Creative Commons: Attribution Non-Commercial Share Alike'),
- ('3', 'CC by-nd', 'Creative Commons: Attribution No Derivatives'),
- ('4', 'CC by-nc', 'Creative Commons: Attribution Non-Commercial'),
- ('5', 'CC by-sa', 'Creative Commons: Attribution Share Alike'),
- ('6', 'CC by', 'Creative Commons: Attribution'),
- ('7', 'Copyright', 'Copyright, no license specified'),
- )
-ORESettings.inlicense = EnumProperty(items=licenses, name='source license', description='license speficied for the source files', default='1')
-ORESettings.outlicense = EnumProperty(items=licenses, name='output license', description='license speficied for the output files', default='1')
-
-ORESettings.sessions = CollectionProperty(type=ORESession, name='Sessions', description='Sessions on Renderfarm.fi')
-
-# all panels, except render panel
-# Example of wrapping every class 'as is'
-import properties_scene
-for member in dir(properties_scene):
- subclass = getattr(properties_scene, member)
- try: subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
- except: pass
-del properties_scene
-
-import properties_world
-for member in dir(properties_world):
- subclass = getattr(properties_world, member)
- try: subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
- except: pass
-del properties_world
-
-import properties_material
-for member in dir(properties_material):
- subclass = getattr(properties_material, member)
- try: subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
- except: pass
-del properties_material
-
-import properties_object
-for member in dir(properties_object):
- subclass = getattr(properties_object, member)
- try: subclass.COMPAT_ENGINES.add('RENDERFARMFI_RENDER')
- except: pass
-del properties_object
-
-class RenderButtonsPanel():
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "render"
- # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
-
-
-class RENDERFARM_MT_Session(bpy.types.Menu):
- bl_label = "Show Session"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator('ore.completed_sessions')
- layout.operator('ore.accept_sessions')
- layout.operator('ore.active_sessions')
- layout.separator()
- layout.operator('ore.cancelled_sessions')
-
-class LOGIN_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel):
- bl_label = 'Login to Renderfarm.fi'
- COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- # XXX layout.operator('ore.check_update')
- ore = context.scene.ore_render
- updateSessionList(ore)
- checkStatus(ore)
-
- if ore.hash=='':
- col = layout.column()
- if ore.hash=='':
- col.prop(ore, 'username', icon=bpy.statusMessage['username'])
- col.prop(ore, 'password', icon=bpy.statusMessage['password'])
- layout.operator('ore.login')
- else:
- layout.label(text='E-mail and password entered.', icon='INFO')
- layout.operator('ore.change_user')
-
-class CHECK_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel):
- bl_label = 'Check for updates'
- COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- ore = context.scene.ore_render
-
- if bpy.found_newer_version == True:
- layout.operator('ore.open_download_location')
- else:
- if bpy.up_to_date == True:
- layout.label(text='You have the latest version')
- layout.operator('ore.check_update')
-
-class SESSIONS_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel):
- bl_label = 'Sessions'
- COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- ore = context.scene.ore_render
-
- layout.menu("RENDERFARM_MT_Session")
- if bpy.queue_selected == 1:
- layout.label(text='Completed Sessions')
- elif bpy.queue_selected == 2:
- layout.label(text='Rendering Sessions')
- elif bpy.queue_selected == 3:
- layout.label(text='Pending Sessions')
- elif bpy.queue_selected == 4:
- layout.label(text='Cancelled and Rejected Sessions')
- layout.template_list(ore, 'sessions', ore, 'selected_session', rows=2)
- if bpy.queue_selected == 3:
- layout.operator('ore.cancel_session')
-
-class RENDER_PT_RenderfarmFi(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Scene Settings"
- COMPAT_ENGINES = set(['RENDERFARMFI_RENDER'])
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
- sce = context.scene
- ore = sce.ore_render
-
- if ore.prepared and ore.hash!='':
- layout.prop(ore, 'memusage')
-
- layout.separator()
- row = layout.row()
- row.label(text='Resolution: '+str(ore.resox)+'x'+str(ore.resoy))
-
- layout.separator()
- row = layout.row()
- row.prop(ore, 'inlicense')
- row.prop(ore, 'outlicense')
-
- layout.separator()
- row = layout.row()
- row.operator('ore.upload')
- row.operator('ore.reset', icon='FILE_REFRESH')
- else:
- layout.prop(ore, 'title', icon=bpy.statusMessage['title'])
- layout.prop(ore, 'shortdesc', icon=bpy.statusMessage['shortdesc'])
- layout.prop(ore, 'longdesc', icon=bpy.statusMessage['longdesc'])
- layout.prop(ore, 'url')
- layout.separator()
- layout.operator('ore.use_scene_settings', icon='HAND')
- row = layout.row()
- row.prop(ore, 'resox')
- row.prop(ore, 'resoy')
- layout.separator()
- layout.prop(ore, 'parts')
- row = layout.row()
- row.prop(ore, 'start')
- row.prop(ore, 'end')
- layout.prop(ore, 'fps')
-
- layout.separator()
- layout.operator('ore.prepare', icon='INFO')
-
-def random_string(length):
- import string
- import random
- return ''.join(random.choice(string.ascii_letters) for ii in range(length + 1))
-
-def encode_multipart_data(data, files):
- boundary = random_string(30)
-
- def get_content_type(filename):
- return 'application/octet-stream' # default this
-
- def encode_field(field_name):
- return ('--' + boundary,
- 'Content-Disposition: form-data; name="%s"' % field_name,
- '', str(data[field_name]))
-
- def encode_file(field_name):
- import codecs
- filename = files [field_name]
- return ('--' + boundary,
- 'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename),
- 'Content-Type: %s' % get_content_type(filename),
- '', str(open(filename, 'rb').read(), encoding='iso-8859-1'))
-
- lines = []
- for name in data:
- lines.extend(encode_field(name))
- for name in files:
- lines.extend(encode_file(name))
- lines.extend(('--%s--' % boundary, ''))
- body = '\r\n'.join(lines)
-
- headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
- 'content-length': str(len(body))}
-
- return body, headers
-
-def send_post(url, data, files):
- connection = http.client.HTTPConnection('xmlrpc.renderfarm.fi')
- connection.request('POST', '/file', *encode_multipart_data(data, files))
- response = connection.getresponse()
- res = response.read()
- return res
-
-def md5_for_file(filepath):
- md5hash = hashlib.md5()
- blocksize = 0x10000
- f = open(filepath, "rb")
- while True:
- data = f.read(blocksize)
- if not data:
- break
- md5hash.update(data)
- return md5hash.hexdigest()
-
-def upload_file(key, userid, sessionid, server, path):
- assert isabs(path)
- assert isfile(path)
-
- data = {
- 'userId': str(userid),
- 'sessionKey': key,
- 'sessionId': sessionid,
- 'md5sum': md5_for_file(path)
- }
- files = {
- 'blenderfile': path
- }
-
- r = send_post(server, data, files)
-
- #print 'Uploaded %r' % (path)
-
- return r
-
-def run_upload(key, userid, sessionid, path):
- #print('Upload', path)
- r = upload_file(key, userid, sessionid, r'http://xmlrpc.renderfarm.fi/file', path)
- o = xmlrpc.client.loads(r)
- #print('Done!')
-
- return o[0][0]
-
-def ore_upload(op, context):
- sce = context.scene
- ore = sce.ore_render
- if not ore.prepared:
- op.report(set(['ERROR']), 'Your user or scene information is not complete')
- return {'CANCELLED'}
- try:
- authproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/auth')
- res = authproxy.auth.getSessionKey(ore.username, ore.hash)
- key = res['key']
- userid = res['userId']
-
- proxy = xmlrpc.client.ServerProxy(r'http://xmlrpc.renderfarm.fi/session')
- proxy._ServerProxy__transport.user_agent = 'Renderfarm.fi Uploader/%s' % (bpy.CURRENT_VERSION)
- res = proxy.session.createSession(userid, key)
- sessionid = res['sessionId']
- key = res['key']
- res = run_upload(key, userid, sessionid, bpy.data.filepath)
- fileid = int(res['fileId'])
-
- res = proxy.session.setTitle(userid, res['key'], sessionid, ore.title)
- res = proxy.session.setLongDescription(userid, res['key'], sessionid, ore.longdesc)
- res = proxy.session.setShortDescription(userid, res['key'], sessionid, ore.shortdesc)
- if len(ore.url)>0:
- res = proxy.session.setExternalURLs(userid, res['key'], sessionid, ore.url)
- res = proxy.session.setStartFrame(userid, res['key'], sessionid, ore.start)
- res = proxy.session.setEndFrame(userid, res['key'], sessionid, ore.end)
- res = proxy.session.setSplit(userid, res['key'], sessionid, ore.parts)
- res = proxy.session.setMemoryLimit(userid, res['key'], sessionid, ore.memusage)
- res = proxy.session.setXSize(userid, res['key'], sessionid, ore.resox)
- res = proxy.session.setYSize(userid, res['key'], sessionid, ore.resoy)
- res = proxy.session.setFrameRate(userid, res['key'], sessionid, ore.fps)
- res = proxy.session.setOutputLicense(userid, res['key'], sessionid, int(ore.outlicense))
- res = proxy.session.setInputLicense(userid, res['key'], sessionid, int(ore.inlicense))
- res = proxy.session.setPrimaryInputFile(userid, res['key'], sessionid, fileid)
- res = proxy.session.submit(userid, res['key'], sessionid)
- op.report(set(['INFO']), 'Submission sent to Renderfarm.fi')
- except xmlrpc.client.Error as v:
- print('ERROR:', v)
- op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi')
- except Exception as e:
- print('Unhandled error:', e)
- op.report(set(['ERROR']), 'An error occurred while sending submission to Renderfarm.fi')
-
- return {'FINISHED'}
-
-def setStatus(property, status):
- if status:
- bpy.statusMessage[property] = 'ERROR'
- else:
- bpy.statusMessage[property] = 'TRIA_RIGHT'
-
-def showStatus(layoutform, property, message):
- if bpy.statusMessage[property] == 'ERROR':
- layoutform.label(text='', icon='ERROR')
-
-def checkStatus(ore):
- bpy.errors = []
-
- if ore.hash=='' and (ore.username=='' or ore.password==''):
- bpy.errors.append('missing_creds')
-
- if '' in (ore.title, ore.longdesc, ore.shortdesc):
- bpy.errors.append('missing_desc')
-
- setStatus('username', ore.hash=='' and ore.username=='')
- setStatus('password', ore.hash=='' and ore.password=='')
-
- setStatus('title', ore.title=='')
- setStatus('longdesc', ore.longdesc=='')
- setStatus('shortdesc', ore.shortdesc=='')
-
-class OreSession:
-
- def __init__(self, id, title):
- self.id = id
- self.title = title
- self.frames = 0
- self.startframe = 0
- self.endframe = 0
- self.rendertime = 0
- self.percentage = 0
-
- def percentageComplete(self):
- totFrames = self.endframe - self.startframe
- done = math.floor((self.frames / totFrames)*100)
- if done > 100: done = 100
- return done
-
-def xmlSessionsToOreSessions(sessions, queue):
- bpy.ore_sessions = []
- completed = sessions[queue]
- for sid in completed:
- s = completed[sid]['title']
- t = completed[sid]['timestamps']
- sinfo = OreSession(sid, s)
- if queue in ('completed', 'active'):
- sinfo.frames = completed[sid]['framesRendered']
- sinfo.startframe = completed[sid]['startFrame']
- sinfo.endframe = completed[sid]['endFrame']
- bpy.ore_sessions.append(sinfo)
-
-def updateSessionList(ore):
- while(len(ore.sessions) > 0):
- ore.sessions.remove(0)
-
- for s in bpy.ore_sessions:
- ore.sessions.add()
- session = ore.sessions[-1]
- session.name = s.title + ' [' + str(s.percentageComplete()) + '% complete]'
-
-class ORE_OpenDownloadLocation(bpy.types.Operator):
- bl_idname = 'ore.open_download_location'
- bl_label = 'Download new version for your platform'
-
- def execute(self, context):
- import webbrowser
- webbrowser.open(bpy.download_location)
- return {'FINISHED'}
-
-class ORE_CancelSession(bpy.types.Operator):
- bl_idname = 'ore.cancel_session'
- bl_label = 'Cancel Session'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
- if len(bpy.ore_sessions)>0:
- s = bpy.ore_sessions[ore.selected_session]
- try:
- res = userproxy.user.cancelSession(ore.username, ore.hash, int(s.id))
- self.report(set(['INFO']), 'Session ' + s.title + ' with id ' + s.id + ' cancelled')
- except:
- self.report(set(['ERROR']), 'Could not cancel session ' + s.title + ' with id ' + s.id)
-
- return {'FINISHED'}
-
-class ORE_GetCompletedSessions(bpy.types.Operator):
- bl_idname = 'ore.completed_sessions'
- bl_label = 'Complete'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- bpy.queue_selected = 1
- userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
-
- sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed')
-
- xmlSessionsToOreSessions(sessions, 'completed')
-
- updateSessionList(ore)
-
- return {'FINISHED'}
-
-class ORE_GetCancelledSessions(bpy.types.Operator):
- bl_idname = 'ore.cancelled_sessions'
- bl_label = 'Cancelled'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- bpy.queue_selected = 4
- userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
-
- sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'completed')
-
- xmlSessionsToOreSessions(sessions, 'canceled')
-
- updateSessionList(ore)
-
- return {'FINISHED'}
-
-class ORE_GetActiveSessions(bpy.types.Operator):
- bl_idname = 'ore.active_sessions'
- bl_label = 'Rendering'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- bpy.queue_selected = 2
- userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
-
- sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'active')
-
- xmlSessionsToOreSessions(sessions, 'active')
-
- updateSessionList(ore)
-
- return {'FINISHED'}
-
-class ORE_GetPendingSessions(bpy.types.Operator):
- bl_idname = 'ore.accept_sessions' # using ORE lingo in API. acceptQueue is session waiting for admin approval
- bl_label = 'Pending'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- bpy.queue_selected = 3
- userproxy = xmlrpc.client.ServerProxy(r'https://xmlrpc.renderfarm.fi/user')
-
- sessions = userproxy.user.getAllSessions(ore.username, ore.hash, 'accept')
-
- xmlSessionsToOreSessions(sessions, 'accept')
-
- updateSessionList(ore)
-
- return {'FINISHED'}
-
-class ORE_CheckUpdate(bpy.types.Operator):
- bl_idname = 'ore.check_update'
- bl_label = 'Check for new version'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
- blenderproxy = xmlrpc.client.ServerProxy(r'http://xmlrpc.renderfarm.fi/blender')
- try:
- self.report(set(['INFO']), 'Checking for newer version on Renderfarm.fi')
- dl_url = blenderproxy.blender.getCurrentVersion(bpy.CURRENT_VERSION)
- if len(dl_url['url']) > 0:
- self.report(set(['INFO']), 'Found a newer version on Renderfarm.fi ' + dl_url['url'])
- bpy.download_location = dl_url['url']
- bpy.found_newer_version = True
- else:
- bpy.up_to_date = True
- self.report(set(['INFO']), 'Done checking for newer version on Renderfarm.fi')
- except xmlrpc.client.Fault as f:
- print('ERROR:', f)
- self.report(set(['ERROR']), 'An error occurred while checking for newer version on Renderfarm.fi')
-
- return {'FINISHED'}
-
-class ORE_LoginOp(bpy.types.Operator):
- bl_idname = 'ore.login'
- bl_label = 'Confirm credentials'
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
-
- if ore.hash=='':
- if ore.password != '' and ore.username != '':
- ore.hash = hashlib.md5(ore.password.encode() + ore.username.encode()).hexdigest()
- ore.password = ''
-
- checkStatus(ore)
-
- if len(bpy.errors) > 0:
- ore.prepared = False
- return {'CANCELLED'}
-
- return {'FINISHED'}
-
-class ORE_PrepareOp(bpy.types.Operator):
- '''Checking the scene will also save to the current file when successful!'''
- bl_idname = 'ore.prepare'
- bl_label = 'Check scene'
-
- def execute(self, context):
- def hasSSSMaterial():
- for m in bpy.data.materials:
- if m.subsurface_scattering.enabled:
- return True
- return False
-
- def hasParticleSystem():
- if len(bpy.data.particles) > 0:
- self.report({'WARNING'}, "Found particle system")
- print("Found particle system")
- return True
- return False
-
- def hasSimulation(t):
- for o in bpy.data.objects:
- for m in o.modifiers:
- if isinstance(m, t):
- self.report({'WARNING'}, "Found simulation: " + str(t))
- print("Found simulation: " + str(t))
- return True
- return False
-
- def hasFluidSimulation():
- return hasSimulation(bpy.types.FluidSimulationModifier)
-
- def hasSmokeSimulation():
- return hasSimulation(bpy.types.SmokeModifier)
-
- def hasClothSimulation():
- return hasSimulation(bpy.types.ClothModifier)
-
- def hasCollisionSimulation():
- return hasSimulation(bpy.types.CollisionModifier)
-
- def hasSoftbodySimulation():
- return hasSimulation(bpy.types.SoftBodyModifier)
-
- def hasUnsupportedSimulation():
- return hasSoftbodySimulation() or hasCollisionSimulation() or hasClothSimulation() or hasSmokeSimulation or hasFluidSimulation() or hasParticleSystem()
-
- def isFilterNode(node):
- t = type(node)
- return t==bpy.types.CompositorNodeBlur or t==bpy.types.CompositorNodeDBlur
-
- def hasCompositingErrors(use_nodes, nodetree, parts):
- if not use_nodes: # no nodes in use, ignore check
- return False
-
- for node in nodetree.nodes:
- # output file absolutely forbidden
- if type(node)==bpy.types.CompositorNodeOutputFile:
- self.report({'ERROR'}, 'File output node is disallowed, remove them from your compositing nodetrees.')
- return True
- # blur et al are problematic when rendering ore.parts>1
- if isFilterNode(node) and parts>1:
- self.report({'WARNING'}, 'A filtering node found and parts > 1. This combination will give bad output.')
- return True
-
- return False
-
- sce = context.scene
- ore = sce.ore_render
-
- errors = False
-
- checkStatus(ore)
-
- if len(bpy.errors) > 0:
- ore.prepared = False
- return {'CANCELLED'}
-
- rd = sce.render
- print("=============================================")
- rd.threads_mode = 'FIXED'
- rd.threads = 1
- rd.resolution_x = ore.resox
- rd.resolution_y = ore.resoy
- if (rd.resolution_percentage != 100):
- print("Resolution percentage is not 100. Changing to 100%")
- self.report({'WARNING'}, "Resolution percentage is not 100. Changing to 100%")
- errors = True
- rd.resolution_percentage = 100
- if rd.file_format != 'PNG':
- print("Renderfarm.fi always uses PNG for output. Changing to PNG.")
- self.report({'WARNING'}, "Renderfarm.fi always uses PNG for output. Changing to PNG.")
- errors = True
- rd.file_format = 'PNG'
- if (rd.use_sss == True or hasSSSMaterial()) and ore.parts > 1:
- print("Subsurface Scattering is not supported when rendering with parts > 1. Disabling")
- self.report({'WARNING'}, "Subsurface Scattering is not supported when rendering with parts > 1. Disabling")
- rd.use_sss = False # disabling because ore.parts > 1. It's ok to use SSS with 1part/frame
- errors = True
- if hasUnsupportedSimulation() == True:
- print("An unsupported simulation was detected. Please check your settings and remove them")
- self.report({'WARNING'}, "An unsupported simulation was detected. Please check your settings and remove them")
- errors = True
- rd.use_save_buffers = False
- rd.use_free_image_textures = True
- if rd.use_compositing:
- if hasCompositingErrors(sce.use_nodes, sce.nodetree, ore.parts):
- print("Found disallowed nodes or problematic setup")
- self.report({'WARNING'}, "Found disallowed nodes or problematic setup")
- errors = True
- print("Done checking the scene. Now do a test render")
- self.report({'INFO'}, "Done checking the scene. Now do a test render")
- print("=============================================")
-
- # if errors found, don't allow to upload, instead have user
- # go through this until everything is ok
- if errors:
- self.report({'WARNING'}, "Settings were changed or other issues found. Check console and do a test render to make sure everything works.")
- ore.prepared = False
- else:
- ore.prepared = True
- rd.engine = 'BLENDER_RENDER'
- bpy.ops.wm.save_mainfile()
- rd.engine = 'RENDERFARMFI_RENDER'
-
- return {'FINISHED'}
-
-class ORE_ResetOp(bpy.types.Operator):
- bl_idname = "ore.reset"
- bl_label = "Reset Preparation"
-
- def execute(self, context):
- sce = context.scene
- sce.ore_render.prepared = False
- return {'FINISHED'}
-
-class ORE_UploaderOp(bpy.types.Operator):
- bl_idname = "ore.upload"
- bl_label = "Render on Renderfarm.fi"
-
- def execute(self, context):
- rd = context.scene.render
- rd.engine = 'BLENDER_RENDER'
- bpy.ops.wm.save_mainfile()
- return ore_upload(self, context)
-
-class ORE_UseBlenderReso(bpy.types.Operator):
- bl_idname = "ore.use_scene_settings"
- bl_label = "Use Scene resolution"
-
- def execute(self, context):
- sce = context.scene
- ore = sce.ore_render
-
- ore.resox = sce.render.resolution_x
- ore.resoy = sce.render.resolution_y
-
- return {'FINISHED'}
-
-class ORE_ChangeUser(bpy.types.Operator):
- bl_idname = "ore.change_user"
- bl_label = "Change user"
-
- def execute(self, context):
- ore = context.scene.ore_render
- ore.password = ''
- ore.hash = ''
-
- return {'FINISHED'}
-
-class RenderfarmFi(bpy.types.RenderEngine):
- bl_idname = 'RENDERFARMFI_RENDER'
- bl_label = "Renderfarm.fi"
-
- def render(self, scene):
- print('Do test renders with Blender Render')
-
-def menu_export(self, context):
- import os
- default_path = os.path.splitext(bpy.data.filepath)[0] + ".py"
- self.layout.operator(RenderfarmFi.bl_idname, text=RenderfarmFi.bl_label)
-
-def register():
- bpy.types.INFO_MT_render.append(menu_export)
-
-def unregister():
- bpy.types.INFO_MT_render.remove(menu_export)
-
-if __name__ == "__main__":
- register()
diff --git a/space_view3d_align_tools.py b/space_view3d_align_tools.py
deleted file mode 100644
index 4ed56b35..00000000
--- a/space_view3d_align_tools.py
+++ /dev/null
@@ -1,338 +0,0 @@
-# AlingTools.py (c) 2009, 2010 Gabriel Beaudin (gabhead)
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Align Tools",
- "author": "Gabriel Beaudin (gabhead)",
- "version": (0,1),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "Tool Shelf",
- "description": "Align selected objects to the active object",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/3D interaction/Align_Tools",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid==22389&group_id=153&atid=468",
- "category": "3D View"}
-
-"""Align Selected Objects"""
-
-import bpy
-
-
-class AlignUi(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
-
- bl_label = "Align Tools"
- bl_context = "objectmode"
-
- def draw(self, context):
- layout = self.layout
- obj = context.object
-
- if obj != None:
- row = layout.row()
- row.label(text="Active object is: ", icon='OBJECT_DATA')
- row = layout.row()
- row.label(obj.name, icon='EDITMODE_HLT')
-
- box = layout.separator()
-
- col = layout.column()
- col.label(text="Align Loc + Rot:", icon='MANIPUL')
-
-
- col = layout.column(align=False)
- col.operator("object.AlignObjects",text="XYZ")
-
- col = layout.column()
- col.label(text="Align Location:", icon='MAN_TRANS')
-
- col = layout.column_flow(columns=5,align=True)
- col.operator("object.AlignObjectsLocationX",text="X")
- col.operator("object.AlignObjectsLocationY",text="Y")
- col.operator("object.AlignObjectsLocationZ",text="Z")
- col.operator("object.AlignObjectsLocationAll",text="All")
-
- col = layout.column()
- col.label(text="Align Rotation:", icon='MAN_ROT')
-
- col = layout.column_flow(columns=5,align=True)
- col.operator("object.AlignObjectsRotationX",text="X")
- col.operator("object.AlignObjectsRotationY",text="Y")
- col.operator("object.AlignObjectsRotationZ",text="Z")
- col.operator("object.AlignObjectsRotationAll",text="All")
-
- col = layout.column()
- col.label(text="Align Scale:", icon='MAN_SCALE')
-
- col = layout.column_flow(columns=5,align=True)
- col.operator("object.AlignObjectsScaleX",text="X")
- col.operator("object.AlignObjectsScaleY",text="Y")
- col.operator("object.AlignObjectsScaleZ",text="Z")
- col.operator("object.AlignObjectsScaleAll",text="All")
-
-
-##Align all
-def main(context):
- for i in bpy.context.selected_objects:
- i.location = bpy.context.active_object.location
- i.rotation_euler = bpy.context.active_object.rotation_euler
-
-## Align Location
-
-def LocAll(context):
- for i in bpy.context.selected_objects:
- i.location = bpy.context.active_object.location
-
-def LocX(context):
- for i in bpy.context.selected_objects:
- i.location.x = bpy.context.active_object.location.x
-
-def LocY(context):
- for i in bpy.context.selected_objects:
- i.location.y = bpy.context.active_object.location.y
-
-def LocZ(context):
- for i in bpy.context.selected_objects:
- i.location.z = bpy.context.active_object.location.z
-
-## Aling Rotation
-def RotAll(context):
- for i in bpy.context.selected_objects:
- i.rotation_euler = bpy.context.active_object.rotation_euler
-
-def RotX(context):
- for i in bpy.context.selected_objects:
- i.rotation_euler.x = bpy.context.active_object.rotation_euler.x
-
-def RotY(context):
- for i in bpy.context.selected_objects:
- i.rotation_euler.y = bpy.context.active_object.rotation_euler.y
-
-def RotZ(context):
- for i in bpy.context.selected_objects:
- i.rotation_euler.z = bpy.context.active_object.rotation_euler.z
-## Aling Scale
-def ScaleAll(context):
- for i in bpy.context.selected_objects:
- i.scale = bpy.context.active_object.scale
-
-def ScaleX(context):
- for i in bpy.context.selected_objects:
- i.scale.x = bpy.context.active_object.scale.x
-
-def ScaleY(context):
- for i in bpy.context.selected_objects:
- i.scale.y = bpy.context.active_object.scale.y
-
-def ScaleZ(context):
- for i in bpy.context.selected_objects:
- i.scale.z = bpy.context.active_object.scale.z
-
-## Classes
-
-## Align All Rotation And Location
-class AlignOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjects"
- bl_label = "Align Selected To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- main(context)
- return {'FINISHED'}
-
-#######################Align Location########################
-## Align LocationAll
-class AlignLocationOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsLocationAll"
- bl_label = "Align Selected Location To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- LocAll(context)
- return {'FINISHED'}
-## Align LocationX
-class AlignLocationXOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsLocationX"
- bl_label = "Align Selected Location X To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- LocX(context)
- return {'FINISHED'}
-## Align LocationY
-class AlignLocationYOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsLocationY"
- bl_label = "Align Selected Location Y To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- LocY(context)
- return {'FINISHED'}
-## Align LocationZ
-class AlignLocationZOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsLocationZ"
- bl_label = "Align Selected Location Z To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- LocZ(context)
- return {'FINISHED'}
-
-#######################Align Rotation########################
-## Align RotationAll
-class AlignRotationOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsRotationAll"
- bl_label = "Align Selected Rotation To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- RotAll(context)
- return {'FINISHED'}
-## Align RotationX
-class AlignRotationXOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsRotationX"
- bl_label = "Align Selected Rotation X To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- RotX(context)
- return {'FINISHED'}
-## Align RotationY
-class AlignRotationYOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsRotationY"
- bl_label = "Align Selected Rotation Y To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- RotY(context)
- return {'FINISHED'}
-## Align RotationZ
-class AlignRotationZOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsRotationZ"
- bl_label = "Align Selected Rotation Z To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- RotZ(context)
- return {'FINISHED'}
-#######################Align Scale########################
-## Scale All
-class AlignScaleOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsScaleAll"
- bl_label = "Align Selected Scale To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- ScaleAll(context)
- return {'FINISHED'}
-## Align ScaleX
-class AlignScaleXOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsScaleX"
- bl_label = "Align Selected Scale X To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- ScaleX(context)
- return {'FINISHED'}
-## Align ScaleY
-class AlignScaleYOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsScaleY"
- bl_label = "Align Selected Scale Y To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- ScaleY(context)
- return {'FINISHED'}
-## Align ScaleZ
-class AlignScaleZOperator(bpy.types.Operator):
- ''''''
- bl_idname = "object.AlignObjectsScaleZ"
- bl_label = "Align Selected Scale Z To Active"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- ScaleZ(context)
- return {'FINISHED'}
-
-## registring
-def register():
- pass
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()
diff --git a/space_view3d_materials_utils.py b/space_view3d_materials_utils.py
deleted file mode 100644
index 5d680eae..00000000
--- a/space_view3d_materials_utils.py
+++ /dev/null
@@ -1,689 +0,0 @@
-#(c) 2010 Michael Williamson (michaelw)
-#ported from original by Michael Williamsn
-#
-#tested r28370
-#
-#
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Material Utils",
- "author": "michaelw",
- "version": (1,3),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Q key",
- "description": "Menu of material tools (assign, select by etc) in the 3D View",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/3D interaction/Materials Utils",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22140&group_id=153&atid=469",
- "category": "3D View"}
-
-"""
-This script has several functions and operators... grouped for convenience
-* assign material:
- offers the user a list of ALL the materials in the blend file and an additional "new" entry
- the chosen material will be assigned to all the selected objects in object mode.
-
- in edit mode the selected faces get the selected material applied.
-
- if the user chose "new" the new material can be renamed using the "last operator" section of the toolbox
- After assigning the material "clean material slots" and "material to texface" are auto run to keep things tidy (see description bellow)
-
-
-* select by material
- in object mode this offers the user a menu of all materials in the blend file
- any objects using the selected material will become selected, any objects without the material will be removed from selection.
-
- in edit mode: the menu offers only the materials attached to the current object. It will select the faces that use the material and deselect those that do not.
-
-* clean material slots
- for all selected objects any empty material slots or material slots with materials that are not used by the mesh faces will be removed.
-
-* Any un-used materials and slots will be removed
-"""
-
-
-import bpy
-from bpy.props import*
-
-
-def replace_material(m1 , m2, all_objects = False):
- #replace material named m1 with material named m2
- #m1 is the name of original material
- #m2 is the name of the material to replace it with
- #'all' will replace throughout the blend file
- try:
- matorg = bpy.data.materials[m1]
- matrep = bpy.data.materials[m2]
-
-
- #store active object
- scn = bpy.context.scene
- ob_active = bpy.context.active_object
-
- if all_objects:
- objs = bpy.data.objects
-
- else:
- objs = bpy.context.selected_editable_objects
-
- for ob in objs:
- if ob.type == 'MESH':
- scn.objects.active = ob
- print(ob.name)
- ms = ob.material_slots.values()
-
- for m in ms:
- if m.material == matorg:
- m.material = matrep
- #don't break the loop as the material can be
- # ref'd more than once
-
- #restore active object
- scn.objects.active = ob_active
- except:
- print('no match to replace')
-
-def select_material_by_name(find_mat):
- #in object mode selects all objects with material find_mat
- #in edit mode selects all faces with material find_mat
-
- #check for editmode
- editmode = False
-
- scn = bpy.context.scene
- actob = bpy.context.active_object
- if actob.mode == 'EDIT':
- editmode =True
- bpy.ops.object.mode_set()
-
-
- if not editmode:
- objs = bpy.data.objects
- for ob in objs:
- if ob.type == 'MESH':
- ms = ob.material_slots.values()
- for m in ms:
- if m.material.name == find_mat:
- ob.select = True
- #the active object may not have the mat!
- #set it to one that does!
- scn.objects.active = ob
- break
- else:
- ob.select = False
-
- #deselect non-meshes
- else:
- ob.select = False
-
- else:
- #it's editmode, so select the faces
- ob = actob
- ms = ob.material_slots.values()
-
- #same material can be on multiple slots
- slot_indeces =[]
- i = 0
- found = False
- for m in ms:
- if m.material.name == find_mat:
- slot_indeces.append(i)
- found = True
- i += 1
- me = ob.data
- for f in me.faces:
- if f.material_index in slot_indeces:
- f.select = True
- else:
- f.select = False
- me.update
- if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-def mat_to_texface():
- #assigns the first image in each material to the faces in the active uvlayer
- #for all selected objects
-
- #check for editmode
- editmode = False
-
- actob = bpy.context.active_object
- if actob.mode == 'EDIT':
- editmode =True
- bpy.ops.object.mode_set()
-
- for ob in bpy.context.selected_editable_objects:
- #get the materials from slots
- ms = ob.material_slots.values()
-
- #build a list of images, one per material
- images=[]
- #get the textures from the mats
- for m in ms:
- gotimage = False
- textures = m.material.texture_slots.values()
- if len(textures) >= 1:
- for t in textures:
- if t != None:
- tex = t.texture
- if tex.type == 'IMAGE':
- img = tex.image
- images.append(img)
- gotimage =True
- break
-
- if not gotimage:
- print('noimage on', m.name)
- images.append(None)
-
- #now we have the images
- #applythem to the uvlayer
-
-
- me = ob.data
- #got uvs?
- if not me.uv_textures:
- scn = bpy.context.scene
- scn.objects.active = ob
- bpy.ops.mesh.uv_texture_add()
- scn.objects.active = actob
-
- #get active uvlayer
- for t in me.uv_textures:
- if t.active:
- uvtex = t.data.values()
- for f in me.faces:
- #check that material had an image!
- if images[f.material_index] != None:
- uvtex[f.index].image = images[f.material_index]
- uvtex[f.index].use_image = True
- else:
- uvtex[f.index].use_image = False
-
- me.update()
-
-
- if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
-
-def assignmatslots(ob, matlist):
- #given an object and a list of material names
- #removes all material slots form the object
- #adds new ones for each material in matlist
- #adds the materials to the slots as well.
-
- scn = bpy.context.scene
- ob_active = bpy.context.active_object
- scn.objects.active = ob
-
- for s in ob.material_slots:
- bpy.ops.object.material_slot_remove()
-
-
- #re-add them and assign material
- i = 0
- for m in matlist:
- mat = bpy.data.materials[m]
- bpy.ops.object.material_slot_add()
- ob.material_slots.values()[i].material = mat
- i += 1
-
- #restore active object:
- scn.objects.active = ob_active
-
-
-def cleanmatslots():
- #check for edit mode
- editmode = False
- actob = bpy.context.active_object
- if actob.mode == 'EDIT':
- editmode =True
- bpy.ops.object.mode_set()
-
-
- objs = bpy.context.selected_editable_objects
-
- for ob in objs:
- print(ob.name)
- mats = ob.material_slots.keys()
-
- #check the faces on the mesh to build a list of used materials
- usedMatIndex =[] #we'll store used materials indices here
- faceMats =[]
- me = ob.data
- for f in me.faces:
- #get the material index for this face...
- faceindex = f.material_index
-
- #indices will be lost: Store face mat use by name
- currentfacemat = mats[faceindex]
- faceMats.append(currentfacemat)
-
-
- #check if index is already listed as used or not
- found = 0
- for m in usedMatIndex:
- if m == faceindex:
- found = 1
- #break
-
- if found == 0:
- #add this index to the list
- usedMatIndex.append(faceindex)
-
- #re-assign the used mats to the mesh and leave out the unused
- ml = []
- mnames = []
- for u in usedMatIndex:
- ml.append( mats[u] )
- #we'll need a list of names to get the face indices...
- mnames.append(mats[u])
-
- assignmatslots(ob, ml)
-
-
- #restore face indices:
- i = 0
- for f in me.faces:
- matindex = mnames.index(faceMats[i])
- f.material_index = matindex
- i += 1
- print('Done')
- if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
-
-
-
-def assign_mat(matname="Default"):
- #get active object so we can restore it later
- actob = bpy.context.active_object
-
- #check if material exists, if it doesn't then create it
- mats =bpy.data.materials
- found = False
- for m in mats:
- if m.name == matname:
- target = m
- found = True
- break
- if not found:
- target = bpy.data.materials.new(matname)
-
-
- #if objectmodeset all faces
- editmode = False
- allfaces = True
- if actob.mode == 'EDIT':
- editmode =True
- allfaces = False
- bpy.ops.object.mode_set()
-
- objs = bpy.context.selected_editable_objects
-
- for ob in objs:
- #set the active object to our object
- scn = bpy.context.scene
- scn.objects.active = ob
-
-
- #check if the material is on the object already
- if ob.type =='MESH':
- #check material slots for matname material
- found=False
- i = 0
- mats = ob.material_slots
- for m in mats:
- if m.name == matname:
- found =True
- index = i
- #make slot active
- ob.active_material_index = i
- break
- i += 1
-
- if not found:
- index=i
- #the material is not attached to the object
- #so attach it!
-
- #add a material slot
- bpy.ops.object.material_slot_add()
-
- #make slot active
- ob.active_material_index = i
-
- #and assign material to slot
- ob.material_slots.values()[i].material = target
- #now assign the material:
- me =ob.data
- if allfaces:
- for f in me.faces:
- f.material_index = index
- elif allfaces == False:
- for f in me.faces:
- if f.select:
- f.material_index = index
- me.update
-
- #restore the active object
- bpy.context.scene.objects.active = actob
- if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
-
-def check_texture(img,mat):
- #finds a texture from an image
- #makes a texture if needed
- #adds it to the material if it isn't there already
-
- tex = bpy.data.textures.get(img.name)
-
- if tex is None:
- tex = bpy.data.textures.new(name=img.name, type='IMAGE')
-
- tex.image = img
-
- #see if the material already uses this tex
- #add it if needed
- found = False
- for m in mat.texture_slots:
- if m and m.texture == tex:
- found = True
- break
- if not found and mat:
- mtex = mat.texture_slots.add()
- mtex.texture = tex
- mtex.texture_coords = 'UV'
- mtex.use_map_color_diffuse = True
-
-def texface_to_mat():
- # editmode check here!
- editmode = False
- ob = bpy.context.object
- if ob.mode =='EDIT':
- editmode = True
- bpy.ops.object.mode_set()
-
- for ob in bpy.context.selected_editable_objects:
-
- faceindex = []
- unique_images = []
-
- # get the texface images and store indices
- if (ob.data.uv_textures):
- for f in ob.data.uv_textures.active.data:
- if f.image:
- img = f.image
- #build list of unique images
- if img not in unique_images:
- unique_images.append(img)
- faceindex.append(unique_images.index(img))
-
- else:
- img = None
- faceindex.append(None)
-
-
-
- #check materials for images exist; create if needed
- matlist = []
- for i in unique_images:
- if i:
- print(i.name)
- try:
- m = bpy.data.materials[i.name]
-
- except:
- m = bpy.data.materials.new(name = i.name)
- continue
-
- finally:
- matlist.append(m.name)
- # add textures if needed
- check_texture(i,m)
-
- #set up the object material slots
- assignmatslots(ob, matlist)
-
- #set texface indices to material slot indices..
- me = ob.data
-
- i = 0
- for f in faceindex:
- if f != None:
- me.faces[i].material_index = f
- i += 1
- if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
-#operator classes:
-#---------------------------------------------------------------------
-
-class VIEW3D_OT_texface_to_material(bpy.types.Operator):
- ''''''
- bl_idname = "texface_to_material"
- bl_label = "MW Texface Images to Material/Texture"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- if context.selected_editable_objects:
- texface_to_mat()
- return {'FINISHED'}
- else:
- self.report({'WARNING'}, "No editable selected objects, could not finish")
- return {'CANCELLED'}
-
-class VIEW3D_OT_assign_material(bpy.types.Operator):
- '''assign a material to the selection'''
- bl_idname = "assign_material"
- bl_label = "MW Assign Material"
- bl_options = {'REGISTER', 'UNDO'}
-
- matname = StringProperty(name = 'Material Name',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- mn = self.properties.matname
- print(mn)
- assign_mat(mn)
- cleanmatslots()
- mat_to_texface()
- return {'FINISHED'}
-
-class VIEW3D_OT_clean_material_slots(bpy.types.Operator):
- '''removes any material slots from the
- selected objects that are not used by the mesh'''
- bl_idname = "clean_material_slots"
- bl_label = "MW Clean Material Slots"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- cleanmatslots()
- return {'FINISHED'}
-
-class VIEW3D_OT_material_to_texface(bpy.types.Operator):
- ''''''
- bl_idname = "material_to_texface"
- bl_label = "MW Material Images to Texface"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- mat_to_texface()
- return {'FINISHED'}
-
-class VIEW3D_OT_select_material_by_name(bpy.types.Operator):
- ''''''
- bl_idname = "select_material_by_name"
- bl_label = "MW Select Material By Name"
- bl_options = {'REGISTER', 'UNDO'}
- matname = StringProperty(name = 'Material Name',
- description = 'Name of Material to Select',
- default = "", maxlen = 21)
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- mn = self.properties.matname
- select_material_by_name(mn)
- return {'FINISHED'}
-
-
-class VIEW3D_OT_replace_material(bpy.types.Operator):
- '''assign a material to the selection'''
- bl_idname = "replace_material"
- bl_label = "MW Replace Material"
- bl_options = {'REGISTER', 'UNDO'}
-
- matorg = StringProperty(name = 'Material to Replace',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
-
- matrep = StringProperty(name = 'Replacement material',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
-
- all_objects = BoolProperty(name ='all_objects',
- description="replace for all objects in this blend file",
- default = True)
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- m1 = self.properties.matorg
- m2 = self.properties.matrep
- all = self.properties.all_objects
- replace_material(m1,m2,all)
- return {'FINISHED'}
-
-#menu classes
-#-------------------------------------------------------------------------------
-class VIEW3D_MT_master_material(bpy.types.Menu):
- bl_label = "Master Material Menu"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.menu("VIEW3D_MT_assign_material", icon='ZOOMIN')
- layout.menu("VIEW3D_MT_select_material", icon='HAND')
- layout.separator()
- layout.operator("clean_material_slots",
- text = 'Clean Material Slots', icon='CANCEL')
- layout.operator("material_to_texface",
- text = 'Material to Texface',icon='FACESEL_HLT')
- layout.operator("texface_to_material",
- text = 'Texface to Material',icon='FACESEL_HLT')
-
- layout.separator()
- layout.operator("replace_material",
- text = 'Replace Material', icon='ARROW_LEFTRIGHT')
-
-
-
-class VIEW3D_MT_assign_material(bpy.types.Menu):
- bl_label = "Assign Material"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- ob = context
- layout.label
- for i in range (len(bpy.data.materials)):
-
- layout.operator("assign_material",
- text=bpy.data.materials[i].name,
- icon='MATERIAL_DATA').matname = bpy.data.materials[i].name
-
- layout.operator("assign_material",text="Add New",
- icon='ZOOMIN')
-
-class VIEW3D_MT_select_material(bpy.types.Menu):
- bl_label = "Select by Material"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- ob = context.object
- layout.label
- if ob.mode == 'OBJECT':
- #show all materials in entire blend file
- for i in range (len(bpy.data.materials)):
-
- layout.operator("select_material_by_name",
- text=bpy.data.materials[i].name,
- icon='MATERIAL_DATA').matname = bpy.data.materials[i].name
-
-
- elif ob.mode == 'EDIT':
- #show only the materials on this object
- mats = ob.material_slots.keys()
- for m in mats:
- layout.operator("select_material_by_name",
- text=m,
- icon='MATERIAL_DATA').matname = m
-
-
-def register():
- km = bpy.context.window_manager.keyconfigs.active.keymaps['3D View']
- kmi = km.items.new('wm.call_menu', 'Q', 'PRESS')
- kmi.properties.name = "VIEW3D_MT_master_material"
-
-def unregister():
- km = bpy.context.window_manager.keyconfigs.active.keymaps['3D View']
- for kmi in km.items:
- if kmi.idname == 'wm.call_menu':
- if kmi.properties.name == "VIEW3D_MT_master_material":
- km.items.remove(kmi)
- break
-
-if __name__ == "__main__":
- register()
diff --git a/space_view3d_panel_measure.py b/space_view3d_panel_measure.py
deleted file mode 100644
index c5df0a03..00000000
--- a/space_view3d_panel_measure.py
+++ /dev/null
@@ -1,1065 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Measure Panel",
- "author": "Buerbaum Martin (Pontiac)",
- "version": (0, 7, 9),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Properties > Measure",
- "description": "Measure distances between objects",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/" \
- "Scripts/3D_interaction/Panel_Measure",
- "tracker_url": "https://projects.blender.org/tracker/index.php?" \
- "func=detail&aid=21445&group_id=153&atid=469",
- "category": "3D View"}
-
-"""
-Measure panel
-
-This script displays in OBJECT MODE:
-* The distance of the 3D cursor to the origin of the
- 3D space (if NOTHING is selected).
-* The distance of the 3D cursor to the center of an object
- (if exactly ONE object is selected).
-* The distance between 2 object centers
- (if exactly TWO objects are selected).
-* The surface area of any selected mesh object.
-
-Display in EDIT MODE (Local and Global space supported):
-* The distance of the 3D cursor to the origin
- (in Local space it is the object center instead).
-* The distance of the 3D cursor to a selected vertex.
-* The distance between 2 selected vertices.
-
-Usage:
-
-This functionality can be accessed via the
-"Properties" panel in 3D View ([N] key).
-
-It's very helpful to use one or two "Empty" objects with
-"Snap during transform" enabled for fast measurement.
-
-Version history:
-v0.7.9 - Updated scene properties for changes in property API.
- See http://lists.blender.org/pipermail/bf-committers/
- 2010-September/028654.html
- Synced API changes in7from local copy.
-v0.7.8 - Various Py API changes by Campbell ...
- bl_default_closed -> bl_options = {'DEFAULT_CLOSED'}
- x.verts -> x.vertices
- @classmethod def poll(cls, context)
- No "location" in bl_addon_info->name
- bl_addon_info->api
-v0.7.7 - One more change to the callback registration code.
- Now it should finally work as intended.
-v0.7.6 - API changes (r885, r886) - register & unregister function
-v0.7.5.3 - Small fix for bug in v0.7.5.1
- (location was off when object was moved)
-v0.7.5.2 - Changed callback registration back to original code &
- fixed bug in there (use bl_idname instead of bl_label)
-v0.7.5.1 - Global mode is now taking rotation into account properly.
-v0.7.5 - Fixed lagging and drawing issues.
-v0.7.4 - Fixed the add_modal_handler and callback_add code.
- Thanks to jesterKing for pointing that out :-)
-v0.7.3.1 - Fixed bug that made all lines in Blender stippled :-)
-v0.7.3 - Added display of delta x/y/z value in 3d view.
- * Inspired by warpi's patch here:
- http://blenderartists.org/forum/showpost.php?p=1671033&postcount=47
- * Also added display of dx,dy,dz lines
- * Changed the "dist" colors to something not already used
- by x/y/z axes.
-v0.7.2 - Merged changes from trunk (scripts_addons r847):
- * obj.matrix -> obj.matrix_world
- * vert.selected -> vert.select
- * face.selected -> face.select
- * bl_addon_info: warning, wiki_url, tracker_url
- * removed __bpydoc__
- * Use fontid=0 for blf functions. 0 is the default font.
-v0.7.1 - Merged changes by Campbell:
- * Fix for API change: Collections like context.selected_objects
- no longer return None for empty lists.
- * Update for mathutils, also stripped some redundant
- conversions (Mostly "Vector()" stuff)
-v0.7 - Initial support for drawing lines.
- (Thanks to Algorith for applying my perspective_matrix patch.)
- The distance value (in BUs) is also drawn in the 3D view now.
- Also fixed some wrong calculations of global/local distances.
- Now it's really "what you see is what is calculated".
- Use bl_addon_info for Add-On information.
- Use "3D View" in category & name
- Renamed reenter_editmode to view3d.reenter_editmode.
- Renamed panel_measure.py into space_view3d_panel_measure.py
- Active object is only used for edit-mode now. Measurement
- with exactly one sel. (but not necessarily active) object
- now gets the obj via the sel-object array.
- API change Mathutils -> mathutils (r557)
- Deselecting 1 of 2 objects now works correctly (active object is ignored).
- Force a redraw of the area so disabling the "measure_panel_draw"
- checkbox will clear the line/text.
- Only calculate area (CPU heavy) if a "area" checkbox is enabled.
-v0.6.4 - Fixed unneeded meshdata duplication (sometimes crashes Blender).
- The script now correctly calculated the surface area (faceAreaGlobal)
- of scaled meshes.
- http://projects.blender.org/tracker/
- ?func=detail&atid=453&aid=21913&group_id=153
-v0.6.3 - Added register & unregister functions.
-v0.6.2 - Fixed precision of second area property.
- Reduced display precision to 5 (instead of 6).
- Added (commented out code) for shortcut [F5] for
- updating EditMode selection & calculation.
- Changed the script so it can be managed from the "Add-Ons" tab
- in the user preferences.
- Corrected FSF address.
-v0.6.1 - Updated reenter_editmode operator description.
- Fixed search for selected mesh objects.
- Added "BU^2" after values that are not yet translated via "unit".
-v0.6
- *) Fix: Removed EditMode/ObjectMode toggle stuff. This causes all the
- crashes and is generally not stable.
- Instead I've added a manual "refresh" button.
- I registered a new operator OBJECT_OT_reenter_editmode for this.
- *) Use "unit" settings (i.e. none/metric/imperial)
- *) Fix: Only display surface area (>=3 objects) if return value is >=0.
- *) Minor: Renamed objectFaceArea to objectSurfaceArea
- *) Updated Vector() and tuple() usage.
- *) Fixed some comments.
-v0.5 - Global surface area (object mode) is now calculated as well.
- Support area calculation for face selection.
- Also made measurement panel closed by default. (Area calculation
- may use up a lot of CPU/RAM in extreme cases)
-v0.4.1 - Various cleanups.
- Using the shorter "scene" instead of "context.scene"
- New functions measureGlobal() and measureLocal() for
- user-friendly access to the "space" setting.
-v0.4 - Calculate & display the surface area of mesh
- objects (local space only right now).
- Expanded global/local switch.
- Made "local" option for 3Dcursor-only in edit mode actually work.
- Fixed local/global calculation for 3Dcursor<->vertex in edit mode.
-v0.3.2 - Fixed calculation & display of local/global coordinates.
- The user can now select via dropdown which space is wanted/needed
- Basically this is a bugfix and new feature at the same time :-)
-v0.3.1 - Fixed bug where "measure_panel_dist" wasn't defined
- before it was used.
- Also added the distance calculation "origin -> 3D cursor" for edit mode.
-v0.3 - Support for mesh edit mode (1 or 2 selected vertices)
-v0.2.1 - Small fix (selecting nothing didn't calculate the distance
- of the cursor from the origin anymore)
-v0.2 - Distance value is now displayed via a FloatProperty widget (and
- therefore saved to file too right now [according to ideasman42].
- The value is save inside the scene right now.)
- Thanks goes to ideasman42 (Campbell Barton) for helping me out on this.
-v0.1 - Initial revision. Seems to work fine for most purposes.
-
-More links:
-http://gitorious.org/blender-scripts/blender-measure-panel-script
-http://blenderartists.org/forum/showthread.php?t=177800
-"""
-
-import bpy
-from bpy.props import *
-from mathutils import Vector, Matrix
-import bgl
-import blf
-
-
-# Precicion for display of float values.
-PRECISION = 4
-
-# Name of the custom properties as stored in the scene.
-COLOR_LOCAL = (1.0, 0.5, 0.0, 0.8)
-COLOR_GLOBAL = (0.5, 0.0, 1.0, 0.8)
-
-
-# Returns a single selected object.
-# Returns None if more than one (or nothing) is selected.
-# Note: Ignores the active object.
-def getSingleObject(context):
- if len(context.selected_objects) == 1:
- return context.selected_objects[0]
-
- return None
-
-
-# Returns a list with 2 3D points (Vector) and a color (RGBA)
-# depending on the current view mode and the selection.
-def getMeasurePoints(context):
- sce = context.scene
-
- # Get a single selected object (or nothing).
- obj = getSingleObject(context)
-
- if (context.mode == 'EDIT_MESH'):
- obj = context.active_object
-
- if (obj and obj.type == 'MESH' and obj.data):
- # Get mesh data from Object.
- mesh = obj.data
-
- # Get transformation matrix from object.
- ob_mat = obj.matrix_world
- # Also make an inversed copy! of the matrix.
- ob_mat_inv = ob_mat.copy().invert()
- # And a transposed one...
- ob_mat_trans = ob_mat.copy().transpose()
-
- # Get the selected vertices.
- # @todo: Better (more efficient) way to do this?
- verts_selected = [v for v in mesh.vertices if v.select == 1]
-
- if len(verts_selected) == 0:
- # Nothing selected.
- # We measure the distance from...
- # local ... the object center to the 3D cursor.
- # global ... the origin to the 3D cursor.
- cur_loc = sce.cursor_location
- obj_loc = obj.location.copy()
-
- # Convert to local space, if needed.
- if measureLocal(sce):
- p1 = cur_loc
- p2 = obj_loc
- return (p1, p2, COLOR_GLOBAL)
-
- else:
- p1 = Vector((0.0, 0.0, 0.0))
- p2 = cur_loc
- return (p1, p2, COLOR_GLOBAL)
-
- elif len(verts_selected) == 1:
- # One vertex selected.
- # We measure the distance from the
- # selected vertex object to the 3D cursor.
- cur_loc = sce.cursor_location
- vert_loc = verts_selected[0].co.copy()
- obj_loc = obj.location.copy()
-
- # Convert to local or global space.
- if measureLocal(sce):
- p1 = obj_loc + vert_loc
- p2 = cur_loc
- return (p1, p2, COLOR_LOCAL)
-
- else:
- p1 = vert_loc * ob_mat_trans
- p2 = cur_loc
- return (p1, p2, COLOR_GLOBAL)
-
- elif len(verts_selected) == 2:
- # Two vertices selected.
- # We measure the distance between the
- # two selected vertices.
- obj_loc = obj.location.copy()
- vert1_loc = verts_selected[0].co.copy()
- vert2_loc = verts_selected[1].co.copy()
-
- # Convert to local or global space.
- if measureLocal(sce):
- p1 = obj_loc + vert1_loc
- p2 = obj_loc + vert2_loc
- return (p1, p2, COLOR_LOCAL)
-
- else:
- p1 = vert1_loc * ob_mat_trans
- p2 = vert2_loc * ob_mat_trans
- return (p1, p2, COLOR_GLOBAL)
-
- else:
- return None
-
- elif (context.mode == 'OBJECT'):
- # We are working on object mode.
-
- if len(context.selected_objects) > 2:
- return None
- elif len(context.selected_objects) == 2:
- # 2 objects selected.
- # We measure the distance between the 2 selected objects.
- obj1, obj2 = context.selected_objects
- obj1_loc = obj1.location.copy()
- obj2_loc = obj2.location.copy()
- return (obj1_loc, obj2_loc, COLOR_GLOBAL)
-
- elif (obj):
- # One object selected.
- # We measure the distance from the object to the 3D cursor.
- cur_loc = sce.cursor_location
- obj_loc = obj.location.copy()
- return (obj_loc, cur_loc, COLOR_GLOBAL)
-
- elif not context.selected_objects:
- # Nothing selected.
- # We measure the distance from the origin to the 3D cursor.
- p1 = Vector((0.0, 0.0, 0.0))
- p2 = sce.cursor_location
- return (p1, p2, COLOR_GLOBAL)
-
- else:
- return None
-
-
-# Return the area of a face (in global space).
-# @note Copies the functionality of the following functions,
-# but also respects the scaling (via the "obj.matrix_world" parameter):
-# @sa: rna_mesh.c:rna_MeshFace_area_get
-# @sa: math_geom.c:area_quad_v3
-# @sa: math_geom.c:area_tri_v3
-def faceAreaGlobal(face, obj):
- area = 0.0
-
- mat = obj.matrix_world
-
- if len(face.vertices) == 4:
- # Quad
-
- # Get vertex indices
- v1, v2, v3, v4 = face.vertices
-
- # Get vertex data
- v1 = obj.data.vertices[v1]
- v2 = obj.data.vertices[v2]
- v3 = obj.data.vertices[v3]
- v4 = obj.data.vertices[v4]
-
- # Apply transform matrix to vertex coordinates.
- v1 = v1.co * mat
- v2 = v2.co * mat
- v3 = v3.co * mat
- v4 = v4.co * mat
-
- vec1 = v2 - v1
- vec2 = v4 - v1
-
- n = vec1.cross(vec2)
-
- area = n.length / 2.0
-
- vec1 = v4 - v3
- vec2 = v2 - v3
-
- n = vec1.cross(vec2)
-
- area += n.length / 2.0
-
- elif len(face.vertices) == 3:
- # Triangle
-
- # Get vertex indices
- v1, v2, v3 = face.vertices
-
- # Get vertex data
- v1 = obj.data.vertices[v1]
- v2 = obj.data.vertices[v2]
- v3 = obj.data.vertices[v3]
-
- # Apply transform matrix to vertex coordinates.
- v1 = v1.co * mat
- v2 = v2.co * mat
- v3 = v3.co * mat
-
- vec1 = v3 - v2
- vec2 = v1 - v2
-
- n = vec1.cross(vec2)
-
- area = n.length / 2.0
-
- return area
-
-
-# Calculate the surface area of a mesh object.
-# *) Set selectedOnly=1 if you only want to count selected faces.
-# *) Set globalSpace=1 if you want to calculate
-# the global surface area (object mode).
-# Note: Be sure you have updated the mesh data before
-# running this with selectedOnly=1!
-# @todo Support other object types (surfaces, etc...)?
-def objectSurfaceArea(obj, selectedOnly, globalSpace):
- if (obj and obj.type == 'MESH' and obj.data):
- areaTotal = 0
-
- mesh = obj.data
-
- # Count the area of all the faces.
- for face in mesh.faces:
- if not selectedOnly or face.select:
- if globalSpace:
- areaTotal += faceAreaGlobal(face, obj)
- else:
- areaTotal += face.area
-
- return areaTotal
-
- # We can not calculate an area for this object.
- return -1
-
-
-# User friendly access to the "space" setting.
-def measureGlobal(sce):
- return (sce.measure_panel_transform == "measure_global")
-
-
-# User friendly access to the "space" setting.
-def measureLocal(sce):
- return (sce.measure_panel_transform == "measure_local")
-
-
-# Converts 3D coordinates in a 3DRegion
-# into 2D screen coordinates for that region.
-def region3d_get_2d_coordinates(context, loc_3d):
- # Get screen information
- mid_x = context.region.width / 2.0
- mid_y = context.region.height / 2.0
- width = context.region.width
- height = context.region.height
-
- # Get matrices
- view_mat = context.space_data.region_3d.perspective_matrix
- total_mat = view_mat
-
- # order is important
- vec = total_mat * Vector((loc_3d[0], loc_3d[1], loc_3d[2], 1.0))
-
- # dehomogenise
- vec = Vector((
- vec[0] / vec[3],
- vec[1] / vec[3],
- vec[2] / vec[3]))
-
- x = int(mid_x + vec[0] * width / 2.0)
- y = int(mid_y + vec[1] * height / 2.0)
-
- return Vector((x, y, 0))
-
-
-def draw_measurements_callback(self, context):
- sce = context.scene
-
- draw = 0
- if hasattr(sce, "measure_panel_draw"):
- draw = sce.measure_panel_draw
-
- # 2D drawing code example
- #bgl.glBegin(bgl.GL_LINE_STRIP)
- #bgl.glVertex2i(0, 0)
- #bgl.glVertex2i(80, 100)
- #bgl.glEnd()
-
- # Get measured 3D points and colors.
- line = getMeasurePoints(context)
- if (line and draw):
- p1, p2, color = line
-
- # Get and convert the Perspective Matrix of the current view/region.
- view3d = bpy.context.space_data
- region = view3d.region_3d
- perspMatrix = region.perspective_matrix
- tempMat = [perspMatrix[i][j] for i in range(4) for j in range(4)]
- perspBuff = bgl.Buffer(bgl.GL_FLOAT, 16, tempMat)
-
- # ---
- # Store previous OpenGL settings.
- # Store MatrixMode
- MatrixMode_prev = bgl.Buffer(bgl.GL_INT, [1])
- bgl.glGetIntegerv(bgl.GL_MATRIX_MODE, MatrixMode_prev)
- MatrixMode_prev = MatrixMode_prev[0]
-
- # Store projection matrix
- ProjMatrix_prev = bgl.Buffer(bgl.GL_DOUBLE, [16])
- bgl.glGetFloatv(bgl.GL_PROJECTION_MATRIX, ProjMatrix_prev)
-
- # Store Line width
- lineWidth_prev = bgl.Buffer(bgl.GL_FLOAT, [1])
- bgl.glGetFloatv(bgl.GL_LINE_WIDTH, lineWidth_prev)
- lineWidth_prev = lineWidth_prev[0]
-
- # Store GL_BLEND
- blend_prev = bgl.Buffer(bgl.GL_BYTE, [1])
- bgl.glGetFloatv(bgl.GL_BLEND, blend_prev)
- blend_prev = blend_prev[0]
-
- line_stipple_prev = bgl.Buffer(bgl.GL_BYTE, [1])
- bgl.glGetFloatv(bgl.GL_LINE_STIPPLE, line_stipple_prev)
- line_stipple_prev = line_stipple_prev[0]
-
- # Store glColor4f
- color_prev = bgl.Buffer(bgl.GL_FLOAT, [4])
- bgl.glGetFloatv(bgl.GL_COLOR, color_prev)
-
- # ---
- # Prepare for 3D drawing
- bgl.glLoadIdentity()
- bgl.glMatrixMode(bgl.GL_PROJECTION)
- bgl.glLoadMatrixf(perspBuff)
-
- bgl.glEnable(bgl.GL_BLEND)
- bgl.glEnable(bgl.GL_LINE_STIPPLE)
-
- # ---
- # Draw 3D stuff.
- width = 1
- bgl.glLineWidth(width)
- # X
- bgl.glColor4f(1, 0, 0, 0.8)
- bgl.glBegin(bgl.GL_LINE_STRIP)
- bgl.glVertex3f(p1[0], p1[1], p1[2])
- bgl.glVertex3f(p2[0], p1[1], p1[2])
- bgl.glEnd()
- # Y
- bgl.glColor4f(0, 1, 0, 0.8)
- bgl.glBegin(bgl.GL_LINE_STRIP)
- bgl.glVertex3f(p1[0], p1[1], p1[2])
- bgl.glVertex3f(p1[0], p2[1], p1[2])
- bgl.glEnd()
- # Z
- bgl.glColor4f(0, 0, 1, 0.8)
- bgl.glBegin(bgl.GL_LINE_STRIP)
- bgl.glVertex3f(p1[0], p1[1], p1[2])
- bgl.glVertex3f(p1[0], p1[1], p2[2])
- bgl.glEnd()
-
- # Dist
- width = 2
- bgl.glLineWidth(width)
- bgl.glColor4f(color[0], color[1], color[2], color[3])
- bgl.glBegin(bgl.GL_LINE_STRIP)
- bgl.glVertex3f(p1[0], p1[1], p1[2])
- bgl.glVertex3f(p2[0], p2[1], p2[2])
- bgl.glEnd()
-
- # ---
- # Restore previous OpenGL settings
- bgl.glLoadIdentity()
- bgl.glMatrixMode(MatrixMode_prev)
- bgl.glLoadMatrixf(ProjMatrix_prev)
- bgl.glLineWidth(lineWidth_prev)
- if not blend_prev:
- bgl.glDisable(bgl.GL_BLEND)
- if not line_stipple_prev:
- bgl.glDisable(bgl.GL_LINE_STIPPLE)
- bgl.glColor4f(color_prev[0],
- color_prev[1],
- color_prev[2],
- color_prev[3])
-
- # ---
- # Draw (2D) text
- # We do this after drawing the lines so
- # we can draw it OVER the line.
- coord_2d = region3d_get_2d_coordinates(context, p2 + (p1 - p2) * 0.5)
- OFFSET_LINE = 10 # Offset the text a bit to the right.
- OFFSET_Y = 15 # Offset of the lines.
- OFFSET_VALUE = 30 # Offset of value(s) from the text.
- dist = (p1 - p2).length
-
- texts = [("Dist:", round(dist, PRECISION)),
- ("X:", round(abs(p1[0] - p2[0]), PRECISION)),
- ("Y:", round(abs(p1[1] - p2[1]), PRECISION)),
- ("Z:", round(abs(p1[2] - p2[2]), PRECISION))]
-
- # Draw all texts
- # @todo Get user pref for text color in 3D View
- bgl.glColor4f(1.0, 1.0, 1.0, 1.0)
- blf.size(0, 12, 72) # Prevent font size to randomly change.
-
- loc_x = coord_2d[0] + OFFSET_LINE
- loc_y = coord_2d[1]
- for t in texts:
- text = t[0]
- value = str(t[1]) + " BU"
-
- blf.position(0, loc_x, loc_y, 0)
- blf.draw(0, text)
- blf.position(0, loc_x + OFFSET_VALUE, loc_y, 0)
- blf.draw(0, value)
-
- loc_y -= OFFSET_Y
-
-
-class VIEW3D_OT_display_measurements(bpy.types.Operator):
- '''Display the measurements made in the 'Measure' panel'''
- # Do not use bl_idname here (class name is used instead),
- # so the callback can be added easily.
- #bl_idname = "view3d.display_measurements"
- bl_label = "Display the measurements made in the" \
- " 'Measure' panel in the 3D View."
- bl_options = {'REGISTER'}
-
- def modal(self, context, event):
- context.area.tag_redraw()
-
- return {'FINISHED'}
-
- def execute(self, context):
- if context.area.type == 'VIEW_3D':
- mgr_ops = context.window_manager.operators.values()
- if not self.bl_idname in [op.bl_idname for op in mgr_ops]:
- # Add the region OpenGL drawing callback
- for WINregion in context.area.regions:
- if WINregion.type == 'WINDOW':
- context.window_manager.add_modal_handler(self)
- self._handle = WINregion.callback_add(
- draw_measurements_callback,
- (self, context),
- 'POST_PIXEL')
-
- print("Measure panel display callback added")
-
- return {'RUNNING_MODAL'}
-
- return {'CANCELLED'}
-
- else:
- self.report({'WARNING'}, "View3D not found, cannot run operator")
- return {'CANCELLED'}
-
-
-class VIEW3D_OT_reenter_editmode(bpy.types.Operator):
- bl_label = "Re-enter EditMode"
- bl_idname = "view3d.reenter_editmode"
- bl_description = "Update mesh data of an active mesh object." \
- " This is done by exiting and re-entering mesh edit mode."
- bl_options = {'REGISTER'}
-
- def invoke(self, context, event):
-
- # Get the active object.
- obj = context.active_object
-
- if (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH'):
- # Exit and re-enter mesh EditMode.
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='EDIT')
- return {'FINISHED'}
-
- return {'CANCELLED'}
-
-
-class VIEW3D_PT_measure(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Measure"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- # Only display this panel in the object and edit mode 3D view.
- if (context.area.type == 'VIEW_3D' and
- (context.mode == 'EDIT_MESH'
- or context.mode == 'OBJECT')):
- return 1
-
- return 0
-
- def draw_header(self, context):
- layout = self.layout
- sce = context.scene
-
- # Force a redraw.
- # This prevents the lines still be drawn after
- # disabling the "measure_panel_draw" checkbox.
- # @todo Better solution?
- context.area.tag_redraw()
-
- # Execute operator (this adds the callback)
- # if it wasn't done yet.
- bpy.ops.view3d.display_measurements()
-
- # Define property for the draw setting.
- bpy.types.Scene.measure_panel_draw = bpy.props.BoolProperty(
- description="Draw distances in 3D View",
- default=1)
-
- # Define property for the calc-area setting.
- # @todo prevent double calculations for each refresh automatically?
- bpy.types.Scene.measure_panel_calc_area = bpy.props.BoolProperty(
- description="Calculate mesh surface area (heavy CPU" \
- " usage on bigger meshes)",
- default=0)
-
- layout.prop(sce, "measure_panel_draw")
-
- def draw(self, context):
- layout = self.layout
- sce = context.scene
-
- # Get a single selected object (or nothing).
- obj = getSingleObject(context)
-
- # Define a temporary attribute for the distance value
- bpy.types.Scene.measure_panel_dist = bpy.props.FloatProperty(
- name="Distance",
- attr="measure_panel_dist",
- precision=PRECISION,
- unit="LENGTH")
- bpy.types.Scene.measure_panel_area1 = bpy.props.FloatProperty(
- attr="measure_panel_area1",
- precision=PRECISION,
- unit="AREA")
- bpy.types.Scene.measure_panel_area2 = bpy.props.FloatProperty(
- attr="measure_panel_area2",
- precision=PRECISION,
- unit="AREA")
-
- TRANSFORM = [
- ("measure_global", "Global",
- "Calculate values in global space."),
- ("measure_local", "Local",
- "Calculate values inside the local object space.")]
-
- # Define dropdown for the global/local setting
- bpy.types.Scene.measure_panel_transform = bpy.props.EnumProperty(
- name="Space",
- description="Choose in which space you want to measure.",
- items=TRANSFORM,
- default='measure_global')
-
- if (context.mode == 'EDIT_MESH'):
- obj = context.active_object
-
- if (obj and obj.type == 'MESH' and obj.data):
- # "Note: a Mesh will return the selection state of the mesh
- # when EditMode was last exited. A Python script operating
- # in EditMode must exit EditMode before getting the current
- # selection state of the mesh."
- # http://www.blender.org/documentation/249PythonDoc/
- # /Mesh.MVert-class.html#sel
- # We can only provide this by existing & re-entering EditMode.
- # @todo: Better way to do this?
-
- # Get mesh data from Object.
- mesh = obj.data
-
- # Get transformation matrix from object.
- ob_mat = obj.matrix_world
- # Also make an inversed copy! of the matrix.
- ob_mat_inv = ob_mat.copy()
- Matrix.invert(ob_mat_inv)
-
- # Get the selected vertices.
- # @todo: Better (more efficient) way to do this?
- verts_selected = [v for v in mesh.vertices if v.select == 1]
-
- if len(verts_selected) == 0:
- # Nothing selected.
- # We measure the distance from...
- # local ... the object center to the 3D cursor.
- # global ... the origin to the 3D cursor.
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='CURSOR')
- row.label(text="", icon='ARROW_LEFTRIGHT')
- if measureLocal(sce):
- row.label(text="Obj. Center")
- else:
- row.label(text="Origin [0,0,0]")
-
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection & distance")
-# @todo
-# description="The surface area value can" \
-# " not be updated in mesh edit mode" \
-# " automatically. Press this button" \
-# " to do this manually, after you changed" \
-# " the selection.")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- elif len(verts_selected) == 1:
- # One vertex selected.
- # We measure the distance from the
- # selected vertex object to the 3D cursor.
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='CURSOR')
- row.label(text="", icon='ARROW_LEFTRIGHT')
- row.label(text="", icon='VERTEXSEL')
-
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection & distance")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- elif len(verts_selected) == 2:
- # Two vertices selected.
- # We measure the distance between the
- # two selected vertices.
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='VERTEXSEL')
- row.label(text="", icon='ARROW_LEFTRIGHT')
- row.label(text="", icon='VERTEXSEL')
-
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection & distance")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- else:
- row = layout.row()
- row.prop(sce, "measure_panel_calc_area",
- text="Surface area (selected faces):")
-
- if (sce.measure_panel_calc_area):
- # Get selected faces
- # @todo: Better (more efficient) way to do this?
- faces_selected = [f for f in mesh.faces
- if f.select == 1]
-
- if len(faces_selected) > 0:
- area = objectSurfaceArea(obj, True,
- measureGlobal(sce))
- if (area >= 0):
- row = layout.row()
- row.label(
- text=str(len(faces_selected)),
- icon='FACESEL')
- sce.measure_panel_area1 = area
- row.prop(sce, "measure_panel_area1")
-
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection & area")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- else:
- row = layout.row()
- row.label(text="Selection not supported.",
- icon='INFO')
-
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection")
-
- else:
- row = layout.row()
- row.operator("view3d.reenter_editmode",
- text="Update selection")
-
- elif (context.mode == 'OBJECT'):
- # We are working on object mode.
-
- if len(context.selected_objects) > 2:
- # We have more that 2 objects selected...
-
- row = layout.row()
- row.prop(sce, "measure_panel_calc_area",
- text="Surface area (selected faces):")
-
- if (sce.measure_panel_calc_area):
-
- mesh_objects = [o for o in context.selected_objects
- if (o.type == 'MESH')]
-
- if (len(mesh_objects) > 0):
- # ... and at least one of them is a mesh.
-
- # Calculate and display surface area of the objects.
- # @todo: Convert to scene units! We do not have a
- # FloatProperty field here for automatic conversion.
-
- row = layout.row()
- for o in mesh_objects:
- area = objectSurfaceArea(o, False,
- measureGlobal(sce))
- if (area >= 0):
- row = layout.row()
- row.label(text=o.name, icon='OBJECT_DATA')
- row.label(text=str(round(area, PRECISION))
- + " BU^2")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- elif len(context.selected_objects) == 2:
- # 2 objects selected.
- # We measure the distance between the 2 selected objects.
-
- obj1, obj2 = context.selected_objects
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='OBJECT_DATA')
- row.prop(obj1, "name", text="")
-
- row.label(text="", icon='ARROW_LEFTRIGHT')
-
- row.label(text="", icon='OBJECT_DATA')
- row.prop(obj2, "name", text="")
-
- row = layout.row()
- row.prop(sce, "measure_panel_calc_area",
- text="Surface area:")
-
- if (sce.measure_panel_calc_area):
- # Calculate and display surface area of the objects.
- area1 = objectSurfaceArea(obj1, False, measureGlobal(sce))
- area2 = objectSurfaceArea(obj2, False, measureGlobal(sce))
- if (area1 >= 0 or area2 >= 0):
- if (area1 >= 0):
- row = layout.row()
- row.label(text=obj1.name, icon='OBJECT_DATA')
- sce.measure_panel_area1 = area1
- row.prop(sce, "measure_panel_area1")
-
- if (area2 >= 0):
- row = layout.row()
- row.label(text=obj2.name, icon='OBJECT_DATA')
- sce.measure_panel_area2 = area2
- row.prop(sce, "measure_panel_area2")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- elif (obj):
- # One object selected.
- # We measure the distance from the object to the 3D cursor.
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- #row.label(text=str(dist_vec.length))
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='CURSOR')
-
- row.label(text="", icon='ARROW_LEFTRIGHT')
-
- row.label(text="", icon='OBJECT_DATA')
- row.prop(obj, "name", text="")
-
- row = layout.row()
- row.prop(sce, "measure_panel_calc_area",
- text="Surface area:")
-
- if (sce.measure_panel_calc_area):
- # Calculate and display surface area of the object.
- area = objectSurfaceArea(obj, False, measureGlobal(sce))
- if (area >= 0):
- row = layout.row()
- row.label(text=obj.name, icon='OBJECT_DATA')
- sce.measure_panel_area1 = area
- row.prop(sce, "measure_panel_area1")
-
- row = layout.row()
- row.prop(sce,
- "measure_panel_transform",
- expand=True)
-
- elif not context.selected_objects:
- # Nothing selected.
- # We measure the distance from the origin to the 3D cursor.
-
- # Get the 2 measure points
- line = getMeasurePoints(context)
- if line != 0:
- dist_vec = line[0] - line[1]
-
- sce.measure_panel_dist = dist_vec.length
-
- row = layout.row()
- row.prop(sce, "measure_panel_dist")
-
- row = layout.row()
- row.label(text="", icon='CURSOR')
- row.label(text="", icon='ARROW_LEFTRIGHT')
- row.label(text="Origin [0,0,0]")
-
- else:
- row = layout.row()
- row.label(text="Selection not supported.",
- icon='INFO')
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()
diff --git a/space_view3d_property_chart.py b/space_view3d_property_chart.py
deleted file mode 100644
index 290b2941..00000000
--- a/space_view3d_property_chart.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Object Property Chart",
- "author": "Campbell Barton (ideasman42)",
- "version": (0,1),
- "blender": (2, 5, 3),
- "api": 31667,
- "location": "Tool Shelf",
- "description": "Edit arbitrary selected properties for objects of the same type",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/3D interaction/Object Property Chart",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22701&group_id=153&atid=469",
- "category": "3D View"}
-
-"""List properties of selected objects"""
-
-import bpy
-
-def _property_chart_data_get(self, context):
- # eg. context.active_object
- obj = eval("context.%s" % self.context_data_path_active)
-
- if obj is None:
- return None, None
-
- # eg. context.selected_objects[:]
- selected_objects = eval("context.%s" % self.context_data_path_selected)[:]
-
- if not selected_objects:
- return None, None
-
- return obj, selected_objects
-
-
-def _property_chart_draw(self, context):
- '''
- This function can run for different types.
- '''
- obj, selected_objects = _property_chart_data_get(self, context)
-
- if not obj:
- return
-
- # active first
- try:
- active_index = selected_objects.index(obj)
- except ValueError:
- active_index = -1
-
- if active_index > 0: # not the first alredy
- selected_objects[0], selected_objects[active_index] = selected_objects[active_index], selected_objects[0]
-
- id_storage = context.scene
-
- strings = id_storage.get(self._PROP_STORAGE_ID)
-
- if strings is None:
- strings = id_storage[self._PROP_STORAGE_ID] = "data data.name"
-
- if strings:
-
- def obj_prop_get(obj, attr_string):
- """return a pair (rna_base, "rna_property") to give to the rna UI property function"""
- attrs = attr_string.split(".")
- val_new = obj
- for i, attr in enumerate(attrs):
- val_old = val_new
- val_new = getattr(val_old, attr, Ellipsis)
-
- if val_new == Ellipsis:
- return None, None
- return val_old, attrs[-1]
-
- strings = strings.split()
-
- prop_all = []
-
- for obj in selected_objects:
- prop_pairs = []
- prop_found = False
- for attr_string in strings:
- prop_pairs.append(obj_prop_get(obj, attr_string))
- if prop_found == False and prop_pairs[-1] != (None, None):
- prop_found = True
-
- if prop_found:
- prop_all.append((obj, prop_pairs))
-
-
- # Collected all props, now display them all
- layout = self.layout
-
- row = layout.row(align=True)
-
- col = row.column()
- col.label(text="name")
- for obj, prop_pairs in prop_all:
- col.prop(obj, "name", text="")
-
- for i in range(len(strings)):
- col = row.column()
-
- # name and copy button
- rowsub = col.row(align=False)
- rowsub.label(text=strings[i].rsplit(".", 1)[-1])
- props = rowsub.operator("wm.chart_copy", text="", icon='PASTEDOWN', emboss=False)
- props.data_path_active = self.context_data_path_active
- props.data_path_selected = self.context_data_path_selected
- props.data_path = strings[i]
-
- for obj, prop_pairs in prop_all:
- data, attr = prop_pairs[i]
- if data:
- col.prop(data, attr, text="")# , emboss=obj==active_object
- else:
- col.label(text="<missing>")
-
- # edit the display props
- col = layout.column()
- col.label(text="Object Properties")
- col.prop(id_storage, '["%s"]' % self._PROP_STORAGE_ID, text="")
-
-
-class View3DEditProps(bpy.types.Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
-
- bl_label = "Property Chart"
- bl_context = "objectmode"
-
- _PROP_STORAGE_ID = "view3d_edit_props"
-
- # _property_chart_draw needs these
- context_data_path_active = "active_object"
- context_data_path_selected = "selected_objects"
-
- draw = _property_chart_draw
-
-
-class SequencerEditProps(bpy.types.Panel):
- bl_space_type = 'SEQUENCE_EDITOR'
- bl_region_type = 'UI'
-
- bl_label = "Property Chart"
-
- _PROP_STORAGE_ID = "sequencer_edit_props"
-
- # _property_chart_draw needs these
- context_data_path_active = "scene.sequence_editor.active_strip"
- context_data_path_selected = "selected_sequences"
-
- draw = _property_chart_draw
-
- @classmethod
- def poll(cls, context):
- return context.scene.sequence_editor is not None
-
-# Operator to copy properties
-
-
-def _property_chart_copy(self, context):
- obj, selected_objects = _property_chart_data_get(self, context)
-
- if not obj:
- return
-
- data_path = self.properties.data_path
-
- # quick & nasty method!
- for obj_iter in selected_objects:
- if obj != obj_iter:
- try:
- exec("obj_iter.%s = obj.%s" % (data_path, data_path))
- except:
- # just incase we need to know what went wrong!
- import traceback
- traceback.print_exc()
-
-from bpy.props import StringProperty
-
-
-class CopyPropertyChart(bpy.types.Operator):
- "Open a path in a file browser"
- bl_idname = "wm.chart_copy"
- bl_label = "Copy properties from active to selected"
-
- data_path_active = StringProperty()
- data_path_selected = StringProperty()
- data_path = StringProperty()
-
- def execute(self, context):
- # so attributes are found for '_property_chart_data_get()'
- self.context_data_path_active = self.properties.data_path_active
- self.context_data_path_selected = self.properties.data_path_selected
-
- _property_chart_copy(self, context)
-
- return {'FINISHED'}
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()
diff --git a/space_view3d_spacebar_menu.py b/space_view3d_spacebar_menu.py
deleted file mode 100644
index 6feffb1d..00000000
--- a/space_view3d_spacebar_menu.py
+++ /dev/null
@@ -1,1471 +0,0 @@
-#3d_cursor_menu.py (c) 2010 Jonathan Smith (JayDez)
-#Original Script by: Mariano Hidalgo (uselessdreamer)
-#contributed to by: Crouch, sim88, sam, meta-androcto
-#
-#Tested with r28146
-#
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-bl_addon_info = {
- "name": "Dynamic Spacebar Menu",
- "author": "JayDez, sim88, meta-androcto", "sam"
- "version": (1,5),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "View3D > Spacebar",
- "description": "Context sensitive spacebar menu",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/3D_interaction/Dynamic_Spacebar_Menu",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22060&group_id=153&atid=469",
- "category": "3D View"}
-
-"""
-Dynamic Menu
-This adds a the Dynamic Spacebar Menu in the View3D.
-
-Usage:
-* This script gives a basic menu with common simple tools for easy access.
-* Very similar to the Spacebar menu in 2.49
-* Context sensitive for Object. Edit, Sculpt, Pose, Weight/Texture/Vertex Paint.
-* Object sensitive based on object selected in edit mode.
-
-Version history:
-v1.5 - (meta-androcto) - adding context sensitive menus.
-v1.3 - (JayDez) - Changed toggle editmode to an if statement, so that
- if you are in editmode it will show change to object mode but
- otherwise it shows change to edit mode. Also added separate icons
- for change to edit mode and to object mode.
-v1.2 - (JayDez) - Editing docs, changing 3D cursor to dynamic menu,
- reorganizing menu.
-v1.1 - (meta-androcto) - added editmode menu
-v1.0 - (meta-androcto) - initial final revision (commited to contrib)
-v0.1 through 0.9 - various tests/contributions by various people and scripts
- Devs: JayDez, Crouch, sim88, meta-androcto, Sam
- Scripts: 3D Cursor Menu, Original Dynamic Menu
-"""
-
-import bpy
-from bpy import *
-from mathutils import Vector, Matrix
-import math
-
-# Dynamic Menu
-class VIEW3D_MT_Space_Dynamic_Menu(bpy.types.Menu):
- bl_label = "Dynamic Spacebar Menu"
-
- def draw(self, context):
- layout = self.layout
- settings = context.tool_settings
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- ob = context
- if ob.mode == 'OBJECT':
- # Object mode
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
- layout.separator()
-
- # Add Menu block
- layout.menu("VIEW3D_MT_AddMenu", icon='OBJECT_DATAMODE')
- layout.separator()
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Parent block
- layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
-
- # Group block
- layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP')
- layout.separator()
-
- # Modifier block
- layout.operator_menu_enum("object.modifier_add", "type" , icon='MODIFIER')
- layout.separator()
-
- # Cursor Block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Align block
- layout.menu("VIEW3D_MT_AlignMenu", icon='ALIGN')
- layout.separator()
-
- # Select block
- layout.menu("VIEW3D_MT_SelectMenu", icon='RESTRICT_SELECT_OFF')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Editmode
- layout.operator("object.editmode_toggle", text="Enter Edit Mode",
- icon='EDITMODE_HLT')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
-
- elif ob.mode == 'EDIT_MESH':
- # Edit mode
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Add block
- bl_label = "Create"
- layout.menu("INFO_MT_mesh_add", text="Add Mesh",
- icon='EDITMODE_HLT')
- layout.separator()
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_EditCursorMenu", icon='CURSOR')
- layout.separator()
-
- # Edit block
- layout.menu("VIEW3D_MT_edit_TK", icon='OUTLINER_OB_MESH')
- layout.separator()
-
- # Multi Select
- layout.menu("VIEW3D_MT_edit_multi", icon='VERTEXSEL')
- layout.separator()
-
- # Extrude block
- layout.menu("VIEW3D_MT_edit_mesh_extrude", icon='EDITMODE_HLT')
- layout.separator()
-
- # Tools block
- layout.menu("VIEW3D_MT_edit_mesh_specials", icon='MODIFIER')
- layout.menu("VIEW3D_MT_uv_map", icon='MOD_UVPROJECT')
-
- # Select block
- layout.menu("VIEW3D_MT_SelectMenu", icon='RESTRICT_SELECT_OFF')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Object Mode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATAMODE')
-
- # Delete Block
- layout.operator("mesh.delete", icon='CANCEL')
-
- if ob.mode == 'EDIT_CURVE':
- # Curve menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Proportional block
- layout.prop_menu_enum(settings, "proportional_edit", icon= "PROP_CON")
- layout.prop_menu_enum(settings, "proportional_edit_falloff", icon= "SMOOTHCURVE")
- layout.separator()
-
- # Edit Control Points
- layout.menu("VIEW3D_MT_EditCurveCtrlpoints",
- icon='CURVE_BEZCURVE')
- layout.separator()
-
- # Edit Curve Specials
- layout.menu("VIEW3D_MT_EditCurveSpecials",
- icon='MODIFIER')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Select Curve Block
- layout.menu("VIEW3D_MT_SelectCurveMenu", icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
- if ob.mode == 'EDIT_SURFACE':
- # Surface menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Proportional block
- layout.prop_menu_enum(settings, "proportional_edit", icon= "PROP_CON")
- layout.prop_menu_enum(settings, "proportional_edit_falloff", icon= "SMOOTHCURVE")
-
- # Edit Curve Specials
- layout.menu("VIEW3D_MT_EditCurveSpecials",
- icon='MODIFIER')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Select Surface
- layout.menu("VIEW3D_MT_SelectSurface", icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
- if ob.mode == 'EDIT_METABALL':
- # Metaball menu
-
- #Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Proportional block
- layout.prop_menu_enum(settings, "proportional_edit", icon= "PROP_CON")
- layout.prop_menu_enum(settings, "proportional_edit_falloff", icon= "SMOOTHCURVE")
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- #Select Metaball
- layout.menu("VIEW3D_MT_SelectMetaball", icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
- elif ob.mode == 'EDIT_LATTICE':
- # Lattice menu
-
- #Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Proportional block
- layout.prop_menu_enum(settings, "proportional_edit", icon= "PROP_CON")
- layout.prop_menu_enum(settings, "proportional_edit_falloff", icon= "SMOOTHCURVE")
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- #Select Lattice
- layout.menu("VIEW3D_MT_select_edit_lattice", icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- layout.operator("lattice.make_regular")
- layout.separator()
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
-
- if context.mode == 'PARTICLE':
- # Particle menu
-
- #Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Proportional block
- layout.prop_menu_enum(settings, "proportional_edit", icon= "PROP_CON")
- layout.prop_menu_enum(settings, "proportional_edit_falloff", icon= "SMOOTHCURVE")
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
- ob = context
- if ob.mode == 'PAINT_WEIGHT':
- # Weight paint menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Weight Paint block
- layout.menu("VIEW3D_MT_paint_weight", icon='WPAINT_HLT')
- layout.separator()
-
- # History/Cursor Block
- layout.menu("VIEW3D_MT_undoS", icon='ARROW_LEFTRIGHT')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.mode_set", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
-
-
- elif ob.mode == 'PAINT_VERTEX':
- # Vertex paint menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Vertex Paint block
- layout.operator("paint.vertex_color_set", icon='VPAINT_HLT')
- layout.separator()
-
- # History/Cursor Block
- layout.menu("VIEW3D_MT_undoS", icon='ARROW_LEFTRIGHT')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.mode_set", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- elif ob.mode == 'PAINT_TEXTURE':
- # Texture paint menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # History/Cursor Block
- layout.menu("VIEW3D_MT_undoS", icon='ARROW_LEFTRIGHT')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Objectmode
- layout.operator("object.mode_set", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- elif ob.mode == 'SCULPT':
- # Sculpt menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Sculpt block
- layout.menu("VIEW3D_MT_sculpt", icon='SCULPTMODE_HLT')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # History/Cursor Block
- layout.menu("VIEW3D_MT_undoS", icon='ARROW_LEFTRIGHT')
-
- # Toolshelf block
- layout.operator("view3d.toolshelf", icon='MENU_PANEL')
- layout.separator()
-
- # Properties block
- layout.operator("view3d.properties", icon='MENU_PANEL')
- layout.separator()
-
- # Toggle Editmode
- layout.operator("object.editmode_toggle", text="Enter Edit Mode",
- icon='EDITMODE_HLT')
-
- elif ob.mode == 'EDIT_ARMATURE':
- # Armature menu
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform block
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
- layout.separator()
-
- # Mirror block
- layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR')
- layout.separator()
-
- # Cursor block
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Edit Armature roll
- layout.menu("VIEW3D_MT_edit_armature_roll",
- icon='BONE_DATA')
- layout.separator()
-
- # Edit Armature Toolkit
- layout.menu("VIEW3D_MT_EditArmatureTK",
- icon='ARMATURE_DATA')
- layout.separator()
-
- # Edit Armature Name
- layout.menu("VIEW3D_MT_ArmatureName",
- icon='NEW')
- layout.separator()
-
- # Parent block
- layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE')
-
- layout.separator()
- layout.operator_menu_enum("armature.flags_set", "mode", text="Bone Settings")
-
- # Edit Armature Select
- layout.menu("VIEW3D_MT_SelectArmatureMenu",
- icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- # Edit Armature Specials
- layout.menu("VIEW3D_MT_armature_specials", icon='MODIFIER')
- layout.separator()
-
- # Toggle Posemode
- layout.operator("object.posemode_toggle", text="Enter Pose Mode",
- icon='EDITMODE_HLT')
-
- # Toggle Posemode
- layout.operator("object.editmode_toggle", text="Enter Object Mode",
- icon='OBJECT_DATA')
-
- # Delete block
- layout.operator("object.delete", text="Delete Object",
- icon='CANCEL')
-
-
- if context.mode == 'POSE':
- # Pose mode menu
- arm = context.active_object.data
-
- # Search Menu
- layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM')
-
- # Transform Menu
- layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL')
-
- # Clear Transform
- layout.menu("VIEW3D_MT_pose_transform")
-
- # Cursor Menu
- layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR')
- layout.separator()
-
- # Select Pose Block
- layout.menu("VIEW3D_MT_SelectPoseMenu", icon='RESTRICT_SELECT_OFF')
- layout.separator()
-
- # Pose Copy Block
- layout.menu("VIEW3D_MT_PoseCopy", icon='FILE')
- layout.separator()
-
-
- if arm.drawtype in ('BBONE', 'ENVELOPE'):
- layout.operator("transform.transform",
- text="Scale Envelope Distance").mode = 'BONESIZE'
-
- layout.menu("VIEW3D_MT_pose_apply")
- layout.separator()
-
- layout.operator("pose.relax")
- layout.separator()
-
- layout.menu("VIEW3D_MT_KeyframeMenu")
- layout.separator()
-
- layout.menu("VIEW3D_MT_pose_pose")
- layout.menu("VIEW3D_MT_pose_motion")
- layout.menu("VIEW3D_MT_pose_group")
- layout.separator()
-
- layout.menu("VIEW3D_MT_pose_ik")
- layout.menu("VIEW3D_MT_PoseNames")
- layout.separator()
-
- layout.menu("VIEW3D_MT_pose_constraints")
- layout.separator()
-
-
-
- layout.operator("pose.quaternions_flip")
- layout.separator()
-
- layout.operator_context = 'INVOKE_AREA'
- layout.operator("pose.armature_layers",
- text="Change Armature Layers...")
- layout.operator("pose.bone_layers", text="Change Bone Layers...")
- layout.separator()
-
- layout.menu("VIEW3D_MT_pose_showhide")
- layout.operator_menu_enum("pose.flags_set", 'mode',
- text="Bone Settings")
-
- # Toggle Editmode
- layout.operator("object.editmode_toggle", text="Enter Edit Mode",
- icon='EDITMODE_HLT')
-
-
-class VIEW3D_MT_AddMenu(bpy.types.Menu):
- bl_label = "Add Object Menu"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.menu("INFO_MT_mesh_add", text="Add Mesh",
- icon='OUTLINER_OB_MESH')
- layout.menu("INFO_MT_curve_add", text="Add Curve",
- icon='OUTLINER_OB_CURVE')
- layout.menu("INFO_MT_surface_add", text="Add Surface",
- icon='OUTLINER_OB_SURFACE')
- layout.operator_menu_enum("object.metaball_add", "type",
- icon='OUTLINER_OB_META')
- layout.operator("object.text_add", text="Add Text",
- icon='OUTLINER_OB_FONT')
- layout.separator()
- layout.menu("INFO_MT_armature_add", text="Add Armature",
- icon='OUTLINER_OB_ARMATURE')
- layout.operator("object.add", text="Lattice",
- icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
- layout.separator()
- layout.operator("object.add", text="Add Empty",
- icon='OUTLINER_OB_EMPTY')
- layout.separator()
-
- layout.operator("object.camera_add", text="Camera",
- icon='OUTLINER_OB_CAMERA')
- layout.operator_menu_enum("object.lamp_add", "type",
- icon="OUTLINER_OB_LAMP")
- layout.separator()
-
- layout.operator_menu_enum("object.effector_add", "type",
- text="Force Field",
- icon='OUTLINER_OB_EMPTY')
- layout.operator_menu_enum("object.group_instance_add", "group",
- text="Group Instance",
- icon='OUTLINER_OB_EMPTY')
-
-
-class VIEW3D_MT_TransformMenu(bpy.types.Menu):
- bl_label = "Transform Menu"
-
- # TODO: get rid of the custom text strings?
- def draw(self, context):
- layout = self.layout
-
- layout.operator("transform.translate", text="Grab/Move")
- # TODO: sub-menu for grab per axis
- layout.operator("transform.rotate", text="Rotate")
- # TODO: sub-menu for rot per axis
- layout.operator("transform.resize", text="Scale")
- # TODO: sub-menu for scale per axis
- layout.separator()
-
- layout.operator("transform.tosphere", text="To Sphere")
- layout.operator("transform.shear", text="Shear")
- layout.operator("transform.warp", text="Warp")
- layout.operator("transform.push_pull", text="Push/Pull")
- if context.edit_object and context.edit_object.type == 'ARMATURE':
- layout.operator("armature.align")
- else:
- layout.operator_context = 'EXEC_REGION_WIN'
- # @todo vvv See alignmenu() in edit.c of b2.4x to get this working.
- layout.operator("transform.transform",
- text="Align to Transform Orientation").mode = 'ALIGN'
- layout.separator()
-
- layout.operator_context = 'EXEC_AREA'
-
- layout.operator("object.origin_set",
- text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
- layout.operator("object.origin_set",
- text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
- layout.operator("object.origin_set",
- text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
-
-
-class VIEW3D_MT_MirrorMenu(bpy.types.Menu):
- bl_label = "Mirror Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("transform.mirror", text="Interactive Mirror")
- layout.separator()
-
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- props = layout.operator("transform.mirror", text="X Global")
- props.constraint_axis = (True, False, False)
- props.constraint_orientation = 'GLOBAL'
- props = layout.operator("transform.mirror", text="Y Global")
- props.constraint_axis = (False, True, False)
- props.constraint_orientation = 'GLOBAL'
- props = layout.operator("transform.mirror", text="Z Global")
- props.constraint_axis = (False, False, True)
- props.constraint_orientation = 'GLOBAL'
-
- if context.edit_object:
- layout.separator()
-
- props = layout.operator("transform.mirror", text="X Local")
- props.constraint_axis = (True, False, False)
- props.constraint_orientation = 'LOCAL'
- props = layout.operator("transform.mirror", text="Y Local")
- props.constraint_axis = (False, True, False)
- props.constraint_orientation = 'LOCAL'
- props = layout.operator("transform.mirror", text="Z Local")
- props.constraint_axis = (False, False, True)
- props.constraint_orientation = 'LOCAL'
-
- layout.operator("object.vertex_group_mirror")
-
-class VIEW3D_MT_ParentMenu(bpy.types.Menu):
- bl_label = "Parent Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("object.parent_set", text="Set")
- layout.operator("object.parent_clear", text="Clear")
-
-class VIEW3D_MT_GroupMenu(bpy.types.Menu):
- bl_label = "Group Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("group.create")
- layout.operator("group.objects_remove")
-
- layout.separator()
-
- layout.operator("group.objects_add_active")
- layout.operator("group.objects_remove_active")
-
-class VIEW3D_MT_AlignMenu(bpy.types.Menu):
- bl_label = "Align Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.menu("VIEW3D_MT_view_align_selected")
-
- layout.separator()
-
- layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
- layout.operator("view3d.camera_to_view", text="Align Active Camera to View")
- layout.operator("view3d.view_selected")
- layout.operator("view3d.view_center_cursor")
-
-class VIEW3D_MT_SelectMenu(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
- layout.separator()
- layout.operator("object.select_all", text="Select/Deselect All")
- layout.operator("object.select_inverse", text="Inverse")
- layout.operator("object.select_random", text="Random")
- layout.operator("object.select_mirror", text="Mirror")
- layout.operator("object.select_by_layer", text="Select All by Layer")
- layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
- layout.operator("object.select_camera", text="Select Camera")
- layout.separator()
- layout.operator_menu_enum("object.select_grouped", "type", text="Grouped")
- layout.operator_menu_enum("object.select_linked", "type", text="Linked")
- layout.operator("object.select_pattern", text="Select Pattern...")
-
-class VIEW3D_MT_SelectEditMenu(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
-
- layout.separator()
-
- layout.operator("mesh.select_all", text="Select/Deselect All")
- layout.operator("mesh.select_inverse", text="Inverse")
-
- layout.separator()
-
- layout.operator("mesh.select_random", text="Random")
- layout.operator("mesh.select_nth", text="Every N Number of Verts")
- layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
- layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces")
- layout.operator("mesh.faces_select_interior", text="Interior Faces")
- layout.operator("mesh.select_axis", text="Side of Active")
-
- layout.separator()
-
- layout.operator("mesh.select_by_number_vertices", text="Triangles").type = 'TRIANGLES'
- layout.operator("mesh.select_by_number_vertices", text="Quads").type = 'QUADS'
- if context.scene.tool_settings.mesh_select_mode[2] == False:
- layout.operator("mesh.select_non_manifold", text="Non Manifold")
- layout.operator("mesh.select_by_number_vertices", text="Loose Verts/Edges").type = 'OTHER'
- layout.operator("mesh.select_similar", text="Similar")
-
- layout.separator()
-
- layout.operator("mesh.select_less", text="Less")
- layout.operator("mesh.select_more", text="More")
-
- layout.separator()
-
- layout.operator("mesh.select_mirror", text="Mirror")
-
- layout.operator("mesh.select_linked", text="Linked")
- layout.operator("mesh.select_vertex_path", text="Vertex Path")
- layout.operator("mesh.loop_multi_select", text="Edge Loop")
- layout.operator("mesh.loop_multi_select", text="Edge Ring").ring = True
-
- layout.separator()
-
- layout.operator("mesh.loop_to_region")
- layout.operator("mesh.region_to_loop")
-
-class VIEW3D_MT_SelectCurveMenu(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
-
- layout.separator()
-
- layout.operator("curve.select_all", text="Select/Deselect All")
- layout.operator("curve.select_inverse")
- layout.operator("curve.select_random")
- layout.operator("curve.select_every_nth")
-
- layout.separator()
-
- layout.operator("curve.de_select_first")
- layout.operator("curve.de_select_last")
- layout.operator("curve.select_next")
- layout.operator("curve.select_previous")
-
- layout.separator()
-
- layout.operator("curve.select_more")
- layout.operator("curve.select_less")
-
-class VIEW3D_MT_SelectArmatureMenu(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
-
-
- layout.separator()
-
- layout.operator("armature.select_all", text="Select/Deselect All")
- layout.operator("armature.select_inverse", text="Inverse")
-
- layout.separator()
-
- layout.operator("armature.select_hierarchy", text="Parent").direction = 'PARENT'
- layout.operator("armature.select_hierarchy", text="Child").direction = 'CHILD'
-
- layout.separator()
-
- props = layout.operator("armature.select_hierarchy", text="Extend Parent")
- props.extend = True
- props.direction = 'PARENT'
-
- props = layout.operator("armature.select_hierarchy", text="Extend Child")
- props.extend = True
- props.direction = 'CHILD'
-
- layout.operator("object.select_pattern", text="Select Pattern...")
-
-
-class VIEW3D_MT_SelectPoseMenu(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
-
- layout.separator()
-
- layout.operator("pose.select_all", text="Select/Deselect All")
- layout.operator("pose.select_inverse", text="Inverse")
- layout.operator("pose.select_constraint_target", text="Constraint Target")
- layout.operator("pose.select_linked", text="Linked")
-
- layout.separator()
-
- layout.operator("pose.select_hierarchy", text="Parent").direction = 'PARENT'
- layout.operator("pose.select_hierarchy", text="Child").direction = 'CHILD'
-
- layout.separator()
-
- props = layout.operator("pose.select_hierarchy", text="Extend Parent")
- props.extend = True
- props.direction = 'PARENT'
-
- props = layout.operator("pose.select_hierarchy", text="Extend Child")
- props.extend = True
- props.direction = 'CHILD'
-
- layout.separator()
-
- layout.operator_menu_enum("pose.select_grouped", "type", text="Grouped")
- layout.operator("object.select_pattern", text="Select Pattern...")
-
-class VIEW3D_MT_PoseCopy(bpy.types.Menu):
- bl_label = "Pose Copy"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("pose.copy")
- layout.operator("pose.paste")
- layout.operator("pose.paste",
- text="Paste X-Flipped Pose").flipped = True
- layout.separator()
-
-class VIEW3D_MT_PoseNames(bpy.types.Menu):
- bl_label = "Pose Copy"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_context = 'EXEC_AREA'
- layout.operator("pose.autoside_names",
- text="AutoName Left/Right").axis = 'XAXIS'
- layout.operator("pose.autoside_names",
- text="AutoName Front/Back").axis = 'YAXIS'
- layout.operator("pose.autoside_names",
- text="AutoName Top/Bottom").axis = 'ZAXIS'
-
- layout.operator("pose.flip_names")
-
-
-class VIEW3D_MT_SelectSurface(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
- layout.operator("view3d.select_circle")
-
- layout.separator()
-
- layout.operator("curve.select_all", text="Select/Deselect All")
- layout.operator("curve.select_inverse")
- layout.operator("curve.select_random")
- layout.operator("curve.select_every_nth")
-
- layout.separator()
-
- layout.operator("curve.select_row")
-
- layout.separator()
-
- layout.operator("curve.select_more")
- layout.operator("curve.select_less")
-
-class VIEW3D_MT_SelectMetaball(bpy.types.Menu):
- bl_label = "Select Menu"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
-
- layout.separator()
-
- #layout.operator("mball.select_deselect_all_metaelems")
- layout.operator("mball.select_inverse_metaelems")
-
- layout.separator()
-
- layout.operator("mball.select_random_metaelems")
-
-class VIEW3D_MT_edit_TK(bpy.types.Menu):
- bl_label = "Edit Mesh Tools"
-
- def draw(self, context):
- layout = self.layout
- row = layout.row()
-
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.menu("VIEW3D_MT_edit_mesh_vertices", icon='VERTEXSEL')
- layout.menu("VIEW3D_MT_edit_mesh_edges", icon='EDGESEL')
- layout.menu("VIEW3D_MT_edit_mesh_faces", icon='FACESEL')
- layout.separator()
- layout.menu("VIEW3D_MT_edit_mesh_normals", icon='META_DATA')
- layout.operator("mesh.loopcut_slide",
- text="Loopcut", icon='EDIT_VEC')
-
-
-
-class VIEW3D_MT_edit_multi(bpy.types.Menu):
- bl_label = "Multi Select"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.separator()
- prop = layout.operator("wm.context_set_value", text="Vertex Select", icon='VERTEXSEL')
- prop.value = "(True, False, False)"
- prop.data_path = "tool_settings.mesh_select_mode"
-
- prop = layout.operator("wm.context_set_value", text="Edge Select", icon='EDGESEL')
- prop.value = "(False, True, False)"
- prop.data_path = "tool_settings.mesh_select_mode"
-
- prop = layout.operator("wm.context_set_value", text="Face Select", icon='FACESEL')
- prop.value = "(False, False, True)"
- prop.data_path = "tool_settings.mesh_select_mode"
- layout.separator()
-
- prop = layout.operator("wm.context_set_value", text="Vertex & Edge Select", icon='EDITMODE_HLT')
- prop.value = "(True, True, False)"
- prop.data_path = "tool_settings.mesh_select_mode"
-
- prop = layout.operator("wm.context_set_value", text="Vertex & Face Select", icon='ORTHO')
- prop.value = "(True, False, True)"
- prop.data_path = "tool_settings.mesh_select_mode"
-
- prop = layout.operator("wm.context_set_value", text="Edge & Face Select", icon='SNAP_FACE')
- prop.value = "(False, True, True)"
- prop.data_path = "tool_settings.mesh_select_mode"
- layout.separator()
-
- prop = layout.operator("wm.context_set_value", text="Vertex & Edge & Face Select", icon='SNAP_VOLUME')
- prop.value = "(True, True, True)"
- prop.data_path = "tool_settings.mesh_select_mode"
-
-class VIEW3D_MT_editM_Edge(bpy.types.Menu):
- bl_label = "Edges"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.operator("mesh.mark_seam")
- layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
- layout.separator()
-
- layout.operator("mesh.mark_sharp")
- layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
- layout.operator("mesh.extrude_move_along_normals", text="Extrude")
- layout.separator()
-
- layout.operator("mesh.edge_rotate",
- text="Rotate Edge CW").direction = 'CW'
- layout.operator("mesh.edge_rotate",
- text="Rotate Edge CCW").direction = 'CCW'
- layout.separator()
-
- layout.operator("TFM_OT_edge_slide", text="Edge Slide")
- layout.operator("mesh.loop_multi_select", text="Edge Loop")
- layout.operator("mesh.loop_multi_select", text="Edge Ring").ring = True
- layout.operator("mesh.loop_to_region")
- layout.operator("mesh.region_to_loop")
-
-
-class VIEW3D_MT_EditCurveCtrlpoints(bpy.types.Menu):
- bl_label = "Control Points"
-
- def draw(self, context):
- layout = self.layout
-
- edit_object = context.edit_object
-
- if edit_object.type == 'CURVE':
- layout.operator("transform.transform").mode = 'TILT'
- layout.operator("curve.tilt_clear")
- layout.operator("curve.separate")
-
- layout.separator()
-
- layout.operator_menu_enum("curve.handle_type_set", "type")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_hook")
-
-
-class VIEW3D_MT_EditCurveSegments(bpy.types.Menu):
- bl_label = "Curve Segments"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("curve.subdivide")
- layout.operator("curve.switch_direction")
-
-class VIEW3D_MT_EditCurveSpecials(bpy.types.Menu):
- bl_label = "Specials"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("curve.subdivide")
- layout.operator("curve.switch_direction")
- layout.operator("curve.spline_weight_set")
- layout.operator("curve.radius_set")
- layout.operator("curve.smooth")
- layout.operator("curve.smooth_radius")
-
-class VIEW3D_MT_EditArmatureTK(bpy.types.Menu):
- bl_label = "Armature Tools"
-
- def draw(self, context):
- layout = self.layout
-
- # Edit Armature
-
- layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONESIZE'
-
- layout.operator("transform.transform", text="Scale B-Bone Width").mode = 'BONESIZE'
-
- layout.separator()
-
- layout.operator("armature.extrude_move")
-
- layout.operator("armature.extrude_forked")
-
- layout.operator("armature.duplicate_move")
- layout.operator("armature.merge")
- layout.operator("armature.fill")
- layout.operator("armature.delete")
- layout.operator("armature.separate")
-
- layout.separator()
-
- layout.operator("armature.subdivide_multi", text="Subdivide")
- layout.operator("armature.switch_direction", text="Switch Direction")
-
-class VIEW3D_MT_ArmatureName(bpy.types.Menu):
- bl_label = "Armature Name"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_context = 'EXEC_AREA'
- layout.operator("armature.autoside_names", text="AutoName Left/Right").type = 'XAXIS'
- layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS'
- layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS'
- layout.operator("armature.flip_names")
- layout.separator()
-
-class VIEW3D_MT_KeyframeMenu(bpy.types.Menu):
- bl_label = "Keyframe Menu"
-
- def draw(self, context):
- layout = self.layout
-
- # Keyframe Bleck
- layout.operator("anim.keyframe_insert_menu",
- text="Insert Keyframe...")
- layout.operator("anim.keyframe_delete_v3d",
- text="Delete Keyframe...")
- layout.operator("anim.keying_set_active_set",
- text="Change Keying Set...")
- layout.separator()
-
-# Classes for VIEW3D_MT_CursorMenu()
-class VIEW3D_OT_pivot_cursor(bpy.types.Operator):
- "Cursor as Pivot Point"
- bl_idname = "view3d.pivot_cursor"
- bl_label = "Cursor as Pivot Point"
-
- @classmethod
- def poll(cls, context):
- return bpy.context.space_data.pivot_point != 'CURSOR'
-
- def execute(self, context):
- bpy.context.space_data.pivot_point = 'CURSOR'
- return {'FINISHED'}
-
-class VIEW3D_OT_revert_pivot(bpy.types.Operator):
- "Revert Pivot Point"
- bl_idname = "view3d.revert_pivot"
- bl_label = "Reverts Pivot Point to median"
-
- @classmethod
- def poll(cls, context):
- return bpy.context.space_data.pivot_point != 'MEDIAN_POINT'
-
- def execute(self, context):
- bpy.context.space_data.pivot_point = 'MEDIAN_POINT'
- # @todo Change this to 'BOUDNING_BOX_CENTER' if needed...
- return{'FINISHED'}
-
-class VIEW3D_MT_CursorMenu(bpy.types.Menu):
- bl_label = "Snap Cursor Menu"
-
- def draw(self, context):
-
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("view3d.snap_cursor_to_selected",
- text="Cursor to Selected")
- layout.operator("view3d.snap_cursor_to_center",
- text="Cursor to Center")
- layout.operator("view3d.snap_cursor_to_grid",
- text="Cursor to Grid")
- layout.operator("view3d.snap_cursor_to_active",
- text="Cursor to Active")
- layout.separator()
- layout.operator("view3d.snap_selected_to_cursor",
- text="Selection to Cursor")
- layout.operator("view3d.snap_selected_to_grid",
- text="Selection to Grid")
- layout.separator()
- layout.operator("view3d.pivot_cursor",
- text="Set Cursor as Pivot Point")
- layout.operator("view3d.revert_pivot",
- text="Revert Pivot Point")
-
-class VIEW3D_MT_EditCursorMenu(bpy.types.Menu):
- bl_label = "Snap Cursor Menu"
-
- def draw(self, context):
-
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("view3d.snap_cursor_to_selected",
- text="Cursor to Selected")
- layout.operator("view3d.snap_cursor_to_center",
- text="Cursor to Center")
- layout.operator("view3d.snap_cursor_to_grid",
- text="Cursor to Grid")
- layout.operator("view3d.snap_cursor_to_active",
- text="Cursor to Active")
- layout.separator()
- layout.operator("view3d.snap_selected_to_cursor",
- text="Selection to Cursor")
- layout.operator("view3d.snap_selected_to_grid",
- text="Selection to Grid")
- layout.separator()
- layout.operator("view3d.pivot_cursor",
- text="Set Cursor as Pivot Point")
- layout.operator("view3d.revert_pivot",
- text="Revert Pivot Point")
- layout.operator("view3d.snap_cursor_to_edge_intersection",
- text="Cursor to Edge Intersection")
- layout.operator("transform.snap_type", text="Snap Tools",
- icon='SNAP_ON')
-
-def abs(val):
- if val > 0:
- return val
- return -val
-
-def LineLineIntersect (p1, p2, p3, p4):
- # based on Paul Bourke's Shortest Line Between 2 lines
-
- min = 0.0000001
-
- v1 = Vector((p1.x - p3.x, p1.y - p3.y, p1.z - p3.z))
- v2 = Vector((p4.x - p3.x, p4.y - p3.y, p4.z - p3.z))
-
- if abs(v2.x) < min and abs(v2.y) < min and abs(v2.z) < min:
- return None
-
- v3 = Vector((p2.x - p1.x, p2.y - p1.y, p2.z - p1.z))
-
- if abs(v3.x) < min and abs(v3.y) < min and abs(v3.z) < min:
- return None
-
- d1 = v1.dot(v2)
- d2 = v2.dot(v3)
- d3 = v1.dot(v3)
- d4 = v2.dot(v2)
- d5 = v3.dot(v3)
-
- d = d5 * d4 - d2 * d2
-
- if abs(d) < min:
- return None
-
- n = d1 * d2 - d3 * d4
-
- mua = n / d
- mub = (d1 + d2 * (mua)) / d4
-
- return [Vector((p1.x + mua * v3.x, p1.y + mua * v3.y, p1.z + mua * v3.z)),
- Vector((p3.x + mub * v2.x, p3.y + mub * v2.y, p3.z + mub * v2.z))]
-
-def edgeIntersect(context, operator):
-
- obj = context.active_object
-
- if (obj.type != "MESH"):
- operator.report({'ERROR'}, "Object must be a mesh")
- return None
-
- edges = [];
- mesh = obj.data
- verts = mesh.vertices
-
- is_editmode = (obj.mode == 'EDIT')
- if is_editmode:
- bpy.ops.object.mode_set(mode='OBJECT')
-
- for e in mesh.edges:
- if e.select:
- edges.append(e)
-
- if is_editmode:
- bpy.ops.object.mode_set(mode='EDIT')
-
- if len(edges) != 2:
- operator.report({'ERROR'}, "Operator requires exactly 2 edges to be selected.")
- return
-
- line = LineLineIntersect(verts[edges[0].vertices[0]].co, verts[edges[0].vertices[1]].co, verts[edges[1].vertices[0]].co, verts[edges[1].vertices[1]].co)
-
- if (line == None):
- operator.report({'ERROR'}, "Selected edges are parallel.")
- return
-
- tm = obj.matrix_world.copy()
- point = ((line[0] + line[1]) / 2)
- point = tm * point
-
- context.scene.cursor_location = point
-
- return point
-
-class VIEW3D_OT_CursorToEdgeIntersection(bpy.types.Operator):
- "Finds the mid-point of the shortest distance between two edges"
-
- bl_idname = "view3d.snap_cursor_to_edge_intersection"
- bl_label = "Cursor to Edge Intersection"
-
- @classmethod
- def poll(cls, context):
- obj = context.active_object
- return obj != None and obj.type == 'MESH'
-
- def execute(self, context):
- edgeIntersect(context, self)
- return {'FINISHED'}
-
-class VIEW3D_MT_undoS(bpy.types.Menu):
- bl_label = "Undo/Redo"
-
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("ed.undo", icon='TRIA_LEFT')
- layout.operator("ed.redo", icon='TRIA_RIGHT')
-
-def register():
- km = bpy.context.window_manager.keyconfigs.active.keymaps['3D View']
- kmi = km.items.new('wm.call_menu', 'SPACE', 'PRESS')
- kmi.properties.name = "VIEW3D_MT_Space_Dynamic_Menu"
-
-
-def unregister():
- km = bpy.context.window_manager.keyconfigs.active.keymaps['3D View']
- for kmi in km.items:
- if kmi.idname == 'wm.call_menu':
- if kmi.properties.name == "VIEW3D_MT_Space_Dynamic_Menu":
- km.items.remove(kmi)
- break
-
-if __name__ == "__main__":
- register()
diff --git a/system_blend_info.py b/system_blend_info.py
deleted file mode 100644
index e9649ba3..00000000
--- a/system_blend_info.py
+++ /dev/null
@@ -1,207 +0,0 @@
-# scene_blend_info.py Copyright (C) 2010, Mariano Hidalgo
-#
-# Show Information About the Blend.
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-bl_addon_info = {
- "name": "Scene Information",
- "author": "uselessdreamer",
- "version": (0,3),
- "blender": (2, 5, 3),
- "api": 31854,
- "location": "Properties space > Scene tab > Blend Info panel",
- "description": "Show information about the .blend",
- "warning": "",
- "wiki_url": 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
- 'Scripts/System/Blend Info',
- "tracker_url": "https://projects.blender.org/tracker/index.php?" \
- "func=detail&aid=22102&group_id=153&atid=469",
- "category": "System"}
-
-import bpy
-
-
-def quantity_string(quantity, text_single, text_plural, text_none=None):
- sep = " "
-
- if not text_none:
- text_none = text_plural
-
- if quantity == 0:
- string = str(quantity) + sep + text_none
-
- if quantity == 1:
- string = str(quantity) + sep + text_single
-
- if quantity >= 2:
- string = str(quantity) + sep + text_plural
-
- if quantity < 0:
- return None
-
- return string
-
-
-class OBJECT_PT_blendinfo(bpy.types.Panel):
- bl_label = "Blend Info"
- bl_space_type = "PROPERTIES"
- bl_region_type = "WINDOW"
- bl_context = "scene"
-
- def draw(self, context):
- amount = 2
- ob_cols = []
- db_cols = []
- etc_cols = []
-
- objects = bpy.data.objects
-
- layout = self.layout
-
- # OBJECTS
-
- l_row = layout.row()
- num = len(bpy.data.objects)
- l_row.label(text=quantity_string(num, "Object", "Objects")
- + " in the scene:",
- icon='OBJECT_DATA')
-
- l_row = layout.row()
- ob_cols.append(l_row.column())
- ob_cols.append(l_row.column())
-
- row = ob_cols[0].row()
- meshes = [o for o in objects.values() if o.type == 'MESH']
- num = len(meshes)
- row.label(text=quantity_string(num, "Mesh", "Meshes"),
- icon='MESH_DATA')
-
- row = ob_cols[1].row()
- curves = [o for o in objects.values() if o.type == 'CURVE']
- num = len(curves)
- row.label(text=quantity_string(num, "Curve", "Curves"),
- icon='CURVE_DATA')
-
- row = ob_cols[0].row()
- cameras = [o for o in objects.values() if o.type == 'CAMERA']
- num = len(cameras)
- row.label(text=quantity_string(num, "Camera", "Cameras"),
- icon='CAMERA_DATA')
-
- row = ob_cols[1].row()
- lamps = [o for o in objects.values() if o.type == 'LAMP']
- num = len(lamps)
- row.label(text=quantity_string(num, "Lamp", "Lamps"),
- icon='LAMP_DATA')
-
- row = ob_cols[0].row()
- armatures = [o for o in objects.values() if o.type == 'ARMATURE']
- num = len(armatures)
- row.label(text=quantity_string(num, "Armature", "Armatures"),
- icon='ARMATURE_DATA')
-
- row = ob_cols[1].row()
- lattices = [o for o in objects.values() if o.type == 'LATTICE']
- num = len(lattices)
- row.label(text=quantity_string(num, "Lattice", "Lattices"),
- icon='LATTICE_DATA')
-
- row = ob_cols[0].row()
- empties = [o for o in objects.values() if o.type == 'EMPTY']
- num = len(empties)
- row.label(text=quantity_string(num, "Empty", "Empties"),
- icon='EMPTY_DATA')
-
- l_row_sep = layout.separator()
-
- # DATABLOCKS
-
- l_row = layout.row()
- num = len(bpy.data.objects)
- l_row.label(text="Datablocks in the scene:")
-
- l_row = layout.row()
- db_cols.append(l_row.column())
- db_cols.append(l_row.column())
-
- row = db_cols[0].row()
- num = len(bpy.data.meshes)
- row.label(text=quantity_string(num, "Mesh", "Meshes"),
- icon='MESH_DATA')
-
- row = db_cols[1].row()
- num = len(bpy.data.curves)
- row.label(text=quantity_string(num, "Curve", "Curves"),
- icon='CURVE_DATA')
-
- row = db_cols[0].row()
- num = len(bpy.data.cameras)
- row.label(text=quantity_string(num, "Camera", "Cameras"),
- icon='CAMERA_DATA')
-
- row = db_cols[1].row()
- num = len(bpy.data.lamps)
- row.label(text=quantity_string(num, "Lamp", "Lamps"),
- icon='LAMP_DATA')
-
- row = db_cols[0].row()
- num = len(bpy.data.armatures)
- row.label(text=quantity_string(num, "Armature", "Armatures"),
- icon='ARMATURE_DATA')
-
- row = db_cols[1].row()
- num = len(bpy.data.lattices)
- row.label(text=quantity_string(num, "Lattice", "Lattices"),
- icon='LATTICE_DATA')
-
- row = db_cols[0].row()
- num = len(bpy.data.materials)
- row.label(text=quantity_string(num, "Material", "Materials"),
- icon='MATERIAL_DATA')
-
- row = db_cols[1].row()
- num = len(bpy.data.worlds)
- row.label(text=quantity_string(num, "World", "Worlds"),
- icon='WORLD_DATA')
-
- row = db_cols[0].row()
- num = len(bpy.data.textures)
- row.label(text=quantity_string(num, "Texture", "Textures"),
- icon='TEXTURE_DATA')
-
- row = db_cols[1].row()
- num = len(bpy.data.images)
- row.label(text=quantity_string(num, "Image", "Images"),
- icon='IMAGE_DATA')
-
- row = db_cols[0].row()
- num = len(bpy.data.texts)
- row.label(text=quantity_string(num, "Text", "Texts"),
- icon='TEXT')
-
-
-def register():
- pass
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()