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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2009-09-19 02:25:49 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2009-09-19 02:25:49 +0400
commitbe50ce61be7fdc96943dbdac79aabd88ba29996f (patch)
tree4dfde72478458923a3b2ce8d22e1658d4508024c /release/scripts
parent0a4d70f4d0ddc5bc709b162d84ec334e66ed848d (diff)
Merged
https://svn.blender.org/svnroot/bf-blender/branches/soc-2008-mxcurioni (r22789) and https://svn.blender.org/svnroot/bf-blender/trunk/blender (r23338) with the "Ignore ancestry" and "Ignore line endings" options enabled (using TortoiseSVN on Windows). After the merge operation, all changes (i.e., deletion) in source/blender/freestyle/ were reverted in order to keep the primary source tree of the Freestyle renderer.
Diffstat (limited to 'release/scripts')
-rw-r--r--release/scripts/3ds_export.py12
-rw-r--r--release/scripts/3ds_import.py19
-rw-r--r--release/scripts/DirectX8Exporter.py3
-rw-r--r--release/scripts/ac3d_import.py30
-rw-r--r--release/scripts/add_mesh_torus.py8
-rw-r--r--release/scripts/animation_bake_constraints.py2
-rw-r--r--release/scripts/animation_clean.py192
-rw-r--r--release/scripts/bevel_center.py2
-rw-r--r--release/scripts/bpymodules/BPyImage.py19
-rw-r--r--release/scripts/bpymodules/BPyMathutils.py17
-rw-r--r--release/scripts/bpymodules/BPyMesh.py8
-rw-r--r--release/scripts/bpymodules/BPyMesh_octree.py332
-rw-r--r--release/scripts/bpymodules/BPyMesh_redux.py5
-rw-r--r--release/scripts/bpymodules/BPySys.py60
-rw-r--r--release/scripts/bpymodules/BPyWindow.py2
-rw-r--r--release/scripts/bpymodules/dxfLibrary.py392
-rw-r--r--release/scripts/bpymodules/mesh_gradient.py6
-rw-r--r--release/scripts/bpymodules/paths_svg2obj.py211
-rw-r--r--release/scripts/bvh_import.py11
-rw-r--r--release/scripts/c3d_import.py7
-rw-r--r--release/scripts/console.py75
-rw-r--r--release/scripts/envelope_symmetry.py2
-rw-r--r--release/scripts/export_dxf.py3166
-rw-r--r--release/scripts/export_fbx.py313
-rw-r--r--release/scripts/export_m3g.py2
-rw-r--r--release/scripts/export_map.py23
-rw-r--r--release/scripts/export_obj.py208
-rw-r--r--release/scripts/flt_properties.py1
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/brown00.pngbin22195 -> 0 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray00.pngbin18513 -> 0 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray01.pngbin9915 -> 0 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray02.pngbin7197 -> 0 bytes
-rwxr-xr-xrelease/scripts/freestyle/data/env_map/gray03.pngbin16109 -> 0 bytes
-rwxr-xr-xrelease/scripts/freestyle/style_modules/ChainingIterators.py731
-rwxr-xr-xrelease/scripts/freestyle/style_modules/Functions0D.py81
-rwxr-xr-xrelease/scripts/freestyle/style_modules/Functions1D.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesB1D.py70
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesU0D.py103
-rwxr-xr-xrelease/scripts/freestyle/style_modules/PredicatesU1D.py381
-rwxr-xr-xrelease/scripts/freestyle/style_modules/anisotropic_diffusion.py74
-rwxr-xr-xrelease/scripts/freestyle/style_modules/apriori_and_causal_density.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/apriori_density.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/backbone_stretcher.py36
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_circles.py46
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_ellipses.py46
-rwxr-xr-xrelease/scripts/freestyle/style_modules/blueprint_squares.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/cartoon.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/contour.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/curvature2d.py60
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour_sketchy.py48
-rwxr-xr-xrelease/scripts/freestyle/style_modules/external_contour_smooth.py44
-rwxr-xr-xrelease/scripts/freestyle/style_modules/extra-lines.sml3
-rw-r--r--release/scripts/freestyle/style_modules/freestyle_init.py2
-rwxr-xr-xrelease/scripts/freestyle/style_modules/haloing.py50
-rwxr-xr-xrelease/scripts/freestyle/style_modules/ignore_small_occlusions.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/invisible_lines.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/japanese_bigbrush.py60
-rwxr-xr-xrelease/scripts/freestyle/style_modules/logical_operators.py36
-rwxr-xr-xrelease/scripts/freestyle/style_modules/long_anisotropically_dense.py81
-rwxr-xr-xrelease/scripts/freestyle/style_modules/multiple_parameterization.py51
-rwxr-xr-xrelease/scripts/freestyle/style_modules/nature.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/near_lines.py44
-rwxr-xr-xrelease/scripts/freestyle/style_modules/occluded_by_specific_object.py45
-rwxr-xr-xrelease/scripts/freestyle/style_modules/polygonalize.py40
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi0.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi0_not_external_contour.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi1.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/qi2.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sequentialsplit_sketchy.py68
-rwxr-xr-xrelease/scripts/freestyle/style_modules/shaders.py1286
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py48
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_topology_broken.py89
-rwxr-xr-xrelease/scripts/freestyle/style_modules/sketchy_topology_preserved.py49
-rwxr-xr-xrelease/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py41
-rwxr-xr-xrelease/scripts/freestyle/style_modules/split_at_tvertices.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/stroke_texture.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/suggestive.py43
-rwxr-xr-xrelease/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py62
-rwxr-xr-xrelease/scripts/freestyle/style_modules/tipremover.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/tvertex_remover.py42
-rwxr-xr-xrelease/scripts/freestyle/style_modules/uniformpruning_zsort.py40
-rwxr-xr-xrelease/scripts/freestyle/style_modules/vector.py241
-rw-r--r--release/scripts/help_bpy_api.py18
-rw-r--r--release/scripts/help_browser.py30
-rw-r--r--release/scripts/help_getting_started.py43
-rw-r--r--release/scripts/help_manual.py41
-rw-r--r--release/scripts/help_release_notes.py41
-rw-r--r--release/scripts/help_tutorials.py42
-rw-r--r--release/scripts/help_web_devcomm.py41
-rw-r--r--release/scripts/help_web_eshop.py41
-rw-r--r--release/scripts/help_web_usercomm.py41
-rw-r--r--release/scripts/image_2d_cutout.py559
-rw-r--r--release/scripts/image_auto_layout.py18
-rw-r--r--release/scripts/image_edit.py72
-rw-r--r--release/scripts/import_dxf.py826
-rw-r--r--release/scripts/import_edl.py961
-rw-r--r--release/scripts/import_lightwave_motion.py2
-rw-r--r--release/scripts/import_obj.py400
-rw-r--r--[-rwxr-xr-x]release/scripts/import_web3d.py1106
-rw-r--r--release/scripts/lightwave_export.py61
-rw-r--r--release/scripts/md2_export.py106
-rw-r--r--release/scripts/mesh_edges2curves.py6
-rw-r--r--release/scripts/mesh_mirror_tool.py8
-rw-r--r--release/scripts/mesh_poly_reduce_grid.py351
-rw-r--r--release/scripts/mesh_skin.py8
-rw-r--r--release/scripts/mesh_unfolder.py6
-rw-r--r--release/scripts/object_active_to_other.py (renamed from release/scripts/help_web_blender.py)54
-rw-r--r--release/scripts/object_cookie_cutter.py24
-rw-r--r--release/scripts/object_drop.py64
-rw-r--r--release/scripts/ply_export.py228
-rw-r--r--release/scripts/ply_import.py21
-rw-r--r--release/scripts/rvk1_torvk2.py394
-rw-r--r--release/scripts/scripttemplate_background_job.py124
-rw-r--r--release/scripts/scripttemplate_camera_object.py (renamed from release/scripts/scripttemplate_camer_object.py)0
-rw-r--r--release/scripts/scripttemplate_gamelogic.py58
-rw-r--r--release/scripts/scripttemplate_gamelogic_basic.py14
-rw-r--r--release/scripts/scripttemplate_gamelogic_module.py45
-rw-r--r--release/scripts/textplugin_convert_ge.py863
-rw-r--r--release/scripts/uvcalc_follow_active_coords.py47
-rw-r--r--release/scripts/uvcalc_quad_clickproj.py10
-rw-r--r--release/scripts/uvcalc_smart_project.py20
-rw-r--r--release/scripts/vertexpaint_from_material.py3
-rw-r--r--release/scripts/vertexpaint_selfshadow_ao.py78
-rw-r--r--release/scripts/wizard_bolt_factory.py2811
-rw-r--r--release/scripts/wizard_curve2tree.py34
-rw-r--r--release/scripts/wizard_landscape_ant.py2148
-rw-r--r--release/scripts/xfig_export.py234
128 files changed, 14231 insertions, 7866 deletions
diff --git a/release/scripts/3ds_export.py b/release/scripts/3ds_export.py
index 54e1ea3db33..87680bce1b0 100644
--- a/release/scripts/3ds_export.py
+++ b/release/scripts/3ds_export.py
@@ -7,7 +7,7 @@ Group: 'Export'
Tooltip: 'Export to 3DS file format (.3ds).'
"""
-__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
+__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
__version__ = "0.90a"
__bpydoc__ = """\
@@ -50,7 +50,10 @@ import Blender
import bpy
from BPyMesh import getMeshFromObject
from BPyObject import getDerivedObjects
-import struct
+try:
+ import struct
+except:
+ struct = None
# So 3ds max can open files, limit names to 12 in length
# this is verry annoying for filenames!
@@ -1009,5 +1012,8 @@ def save_3ds(filename):
if __name__=='__main__':
- Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds'))
+ if struct:
+ Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds'))
+ else:
+ Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
# save_3ds('/test_b.3ds')
diff --git a/release/scripts/3ds_import.py b/release/scripts/3ds_import.py
index 028b9633606..bcde82c4869 100644
--- a/release/scripts/3ds_import.py
+++ b/release/scripts/3ds_import.py
@@ -133,10 +133,12 @@ import BPyImage
import BPyMessages
-import struct
-from struct import calcsize, unpack
+try:
+ from struct import calcsize, unpack
+except:
+ calcsize= unpack= None
+
-import os
# If python version is less than 2.4, try to get set stuff from module
try:
@@ -844,11 +846,13 @@ def load_3ds(filename, PREF_UI= True):
# IMPORT_AS_INSTANCE= Blender.Draw.Create(0)
IMPORT_CONSTRAIN_BOUNDS= Blender.Draw.Create(10.0)
IMAGE_SEARCH= Blender.Draw.Create(1)
+ APPLY_MATRIX= Blender.Draw.Create(0)
# Get USER Options
pup_block= [\
('Size Constraint:', IMPORT_CONSTRAIN_BOUNDS, 0.0, 1000.0, 'Scale the model by 10 until it reacehs the size constraint. Zero Disables.'),\
('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\
+ ('Transform Fix', APPLY_MATRIX, 'Workaround for object transformations importing incorrectly'),\
#('Group Instance', IMPORT_AS_INSTANCE, 'Import objects into a new scene and group, creating an instance in the current scene.'),\
]
@@ -861,6 +865,7 @@ def load_3ds(filename, PREF_UI= True):
IMPORT_CONSTRAIN_BOUNDS= IMPORT_CONSTRAIN_BOUNDS.val
# IMPORT_AS_INSTANCE= IMPORT_AS_INSTANCE.val
IMAGE_SEARCH = IMAGE_SEARCH.val
+ APPLY_MATRIX = APPLY_MATRIX.val
if IMPORT_CONSTRAIN_BOUNDS:
BOUNDS_3DS[:]= [1<<30, 1<<30, 1<<30, -1<<30, -1<<30, -1<<30]
@@ -887,6 +892,8 @@ def load_3ds(filename, PREF_UI= True):
if ob.type=='Mesh':
me= ob.getData(mesh=1)
me.verts.delete([me.verts[0],])
+ if not APPLY_MATRIX:
+ me.transform(ob.matrixWorld.copy().invert())
# Done DUMMYVERT
"""
@@ -953,7 +960,10 @@ def load_3ds(filename, PREF_UI= True):
DEBUG= False
if __name__=='__main__' and not DEBUG:
- Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds')
+ if calcsize==None:
+ Blender.Draw.PupMenu('Error%t|a full python installation not found')
+ else:
+ Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds')
# For testing compatibility
#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False)
@@ -961,6 +971,7 @@ if __name__=='__main__' and not DEBUG:
'''
else:
+ import os
# DEBUG ONLY
TIME= Blender.sys.time()
import os
diff --git a/release/scripts/DirectX8Exporter.py b/release/scripts/DirectX8Exporter.py
index b8bdae4de2b..8a0ecaf0eb7 100644
--- a/release/scripts/DirectX8Exporter.py
+++ b/release/scripts/DirectX8Exporter.py
@@ -45,7 +45,8 @@ from Blender import Types, Object, NMesh, Material,Armature,Mesh
from Blender.Mathutils import *
from Blender import Draw, BGL
from Blender.BGL import *
-import math
+try: import math
+except: math = None
global mat_flip,index_list,space,bone_list,mat_dict
global anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_norm
diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py
index 6a2b290e010..2f5512e7150 100644
--- a/release/scripts/ac3d_import.py
+++ b/release/scripts/ac3d_import.py
@@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.'
__author__ = "Willian P. Germano"
__url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org",
"PLib 3d gaming lib, http://plib.sf.net")
-__version__ = "2.43.1 2007-02-21"
+__version__ = "2.48.1 2009-01-11"
__bpydoc__ = """\
This script imports AC3D models into Blender.
@@ -31,6 +31,7 @@ Known issues:<br>
Config Options:<br>
- display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br>
- subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br>
+ - emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.<br>
- textures dir (string): if non blank, when imported texture paths are
wrong in the .ac file, Blender will also look for them at this dir.
@@ -50,11 +51,12 @@ users can configure (see config options above).
# --------------------------------------------------------------------------
# Thanks: Melchior Franz for extensive bug testing and reporting, making this
# version cope much better with old or bad .ac files, among other improvements;
-# Stewart Andreason for reporting a serious crash.
+# Stewart Andreason for reporting a serious crash; Francesco Brisa for the
+# emis as mircol functionality (w/ patch).
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
-# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br
+# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -89,15 +91,19 @@ DISPLAY_TRANSP = True
SUBDIV = True
+EMIS_AS_MIRCOL = False
+
+
tooltips = {
'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.',
'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.',
- 'TEXTURES_DIR': 'Additional folder to look for missing textures.'
+ 'TEXTURES_DIR': 'Additional folder to look for missing textures.',
+ 'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.'
}
def update_registry():
- global TEXTURES_DIR, DISPLAY_TRANSP
- rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV)])
+ global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL
+ rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)])
Registry.SetKey('ac3d_import', rd, True)
rd = Registry.GetKey('ac3d_import', True)
@@ -109,6 +115,7 @@ if rd:
TEXTURES_DIR = rd['TEXTURES_DIR']
DISPLAY_TRANSP = rd['DISPLAY_TRANSP']
SUBDIV = rd['SUBDIV']
+ EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL']
except:
update_registry()
else: update_registry()
@@ -299,7 +306,7 @@ class AC3DImport:
lines = self.lines
line = lines[i].split()
mat_name = ''
- mat_col = mat_amb = mat_emit = mat_spec_col = [0,0,0]
+ mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0]
mat_alpha = 1
mat_spec = 1.0
@@ -310,11 +317,15 @@ class AC3DImport:
mat_amb = (v[0]+v[1]+v[2]) / 3.0
v = map(float,[line[11],line[12],line[13]])
mat_emit = (v[0]+v[1]+v[2]) / 3.0
+ if EMIS_AS_MIRCOL:
+ mat_emit = 0
+ mat_mir_col = map(float,[line[11],line[12],line[13]])
+
mat_spec_col = map(float,[line[15],line[16],line[17]])
mat_spec = float(line[19]) / 64.0
mat_alpha = float(line[-1])
mat_alpha = 1 - mat_alpha
- self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_alpha])
+ self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha])
i += 1
line = lines[i].split()
@@ -590,7 +601,8 @@ class AC3DImport:
m.emit = mat[3]
m.specCol = (mat[4][0], mat[4][1], mat[4][2])
m.spec = mat[5]
- m.alpha = mat[6]
+ m.mirCol = (mat[6][0], mat[6][1], mat[6][2])
+ m.alpha = mat[7]
if m.alpha < 1.0:
m.mode |= MAT_MODE_ZTRANSP
has_transp_mats = True
diff --git a/release/scripts/add_mesh_torus.py b/release/scripts/add_mesh_torus.py
index 4f759256497..2941c56420e 100644
--- a/release/scripts/add_mesh_torus.py
+++ b/release/scripts/add_mesh_torus.py
@@ -6,7 +6,8 @@ Group: 'AddMesh'
"""
import BPyAddMesh
import Blender
-from math import cos, sin, pi
+try: from math import cos, sin, pi
+except: math = None
def add_torus(PREF_MAJOR_RAD, PREF_MINOR_RAD, PREF_MAJOR_SEG, PREF_MINOR_SEG):
Vector = Blender.Mathutils.Vector
@@ -61,5 +62,8 @@ def main():
BPyAddMesh.add_mesh_simple('Torus', verts, [], faces)
-main()
+if cos and sin and pi:
+ main()
+else:
+ Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/animation_bake_constraints.py b/release/scripts/animation_bake_constraints.py
index 58e9e2b1d02..16855828460 100644
--- a/release/scripts/animation_bake_constraints.py
+++ b/release/scripts/animation_bake_constraints.py
@@ -155,7 +155,7 @@ usrObjectNamePrefix= ""
# if that armature had bones (spine, neck, arm) and the bone prefix was "a."
# the bones and IPO curves will be (a.spine, a.neck, a.arm)
-R2D = 18/3.1415 # radian to grad
+R2D = 18/3.141592653589793 # radian to grad
BLENDER_VERSION = Blender.Get('version')
# Gets the current scene, there can be many scenes in 1 blend file.
diff --git a/release/scripts/animation_clean.py b/release/scripts/animation_clean.py
new file mode 100644
index 00000000000..fc44f264ac1
--- /dev/null
+++ b/release/scripts/animation_clean.py
@@ -0,0 +1,192 @@
+#!BPY
+
+"""
+Name: 'Clean Animation Curves'
+Blender: 249
+Group: 'Animation'
+Tooltip: 'Remove unused keyframes for ipo curves'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2008-2009: Blender Foundation
+#
+# 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,
+# --------------------------------------------------------------------------
+
+import bpy
+from Blender import IpoCurve, Draw, Window
+
+def clean_ipos(ipos):
+ eul = 0.001
+
+ def isflat(vec):
+ prev_y = vec[0][1]
+ mid_y = vec[1][1]
+ next_y = vec[2][1]
+
+ # flat status for prev and next
+ return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul
+
+
+
+ X=0
+ Y=1
+ PREV=0
+ MID=1
+ NEXT=2
+
+ LEFT = 0
+ RIGHT = 1
+
+ TOT = 0
+ TOTBEZ = 0
+ # for ipo in bpy.data.ipos:
+ for ipo in ipos:
+ if ipo.lib:
+ continue
+ # print ipo
+ for icu in ipo:
+ interp = icu.interpolation
+ extend = icu.extend
+
+ bezierPoints = icu.bezierPoints
+ bezierVecs = [bez.vec for bez in bezierPoints]
+
+ l = len(bezierPoints)
+
+ TOTBEZ += l
+
+ # our aim is to simplify this ipo as much as possible!
+ if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR:
+ #print "Not yet supported"
+
+ if interp == IpoCurve.InterpTypes.BEZIER:
+ flats = [isflat(bez) for bez in bezierVecs]
+ else:
+ # A bit of a waste but fake the locations for these so they will always be flats
+ # IS better then too much duplicate code.
+ flats = [(True, True)] * l
+ for v in bezierVecs:
+ v[PREV][Y] = v[NEXT][Y] = v[MID][Y]
+
+
+ # remove middle points
+ if l>2:
+ done_nothing = False
+
+ while not done_nothing and len(bezierVecs) > 2:
+ done_nothing = True
+ i = l-2
+
+ while i > 0:
+ #print i
+ #print i, len(bezierVecs)
+ if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]:
+
+ if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul:
+ done_nothing = False
+
+ del flats[i]
+ del bezierVecs[i]
+ icu.delBezier(i)
+ TOT += 1
+ l-=1
+ i-=1
+
+ # remove endpoints
+ if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1:
+ #print l, len(bezierVecs)
+ # start
+
+ while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)):
+ print "\tremoving 1 point from start of the curve"
+ del flats[0]
+ del bezierVecs[0]
+ icu.delBezier(0)
+ TOT += 1
+ l-=1
+
+
+ # End
+ while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul):
+ print "\tremoving 1 point from end of the curve", l
+ del flats[l-1]
+ del bezierVecs[l-1]
+ icu.delBezier(l-1)
+ TOT += 1
+ l-=1
+
+
+
+ if l==2:
+ if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul:
+ # remove the second point
+ print "\tremoving 1 point from 2 point bez curve"
+ # remove the second point
+ del flats[1]
+ del bezierVecs[1]
+ icu.delBezier(1)
+ TOT+=1
+ l-=1
+
+ # Change to linear for faster evaluation
+ '''
+ if l==1:
+ print 'Linear'
+ icu.interpolation = IpoCurve.InterpTypes.LINEAR
+ '''
+
+
+
+
+ if interp== IpoCurve.InterpTypes.CONST:
+ print "Not yet supported"
+
+ print 'total', TOT, TOTBEZ
+ return TOT, TOTBEZ
+
+def main():
+ ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3')
+
+ sce = bpy.data.scenes.active
+ ipos = []
+
+ if ret == 3:
+ ipos.extend(list(bpy.data.ipos))
+ else:
+ for ob in sce.objects.context:
+ if ret == 1:
+ ipo = ob.ipo
+ if ipo:
+ ipos.append(ipo)
+
+ elif ret == 2:
+ action = ob.action
+ if action:
+ ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo])
+
+
+
+ if not ipos:
+ Draw.PupMenu('Error%t|No ipos found')
+ else:
+ total_removed, total = clean_ipos(ipos)
+ Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points')
+
+ Window.RedrawAll()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py
index 063c6380483..637ed08127f 100644
--- a/release/scripts/bevel_center.py
+++ b/release/scripts/bevel_center.py
@@ -1,5 +1,5 @@
#!BPY
-# coding: utf-8
+# -*- coding: utf-8 -*-
""" Registration info for Blender menus
Name: 'Bevel Center'
Blender: 243
diff --git a/release/scripts/bpymodules/BPyImage.py b/release/scripts/bpymodules/BPyImage.py
index 2c342ddec39..504e4ee29ba 100644
--- a/release/scripts/bpymodules/BPyImage.py
+++ b/release/scripts/bpymodules/BPyImage.py
@@ -79,7 +79,7 @@ def addSlash(path):
return path + sys.sep
-def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False):
+def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False, CONVERT_CALLBACK=None):
'''
imagePath: The image filename
If a path precedes it, this will be searched as well.
@@ -93,13 +93,30 @@ def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=Tr
RECURSIVE: If True, directories will be recursivly searched.
Be carefull with this if you have files in your root directory because it may take a long time.
+
+ CASE_INSENSITIVE: for non win32 systems, find the correct case for the file.
+
+ CONVERT_CALLBACK: a function that takes an existing path and returns a new one.
+ Use this when loading image formats blender may not support, the CONVERT_CALLBACK
+ can take the path for a GIF (for example), convert it to a PNG and return the PNG's path.
+ For formats blender can read, simply return the path that is given.
'''
+ # VERBOSE = True
+
if VERBOSE: print 'img:', imagePath, 'file:', filePath
+
+ if os == None and CASE_INSENSITIVE:
+ CASE_INSENSITIVE = True
+
# When we have the file load it with this. try/except niceness.
def imageLoad(path):
#if path.endswith('\\') or path.endswith('/'):
# raise 'INVALID PATH'
+
+ if CONVERT_CALLBACK:
+ path = CONVERT_CALLBACK(path)
+
try:
img = bpy.data.images.new(filename=path)
if VERBOSE: print '\t\tImage loaded "%s"' % path
diff --git a/release/scripts/bpymodules/BPyMathutils.py b/release/scripts/bpymodules/BPyMathutils.py
index 27736b4169e..4882e9aaf21 100644
--- a/release/scripts/bpymodules/BPyMathutils.py
+++ b/release/scripts/bpymodules/BPyMathutils.py
@@ -132,7 +132,6 @@ modified for Blender/Mathutils by Campell Barton
######################################################################
# Public interface
######################################################################
-from Blender.Mathutils import DotVecs
def convexHull(point_list_2d):
"""Calculate the convex hull of a set of vectors
The vectors can be 3 or 4d but only the Xand Y are used.
@@ -197,7 +196,7 @@ def plane2mat(plane, normalize= False):
up= cent - ((plane[0]+plane[1])/2.0)
right= cent - ((plane[1]+plane[2])/2.0)
- z= CrossVecs(up, right)
+ z= up.cross(right)
if normalize:
up.normalize()
@@ -225,15 +224,5 @@ from math import pi, sin, cos, sqrt
def angleToLength(angle):
# Alredy accounted for
- if angle < 0.000001:
- return 1.0
-
- angle = 2*pi*angle/360
- x,y = cos(angle), sin(angle)
- # print "YX", x,y
- # 0 d is hoz to the right.
- # 90d is vert upward.
- fac=1/x
- x=x*fac
- y=y*fac
- return sqrt((x*x)+(y*y))
+ if angle < 0.000001: return 1.0
+ else: return abs(1.0 / cos(pi*angle/180));
diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py
index 415c2a12c69..292f7a4b91e 100644
--- a/release/scripts/bpymodules/BPyMesh.py
+++ b/release/scripts/bpymodules/BPyMesh.py
@@ -479,7 +479,7 @@ def pickMeshRayFaceWeight(me, orig, rdir):
w0 = (l1+l2)
w1 = (l0+l2)
- w2 = (l1+l2)
+ w2 = (l1+l0)
totw= w0 + w1 + w2
w0=w0/totw
@@ -569,12 +569,11 @@ def face_edges(me):
def facesPlanerIslands(me):
- DotVecs= Blender.Mathutils.DotVecs
def roundvec(v):
return round(v[0], 4), round(v[1], 4), round(v[2], 4)
- face_props= [(cent, no, roundvec(no), DotVecs(cent, no)) for f in me.faces for no, cent in ((f.no, f.cent),)]
+ face_props= [(cent, no, roundvec(no), cent.dot(no)) for f in me.faces for no, cent in ((f.no, f.cent),)]
face_edge_users= face_edges(me)
islands= []
@@ -607,7 +606,7 @@ def facesPlanerIslands(me):
face_prop2= face_props[fidx2]
# normals are the same?
if face_prop1[2]==face_prop2[2]:
- if abs(face_prop1[3] - DotVecs(face_prop1[1], face_prop2[0])) < 0.000001:
+ if abs(face_prop1[3] - face_prop1[1].dot(face_prop2[0])) < 0.000001:
used_faces[fidx2]= 1
island.append(fidx2)
islands.append([me.faces[i] for i in island])
@@ -616,7 +615,6 @@ def facesPlanerIslands(me):
def facesUvIslands(me, PREF_IMAGE_DELIMIT=True):
- DotVecs= Blender.Mathutils.DotVecs
def roundvec(v):
return round(v[0], 4), round(v[1], 4)
diff --git a/release/scripts/bpymodules/BPyMesh_octree.py b/release/scripts/bpymodules/BPyMesh_octree.py
deleted file mode 100644
index 368a33496eb..00000000000
--- a/release/scripts/bpymodules/BPyMesh_octree.py
+++ /dev/null
@@ -1,332 +0,0 @@
-from Blender import *
-
-try:
- import psyco
- psyco.full()
-except:
- print 'no psyco for you!'
-
-DotVecs= Mathutils.DotVecs
-#========================================================
-# SPACIAL TREE - Seperate Class - use if you want to
-# USed for getting vert is a proximity
-LEAF_SIZE = 128
-class octreeNode:
- def __init__(self, verts, parent):
-
- # Assunme we are a leaf node, until split is run.
- self.verts = verts
- self.children = []
-
- if parent == None: # ROOT NODE, else set bounds when making children,
- # BOUNDS
- v= verts[0]
- maxx,maxy,maxz= v.co
- minx,miny,minz= maxx,maxy,maxz
-
- for v in verts:
- x,y,z= v.co
- if x>maxx: maxx= x
- if y>maxy: maxy= y
- if z>maxz: maxz= z
-
- if x<minx: minx= x
- if y<miny: miny= y
- if z<minz: minz= z
-
- self.minx= minx
- self.miny= miny
- self.minz= minz
-
- self.maxx= maxx
- self.maxy= maxy
- self.maxz= maxz
-
- # We have no parent to split us so split ourselves.
- #self.setCornerPoints()
- self.splitNode()
-
- def splitNode(self):
- if len(self.verts) > LEAF_SIZE:
- self.makeChildren() # 8 new children,
- self.verts = None
- # Alredy assumed a leaf not so dont do anything here.
-
- def makeChildren(self):
- verts= self.verts
- # Devide into 8 children.
- axisDividedVerts = [[],[],[],[],[],[],[],[]] # Verts Only
-
-
- divx = (self.maxx + self.minx) / 2
- divy = (self.maxy + self.miny) / 2
- divz = (self.maxz + self.minz) / 2
-
- # Sort into 8
- for v in verts:
- x,y,z = v.co
-
- if x > divx:
- if y > divy:
- if z > divz:
- axisDividedVerts[0].append(v)
- else:
- axisDividedVerts[1].append(v)
- else:
- if z > divz:
- axisDividedVerts[2].append(v)
- else:
- axisDividedVerts[3].append(v)
- else:
- if y > divy:
- if z > divz:
- axisDividedVerts[4].append(v)
- else:
- axisDividedVerts[5].append(v)
- else:
- if z > divz:
- axisDividedVerts[6].append(v)
- else:
- axisDividedVerts[7].append(v)
-
- # populate self.children
- for i in xrange(8):
- octNode = octreeNode(axisDividedVerts[i], self)
- # Set bounds manually
- if i == 0:
- octNode.minx = divx
- octNode.maxx = self.maxx
- octNode.miny = divy
- octNode.maxy = self.maxy
- octNode.minz = divz
- octNode.maxz = self.maxz
- elif i == 1:
- octNode.minx = divx
- octNode.maxx = self.maxx
- octNode.miny = divy
- octNode.maxy = self.maxy
- octNode.minz = self.minz #
- octNode.maxz = divz #
- elif i == 2:
- octNode.minx = divx
- octNode.maxx = self.maxx
- octNode.miny = self.miny #
- octNode.maxy = divy #
- octNode.minz = divz
- octNode.maxz = self.maxz
- elif i == 3:
- octNode.minx = divx
- octNode.maxx = self.maxx
- octNode.miny = self.miny #
- octNode.maxy = divy #
- octNode.minz = self.minz #
- octNode.maxz = divz #
- elif i == 4:
- octNode.minx = self.minx #
- octNode.maxx = divx #
- octNode.miny = divy
- octNode.maxy = self.maxy
- octNode.minz = divz
- octNode.maxz = self.maxz
- elif i == 5:
- octNode.minx = self.minx #
- octNode.maxx = divx #
- octNode.miny = divy
- octNode.maxy = self.maxy
- octNode.minz = self.minz #
- octNode.maxz = divz #
- elif i == 6:
- octNode.minx = self.minx #
- octNode.maxx = divx #
- octNode.miny = self.miny #
- octNode.maxy = divy #
- octNode.minz = divz
- octNode.maxz = self.maxz
- elif i == 7:
- octNode.minx = self.minx #
- octNode.maxx = divx #
- octNode.miny = self.miny #
- octNode.maxy = divy #
- octNode.minz = self.minz #
- octNode.maxz = divz #
- #octNode.setCornerPoints()
- octNode.splitNode() # Splits the node if it can.
- self.children.append(octNode)
-
- # GETS VERTS IN A Distance RANGE-
- def getVertsInRange(self, loc, normal, range_val, vertList):
- #loc= Mathutils.Vector(loc) # MUST BE VECTORS
- #normal= Mathutils.Vector(normal)
-
- '''
- loc: Vector of the location to search from
- normal: None or Vector - if a vector- will only get verts on this side of the vector
- range_val: maximum distance. A negative value will fill the list with teh closest vert only.
- vertList: starts as an empty list
- list that this function fills with verts that match
- '''
- xloc,yloc,zloc= loc
-
- if range_val<0:
- range_val= -range_val
- FIND_CLOSEST= True
- vertList.append(None) # just update the 1 vertex
- else:
- FIND_CLOSEST= False
-
- if self.children:
- # Check if the bounds are in range_val,
- for childNode in self.children:
- # First test if we are surrounding the point.
- if\
- childNode.minx - range_val < xloc and\
- childNode.maxx + range_val > xloc and\
- childNode.miny - range_val < yloc and\
- childNode.maxy + range_val > yloc and\
- childNode.minz - range_val < zloc and\
- childNode.maxz + range_val > zloc:
- # Recurse down or get virts.
- childNode.getVertsInRange(loc, normal, range_val, vertList)
- #continue # Next please
-
- else: # we are a leaf node. Test vert locations.
- if not normal:
- # Length only check
- for v in self.verts:
- length = (loc - v.co).length
- if length < range_val:
- if FIND_CLOSEST:
- # Just update the 1 vert
- vertList[0]= (v, length)
- range_val= length # Shink the length so we only get verts from their.
- else:
- vertList.append((v, length))
- else:
- # Lengh and am I infront of the vert.
- for v in self.verts:
- length = (loc - v.co).length
- if length < range_val:
- # Check if the points in front
- dot= DotVecs(normal, loc) - DotVecs(normal, v.co)
- if dot<0:
- vertList.append((v, length))
-
-# END TREE
-
-
-
-
-# EXAMPLE RADIO IN PYTHON USING THE ABOVE FUNCTION
-"""
-import BPyMesh
-# Radio bake
-def bake():
-
- _AngleBetweenVecs_= Mathutils.AngleBetweenVecs
- def AngleBetweenVecs(a1,a2):
- try:
- return _AngleBetweenVecs_(a1,a2)
- except:
- return 180
-
-
-
- scn = Scene.GetCurrent()
- ob = scn.getActiveObject()
- me = ob.getData(mesh=1)
-
- dist= Draw.PupFloatInput('MaxDist:', 2.0, 0.1, 20.0, 0.1, 3)
- if dist==None:
- return
-
- # Make nice normals
- BPyMesh.meshCalcNormals(me)
-
-
- len_verts= len(me.verts)
- #me.sel= False
- meshOctTree = octreeNode(me.verts, None)
-
-
-
- # Store face areas
- vertex_areas= [0.0] * len_verts
-
- # Get vertex areas - all areas of face users
- for f in me.faces:
- a= f.area
- for v in f.v:
- vertex_areas[v.index] += a
-
-
-
- bias= 0.001
-
- t= sys.time()
-
- # Tone for the verts
- vert_tones= [0.0] * len_verts
- maxtone= 0.0
- mintone= 100000000
- for i, v in enumerate(me.verts):
- if not i%10:
- print 'verts to go', len_verts-i
- v_co= v.co
- v_no= v.no
- verts_in_range= []
- meshOctTree.getVertsInRange(v_co, v_no, dist, verts_in_range)
-
- tone= 0.0
- # These are verts in our range
- for test_v, length in verts_in_range:
- if bias<length:
- try:
- # Make sure this isnt a back facing vert
- normal_diff= AngleBetweenVecs(test_v.no, v_no)
- except:
- continue
-
- if normal_diff > 90: # were facing this vert
- #if 1:
- # Current value us between zz90 and 180
- # make between 0 and 90
- # so 0 is right angles and 90 is direct opposite vertex normal
- normal_diff= (normal_diff-90)
-
- # Vertex area needs to be taken into account so we dont have small faces over influencing.
- vertex_area= vertex_areas[test_v.index]
-
- # Get the angle the vertex is in location from the location and normal of the vert.
- above_diff= AngleBetweenVecs(test_v.co-v.co, v_no)
- ## Result will be between 0 :above and 90: horizon.. invert this so horizon has littel effect
- above_diff= 90-above_diff
- # dist-length or 1.0/length both work well
- tone= (dist-length) * vertex_area * above_diff * normal_diff
- vert_tones[i] += tone
-
- if maxtone<vert_tones[i]:
- maxtone= vert_tones[i]
- if mintone>vert_tones[i]:
- mintone= vert_tones[i]
-
-
- if not maxtone:
- Draw.PupMenu('No verts in range, use a larger range')
- return
-
- # Apply tones
- for f in me.faces:
- f_col= f.col
- for i, v in enumerate(f.v):
- c= f_col[i]
- v_index= v.index
- tone= int(((maxtone - vert_tones[v.index]) / maxtone) * 255 )
- #print tone
- c.r= c.g= c.b= tone
-
- print 'time', sys.time()-t
-
-
-if __name__=="__main__":
- bake()
-""" \ No newline at end of file
diff --git a/release/scripts/bpymodules/BPyMesh_redux.py b/release/scripts/bpymodules/BPyMesh_redux.py
index 1bcc6e9f7c8..5955d696fbd 100644
--- a/release/scripts/bpymodules/BPyMesh_redux.py
+++ b/release/scripts/bpymodules/BPyMesh_redux.py
@@ -25,7 +25,6 @@ import Blender
import bpy
Vector= Blender.Mathutils.Vector
Ang= Blender.Mathutils.AngleBetweenVecs
-CrossVecs= Blender.Mathutils.CrossVecs
MidpointVecs= Blender.Mathutils.MidpointVecs
import BPyMesh
@@ -198,8 +197,8 @@ def redux(ob, REDUX=0.5, BOUNDRY_WEIGHT=2.0, REMOVE_DOUBLES=False, FACE_AREA_WEI
# the point of collapsing.
# Enlarge so we know they intersect: self.length*2
- cv1= CrossVecs(v1no, CrossVecs(v1no, v1co-v2co))
- cv2= CrossVecs(v2no, CrossVecs(v2no, v2co-v1co))
+ cv1= v1no.cross(v1no.cross(v1co-v2co))
+ cv2= v2no.cross(v2no.cross(v2co-v1co))
# Scale to be less then the edge lengths.
cv2.length = cv1.length = 1
diff --git a/release/scripts/bpymodules/BPySys.py b/release/scripts/bpymodules/BPySys.py
index 594264fad84..a2d2120ebff 100644
--- a/release/scripts/bpymodules/BPySys.py
+++ b/release/scripts/bpymodules/BPySys.py
@@ -12,3 +12,63 @@ def cleanName(name):
for ch in invalid: name = name.replace(ch, '_')
return name
+def caseInsensitivePath(path, RET_FOUND=False):
+ '''
+ Get a case insensitive path on a case sensitive system
+
+ RET_FOUND is for internal use only, to avoid too many calls to os.path.exists
+ # Example usage
+ getCaseInsensitivePath('/hOmE/mE/sOmEpAtH.tXt')
+ '''
+ import os # todo, what happens with no os?
+
+ if os==None:
+ if RET_FOUND: ret = path, True
+ else: ret = path
+ return ret
+
+ if path=='' or os.path.exists(path):
+ if RET_FOUND: ret = path, True
+ else: ret = path
+ return ret
+
+ f = os.path.basename(path) # f may be a directory or a file
+ d = os.path.dirname(path)
+
+ suffix = ''
+ if not f: # dir ends with a slash?
+ if len(d) < len(path):
+ suffix = path[:len(path)-len(d)]
+
+ f = os.path.basename(d)
+ d = os.path.dirname(d)
+
+ if not os.path.exists(d):
+ d, found = caseInsensitivePath(d, True)
+
+ if not found:
+ if RET_FOUND: ret = path, False
+ else: ret = path
+ return ret
+
+ # at this point, the directory exists but not the file
+
+ try: # we are expecting 'd' to be a directory, but it could be a file
+ files = os.listdir(d)
+ except:
+ if RET_FOUND: ret = path, False
+ else: ret = path
+
+ f_low = f.lower()
+
+ try: f_nocase = [fl for fl in files if fl.lower() == f_low][0]
+ except: f_nocase = None
+
+ if f_nocase:
+ if RET_FOUND: ret = os.path.join(d, f_nocase) + suffix, True
+ else: ret = os.path.join(d, f_nocase) + suffix
+ return ret
+ else:
+ if RET_FOUND: ret = path, False
+ else: ret = path
+ return ret # cant find the right one, just return the path as is. \ No newline at end of file
diff --git a/release/scripts/bpymodules/BPyWindow.py b/release/scripts/bpymodules/BPyWindow.py
index f48f5dfc0ad..d3fd4fa88b5 100644
--- a/release/scripts/bpymodules/BPyWindow.py
+++ b/release/scripts/bpymodules/BPyWindow.py
@@ -1,6 +1,6 @@
import Blender
from Blender import Mathutils, Window, Scene, Draw, Mesh
-from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect
+from Blender.Mathutils import Matrix, Vector, Intersect
# DESCRIPTION:
# screen_x, screen_y the origin point of the pick ray
diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py
index 5c63e7f5bf5..ccd8ef9b625 100644
--- a/release/scripts/bpymodules/dxfLibrary.py
+++ b/release/scripts/bpymodules/dxfLibrary.py
@@ -1,10 +1,10 @@
#dxfLibrary.py : provides functions for generating DXF files
# --------------------------------------------------------------------------
-__version__ = "v1.27beta - 2008.10.05"
-__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
+__version__ = "v1.33 - 2009.06.16"
+__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
__license__ = "GPL"
-__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
-__bpydoc__ ="""The script exports geometry data to DXF format r12 version.
+__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
+__bpydoc__ ="""The library to export geometry data to DXF format r12 version.
Copyright %s
Version %s
@@ -12,33 +12,51 @@ License %s
Homepage %s
See the homepage for documentation.
-url:
+Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
IDEAs:
-
-
+
TODO:
--
+- add support for DXFr14 (needs extended file header)
+- add support for SPLINEs (possible first in DXFr14 version)
+- add user preset for floating point precision (3-16?)
History
+v1.33 - 2009.06.16 by migius
+ - modif _point(): converts all coords to floats
+ - modif LineType class: implement elements
+ - added VPORT class, incl. defaults
+ - fix Insert class
+v1.32 - 2009.06.06 by migius
+ - modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0
+ - modif Text class: alignment parameter reactivated
+v1.31 - 2009.06.02 by migius
+ - modif _Entity class: added paperspace,elevation
+v1.30 - 2009.05.28 by migius
+ - bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0
+v1.29 - 2008.12.28 by Yorik
+ - modif POLYLINE to support bulge segments
+v1.28 - 2008.12.13 by Steeve/BlenderArtists
+ - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
v1.27 - 2008.10.07 by migius
-- beautifying output code: keys whitespace prefix
-- refactoring DXF-strings format: NewLine moved to the end of
+ - beautifying output code: keys whitespace prefix
+ - refactoring DXF-strings format: NewLine moved to the end of
v1.26 - 2008.10.05 by migius
-- modif POLYLINE to support POLYFACE
+ - modif POLYLINE to support POLYFACE
v1.25 - 2008.09.28 by migius
-- modif FACE class for r12
+ - modif FACE class for r12
v1.24 - 2008.09.27 by migius
-- modif POLYLINE class for r12
-- changing output format from r9 to r12(AC1009)
+ - modif POLYLINE class for r12
+ - changing output format from r9 to r12(AC1009)
v1.1 (20/6/2005) by www.stani.be/python/sdxf
-- Python library to generate dxf drawings
+ - Python library to generate dxf drawings
______________________________________________________________
""" % (__author__,__version__,__license__,__url__)
# --------------------------------------------------------------------------
# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
-# 2008 modif by Remigiusz Fiedler (AKA migius)
+# 2008/2009 modif by Remigiusz Fiedler (AKA migius)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -76,12 +94,11 @@ _HEADER_POINTS=['insbase','extmin','extmax']
def _point(x,index=0):
"""Convert tuple to a dxf point"""
#print 'deb: _point=', x #-------------
- return '\n'.join([' %s\n%s'%((i+1)*10+index,x[i]) for i in range(len(x))])
+ return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))])
def _points(plist):
"""Convert a list of tuples to dxf points"""
out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
- #print 'deb: points=\n', out #-------------------
return out
#---base classes----------------------------------------
@@ -100,17 +117,21 @@ class _Call:
#-------------------------------------------------------
class _Entity(_Call):
"""Base class for _common group codes for entities."""
- def __init__(self,color=None,extrusion=None,layer='0',
+ def __init__(self,paperspace=None,color=None,layer='0',
lineType=None,lineTypeScale=None,lineWeight=None,
- thickness=None,parent=None):
+ extrusion=None,elevation=None,thickness=None,
+ parent=None):
"""None values will be omitted."""
+ self.paperspace = paperspace
self.color = color
- self.extrusion = extrusion
self.layer = layer
self.lineType = lineType
self.lineTypeScale = lineTypeScale
self.lineWeight = lineWeight
+ self.extrusion = extrusion
+ self.elevation = elevation
self.thickness = thickness
+ #self.visible = visible
self.parent = parent
def _common(self):
@@ -118,13 +139,16 @@ class _Entity(_Call):
if self.parent:parent=self.parent
else:parent=self
result =''
+ if parent.paperspace==1: result+=' 67\n1\n'
if parent.layer!=None: result+=' 8\n%s\n'%parent.layer
if parent.color!=None: result+=' 62\n%s\n'%parent.color
- if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType
- #TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
+ # TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
+ # TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
+ if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation
if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
+ if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
return result
#--------------------------
@@ -154,56 +178,56 @@ BYBLOCK=0
BYLAYER=256
#---block-type flags (bit coded values, may be combined):
-ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
+ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
-XREF =4 # This block is an external reference (xref)
-XREF_OVERLAY =8 # This block is an xref overlay
-EXTERNAL =16 # This block is externally dependent
-RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
-REFERENCED =64 # This definition is a referenced external reference (ignored on input)
+XREF =4 # This block is an external reference (xref)
+XREF_OVERLAY =8 # This block is an xref overlay
+EXTERNAL =16 # This block is externally dependent
+RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
+REFERENCED =64 # This definition is a referenced external reference (ignored on input)
#---mtext flags
#attachment point
-TOP_LEFT = 1
-TOP_CENTER = 2
-TOP_RIGHT = 3
-MIDDLE_LEFT = 4
-MIDDLE_CENTER = 5
+TOP_LEFT = 1
+TOP_CENTER = 2
+TOP_RIGHT = 3
+MIDDLE_LEFT = 4
+MIDDLE_CENTER = 5
MIDDLE_RIGHT = 6
-BOTTOM_LEFT = 7
-BOTTOM_CENTER = 8
-BOTTOM_RIGHT = 9
+BOTTOM_LEFT = 7
+BOTTOM_CENTER = 8
+BOTTOM_RIGHT = 9
#drawing direction
-LEFT_RIGHT = 1
-TOP_BOTTOM = 3
-BY_STYLE = 5 #the flow direction is inherited from the associated text style
+LEFT_RIGHT = 1
+TOP_BOTTOM = 3
+BY_STYLE = 5 #the flow direction is inherited from the associated text style
#line spacing style (optional):
-AT_LEAST = 1 #taller characters will override
-EXACT = 2 #taller characters will not override
+AT_LEAST = 1 #taller characters will override
+EXACT = 2 #taller characters will not override
#---polyline flags
-CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
-CURVE_FIT =2 # Curve-fit vertices have been added
-SPLINE_FIT =4 # Spline-fit vertices have been added
-POLYLINE_3D =8 # This is a 3D polyline
-POLYGON_MESH =16 # This is a 3D polygon mesh
-CLOSED_N =32 # The polygon mesh is closed in the N direction
-POLYFACE_MESH =64 # The polyline is a polyface mesh
-CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
+CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
+CURVE_FIT =2 # Curve-fit vertices have been added
+SPLINE_FIT =4 # Spline-fit vertices have been added
+POLYLINE_3D =8 # This is a 3D polyline
+POLYGON_MESH =16 # This is a 3D polygon mesh
+CLOSED_N =32 # The polygon mesh is closed in the N direction
+POLYFACE_MESH =64 # The polyline is a polyface mesh
+CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
#---text flags
#horizontal
-LEFT = 0
-CENTER = 1
-RIGHT = 2
-ALIGNED = 3 #if vertical alignment = 0
-MIDDLE = 4 #if vertical alignment = 0
-FIT = 5 #if vertical alignment = 0
+LEFT = 0
+CENTER = 1
+RIGHT = 2
+ALIGNED = 3 #if vertical alignment = 0
+MIDDLE = 4 #if vertical alignment = 0
+FIT = 5 #if vertical alignment = 0
#vertical
-BASELINE = 0
-BOTTOM = 1
-MIDDLE = 2
-TOP = 3
+BASELINE = 0
+BOTTOM = 1
+MIDDLE = 2
+TOP = 3
####3) Classes
#---entitities -----------------------------------------------
@@ -239,7 +263,7 @@ class Face(_Entity):
"""3dface"""
def __init__(self,points,**common):
_Entity.__init__(self,**common)
- if len(points)<4: #fix for r12 format
+ while len(points)<4: #fix for r12 format
points.append(points[-1])
self.points=points
@@ -269,7 +293,7 @@ class Insert(_Entity):
self.rotation=rotation
def __str__(self):
- result=' 0\nINSERT\n 2\n%s\n%s\n%s\n'%\
+ result=' 0\nINSERT\n 2\n%s\n%s%s\n'%\
(self.name,self._common(),_point(self.point))
if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
@@ -295,51 +319,80 @@ class Line(_Entity):
#-----------------------------------------------
class PolyLine(_Entity):
def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
+ #width = number, or width = list [width_start=None, width_end=None]
+ #for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...]
+ #for 3d-polyline: points = [ [x, y, z], ...]
+ #for polyface: points = [points_list, faces_list]
_Entity.__init__(self,**common)
self.points=points
self.org_point=org_point
self.flag=flag
- if self.flag==64:
+ self.polyface = False
+ self.polyline2d = False
+ self.faces = [] # dummy value
+ self.width= None # dummy value
+ if self.flag & POLYFACE_MESH:
+ self.polyface=True
self.points=points[0]
self.faces=points[1]
self.p_count=len(self.points)
self.f_count=len(self.faces)
- self.width=width
+ elif not self.flag & POLYLINE_3D:
+ self.polyline2d = True
+ if width:
+ if type(width)!='list':
+ width=[width,width]
+ self.width=width
def __str__(self):
result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
- #print 'deb: self._common()', self._common() #----------
result+=' 66\n1\n'
result+='%s\n' %_point(self.org_point)
- if self.flag==64:
+ if self.polyface:
result+=' 71\n%s\n' %self.p_count
result+=' 72\n%s\n' %self.f_count
+ elif self.polyline2d:
+ if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
for point in self.points:
result+=' 0\nVERTEX\n'
result+=' 8\n%s\n' %self.layer
- result+='%s\n' %_point(point)
- if self.flag==64: result+=' 70\n192\n'
- if self.width: result+=' 40\n%s\n 41\n%s\n' %(self.width,self.width)
- if self.flag==64:
- for face in self.faces:
- result+=' 0\nVERTEX\n'
- result+=' 8\n%s\n' %self.layer
- result+='%s\n' %_point(self.org_point)
- result+=' 70\n128\n'
- result+=' 71\n%s\n' %face[0]
- result+=' 72\n%s\n' %face[1]
- result+=' 73\n%s\n' %face[2]
- if len(face)==4: result+=' 74\n%s\n' %face[3]
+ if self.polyface:
+ result+='%s\n' %_point(point[0:3])
+ result+=' 70\n192\n'
+ elif self.polyline2d:
+ result+='%s\n' %_point(point[0:2])
+ if len(point)>4:
+ width1, width2 = point[3], point[4]
+ if width1!=None: result+=' 40\n%s\n' %width1
+ if width2!=None: result+=' 41\n%s\n' %width2
+ if len(point)==6:
+ bulge = point[5]
+ if bulge: result+=' 42\n%s\n' %bulge
+ else:
+ result+='%s\n' %_point(point[0:3])
+ for face in self.faces:
+ result+=' 0\nVERTEX\n'
+ result+=' 8\n%s\n' %self.layer
+ result+='%s\n' %_point(self.org_point)
+ result+=' 70\n128\n'
+ result+=' 71\n%s\n' %face[0]
+ result+=' 72\n%s\n' %face[1]
+ result+=' 73\n%s\n' %face[2]
+ if len(face)==4: result+=' 74\n%s\n' %face[3]
result+=' 0\nSEQEND\n'
result+=' 8\n%s\n' %self.layer
return result
#-----------------------------------------------
class Point(_Entity):
- """Colored solid fill."""
+ """Point."""
def __init__(self,points=None,**common):
_Entity.__init__(self,**common)
self.points=points
+ def __str__(self): # TODO:
+ return ' 0\nPOINT\n%s%s\n' %(self._common(),
+ _points(self.points)
+ )
#-----------------------------------------------
class Solid(_Entity):
@@ -380,7 +433,7 @@ class Text(_Entity):
if self.style: result+=' 7\n%s\n'%self.style
if self.flag: result+=' 71\n%s\n'%self.flag
if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
- #TODO: if self.alignment: result+='%s\n'%_point(self.alignment,1)
+ if self.alignment: result+='%s\n'%_point(self.alignment,1)
if self.justifyver: result+=' 73\n%s\n'%self.justifyver
return result
@@ -468,7 +521,7 @@ class Block(_Collection):
self.name=name
self.flag=0
self.base=base
- def __str__(self):
+ def __str__(self): # TODO:
e=''.join([str(x)for x in self.entities])
return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\
(self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
@@ -488,20 +541,27 @@ class Layer(_Call):
#-----------------------------------------------
class LineType(_Call):
"""Custom linetype"""
- def __init__(self,name='continuous',description='Solid line',elements=[],flag=64):
- # TODO: Implement lineType elements
+ def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0):
self.name=name
self.description=description
self.elements=copy.copy(elements)
self.flag=flag
def __str__(self):
- return ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n 73\n%s\n 40\n0.0\n'%\
- (self.name.upper(),self.flag,self.description,len(self.elements))
+ result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\
+ (self.name.upper(),self.flag,self.description)
+ if self.elements:
+ elements = ' 73\n%s\n' %(len(self.elements)-1)
+ elements += ' 40\n%s\n' %(self.elements[0])
+ for e in self.elements[1:]:
+ elements += ' 49\n%s\n' %e
+ result += elements
+ return result
+
#-----------------------------------------------
class Style(_Call):
"""Text style"""
- def __init__(self,name='standard',flag=0,height=0,widthFactor=40,obliqueAngle=50,
+ def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0,
mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
self.name=name
self.flag=flag
@@ -519,27 +579,137 @@ class Style(_Call):
self.font.upper(),self.bigFont.upper())
#-----------------------------------------------
+class VPort(_Call):
+ def __init__(self,name,flag=0,
+ leftBottom=(0.0,0.0),
+ rightTop=(1.0,1.0),
+ center=(0.5,0.5),
+ snap_base=(0.0,0.0),
+ snap_spacing=(0.1,0.1),
+ grid_spacing=(0.1,0.1),
+ direction=(0.0,0.0,1.0),
+ target=(0.0,0.0,0.0),
+ height=1.0,
+ ratio=1.0,
+ lens=50,
+ frontClipping=0,
+ backClipping=0,
+ snap_rotation=0,
+ twist=0,
+ mode=0,
+ circle_zoom=100,
+ fast_zoom=1,
+ ucsicon=1,
+ snap_on=0,
+ grid_on=0,
+ snap_style=0,
+ snap_isopair=0
+ ):
+ self.name=name
+ self.flag=flag
+ self.leftBottom=leftBottom
+ self.rightTop=rightTop
+ self.center=center
+ self.snap_base=snap_base
+ self.snap_spacing=snap_spacing
+ self.grid_spacing=grid_spacing
+ self.direction=direction
+ self.target=target
+ self.height=float(height)
+ self.ratio=float(ratio)
+ self.lens=float(lens)
+ self.frontClipping=float(frontClipping)
+ self.backClipping=float(backClipping)
+ self.snap_rotation=float(snap_rotation)
+ self.twist=float(twist)
+ self.mode=mode
+ self.circle_zoom=circle_zoom
+ self.fast_zoom=fast_zoom
+ self.ucsicon=ucsicon
+ self.snap_on=snap_on
+ self.grid_on=grid_on
+ self.snap_style=snap_style
+ self.snap_isopair=snap_isopair
+ def __str__(self):
+ output = [' 0', 'VPORT',
+ ' 2', self.name,
+ ' 70', self.flag,
+ _point(self.leftBottom),
+ _point(self.rightTop,1),
+ _point(self.center,2), # View center point (in DCS)
+ _point(self.snap_base,3),
+ _point(self.snap_spacing,4),
+ _point(self.grid_spacing,5),
+ _point(self.direction,6), #view direction from target (in WCS)
+ _point(self.target,7),
+ ' 40', self.height,
+ ' 41', self.ratio,
+ ' 42', self.lens,
+ ' 43', self.frontClipping,
+ ' 44', self.backClipping,
+ ' 50', self.snap_rotation,
+ ' 51', self.twist,
+ ' 71', self.mode,
+ ' 72', self.circle_zoom,
+ ' 73', self.fast_zoom,
+ ' 74', self.ucsicon,
+ ' 75', self.snap_on,
+ ' 76', self.grid_on,
+ ' 77', self.snap_style,
+ ' 78', self.snap_isopair
+ ]
+
+ output_str = ''
+ for s in output:
+ output_str += '%s\n' %s
+ return output_str
+
+
+
+#-----------------------------------------------
class View(_Call):
- def __init__(self,name,flag=0,width=1,height=1,center=(0.5,0.5),
- direction=(0,0,1),target=(0,0,0),lens=50,
- frontClipping=0,backClipping=0,twist=0,mode=0):
+ def __init__(self,name,flag=0,
+ width=1,
+ height=1,
+ center=(0.5,0.5),
+ direction=(0,0,1),
+ target=(0,0,0),
+ lens=50,
+ frontClipping=0,
+ backClipping=0,
+ twist=0,mode=0
+ ):
self.name=name
self.flag=flag
- self.width=width
- self.height=height
+ self.width=float(width)
+ self.height=float(height)
self.center=center
self.direction=direction
self.target=target
- self.lens=lens
- self.frontClipping=frontClipping
- self.backClipping=backClipping
- self.twist=twist
+ self.lens=float(lens)
+ self.frontClipping=float(frontClipping)
+ self.backClipping=float(backClipping)
+ self.twist=float(twist)
self.mode=mode
def __str__(self):
- return ' 0\nVIEW\n 2\n%s\n 70\n%s\n 40\n%s\n%s\n 41\n%s\n%s\n%s\n 42\n%s\n 43\n%s\n 44\n%s\n 50\n%s\n 71\n%s\n'%\
- (self.name,self.flag,self.height,_point(self.center),self.width,
- _point(self.direction,1),_point(self.target,2),self.lens,
- self.frontClipping,self.backClipping,self.twist,self.mode)
+ output = [' 0', 'VIEW',
+ ' 2', self.name,
+ ' 70', self.flag,
+ ' 40', self.height,
+ _point(self.center),
+ ' 41', self.width,
+ _point(self.direction,1),
+ _point(self.target,2),
+ ' 42', self.lens,
+ ' 43', self.frontClipping,
+ ' 44', self.backClipping,
+ ' 50', self.twist,
+ ' 71', self.mode
+ ]
+ output_str = ''
+ for s in output:
+ output_str += '%s\n' %s
+ return output_str
#-----------------------------------------------
def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
@@ -552,11 +722,12 @@ def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
#-----------------------------------------------
class Drawing(_Collection):
"""Dxf drawing. Use append or any other list methods to add objects."""
- def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0),
+ def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0),
layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
- views=[],entities=None,fileName='test.dxf'):
+ views=[],vports=[],entities=None,fileName='test.dxf'):
# TODO: replace list with None,arial
- if not entities:entities=[]
+ if not entities:
+ entities=[]
_Collection.__init__(self,entities)
self.insbase=insbase
self.extmin=extmin
@@ -565,6 +736,7 @@ class Drawing(_Collection):
self.linetypes=copy.copy(linetypes)
self.styles=copy.copy(styles)
self.views=copy.copy(views)
+ self.vports=copy.copy(vports)
self.blocks=copy.copy(blocks)
self.fileName=fileName
#private
@@ -608,7 +780,8 @@ class Drawing(_Collection):
header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
header=self._section('header',header)
- tables=[self._table('ltype',[str(x) for x in self.linetypes]),
+ tables=[self._table('vport',[str(x) for x in self.vports]),
+ self._table('ltype',[str(x) for x in self.linetypes]),
self._table('layer',[str(x) for x in self.layers]),
self._table('style',[str(x) for x in self.styles]),
self._table('view',[str(x) for x in self.views]),
@@ -680,9 +853,9 @@ def test():
#Drawing
d=Drawing()
#tables
- d.blocks.append(b) #table blocks
- d.styles.append(Style()) #table styles
- d.views.append(View('Normal')) #table view
+ d.blocks.append(b) #table blocks
+ d.styles.append(Style()) #table styles
+ d.views.append(View('Normal')) #table view
d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
#entities
@@ -692,17 +865,16 @@ def test():
d.append(Line(points=[(0,0,0),(1,1,1)]))
d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
d.append(Text('Please donate!',point=(3,0,1)))
- d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
+ #d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
- d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],closed=1,color=1))
+ #d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1))
#d.saveas('c:\\test.dxf')
d.saveas('test.dxf')
-
#-----------------------------------------------------
if __name__=='__main__':
if not copy:
Draw.PupMenu('Error%t|This script requires a full python install')
- main()
+ else: test()
\ No newline at end of file
diff --git a/release/scripts/bpymodules/mesh_gradient.py b/release/scripts/bpymodules/mesh_gradient.py
index 936f4958467..e582a30152b 100644
--- a/release/scripts/bpymodules/mesh_gradient.py
+++ b/release/scripts/bpymodules/mesh_gradient.py
@@ -6,7 +6,7 @@ import BPyWindow
mouseViewRay= BPyWindow.mouseViewRay
from Blender import Mathutils, Window, Scene, Draw, sys
-from Blender.Mathutils import CrossVecs, Vector, Intersect, LineIntersect, AngleBetweenVecs
+from Blender.Mathutils import Vector, Intersect, LineIntersect, AngleBetweenVecs
LMB= Window.MButs['L']
def mouseup():
@@ -101,11 +101,11 @@ def vertexGradientPick(ob, MODE):
# make a line 90d to the grad in screenspace.
if (OriginA-OriginB).length <= eps: # Persp view. same origin different direction
- cross_grad= CrossVecs(DirectionA, DirectionB)
+ cross_grad= DirectionA.cross(DirectionB)
ORTHO= False
else: # Ortho - Same direction, different origin
- cross_grad= CrossVecs(DirectionA, OriginA-OriginB)
+ cross_grad= DirectionA.cross(OriginA-OriginB)
ORTHO= True
cross_grad.normalize()
diff --git a/release/scripts/bpymodules/paths_svg2obj.py b/release/scripts/bpymodules/paths_svg2obj.py
index de40bea3191..6bab6dcbfd8 100644
--- a/release/scripts/bpymodules/paths_svg2obj.py
+++ b/release/scripts/bpymodules/paths_svg2obj.py
@@ -1,7 +1,7 @@
# -*- coding: latin-1 -*-
"""
-SVG 2 OBJ translater, 0.5.9h
-Copyright (c) jm soler juillet/novembre 2004-april 2007,
+SVG 2 OBJ translater, 0.5.9o
+Copyright (c) jm soler juillet/novembre 2004-april 2009,
# ---------------------------------------------------------------
released under GNU Licence
for the Blender 2.42 Python Scripts Bundle.
@@ -20,7 +20,6 @@ en même temps que ce programme ; si ce n'est pas le cas, écrivez à la
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307, États-Unis.
-
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
@@ -35,7 +34,7 @@ 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 St, Fifth Floor, Boston, MA 02110-1301 USA
# ---------------------------------------------------------------
-
+#
#---------------------------------------------------------------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
@@ -253,15 +252,29 @@ Changelog:
0.5.9h : - 2007/5/2
- script was updated with the modifs by cambo
- - removed all debug statements
+ - removed all debug statements
- correction of a zero division error in the calc_arc function.
+ 0.5.9f: - 2007/15/7
+ - Correction de plusieurs bugs sur l'attributions des couleurs et le nommage
+ des courbes
+
+ 0.5.9i : - ??/??/??
+ - Patch externe réalisé sur blender.org project.
+
+ 0.5.9j : - 08/11/2008
+ 0.5.9k : - 14/01/2009
+ 0.5.9l : - 31/01/2009
+ 0.5.9n : - 01/02/2009
+ 0.5.9o : - 04/04/2009, remove pattern if it made with path.
+
+
==================================================================================
=================================================================================="""
SHARP_IMPORT=0
SCALE=1
scale_=1
-DEBUG = 0#print
+DEBUG = 0
DEVELOPPEMENT=0
TESTCOLOR=0
@@ -269,6 +282,7 @@ LAST_ID=''
LAST_COLOR=[0.0,0.0,0.0,0.0]
SEPARATE_CURVES=0
USE_COLORS=0
+PATTERN=0
SVGCOLORNAMELIST={ 'aliceblue':[240, 248, 255] ,'antiquewhite':[250, 235, 215]
,'aqua':[ 0, 255, 255], 'aquamarine':[127, 255, 212]
@@ -533,7 +547,7 @@ def createCURVES(curves, name):
scene.objects.selected = []
if not SEPARATE_CURVES:
- c = Curve.New()
+ c = Curve.New()
c.setResolu(24)
MATNAME=[]
@@ -709,7 +723,6 @@ def circle(prp):
else : cx =float(prp['cx'])
if 'cy' not in prp: cy=0.0
else : cy =float(prp['cy'])
- #print prp.keys()
r = float(prp['r'])
D=['M',str(cx),str(cy+r),
'C',str(cx-r), str(cy+r*0.552),str(cx-0.552*r),str(cy+r), str(cx),str(cy+r),
@@ -777,6 +790,7 @@ def polygon(prp):
D.append('Z')
return D
+
#--------------------
# 0.5.8, to remove exec
#--------------------
@@ -852,7 +866,7 @@ def calc_arc (cpx,cpy, rx, ry, ang, fa , fs , x, y) :
#--------------------
# 0.3.9
#--------------------
-def curve_to_a(c,D,n0,CP): #A,a
+def curve_to_a(curves, c,D,n0,CP): #A,a
global SCALE
l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])]
@@ -866,8 +880,7 @@ def curve_to_a(c,D,n0,CP): #A,a
POINTS= calc_arc (CP[0],CP[1],
l[0], l[1], l[2]*(PI / 180.0),
l[3], l[4],
- l[5], l[6] )
- #if DEBUG == 1 : print POINTS
+ l[5], l[6] )
for p in POINTS :
B=Bez()
B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]]
@@ -881,16 +894,23 @@ def curve_to_a(c,D,n0,CP): #A,a
BP.co[2]=BP.co[0]
BP.co[3]=BP.co[1]
CP=[l[5], l[6]]
+ #---------- 059m------------
+ if len(D)>c[1]+7 and D[c[1]+8] not in TAGcourbe :
+ c[1]+=7
+ curves,n0,CP=curve_to_a(curves, c, D, n0,CP)
+ #---------- 059m------------
return curves,n0,CP
-def move_to(c, D, n0,CP, proprietes):
+def move_to(curves, c, D, n0,CP, proprietes):
global DEBUG,TAGcourbe, LAST_ID
global USE_COLORS
l=[float(D[c[1]+1]),float(D[c[1]+2])]
+
if c[0]=='m':
l=[l[0]+CP[0],
l[1] + CP[1]]
+
if n0 in curves.ITEM:
n0+=1
CP=[l[0],l[1]]
@@ -917,14 +937,12 @@ def move_to(c, D, n0,CP, proprietes):
B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
B.ha=['L','C']
B.tag=c[0]
- curves.ITEM[n0].beziers_knot.append(B)
- #if DEBUG==1: print curves.ITEM[n0], CP
+ curves.ITEM[n0].beziers_knot.append(B)
return curves,n0,CP
-def close_z(c,D,n0,CP): #Z,z
+def close_z(curves, c,D,n0,CP): #Z,z
curves.ITEM[n0].flagUV[0]=1
if len(curves.ITEM[n0].beziers_knot)>1:
- #print len(curves.ITEM[n0].beziers_knot)
BP=curves.ITEM[n0].beziers_knot[-1]
BP0=curves.ITEM[n0].beziers_knot[0]
if BP.tag in ['c','C','s','S',]:
@@ -936,7 +954,7 @@ def close_z(c,D,n0,CP): #Z,z
n0-=1
return curves,n0,CP
-def curve_to_q(c,D,n0,CP): #Q,q
+def curve_to_q(curves, c,D,n0,CP): #Q,q
l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])]
if c[0]=='q':
l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]]
@@ -948,15 +966,14 @@ def curve_to_q(c,D,n0,CP): #Q,q
BP.co[2]=BP.co[0]
BP.co[3]=BP.co[1]
curves.ITEM[n0].beziers_knot.append(B)
- #if DEBUG==1: print B.co,BP.co
CP=[l[2],l[3]]
#if DEBUG==1: pass
if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
c[1]+=4
- curve_to_q(c, D, n0,CP)
+ curves,n0,CP=curve_to_q(curves, c, D, n0,CP)
return curves,n0,CP
-def curve_to_t(c,D,n0,CP): #T,t
+def curve_to_t(curves, c,D,n0,CP): #T,t
l=[float(D[c[1]+1]),float(D[c[1]+2])]
if c[0]=='t':
l=[l[0]+CP[0], l[1]+CP[1]]
@@ -970,11 +987,10 @@ def curve_to_t(c,D,n0,CP): #T,t
BP.co[2]=l0[2]
BP.co[3]=l0[3]
curves.ITEM[n0].beziers_knot.append(B)
- #if DEBUG==1: print B.co,BP.co
CP=[l[0],l[1]]
if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
c[1]+=4
- curve_to_t(c, D, n0,CP)
+ curves,n0,CP=curve_to_t(curves, c, D, n0,CP)
return curves,n0,CP
#--------------------
@@ -985,7 +1001,7 @@ def build_SYMETRIC(l):
Y=l[3]-(l[1]-l[3])
return X,Y
-def curve_to_s(c,D,n0,CP): #S,s
+def curve_to_s(curves, c,D,n0,CP): #S,s
l=[float(D[c[1]+1]),
float(D[c[1]+2]),
float(D[c[1]+3]),
@@ -1003,17 +1019,16 @@ def curve_to_s(c,D,n0,CP): #S,s
#--------------------
BP.co[2],BP.co[3]=build_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]])
curves.ITEM[n0].beziers_knot.append(B)
- #if DEBUG==1: print B.co,BP.co
#--------------------
# 0.4.3
#--------------------
CP=[l[2],l[3]]
if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
c[1]+=4
- curve_to_c(c, D, n0,CP)
+ curves,n0,CP=curve_to_c(curves, c, D, n0,CP)
return curves,n0,CP
-def curve_to_c(c, D, n0,CP): #c,C
+def curve_to_c(curves, c, D, n0,CP): #c,C
l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])]
if c[0]=='c':
@@ -1030,6 +1045,8 @@ def curve_to_c(c, D, n0,CP): #c,C
l[5],
l[2],
l[3]] #plus toucher au 2-3
+
+
B.ha=['C','C']
B.tag=c[0]
BP=curves.ITEM[n0].beziers_knot[-1]
@@ -1037,32 +1054,38 @@ def curve_to_c(c, D, n0,CP): #c,C
BP.co[3]=l[1]
BP.ha[1]='C'
curves.ITEM[n0].beziers_knot.append(B)
- #if DEBUG==1: print B.co,BP.co
CP=[l[4],l[5]]
if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe :
- c[1]+=6
- curve_to_c(c, D, n0,CP)
+ c[1]+=6
+ curves,n0,CP=curve_to_c(curves, c, D, n0,CP)
return curves,n0,CP
-def draw_line_l(c, D, n0,CP): #L,l
- l=[float(D[c[1]+1]),float(D[c[1]+2])]
+def draw_line_l(curves, c, D, n0,CP): #L,l
+
+ l=[float(D[c[1]+1]),float(D[c[1]+2])]
if c[0]=='l':
l=[l[0]+CP[0],
- l[1]+CP[1]]
+ l[1]+CP[1]]
B=Bez()
- B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
+ B.co=[l[0],l[1],
+ l[0],l[1],
+ l[0],l[1]]
+
B.ha=['L','L']
B.tag=c[0]
BP=curves.ITEM[n0].beziers_knot[-1]
BP.ha[1]='L'
+
curves.ITEM[n0].beziers_knot.append(B)
- CP=[B.co[0],B.co[1]]
+ CP=[B.co[4],B.co[5]]
+
if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
c[1]+=2
- draw_line_l(c, D, n0,CP) #L
+ curves,n0,CP=draw_line_l(curves, c, D, n0,CP) #L
+
return curves,n0,CP
-def draw_line_h(c,D,n0,CP): #H,h
+def draw_line_h(curves, c,D,n0,CP): #H,h
if c[0]=='h':
l=[float(D[c[1]+1])+float(CP[0]),CP[1]]
else:
@@ -1077,7 +1100,7 @@ def draw_line_h(c,D,n0,CP): #H,h
CP=[l[0],l[1]]
return curves,n0,CP
-def draw_line_v(c,D,n0,CP): #V, v
+def draw_line_v(curves, c,D,n0,CP): #V, v
if c[0]=='v':
l=[CP[0], float(D[c[1]+1])+CP[1]]
else:
@@ -1121,17 +1144,31 @@ TAGtransform=['M','L','C','S','H','V','T','Q']
tagTRANSFORM=0
def wash_DATA(ndata):
- if ndata:
- #if DEBUG==1: print ndata
+ if ndata:
ndata = ndata.strip()
+
if ndata[0]==',':ndata=ndata[1:]
if ndata[-1]==',':ndata=ndata[:-1]
+
#--------------------
# 0.4.0 : 'e'
#--------------------
- i = ndata.find('-')
- if i != -1 and ndata[i-1] not in ' ,e':
- ndata=ndata.replace('-',',-')
+ ni=0
+ i = ndata.find('-',ni)
+ if i != -1:
+ while i>-1 :
+ i = ndata.find('-',ni)
+ # 059l ------
+ if i>0 :
+ if ndata[i-1] not in [' ',',','e']:
+ ndata=ndata[:i]+','+ndata[i:]
+ ni=i+2
+ else:
+ ni=i+1
+ elif i>-1:
+ ni=1
+ # 059l ------
+
ndata=ndata.replace(',,',',')
ndata=ndata.replace(' ',',')
ndata=ndata.split(',')
@@ -1153,7 +1190,7 @@ def list_DATA(DATA):
# borner les differents segments qui devront etre
# traites
# pour cela construire une liste avec chaque
- # la position de chaqe emplacement tag de type
+ # position de chaque emplacement tag de type
# commande path...
# ----------------------------------------
tagplace=[]
@@ -1169,8 +1206,10 @@ def list_DATA(DATA):
# d'apparition des tags
#------------------------------------------
tagplace.sort()
-
+
tpn=range(len(tagplace))
+
+
#--------------------
# 0.3.5 :: short data, only one tag
#--------------------
@@ -1179,14 +1218,18 @@ def list_DATA(DATA):
for t in tpn[:-1]:
DATA2.append(DATA[tagplace[t]:tagplace[t]+1])
ndata=DATA[tagplace[t]+1:tagplace[t+1]]
+
if DATA2[-1] not in ['z','Z'] :
ndata=wash_DATA(ndata)
DATA2.extend(ndata)
+
DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])
+
if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
ndata=DATA[tagplace[t+1]+1:]
ndata=wash_DATA(ndata)
DATA2.extend(ndata) #059a
+
else:
#--------------------
# 0.3.5 : short data,only one tag
@@ -1276,15 +1319,13 @@ def control_CONTAINT(txt):
nt0=txt[t0:t1+1]
t2=nt0[nt0.find('(')+1:-1]
val=nt0[:nt0.find('(')]
+
while t2.find(' ')!=-1:
t2=t2.replace(' ',' ')
- t2=t2.replace(' ',',')
+ while t2.find(', ')!=-1: #059l
+ t2=t2.replace(', ',',') #059l
- """
- t2=t2.split(',')
- for index, t in enumerate(t2):
- t2[index]=float(t)
- """
+ t2=t2.replace(' ',',')
t2=[float(t) for t in t2.split(',')]
if val=='rotate' :
@@ -1314,12 +1355,24 @@ def curve_FILL(Courbe,proprietes):
i= i+6
Courbe[n].color=[int(pr[i:i+2],16),int(pr[i+2:i+4],16),int(pr[i+4:i+6],16)]
Courbe[n].mat=1
- elif ';fill-opacity' in pr:
- i= pr.find('fill:')+5
- i2= pr.find(';',i)
- COLORNAME= pr[i:i2]
- Courbe[n].color=SVGCOLORNAMELIST[COLORNAME]
- Courbe[n].mat=1
+ elif ';fill-opacity' in pr:
+ if pr.find('fill:url')==-1:
+ i= pr.find('fill:')+5
+ i2= pr.find(';',i)
+ COLORNAME= pr[i:i2]
+ Courbe[n].color=SVGCOLORNAMELIST[COLORNAME]
+ Courbe[n].mat=1
+ elif 'color:' in pr:
+ i= pr.find('color:')+6
+ i2= pr.find(';',i)
+ COLORNAME= pr[i:i2]
+ Courbe[n].color=SVGCOLORNAMELIST[COLORNAME]
+ Courbe[n].mat=1
+ else :
+ COLORNAME= 'white'
+ Courbe[n].color=SVGCOLORNAMELIST[COLORNAME]
+ Courbe[n].mat=1
+
#----------------------------------------------
# 0.4.1 : apply transform stack
#----------------------------------------------
@@ -1367,9 +1420,8 @@ def filter(d):
def get_BOUNDBOX(BOUNDINGBOX,SVG):
if 'viewbox' not in SVG:
h=float(filter(SVG['height']))
- #if DEBUG==1 : print 'h : ',h
+
w=float(filter(SVG['width']))
- #if DEBUG==1 : print 'w :',w
BOUNDINGBOX['rec']=[0.0,0.0,w,h]
r=BOUNDINGBOX['rec']
BOUNDINGBOX['coef']=w/h
@@ -1414,13 +1466,13 @@ def collect_ATTRIBUTS(data):
# --------------------------------------------
def build_HIERARCHY(t):
global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
- global LAST_ID
+ global LAST_ID, PATTERN
TRANSFORM=0
t=t.replace('\t',' ')
while t.find(' ')!=-1: t=t.replace(' ',' ')
n0=0
t0=t1=0
- baliste=[]
+ #baliste=[]
balisetype=['?','?','/','/','!','!']
BALISES=['D', #DECL_TEXTE',
'D', #DECL_TEXTE',
@@ -1442,35 +1494,41 @@ def build_HIERARCHY(t):
if t0>-1 and t1>-1:
if t[t0+1] in balisetype:
b=balisetype.index(t[t0+1])
+
if t[t0+2]=='-':
b=balisetype.index(t[t0+1])+1
- #print t[t0:t1]
+
balise=BALISES[b]
+
if b==2:
parent=STACK.pop(-1)
if parent!=None and TRANSFORM>0:
TRANSFORM-=1
+
elif t[t1-1] in balisetype:
balise=BALISES[balisetype.index(t[t1-1])+1]
+
else:
t2=t.find(' ',t0)
if t2>t1: t2=t1
ouvrante=1
NOM=t[t0+1:t2]
+
+
if '</'+NOM in t: #.find('</'+NOM)>-1:
balise=BALISES[-1]
+ if NOM=='pattern' and not PATTERN:
+ t1=t.find('</'+NOM+'>',t0)+len('</'+NOM+'>')
+ balise=BALISES[-3]
else:
balise=BALISES[-2]
if balise=='E' or balise=='O':
+
proprietes=collect_ATTRIBUTS(t[t0:t1+ouvrante])
- #print proprietes
if 'id' in proprietes:
LAST_ID=proprietes['id']
- #print LAST_ID
-
-
if balise=='O' and 'transform' in proprietes:
STACK.append(proprietes['transform'])
@@ -1490,19 +1548,24 @@ def build_HIERARCHY(t):
#--------------------
D=OTHERSSHAPES[proprietes['TYPE']](proprietes)
+ #elif proprietes['TYPE'] in ['pattern']:
+ # print 'pattern'
+ # D=''
+
+ CP=[0.0,0.0]
if len(D)>0:
cursor=0
proprietes['n']=[]
for cell in D:
- #if DEBUG==2 : print 'cell : ',cell ,' --'
+
if len(cell)>=1 and cell[0] in TAGcourbe:
#--------------------
# 0.5.8, to remove exec
#--------------------
if cell[0] in ['m','M']:
- curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP,proprietes)
+ curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP,proprietes)
else:
- curves,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)
+ curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP)
cursor+=1
if TRANSFORM>0 or 'transform' in proprietes :
@@ -1513,7 +1576,6 @@ def build_HIERARCHY(t):
elif proprietes['TYPE'] == 'svg':
- #print 'proprietes.keys()',proprietes.keys()
BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes)
else:
#--------------------
@@ -1525,7 +1587,7 @@ def build_HIERARCHY(t):
def scan_FILE(nom):
global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
- global SEPARATE_CURVES, USE_COLORS
+ global SEPARATE_CURVES, USE_COLORS, PATTERN
dir,name=split(nom)
name=name.split('.')
@@ -1541,13 +1603,14 @@ def scan_FILE(nom):
togAS = Blender.Draw.Create(0)
togSP = Blender.Draw.Create(0)
togCOL = Blender.Draw.Create(0)
+ Pattern= Blender.Draw.Create(0)
block=[\
("Clamp Width 1", togW, "Rescale the import with a Width of one unit"),\
("Clamp Height 1", togH, "Rescale the import with a Heightof one unit"),\
("No Rescaling", togAS, "No rescaling, the result can be very large"),\
("Separate Curves", togSP, "Create an object for each curve, Slower. May manage colors"),\
- ("Import Colors", togCOL, "try to import color if the path is set as 'fill'. Only With separate option")]
-
+ ("Import Colors", togCOL, "try to import color if the path is set as 'fill'. Only With separate option"),\
+ ("Import Patterns", Pattern, "import pattern content if it is made with paths.")]
retval = Blender.Draw.PupBlock("Import Options", block)
if togW.val: scale_=1
elif togH.val: scale_=2
@@ -1556,6 +1619,8 @@ def scan_FILE(nom):
if togSP.val: SEPARATE_CURVES=1
if togCOL.val and SEPARATE_CURVES : USE_COLORS=1
+
+ if Pattern.val : PATTERN =1
t1=Blender.sys.time()
# 0.4.1 : to avoid to use sax and the xml
@@ -1583,4 +1648,4 @@ def functionSELECT(nom):
if __name__=='__main__':
- Blender.Window.FileSelector (functionSELECT, 'SELECT an .SVG FILE', '*.svg')
+ Blender.Window.FileSelector (functionSELECT, 'SELECT an .SVG FILE', '*.svg') \ No newline at end of file
diff --git a/release/scripts/bvh_import.py b/release/scripts/bvh_import.py
index 5cdd8a71231..4134503c511 100644
--- a/release/scripts/bvh_import.py
+++ b/release/scripts/bvh_import.py
@@ -277,12 +277,17 @@ def read_bvh(file_path, GLOBAL_SCALE=1.0):
for bvh_node in bvh_nodes.itervalues():
if not bvh_node.rest_tail_world:
- if len(bvh_node.children)==1:
+ if len(bvh_node.children)==0:
+ # could just fail here, but rare BVH files have childless nodes
+ bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
+ bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
+ elif len(bvh_node.children)==1:
bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
else:
- if not bvh_node.children:
- raise 'error, bvh node has no end and no children. bad file'
+ # allow this, see above
+ #if not bvh_node.children:
+ # raise 'error, bvh node has no end and no children. bad file'
# Removed temp for now
rest_tail_world= Vector(0,0,0)
diff --git a/release/scripts/c3d_import.py b/release/scripts/c3d_import.py
index bfe691c394c..98f643cbab9 100644
--- a/release/scripts/c3d_import.py
+++ b/release/scripts/c3d_import.py
@@ -527,9 +527,10 @@ def setupAnim(StartFrame, EndFrame, VideoFrameRate):
if VideoFrameRate>120: VideoFrameRate=120
# set up anim panel for them
context=scn.getRenderingContext()
- context.startFrame(StartFrame)
- context.endFrame(EndFrame)
- context.framesPerSec(int(VideoFrameRate))
+ context.sFrame=StartFrame
+ context.eFrame=EndFrame
+ context.fps=int(VideoFrameRate)
+
Blender.Set("curframe",StartFrame)
Blender.Redraw()
return
diff --git a/release/scripts/console.py b/release/scripts/console.py
index 0e46f41f581..c6ae22a86f5 100644
--- a/release/scripts/console.py
+++ b/release/scripts/console.py
@@ -708,20 +708,23 @@ def draw_gui():
# Fixed margin. use a margin since 0 margin can be hard to seewhen close to a crt's edge.
margin = 4
+ # Convenience
+ FNT_NAME, FNT_HEIGHT = __FONT_SIZES__[__FONT_SIZE__]
+
# Draw cursor location colour
if __CONSOLE_LINE_OFFSET__ == 0:
- cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZES__[__FONT_SIZE__][0])
+ cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], FNT_NAME)
BGL.glColor3f(0.8, 0.2, 0.2)
if cmd2curWidth == 0:
- BGL.glRecti(margin,2,margin+2, __FONT_SIZES__[__FONT_SIZE__][1]+2)
+ BGL.glRecti(margin,2,margin+2, FNT_HEIGHT+2)
else:
- BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, __FONT_SIZES__[__FONT_SIZE__][1]+2)
+ BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, FNT_HEIGHT+2)
BGL.glColor3f(1,1,1)
# Draw the set of cammands to the buffer
consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1
wrapLineIndex = 0
- while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * __FONT_SIZES__[__FONT_SIZE__][1]:
+ while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * FNT_HEIGHT:
if cmdBuffer[-consoleLineIdx].type == 0:
BGL.glColor3f(1, 1, 1)
elif cmdBuffer[-consoleLineIdx].type == 1:
@@ -734,53 +737,41 @@ def draw_gui():
BGL.glColor3f(1, 1, 0)
if consoleLineIdx == 1: # user input
- BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
- Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
- else:
- BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
- Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-
- # Wrapping is totally slow, can even hang blender - dont do it!
- '''
- if consoleLineIdx == 1: # NEVER WRAP THE USER INPUT
- BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
- # BUG, LARGE TEXT DOSENT DISPLAY
- Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
-
-
- else: # WRAP?
- # LINE WRAP
- if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0]) > __CONSOLE_RECT__[2]:
+ BGL.glRasterPos2i(margin, (FNT_HEIGHT * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
+ else: # WRAP
+ lwid = Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
+ if margin + lwid > __CONSOLE_RECT__[2]:
wrapLineList = []
- copyCmd = [cmdBuffer[-consoleLineIdx].cmd, '']
- while copyCmd != ['','']:
- while margin + Draw.GetStringWidth(copyCmd[0], __FONT_SIZES__[__FONT_SIZE__][0]) > __CONSOLE_RECT__[2]:
- #print copyCmd
- copyCmd[1] = '%s%s'% (copyCmd[0][-1], copyCmd[1]) # Add the char on the end
- copyCmd[0] = copyCmd[0][:-1]# remove last chat
-
- # Now we have copyCmd[0] at a good length we can print it.
- if copyCmd[0] != '':
- wrapLineList.append(copyCmd[0])
-
- copyCmd[0]=''
- copyCmd = [copyCmd[1], copyCmd[0]]
-
+ wtext = cmdBuffer[-consoleLineIdx].cmd
+ wlimit = len(wtext)
+ chunksz = int(( __CONSOLE_RECT__[2] - margin ) / (lwid / len(wtext)))
+ lstart = 0
+ fsize = FNT_NAME
+ while lstart < wlimit:
+ lend = min(lstart+chunksz,wlimit)
+ ttext = wtext[lstart:lend]
+ while lend < wlimit and Draw.GetStringWidth(ttext, fsize) + margin < __CONSOLE_RECT__[2]:
+ lend += 1
+ ttext = wtext[lstart:lend]
+ while lend > lstart+1 and Draw.GetStringWidth(ttext, fsize) + margin > __CONSOLE_RECT__[2]:
+ lend -= 1
+ ttext = wtext[lstart:lend]
+ wrapLineList.append(ttext)
+ lstart = lend
# Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change)
wrapLineList.reverse()
for wline in wrapLineList:
- BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1]*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
- Draw.Text(wline, __FONT_SIZES__[__FONT_SIZE__][0])
+ BGL.glRasterPos2i(margin, (FNT_HEIGHT*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
+ Draw.Text(wline, FNT_NAME)
wrapLineIndex += 1
- wrapLineIndex-=1 # otherwise we get a silly extra line.
+ wrapLineIndex-=1 # otherwise we get a silly extra line.
else: # no wrapping.
- BGL.glRasterPos2i(margin, (__FONT_SIZES__[__FONT_SIZE__][1] * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
- Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZES__[__FONT_SIZE__][0])
- '''
+ BGL.glRasterPos2i(margin, (FNT_HEIGHT * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
consoleLineIdx += 1
-
# This recieves the event index, call a function from here depending on the event.
def handle_button_event(evt):
diff --git a/release/scripts/envelope_symmetry.py b/release/scripts/envelope_symmetry.py
index a52e622a65b..a72e8c060b4 100644
--- a/release/scripts/envelope_symmetry.py
+++ b/release/scripts/envelope_symmetry.py
@@ -4,7 +4,7 @@
Name: 'Envelope Symmetry'
Blender: 234
Group: 'Animation'
-Tooltip: 'Make envelope symetrical'
+Tooltip: 'Make envelope symmetrical'
"""
__author__ = "Jonas Petersen"
diff --git a/release/scripts/export_dxf.py b/release/scripts/export_dxf.py
index 061e29b81c7..17f2132fbe8 100644
--- a/release/scripts/export_dxf.py
+++ b/release/scripts/export_dxf.py
@@ -1,41 +1,97 @@
#!BPY
"""
- Name: 'Autodesk DXF (.dxf)'
- Blender: 247
+ Name: 'Autodesk DXF (.dxf/dwg)'
+ Blender: 249
Group: 'Export'
- Tooltip: 'Export geometry to DXF-r12 (Drawing eXchange Format).'
+ Tooltip: 'Export geometry to DXF/DWG-r12 (Drawing eXchange Format).'
"""
-__version__ = "v1.27beta - 2008.10.07"
+__version__ = "1.35 - 2009.06.18"
__author__ = "Remigiusz Fiedler (AKA migius)"
__license__ = "GPL"
-__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
+__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
__bpydoc__ ="""The script exports Blender geometry to DXF format r12 version.
Version %s
Copyright %s
License %s
-extern dependances: dxfLibrary.py
+extern dependances: dxfLibrary.py, dxfColorMap.py (optionaly: DConvertCon.exe)
+
+CONTRIBUTORS:
+Remigiusz Fiedler (AKA migius)
+Alexandros Sigalas (AKA alxarch)
+Stani Michiels (AKA stani)
See the homepage for documentation.
url: %s
IDEAs:
- - correct normals for POLYLINE-POLYFACE via proper point-order
- - HPGL output for 2d and flattened 3d content
+- HPGL output, usefull for correct scaled printing of 2d drawings
TODO:
-- optimize back-faces removal (probably needs matrix transform)
+- export dupligroups and dupliverts as blocks (as option)
- optimize POLYFACE routine: remove double-vertices
-- optimize POLYFACE routine: remove unused vertices
+- fix support for X,Y-rotated curves(to POLYLINEs): fix blender negative-matrix.invert()
- support hierarchies: groups, instances, parented structures
-- support 210-code (3d orientation vector)
-- presets for architectural scales
-- write drawing extends for automatic view positioning in CAD
+- support n/f-gons as POLYFACEs with invisible edges
+- mapping materials to DXF-styles
+- ProgressBar
+- export rotation of Camera to VIEW/VPORT
+- export parented Cameras to VIEW/VPORT
+- wip: write drawing extends for automatic view positioning in CAD
+- wip: fix text-objects in persp-projection
+- wip: translate current 3D-View to *ACTIVE-VPORT
+- wip: fix support Include-Duplis, cause not conform with INSERT-method
History
+v1.35 - 2009.06.18 by migius
+- export multiple-instances of Curve-Objects as BLOCK/INSERTs
+- added export Cameras (ortho and persp) to VPORTs, incl. clipping
+- added export Cameras (ortho and persp) to VIEWs, incl. clipping
+- export multiple-instances of Mesh-Objects as BLOCK/INSERTs
+- on start prints dxfLibrary version
+v1.34 - 2009.06.08 by migius
+- export Lamps and Cameras as POINTs
+- export passepartout for perspective projection
+- added option for export objects only from visible layers
+- optimized POLYFACE output: remove loose vertices in back-faces-mode
+- cleaning code
+- fix nasty bug in getExtrusion()
+- support text-objects, also in ortho/persp-projection
+- support XYmirrored 2d-curves to 2dPOLYLINEs
+- support thickness and elevation for curve-objects
+- fix extrusion 210-code (3d orientation vector)
+- fix POLYFACE export, synchronized also dxfLibrary.py
+- changed to the new 2.49 method Vector.cross()
+- output style manager (first try)
+v1.33 - 2009.05.25 by migius
+- bugfix flipping normals in mirrored mesh-objects
+- added UI-Button for future Shadow Generator
+- support curve objects in projection-2d mode
+- UI stuff: camera selector/manager
+v1.32 - 2009.05.22 by migius
+- debug mode for curve-objects: output redirect to Blender
+- wip support 210-code(extrusion) calculation
+- default settings for 2D and 3D export
+v1.31 - 2009.05.18 by migius
+- globals translated to GUI_A/B dictionary
+- optimizing back-faces removal for "hidden-lines" mode
+- presets for global location and scale (architecture)
+- UI layout: scrollbars, pan with MMB/WHEEL, dynamic width
+- new GUI with Draw.Register() from DXF-importer.py
+v1.30 - 2008.12.14 by migius
+- started work on GUI with Draw.Register()
+v1.29 - 2009.04.11 by stani
+- added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter
+v1.28 - 2009.02.05 by Alexandros Sigalas (alxarch)
+- added option to apply modifiers on exported meshes
+- added option to also export duplicates (from dupliverts etc)
+v1.28 - 2008.10.22 by migius
+- workaround for PVert-bug on ubuntu (reported by Yorik)
+- add support for FGons - ignore invisible_tagged edges
+- add support for camera: ortho and perspective
v1.27 - 2008.10.07 by migius
- exclude Stani's DXF-Library to extern module
v1.26 - 2008.10.05 by migius
@@ -86,322 +142,2900 @@ ______________________________________________________________
import Blender
-from Blender import Mathutils, Window, Scene, sys, Draw
-import BPyMessages
+from Blender import Mathutils, Window, Scene, Draw, Camera, BezTriple
+from Blender import Registry, Object, Mesh, Curve
+import os
+import subprocess
+
+try:
+ import dxfLibrary as DXF
+ #reload(DXF)
+ #reload(dxfLibrary)
+ #from dxfLibrary import *
+except:
+ DXF=None
+ print "DXF-Exporter: error! found no dxfLibrary.py module in Blender script folder"
+ Draw.PupMenu("Error%t|found no dxfLibrary.py module in script folder")
+
+
+import math
+from math import atan, atan2, log10, sin, cos
+
+#pi = math.pi
+#pi = 3.14159265359
+r2d = 180.0 / math.pi
+d2r = math.pi / 180.0
+#note: d2r * angle == math.radians(angle)
+#note: r2d * angle == math.degrees(angle)
+
+
+#DEBUG = True #activates debug mode
+
+
+#----globals------------------------------------------
+ONLYSELECTED = 1 # 0/1 = False/True
+ONLYVISIBLE = 1 # ignore objects on invisible layers
+POLYLINES = 1 # prefer POLYLINEs not LINEs
+POLYFACES = 1 # prefer POLYFACEs not 3DFACEs
+PROJECTION = 0 # output geometry will be projected to XYplane with Z=0.0
+HIDDEN_LINES = 0 #filter out hidden geometry
+SHADOWS = 0 # sun/shadows simulation
+CAMERA = 1 # selected camera index
+PERSPECTIVE = 0 # projection (camera) type: perspective, opposite to orthographic
+CAMERAVIEW = 0 # use camera for projection, opposite is 3d-view
+INSTANCES = 1 # Export instances of Mesh/Curve as BLOCK/INSERTs on/off
+APPLY_MODIFIERS = 1
+INCLUDE_DUPLIS = 0
+OUTPUT_DWG = 0 #optional save to DWG with extern converter
+
+G_SCALE = 1.0 #(0.0001-1000) global scaling factor for output dxf data
+G_ORIGIN = [0.0,0.0,0.0] #global translation-vector (x,y,z) in Blender units
+ELEVATION = 0.0 #standard elevation = coordinate Z value in Blender units
+
+BYBLOCK = 0 #DXF-attribute: assign property to BLOCK defaults
+BYLAYER = None #256 #DXF-attribute: assign property to LAYER defaults
+PREFIX = 'BF_' #used as prefix for DXF names
+LAYERNAME_DEF = '' #default layer name
+LAYERCOLOR_DEF = 7 #default layer color index
+LAYERLTYPE_DEF = 0 #'CONTINUOUS' - default layer lineType
+ENTITYLAYER_DEF = LAYERNAME_DEF #default entity color index
+ENTITYCOLOR_DEF = BYLAYER #default entity color index
+ENTITYLTYPE_DEF = BYLAYER #default entity lineType
+
+E_M = 0
+LAB = "scroll MMB/WHEEL . wip .. todo" #"*) parts under construction"
+M_OBJ = 0
+
+FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE)
+NAMELENGTH_MAX = 80 #max_obnamelength in DXF, (limited to 256? )
+INIFILE_DEFAULT_NAME = 'exportDXF'
+INIFILE_EXTENSION = '.ini'
+INIFILE_HEADER = '#ExportDXF.py ver.1.0 config data'
+INFFILE_HEADER = '#ExportDXF.py ver.1.0 analyze of DXF-data'
+
+BLOCKREGISTRY = {} # registry and map for BLOCKs
+SCENE = None
+WORLDX = Mathutils.Vector((1,0,0))
+WORLDY = Mathutils.Vector((0,1,0))
+WORLDZ = Mathutils.Vector((0,0,1))
-#import dxfLibrary
-#reload(dxfLibrary)
-from dxfLibrary import *
+AUTO = BezTriple.HandleTypes.AUTO
+FREE = BezTriple.HandleTypes.FREE
+VECT = BezTriple.HandleTypes.VECT
+ALIGN = BezTriple.HandleTypes.ALIGN
+#-------- DWG support ------------------------------------------
+extCONV_OK = True
+extCONV = 'DConvertCon.exe'
+extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV)
+if not os.path.isfile(extCONV_PATH):
+ extCONV_OK = False
+ extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\
+Copy first %s into Blender script directory.|\
+More details in online Help.' %extCONV
+else:
+ if not os.sys.platform.startswith('win'):
+ # check if Wine installed:
+ if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip():
+ extCONV_PATH = 'wine %s'%extCONV_PATH
+ else:
+ extCONV_OK = False
+ extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\
+The external DWG-converter (%s) needs Wine installed on your system.|\
+More details in online Help.' %extCONV
+#print 'extCONV_PATH = ', extCONV_PATH
+
+
+#----------------------------------------------
+def updateMenuCAMERA():
+ global CAMERAS
+ global MenuCAMERA
+ global MenuLIGHT
+
+ scn = Scene.GetCurrent()
+ objs = scn.getChildren()
+ currcam = scn.getCurrentCamera()
+ if currcam: currcam = currcam.getName()
+ maincams = []
+ MenuCAMERA = "Select Camera%t"
+ for cam in objs:
+ if cam.getType() == 'Camera':
+ if cam.getName()[0:4] != "Temp":
+ maincams.append(cam.getName())
+ maincams.sort()
+ maincams.reverse()
+ CAMERAS = maincams
+ for i, cam in enumerate(CAMERAS):
+ if cam==currcam:
+ MenuCAMERA += "|* " + cam
+ else: MenuCAMERA += "| " + cam
+ MenuCAMERA += "|current 3d-View"
+ MenuLIGHT = "Select Sun%t| *todo"
+
+
+#----------------------------------------------
+def updateCAMERA():
+ global CAMERA, GUI_A
+ #CAMERA = 1
+ scn = Scene.GetCurrent()
+ currcam = scn.getCurrentCamera()
+ if currcam: currcam = currcam.getName()
+ if currcam in CAMERAS:
+ CAMERA = CAMERAS.index(currcam)+1
+ GUI_A['camera_selected'].val = CAMERA
+
+#----------------------------------------------
+def gotoCAMERA():
+ cam = Object.Get(CAMERAS[CAMERA-1])
+ #print 'deb: CAMERA, cam',CAMERA, cam
+ if cam.getType() != 'Camera':
+ sure = Draw.PupMenu("Info: %t| It is not a Camera Object.")
+ else:
+ scn = Scene.getCurrent()
+ scn.setCurrentCamera(cam)
+ Window.CameraView(0)
+ Window.Redraw()
+ updateMenuCAMERA()
+
+
+#------- Duplicates support ----------------------------------------------
+def dupTest(object):
+ """
+ Checks objects for duplicates enabled (any type)
+ object: Blender Object.
+ Returns: Boolean - True if object has any kind of duplicates enabled.
+ """
+ if (object.enableDupFrames or \
+ object.enableDupGroup or \
+ object.enableDupVerts):
+ return True
+ else:
+ return False
+
+def getObjectsAndDuplis(oblist,MATRICES=False,HACK=False):
+ """
+ Return a list of real objects and duplicates and optionally their matrices
+ oblist: List of Blender Objects
+ MATRICES: Boolean - Check to also get the objects matrices, default=False
+ HACK: Boolean - See note, default=False
+ Returns: List of objects or
+ List of tuples of the form:(ob,matrix) if MATRICES is set to True
+ NOTE: There is an ugly hack here that excludes all objects whose name
+ starts with "dpl_" to exclude objects that are parented to a duplicating
+ object, User must name objects properly if hack is used.
+ """
+
+ result = []
+ for ob in oblist:
+ if INCLUDE_DUPLIS and dupTest(ob):
+ dup_obs=ob.DupObjects
+ if len(dup_obs):
+ for dup_ob, dup_mx in dup_obs:
+ if MATRICES:
+ result.append((dup_ob,dup_mx))
+ else:
+ result.append(dup_ob)
+ else:
+ if HACK:
+ if ob.getName()[0:4] != "dpl_":
+ if MATRICES:
+ mx = ob.mat
+ result.append((ob,mx))
+ else:
+ result.append(ob)
+ else:
+ if MATRICES:
+ mx = ob.mat
+ result.append((ob,mx))
+ else:
+ result.append(ob)
+ return result
+
#-----------------------------------------------------
-def hidden_status(faces, mx_n):
- #print 'HIDDEN_MODE: caution! not full implemented yet'
- ok_faces = []
- ok_edges = []
- #sort out back-faces = with normals pointed away from camera
+def hidden_status(faces, mx, mx_n):
+ # sort out back-faces = with normals pointed away from camera
+ #print 'HIDDEN_LINES: caution! not full implemented yet'
+ front_faces = []
+ front_edges = []
for f in faces:
#print 'deb: face=', f #---------
+ #print 'deb: dir(face)=', dir(f) #---------
# get its normal-vector in localCS
vec_normal = f.no.copy()
#print 'deb: vec_normal=', vec_normal #------------------
- #must be transfered to camera/view-CS
+ # must be transfered to camera/view-CS
vec_normal *= mx_n
#vec_normal *= mb.rotationPart()
#print 'deb:2vec_normal=', vec_normal #------------------
#vec_normal *= mw0.rotationPart()
#print 'deb:3vec_normal=', vec_normal, '\n' #------------------
- # normal must point the Z direction-hemisphere
- if vec_normal[2] > 0.0 :
- ok_faces.append(f.index)
+
+ frontFace = False
+ if not PERSPECTIVE: #for ortho mode ----------
+ # normal must point the Z direction-hemisphere
+ if vec_normal[2] > 0.00001:
+ frontFace = True
+ else:
+ v = f.verts[0]
+ vert = Mathutils.Vector(v.co) * mx
+ if Mathutils.DotVecs(vert, vec_normal) < 0.00001:
+ frontFace = True
+
+ if frontFace:
+ front_faces.append(f.index)
for key in f.edge_keys:
#this test can be done faster with set()
- if key not in ok_edges:
- ok_edges.append(key)
- #print 'deb: amount of visible faces=', len(ok_faces) #---------
- #print 'deb: visible faces=', ok_faces #---------
- #print 'deb: amount of visible edges=', len(ok_edges) #---------
- #print 'deb: visible edges=', ok_edges #---------
- return ok_faces, ok_edges
+ if key not in front_edges:
+ front_edges.append(key)
+
+ #print 'deb: amount of visible faces=', len(front_faces) #---------
+ #print 'deb: visible faces=', front_faces #---------
+ #print 'deb: amount of visible edges=', len(front_edges) #---------
+ #print 'deb: visible edges=', front_edges #---------
+ return front_faces, front_edges
+
+
+#---- migration to 2.49-------------------------------------------------
+if 'cross' in dir(Mathutils.Vector()):
+ #Draw.PupMenu('DXF exporter: Abort%t|This script version works for Blender up 2.49 only!')
+ def M_CrossVecs(v1,v2):
+ return v1.cross(v2) #for up2.49
+ def M_DotVecs(v1,v2):
+ return v1.dot(v2) #for up2.49
+else:
+ def M_CrossVecs(v1,v2):
+ return Mathutils.CrossVecs(v1,v2) #for pre2.49
+ def M_DotVecs(v1,v2):
+ return Mathutils.DotVecs(v1,v2) #for pre2.49
+
+
+#-----------------------------------------------------
+def getExtrusion(matrix):
+ """calculates DXF-Extrusion = Arbitrary Xaxis and Zaxis vectors
+
+ """
+ AZaxis = matrix[2].copy().resize3D().normalize() # = ArbitraryZvector
+ Extrusion = [AZaxis[0],AZaxis[1],AZaxis[2]]
+ if AZaxis[2]==1.0:
+ Extrusion = None
+ AXaxis = matrix[0].copy().resize3D() # = ArbitraryXvector
+ else:
+ threshold = 1.0 / 64.0
+ if abs(AZaxis[0]) < threshold and abs(AZaxis[1]) < threshold:
+ # AXaxis is the intersection WorldPlane and ExtrusionPlane
+ AXaxis = M_CrossVecs(WORLDY,AZaxis)
+ else:
+ AXaxis = M_CrossVecs(WORLDZ,AZaxis)
+ #print 'deb:\n' #-------------
+ #print 'deb:getExtrusion() Extrusion=', Extrusion #---------
+ return Extrusion, AXaxis.normalize()
#-----------------------------------------------------
-def projected_co(vec, mw):
- # convert the world coordinates of vector to screen coordinates
- #co = vec.co.copy().resize4D()
- co = vec.copy().resize4D()
- co[3] = 1.0
- sc = co * mw
- #print 'deb: viewprojection=', sc #---------
- return [sc[0],sc[1],0.0]
-
-
-#--------not used---------------------------------------------
-def flatten(points, mw):
- for i,v in enumerate(points):
- v = projected_co(v, mw)
- points[i]=v
- #print 'deb: flatten points=', points #---------
- return points
+def getZRotation(AXaxis, rot_matrix_invert):
+ """calculates ZRotation = angle between ArbitraryXvector and obj.matrix.Xaxis
+
+ """
+ # this works: Xaxis is the obj.matrix-Xaxis vector
+ # but not correct for all orientations
+ #Xaxis = matrix[0].copy().resize3D() # = ArbitraryXvector
+ ##Xaxis.normalize() # = ArbitraryXvector
+ #ZRotation = - Mathutils.AngleBetweenVecs(Xaxis,AXaxis) #output in radians
+
+ # this works for all orientations, maybe a bit faster
+ # transform AXaxis into OCS:Object-Coord-System
+ #rot_matrix = normalizeMat(matrix.rotationPart())
+ #rot_matrix_invert = rot_matrix.invert()
+ vec = AXaxis * rot_matrix_invert
+ ##vec = AXaxis * matrix.copy().invert()
+ ##vec.normalize() # not needed for atan2()
+ #print '\ndeb:getExtrusion() vec=', vec #---------
+ ZRotation = - atan2(vec[1],vec[0]) #output in radians
+
+ #print 'deb:ZRotation() ZRotation=', ZRotation*r2d #---------
+ return ZRotation
+
+
+#------------------------------------------
+def normalizeMat(matrix):
+ mat12 = matrix.copy()
+ mat12 = [Mathutils.Vector(v).normalize() for v in mat12]
+ if len(mat12)>3:
+ matr12 = Mathutils.Matrix(mat12[0],mat12[1],mat12[2],mat12[3])
+ else:
+ matr12 = Mathutils.Matrix(mat12[0],mat12[1],mat12[2])
+ return matr12
+
#-----------------------------------------------------
-def exportMesh(ob, mx, mx_n):
+def projected_co(verts, matrix):
+ """ converts coordinates of points from OCS to WCS->ScreenCS
+ needs matrix: a projection matrix
+ needs verts: a list of vectors[x,y,z]
+ returns a list of [x,y,z]
+ """
+ #print 'deb:projected_co() verts=', verts #---------
+ temp_verts = [Mathutils.Vector(v)*matrix for v in verts]
+ #print 'deb:projected_co() temp_verts=', temp_verts #---------
+
+ if GUI_A['Z_force_on'].val: locZ = GUI_A['Z_elev'].val
+ else: locZ = 0.0
+
+ if PROJECTION:
+ if PERSPECTIVE:
+ clipStart = 10.0
+ for v in temp_verts:
+ coef = - clipStart / v[2]
+ v[0] *= coef
+ v[1] *= coef
+ v[2] = locZ
+ for v in temp_verts:
+ v[2] = locZ
+ temp_verts = [v[:3] for v in temp_verts]
+ #print 'deb:projected_co() out_verts=', temp_verts #---------
+ return temp_verts
+
+
+#-----------------------------------------------------
+def isLeftHand(matrix):
+ #Is the matrix a left-hand-system, or not?
+ ma = matrix.rotationPart()
+ crossXY = M_CrossVecs(ma[0], ma[1])
+ check = M_DotVecs(ma[2], crossXY)
+ if check < 0.00001: return 1
+ return 0
+
+
+#-----------------------------------------------------
+def exportMesh(ob, mx, mx_n, me=None, **common):
+ """converts Mesh-Object to desired projection and representation(DXF-Entity type)
+ """
+ global BLOCKREGISTRY
entities = []
- me = ob.getData(mesh=1)
- #me.transform(mx)
- # above is eventualy faster, but bad, cause
- # directly transforms origin geometry and write back rounding errors
- me_verts = me.verts[:] #we dont want manipulate origin data
- #print 'deb: me_verts=', me_verts #---------
- #me.transform(mx_inv) #counterpart to - back to the origin state
- for v in me_verts:
- v.co *= mx
- faces=[]
- edges=[]
- if HIDDEN_MODE:
- ok_faces, ok_edges = hidden_status(me.faces, mx_n)
-
- #if (not FLATTEN) and len(me.faces)>0 and ONLYFACES:
- if ONLYFACES:
- if POLYFACES: #export 3D as POLYFACEs
- allpoints = []
- allfaces = []
- allpoints = [v.co[:3] for v in me_verts]
- for f in me.faces:
- #print 'deb: face=', f #---------
- if not HIDDEN_MODE or \
- (HIDDEN_MODE and f.index in ok_faces):
- if 1:
- points = f.verts
- face = [p.index+1 for p in points]
- #print 'deb: face=', face #---------
- allfaces.append(face)
- else: #bad, cause create multiple vertex instances
- points = f.verts
- points = [ me_verts[p.index].co[:3] for p in points]
- #points = [p.co[:3] for p in points]
- #print 'deb: points=', points #---------
- index = len(allpoints)+1
- face = [index+i for i in range(len(points))]
- allpoints.extend(points)
- allfaces.append(face)
- if allpoints and allfaces:
- #print 'deb: allpoints=', allpoints #---------
- #print 'deb: allfaces=', allfaces #---------
- dxfPOLYFACE = PolyLine([allpoints, allfaces], flag=64)
+ block = None
+ #print 'deb:exportMesh() given common=', common #---------
+ if me==None:
+ me = ob.getData(mesh=1)
+ else:
+ me.getFromObject(ob)
+ # idea: me.transform(mx); get verts data; me.transform(mx_inv)= back to the origin state
+ # the .transform-method is fast, but bad, cause invasive:
+ # it manipulates original geometry and by retransformation lefts back rounding-errors
+ # we dont want to manipulate original data!
+ #temp_verts = me.verts[:] #doesn't work on ubuntu(Yorik), bug?
+ if me.verts:
+ #print 'deb:exportMesh() started' #---------
+
+ #print 'deb:exportMesh() ob.name=', ob.name #---------
+ #print 'deb:exportMesh() me.name=', me.name #---------
+ #print 'deb:exportMesh() me.users=', me.users #---------
+ # check if there are more instances of this mesh (if used by other objects), then write to BLOCK/INSERT
+ if GUI_A['instances_on'].val and me.users>1 and not PROJECTION:
+ if me.name in BLOCKREGISTRY.keys():
+ insert_name = BLOCKREGISTRY[me.name]
+ # write INSERT to entities
+ entities = exportInsert(ob, mx,insert_name, **common)
+ else:
+ # generate geom_output in ObjectCS
+ allpoints = [v.co for v in me.verts]
+ identity_matrix = Mathutils.Matrix().identity()
+ allpoints = projected_co(allpoints, identity_matrix)
+ #allpoints = toGlobalOrigin(allpoints)
+ faces=[]
+ edges=[]
+ for e in me.edges: edges.append(e.key)
+ faces = [[v.index for v in f.verts] for f in me.faces]
+ entities = writeMeshEntities(allpoints, edges, faces, **common)
+ if entities: # if not empty block
+ # write BLOCK definition and INSERT entity
+ # BLOCKREGISTRY = dictionary 'blender_name':'dxf_name'.append(me.name)
+ BLOCKREGISTRY[me.name]=validDXFr12name(('ME_'+ me.name))
+ insert_name = BLOCKREGISTRY[me.name]
+ block = DXF.Block(insert_name,flag=0,base=(0,0,0),entities=entities)
+ # write INSERT as entity
+ entities = exportInsert(ob, mx, insert_name, **common)
+
+ else: # no other instances, so go the standard way
+ allpoints = [v.co for v in me.verts]
+ allpoints = projected_co(allpoints, mx)
+ allpoints = toGlobalOrigin(allpoints)
+ faces=[]
+ edges=[]
+ if me.faces and PROJECTION and HIDDEN_LINES:
+ #if DEBUG: print 'deb:exportMesh HIDDEN_LINES mode' #---------
+ faces, edges = hidden_status(me.faces, mx, mx_n)
+ faces = [[v.index for v in me.faces[f_nr].verts] for f_nr in faces]
+ else:
+ #if DEBUG: print 'deb:exportMesh STANDARD mode' #---------
+ for e in me.edges: edges.append(e.key)
+ #faces = [f.index for f in me.faces]
+ faces = [[v.index for v in f.verts] for f in me.faces]
+ #faces = [[allpoints[v.index] for v in f.verts] for f in me.faces]
+ #print 'deb: allpoints=\n', allpoints #---------
+ #print 'deb: edges=\n', edges #---------
+ #print 'deb: faces=\n', faces #---------
+ if isLeftHand(mx): # then change vertex-order in every face
+ for f in faces:
+ f.reverse()
+ #f = [f[-1]] + f[:-1] #TODO: might be needed
+ #print 'deb: faces=\n', faces #---------
+ entities = writeMeshEntities(allpoints, edges, faces, **common)
+
+ return entities, block
+
+
+#-------------------------------------------------
+def writeMeshEntities(allpoints, edges, faces, **common):
+ """help routine for exportMesh()
+ """
+ entities = []
+
+ c = mesh_as_list[GUI_A['mesh_as'].val]
+ if 'POINTs'==c: # export Mesh as multiple POINTs
+ for p in allpoints:
+ dxfPOINT = DXF.Point(points=[p],**common)
+ entities.append(dxfPOINT)
+ elif 'LINEs'==c or (not faces):
+ if edges and allpoints:
+ if DEBUG: mesh_drawBlender(allpoints, edges, None) #deb: draw to blender scene
+ for e in edges:
+ points = [allpoints[e[0]], allpoints[e[1]]]
+ dxfLINE = DXF.Line(points, **common)
+ entities.append(dxfLINE)
+ elif faces:
+ if c in ('POLYFACE','POLYLINE'):
+ if allpoints:
+ #TODO: purge allpoints: left only vertices used by faces
+ if DEBUG: mesh_drawBlender(allpoints, None, faces) #deb: draw to scene
+ if not (PROJECTION and HIDDEN_LINES):
+ faces = [[v+1 for v in f] for f in faces]
+ else:
+ # for back-Faces-mode remove face-free verts
+ map=verts_state= [0]*len(allpoints)
+ for f in faces:
+ for v in f:
+ verts_state[v]=1
+ if 0 in verts_state: # if dirty state
+ i,newverts=0,[]
+ for used_i,used in enumerate(verts_state):
+ if used:
+ newverts.append(allpoints[used_i])
+ map[used_i]=i
+ i+=1
+ allpoints = newverts
+ faces = [[map[v]+1 for v in f] for f in faces]
+ dxfPOLYFACE = DXF.PolyLine([allpoints, faces], flag=64, **common)
+ #print '\n deb: dxfPOLYFACE=',dxfPOLYFACE #-------------
entities.append(dxfPOLYFACE)
- else: #export 3D as 3DFACEs
- for f in me.faces:
+ elif '3DFACEs'==c:
+ if DEBUG: mesh_drawBlender(allpoints, None, faces) #deb: draw to scene
+ for f in faces:
#print 'deb: face=', f #---------
- if not HIDDEN_MODE or \
- (HIDDEN_MODE and f.index in ok_faces):
- points = f.verts
- points = [ me_verts[p.index].co[:3] for p in points]
- #points = [p.co[:3] for p in points]
- #print 'deb: points=', points #---------
- dxfFACE = Face(points)
- entities.append(dxfFACE)
-
- else: #export 3D as LINEs
- if HIDDEN_MODE and len(me.faces)!=0:
- for e in ok_edges:
- points = [ me_verts[key].co[:3] for key in e]
- dxfLINE = Line(points)
- entities.append(dxfLINE)
+ points = [allpoints[key] for key in f]
+ #points = [p.co[:3] for p in points]
+ #print 'deb: pointsXX=\n', points #---------
+ dxfFACE = DXF.Face(points, **common)
+ entities.append(dxfFACE)
- else:
- for e in me.edges:
- #print 'deb: edge=', e #---------
- points=[]
- #points = [e.v1.co*mx, e.v2.co*mx]
- points = [ me_verts[key].co[:3] for key in e.key]
- #print 'deb: points=', points #---------
- dxfLINE = Line(points)
- entities.append(dxfLINE)
return entities
#-----------------------------------------------------
-def exportCurve(ob, mx):
+def mesh_drawBlender(vertList, edgeList, faceList, name="dxfMesh", flatten=False, AT_CUR=True, link=True):
+ #print 'deb:mesh_drawBlender started XXXXXXXXXXXXXXXXXX' #---------
+ ob = Object.New("Mesh",name)
+ me = Mesh.New(name)
+ #print 'deb: vertList=\n', vertList #---------
+ #print 'deb: edgeList=\n', edgeList #---------
+ #print 'deb: faceList=\n', faceList #---------
+ me.verts.extend(vertList)
+ if edgeList: me.edges.extend(edgeList)
+ if faceList: me.faces.extend(faceList)
+ if flatten:
+ for v in me.verts: v.co.z = 0.0
+ ob.link(me)
+ if link:
+ sce = Scene.getCurrent()
+ sce.objects.link(ob)
+ #me.triangleToQuad()
+ if AT_CUR:
+ cur_loc = Window.GetCursorPos()
+ ob.setLocation(cur_loc)
+ Blender.Redraw()
+ #return ob
+
+#-----------------------------------------------------
+def curve_drawBlender(vertList, org_point=[0.0,0.0,0.0], closed=0, name="dxfCurve", flatten=False, AT_CUR=True, link=True):
+ #print 'deb:curve_drawBlender started XXXXXXXXXXXXXXXXXX' #---------
+ ob = Object.New("Curve",name)
+ cu = Curve.New(name)
+ #print 'deb: vertList=\n', vertList #---------
+ curve = cu.appendNurb(BezTriple.New(vertList[0]))
+ for p in vertList[1:]:
+ curve.append(BezTriple.New(p))
+ for point in curve:
+ #point.handleTypes = [VECT, VECT]
+ point.handleTypes = [FREE, FREE]
+ point.radius = 1.0
+ curve.flagU = closed # 0 sets the curve not cyclic=open
+ cu.setResolu(6)
+ cu.update() #important for handles calculation
+ if flatten:
+ for v in cu.verts: v.co.z = 0.0
+ ob.link(cu)
+ if link:
+ sce = Scene.getCurrent()
+ sce.objects.link(ob)
+ #me.triangleToQuad()
+ if AT_CUR:
+ cur_loc = Window.GetCursorPos()
+ ob.setLocation(cur_loc)
+ elif org_point:
+ cur_loc=org_point
+ ob.setLocation(cur_loc)
+ Blender.Redraw()
+ #return ob
+
+
+#-----------------------------------------------------
+def toGlobalOrigin(points):
+ """relocates points to the new location
+ needs a list of points [x,y,z]
+ """
+ if GUI_A['g_origin_on'].val:
+ for p in points:
+ p[0] += G_ORIGIN[0]
+ p[1] += G_ORIGIN[1]
+ p[2] += G_ORIGIN[2]
+ return points
+
+
+#-----------------------------------------------------
+def exportEmpty(ob, mx, mw, **common):
+ """converts Empty-Object to desired projection and representation(DXF-Entity type)
+ """
+ p = Mathutils.Vector(ob.loc)
+ [p] = projected_co([p], mx)
+ [p] = toGlobalOrigin([p])
+
+ entities = []
+ c = empty_as_list[GUI_A['empty_as'].val]
+ if c=="POINT": # export Empty as POINT
+ dxfPOINT = DXF.Point(points=[p],**common)
+ entities.append(dxfPOINT)
+ return entities
+
+#-----------------------------------------------------
+def exportCamera(ob, mx, mw, **common):
+ """converts Camera-Object to desired projection and representation(DXF-Entity type)
+ """
+ location = Mathutils.Vector(ob.loc)
+ [location] = projected_co([location], mx)
+ [location] = toGlobalOrigin([location])
+ view_name=validDXFr12name(('CAM_'+ ob.name))
+
+ camera = Camera.Get(ob.getData(name_only=True))
+ #print 'deb: camera=', dir(camera) #------------------
+ if camera.type=='persp':
+ mode = 1+2+4+16
+ # mode flags: 1=persp, 2=frontclip, 4=backclip,16=FrontZ
+ elif camera.type=='ortho':
+ mode = 0+2+4+16
+
+ leftBottom=(0.0,0.0) # default
+ rightTop=(1.0,1.0) # default
+ center=(0.0,0.0) # default
+
+ direction = Mathutils.Vector(0.0,0.0,1.0) * mx.rotationPart() # in W-C-S
+ direction.normalize()
+ target=Mathutils.Vector(ob.loc) - direction # in W-C-S
+ #ratio=1.0
+ width=height= camera.scale # for ortho-camera
+ lens = camera.lens # for persp-camera
+ frontClipping = -(camera.clipStart - 1.0)
+ backClipping = -(camera.clipEnd - 1.0)
+
+ entities, vport, view = [], None, None
+ c = camera_as_list[GUI_A['camera_as'].val]
+ if c=="POINT": # export as POINT
+ dxfPOINT = DXF.Point(points=[location],**common)
+ entities.append(dxfPOINT)
+ elif c=="VIEW": # export as VIEW
+ view = DXF.View(name=view_name,
+ center=center, width=width, height=height,
+ frontClipping=frontClipping,backClipping=backClipping,
+ direction=direction,target=target,lens=lens,mode=mode
+ )
+ elif c=="VPORT": # export as VPORT
+ vport = DXF.VPort(name=view_name,
+ center=center, ratio=1.0, height=height,
+ frontClipping=frontClipping,backClipping=backClipping,
+ direction=direction,target=target,lens=lens,mode=mode
+ )
+ return entities, vport, view
+
+#-----------------------------------------------------
+def exportLamp(ob, mx, mw, **common):
+ """converts Lamp-Object to desired projection and representation(DXF-Entity type)
+ """
+ p = Mathutils.Vector(ob.loc)
+ [p] = projected_co([p], mx)
+ [p] = toGlobalOrigin([p])
+
+ entities = []
+ c = lamp_as_list[GUI_A['lamp_as'].val]
+ if c=="POINT": # export as POINT
+ dxfPOINT = DXF.Point(points=[p],**common)
+ entities.append(dxfPOINT)
+ return entities
+
+#-----------------------------------------------------
+def exportInsert(ob, mx, insert_name, **common):
+ """converts Object to DXF-INSERT in given orientation
+ """
+ WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem
+ sizeX = ob.SizeX
+ sizeY = ob.SizeY
+ sizeZ = ob.SizeZ
+ rotX = ob.RotX
+ rotY = ob.RotY
+ rotZ = ob.RotZ
+ #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #---------
+
+ Thickness,Extrusion,ZRotation,Elevation = None,None,None,None
+
+ AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector
+ if not PROJECTION:
+ #Extrusion, ZRotation, Elevation = getExtrusion(mx)
+ Extrusion, AXaxis = getExtrusion(mx)
+
+ entities = []
+
+ if 1:
+ if not PROJECTION:
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\
+ AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ)
+ ZRotation *= r2d
+ point = ECS_origin
+ else: #TODO: fails correct location
+ point1 = Mathutils.Vector(ob.loc)
+ [point] = projected_co([point1], mx)
+ if PERSPECTIVE:
+ clipStart = 10.0
+ coef = -clipStart / (point1*mx)[2]
+ #print 'deb: coef=', coef #--------------
+ #TODO: ? sizeX *= coef
+ #sizeY *= coef
+ #sizeZ *= coef
+
+ #print 'deb: point=', point #--------------
+ [point] = toGlobalOrigin([point])
+
+ #if DEBUG: text_drawBlender(textstr,points,OCS_origin) #deb: draw to scene
+ common['extrusion']= Extrusion
+ #common['elevation']= Elevation
+ #print 'deb: common=', common #------------------
+ if 0: #DEBUG
+ #linepoints = [[0,0,0], [AXaxis[0],AXaxis[1],AXaxis[2]]]
+ linepoints = [[0,0,0], point]
+ dxfLINE = DXF.Line(linepoints,**common)
+ entities.append(dxfLINE)
+
+ xscale=sizeX
+ yscale=sizeY
+ zscale=sizeZ
+ cols=None
+ colspacing=None
+ rows=None
+ rowspacing=None
+
+ dxfINSERT = DXF.Insert(insert_name,point=point,rotation=ZRotation,\
+ xscale=xscale,yscale=yscale,zscale=zscale,\
+ cols=cols,colspacing=colspacing,rows=rows,rowspacing=rowspacing,\
+ **common)
+ entities.append(dxfINSERT)
+
+ return entities
+
+
+#-----------------------------------------------------
+def exportText(ob, mx, mw, **common):
+ """converts Text-Object to desired projection and representation(DXF-Entity type)
+ """
+ text3d = ob.getData()
+ textstr = text3d.getText()
+ WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem
+ sizeX = ob.SizeX
+ sizeY = ob.SizeY
+ sizeZ = ob.SizeZ
+ rotX = ob.RotX
+ rotY = ob.RotY
+ rotZ = ob.RotZ
+ #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #---------
+
+ Thickness,Extrusion,ZRotation,Elevation = None,None,None,None
+
+ AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector
+ if not PROJECTION:
+ #Extrusion, ZRotation, Elevation = getExtrusion(mx)
+ Extrusion, AXaxis = getExtrusion(mx)
+
+ # no thickness/width for TEXTs converted into ScreenCS
+ if text3d.getExtrudeDepth():
+ Thickness = text3d.getExtrudeDepth() * sizeZ
+
+ #Horizontal text justification type, code 72, (optional, default = 0)
+ # integer codes (not bit-coded)
+ #0=left, 1=center, 2=right
+ #3=aligned, 4=middle, 5=fit
+ Alignment = None
+ alignment = text3d.getAlignment().value
+ if alignment in (1,2): Alignment = alignment
+
+ textHeight = text3d.getSize() / 1.7
+ textFlag = 0
+ if sizeX < 0.0: textFlag |= 2 # set flag for horizontal mirrored
+ if sizeZ < 0.0: textFlag |= 4 # vertical mirrored
+
+ entities = []
+ c = text_as_list[GUI_A['text_as'].val]
+
+ if c=="TEXT": # export text as TEXT
+ if not PROJECTION:
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\
+ AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ)
+ ZRotation *= r2d
+ point = ECS_origin
+ else: #TODO: fails correct location
+ point1 = Mathutils.Vector(ob.loc)
+ [point] = projected_co([point1], mx)
+ if PERSPECTIVE:
+ clipStart = 10.0
+ coef = -clipStart / (point1*mx)[2]
+ textHeight *= coef
+ #print 'deb: coef=', coef #--------------
+
+ #print 'deb: point=', point #--------------
+ [point] = toGlobalOrigin([point])
+ point2 = point
+
+ #if DEBUG: text_drawBlender(textstr,points,OCS_origin) #deb: draw to scene
+ common['extrusion']= Extrusion
+ #common['elevation']= Elevation
+ common['thickness']= Thickness
+ #print 'deb: common=', common #------------------
+ if 0: #DEBUG
+ #linepoints = [[0,0,0], [AXaxis[0],AXaxis[1],AXaxis[2]]]
+ linepoints = [[0,0,0], point]
+ dxfLINE = DXF.Line(linepoints,**common)
+ entities.append(dxfLINE)
+
+ dxfTEXT = DXF.Text(text=textstr,point=point,alignment=point2,rotation=ZRotation,\
+ flag=textFlag,height=textHeight,justifyhor=Alignment,**common)
+ entities.append(dxfTEXT)
+ if Thickness:
+ common['thickness']= -Thickness
+ dxfTEXT = DXF.Text(text=textstr,point=point,alignment=point2,rotation=ZRotation,\
+ flag=textFlag,height=textHeight,justifyhor=Alignment,**common)
+ entities.append(dxfTEXT)
+ return entities
+
+
+#-------------------------------------------
+def euler2matrix(rx, ry, rz):
+ """creates full 3D rotation matrix (optimized)
+ needs rx, ry, rz angles in radians
+ """
+ #print 'rx, ry, rz: ', rx, ry, rz
+ A, B = sin(rx), cos(rx)
+ C, D = sin(ry), cos(ry)
+ E, F = sin(rz), cos(rz)
+ AC, BC = A*C, B*C
+ return Mathutils.Matrix([D*F, D*E, -C],
+ [AC*F-B*E, AC*E+B*F, A*D],
+ [BC*F+A*E, BC*E-A*F, B*D])
+
+
+#-----------------------------------------------------
+def getTargetOrientation(mx,Extrusion,AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ):
+ """given
+ """
+ if 1:
+ rot_matrix = normalizeMat(mx.rotationPart())
+ #TODO: workaround for blender negative-matrix.invert()
+ # partially done: works only for rotX,rotY==0.0
+ if sizeX<0.0: rot_matrix[0] *= -1
+ if sizeY<0.0: rot_matrix[1] *= -1
+ #if sizeZ<0.0: rot_matrix[2] *= -1
+ rot_matrix_invert = rot_matrix.invert()
+ else: #TODO: to check, why below rot_matrix_invert is not equal above one
+ rot_euler_matrix = euler2matrix(rotX,rotY,rotZ)
+ rot_matrix_invert = euler2matrix(-rotX,-rotY,-rotZ)
+
+ # OCS_origin is Global_Origin in ObjectCoordSystem
+ OCS_origin = Mathutils.Vector(WCS_loc) * rot_matrix_invert
+ #print 'deb: OCS_origin=', OCS_origin #---------
+
+ ZRotation = rotZ
+ if Extrusion!=None:
+ ZRotation = getZRotation(AXaxis,rot_matrix_invert)
+ #Zrotmatrix = Mathutils.RotationMatrix(-ZRotation, 3, "Z")
+ rs, rc = sin(ZRotation), cos(ZRotation)
+ Zrotmatrix = Mathutils.Matrix([rc, rs,0.0],[-rs,rc,0.0],[0.0,0.0,1.0])
+ #print 'deb: Zrotmatrix=\n', Zrotmatrix #--------------
+
+ # ECS_origin is Global_Origin in EntityCoordSystem
+ ECS_origin = OCS_origin * Zrotmatrix
+ #print 'deb: ECS_origin=', ECS_origin #---------
+ #TODO: it doesnt work yet for negative scaled curve-objects!
+ return ZRotation,Zrotmatrix,OCS_origin,ECS_origin
+
+
+#-----------------------------------------------------
+def exportCurve(ob, mx, mw, **common):
+ """converts Curve-Object to desired projection and representation(DXF-Entity type)
+ """
entities = []
+ block = None
curve = ob.getData()
- for cur in curve:
- #print 'deb: START cur=', cur #--------------
- if 1: #not cur.isNurb():
- #print 'deb: START points' #--------------
+ #print 'deb: curve=', dir(curve) #---------
+ # TODO: should be: if curve.users>1 and not (PERSPECTIVE or (PROJECTION and HIDDEN_MODE):
+ if GUI_A['instances_on'].val and curve.users>1 and not PROJECTION:
+ if curve.name in BLOCKREGISTRY.keys():
+ insert_name = BLOCKREGISTRY[curve.name]
+ # write INSERT to entities
+ entities = exportInsert(ob, mx,insert_name, **common)
+ else:
+ # generate geom_output in ObjectCS
+ imx = Mathutils.Matrix().identity()
+ WCS_loc = [0,0,0] # WCS_loc is object location in WorldCoordSystem
+ #print 'deb: WCS_loc=', WCS_loc #---------
+ sizeX = sizeY = sizeZ = 1.0
+ rotX = rotY = rotZ = 0.0
+ Thickness,Extrusion,ZRotation,Elevation = None,None,None,None
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = None,None,None,None
+ AXaxis = imx[0].copy().resize3D() # = ArbitraryXvector
+ OCS_origin = [0,0,0]
+ if not PROJECTION:
+ #Extrusion, ZRotation, Elevation = getExtrusion(mx)
+ Extrusion, AXaxis = getExtrusion(imx)
+
+ # no thickness/width for POLYLINEs converted into Screen-C-S
+ #print 'deb: curve.ext1=', curve.ext1 #---------
+ if curve.ext1: Thickness = curve.ext1 * sizeZ
+ if curve.ext2 and sizeX==sizeY:
+ Width = curve.ext2 * sizeX
+ if "POLYLINE"==curve_as_list[GUI_A['curve_as'].val]: # export as POLYLINE
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(imx,Extrusion,\
+ AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ)
+
+ entities = writeCurveEntities(curve, imx,
+ Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix,
+ WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ,
+ **common)
+
+ if entities: # if not empty block
+ # write BLOCK definition and INSERT entity
+ # BLOCKREGISTRY = dictionary 'blender_name':'dxf_name'.append(me.name)
+ BLOCKREGISTRY[curve.name]=validDXFr12name(('CU_'+ curve.name))
+ insert_name = BLOCKREGISTRY[curve.name]
+ block = DXF.Block(insert_name,flag=0,base=(0,0,0),entities=entities)
+ # write INSERT as entity
+ entities = exportInsert(ob, mx, insert_name, **common)
+
+ else: # no other instances, so go the standard way
+ WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem
+ #print 'deb: WCS_loc=', WCS_loc #---------
+ sizeX = ob.SizeX
+ sizeY = ob.SizeY
+ sizeZ = ob.SizeZ
+ rotX = ob.RotX
+ rotY = ob.RotY
+ rotZ = ob.RotZ
+ #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #---------
+
+ Thickness,Extrusion,ZRotation,Elevation = None,None,None,None
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = None,None,None,None
+ AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector
+ OCS_origin = [0,0,0]
+ if not PROJECTION:
+ #Extrusion, ZRotation, Elevation = getExtrusion(mx)
+ Extrusion, AXaxis = getExtrusion(mx)
+
+ # no thickness/width for POLYLINEs converted into Screen-C-S
+ #print 'deb: curve.ext1=', curve.ext1 #---------
+ if curve.ext1: Thickness = curve.ext1 * sizeZ
+ if curve.ext2 and sizeX==sizeY:
+ Width = curve.ext2 * sizeX
+ if "POLYLINE"==curve_as_list[GUI_A['curve_as'].val]: # export as POLYLINE
+ ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\
+ AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ)
+ entities = writeCurveEntities(curve, mx,
+ Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix,
+ WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ,
+ **common)
+
+ return entities, block
+
+
+#-------------------------------------------------
+def writeCurveEntities(curve, mx,
+ Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix,
+ WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ,
+ **common):
+ """help routine for exportCurve()
+ """
+ entities = []
+
+ if 1:
+ for cur in curve:
+ #print 'deb: START cur=', cur #--------------
points = []
- org_point = [0.0,0.0,0.0]
- for point in cur:
- #print 'deb: point=', point #---------
- if cur.isNurb():
+ if cur.isNurb():
+ for point in cur:
+ #print 'deb:isNurb point=', point #---------
vec = point[0:3]
- else:
- point = point.getTriple()
- #print 'deb: point=', point #---------
- vec = point[1]
- #print 'deb: vec=', vec #---------
- pkt = Mathutils.Vector(vec) * mx
- #print 'deb: pkt=', pkt #---------
- #pkt *= SCALE_FACTOR
- if 0: #FLATTEN:
- pkt = projected_co(pkt, mw)
- points.append(pkt)
- if cur.isCyclic(): closed = 1
- else: closed = 0
+ #print 'deb: vec=', vec #---------
+ pkt = Mathutils.Vector(vec)
+ #print 'deb: pkt=', pkt #---------
+ points.append(pkt)
+ else:
+ for point in cur:
+ #print 'deb:isBezier point=', point.getTriple() #---------
+ vec = point.getTriple()[1]
+ #print 'deb: vec=', vec #---------
+ pkt = Mathutils.Vector(vec)
+ #print 'deb: pkt=', pkt #---------
+ points.append(pkt)
+
+ #print 'deb: points', points #--------------
if len(points)>1:
- #print 'deb: points', points #--------------
- if POLYLINES: dxfPLINE = PolyLine(points,org_point,closed)
- else: dxfPLINE = LineList(points,org_point,closed)
- entities.append(dxfPLINE)
+ c = curve_as_list[GUI_A['curve_as'].val]
+
+ if c=="POLYLINE": # export Curve as POLYLINE
+ if not PROJECTION:
+ # recalculate points(2d=X,Y) into Entity-Coords-System
+ for p in points: # list of vectors
+ p[0] *= sizeX
+ p[1] *= sizeY
+ p2 = p * Zrotmatrix
+ p2[0] += ECS_origin[0]
+ p2[1] += ECS_origin[1]
+ p[0],p[1] = p2[0],p2[1]
+ else:
+ points = projected_co(points, mx)
+ #print 'deb: points', points #--------------
+
+ if cur.isCyclic(): closed = 1
+ else: closed = 0
+ points = toGlobalOrigin(points)
+
+ if DEBUG: curve_drawBlender(points,OCS_origin,closed) #deb: draw to scene
+
+ common['extrusion']= Extrusion
+ ##common['rotation']= ZRotation
+ ##common['elevation']= Elevation
+ common['thickness']= Thickness
+ #print 'deb: common=', common #------------------
+
+ if 0: #DEBUG
+ p=AXaxis[:3]
+ entities.append(DXF.Line([[0,0,0], p],**common))
+ p=ECS_origin[:3]
+ entities.append(DXF.Line([[0,0,0], p],**common))
+ common['color']= 5
+ p=OCS_origin[:3]
+ entities.append(DXF.Line([[0,0,0], p],**common))
+ #OCS_origin=[0,0,0] #only debug----------------
+ dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common)
+ entities.append(dxfPLINE)
+
+ dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common)
+ entities.append(dxfPLINE)
+ if Thickness:
+ common['thickness']= -Thickness
+ dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common)
+ entities.append(dxfPLINE)
+
+ elif c=="LINEs": # export Curve as multiple LINEs
+ points = projected_co(points, mx)
+ if cur.isCyclic(): points.append(points[0])
+ #print 'deb: points', points #--------------
+ points = toGlobalOrigin(points)
+
+ if DEBUG: curve_drawBlender(points,WCS_loc,closed) #deb: draw to scene
+ common['extrusion']= Extrusion
+ common['elevation']= Elevation
+ common['thickness']= Thickness
+ #print 'deb: common=', common #------------------
+ for i in range(len(points)-1):
+ linepoints = [points[i], points[i+1]]
+ dxfLINE = DXF.Line(linepoints,**common)
+ entities.append(dxfLINE)
+ if Thickness:
+ common['thickness']= -Thickness
+ for i in range(len(points)-1):
+ linepoints = [points[i], points[i+1]]
+ dxfLINE = DXF.Line(linepoints,**common)
+ entities.append(dxfLINE)
+
+ elif c=="POINTs": # export Curve as multiple POINTs
+ points = projected_co(points, mx)
+ for p in points:
+ dxfPOINT = DXF.Point(points=[p],**common)
+ entities.append(dxfPOINT)
return entities
+
#-----------------------------------------------------
-def do_export(sel_group, filepath):
+def getClipBox(camera):
+ """calculates Field-of-View-Clipping-Box of given Camera
+ returns clip_box: a list of vertices
+ returns matr: translation matrix
+ """
+ sce = Scene.GetCurrent()
+ context = sce.getRenderingContext()
+ #print 'deb: context=\n', context #------------------
+ sizeX = context.sizeX
+ sizeY = context.sizeY
+ ratioXY = sizeX/float(sizeY)
+ #print 'deb: size X,Y, ratio=', sizeX, sizeY, ratioXY #------------------
+
+ clip1_Z = - camera.clipStart
+ clip2_Z = - camera.clipEnd
+ #print 'deb: clip Start=', camera.clipStart #------------------
+ #print 'deb: clip End=', camera.clipEnd #------------------
+
+ if camera.type=='ortho':
+ scale = camera.scale
+ #print 'deb: camscale=', scale #------------------
+ clip1shiftX = clip2shiftX = camera.shiftX * scale
+ clip1shiftY = clip2shiftY = camera.shiftY * scale
+ clip1_X = scale * 0.5
+ clip1_Y = scale * 0.5
+ if ratioXY > 1.0: clip1_Y /= ratioXY
+ else: clip1_X *= ratioXY
+ clip2_X = clip1_X
+ clip2_Y = clip1_Y
+
+ near = clip1_Z
+ far = clip2_Z
+ right, left = clip1_X, -clip1_X
+ top, bottom = clip1_Y, -clip1_Y
+
+ scaleX = 2.0/float(right - left)
+ x3 = -float(right + left)/float(right - left)
+ scaleY = 2.0/float(top - bottom)
+ y3 = -float(top + bottom)/float(top - bottom)
+ scaleZ = 1.0/float(far - near)
+ z3 = -float(near)/float(far - near)
+
+ matrix = Mathutils.Matrix( [scaleX, 0.0, 0.0, x3],
+ [0.0, scaleY, 0.0, y3],
+ [0.0, 0.0, scaleZ, z3],
+ [0.0, 0.0, 0.0, 1.0])
+
+ elif camera.type=='persp':
+ #viewpoint = [0.0, 0.0, 0.0] #camera's coordinate system, hehe
+ #lens = camera.lens
+ angle = camera.angle
+ #print 'deb: cam angle=', angle #------------------
+ shiftX = camera.shiftX
+ shiftY = camera.shiftY
+ fov_coef = atan(angle * d2r)
+ fov_coef *= 1.3 #incl. passpartou
+ clip1_k = clip1_Z * fov_coef
+ clip2_k = clip2_Z * fov_coef
+ clip1shiftX = - camera.shiftX * clip1_k
+ clip2shiftX = - camera.shiftX * clip2_k
+ clip1shiftY = - camera.shiftY * clip1_k
+ clip2shiftY = - camera.shiftY * clip2_k
+ clip1_X = clip1_Y = clip1_k * 0.5
+ clip2_X = clip2_Y = clip2_k * 0.5
+ if ratioXY > 1.0:
+ clip1_Y /= ratioXY
+ clip2_Y /= ratioXY
+ else:
+ clip1_X *= ratioXY
+ clip2_X *= ratioXY
+
+ near = clip1_Z
+ far = clip2_Z
+ right, left = clip1_X, -clip1_X
+ top, bottom = clip1_Y, -clip1_Y
+ #return Matrix( [scaleX, 0.0, x2, 0.0],
+ #[0.0, scaleY, y2, 0.0],
+ #[0.0, 0.0, scaleZ, wZ],
+ #[0.0, 0.0, -1.0, 0.0])
+ matrix = Mathutils.Matrix( [(2.0 * near)/float(right - left), 0.0, float(right + left)/float(right - left), 0.0],
+ [0.0, (2.0 * near)/float(top - bottom), float(top + bottom)/float(top - bottom), 0.0],
+ [0.0, 0.0, -float(far + near)/float(far - near), -(2.0 * far * near)/float(far - near)],
+ [0.0, 0.0, -1.0, 0.0])
+
+
+ clip_box = [
+ -clip1_X + clip1shiftX, clip1_X + clip1shiftX,
+ -clip1_Y + clip1shiftY, clip1_Y + clip1shiftY,
+ -clip2_X + clip2shiftX, clip2_X + clip2shiftX,
+ -clip2_Y + clip2shiftY, clip2_Y + clip2shiftY,
+ clip1_Z, clip2_Z]
+ #print 'deb: clip_box=\n', clip_box #------------------
+ #drawClipBox(clip_box)
+ return clip_box, matrix
+
+
+#-----------------------------------------------------
+def drawClipBox(clip_box):
+ """debug tool: draws Clipping-Box of a Camera View
+ """
+ min_X1, max_X1, min_Y1, max_Y1,\
+ min_X2, max_X2, min_Y2, max_Y2,\
+ min_Z, max_Z = clip_box
+ verts = []
+ verts.append([min_X1, min_Y1, min_Z])
+ verts.append([max_X1, min_Y1, min_Z])
+ verts.append([max_X1, max_Y1, min_Z])
+ verts.append([min_X1, max_Y1, min_Z])
+ verts.append([min_X2, min_Y2, max_Z])
+ verts.append([max_X2, min_Y2, max_Z])
+ verts.append([max_X2, max_Y2, max_Z])
+ verts.append([min_X2, max_Y2, max_Z])
+ faces = [[0,1,2,3],[4,5,6,7]]
+ newmesh = Mesh.New()
+ newmesh.verts.extend(verts)
+ newmesh.faces.extend(faces)
+
+ plan = Object.New('Mesh','clip_box')
+ plan.link(newmesh)
+ sce = Scene.GetCurrent()
+ sce.objects.link(plan)
+ plan.setMatrix(sce.objects.camera.matrix)
+
+
+#-------------------------------------------------
+def getCommons(ob):
+ """set up common attributes for output style:
+ color=None
+ extrusion=None
+ layer='0',
+ lineType=None
+ lineTypeScale=None
+ lineWeight=None
+ thickness=None
+ parent=None
+ """
+
+ layers = ob.layers #gives a list e.g.[1,5,19]
+ if layers: ob_layer_nr = layers[0]
+ #print 'ob_layer_nr=', ob_layer_nr #--------------
+
+ materials = ob.getMaterials()
+ if materials:
+ ob_material = materials[0]
+ ob_mat_color = ob_material.rgbCol
+ else: ob_mat_color, ob_material = None, None
+ #print 'ob_mat_color, ob_material=', ob_mat_color, ob_material #--------------
+
+ data = ob.getData()
+ data_materials = ob.getMaterials()
+ if data_materials:
+ data_material = data_materials[0]
+ data_mat_color = data_material.rgbCol
+ else: data_mat_color, data_material = None, None
+ #print 'data_mat_color, data_material=', data_mat_color, data_material #--------------
+
+ entitylayer = ENTITYLAYER_DEF
+ c = entitylayer_from_list[GUI_A['entitylayer_from'].val]
+ #["default_LAYER","obj.name","obj.layer","obj.material","obj.data.name","obj.data.material","..vertexgroup","..group","..map_table"]
+ if c=="default_LAYER":
+ entitylayer = LAYERNAME_DEF
+ elif c=="obj.layer" and ob_layer_nr:
+ entitylayer = 'LAYER'+ str(ob_layer_nr)
+ elif c=="obj.material" and ob_material:
+ entitylayer = ob_material.name
+ elif c=="obj.name":
+ entitylayer = ob.name
+ elif c=="obj.data.material" and ob_material:
+ entitylayer = data_material.name
+ elif c=="obj.data.name":
+ entitylayer = data.name
+ entitylayer = validDXFr12name(PREFIX+entitylayer)
+ if entitylayer=="": entitylayer = "BF_0"
+
+ entitycolor = ENTITYCOLOR_DEF
+ c = entitycolor_from_list[GUI_A['entitycolor_from'].val]
+ if c=="default_COLOR":
+ entitycolor = LAYERCOLOR_DEF
+ elif c=="BYLAYER":
+ entitycolor = BYLAYER
+ elif c=="BYBLOCK":
+ entitycolor = BYBLOCK
+ elif c=="obj.layer" and ob_layer_nr:
+ entitycolor = ob_layer_nr
+ elif c=="obj.color" and ob.color:
+ entitycolor = col2DXF(ob.color)
+ elif c=="obj.material" and ob_mat_color:
+ entitycolor = col2DXF(ob_mat_color)
+ elif c=="obj.data.material" and data_mat_color:
+ entitycolor = col2DXF(data_mat_color)
+ #if entitycolor!=None: layercolor = entitycolor
+
+ entityltype = ENTITYLTYPE_DEF
+ c = entityltype_from_list[GUI_A['entityltype_from'].val]
+ if c=="default_LTYPE":
+ entityltype = LAYERLTYPE_DEF
+ elif c=="BYLAYER":
+ entityltype = BYLAYER
+ elif c=="BYBLOCK":
+ entityltype = BYBLOCK
+ elif c:
+ entityltype = c
+
+ return entitylayer,entitycolor,entityltype
+
+
+#-----------------------------------------------------
+def do_export(export_list, filepath):
+ global PERSPECTIVE, CAMERAVIEW, BLOCKREGISTRY
Window.WaitCursor(1)
- t = sys.time()
-
- #init Drawing ---------------------
- d=Drawing()
- #add Tables -----------------
- #d.blocks.append(b) #table blocks
- d.styles.append(Style()) #table styles
- d.views.append(View('Normal')) #table view
- d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
-
- #add Entities --------------------
- something_ready = False
- #ViewVector = Mathutils.Vector(Window.GetViewVector())
- #print 'deb: ViewVector=', ViewVector #------------------
- mw0 = Window.GetViewMatrix()
- #mw0 = Window.GetPerspMatrix() #TODO: how get it working?
- mw = mw0.copy()
- if FLATTEN:
- m0 = Mathutils.Matrix()
- m0[2][2]=0.0
- mw *= m0 #flatten ViewMatrix
-
- for ob in sel_group:
+ t = Blender.sys.time()
+
+ # init Drawing ---------------------
+ d=DXF.Drawing()
+ # add Tables -----------------
+ # initialized automatic: d.blocks.append(b) #section BLOCKS
+ # initialized automatic: d.styles.append(DXF.Style()) #table STYLE
+
+ #table LTYPE ---------------
+ #d.linetypes.append(DXF.LineType(name='CONTINUOUS',description='--------',elements=[0.0]))
+ d.linetypes.append(DXF.LineType(name='DOT',description='. . . . . . .',elements=[0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='DASHED',description='__ __ __ __ __',elements=[0.8, 0.5, -0.3]))
+ d.linetypes.append(DXF.LineType(name='DASHDOT',description='__ . __ . __ .',elements=[1.0, 0.5, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='DIVIDE',description='____ . . ____ . . ',elements=[1.25, 0.5, -0.25, 0.0, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='BORDER',description='__ __ . __ __ . ',elements=[1.75, 0.5, -0.25, 0.5, -0.25, 0.0, -0.25]))
+ d.linetypes.append(DXF.LineType(name='HIDDEN',description='__ __ __ __ __',elements=[0.4, 0.25, -0.25]))
+ d.linetypes.append(DXF.LineType(name='CENTER',description='____ _ ____ _ __',elements=[2.0, 1.25, -0.25, 0.25, -0.25]))
+
+ #d.vports.append(DXF.VPort('*ACTIVE'))
+ d.vports.append(DXF.VPort('*ACTIVE',center=(-5.0,1.0),height=10.0))
+ #d.vports.append(DXF.VPort('*ACTIVE',leftBottom=(-100.0,-60.0),rightTop=(100.0,60.0)))
+ #d.views.append(DXF.View('Normal')) #table view
+ d.views.append(DXF.ViewByWindow('BF_TOPVIEW',leftBottom=(-100,-60),rightTop=(100,60))) #idem
+
+ # add Entities --------------------
+ BLOCKREGISTRY = {} # registry and map for BLOCKs
+ PERSPECTIVE = 0
+ something_ready = 0
+ selected_len = len(export_list)
+ sce = Scene.GetCurrent()
+
+ mw = Mathutils.Matrix( [1.0, 0.0, 0.0, 0.0],
+ [0.0, 1.0, 0.0, 0.0],
+ [0.0, 0.0, 1.0, 0.0],
+ [0.0, 0.0, 0.0, 1.0])
+ if PROJECTION:
+ if CAMERA<len(CAMERAS)+1: # the biggest number is the current 3d-view
+ act_camera = Object.Get(CAMERAS[CAMERA-1])
+ #context = sce.getRenderingContext()
+ #print 'deb: context=\n', context #------------------
+ #print 'deb: context=\n', dir(context) #------------------
+ #act_camera = sce.objects.camera
+ #print 'deb: act_camera=', act_camera #------------------
+ if act_camera:
+ CAMERAVIEW = 1
+ mc0 = act_camera.matrix.copy()
+ #print 'deb: camera.Matrix=\n', mc0 #------------------
+ camera = Camera.Get(act_camera.getData(name_only=True))
+ #print 'deb: camera=', dir(camera) #------------------
+ if camera.type=='persp': PERSPECTIVE = 1
+ elif camera.type=='ortho': PERSPECTIVE = 0
+ # mcp is matrix.camera.perspective
+ clip_box, mcp = getClipBox(camera)
+ if PERSPECTIVE:
+ # get border
+ # lens = camera.lens
+ min_X1, max_X1, min_Y1, max_Y1,\
+ min_X2, max_X2, min_Y2, max_Y2,\
+ min_Z, max_Z = clip_box
+ verts = []
+ verts.append([min_X1, min_Y1, min_Z])
+ verts.append([max_X1, min_Y1, min_Z])
+ verts.append([max_X1, max_Y1, min_Z])
+ verts.append([min_X1, max_Y1, min_Z])
+ border=verts
+ mw = mc0.copy().invert()
+
+ else: # get 3D-View instead of camera-view
+ #ViewVector = Mathutils.Vector(Window.GetViewVector())
+ #print 'deb: ViewVector=\n', ViewVector #------------------
+ #TODO: what is Window.GetViewOffset() for?
+ #print 'deb: Window.GetViewOffset():', Window.GetViewOffset() #---------
+ #Window.SetViewOffset([0,0,0])
+ mw0 = Window.GetViewMatrix()
+ #print 'deb: mwOrtho =\n', mw0 #---------
+ mwp = Window.GetPerspMatrix() #TODO: how to get it working?
+ #print 'deb: mwPersp =\n', mwp #---------
+ mw = mw0.copy()
+
+ #print 'deb: ViewMatrix=\n', mw #------------------
+
+ if APPLY_MODIFIERS: tmp_me = Mesh.New('tmp')
+ else: tmp_me = None
+
+ if GUI_A['paper_space_on'].val==1: espace=1
+ else: espace=None
+
+ layernames = []
+ for ob,mx in export_list:
entities = []
- mx = ob.matrix.copy()
- mb = mx.copy()
- #print 'deb: mb =\n', mb #---------
- #print 'deb: mw0 =\n', mw0 #---------
- mx_n = mx.rotationPart() * mw0.rotationPart() #trans-matrix for normal_vectors
- if SCALE_FACTOR!=1.0: mx *= SCALE_FACTOR
- if FLATTEN: mx *= mw
-
+ block = None
+ #mx = ob.matrix.copy()
+ #print 'deb: ob =', ob #---------
+ #print 'deb: ob.type =', ob.type #---------
+ #print 'deb: mx =\n', mx #---------
+ #print 'deb: mw0 =\n', mw0 #---------
+ #mx_n is trans-matrix for normal_vectors for front-side faces
+ mx_n = mx.rotationPart() * mw.rotationPart()
+ if G_SCALE!=1.0: mx *= G_SCALE
+ mx *= mw
+
#mx_inv = mx.copy().invert()
- #print 'deb: mx =\n', mx #---------
+ #print 'deb: mx =\n', mx #---------
#print 'deb: mx_inv=\n', mx_inv #---------
- if (ob.type == 'Mesh'):
- entities = exportMesh(ob, mx, mx_n)
- elif (ob.type == 'Curve'):
- entities = exportCurve(ob, mx)
+ if ob.type in ('Mesh','Curve','Empty','Text','Camera','Lamp'):
+ elayer,ecolor,eltype = getCommons(ob)
+ #print 'deb: elayer,ecolor,eltype =', elayer,ecolor,eltype #--------------
+
+ #TODO: use ob.boundBox for drawing extends
+
+ if elayer!=None:
+ if elayer not in layernames:
+ layernames.append(elayer)
+ if ecolor!=None: tempcolor = ecolor
+ else: tempcolor = LAYERCOLOR_DEF
+ d.layers.append(DXF.Layer(color=tempcolor, name=elayer))
+
+ if (ob.type == 'Mesh') and GUI_B['bmesh'].val:
+ entities, block = exportMesh(ob, mx, mx_n, tmp_me,\
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+ elif (ob.type == 'Curve') and GUI_B['bcurve'].val:
+ entities, block = exportCurve(ob, mx, mw, \
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+ elif (ob.type == 'Empty') and GUI_B['empty'].val:
+ entities = exportEmpty(ob, mx, mw, \
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+ elif (ob.type == 'Text') and GUI_B['text'].val:
+ entities = exportText(ob, mx, mw, \
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+ elif (ob.type == 'Camera') and GUI_B['camera'].val:
+ entities, vport, view = exportCamera(ob, mx, mw, \
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+ if vport: d.vports.append(vport)
+ if view: d.views.append(view)
+ elif (ob.type == 'Lamp') and GUI_B['lamp'].val:
+ entities = exportLamp(ob, mx, mw, \
+ paperspace=espace, color=ecolor, layer=elayer, lineType=eltype)
+
+ if entities:
+ something_ready += 1
+ for e in entities:
+ d.append(e)
+
+ if block:
+ d.blocks.append(block) #add to BLOCK-section
- for e in entities:
- d.append(e)
- something_ready = True
if something_ready:
- d.saveas(filepath)
- Window.WaitCursor(0)
- #Draw.PupMenu('DXF Exporter: job finished')
- print 'exported to %s' % filepath
- print 'finished in %.2f seconds' % (sys.time()-t)
+ if PERSPECTIVE: # generate view border - passepartout
+ identity_matrix = Mathutils.Matrix().identity()
+ points = projected_co(border, identity_matrix)
+ closed = 1
+ points = toGlobalOrigin(points)
+ c = curve_as_list[GUI_A['curve_as'].val]
+ if c=="LINEs": # export Curve as multiple LINEs
+ for i in range(len(points)-1):
+ linepoints = [points[i], points[i+1]]
+ dxfLINE = DXF.Line(linepoints,paperspace=espace,color=LAYERCOLOR_DEF)
+ entities.append(dxfLINE)
+ else:
+ dxfPLINE = DXF.PolyLine(points,points[0],closed,\
+ paperspace=espace, color=LAYERCOLOR_DEF)
+ d.append(dxfPLINE)
+
+
+ if not GUI_A['outputDWG_on'].val:
+ print 'writing to %s' % filepath
+ try:
+ d.saveas(filepath)
+ Window.WaitCursor(0)
+ #print '%s objects exported to %s' %(something_ready,filepath)
+ print '%s/%s objects exported in %.2f seconds. -----DONE-----' %(something_ready,selected_len,(Blender.sys.time()-t))
+ Draw.PupMenu('DXF Exporter: job finished!| %s/%s objects exported in %.2f sek.' %(something_ready,selected_len, (Blender.sys.time()-t)))
+ except IOError:
+ Window.WaitCursor(0)
+ Draw.PupMenu('DXF Exporter: Write Error: Permission denied:| %s' %filepath)
+
+ else:
+ if not extCONV_OK:
+ Draw.PupMenu(extCONV_TEXT)
+ Window.WaitCursor(False)
+ else:
+ print 'temp. exporting to %s' % filepath
+ d.saveas(filepath)
+ #Draw.PupMenu('DXF Exporter: job finished')
+ #print 'exported to %s' % filepath
+ #print 'finished in %.2f seconds' % (Blender.sys.time()-t)
+ filedwg = filepath[:-3]+'dwg'
+ print 'exporting to %s' % filedwg
+ os.system('%s %s -acad13 -dwg' %(extCONV_PATH,filepath))
+ #os.chdir(cwd)
+ os.remove(filepath)
+ Window.WaitCursor(0)
+ print ' finished in %.2f seconds. -----DONE-----' % (Blender.sys.time()-t)
+ Draw.PupMenu('DWG Exporter: job finished!| %s/%s objects exported in %.2f sek.' %(something_ready,selected_len, (Blender.sys.time()-t)))
else:
Window.WaitCursor(0)
- print "Abort: selected objects dont mach choosen export option, nothing exported!"
- Draw.PupMenu('DXF Exporter: nothing exported!|selected objects dont mach choosen export option!')
+ print "Abort: selected objects dont match choosen export option, nothing exported!"
+ Draw.PupMenu('DXF Exporter: nothing exported!|selected objects dont match choosen export option!')
-#----globals------------------------------------------
-ONLYSELECTED = True
-POLYLINES = True
-ONLYFACES = False
-POLYFACES = 1
-FLATTEN = 0
-HIDDEN_MODE = False #filter out hidden lines
-SCALE_FACTOR = 1.0 #optional, can be done later in CAD too
+#------------------------------------------------------
+"""
+v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\
+28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,\
+123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,\
+151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,\
+171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,\
+191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,\
+211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,\
+231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
+invalid = ''.join([chr(i) for i in v])
+del v, i
+"""
+#TODO: validDXFr14 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.'
+validDXFr12 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
+
+#------------------------------------------------------
+def cleanName(name,valid):
+ validname = ''
+ for ch in name:
+ if ch not in valid: ch = '_'
+ validname += ch
+ return validname
+#------------------------------------------------------
+def validDXFr12name(str_name):
+ dxfname = str(str_name)
+ dxfname = dxfname[:NAMELENGTH_MAX].upper()
+ dxfname = cleanName(dxfname,validDXFr12)
+ return dxfname
-#-----------------------------------------------------
-def dxf_export_ui(filepath):
- global ONLYSELECTED,\
- POLYLINES,\
- ONLYFACES,\
- POLYFACES,\
- FLATTEN,\
- HIDDEN_MODE,\
- SCALE_FACTOR
-
- print '\n\nDXF-Export %s -----------------------' %__version__
- #filepath = 'blend_test.dxf'
- # Dont overwrite
- if not BPyMessages.Warning_SaveOver(filepath):
- print 'Aborted by user: nothing exported'
- return
- #test():return
-
-
- PREF_ONLYSELECTED= Draw.Create(ONLYSELECTED)
- PREF_POLYLINES= Draw.Create(POLYLINES)
- PREF_ONLYFACES= Draw.Create(ONLYFACES)
- PREF_POLYFACES= Draw.Create(POLYFACES)
- PREF_FLATTEN= Draw.Create(FLATTEN)
- PREF_HIDDEN_MODE= Draw.Create(HIDDEN_MODE)
- PREF_SCALE_FACTOR= Draw.Create(SCALE_FACTOR)
- PREF_HELP= Draw.Create(0)
- block = [\
- ("only selected", PREF_ONLYSELECTED, "export only selected geometry"),\
- ("global Scale:", PREF_SCALE_FACTOR, 0.001, 1000, "set global Scale factor for exporting geometry"),\
- ("only faces", PREF_ONLYFACES, "from mesh-objects export only faces, otherwise only edges"),\
- ("write POLYFACE", PREF_POLYFACES, "export mesh to POLYFACE, otherwise to 3DFACEs"),\
- ("write POLYLINEs", PREF_POLYLINES, "export curve to POLYLINE, otherwise to LINEs"),\
- ("3D-View to Flat", PREF_FLATTEN, "flatten geometry according current 3d-View"),\
- ("Hidden Mode", PREF_HIDDEN_MODE, "filter out hidden lines"),\
- #(''),\
- ("online Help", PREF_HELP, "calls DXF-Exporter Manual Page on Wiki.Blender.org"),\
- ]
-
- if not Draw.PupBlock("DXF-Exporter %s" %__version__[:10], block): return
-
- if PREF_HELP.val!=0:
+#print cleanName('dumka',validDXFr12)
+#print validDXFr12name('dum 15%ka')
+
+#------------------------------------------------------
+def col2RGB(color):
+ return [int(floor(255*color[0])),
+ int(floor(255*color[1])),
+ int(floor(255*color[2]))]
+
+global dxfColors
+dxfColors=None
+
+#------------------------------------------------------
+def col2DXF(rgbcolor):
+ global dxfColors
+ if dxfColors is None:
+ from dxfColorMap import color_map
+ dxfColors = [(tuple(color),idx) for idx, color in color_map.iteritems()]
+ dxfColors.sort()
+ entry = (tuple(rgbcolor), -1)
+ dxfColors.append(entry)
+ dxfColors.sort()
+ i = dxfColors.index(entry)
+ dxfColors.pop(i)
+ return dxfColors[i-1][1]
+
+
+
+# NEW UI -----#################################################-----------------
+# ------------#################################################-----------------
+
+class Settings: #-----------------------------------------------------------------
+ """A container for all the export settings and objects.
+
+ This is like a collection of globally accessable persistant properties and functions.
+ """
+ # Optimization constants
+ MIN = 0
+ MID = 1
+ PRO = 2
+ MAX = 3
+
+ def __init__(self, keywords, drawTypes):
+ """initialize all the important settings used by the export functions.
+ """
+ self.obj_number = 1 #global object_number for progress_bar
+
+ self.var = dict(keywords) #a dictionary of (key_variable:Value) control parameter
+ self.drawTypes = dict(drawTypes) #a dictionary of (entity_type:True/False) = import on/off for this entity_type
+
+ self.var['colorFilter_on'] = False #deb:remi------------
+ self.acceptedColors = [0,2,3,4,5,6,7,8,9,
+ 10 ]
+
+ self.var['materialFilter_on'] = False #deb:remi------------
+ self.acceptedLayers = ['3',
+ '0'
+ ]
+
+ self.var['groupFilter_on'] = False #deb:remi------------
+ self.acceptedLayers = ['3',
+ '0'
+ ]
+
+ #self.var['objectFilter_on'] = 0 #deb:remi------------
+ self.acceptedBlocks = ['WALL_1871',
+ 'BOX02'
+ ]
+ self.unwantedBlocks = ['BOX05',
+ 'BOX04'
+ ]
+
+
+ def update(self, keywords, drawTypes):
+ """update all the important settings used by the draw functions.
+ mostly used after loading parameters from INI-file
+ """
+
+ for k, v in keywords.iteritems():
+ self.var[k] = v
+ #print 'deb:settings_update var %s= %s' %(k, self.var[k]) #--------------
+ for t, v in drawTypes.iteritems():
+ self.drawTypes[t] = v
+ #print 'deb:settings_update drawType %s= %s' %(t, self.drawTypes[t]) #--------------
+
+ self.drawTypes['arc'] = self.drawTypes['surface']
+ self.drawTypes['circle'] = self.drawTypes['surface']
+ self.drawTypes['ellipse'] = self.drawTypes['surface']
+ self.drawTypes['trace'] = self.drawTypes['solid']
+ self.drawTypes['insert'] = self.drawTypes['group']
+ #self.drawTypes['vport'] = self.drawTypes['view']
+
+ #print 'deb:self.drawTypes', self.drawTypes #---------------
+
+
+ def validate(self, drawing):
+ """Given the drawing, build dictionaries of Layers, Colors and Blocks.
+ """
+ global oblist
+ #adjust the distance parameter to globalScale
+ if self.var['g_scale'] != 1.0:
+ self.var['dist_min'] = self.var['dist_min'] / self.var['g_scale']
+ self.g_origin = Mathutils.Vector(self.var['g_originX'], self.var['g_originY'], self.var['g_originZ'])
+
+
+ def write(self, text, newline=True):
+ """Wraps the built-in print command in a optimization check.
+ """
+ if self.var['optimization'] <= self.MID:
+ if newline:
+ print text
+ else:
+ print text,
+
+
+ def redraw(self):
+ """Update Blender if optimization level is low enough.
+ """
+ if self.var['optimization'] <= self.MIN:
+ Blender.Redraw()
+
+
+ def progress(self, done, text):
+ """Wrapper for Blender.Window.DrawProgressBar.
+ """
+ if self.var['optimization'] <= self.PRO:
+ progressbar = done * self.obj_number
+ Window.DrawProgressBar(progressbar, text)
+ #print 'deb:drawer done, progressbar: ', done, progressbar #-----------------------
+
+
+
+# GUI STUFF -----#################################################-----------------
+from Blender.BGL import *
+
+EVENT_NONE = 1
+EVENT_START = 2
+EVENT_REDRAW = 3
+EVENT_LOAD_INI = 4
+EVENT_SAVE_INI = 5
+EVENT_RESET = 6
+EVENT_CHOOSE_INI = 7
+EVENT_CHOOSE_DXF = 8
+EVENT_HELP = 9
+EVENT_CAMERA = 10
+EVENT_LIGHT =11
+EVENT_DXF_DIR = 12
+EVENT_setCAMERA = 13
+# = 14
+EVENT_ORIGIN = 15
+EVENT_SCALE = 16
+EVENT_PRESET2D = 20
+EVENT_PRESET3D = 21
+EVENT_PRESETPLINE = 22
+EVENT_PRESETS = 23
+EVENT_EXIT = 100
+
+GUI_A = {} # GUI-buttons dictionary for parameter
+GUI_B = {} # GUI-buttons dictionary for drawingTypes
+
+# settings default, initialize ------------------------
+
+#-----------------------------------------------
+def prepareMenu(title,list):
+ menu = title
+ for i, item in enumerate(list):
+ menu += '|'+ item + ' %x' + str(i)
+ return menu
+
+#-----------------------------------------------
+mesh_as_list = ["3DFACEs","POLYFACE","POLYLINE","LINEs","POINTs"]
+mesh_as_menu = prepareMenu("export to: %t", mesh_as_list)
+
+curve_as_list = ["LINEs","POLYLINE","..LWPOLYLINE r14","..SPLINE r14","POINTs"]
+curve_as_menu = prepareMenu("export to: %t", curve_as_list)
+
+surface_as_list = ["..3DFACEs","..POLYFACE","..POINTs","..NURBS"]
+surface_as_menu = prepareMenu("export to: %t", surface_as_list)
+
+meta_as_list = ["..3DFACEs","..POLYFACE","..3DSOLID"]
+meta_as_menu = prepareMenu("export to: %t", meta_as_list)
+
+text_as_list = ["TEXT","..MTEXT","..ATTRIBUT"]
+text_as_menu = prepareMenu("export to: %t", text_as_list)
+
+empty_as_list = ["POINT","..INSERT","..XREF"]
+empty_as_menu = prepareMenu("export to: %t|", empty_as_list)
+
+group_as_list = ["..GROUP","..BLOCK","..ungroup"]
+group_as_menu = prepareMenu("export to: %t", group_as_list)
+
+parent_as_list = ["..BLOCK","..ungroup"]
+parent_as_menu = prepareMenu("export to: %t", parent_as_list)
+
+proxy_as_list = ["..BLOCK","..XREF","..ungroup","..POINT"]
+proxy_as_menu = prepareMenu("export to: %t", proxy_as_list)
+
+camera_as_list = ["..BLOCK","..A_CAMERA","VPORT","VIEW","POINT"]
+camera_as_menu = prepareMenu("export to: %t", camera_as_list)
+
+lamp_as_list = ["..BLOCK","..A_LAMP","POINT"]
+lamp_as_menu = prepareMenu("export to: %t", lamp_as_list)
+
+material_to_list= ["COLOR","LAYER","..LINESTYLE","..BLOCK","..XDATA","..INI-File"]
+material_to_menu = prepareMenu("export to: %t", material_to_list)
+
+ltype_map_list= ["object_rgb","material_rgb","..map_table"]
+ltype_map_menu = prepareMenu("export to: %t", ltype_map_list)
+
+
+
+layername_from_list = [LAYERNAME_DEF,"drawing_name","scene_name"]
+layername_from_menu = prepareMenu("defaultLAYER: %t", layername_from_list)
+
+layerltype_def_list = ["CONTINUOUS","DOT","DASHED","DASHDOT","BORDER","HIDDEN"]
+layerltype_def_menu = prepareMenu("LINETYPE set to: %t",layerltype_def_list)
+
+entitylayer_from_list = ["default_LAYER","obj.name","obj.layer","obj.material","obj.data.name","obj.data.material","..vertexgroup","..group","..map_table"]
+entitylayer_from_menu = prepareMenu("entityLAYER from: %t", entitylayer_from_list)
+#print 'deb: entitylayer_from_menu=', entitylayer_from_menu #--------------
+
+entitycolor_from_list = ["default_COLOR","BYLAYER","BYBLOCK","obj.layer","obj.color","obj.material","obj.data.material","..map_table"]
+entitycolor_from_menu = prepareMenu("entityCOLOR set to: %t",entitycolor_from_list)
+
+entityltype_from_list = ["default_LTYPE","BYLAYER","BYBLOCK","CONTINUOUS","DOT","DASHED","DASHDOT","BORDER","HIDDEN"]
+entityltype_from_menu = prepareMenu("entityCOLOR set to: %t",entityltype_from_list)
+
+#dxf-LINE,ARC,CIRCLE,ELLIPSE
+
+g_scale_list = ''.join((
+ 'scale factor: %t',
+ '|user def. %x12',
+ '|yard to m %x8',
+ '|feet to m %x7',
+ '|inch to m %x6',
+ '| x 100000 %x5',
+ '| x 10000 %x4',
+ '| x 1000 %x3',
+ '| x 100 %x2',
+ '| x 10 %x1',
+ '| x 1 %x0',
+ '| x 0.1 %x-1',
+ '| x 0.01 %x-2',
+ '| x 0.001 %x-3',
+ '| x 0.0001 %x-4',
+ '| x 0.00001 %x-5'))
+
+#print 'deb: g_scale_list', g_scale_list #-----------
+
+dxfFileName = Draw.Create("")
+iniFileName = Draw.Create(INIFILE_DEFAULT_NAME + INIFILE_EXTENSION)
+user_preset = 0
+config_UI = Draw.Create(0) #switch_on/off extended config_UI
+g_scale_as = Draw.Create(int(log10(G_SCALE)))
+
+
+keywords_org = {
+ 'optimization': 2,
+ 'dummy_on' : 0,
+
+ 'xref_on' : 1,
+ 'block_nn': 0,
+
+ 'paper_space_on': 0,
+ 'layFrozen_on': 0,
+ 'objectFilter_on': 0,
+ 'materialFilter_on': 0,
+ 'colorFilter_on': 0,
+ 'groupFilter_on': 0,
+
+ 'only_selected_on': ONLYSELECTED,
+ 'only_visible_on': ONLYVISIBLE,
+ 'projection_on' : PROJECTION,
+ 'hidden_lines_on': HIDDEN_LINES,
+ 'shadows_on' : SHADOWS,
+ 'light_on' : 1,
+ 'outputDWG_on' : OUTPUT_DWG,
+ 'to_polyline_on': POLYLINES,
+ 'to_polyface_on': POLYFACES,
+ 'instances_on': INSTANCES,
+ 'apply_modifiers_on': APPLY_MODIFIERS,
+ 'include_duplis_on': INCLUDE_DUPLIS,
+ 'camera_selected': CAMERA,
+
+ 'g_originX' : G_ORIGIN[0],
+ 'g_originY' : G_ORIGIN[1],
+ 'g_originZ' : G_ORIGIN[2],
+ 'g_origin_on': 0,
+ 'g_scale' : float(G_SCALE),
+# 'g_scale_as': int(log10(G_SCALE)), # 0,
+ 'g_scale_on': 0,
+ 'Z_force_on': 0,
+ 'Z_elev': float(ELEVATION),
+
+
+ 'prefix_def' : PREFIX,
+ 'layername_def' : LAYERNAME_DEF,
+ 'layercolor_def': LAYERCOLOR_DEF,
+ 'layerltype_def': LAYERLTYPE_DEF,
+ 'entitylayer_from': 5,
+ 'entitycolor_from': 1,
+ 'entityltype_from' : 1,
+
+ 'material_on': 1,
+ 'material_to': 2,
+ 'fill_on' : 1,
+
+ 'mesh_as' : 1,
+ 'curve_as' : 1,
+ 'surface_as' : 1,
+ 'meta_as' : 1,
+ 'text_as' : 0,
+ 'empty_as' : 0,
+ 'group_as' : 0,
+ 'parent_as' : 0,
+ 'proxy_as' : 0,
+ 'camera_as': 3,
+ 'lamp_as' : 2,
+ }
+
+drawTypes_org = {
+ 'bmesh' : 1,
+ 'bcurve': 1,
+ 'surface': 0,
+ 'bmeta' : 0,
+ 'text' : 1,
+ 'empty' : 1,
+ 'group' : 1,
+ 'parent': 1,
+ 'proxy' : 0,
+ 'camera': 0,
+ 'lamp' : 0,
+
+# 'view' : 0,
+ }
+
+# creating of GUI-buttons
+# GUI_A - GUI-buttons dictionary for parameter
+# GUI_B - GUI-buttons dictionary for drawingTypes
+for k, v in keywords_org.iteritems():
+ GUI_A[k] = Draw.Create(v)
+for k, v in drawTypes_org.iteritems():
+ GUI_B[k] = Draw.Create(v)
+#print 'deb:init GUI_A: ', GUI_A #---------------
+#print 'deb:init GUI_B: ', GUI_B #---------------
+
+model_space_on = Draw.Create(1)
+
+# initialize settings-object controls how dxf entities are drawn
+settings = Settings(keywords_org, drawTypes_org)
+
+
+def update_RegistryKey(key, item): #
+ """updates key in Blender.Registry
+ """
+ cache = True # data is also saved to a file
+ rdict = Registry.GetKey('DXF_Exporter', cache)
+ if not rdict: rdict = {}
+ if item:
+ rdict[key] = item
+ Registry.SetKey('DXF_Exporter', rdict, cache)
+ #print 'deb:update_RegistryKey rdict', rdict #---------------
+
+
+def check_RegistryKey(key):
+ """ check if the key is already there (saved on a previous execution of this script)
+ """
+ cache = True # data is also saved to a file
+ rdict = Registry.GetKey('DXF_Exporter', cache)
+ #print 'deb:check_RegistryKey rdict:', rdict #----------------
+ if rdict: # if found, get the values saved there
+ try:
+ item = rdict[key]
+ return item
+ except:
+ #update_RegistryKey() # if data isn't valid rewrite it
+ pass
+
+def saveConfig(): #--todo-----------------------------------------------
+ """Save settings/config/materials from GUI to INI-file.
+
+ Write all config data to INI-file.
+ """
+ global iniFileName
+
+ iniFile = iniFileName.val
+ #print 'deb:saveConfig inifFile: ', inifFile #----------------------
+ if iniFile.lower().endswith(INIFILE_EXTENSION):
+
+ #--todo-- sort key.list for output
+ #key_list = GUI_A.keys().val
+ #key_list.sort()
+ #for key in key_list:
+ # l_name, l_data = key, GUI_A[key].val
+ # list_A
+
+ output_str = '[%s,%s]' %(GUI_A, GUI_B)
+ if output_str =='None':
+ Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no config-data present to save!')
+ else:
+ if Blender.sys.exists(iniFile):
+ f = file(iniFile, 'r')
+ header_str = f.readline()
+ f.close()
+ if header_str.startswith(INIFILE_HEADER[0:13]):
+ if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1:
+ save_ok = True
+ else: save_ok = False
+ elif Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile +
+ '|Alert: this file has no valid ImportDXF-header| ! it may belong to another aplication !') == 1:
+ save_ok = True
+ else: save_ok = False
+ else: save_ok = True
+
+ if save_ok:
+ # replace: ',' -> ',\n'
+ # replace: '{' -> '\n{\n'
+ # replace: '}' -> '\n}\n'
+ output_str = ',\n'.join(output_str.split(','))
+ output_str = '\n}'.join(output_str.split('}'))
+ output_str = '{\n'.join(output_str.split('{'))
+ try:
+ f = file(iniFile, 'w')
+ f.write(INIFILE_HEADER + '\n# this is a comment line\n')
+ f.write(output_str)
+ f.close()
+ #Draw.PupMenu('DXF-Exporter: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile)
+ except:
+ Draw.PupMenu('DXF-Exporter: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile)
+
+ else:
+ Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid name/extension for INI-file selected!')
+ print "DXF-Exporter: Alert!: no valid INI-file selected."
+ if not iniFile:
+ if dxfFileName.val.lower().endswith('.dxf'):
+ iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION
+
+
+def loadConfig(): #remi--todo-----------------------------------------------
+ """Load settings/config/materials from INI-file.
+
+ TODO: Read material-assignements from config-file.
+ """
+ #20070724 buggy Window.FileSelector(loadConfigFile, 'Load config data from INI-file', inifilename)
+ global iniFileName, GUI_A, GUI_B
+
+ iniFile = iniFileName.val
+ update_RegistryKey('iniFileName', iniFile)
+ #print 'deb:loadConfig iniFile: ', iniFile #----------------------
+ if iniFile.lower().endswith(INIFILE_EXTENSION) and Blender.sys.exists(iniFile):
+ f = file(iniFile, 'r')
+ header_str = f.readline()
+ if header_str.startswith(INIFILE_HEADER):
+ data_str = f.read()
+ f.close()
+ #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-----------------
+ data = eval(data_str)
+ for k, v in data[0].iteritems():
+ try: GUI_A[k].val = v
+ except: GUI_A[k] = Draw.Create(v)
+ for k, v in data[1].iteritems():
+ try: GUI_B[k].val = v
+ except: GUI_B[k] = Draw.Create(v)
+ else:
+ f.close()
+ Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile)
+ else:
+ Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid INI-file selected!')
+ print "DXF-Exporter: Alert!: no valid INI-file selected."
+ if not iniFileName:
+ if dxfFileName.val.lower().endswith('.dxf'):
+ iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION
+
+
+
+def updateConfig(keywords, drawTypes): #-----------------------------------------------
+ """updates GUI_settings with given dictionaries
+
+ """
+ global GUI_A, GUI_B
+ #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #---------
+ for k, v in keywords.iteritems():
+ GUI_A[k].val = v
+ for k, v in drawTypes.iteritems():
+ GUI_B[k].val = v
+
+def resetDefaultConfig(): #-----------------------------------------------
+ """Resets settings/config/materials to defaults.
+
+ """
+ #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #---------
+ updateConfig(keywords_org, drawTypes_org)
+
+
+def presetConfig_polyline(activate): #-----------------------------------------------
+ """Sets settings/config for polygon representation: POLYLINE(FACE) or LINEs/3DFACEs.
+
+ """
+ global GUI_A
+ if activate:
+ GUI_A['to_polyline_on'].val = 1
+ GUI_A['mesh_as'].val = 1
+ GUI_A['curve_as'].val = 1
+ else:
+ GUI_A['to_polyline_on'].val = 0
+ GUI_A['mesh_as'].val = 0
+ GUI_A['curve_as'].val = 0
+
+def resetDefaultConfig_2D(): #-----------------------------------------------
+ """Sets settings/config/materials to defaults 2D.
+
+ """
+ keywords2d = {
+ 'projection_on' : 1,
+ 'fill_on' : 1,
+ 'text_as' : 0,
+ 'group_as' : 0,
+ }
+
+ drawTypes2d = {
+ 'bmesh' : 1,
+ 'bcurve': 1,
+ 'surface':0,
+ 'bmeta' : 0,
+ 'text' : 1,
+ 'empty' : 1,
+ 'group' : 1,
+ 'parent' : 1,
+ #'proxy' : 0,
+ #'camera': 0,
+ #'lamp' : 0,
+
+ }
+ presetConfig_polyline(1)
+ updateConfig(keywords2d, drawTypes2d)
+
+def resetDefaultConfig_3D(): #-----------------------------------------------
+ """Sets settings/config/materials to defaults 3D.
+
+ """
+ keywords3d = {
+ 'projection_on' : 0,
+ 'fill_on' : 0,
+ 'text_as' : 0,
+ 'group_as' : 0,
+ }
+
+ drawTypes3d = {
+ 'bmesh' : 1,
+ 'bcurve': 1,
+ 'surface':0,
+ 'bmeta' : 0,
+ 'text' : 0,
+ 'empty' : 1,
+ 'group' : 1,
+ 'parent' : 1,
+ #'proxy' : 0,
+ #'camera': 1,
+ #'lamp' : 1,
+ }
+ presetConfig_polyline(1)
+ updateConfig(keywords3d, drawTypes3d)
+
+
+def inputGlobalScale():
+ """Pop-up UI-Block for global scale factor
+ """
+ global GUI_A
+ #print 'deb:inputGlobalScale ##########' #------------
+ x_scale = Draw.Create(GUI_A['g_scale'].val)
+ block = []
+ #block.append("global translation vector:")
+ block.append(("", x_scale, 0.0, 10000000.0))
+
+ retval = Draw.PupBlock("set global scale factor:", block)
+
+ GUI_A['g_scale'].val = float(x_scale.val)
+
+
+def inputOriginVector():
+ """Pop-up UI-Block for global translation vector
+ """
+ global GUI_A
+ #print 'deb:inputOriginVector ##########' #------------
+ x_origin = Draw.Create(GUI_A['g_originX'].val)
+ y_origin = Draw.Create(GUI_A['g_originY'].val)
+ z_origin = Draw.Create(GUI_A['g_originZ'].val)
+ block = []
+ #block.append("global translation vector:")
+ block.append(("X: ", x_origin, -100000000.0, 100000000.0))
+ block.append(("Y: ", y_origin, -100000000.0, 100000000.0))
+ block.append(("Z: ", z_origin, -100000000.0, 100000000.0))
+
+ retval = Draw.PupBlock("set global translation vector:", block)
+
+ GUI_A['g_originX'].val = x_origin.val
+ GUI_A['g_originY'].val = y_origin.val
+ GUI_A['g_originZ'].val = z_origin.val
+
+
+def update_globals(): #-----------------------------------------------------------------
+ """ update globals if GUI_A changed
+ """
+ global ONLYSELECTED,ONLYVISIBLE, DEBUG,\
+ PROJECTION, HIDDEN_LINES, CAMERA, \
+ G_SCALE, G_ORIGIN,\
+ PREFIX, LAYERNAME_DEF, LAYERCOLOR_DEF, LAYERLTYPE_DEF,\
+ APPLY_MODIFIERS, INCLUDE_DUPLIS,\
+ OUTPUT_DWG
+ #global POLYLINES
+
+ ONLYSELECTED = GUI_A['only_selected_on'].val
+ ONLYVISIBLE = GUI_A['only_visible_on'].val
+ """
+ POLYLINES = GUI_A['to_polyline_on'].val
+ if GUI_A['curve_as'].val==1: POLYLINES=1
+ else: POLYLINES=0
+ """
+
+ if GUI_A['optimization'].val==0: DEBUG = 1
+ else: DEBUG = 0
+ PROJECTION = GUI_A['projection_on'].val
+ HIDDEN_LINES = GUI_A['hidden_lines_on'].val
+ CAMERA = GUI_A['camera_selected'].val
+ G_SCALE = GUI_A['g_scale'].val
+ if GUI_A['g_origin_on'].val:
+ G_ORIGIN[0] = GUI_A['g_originX'].val
+ G_ORIGIN[1] = GUI_A['g_originY'].val
+ G_ORIGIN[2] = GUI_A['g_originZ'].val
+ if GUI_A['g_scale_on'].val:
+ G_ORIGIN[0] *= G_SCALE
+ G_ORIGIN[1] *= G_SCALE
+ G_ORIGIN[2] *= G_SCALE
+
+ PREFIX = GUI_A['prefix_def'].val
+ LAYERNAME_DEF = GUI_A['layername_def'].val
+ LAYERCOLOR_DEF = GUI_A['layercolor_def'].val
+ LAYERLTYPE_DEF = layerltype_def_list[GUI_A['layerltype_def'].val]
+
+ APPLY_MODIFIERS = GUI_A['apply_modifiers_on'].val
+ INCLUDE_DUPLIS = GUI_A['include_duplis_on'].val
+ OUTPUT_DWG = GUI_A['outputDWG_on'].val
+ #print 'deb: GUI HIDDEN_LINES=', HIDDEN_LINES #---------
+ #print 'deb: GUI GUI_A: ', GUI_A['hidden_lines_on'].val #---------------
+ #print 'deb: GUI GUI_B: ', GUI_B #---------------
+
+
+def draw_UI(): #-----------------------------------------------------------------
+ """ Draw startUI and setup Settings.
+ """
+ global GUI_A, GUI_B #__version__
+ global user_preset, iniFileName, dxfFileName, config_UI, g_scale_as
+ global model_space_on
+ global SCROLL
+
+ global mPAN_X, menu_orgX, mPAN_Xmax
+ global mPAN_Y, menu_orgY, mPAN_Ymax
+ global menu__Area, headerArea, screenArea, scrollArea
+
+ size=Buffer(GL_FLOAT, 4)
+ glGetFloatv(GL_SCISSOR_BOX, size) #window X,Y,sizeX,sizeY
+ size= size.list
+ #print '-------------size:', size #--------------------------
+ for s in [0,1,2,3]: size[s]=int(size[s])
+ window_Area = [0,0,size[2],size[3]-2]
+ scrollXArea = [0,0,window_Area[2],15]
+ scrollYArea = [0,0,15,window_Area[3]]
+
+ menu_orgX = -mPAN_X
+ #menu_orgX = 0 #scrollW
+ #if menu_pan: menu_orgX -= mPAN_X
+ if menu_orgX < -mPAN_Xmax: menu_orgX, mPAN_X = -mPAN_Xmax,mPAN_Xmax
+ if menu_orgX > 0: menu_orgX, mPAN_X = 0,0
+
+ menu_orgY = -mPAN_Y
+ #if menu_pan: menu_orgY -= mPAN_Y
+ if menu_orgY < -mPAN_Ymax: menu_orgY, mPAN_Y = -mPAN_Ymax,mPAN_Ymax
+ if menu_orgY > 0: menu_orgY, mPAN_Y = 0,0
+
+
+ menu_margin = 10
+ butt_margin = 10
+ common_column = int((window_Area[2] - (3 * butt_margin) - (2 * menu_margin)-30) / 4.0)
+ common_column = 70
+ # This is for easy layout changes
+ but_0c = common_column #button 1.column width
+ but_1c = common_column #button 1.column width
+ but_2c = common_column #button 2.column
+ but_3c = common_column #button 3.column
+ menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width
+
+ simple_menu_h = 260
+ extend_menu_h = 345
+ menu_h = simple_menu_h # y is menu upper.y
+ if config_UI.val:
+ menu_h += extend_menu_h
+
+ mPAN_Xmax = menu_w-window_Area[2]+50
+ mPAN_Ymax = menu_h-window_Area[3]+30
+
+ y = menu_h
+ x = 0 #menu left.x
+ x +=menu_orgX+20
+ y +=menu_orgY+20
+
+
+ but0c = x + menu_margin #buttons 0.column position.x
+ but1c = but0c + but_0c + butt_margin
+ but2c = but1c + but_1c + butt_margin
+ but3c = but2c + but_2c + butt_margin
+ but4c = but3c + but_3c
+
+ # Here starts menu -----------------------------------------------------
+ #glClear(GL_COLOR_BUFFER_BIT)
+ #glRasterPos2d(8, 125)
+
+
+ ui_box(x, y, x+menu_w+menu_margin*2, y-menu_h)
+ y -= 20
+ Draw.Label("DXF(r12)-Exporter v" + __version__, but0c, y, menu_w, 20)
+
+ if config_UI.val:
+ b0, b0_ = but0c, but_0c-20 + butt_margin
+ b1, b1_ = but1c-20, but_1c+20
+ y_top = y
+
+ y -= 10
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['bmesh'] = Draw.Toggle('Mesh', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bmesh'].val, "Export Mesh-Objects on/off")
+ if GUI_B['bmesh'].val:
+ GUI_A['mesh_as'] = Draw.Menu(mesh_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['mesh_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['bcurve'] = Draw.Toggle('Curve', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bcurve'].val, "Export Curve-Objects on/off")
+ if GUI_B['bcurve'].val:
+ GUI_A['curve_as'] = Draw.Menu(curve_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['curve_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['surface'] = Draw.Toggle('..Surface', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['surface'].val, "(*todo) Export Surface-Objects on/off")
+ if GUI_B['surface'].val:
+ GUI_A['surface_as'] = Draw.Menu(surface_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['surface_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['bmeta'] = Draw.Toggle('..Meta', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bmeta'].val, "(*todo) Export Meta-Objects on/off")
+ if GUI_B['bmeta'].val:
+ GUI_A['meta_as'] = Draw.Menu(meta_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['meta_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['text'] = Draw.Toggle('Text', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['text'].val, "Export Text-Objects on/off")
+ if GUI_B['text'].val:
+ GUI_A['text_as'] = Draw.Menu(text_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['text_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['empty'] = Draw.Toggle('Empty', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['empty'].val, "Export Empty-Objects on/off")
+ if GUI_B['empty'].val:
+ GUI_A['empty_as'] = Draw.Menu(empty_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['empty_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y_down = y
+ # -----------------------------------------------
+
+ y = y_top
+ b0, b0_ = but2c, but_2c-20 + butt_margin
+ b1, b1_ = but3c-20, but_3c+20
+
+ y -= 10
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['group'] = Draw.Toggle('..Group', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['group'].val, "(*todo) Export Group-Relationships on/off")
+ if GUI_B['group'].val:
+ GUI_A['group_as'] = Draw.Menu(group_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['group_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['parent'] = Draw.Toggle('..Parent', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['parent'].val, "(*todo) Export Parent-Relationships on/off")
+ if GUI_B['parent'].val:
+ GUI_A['parent_as'] = Draw.Menu(parent_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['parent_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['proxy'] = Draw.Toggle('..Proxy', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['proxy'].val, "(*todo) Export Proxy-Objects on/off")
+ if GUI_B['proxy'].val:
+ GUI_A['proxy_as'] = Draw.Menu(proxy_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['proxy_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['camera'] = Draw.Toggle('Camera', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['camera'].val, "(*wip) Export Camera-Objects on/off")
+ if GUI_B['camera'].val:
+ GUI_A['camera_as'] = Draw.Menu(camera_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['camera_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_B['lamp'] = Draw.Toggle('Lamp', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['lamp'].val, "(*wip) Export Lamp-Objects on/off")
+ if GUI_B['lamp'].val:
+ GUI_A['lamp_as'] = Draw.Menu(lamp_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['lamp_as'].val, "Select target DXF-object")
+ Draw.EndAlign()
+
+
+ if y < y_down: y_down = y
+ # -----end supported objects--------------------------------------
+
+ y_top = y_down
+ y = y_top
+ y -= 10
+ y -= 20
+ but_ = menu_w / 6
+ b0 = but0c + (menu_w - but_*6)/2
+ Draw.BeginAlign()
+ #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['dummy_on'].val, "placeholder only on/off")
+ GUI_A['paper_space_on'] = Draw.Toggle('Paper', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['paper_space_on'].val, "Export to Paper-Space, otherwise to Model-Space on/off")
+ GUI_A['layFrozen_on'] = Draw.Toggle ('..frozen', EVENT_NONE, b0+but_*1, y, but_, 20, GUI_A['layFrozen_on'].val, "(*todo) Support LAYER.frozen status on/off")
+ GUI_A['materialFilter_on'] = Draw.Toggle('..material', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['materialFilter_on'].val, "(*todo) Material filtering on/off")
+ GUI_A['colorFilter_on'] = Draw.Toggle('..color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*todo) Color filtering on/off")
+ GUI_A['groupFilter_on'] = Draw.Toggle('..group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*todo) Group filtering on/off")
+ GUI_A['objectFilter_on'] = Draw.Toggle('..object', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['objectFilter_on'].val, "(*todo) Object filtering on/off")
+ Draw.EndAlign()
+
+ # -----end filters--------------------------------------
+
+ b0, b0_ = but0c, but_0c + butt_margin
+ b1, b1_ = but1c, but_1c
+
+ y -= 10
+ y -= 20
+ Draw.BeginAlign()
+ GUI_A['g_origin_on'] = Draw.Toggle('Location', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_origin_on'].val, "Global relocate all objects on/off")
+ if GUI_A['g_origin_on'].val:
+ tmp = Draw.PushButton('=', EVENT_ORIGIN, b1, y, 20, 20, "Edit relocation-vector (x,y,z in DXF units)")
+ origin_str = '(%.4f, %.4f, %.4f)' % (
+ GUI_A['g_originX'].val,
+ GUI_A['g_originY'].val,
+ GUI_A['g_originZ'].val
+ )
+ tmp = Draw.Label(origin_str, b1+20, y, 300, 20)
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_A['g_scale_on'] = Draw.Toggle('Scale', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_scale_on'].val, "Global scale all objects on/off")
+ if GUI_A['g_scale_on'].val:
+ g_scale_as = Draw.Menu(g_scale_list, EVENT_SCALE, b1, y, 45, 20, g_scale_as.val, "Factor for scaling the DXFdata")
+ if g_scale_as.val == 12:
+ pass
+ else:
+ if g_scale_as.val == 6: #scale inches to meters
+ GUI_A['g_scale'].val = 0.0254000
+ elif g_scale_as.val == 7: #scale feets to meters
+ GUI_A['g_scale'].val = 0.3048000
+ elif g_scale_as.val == 8: #scale yards to meters
+ GUI_A['g_scale'].val = 0.9144000
+ else:
+ GUI_A['g_scale'].val = 10.0 ** int(g_scale_as.val)
+ scale_float = GUI_A['g_scale'].val
+ if scale_float < 0.000001 or scale_float > 1000000:
+ scale_str = ' = %s' % GUI_A['g_scale'].val
+ else:
+ scale_str = ' = %.6f' % GUI_A['g_scale'].val
+ Draw.Label(scale_str, b1+45, y, 200, 20)
+ Draw.EndAlign()
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_A['Z_force_on'] = Draw.Toggle('Elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, "Overwrite Z-coordinates (flatten geometry) on/off")
+ if GUI_A['Z_force_on'].val:
+ GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['Z_elev'].val, -1000, 1000, "Set value for default Z-coordinate (in DXF units)")
+ Draw.EndAlign()
+
+ """
+ y -= 30
+ Draw.BeginAlign()
+ GUI_A['material_on'] = Draw.Toggle('.material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "Support for material assignment on/off")
+ if GUI_A['material_on'].val:
+ GUI_A['material_to'] = Draw.Menu(material_to_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_to'].val, "Material assigned to?")
+ Draw.EndAlign()
+ """
+
+ #b0, b0_ = but0c, but_0c + butt_margin
+ b0, b0_ = but0c, 50
+ b1, b1_ = b0+b0_, but_0c-b0_+ but_1c + butt_margin
+ b2, b2_ = but2c, but_2c
+ b3, b3_ = but3c, but_3c
+
+ y -= 30
+ Draw.Label('Output:', b0, y, b0_, 20)
+ Draw.Label('LAYER:', b1, y, b1_, 20)
+ Draw.Label('COLOR:', b2, y, b2_, 20)
+ Draw.Label('LINETYPE:', b3, y, b3_, 20)
+ #Draw.Label('LINESIZE:', b4, y, b4_, 20)
+
+ y -= 20
+ Draw.BeginAlign()
+ GUI_A['prefix_def'] = Draw.String('', EVENT_NONE, b0, y, b0_, 20, GUI_A['prefix_def'].val, 10, "Type Prefix for LAYERs")
+ GUI_A['layername_def'] = Draw.String('', EVENT_NONE, b1, y, b1_, 20, GUI_A['layername_def'].val, 10, "Type default LAYER name")
+ GUI_A['layercolor_def'] = Draw.Number('', EVENT_NONE, b2, y, b2_, 20, GUI_A['layercolor_def'].val, 1, 255, "Set default COLOR. (0=BYBLOCK,256=BYLAYER)")
+ GUI_A['layerltype_def'] = Draw.Menu(layerltype_def_menu, EVENT_NONE, b3, y, b3_, 20, GUI_A['layerltype_def'].val, "Set default LINETYPE")
+ Draw.EndAlign()
+
+ y -= 25
+ Draw.Label('Style:', b0, y, b0_, 20)
+ Draw.BeginAlign()
+ GUI_A['entitylayer_from'] = Draw.Menu(entitylayer_from_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['entitylayer_from'].val, "entity LAYER assigned to?")
+ GUI_A['entitycolor_from'] = Draw.Menu(entitycolor_from_menu, EVENT_NONE, b2, y, b2_, 20, GUI_A['entitycolor_from'].val, "entity COLOR assigned to?")
+ GUI_A['entityltype_from'] = Draw.Menu(entityltype_from_menu, EVENT_NONE, b3, y, b3_, 20, GUI_A['entityltype_from'].val, "Set entity LINETYPE")
+ Draw.EndAlign()
+
+ y -= 10
+
+ y_down = y
+ # -----end material,translate,scale------------------------------------------
+
+
+ #--------------------------------------
+ y_top = y_down
+ y = y_top
+
+ y -= 30
+ Draw.BeginAlign()
+ Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but0c, y, but_0c, 20, 'Select INI-file with file selector')
+ iniFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_1c-60, 20, iniFileName.val, FILENAME_MAX, "Write here the name of the INI-file")
+ but = but4c-60
+ Draw.PushButton('#', EVENT_PRESETS, but, y, 20, 20, "Toggle Preset-INI-files")
+ Draw.PushButton('L', EVENT_LOAD_INI, but+20, y, 20, 20, 'Loads configuration from selected ini-file: %s' % iniFileName.val)
+ Draw.PushButton('S', EVENT_SAVE_INI, but+40, y, 20, 20, 'Saves configuration to selected ini-file: %s' % iniFileName.val)
+ Draw.EndAlign()
+
+ bm = butt_margin/2
+
+ y -= 10
+ y -= 20
+ Draw.BeginAlign()
+ Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file with file selector')
+ dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_0c-menu_margin, 20, dxfFileName.val, FILENAME_MAX, "Type path/name of output DXF-file")
+ Draw.EndAlign()
+
+ y -= 30
+ config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but0c, y, but_0c+bm, 20, config_UI.val, 'Advanced configuration on/off' )
+ Draw.BeginAlign()
+ but, but_ = but1c, but_1c+bm
+ but_ /= 3
+ Draw.PushButton('X', EVENT_RESET, but, y, 15, 20, "Reset configuration to defaults")
+ Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'Set to standard configuration for 2D export')
+ Draw.PushButton('3D', EVENT_PRESET3D, but+(but_*2), y, but_, 20, 'Set to standard configuration for 3D import')
+ Draw.EndAlign()
+
+
+ y -= 30
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['only_selected_on'] = Draw.Toggle('Export Selection', EVENT_NONE, b0, y, b0_, 20, GUI_A['only_selected_on'].val, "Export only selected geometry on/off")
+ b0, b0_ = but2c, but_2c + butt_margin + but_3c
+ Draw.BeginAlign()
+ GUI_A['projection_on'] = Draw.Toggle('2d Projection', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['projection_on'].val, "Export a 2d Projection according 3d-View or Camera-View on/off")
+ if GUI_A['projection_on'].val:
+ GUI_A['camera_selected'] = Draw.Menu(MenuCAMERA, EVENT_CAMERA, b0, y-20, b0_-20, 20, GUI_A['camera_selected'].val, 'Choose the camera to be rendered')
+ Draw.PushButton('>', EVENT_setCAMERA, b0+b0_-20, y-20, 20, 20, 'switch to selected Camera - make it active')
+ GUI_A['hidden_lines_on'] = Draw.Toggle('Remove backFaces', EVENT_NONE, b0, y-40, b0_, 20, GUI_A['hidden_lines_on'].val, "Filter out backFaces on/off")
+ #GUI_A['shadows_on'] = Draw.Toggle('..Shadows', EVENT_REDRAW, b0, y-60, but_2c, 20, GUI_A['shadows_on'].val, "(*todo) Shadow tracing on/off")
+ #GUI_A['light_on'] = Draw.Menu(MenuLIGHT, EVENT_LIGHT, but3c, y-60, but_3c, 20, GUI_A['light_on'].val, '(*todo) Choose the light source(sun) to be rendered')
+ Draw.EndAlign()
+
+ y -= 20
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['only_visible_on'] = Draw.Toggle('Visible only', EVENT_PRESETPLINE, b0, y, b0_, 20, GUI_A['only_visible_on'].val, "Export only from visible layers on/off")
+ #b0, b0_ = but2c, but_2c + butt_margin + but_3c
+
+ y -= 20
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['to_polyline_on'] = Draw.Toggle('POLYLINE-Mode', EVENT_PRESETPLINE, b0, y, b0_, 20, GUI_A['to_polyline_on'].val, "Export to POLYLINE/POLYFACEs, otherwise to LINEs/3DFACEs on/off")
+ #b0, b0_ = but2c, but_2c + butt_margin + but_3c
+
+ y -= 20
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['instances_on'] = Draw.Toggle('Instances as BLOCKs', EVENT_NONE, b0, y, b0_, 20, GUI_A['instances_on'].val, "Export instances (multi-users) of Mesh/Curve as BLOCK/INSERTs on/off")
+ #b0, b0_ = but2c, but_2c + butt_margin + but_3c
+
+ y -= 20
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['apply_modifiers_on'] = Draw.Toggle('Apply Modifiers', EVENT_NONE, b0, y, b0_, 20, GUI_A['apply_modifiers_on'].val, "Apply modifier stack to mesh objects before export on/off")
+ #b0, b0_ = but2c, but_2c + butt_margin + but_3c
+
+ y -= 20
+ b0, b0_ = but0c, but_0c + butt_margin +but_1c
+ GUI_A['include_duplis_on'] = Draw.Toggle('Include Duplis', EVENT_NONE, b0, y, b0_, 20, GUI_A['include_duplis_on'].val, "Export Duplicates (dupliverts, dupliframes, dupligroups) on/off")
+ #b0, b0_ = but2c, but_2c + butt_margin + but_3c
+
+
+
+ y -= 30
+ Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c+bm, 20, '' )
+ Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c+bm, 20, 'goes to online-Manual on wiki.blender.org')
+ GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but2c, y, 40, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/Draw-in, 1=Verbose, 2=ProgressBar, 3=SilentMode")
+ GUI_A['outputDWG_on'] = Draw.Toggle('DWG*', EVENT_NONE, but2c, y+20, 40, 20, GUI_A['outputDWG_on'].val, "converts DXF to DWG (needs external converter) on/off")
+
+ Draw.BeginAlign()
+ Draw.PushButton('START EXPORT', EVENT_START, but2c+40, y, but_2c-40+but_3c+butt_margin, 40, 'Start the export process. For Cancel go to console and hit Ctrl-C')
+ Draw.EndAlign()
+
+ y -= 20
+ #Draw.BeginAlign()
+ #Draw.Label(' ', but0c-menu_margin, y, menu_margin, 20)
+ #Draw.Label(LAB, but0c, y, menu_w, 20)
+ Draw.Label(LAB, 30, y, menu_w, 20)
+ #Draw.Label(' ', but0c+menu_w, y, menu_margin, 20)
+ #Draw.EndAlign()
+
+ ui_scrollbarX(menu_orgX, menu_w+50, scrollXArea, c_fg, c_bg)
+ ui_scrollbarY(menu_orgY, menu_h+30, scrollYArea, c_fg, c_bg)
+
+
+
+
+#-- END GUI Stuf-----------------------------------------------------
+
+c0=[0.2,0.2,0.2,0.0]
+c1=[0.7,0.7,0.9,0.0]
+c2=[0.71,0.71,0.71,0.0]
+c3=[0.4,0.4,0.4,0.0]
+c4=[0.95,0.95,0.9,0.0]
+c5=[0.64,0.64,0.64,0]
+c6=[0.75,0.75,0.75,0]
+c7=[0.6,0.6,0.6,0]
+c8=[1.0,0.0,0.0,0]
+c9=[0.7,0.0,0.0,0]
+c10=[0.64,0.81,0.81,0]
+c11=[0.57,0.71,0.71,0]
+c_nor= c5[:3]
+c_act= c10[:3]
+c_sel= c11[:3]
+c_tx = c0[:3]
+c_fg = c2[:3]
+c_bg = c5[:3]
+
+def ui_rect(coords,color):
+ [X1,Y1,X2,Y2],[r,g,b] = coords,color
+ glColor3f(r,g,b)
+ glRecti(X1,Y1,X2,Y2)
+def ui_rectA(coords,color):
+ [X1,Y1,X2,Y2],[r,g,b,a] = coords,color
+ glColor4f(r,g,b,a)
+ glRecti(X1,Y1,X2,Y2) #integer coords
+ #glRectf(X1,Y1,X2,Y2) #floating coords
+def ui_line(coords,color):
+ [X1,Y1,X2,Y2],[r,g,b] = coords,color
+ glColor3f(r,g,b)
+ glBegin(GL_LINES)
+ glVertex2i(X1,Y1)
+ glVertex2i(X2,Y2)
+ glEnd()
+def ui_panel(posX,posY,L,H,color):
+ [r,g,b] = color
+ ui_rect([posX+4,posY-4,posX+L+4,posY-H-4],[.55,.55,.55]) #1st shadow
+ ui_rect([posX+3,posY-3,posX+L+3,posY-H-3],[.45,.45,.45])
+ ui_rect([posX+3,posY-3,posX+L+2,posY-H-2],[.30,.30,.30]) #2nd shadow
+ ui_rect([posX,posY-H,posX+L,posY],[r,g,b]) #Main
+ ui_rect([posX+3,posY-19,posX+L-3,posY-2],[.75*r,.75*g,.75*b]) #Titlebar
+ ui_line([posX+3,posY-19,posX+3,posY-2],[.25,.25,.25])
+ ui_line([posX+4,posY-19,posX+4,posY-2],[(r+.75)/4,(g+.75)/4,(b+.75)/4])
+ ui_line([posX+4,posY-2,posX+L-3,posY-2],[(r+.75)/4,(g+.75)/4,(b+.75)/4])
+def ui_box(x,y,xright,bottom):
+ color = [0.75, 0.75, 0.75]
+ coords = x+1,y+1,xright-1,bottom-1
+ ui_rect(coords,color)
+
+def ui_scrollbarX(Focus,PanelH,Area, color_fg, color_bg):
+ # Area = ScrollBarArea
+ # point1=down/left, point2=top/right
+ P1X,P1Y,P2X,P2Y = Area
+ AreaH = P2X-P1X
+ if PanelH > AreaH:
+ Slider = int(AreaH * (AreaH / float(PanelH)))
+ if Slider<3: Slider = 3 #minimal slider heigh
+ posX = -int(AreaH * (Focus / float(PanelH)))
+ ui_rect([P1X,P1Y,P2X,P2Y], color_bg)
+ ui_rect([P1X+posX,P1Y+3,P1X+posX+Slider,P2Y-3], color_fg)
+
+def ui_scrollbarY(Focus,PanelH,Area, color_fg, color_bg):
+ # Area = ScrollBarArea
+ # point1=down/left, point2=top/right
+ P1X,P1Y,P2X,P2Y = Area
+ AreaH = P2Y-P1Y
+ if PanelH > AreaH:
+ Slider = int(AreaH * (AreaH / float(PanelH)))
+ if Slider<3: Slider = 3 #minimal slider heigh
+ posY = -int(AreaH * (Focus / float(PanelH)))
+ ui_rect([P1X,P1Y,P2X-1,P2Y], color_bg)
+ #ui_rect([P1X+3,P2Y-posY,P2X-4,P2Y-posY-Slider], color_fg)
+ ui_rect([P1X+3,P1Y+posY,P2X-4,P1Y+posY+Slider], color_fg)
+
+
+#------------------------------------------------------------
+def dxf_callback(input_filename):
+ global dxfFileName
+ dxfFileName.val=input_filename
+# dirname == Blender.sys.dirname(Blender.Get('filename'))
+# update_RegistryKey('DirName', dirname)
+# update_RegistryKey('dxfFileName', input_filename)
+
+def ini_callback(input_filename):
+ global iniFileName
+ iniFileName.val=input_filename
+
+#------------------------------------------------------------
+def getSpaceRect():
+ __UI_RECT__ = Buffer(GL_FLOAT, 4)
+ glGetFloatv(GL_SCISSOR_BOX, __UI_RECT__)
+ __UI_RECT__ = __UI_RECT__.list
+ return (int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2]), int(__UI_RECT__[3]))
+
+def getRelMousePos(mco, winRect):
+ # mco = Blender.Window.GetMouseCoords()
+ if pointInRect(mco, winRect):
+ return (mco[0] - winRect[0], mco[1] - winRect[1])
+ return None
+
+
+def pointInRect(pt, rect):
+ if rect[0] < pt[0] < rect[0]+rect[2] and\
+ rect[1] < pt[1] < rect[1]+rect[3]:
+ return True
+ else:
+ return False
+
+
+
+#--- variables UI menu ---------------------------
+mco = [0,0] # mouse coordinaten
+mbX, mbY = 0,0 # mouse buffer coordinaten
+scrollW = 20 # width of scrollbar
+rowH = 20 # height of menu raw
+menu__H = 2 * rowH +5 # height of menu bar
+headerH = 1 * rowH # height of column header bar
+scroll_left = True # position of scrollbar
+menu_bottom = False # position of menu
+edit_mode = False # indicator/activator
+iconlib_mode = False # indicator/activator
+icon_maps = [] #[['blenderbuttons.png',12,25,20,21],
+#['referenceicons.png',12,25,20,21]]
+help_text = False # indicator/activator
+menu_pan = False # indicator/activator
+compact_DESIGN = True # toggle UI
+showLINK = True # toggle Links
+filterList=[-1,-1,-1,-1,-1]
+dubbleclik_delay = 0.25
+
+PAN_X,PAN_Y = 0,0 # pan coordinates in characters
+mPAN_X,mPAN_Y = 0,0 # manu pan coordinates in characters
+menu_orgX = 0
+menu_orgY = 0
+mPAN_Xmax = 800
+mPAN_Ymax = 800
+
+
+#------------------------------------------------------------
+def event(evt, val):
+ global mbX, mbY, UP, UP0, scroll_pan, FOCUS_fix
+ global menu_bottom, scroll_left, mco
+ global PAN_X, PAN_Y, PAN_X0, PAN_Y0
+ global mPAN_X, mPAN_Y, mPAN_X0, mPAN_Y0, menu_pan
+
+ #if Blender.event:
+ # print 'Blender.event:%s, evt:%s' %(Blender.event, evt) #------------
+
+ if evt in (Draw.QKEY, Draw.ESCKEY) and not val:
+ print 'DXF-Exporter *** end ***' #---------------------
+ Draw.Exit()
+
+ elif val:
+ if evt==Draw.MIDDLEMOUSE:
+ mco2 = Window.GetMouseCoords()
+ relativeMouseCo = getRelMousePos(mco2, getSpaceRect())
+ if relativeMouseCo != None:
+ #rect = [menu__X1,menu__Y1,menu__X2,menu__Y2]
+ if 1: #pointInRect(relativeMouseCo, menu__Area):
+ menu_pan = True
+ mPAN_X0 = mPAN_X
+ mPAN_Y0 = mPAN_Y
+ mco = mco2
+ elif evt == Draw.MOUSEY or evt == Draw.MOUSEX:
+ if menu_pan:
+ mco2 = Window.GetMouseCoords()
+ mbX = mco2[0]-mco[0]
+ mbY = mco2[1]-mco[1]
+ mPAN_X = mPAN_X0 - mbX
+ mPAN_Y = mPAN_Y0 - mbY
+ #print mbX, mbY #--------------------
+ Draw.Redraw()
+ elif evt == Draw.WHEELDOWNMOUSE:
+ mPAN_Y -= 80
+ Draw.Redraw()
+ elif evt == Draw.WHEELUPMOUSE:
+ mPAN_Y += 80
+ Draw.Redraw()
+ else: # = if val==False:
+ if evt==Draw.LEFTMOUSE:
+ scroll_pan = False
+ elif evt==Draw.MIDDLEMOUSE:
+ menu_pan = False
+
+def bevent(evt):
+ global config_UI, user_preset
+ global CAMERA, GUI_A
+
+ ######### Manages GUI events
+ if (evt==EVENT_EXIT):
+ Draw.Exit()
+ print 'DXF-Exporter *** end ***' #---------------------
+ elif (evt==EVENT_CHOOSE_INI):
+ Window.FileSelector(ini_callback, "INI-file Selection", '*.ini')
+ elif (evt==EVENT_REDRAW):
+ Draw.Redraw()
+ elif (evt==EVENT_RESET):
+ resetDefaultConfig()
+ Draw.Redraw()
+ elif (evt==EVENT_PRESET2D):
+ resetDefaultConfig_2D()
+ Draw.Redraw()
+ elif (evt==EVENT_PRESET3D):
+ resetDefaultConfig_3D()
+ Draw.Redraw()
+ elif evt in (EVENT_CAMERA,EVENT_LIGHT):
+ CAMERA = GUI_A['camera_selected'].val
+ if CAMERA==len(CAMERAS)+1:
+ doAllCameras = True
+ else:
+ pass #print 'deb: CAMERAS=',CAMERAS #----------------
+ Draw.Redraw()
+ elif (evt==EVENT_setCAMERA):
+ if CAMERA<len(CAMERAS)+1:
+ gotoCAMERA()
+
+ elif (evt==EVENT_SCALE):
+ if g_scale_as.val == 12:
+ inputGlobalScale()
+ if GUI_A['g_scale'].val < 0.00000001:
+ GUI_A['g_scale'].val = 0.00000001
+ Draw.Redraw()
+ elif (evt==EVENT_ORIGIN):
+ inputOriginVector()
+ Draw.Redraw()
+ elif (evt==EVENT_PRESETPLINE):
+ presetConfig_polyline(GUI_A['to_polyline_on'].val)
+ Draw.Redraw()
+ elif (evt==EVENT_PRESETS):
+ user_preset += 1
+ index = str(user_preset)
+ if user_preset > 5: user_preset = 0; index = ''
+ iniFileName.val = INIFILE_DEFAULT_NAME + index + INIFILE_EXTENSION
+ Draw.Redraw()
+ elif (evt==EVENT_HELP):
try:
import webbrowser
webbrowser.open('http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
except:
- Draw.PupMenu('DXF Exporter: %t|no connection to manual-page on Blender-Wiki! try:|\
+ Draw.PupMenu('DXF-Exporter: HELP Alert!%t|no connection to manual-page on Blender-Wiki! try:|\
http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf')
- return
+ Draw.Redraw()
+ elif (evt==EVENT_LOAD_INI):
+ loadConfig()
+ Draw.Redraw()
+ elif (evt==EVENT_SAVE_INI):
+ saveConfig()
+ Draw.Redraw()
+ elif (evt==EVENT_DXF_DIR):
+ dxfFile = dxfFileName.val
+ dxfPathName = ''
+ if '/' in dxfFile:
+ dxfPathName = '/'.join(dxfFile.split('/')[:-1]) + '/'
+ elif '\\' in dxfFile:
+ dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\'
+ dxfFileName.val = dxfPathName + '*.dxf'
+# dirname == Blender.sys.dirname(Blender.Get('filename'))
+# update_RegistryKey('DirName', dirname)
+# update_RegistryKey('dxfFileName', dxfFileName.val)
+ GUI_A['only_selected_on'].val = 1
+ Draw.Redraw()
+ elif (evt==EVENT_CHOOSE_DXF):
+ filename = '' # '*.dxf'
+ if dxfFileName.val: filename = dxfFileName.val
+ Window.FileSelector(dxf_callback, "DXF-file Selection", filename)
+ elif (evt==EVENT_START):
+ dxfFile = dxfFileName.val
+ #print 'deb: dxfFile file: ', dxfFile #----------------------
+ if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode
+ update_RegistryKey('dxfFileName', dxfFileName.val)
+ update_globals()
+ if dxfFile.lower().endswith('*.dxf'):
+ if Draw.PupMenu('DXF-Exporter: OK?|will write multiple DXF-files, one for each Scene, in:|%s' % dxfFile) == 1:
+ global UI_MODE
+ UI_MODE = False
+ #TODO: multi_export(dxfFile[:-5]) # cut last 5 characters '*.dxf'
+ Draw.Redraw()
+ UI_MODE = True
+ else:
+ Draw.Redraw()
+ elif dxfFile.lower()[-4:] in ('.dxf','.dwg'): # and Blender.sys.exists(dxfFile):
+ print 'preparing for export ---' #Standard Mode: activated
+ filepath = dxfFile
+ sce = Scene.GetCurrent()
+ if ONLYSELECTED: sel_group = sce.objects.selected
+ else: sel_group = sce.objects
+
+ if ONLYVISIBLE:
+ sel_group_temp = []
+ layerlist = sce.getLayers()
+ for ob in sel_group:
+ for lay in ob.layers:
+ if lay in layerlist:
+ sel_group_temp.append(ob)
+ break
+ sel_group = sel_group_temp
+
+ export_list = getObjectsAndDuplis(sel_group,MATRICES=True)
+
+ if export_list: do_export(export_list, filepath)
+ else:
+ print "Abort: selection was empty, no object to export!"
+ Draw.PupMenu('DXF Exporter: nothing exported!|empty selection!')
+ else:
+ Draw.PupMenu('DXF-Exporter: Alert!%t|no valid DXF-file selected!')
+ print "DXF-Exporter: error, no valid DXF-file selected! try again"
+ Draw.Redraw()
- ONLYSELECTED = PREF_ONLYSELECTED.val
- POLYLINES = PREF_POLYLINES.val
- ONLYFACES = PREF_ONLYFACES.val
- POLYFACES = PREF_POLYFACES.val
- FLATTEN = PREF_FLATTEN.val
- HIDDEN_MODE = PREF_HIDDEN_MODE.val
- SCALE_FACTOR = PREF_SCALE_FACTOR.val
- sce = Scene.GetCurrent()
- if ONLYSELECTED: sel_group = sce.objects.selected
- else: sel_group = sce.objects
- if sel_group: do_export(sel_group, filepath)
- else:
- print "Abort: selection was empty, no object to export!"
- Draw.PupMenu('DXF Exporter: nothing exported!|empty selection!')
- # Timing the script is a good way to be aware on any speed hits when scripting
+def multi_export(DIR): #TODO:
+ """Imports all DXF-files from directory DIR.
+
+ """
+ global SCENE
+ batchTIME = Blender.sys.time()
+ #if #DIR == "": DIR = os.path.curdir
+ if DIR == "": DIR = Blender.sys.dirname(Blender.Get('filename'))
+ print 'Multifiles Import from %s' %DIR
+ files = \
+ [Blender.sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')]
+ if not files:
+ print '...None DXF-files found. Abort!'
+ return
+
+ i = 0
+ for dxfFile in files:
+ i += 1
+ print '\nDXF-file', i, 'of', len(files) #,'\nImporting', dxfFile
+ if ONLYSELECTED:
+ _dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
+ _dxf_file = _dxf_file[:-4] # cut last char:'.dxf'
+ _dxf_file = _dxf_file[:NAMELENGTH_MAX] #? [-NAMELENGTH_MAX:])
+ SCENE = Blender.Scene.New(_dxf_file)
+ SCENE.makeCurrent()
+ #or so? Blender.Scene.makeCurrent(_dxf_file)
+ #sce = bpy.data.scenes.new(_dxf_file)
+ #bpy.data.scenes.active = sce
+ else:
+ SCENE = Blender.Scene.GetCurrent()
+ SCENE.objects.selected = [] # deselect all
+ main(dxfFile)
+ #Blender.Redraw()
+
+ print 'TOTAL TIME: %.6f' % (Blender.sys.time() - batchTIME)
+ print '\a\r', # beep when done
#-----------------------------------------------------
if __name__=='__main__':
- #main()
- if not copy:
- Draw.PupMenu('Error%t|This script requires a full python install')
- Window.FileSelector(dxf_export_ui, 'EXPORT DXF', sys.makename(ext='.dxf'))
-
-
+
+ if DXF:
+ print '\n\n\n'
+ print 'DXF-Exporter v%s *** start ***' %(__version__) #---------------------
+ print 'with Library %s' %(DXF.__version__) #---------------------
+ if not DXF.copy:
+ print "DXF-Exporter: dxfLibrary.py script requires a full Python install"
+ Draw.PupMenu('Error%t|The dxfLibrary.py script requires a full Python install')
+ else:
+ #Window.FileSelector(dxf_export_ui, 'EXPORT DXF', Blender.sys.makename(ext='.dxf'))
+ # recall last used DXF-file and INI-file names
+ dxffilename = check_RegistryKey('dxfFileName')
+ #print 'deb:start dxffilename:', dxffilename #----------------
+ if dxffilename: dxfFileName.val = dxffilename
+ else:
+ dirname = Blender.sys.dirname(Blender.Get('filename'))
+ #print 'deb:start dirname:', dirname #----------------
+ dxfFileName.val = Blender.sys.join(dirname, '')
+ inifilename = check_RegistryKey('iniFileName')
+ if inifilename: iniFileName.val = inifilename
+
+ updateMenuCAMERA()
+ updateCAMERA()
+
+ Draw.Register(draw_UI, event, bevent)
+
\ No newline at end of file
diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py
index 3f02a71f951..50357cbfa75 100644
--- a/release/scripts/export_fbx.py
+++ b/release/scripts/export_fbx.py
@@ -1,13 +1,13 @@
#!BPY
"""
Name: 'Autodesk FBX (.fbx)...'
-Blender: 244
+Blender: 249
Group: 'Export'
Tooltip: 'Selection to an ASCII Autodesk FBX '
"""
__author__ = "Campbell Barton"
__url__ = ['www.blender.org', 'blenderartists.org']
-__version__ = "1.1"
+__version__ = "1.2"
__bpydoc__ = """\
This script is an exporter to the FBX file format.
@@ -66,8 +66,6 @@ import BPyMesh
import BPySys
import BPyMessages
-import sys
-
## This was used to make V, but faster not to do all that
##valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_,.()[]{}'
##v = range(255)
@@ -95,8 +93,8 @@ def copy_images(dest_dir, textures):
dest_dir += Blender.sys.sep
image_paths = set()
- for img in textures:
- image_paths.add(Blender.sys.expandpath(img.filename))
+ for tex in textures:
+ image_paths.add(Blender.sys.expandpath(tex.filename))
# Now copy images
copyCount = 0
@@ -159,14 +157,29 @@ def increment_string(t):
# todo - Disallow the name 'Scene' and 'blend_root' - it will bugger things up.
def sane_name(data, dct):
#if not data: return None
- name = data.name
+
+ if type(data)==tuple: # materials are paired up with images
+ data, other = data
+ use_other = True
+ else:
+ other = None
+ use_other = False
+
+ if data: name = data.name
+ else: name = None
+ orig_name = name
+
+ if other:
+ orig_name_other = other.name
+ name = '%s #%s' % (name, orig_name_other)
+ else:
+ orig_name_other = None
# dont cache, only ever call once for each data type now,
# so as to avoid namespace collision between types - like with objects <-> bones
#try: return dct[name]
#except: pass
- orig_name = name
if not name:
name = 'unnamed' # blank string, ASKING FOR TROUBLE!
else:
@@ -175,7 +188,11 @@ def sane_name(data, dct):
while name in dct.itervalues(): name = increment_string(name)
- dct[orig_name] = name
+ if use_other: # even if other is None - orig_name_other will be a string or None
+ dct[orig_name, orig_name_other] = name
+ else:
+ dct[orig_name] = name
+
return name
def sane_obname(data): return sane_name(data, sane_name_mapping_ob)
@@ -184,7 +201,19 @@ def sane_texname(data): return sane_name(data, sane_name_mapping_tex)
def sane_takename(data): return sane_name(data, sane_name_mapping_take)
def sane_groupname(data): return sane_name(data, sane_name_mapping_group)
-
+def derived_paths(fname_orig, basepath, FORCE_CWD=False):
+ '''
+ fname_orig - blender path, can be relative
+ basepath - fname_rel will be relative to this
+ FORCE_CWD - dont use the basepath, just add a ./ to the filename.
+ use when we know the file will be in the basepath.
+ '''
+ fname = Blender.sys.expandpath(fname_orig)
+ fname_strip = strip_path(fname)
+ if FORCE_CWD: fname_rel = '.' + Blender.sys.sep + fname_strip
+ else: fname_rel = Blender.sys.relpath(fname, basepath)
+ if fname_rel.startswith('//'): fname_rel = '.' + Blender.sys.sep + fname_rel[2:]
+ return fname, fname_strip, fname_rel
def mat4x4str(mat):
@@ -342,6 +371,8 @@ def write(filename, batch_objects = None, \
# end batch support
+ # Use this for working out paths relative to the export location
+ basepath = Blender.sys.dirname(filename)
# ----------------------------------------------
# storage classes
@@ -499,7 +530,7 @@ def write(filename, batch_objects = None, \
if time:
curtime = time.localtime()[0:6]
else:
- curtime = [0,0,0,0,0,0]
+ curtime = (0,0,0,0,0,0)
#
file.write(\
'''FBXHeaderExtension: {
@@ -971,7 +1002,7 @@ def write(filename, batch_objects = None, \
#eDIRECTIONAL
#eSPOT
light_type = light.type
- if light_type > 3: light_type = 0
+ if light_type > 2: light_type = 1 # hemi and area lights become directional
mode = light.mode
if mode & Blender.Lamp.Modes.RayShadow or mode & Blender.Lamp.Modes.Shadows:
@@ -1141,10 +1172,9 @@ def write(filename, batch_objects = None, \
Property: "Width", "int", "",0
Property: "Height", "int", "",0''')
if tex:
- fname = tex.filename
- fname_strip = strip_path(fname)
+ fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY)
else:
- fname = fname_strip = ''
+ fname = fname_strip = fname_rel = ''
file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip)
@@ -1163,7 +1193,7 @@ def write(filename, batch_objects = None, \
file.write('\n\t\tFilename: "%s"' % fname_strip)
if fname_strip: fname_strip = '/' + fname_strip
- file.write('\n\t\tRelativeFilename: "fbx%s"' % fname_strip) # make relative
+ file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # make relative
file.write('\n\t}')
@@ -1202,13 +1232,14 @@ def write(filename, batch_objects = None, \
}''')
file.write('\n\t\tMedia: "Video::%s"' % texname)
+
if tex:
- fname = tex.filename
- file.write('\n\t\tFileName: "%s"' % strip_path(fname))
- file.write('\n\t\tRelativeFilename: "fbx/%s"' % strip_path(fname)) # need some make relative command
+ fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY)
else:
- file.write('\n\t\tFileName: ""')
- file.write('\n\t\tRelativeFilename: "fbx"')
+ fname = fname_strip = fname_rel = ''
+
+ file.write('\n\t\tFileName: "%s"' % fname_strip)
+ file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # need some make relative command
file.write('''
ModelUVTranslation: 0,0
@@ -1321,17 +1352,20 @@ def write(filename, batch_objects = None, \
me = my_mesh.blenData
# if there are non NULL materials on this mesh
- if [mat for mat in my_mesh.blenMaterials if mat]: do_materials = True
- else: do_materials = False
+ if my_mesh.blenMaterials: do_materials = True
+ else: do_materials = False
if my_mesh.blenTextures: do_textures = True
- else: do_textures = False
+ else: do_textures = False
+
+ do_uvs = me.faceUV
file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
file.write('\n\t\tVersion: 232') # newline is added in write_object_props
- write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())
+ poseMatrix = write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())[3]
+ pose_items.append((my_mesh.fbxName, poseMatrix))
file.write('\n\t\t}')
file.write('\n\t\tMultiLayer: 0')
@@ -1373,22 +1407,18 @@ def write(filename, batch_objects = None, \
else: file.write(',%i,%i,%i,%i' % fi )
i+=1
- ed_val = [None, None]
- LOOSE = Blender.Mesh.EdgeFlags.LOOSE
+ file.write('\n\t\tEdges: ')
+ i=-1
for ed in me.edges:
- if ed.flag & LOOSE:
- ed_val[0] = ed.v1.index
- ed_val[1] = -(ed.v2.index+1)
if i==-1:
- file.write('%i,%i' % tuple(ed_val) )
+ file.write('%i,%i' % (ed.v1.index, ed.v2.index))
i=0
else:
if i==13:
file.write('\n\t\t')
i=0
- file.write(',%i,%i' % tuple(ed_val) )
+ file.write(',%i,%i' % (ed.v1.index, ed.v2.index))
i+=1
- del LOOSE
file.write('\n\t\tGeometryVersion: 124')
@@ -1411,6 +1441,51 @@ def write(filename, batch_objects = None, \
i+=1
file.write('\n\t\t}')
+ # Write Face Smoothing
+ file.write('''
+ LayerElementSmoothing: 0 {
+ Version: 102
+ Name: ""
+ MappingInformationType: "ByPolygon"
+ ReferenceInformationType: "Direct"
+ Smoothing: ''')
+
+ i=-1
+ for f in me.faces:
+ if i==-1:
+ file.write('%i' % f.smooth); i=0
+ else:
+ if i==54:
+ file.write('\n '); i=0
+ file.write(',%i' % f.smooth)
+ i+=1
+
+ file.write('\n\t\t}')
+
+ # Write Edge Smoothing
+ file.write('''
+ LayerElementSmoothing: 1 {
+ Version: 101
+ Name: ""
+ MappingInformationType: "ByEdge"
+ ReferenceInformationType: "Direct"
+ Smoothing: ''')
+
+ SHARP = Blender.Mesh.EdgeFlags.SHARP
+ i=-1
+ for ed in me.edges:
+ if i==-1:
+ file.write('%i' % ((ed.flag&SHARP)!=0)); i=0
+ else:
+ if i==54:
+ file.write('\n '); i=0
+ file.write(',%i' % ((ed.flag&SHARP)!=0))
+ i+=1
+
+ file.write('\n\t\t}')
+ del SHARP
+
+
# Write VertexColor Layers
# note, no programs seem to use this info :/
collayers = []
@@ -1434,13 +1509,13 @@ def write(filename, batch_objects = None, \
for f in me.faces:
for col in f.col:
if i==-1:
- file.write('%i,%i,%i' % (col[0], col[1], col[2]))
+ file.write('%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0))
i=0
else:
if i==7:
file.write('\n\t\t\t\t')
i=0
- file.write(',%i,%i,%i' % (col[0], col[1], col[2]))
+ file.write(',%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0))
i+=1
ii+=1 # One more Color
@@ -1463,7 +1538,7 @@ def write(filename, batch_objects = None, \
# Write UV and texture layers.
uvlayers = []
- if me.faceUV:
+ if do_uvs:
uvlayers = me.getUVLayerNames()
uvlayer_orig = me.activeUVLayer
for uvindex, uvlayer in enumerate(uvlayers):
@@ -1526,13 +1601,13 @@ def write(filename, batch_objects = None, \
if len(my_mesh.blenTextures) == 1:
file.write('0')
else:
- #texture_mapping_local = {None:0}
texture_mapping_local = {None:-1}
i = 0 # 1 for dummy
for tex in my_mesh.blenTextures:
- texture_mapping_local[tex] = i
- i+=1
+ if tex: # None is set above
+ texture_mapping_local[tex] = i
+ i+=1
i=-1
for f in me.faces:
@@ -1582,32 +1657,32 @@ def write(filename, batch_objects = None, \
file.write('0')
else:
# Build a material mapping for this
- #material_mapping_local = [0] * 16 # local-index : global index.
- material_mapping_local = [-1] * 16 # local-index : global index.
- i= 0 # 1
- for j, mat in enumerate(my_mesh.blenMaterials):
- if mat:
- material_mapping_local[j] = i
- i+=1
- # else leave as -1
+ material_mapping_local = {} # local-mat & tex : global index.
+
+ for j, mat_tex_pair in enumerate(my_mesh.blenMaterials):
+ material_mapping_local[mat_tex_pair] = j
len_material_mapping_local = len(material_mapping_local)
+ mats = my_mesh.blenMaterialList
+
i=-1
for f in me.faces:
- f_mat = f.mat
- if f_mat >= len_material_mapping_local:
- f_mat = 0
+ try: mat = mats[f.mat]
+ except:mat = None
+
+ if do_uvs: tex = f.image # WARNING - MULTI UV LAYER IMAGES NOT SUPPORTED :/
+ else: tex = None
if i==-1:
i=0
- file.write( '%s' % (material_mapping_local[f_mat]))
+ file.write( '%s' % (material_mapping_local[mat, tex])) # None for mat or tex is ok
else:
if i==55:
file.write('\n\t\t\t\t')
i=0
- file.write(',%s' % (material_mapping_local[f_mat]))
+ file.write(',%s' % (material_mapping_local[mat, tex]))
i+=1
file.write('\n\t\t}')
@@ -1642,7 +1717,7 @@ def write(filename, batch_objects = None, \
TypedIndex: 0
}''')
- if me.faceUV:
+ if do_uvs: # same as me.faceUV
file.write('''
LayerElement: {
Type: "LayerElementUV"
@@ -1724,8 +1799,8 @@ def write(filename, batch_objects = None, \
ob_all_typegroups = [ob_meshes, ob_lights, ob_cameras, ob_arms, ob_null]
groups = [] # blender groups, only add ones that have objects in the selections
- materials = {}
- textures = {}
+ materials = {} # (mat, image) keys, should be a set()
+ textures = {} # should be a set()
tmp_ob_type = ob_type = None # incase no objects are exported, so as not to raise an error
@@ -1825,30 +1900,34 @@ def write(filename, batch_objects = None, \
if EXP_MESH_HQ_NORMALS:
BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
- for mat in mats:
- # 2.44 use mat.lib too for uniqueness
- if mat: materials[mat] = mat
-
texture_mapping_local = {}
+ material_mapping_local = {}
if me.faceUV:
uvlayer_orig = me.activeUVLayer
for uvlayer in me.getUVLayerNames():
me.activeUVLayer = uvlayer
for f in me.faces:
- img = f.image
- textures[img] = texture_mapping_local[img] = img
+ tex = f.image
+ textures[tex] = texture_mapping_local[tex] = None
+
+ try: mat = mats[f.mat]
+ except: mat = None
+
+ materials[mat, tex] = material_mapping_local[mat, tex] = None # should use sets, wait for blender 2.5
+
me.activeUVLayer = uvlayer_orig
+ else:
+ for mat in mats:
+ # 2.44 use mat.lib too for uniqueness
+ materials[mat, None] = material_mapping_local[mat, None] = None
+ else:
+ materials[None, None] = None
if EXP_ARMATURE:
armob = BPyObject.getObjectArmature(ob)
blenParentBoneName = None
- # Note - Fixed in BPyObject but for now just copy the function because testers wont have up to date modukes,
- # TODO - remove this for 2.45 release since getObjectArmature has been fixed
- if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.ARMATURE:
- armob = ob.parent
-
# parent bone - special case
if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.BONE:
armob = ob.parent
@@ -1864,8 +1943,9 @@ def write(filename, batch_objects = None, \
my_mesh = my_object_generic(ob, mtx)
my_mesh.blenData = me
my_mesh.origData = origData
- my_mesh.blenMaterials = mats
- my_mesh.blenTextures = texture_mapping_local.values()
+ my_mesh.blenMaterials = material_mapping_local.keys()
+ my_mesh.blenMaterialList = mats
+ my_mesh.blenTextures = texture_mapping_local.keys()
# if only 1 null texture then empty the list
if len(my_mesh.blenTextures) == 1 and my_mesh.blenTextures[0] == None:
@@ -1984,8 +2064,8 @@ def write(filename, batch_objects = None, \
# Finished finding groups we use
- materials = [(sane_matname(mat), mat) for mat in materials.itervalues() if mat]
- textures = [(sane_texname(img), img) for img in textures.itervalues() if img]
+ materials = [(sane_matname(mat_tex_pair), mat_tex_pair) for mat_tex_pair in materials.iterkeys()]
+ textures = [(sane_texname(tex), tex) for tex in textures.iterkeys() if tex]
materials.sort() # sort by name
textures.sort()
@@ -2114,8 +2194,8 @@ Objects: {''')
write_camera_default()
- for matname, mat in materials:
- write_material(matname, mat)
+ for matname, (mat, tex) in materials:
+ write_material(matname, mat) # We only need to have a material per image pair, but no need to write any image info into the material (dumb fbx standard)
# each texture uses a video, odd
for texname, tex in textures:
@@ -2235,7 +2315,7 @@ Relations: {''')
Model: "Model::Camera Switcher", "CameraSwitcher" {
}''')
- for matname, mat in materials:
+ for matname, (mat, tex) in materials:
file.write('\n\tMaterial: "Material::%s", "" {\n\t}' % matname)
if textures:
@@ -2287,9 +2367,14 @@ Connections: {''')
if materials:
for my_mesh in ob_meshes:
# Connect all materials to all objects, not good form but ok for now.
- for mat in my_mesh.blenMaterials:
- if mat:
- file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat.name], my_mesh.fbxName))
+ for mat, tex in my_mesh.blenMaterials:
+ if mat: mat_name = mat.name
+ else: mat_name = None
+
+ if tex: tex_name = tex.name
+ else: tex_name = None
+
+ file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat_name, tex_name], my_mesh.fbxName))
if textures:
for my_mesh in ob_meshes:
@@ -2507,8 +2592,18 @@ Takes: {''')
for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale
if TX_CHAN=='T': context_bone_anim_vecs = [mtx[0].translationPart() for mtx in context_bone_anim_mats]
- elif TX_CHAN=='R': context_bone_anim_vecs = [mtx[1].toEuler() for mtx in context_bone_anim_mats]
- else: context_bone_anim_vecs = [mtx[0].scalePart() for mtx in context_bone_anim_mats]
+ elif TX_CHAN=='S': context_bone_anim_vecs = [mtx[0].scalePart() for mtx in context_bone_anim_mats]
+ elif TX_CHAN=='R':
+ # Was....
+ # elif TX_CHAN=='R': context_bone_anim_vecs = [mtx[1].toEuler() for mtx in context_bone_anim_mats]
+ #
+ # ...but we need to use the previous euler for compatible conversion.
+ context_bone_anim_vecs = []
+ prev_eul = None
+ for mtx in context_bone_anim_mats:
+ if prev_eul: prev_eul = mtx[1].toEuler(prev_eul)
+ else: prev_eul = mtx[1].toEuler()
+ context_bone_anim_vecs.append(prev_eul)
file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation
@@ -2527,10 +2622,9 @@ Takes: {''')
if frame!=act_start:
file.write(',')
- # Curve types are
+ # Curve types are 'C,n' for constant, 'L' for linear
# C,n is for bezier? - linear is best for now so we can do simple keyframe removal
- file.write('\n\t\t\t\t\t\t\t%i,%.15f,C,n' % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] ))
- #file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] ))
+ file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] ))
frame+=1
else:
# remove unneeded keys, j is the frame, needed when some frames are removed.
@@ -2538,11 +2632,32 @@ Takes: {''')
# last frame to fisrt frame, missing 1 frame on either side.
# removeing in a backwards loop is faster
- for j in xrange( (act_end-act_start)-1, 0, -1 ):
- # Is this key reduenant?
- if abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j-1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT and\
- abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j+1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT:
+ #for j in xrange( (act_end-act_start)-1, 0, -1 ):
+ # j = (act_end-act_start)-1
+ j = len(context_bone_anim_keys)-2
+ while j > 0 and len(context_bone_anim_keys) > 2:
+ # print j, len(context_bone_anim_keys)
+ # Is this key the same as the ones next to it?
+
+ # co-linear horizontal...
+ if abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j-1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT and\
+ abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j+1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT:
+
del context_bone_anim_keys[j]
+
+ else:
+ frame_range = float(context_bone_anim_keys[j+1][1] - context_bone_anim_keys[j-1][1])
+ frame_range_fac1 = (context_bone_anim_keys[j+1][1] - context_bone_anim_keys[j][1]) / frame_range
+ frame_range_fac2 = 1.0 - frame_range_fac1
+
+ if abs(((context_bone_anim_keys[j-1][0]*frame_range_fac1 + context_bone_anim_keys[j+1][0]*frame_range_fac2)) - context_bone_anim_keys[j][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT:
+ del context_bone_anim_keys[j]
+ else:
+ j-=1
+
+ # keep the index below the list length
+ if j > len(context_bone_anim_keys)-2:
+ j = len(context_bone_anim_keys)-2
if len(context_bone_anim_keys) == 2 and context_bone_anim_keys[0][0] == context_bone_anim_keys[1][0]:
# This axis has no moton, its okay to skip KeyCount and Keys in this case
@@ -2555,8 +2670,7 @@ Takes: {''')
if frame != context_bone_anim_keys[0][1]: # not the first
file.write(',')
# frame is alredy one less then blenders frame
- file.write('\n\t\t\t\t\t\t\t%i,%.15f,C,n' % (fbx_time(frame), val ))
- #file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame), val ))
+ file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame), val ))
if i==0: file.write('\n\t\t\t\t\t\tColor: 1,0,0')
elif i==1: file.write('\n\t\t\t\t\t\tColor: 0,1,0')
@@ -2658,7 +2772,7 @@ Takes: {''')
# copy images if enabled
if EXP_IMAGE_COPY:
- copy_images( Blender.sys.dirname(filename), [ tex[1] for tex in textures if tex[1] != None ])
+ copy_images( basepath, [ tex[1] for tex in textures if tex[1] != None ])
print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time)
return True
@@ -2722,15 +2836,16 @@ def fbx_ui_exit(e,v):
GLOBALS['EVENT'] = e
def do_help(e,v):
- url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx'
- print 'Trying to open web browser with documentation at this address...'
- print '\t' + url
-
- try:
- import webbrowser
- webbrowser.open(url)
- except:
- print '...could not open a browser window.'
+ url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx'
+ print 'Trying to open web browser with documentation at this address...'
+ print '\t' + url
+
+ try:
+ import webbrowser
+ webbrowser.open(url)
+ except:
+ Blender.Draw.PupMenu("Error%t|Opening a webbrowser requires a full python installation")
+ print '...could not open a browser window.'
@@ -2834,7 +2949,7 @@ def fbx_ui():
Draw.BeginAlign()
GLOBALS['ANIM_OPTIMIZE'] = Draw.Toggle('Optimize Keyframes', EVENT_REDRAW, x+20, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE'].val, 'Remove double keyframes', do_redraw)
if GLOBALS['ANIM_OPTIMIZE'].val:
- GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Number('Precission: ', EVENT_NONE, x+180, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val, 3, 16, 'Tolerence for comparing double keyframes (higher for greater accuracy)')
+ GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Number('Precission: ', EVENT_NONE, x+180, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val, 1, 16, 'Tolerence for comparing double keyframes (higher for greater accuracy)')
Draw.EndAlign()
Draw.BeginAlign()
@@ -2912,7 +3027,7 @@ def write_ui():
# animation opts
GLOBALS['ANIM_ENABLE'] = Draw.Create(1)
GLOBALS['ANIM_OPTIMIZE'] = Draw.Create(1)
- GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Create(6) # decimal places
+ GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Create(4) # decimal places
GLOBALS['ANIM_ACTION_ALL'] = [Draw.Create(0), Draw.Create(1)] # not just the current action
# batch export options
diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py
index 86ac03cc407..c74e7acbcd3 100644
--- a/release/scripts/export_m3g.py
+++ b/release/scripts/export_m3g.py
@@ -11,7 +11,7 @@ Tooltip: 'Export to M3G'
#
# Source: http://www.nelson-games.de/bl2m3g/source
#
-# $Id: m3g_export.py,v 0.1 2005/04/19 12:25 gerhardv Exp gerhardv $
+# $Id$
#
# Author: Gerhard Völkl
#
diff --git a/release/scripts/export_map.py b/release/scripts/export_map.py
index 7df78fc3c9a..2262ae3b89b 100644
--- a/release/scripts/export_map.py
+++ b/release/scripts/export_map.py
@@ -2,14 +2,14 @@
"""
Name: 'Quake 3 (.map)'
-Blender: 243
+Blender: 249
Group: 'Export'
Tooltip: 'Export to Quake map format'
"""
__author__ = 'Campbell Barton'
-__version__ = '0.1'
-__email__ = "cbarton@metavr.com"
+__version__ = '0.1a'
+__email__ = "ideasman42@gmail.com"
__bpydoc__ = """\
This script Exports a Quake 3 map format.
@@ -197,7 +197,7 @@ def is_tricyl_facegroup(faces):
is the face group a tri cylinder
Returens a bool, true if the faces make an extruded tri solid
'''
- return False
+
# cube must have 5 faces
if len(faces) != 5:
print '1'
@@ -234,7 +234,7 @@ def write_node_map(file, ob):
as a MAP node as long as it has the property name - classname
returns True/False based on weather a node was written
'''
- props= [(p.name, p.data) for p in ob.properties]
+ props= [(p.name, p.data) for p in ob.game_properties]
IS_MAP_NODE= False
for name, value in props:
@@ -249,6 +249,10 @@ def write_node_map(file, ob):
file.write('{\n')
for name_value in props:
file.write('"%s" "%s"\n' % name_value)
+ if PREF_GRID_SNAP.val:
+ file.write('"origin" "%d %d %d"\n' % tuple([round(axis*PREF_SCALE.val) for axis in ob.getLocation('worldspace')]) )
+ else:
+ file.write('"origin" "%.6f %.6f %.6f"\n' % tuple([axis*PREF_SCALE.val for axis in ob.getLocation('worldspace')]) )
file.write('}\n')
return True
@@ -287,7 +291,7 @@ def export_map(filepath):
TOTBRUSH= TOTLAMP= TOTNODE= 0
for ob in Object.GetSelected():
- type= ob.getType()
+ type= ob.type
if type == 'Mesh': obs_mesh.append(ob)
elif type == 'Surf': obs_surf.append(ob)
elif type == 'Lamp': obs_lamp.append(ob)
@@ -406,9 +410,10 @@ NULL
else:
print "NOT EXPORTING PATCH", surf_name, u,v, 'Unsupported'
-
- file.write('}\n') # end worldspan
+
+ if obs_mesh or obs_surf:
+ file.write('}\n') # end worldspan
print '\twriting lamps'
@@ -446,4 +451,4 @@ def main():
Window.FileSelector(export_map, 'EXPORT MAP', '*.map')
if __name__ == '__main__': main()
-# export_map('/foo.map') \ No newline at end of file
+# export_map('/foo.map')
diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py
index 9feb02638c3..7dffb5d2048 100644
--- a/release/scripts/export_obj.py
+++ b/release/scripts/export_obj.py
@@ -2,14 +2,14 @@
"""
Name: 'Wavefront (.obj)...'
-Blender: 248
+Blender: 249
Group: 'Export'
Tooltip: 'Save a Wavefront OBJ File'
"""
-__author__ = "Campbell Barton, Jiri Hnidek"
+__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
-__version__ = "1.2"
+__version__ = "1.22"
__bpydoc__ = """\
This script is an exporter to OBJ file format.
@@ -23,11 +23,11 @@ will be exported as mesh data.
"""
-# --------------------------------------------------------------------------
-# OBJ Export v1.1 by Campbell Barton (AKA Ideasman)
-# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
+# Script copyright (C) Campbell J Barton 2007-2009
+# - V1.22- bspline import/export added (funded by PolyDimensions GmbH)
+#
# 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
@@ -120,7 +120,7 @@ def write_mtl(filename):
if img: # We have an image on the face!
file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image
- elif not mat: # No face image. if we havea material search for MTex image.
+ elif mat: # No face image. if we havea material search for MTex image.
for mtex in mat.getTextures():
if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
try:
@@ -181,11 +181,89 @@ def copy_images(dest_dir):
copyCount+=1
print '\tCopied %d images' % copyCount
+
+def test_nurbs_compat(ob):
+ if ob.type != 'Curve':
+ return False
+
+ for nu in ob.data:
+ if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
+ return True
+
+ return False
+
+def write_nurb(file, ob, ob_mat):
+ tot_verts = 0
+ cu = ob.data
+
+ # use negative indices
+ Vector = Blender.Mathutils.Vector
+ for nu in cu:
+
+ if nu.type==0: DEG_ORDER_U = 1
+ else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct
+
+ if nu.type==1:
+ print "\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported"
+ continue
+
+ if nu.knotsV:
+ print "\tWarning, surface:", ob.name, "only poly and nurbs curves supported"
+ continue
+
+ if len(nu) <= DEG_ORDER_U:
+ print "\tWarning, orderU is lower then vert count, skipping:", ob.name
+ continue
+
+ pt_num = 0
+ do_closed = (nu.flagU & 1)
+ do_endpoints = (do_closed==0) and (nu.flagU & 2)
+
+ for pt in nu:
+ pt = Vector(pt[0], pt[1], pt[2]) * ob_mat
+ file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2]))
+ pt_num += 1
+ tot_verts += pt_num
+
+ file.write('g %s\n' % (fixName(ob.name))) # fixName(ob.getData(1)) could use the data name too
+ file.write('cstype bspline\n') # not ideal, hard coded
+ file.write('deg %d\n' % DEG_ORDER_U) # not used for curves but most files have it still
+
+ curve_ls = [-(i+1) for i in xrange(pt_num)]
+
+ # 'curv' keyword
+ if do_closed:
+ if DEG_ORDER_U == 1:
+ pt_num += 1
+ curve_ls.append(-1)
+ else:
+ pt_num += DEG_ORDER_U
+ curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U]
+
+ file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve
+
+ # 'parm' keyword
+ tot_parm = (DEG_ORDER_U + 1) + pt_num
+ tot_parm_div = float(tot_parm-1)
+ parm_ls = [(i/tot_parm_div) for i in xrange(tot_parm)]
+
+ if do_endpoints: # end points, force param
+ for i in xrange(DEG_ORDER_U+1):
+ parm_ls[i] = 0.0
+ parm_ls[-(1+i)] = 1.0
+
+ file.write('parm u %s\n' % ' '.join( [str(i) for i in parm_ls] ))
+
+ file.write('end\n')
+
+ return tot_verts
+
def write(filename, objects,\
EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\
EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\
-EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False):
+EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False,\
+EXPORT_POLYGROUPS=False, EXPORT_CURVE_AS_NURBS=True):
'''
Basic write function. The context and options must be alredy set
This can be accessed externaly
@@ -199,6 +277,29 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=Fal
def veckey2d(v):
return round(v.x, 6), round(v.y, 6)
+ def findVertexGroupName(face, vWeightMap):
+ """
+ Searches the vertexDict to see what groups is assigned to a given face.
+ We use a frequency system in order to sort out the name because a given vetex can
+ belong to two or more groups at the same time. To find the right name for the face
+ we list all the possible vertex group names with their frequency and then sort by
+ frequency in descend order. The top element is the one shared by the highest number
+ of vertices is the face's group
+ """
+ weightDict = {}
+ for vert in face:
+ vWeights = vWeightMap[vert.index]
+ for vGroupName, weight in vWeights:
+ weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight
+
+ if weightDict:
+ alist = [(weight,vGroupName) for vGroupName, weight in weightDict.iteritems()] # sort least to greatest amount of weight
+ alist.sort()
+ return(alist[-1][1]) # highest value last
+ else:
+ return '(null)'
+
+
print 'OBJ Export path: "%s"' % filename
temp_mesh_name = '~tmp-mesh'
@@ -239,12 +340,23 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=Fal
globalNormals = {}
- # Get all meshs
+ # Get all meshes
for ob_main in objects:
for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
+
+ # Nurbs curve support
+ if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
+ if EXPORT_ROTX90:
+ ob_mat = ob_mat * mat_xrot90
+
+ totverts += write_nurb(file, ob, ob_mat)
+
+ continue
+ # end nurbs
+
# Will work for non meshes now! :)
# getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
- me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn)
+ me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn)
if not me:
continue
@@ -397,6 +509,17 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=Fal
if not faceuv:
f_image = None
+ if EXPORT_POLYGROUPS:
+ # Retrieve the list of vertex groups
+ vertGroupNames = me.getVertGroupNames()
+
+ currentVGroup = ''
+ # Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to
+ vgroupsMap = [[] for _i in xrange(len(me.verts))]
+ for vertexGroupName in vertGroupNames:
+ for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1):
+ vgroupsMap[vIdx].append((vertexGroupName, vWeight))
+
for f_index, f in enumerate(faces):
f_v= f.v
f_smooth= f.smooth
@@ -411,9 +534,18 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=Fal
else:
key = materialNames[f_mat], None # No image, use None instead.
+ # Write the vertex group
+ if EXPORT_POLYGROUPS:
+ if vertGroupNames:
+ # find what vertext group the face belongs to
+ theVGroup = findVertexGroupName(f,vgroupsMap)
+ if theVGroup != currentVGroup:
+ currentVGroup = theVGroup
+ file.write('g %s\n' % theVGroup)
+
# CHECK FOR CONTEXT SWITCH
if key == contextMat:
- pass # Context alredy switched, dont do anythoing
+ pass # Context alredy switched, dont do anything
else:
if key[0] == None and key[1] == None:
# Write a null material, since we know the context has changed.
@@ -438,6 +570,7 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=Fal
if EXPORT_GROUP_BY_MAT:
file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
+
file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
contextMat = key
@@ -539,7 +672,8 @@ def write_ui(filename):
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
- EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
+ EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
+ EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
EXPORT_APPLY_MODIFIERS = Draw.Create(0)
EXPORT_ROTX90 = Draw.Create(1)
@@ -557,6 +691,9 @@ def write_ui(filename):
EXPORT_GROUP_BY_OB = Draw.Create(0)
EXPORT_GROUP_BY_MAT = Draw.Create(0)
EXPORT_KEEP_VERT_ORDER = Draw.Create(1)
+ EXPORT_POLYGROUPS = Draw.Create(0)
+ EXPORT_CURVE_AS_NURBS = Draw.Create(1)
+
# Old UI
'''
@@ -607,7 +744,7 @@ def write_ui(filename):
GLOBALS['EVENT'] = e
def do_split(e,v):
- global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER
+ global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER, EXPORT_POLYGROUPS
if EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val:
EXPORT_KEEP_VERT_ORDER.val = 0
else:
@@ -621,6 +758,7 @@ def write_ui(filename):
if not (EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val):
EXPORT_KEEP_VERT_ORDER.val = 1
+
def do_help(e,v):
url = __url__[0]
print 'Trying to open web browser with documentation at this address...'
@@ -637,43 +775,47 @@ def write_ui(filename):
# Center based on overall pup size
ui_x -= 165
- ui_y -= 110
+ ui_y -= 140
global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
- EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
+ EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
+ EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
- Draw.Label('Context...', ui_x+9, ui_y+209, 220, 20)
+ Draw.Label('Context...', ui_x+9, ui_y+239, 220, 20)
Draw.BeginAlign()
- EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+189, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
- EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+189, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
- EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+189, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
+ EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+219, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
+ EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+219, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
+ EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+219, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
Draw.EndAlign()
- Draw.Label('Output Options...', ui_x+9, ui_y+159, 220, 20)
+ Draw.Label('Output Options...', ui_x+9, ui_y+189, 220, 20)
Draw.BeginAlign()
- EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+140, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
- EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+140, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
- EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+140, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
+ EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+170, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
+ EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+170, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
+ EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+170, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
Draw.EndAlign()
- Draw.Label('Export...', ui_x+9, ui_y+109, 220, 20)
+ Draw.Label('Export...', ui_x+9, ui_y+139, 220, 20)
Draw.BeginAlign()
- EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+90, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
- EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+90, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
+ EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+120, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
+ EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+120, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
Draw.EndAlign()
Draw.BeginAlign()
- EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+90, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
- EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+90, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
+ EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+120, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
+ EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+120, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
Draw.EndAlign()
Draw.BeginAlign()
- EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+90, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
- EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+90, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
+ EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+120, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
+ EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+120, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
Draw.EndAlign()
+ EXPORT_POLYGROUPS = Draw.Toggle('Polygroups', EVENT_REDRAW, ui_x+9, ui_y+95, 120, 20, EXPORT_POLYGROUPS.val, 'Export vertex groups as OBJ groups (one group per face approximation).')
+
+ EXPORT_CURVE_AS_NURBS = Draw.Toggle('Nurbs', EVENT_NONE, ui_x+139, ui_y+95, 100, 20, EXPORT_CURVE_AS_NURBS.val, 'Export 3D nurbs curves and polylines as OBJ curves, (bezier not supported).')
Draw.Label('Blender Objects as OBJ:', ui_x+9, ui_y+59, 220, 20)
@@ -727,7 +869,8 @@ def write_ui(filename):
EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val
EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val
EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val
-
+ EXPORT_POLYGROUPS = EXPORT_POLYGROUPS.val
+ EXPORT_CURVE_AS_NURBS = EXPORT_CURVE_AS_NURBS.val
base_name, ext = splitExt(filename)
@@ -776,7 +919,8 @@ def write_ui(filename):
EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
EXPORT_ROTX90, EXPORT_BLEN_OBS,\
- EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER)
+ EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
+ EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS)
Blender.Set('curframe', orig_frame)
diff --git a/release/scripts/flt_properties.py b/release/scripts/flt_properties.py
index 4c841e9c0c0..b9d93b5f52d 100644
--- a/release/scripts/flt_properties.py
+++ b/release/scripts/flt_properties.py
@@ -1,4 +1,3 @@
-#!BPY
# flt_properties.py. For setting default OpenFLight ID property types
# Copyright (C) 2007 Blender Foundation
#
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png
deleted file mode 100755
index 855f06f4fb9..00000000000
--- a/release/scripts/freestyle/data/env_map/brown00.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png
deleted file mode 100755
index 7c9b1a8149e..00000000000
--- a/release/scripts/freestyle/data/env_map/gray00.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png
deleted file mode 100755
index 06542908e6b..00000000000
--- a/release/scripts/freestyle/data/env_map/gray01.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png
deleted file mode 100755
index 0208f4920d9..00000000000
--- a/release/scripts/freestyle/data/env_map/gray02.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png
deleted file mode 100755
index aab9b957c21..00000000000
--- a/release/scripts/freestyle/data/env_map/gray03.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py
deleted file mode 100755
index 968b849f0ae..00000000000
--- a/release/scripts/freestyle/style_modules/ChainingIterators.py
+++ /dev/null
@@ -1,731 +0,0 @@
-#
-# Filename : ChainingIterators.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Chaining Iterators to be used with chaining operators
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-
-## the natural chaining iterator
-## It follows the edges of same nature following the topology of
-## objects with preseance on silhouettes, then borders,
-## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
-## You can specify whether to stay in the selection or not.
-class pyChainSilhouetteIterator(ChainingIterator):
- def __init__(self, stayInSelection=1):
- ChainingIterator.__init__(self, stayInSelection, 1,None,1)
- def getExactTypeName(self):
- return "pyChainSilhouetteIterator"
- def init(self):
- pass
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for i in range(len(natures)):
- currentNature = self.getCurrentEdge().getNature()
- if(natures[i] & currentNature):
- count=0
- while(it.isEnd() == 0):
- visitNext = 0
- oNature = it.getObject().getNature()
- if(oNature & natures[i] != 0):
- if(natures[i] != oNature):
- for j in range(i):
- if(natures[j] & oNature != 0):
- visitNext = 1
- break
- if(visitNext != 0):
- break
- count = count+1
- winner = it.getObject()
- it.increment()
- if(count != 1):
- winner = None
- break
- return winner
-
-## the natural chaining iterator
-## It follows the edges of same nature on the same
-## objects with preseance on silhouettes, then borders,
-## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
-## You can specify whether to stay in the selection or not.
-## You can specify whether to chain iterate over edges that were
-## already visited or not.
-class pyChainSilhouetteGenericIterator(ChainingIterator):
- def __init__(self, stayInSelection=1, stayInUnvisited=1):
- ChainingIterator.__init__(self, stayInSelection, stayInUnvisited,None,1)
- def getExactTypeName(self):
- return "pyChainSilhouetteGenericIterator"
- def init(self):
- pass
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for i in range(len(natures)):
- currentNature = self.getCurrentEdge().getNature()
- if(natures[i] & currentNature):
- count=0
- while(it.isEnd() == 0):
- visitNext = 0
- oNature = it.getObject().getNature()
- ve = it.getObject()
- if(ve.getId() == self.getCurrentEdge().getId()):
- it.increment()
- continue
- if(oNature & natures[i] != 0):
- if(natures[i] != oNature):
- for j in range(i):
- if(natures[j] & oNature != 0):
- visitNext = 1
- break
- if(visitNext != 0):
- break
- count = count+1
- winner = ve
- it.increment()
- if(count != 1):
- winner = None
- break
- return winner
-
-class pyExternalContourChainingIterator(ChainingIterator):
- def __init__(self):
- ChainingIterator.__init__(self, 0, 1,None,1)
- self._isExternalContour = ExternalContourUP1D()
-
- def getExactTypeName(self):
- return "pyExternalContourIterator"
-
- def init(self):
- self._nEdges = 0
- self._isInSelection = 1
-
- def checkViewEdge(self, ve, orientation):
- if(orientation != 0):
- vertex = ve.B()
- else:
- vertex = ve.A()
- it = AdjacencyIterator(vertex,1,1)
- while(it.isEnd() == 0):
- ave = it.getObject()
- if(self._isExternalContour(ave)):
- return 1
- it.increment()
- print "pyExternlContourChainingIterator : didn't find next edge"
- return 0
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(self._isExternalContour(ve)):
- if (ve.getTimeStamp() == GetTimeStampCF()):
- winner = ve
- it.increment()
-
- self._nEdges = self._nEdges+1
- if(winner == None):
- orient = 1
- it = AdjacencyIterator(iter)
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(it.isIncoming() != 0):
- orient = 0
- good = self.checkViewEdge(ve,orient)
- if(good != 0):
- winner = ve
- it.increment()
- return winner
-
-## the natural chaining iterator
-## with a sketchy multiple touch
-class pySketchyChainSilhouetteIterator(ChainingIterator):
- def __init__(self, nRounds=3,stayInSelection=1):
- ChainingIterator.__init__(self, stayInSelection, 0,None,1)
- self._timeStamp = GetTimeStampCF()+nRounds
- self._nRounds = nRounds
- def getExactTypeName(self):
- return "pySketchyChainSilhouetteIterator"
- def init(self):
- self._timeStamp = GetTimeStampCF()+self._nRounds
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for i in range(len(natures)):
- currentNature = self.getCurrentEdge().getNature()
- if(natures[i] & currentNature):
- count=0
- while(it.isEnd() == 0):
- visitNext = 0
- oNature = it.getObject().getNature()
- ve = it.getObject()
- if(ve.getId() == self.getCurrentEdge().getId()):
- it.increment()
- continue
- if(oNature & natures[i] != 0):
- if(natures[i] != oNature):
- for j in range(i):
- if(natures[j] & oNature != 0):
- visitNext = 1
- break
- if(visitNext != 0):
- break
- count = count+1
- winner = ve
- it.increment()
- if(count != 1):
- winner = None
- break
- if(winner == None):
- winner = self.getCurrentEdge()
- if(winner.getChainingTimeStamp() == self._timeStamp):
- winner = None
- return winner
-
-
-# Chaining iterator designed for sketchy style.
-# can chain several times the same ViewEdge
-# in order to produce multiple strokes per ViewEdge.
-class pySketchyChainingIterator(ChainingIterator):
- def __init__(self, nRounds=3, stayInSelection=1):
- ChainingIterator.__init__(self, stayInSelection, 0,None,1)
- self._timeStamp = GetTimeStampCF()+nRounds
- self._nRounds = nRounds
- def getExactTypeName(self):
- return "pySketchyChainingIterator"
-
- def init(self):
- self._timeStamp = GetTimeStampCF()+self._nRounds
-
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == self.getCurrentEdge().getId()):
- it.increment()
- continue
- winner = ve
- it.increment()
- if(winner == None):
- winner = self.getCurrentEdge()
- if(winner.getChainingTimeStamp() == self._timeStamp):
- return None
- return winner
-
-
-## Chaining iterator that fills small occlusions
-## percent
-## The max length of the occluded part
-## expressed in % of the total chain length
-class pyFillOcclusionsRelativeChainingIterator(ChainingIterator):
- def __init__(self, percent):
- ChainingIterator.__init__(self, 0, 1,None,1)
- self._length = 0
- self._percent = float(percent)
- def getExactTypeName(self):
- return "pyFillOcclusionsChainingIterator"
- def init(self):
- # each time we're evaluating a chain length
- # we try to do it once. Thus we reinit
- # the chain length here:
- self._length = 0
- def traverse(self, iter):
- winner = None
- winnerOrientation = 0
- print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for nat in natures:
- if(self.getCurrentEdge().getNature() & nat != 0):
- count=0
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getNature() & nat != 0):
- count = count+1
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- it.increment()
- if(count != 1):
- winner = None
- break
- if(winner != None):
- # check whether this edge was part of the selection
- if(winner.getTimeStamp() != GetTimeStampCF()):
- #print "---", winner.getId().getFirst(), winner.getId().getSecond()
- # if not, let's check whether it's short enough with
- # respect to the chain made without staying in the selection
- #------------------------------------------------------------
- # Did we compute the prospective chain length already ?
- if(self._length == 0):
- #if not, let's do it
- _it = pyChainSilhouetteGenericIterator(0,0)
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- _it.init()
- while(_it.isEnd() == 0):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.increment()
- if(_it.isBegin() != 0):
- break;
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- if(_it.isBegin() == 0):
- _it.decrement()
- while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.decrement()
-
- # let's do the comparison:
- # nw let's compute the length of this connex non selected part:
- connexl = 0
- _cit = pyChainSilhouetteGenericIterator(0,0)
- _cit.setBegin(winner)
- _cit.setCurrentEdge(winner)
- _cit.setOrientation(winnerOrientation)
- _cit.init()
- while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
- ve = _cit.getObject()
- #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond()
- connexl = connexl + ve.getLength2D()
- _cit.increment()
- if(connexl > self._percent * self._length):
- winner = None
- return winner
-
-## Chaining iterator that fills small occlusions
-## size
-## The max length of the occluded part
-## expressed in pixels
-class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator):
- def __init__(self, length):
- ChainingIterator.__init__(self, 0, 1,None,1)
- self._length = float(length)
- def getExactTypeName(self):
- return "pySmallFillOcclusionsChainingIterator"
- def init(self):
- pass
- def traverse(self, iter):
- winner = None
- winnerOrientation = 0
- #print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for nat in natures:
- if(self.getCurrentEdge().getNature() & nat != 0):
- count=0
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getNature() & nat != 0):
- count = count+1
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- it.increment()
- if(count != 1):
- winner = None
- break
- if(winner != None):
- # check whether this edge was part of the selection
- if(winner.getTimeStamp() != GetTimeStampCF()):
- #print "---", winner.getId().getFirst(), winner.getId().getSecond()
- # nw let's compute the length of this connex non selected part:
- connexl = 0
- _cit = pyChainSilhouetteGenericIterator(0,0)
- _cit.setBegin(winner)
- _cit.setCurrentEdge(winner)
- _cit.setOrientation(winnerOrientation)
- _cit.init()
- while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
- ve = _cit.getObject()
- #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond()
- connexl = connexl + ve.getLength2D()
- _cit.increment()
- if(connexl > self._length):
- winner = None
- return winner
-
-
-## Chaining iterator that fills small occlusions
-## percent
-## The max length of the occluded part
-## expressed in % of the total chain length
-class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator):
- def __init__(self, percent, l):
- ChainingIterator.__init__(self, 0, 1,None,1)
- self._length = 0
- self._absLength = l
- self._percent = float(percent)
- def getExactTypeName(self):
- return "pyFillOcclusionsChainingIterator"
- def init(self):
- # each time we're evaluating a chain length
- # we try to do it once. Thus we reinit
- # the chain length here:
- self._length = 0
- def traverse(self, iter):
- winner = None
- winnerOrientation = 0
- print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for nat in natures:
- if(self.getCurrentEdge().getNature() & nat != 0):
- count=0
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getNature() & nat != 0):
- count = count+1
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- it.increment()
- if(count != 1):
- winner = None
- break
- if(winner != None):
- # check whether this edge was part of the selection
- if(winner.getTimeStamp() != GetTimeStampCF()):
- #print "---", winner.getId().getFirst(), winner.getId().getSecond()
- # if not, let's check whether it's short enough with
- # respect to the chain made without staying in the selection
- #------------------------------------------------------------
- # Did we compute the prospective chain length already ?
- if(self._length == 0):
- #if not, let's do it
- _it = pyChainSilhouetteGenericIterator(0,0)
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- _it.init()
- while(_it.isEnd() == 0):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.increment()
- if(_it.isBegin() != 0):
- break;
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- if(_it.isBegin() == 0):
- _it.decrement()
- while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.decrement()
-
- # let's do the comparison:
- # nw let's compute the length of this connex non selected part:
- connexl = 0
- _cit = pyChainSilhouetteGenericIterator(0,0)
- _cit.setBegin(winner)
- _cit.setCurrentEdge(winner)
- _cit.setOrientation(winnerOrientation)
- _cit.init()
- while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())):
- ve = _cit.getObject()
- #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond()
- connexl = connexl + ve.getLength2D()
- _cit.increment()
- if((connexl > self._percent * self._length) or (connexl > self._absLength)):
- winner = None
- return winner
-
-## Chaining iterator that fills small occlusions without caring about the
-## actual selection
-## percent
-## The max length of the occluded part
-## expressed in % of the total chain length
-class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator):
- def __init__(self, percent, l):
- ChainingIterator.__init__(self, 0, 1,None,1)
- self._length = 0
- self._absLength = l
- self._percent = float(percent)
- def getExactTypeName(self):
- return "pyFillOcclusionsChainingIterator"
- def init(self):
- # each time we're evaluating a chain length
- # we try to do it once. Thus we reinit
- # the chain length here:
- self._length = 0
- def traverse(self, iter):
- winner = None
- winnerOrientation = 0
- print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getId() == mateVE.getId() ):
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for nat in natures:
- if(self.getCurrentEdge().getNature() & nat != 0):
- count=0
- while(it.isEnd() == 0):
- ve = it.getObject()
- if(ve.getNature() & nat != 0):
- count = count+1
- winner = ve
- if(it.isIncoming() == 0):
- winnerOrientation = 1
- else:
- winnerOrientation = 0
- it.increment()
- if(count != 1):
- winner = None
- break
- if(winner != None):
- # check whether this edge was part of the selection
- if(winner.qi() != 0):
- #print "---", winner.getId().getFirst(), winner.getId().getSecond()
- # if not, let's check whether it's short enough with
- # respect to the chain made without staying in the selection
- #------------------------------------------------------------
- # Did we compute the prospective chain length already ?
- if(self._length == 0):
- #if not, let's do it
- _it = pyChainSilhouetteGenericIterator(0,0)
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- _it.init()
- while(_it.isEnd() == 0):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.increment()
- if(_it.isBegin() != 0):
- break;
- _it.setBegin(winner)
- _it.setCurrentEdge(winner)
- _it.setOrientation(winnerOrientation)
- if(_it.isBegin() == 0):
- _it.decrement()
- while ((_it.isEnd() == 0) and (_it.isBegin() == 0)):
- ve = _it.getObject()
- #print "--------", ve.getId().getFirst(), ve.getId().getSecond()
- self._length = self._length + ve.getLength2D()
- _it.decrement()
-
- # let's do the comparison:
- # nw let's compute the length of this connex non selected part:
- connexl = 0
- _cit = pyChainSilhouetteGenericIterator(0,0)
- _cit.setBegin(winner)
- _cit.setCurrentEdge(winner)
- _cit.setOrientation(winnerOrientation)
- _cit.init()
- while((_cit.isEnd() == 0) and (_cit.getObject().qi() != 0)):
- ve = _cit.getObject()
- #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond()
- connexl = connexl + ve.getLength2D()
- _cit.increment()
- if((connexl > self._percent * self._length) or (connexl > self._absLength)):
- winner = None
- return winner
-
-
-## the natural chaining iterator
-## It follows the edges of same nature on the same
-## objects with preseance on silhouettes, then borders,
-## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
-## You can specify whether to stay in the selection or not.
-class pyNoIdChainSilhouetteIterator(ChainingIterator):
- def __init__(self, stayInSelection=1):
- ChainingIterator.__init__(self, stayInSelection, 1,None,1)
- def getExactTypeName(self):
- return "pyChainSilhouetteIterator"
- def init(self):
- pass
- def traverse(self, iter):
- winner = None
- it = AdjacencyIterator(iter)
- tvertex = self.getVertex()
- if type(tvertex) is TVertex:
- mateVE = tvertex.mate(self.getCurrentEdge())
- while(it.isEnd() == 0):
- ve = it.getObject()
- feB = self.getCurrentEdge().fedgeB()
- feA = ve.fedgeA()
- vB = feB.vertexB()
- vA = feA.vertexA()
- if vA.getId().getFirst() == vB.getId().getFirst():
- winner = ve
- break
- feA = self.getCurrentEdge().fedgeA()
- feB = ve.fedgeB()
- vB = feB.vertexB()
- vA = feA.vertexA()
- if vA.getId().getFirst() == vB.getId().getFirst():
- winner = ve
- break
- feA = self.getCurrentEdge().fedgeB()
- feB = ve.fedgeB()
- vB = feB.vertexB()
- vA = feA.vertexB()
- if vA.getId().getFirst() == vB.getId().getFirst():
- winner = ve
- break
- feA = self.getCurrentEdge().fedgeA()
- feB = ve.fedgeA()
- vB = feB.vertexA()
- vA = feA.vertexA()
- if vA.getId().getFirst() == vB.getId().getFirst():
- winner = ve
- break
- it.increment()
- else:
- ## case of NonTVertex
- natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
- for i in range(len(natures)):
- currentNature = self.getCurrentEdge().getNature()
- if(natures[i] & currentNature):
- count=0
- while(it.isEnd() == 0):
- visitNext = 0
- oNature = it.getObject().getNature()
- if(oNature & natures[i] != 0):
- if(natures[i] != oNature):
- for j in range(i):
- if(natures[j] & oNature != 0):
- visitNext = 1
- break
- if(visitNext != 0):
- break
- count = count+1
- winner = it.getObject()
- it.increment()
- if(count != 1):
- winner = None
- break
- return winner
-
diff --git a/release/scripts/freestyle/style_modules/Functions0D.py b/release/scripts/freestyle/style_modules/Functions0D.py
deleted file mode 100755
index 872b4e10286..00000000000
--- a/release/scripts/freestyle/style_modules/Functions0D.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from freestyle_init import *
-
-
-class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
- def getName(self):
- return "InverseCurvature2DAngleF0D"
-
- def __call__(self, inter):
- func = Curvature2DAngleF0D()
- c = func(inter)
- return (3.1415 - c)
-
-class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
- def getName(self):
- return "CurvilinearLengthF0D"
-
- def __call__(self, inter):
- i0d = inter.getObject()
- s = i0d.getExactTypeName()
- if (string.find(s, "CurvePoint") == -1):
- print "CurvilinearLengthF0D: not implemented yet for %s" % (s)
- return -1
- cp = castToCurvePoint(i0d)
- return cp.t2d()
-
-## estimate anisotropy of density
-class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
- def __init__(self,level):
- UnaryFunction0DDouble.__init__(self)
- self.IsoDensity = ReadCompleteViewMapPixelF0D(level)
- self.d0Density = ReadSteerableViewMapPixelF0D(0, level)
- self.d1Density = ReadSteerableViewMapPixelF0D(1, level)
- self.d2Density = ReadSteerableViewMapPixelF0D(2, level)
- self.d3Density = ReadSteerableViewMapPixelF0D(3, level)
- def getName(self):
- return "pyDensityAnisotropyF0D"
- def __call__(self, inter):
- c_iso = self.IsoDensity(inter)
- c_0 = self.d0Density(inter)
- c_1 = self.d1Density(inter)
- c_2 = self.d2Density(inter)
- c_3 = self.d3Density(inter)
- cMax = max( max(c_0,c_1), max(c_2,c_3))
- cMin = min( min(c_0,c_1), min(c_2,c_3))
- if ( c_iso == 0 ):
- v = 0
- else:
- v = (cMax-cMin)/c_iso
- return (v)
-
-## Returns the gradient vector for a pixel
-## l
-## the level at which one wants to compute the gradient
-class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
- def __init__(self, l):
- UnaryFunction0DVec2f.__init__(self)
- self._l = l
- self._step = pow(2,self._l)
- def getName(self):
- return "pyViewMapGradientVectorF0D"
- def __call__(self, iter):
- p = iter.getObject().getPoint2D()
- gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
- gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
- return Vector(gx, gy)
-
-class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
- def __init__(self, l):
- UnaryFunction0DDouble.__init__(self)
- self._l = l
- self._step = pow(2,self._l)
- def getName(self):
- return "pyViewMapGradientNormF0D"
- def __call__(self, iter):
- p = iter.getObject().getPoint2D()
- gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
- gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()))
- grad = Vector(gx, gy)
- return grad.length
-
-
diff --git a/release/scripts/freestyle/style_modules/Functions1D.py b/release/scripts/freestyle/style_modules/Functions1D.py
deleted file mode 100755
index aaf115356cb..00000000000
--- a/release/scripts/freestyle/style_modules/Functions1D.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from freestyle_init import *
-from Functions0D import *
-import string
-
-class pyGetInverseProjectedZF1D(UnaryFunction1DDouble):
- def getName(self):
- return "pyGetInverseProjectedZF1D"
-
- def __call__(self, inter):
- func = GetProjectedZF1D()
- z = func(inter)
- return (1.0 - z)
-
-class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
- def getName(self):
- return "pyGetInverseProjectedZF1D"
-
- def __call__(self, inter):
- func = GetProjectedZF1D()
- z = func(inter)
- return (1.0 - z*z)
-
-class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
- def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0):
- UnaryFunction1DDouble.__init__(self, integrationType)
- self._func = pyDensityAnisotropyF0D(level)
- self._integration = integrationType
- self._sampling = sampling
- def getName(self):
- return "pyDensityAnisotropyF1D"
- def __call__(self, inter):
- v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
- return v
-
-class pyViewMapGradientNormF1D(UnaryFunction1DDouble):
- def __init__(self,l, integrationType, sampling=2.0):
- UnaryFunction1DDouble.__init__(self, integrationType)
- self._func = pyViewMapGradientNormF0D(l)
- self._integration = integrationType
- self._sampling = sampling
- def getName(self):
- return "pyViewMapGradientNormF1D"
- def __call__(self, inter):
- v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
- return v
diff --git a/release/scripts/freestyle/style_modules/PredicatesB1D.py b/release/scripts/freestyle/style_modules/PredicatesB1D.py
deleted file mode 100755
index d4c1cace3fe..00000000000
--- a/release/scripts/freestyle/style_modules/PredicatesB1D.py
+++ /dev/null
@@ -1,70 +0,0 @@
-from freestyle_init import *
-from Functions1D import *
-from random import *
-
-class pyZBP1D(BinaryPredicate1D):
- def getName(self):
- return "pyZBP1D"
-
- def __call__(self, i1, i2):
- func = GetZF1D()
- return (func(i1) > func(i2))
-
-class pyZDiscontinuityBP1D(BinaryPredicate1D):
- def __init__(self, iType = IntegrationType.MEAN):
- BinaryPredicate1D.__init__(self)
- self._GetZDiscontinuity = ZDiscontinuityF1D(iType)
-
- def getName(self):
- return "pyZDiscontinuityBP1D"
-
- def __call__(self, i1, i2):
- return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2))
-
-class pyLengthBP1D(BinaryPredicate1D):
- def getName(self):
- return "LengthBP1D"
-
- def __call__(self, i1, i2):
- return (i1.getLength2D() > i2.getLength2D())
-
-class pySilhouetteFirstBP1D(BinaryPredicate1D):
- def getName(self):
- return "SilhouetteFirstBP1D"
-
- def __call__(self, inter1, inter2):
- bpred = SameShapeIdBP1D()
- if (bpred(inter1, inter2) != 1):
- return 0
- if (inter1.getNature() & Nature.SILHOUETTE):
- return (inter2.getNature() & Nature.SILHOUETTE)
- return (inter1.getNature() == inter2.getNature())
-
-class pyNatureBP1D(BinaryPredicate1D):
- def getName(self):
- return "NatureBP1D"
-
- def __call__(self, inter1, inter2):
- return (inter1.getNature() & inter2.getNature())
-
-class pyViewMapGradientNormBP1D(BinaryPredicate1D):
- def __init__(self,l, sampling=2.0):
- BinaryPredicate1D.__init__(self)
- self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
- def getName(self):
- return "pyViewMapGradientNormBP1D"
- def __call__(self, i1,i2):
- print "compare gradient"
- return (self._GetGradient(i1) > self._GetGradient(i2))
-
-class pyShuffleBP1D(BinaryPredicate1D):
- def __init__(self):
- BinaryPredicate1D.__init__(self)
- seed(1)
- def getName(self):
- return "pyNearAndContourFirstBP1D"
-
- def __call__(self, inter1, inter2):
- r1 = uniform(0,1)
- r2 = uniform(0,1)
- return (r1<r2)
diff --git a/release/scripts/freestyle/style_modules/PredicatesU0D.py b/release/scripts/freestyle/style_modules/PredicatesU0D.py
deleted file mode 100755
index 42cde5c222f..00000000000
--- a/release/scripts/freestyle/style_modules/PredicatesU0D.py
+++ /dev/null
@@ -1,103 +0,0 @@
-from freestyle_init import *
-from Functions0D import *
-
-class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
- def __init__(self,a):
- UnaryPredicate0D.__init__(self)
- self._a = a
-
- def getName(self):
- return "HigherCurvature2DAngleUP0D"
-
- def __call__(self, inter):
- func = Curvature2DAngleF0D()
- a = func(inter)
- return ( a > self._a)
-
-class pyUEqualsUP0D(UnaryPredicate0D):
- def __init__(self,u, w):
- UnaryPredicate0D.__init__(self)
- self._u = u
- self._w = w
-
- def getName(self):
- return "UEqualsUP0D"
-
- def __call__(self, inter):
- func = pyCurvilinearLengthF0D()
- u = func(inter)
- return ( ( u > (self._u-self._w) ) and ( u < (self._u+self._w) ) )
-
-class pyVertexNatureUP0D(UnaryPredicate0D):
- def __init__(self,nature):
- UnaryPredicate0D.__init__(self)
- self._nature = nature
-
- def getName(self):
- return "pyVertexNatureUP0D"
-
- def __call__(self, inter):
- v = inter.getObject()
- nat = v.getNature()
- if(nat & self._nature):
- return 1;
- return 0
-
-## check whether an Interface0DIterator
-## is a TVertex and is the one that is
-## hidden (inferred from the context)
-class pyBackTVertexUP0D(UnaryPredicate0D):
- def __init__(self):
- UnaryPredicate0D.__init__(self)
- self._getQI = QuantitativeInvisibilityF0D()
- def getName(self):
- return "pyBackTVertexUP0D"
- def __call__(self, iter):
- v = iter.getObject()
- nat = v.getNature()
- if(nat & Nature.T_VERTEX == 0):
- return 0
- next = iter
- if(next.isEnd()):
- return 0
- if(self._getQI(next) != 0):
- return 1
- return 0
-
-class pyParameterUP0DGoodOne(UnaryPredicate0D):
- def __init__(self,pmin,pmax):
- UnaryPredicate0D.__init__(self)
- self._m = pmin
- self._M = pmax
- #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
-
- def getName(self):
- return "pyCurvilinearAbscissaHigherThanUP0D"
-
- def __call__(self, inter):
- #s = self.getCurvilinearAbscissa(inter)
- u = inter.u()
- #print u
- return ((u>=self._m) and (u<=self._M))
-
-class pyParameterUP0D(UnaryPredicate0D):
- def __init__(self,pmin,pmax):
- UnaryPredicate0D.__init__(self)
- self._m = pmin
- self._M = pmax
- #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
-
- def getName(self):
- return "pyCurvilinearAbscissaHigherThanUP0D"
-
- def __call__(self, inter):
- func = Curvature2DAngleF0D()
- c = func(inter)
- b1 = (c>0.1)
- #s = self.getCurvilinearAbscissa(inter)
- u = inter.u()
- #print u
- b = ((u>=self._m) and (u<=self._M))
- return b and b1
-
-
diff --git a/release/scripts/freestyle/style_modules/PredicatesU1D.py b/release/scripts/freestyle/style_modules/PredicatesU1D.py
deleted file mode 100755
index f39aa99a5a3..00000000000
--- a/release/scripts/freestyle/style_modules/PredicatesU1D.py
+++ /dev/null
@@ -1,381 +0,0 @@
-from freestyle_init import *
-from Functions1D import *
-
-count = 0
-class pyNFirstUP1D(UnaryPredicate1D):
- def __init__(self, n):
- UnaryPredicate1D.__init__(self)
- self.__n = n
- def __call__(self, inter):
- global count
- count = count + 1
- if count <= self.__n:
- return 1
- return 0
-
-class pyHigherLengthUP1D(UnaryPredicate1D):
- def __init__(self,l):
- UnaryPredicate1D.__init__(self)
- self._l = l
-
- def getName(self):
- return "HigherLengthUP1D"
-
- def __call__(self, inter):
- return (inter.getLength2D() > self._l)
-
-class pyNatureUP1D(UnaryPredicate1D):
- def __init__(self,nature):
- UnaryPredicate1D.__init__(self)
- self._nature = nature
- self._getNature = CurveNatureF1D()
-
- def getName(self):
- return "pyNatureUP1D"
-
- def __call__(self, inter):
- if(self._getNature(inter) & self._nature):
- return 1
- return 0
-
-class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D):
- def __init__(self,n,a):
- UnaryPredicate1D.__init__(self)
- self._n = n
- self._a = a
-
- def getName(self):
- return "HigherNumberOfTurnsUP1D"
-
- def __call__(self, inter):
- count = 0
- func = Curvature2DAngleF0D()
- it = inter.verticesBegin()
- while(it.isEnd() == 0):
- if(func(it) > self._a):
- count = count+1
- if(count > self._n):
- return 1
- it.increment()
- return 0
-
-class pyDensityUP1D(UnaryPredicate1D):
- def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._wsize = wsize
- self._threshold = threshold
- self._integration = integration
- self._func = DensityF1D(self._wsize, self._integration, sampling)
-
- def getName(self):
- return "pyDensityUP1D"
-
- def __call__(self, inter):
- if(self._func(inter) < self._threshold):
- return 1
- return 0
-
-class pyLowSteerableViewMapDensityUP1D(UnaryPredicate1D):
- def __init__(self,threshold, level,integration = IntegrationType.MEAN):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._level = level
- self._integration = integration
-
- def getName(self):
- return "pyLowSteerableViewMapDensityUP1D"
-
- def __call__(self, inter):
- func = GetSteerableViewMapDensityF1D(self._level, self._integration)
- v = func(inter)
- print v
- if(v < self._threshold):
- return 1
- return 0
-
-class pyLowDirectionalViewMapDensityUP1D(UnaryPredicate1D):
- def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._orientation = orientation
- self._level = level
- self._integration = integration
-
- def getName(self):
- return "pyLowDirectionalViewMapDensityUP1D"
-
- def __call__(self, inter):
- func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration)
- v = func(inter)
- #print v
- if(v < self._threshold):
- return 1
- return 0
-
-class pyHighSteerableViewMapDensityUP1D(UnaryPredicate1D):
- def __init__(self,threshold, level,integration = IntegrationType.MEAN):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._level = level
- self._integration = integration
- self._func = GetSteerableViewMapDensityF1D(self._level, self._integration)
- def getName(self):
- return "pyHighSteerableViewMapDensityUP1D"
-
- def __call__(self, inter):
-
- v = self._func(inter)
- if(v > self._threshold):
- return 1
- return 0
-
-class pyHighDirectionalViewMapDensityUP1D(UnaryPredicate1D):
- def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._orientation = orientation
- self._level = level
- self._integration = integration
- self._sampling = sampling
- def getName(self):
- return "pyLowDirectionalViewMapDensityUP1D"
-
- def __call__(self, inter):
- func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration, self._sampling)
- v = func(inter)
- if(v > self._threshold):
- return 1
- return 0
-
-class pyHighViewMapDensityUP1D(UnaryPredicate1D):
- def __init__(self,threshold, level,integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._level = level
- self._integration = integration
- self._sampling = sampling
- self._func = GetCompleteViewMapDensityF1D(self._level, self._integration, self._sampling) # 2.0 is the smpling
-
- def getName(self):
- return "pyHighViewMapDensityUP1D"
-
- def __call__(self, inter):
- #print "toto"
- #print func.getName()
- #print inter.getExactTypeName()
- v= self._func(inter)
- if(v > self._threshold):
- return 1
- return 0
-
-class pyDensityFunctorUP1D(UnaryPredicate1D):
- def __init__(self,wsize,threshold, functor, funcmin=0.0, funcmax=1.0, integration = IntegrationType.MEAN):
- UnaryPredicate1D.__init__(self)
- self._wsize = wsize
- self._threshold = float(threshold)
- self._functor = functor
- self._funcmin = float(funcmin)
- self._funcmax = float(funcmax)
- self._integration = integration
-
- def getName(self):
- return "pyDensityFunctorUP1D"
-
- def __call__(self, inter):
- func = DensityF1D(self._wsize, self._integration)
- res = self._functor(inter)
- k = (res-self._funcmin)/(self._funcmax-self._funcmin)
- if(func(inter) < self._threshold*k):
- return 1
- return 0
-
-class pyZSmallerUP1D(UnaryPredicate1D):
- def __init__(self,z, integration=IntegrationType.MEAN):
- UnaryPredicate1D.__init__(self)
- self._z = z
- self._integration = integration
- def getName(self):
- return "pyZSmallerUP1D"
-
- def __call__(self, inter):
- func = GetProjectedZF1D(self._integration)
- if(func(inter) < self._z):
- return 1
- return 0
-
-class pyIsOccludedByUP1D(UnaryPredicate1D):
- def __init__(self,id):
- UnaryPredicate1D.__init__(self)
- self._id = id
- def getName(self):
- return "pyIsOccludedByUP1D"
- def __call__(self, inter):
- func = GetShapeF1D()
- shapes = func(inter)
- for s in shapes:
- if(s.getId() == self._id):
- return 0
- it = inter.verticesBegin()
- itlast = inter.verticesEnd()
- itlast.decrement()
- v = it.getObject()
- vlast = itlast.getObject()
- tvertex = v.viewvertex()
- if type(tvertex) is TVertex:
- print "TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]"
- eit = tvertex.edgesBegin()
- while(eit.isEnd() == 0):
- ve, incoming = eit.getObject()
- if(ve.getId() == self._id):
- return 1
- print "-------", ve.getId().getFirst(), "-", ve.getId().getSecond()
- eit.increment()
- tvertex = vlast.viewvertex()
- if type(tvertex) is TVertex:
- print "TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]"
- eit = tvertex.edgesBegin()
- while(eit.isEnd() == 0):
- ve, incoming = eit.getObject()
- if(ve.getId() == self._id):
- return 1
- print "-------", ve.getId().getFirst(), "-", ve.getId().getSecond()
- eit.increment()
- return 0
-
-class pyIsInOccludersListUP1D(UnaryPredicate1D):
- def __init__(self,id):
- UnaryPredicate1D.__init__(self)
- self._id = id
- def getName(self):
- return "pyIsInOccludersListUP1D"
- def __call__(self, inter):
- func = GetOccludersF1D()
- occluders = func(inter)
- for a in occluders:
- if(a.getId() == self._id):
- return 1
- return 0
-
-class pyIsOccludedByItselfUP1D(UnaryPredicate1D):
- def __init__(self):
- UnaryPredicate1D.__init__(self)
- self.__func1 = GetOccludersF1D()
- self.__func2 = GetShapeF1D()
- def getName(self):
- return "pyIsOccludedByItselfUP1D"
- def __call__(self, inter):
- lst1 = self.__func1(inter)
- lst2 = self.__func2(inter)
- for vs1 in lst1:
- for vs2 in lst2:
- if vs1.getId() == vs2.getId():
- return 1
- return 0
-
-class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
- def __init__(self, idlist):
- UnaryPredicate1D.__init__(self)
- self._idlist = idlist
- self.__func1 = GetOccludersF1D()
- def getName(self):
- return "pyIsOccludedByIdListUP1D"
- def __call__(self, inter):
- lst1 = self.__func1(inter)
- for vs1 in lst1:
- for id in self._idlist:
- if vs1.getId() == id:
- return 1
- return 0
-
-class pyShapeIdListUP1D(UnaryPredicate1D):
- def __init__(self,idlist):
- UnaryPredicate1D.__init__(self)
- self._idlist = idlist
- self._funcs = []
- for id in idlist :
- self._funcs.append(ShapeUP1D(id.getFirst(), id.getSecond()))
-
- def getName(self):
- return "pyShapeIdUP1D"
- def __call__(self, inter):
- for func in self._funcs :
- if(func(inter) == 1) :
- return 1
- return 0
-
-## deprecated
-class pyShapeIdUP1D(UnaryPredicate1D):
- def __init__(self,id):
- UnaryPredicate1D.__init__(self)
- self._id = id
- def getName(self):
- return "pyShapeIdUP1D"
- def __call__(self, inter):
- func = GetShapeF1D()
- shapes = func(inter)
- for a in shapes:
- if(a.getId() == self._id):
- return 1
- return 0
-
-class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
- def __init__(self,threshold, level, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._l = threshold
- self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling)
- def getName(self):
- return "pyHighDensityAnisotropyUP1D"
- def __call__(self, inter):
- return (self.func(inter) > self._l)
-
-class pyHighViewMapGradientNormUP1D(UnaryPredicate1D):
- def __init__(self,threshold, l, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._threshold = threshold
- self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
- def getName(self):
- return "pyHighViewMapGradientNormUP1D"
- def __call__(self, inter):
- gn = self._GetGradient(inter)
- #print gn
- return (gn > self._threshold)
-
-class pyDensityVariableSigmaUP1D(UnaryPredicate1D):
- def __init__(self,functor, sigmaMin,sigmaMax, lmin, lmax, tmin, tmax, integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._functor = functor
- self._sigmaMin = float(sigmaMin)
- self._sigmaMax = float(sigmaMax)
- self._lmin = float(lmin)
- self._lmax = float(lmax)
- self._tmin = tmin
- self._tmax = tmax
- self._integration = integration
- self._sampling = sampling
-
- def getName(self):
- return "pyDensityUP1D"
-
- def __call__(self, inter):
- sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin
- t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin
- if(sigma<self._sigmaMin):
- sigma = self._sigmaMin
- self._func = DensityF1D(sigma, self._integration, self._sampling)
- d = self._func(inter)
- if(d<t):
- return 1
- return 0
-
-class pyClosedCurveUP1D(UnaryPredicate1D):
- def __call__(self, inter):
- it = inter.verticesBegin()
- itlast = inter.verticesEnd()
- itlast.decrement()
- vlast = itlast.getObject()
- v = it.getObject()
- print v.getId().getFirst(), v.getId().getSecond()
- print vlast.getId().getFirst(), vlast.getId().getSecond()
- if(v.getId() == vlast.getId()):
- return 1
- return 0
diff --git a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
deleted file mode 100755
index 7e7ebf647bd..00000000000
--- a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Filename : anisotropic_diffusion.py
-# Author : Fredo Durand
-# Date : 12/08/2004
-# Purpose : Smoothes lines using an anisotropic diffusion scheme
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-from PredicatesU0D import *
-from math import *
-
-## thickness modifiers
-
-normalInfo=Normal2DF0D()
-curvatureInfo=Curvature2DAngleF0D()
-
-def edgestopping(x, sigma):
- return exp(- x*x/(2*sigma*sigma))
-
-class pyDiffusion2Shader(StrokeShader):
- def __init__(self, lambda1, nbIter):
- StrokeShader.__init__(self)
- self._lambda = lambda1
- self._nbIter = nbIter
- def getName(self):
- return "pyDiffusionShader"
- def shade(self, stroke):
- for i in range (1, self._nbIter):
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v=it.getObject()
- p1 = v.getPoint()
- p2 = normalInfo(it.castToInterface0DIterator())*self._lambda*curvatureInfo(it.castToInterface0DIterator())
- v.setPoint(p1+p2)
- it.increment()
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
-Operators.select( upred )
-bpred = TrueBP1D();
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred) )
-shaders_list = [
- ConstantThicknessShader(4),
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
- SamplingShader(2),
- pyDiffusion2Shader(-0.03, 30),
- IncreasingColorShader(1.0,0.0,0.0,1, 0, 1, 0, 1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
-
-
-
diff --git a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
deleted file mode 100755
index 7cdd4b2fd66..00000000000
--- a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Filename : apriori_and_causal_density.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Selects the lines with high a priori density and
-# subjects them to the causal density so as to avoid
-# cluttering
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.3, IntegrationType.LAST))
-Operators.select(upred)
-bpred = TrueBP1D()
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- ConstantThicknessShader(2),
- ConstantColorShader(0.0, 0.0, 0.0,1)
- ]
-Operators.create(pyDensityUP1D(1,0.1, IntegrationType.MEAN), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/apriori_density.py b/release/scripts/freestyle/style_modules/apriori_density.py
deleted file mode 100755
index 5ff6c58e77f..00000000000
--- a/release/scripts/freestyle/style_modules/apriori_density.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : apriori_density.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws lines having a high a priori density
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.1,5)))
-bpred = TrueBP1D()
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.0007,5))
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- ConstantThicknessShader(2),
- ConstantColorShader(0.0, 0.0, 0.0,1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/backbone_stretcher.py b/release/scripts/freestyle/style_modules/backbone_stretcher.py
deleted file mode 100755
index 8a6b9d71a66..00000000000
--- a/release/scripts/freestyle/style_modules/backbone_stretcher.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Filename : backbone_stretcher.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Stretches the geometry of visible lines
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [TextureAssignerShader(4), ConstantColorShader(0.5, 0.5, 0.5), BackboneStretcherShader(20)]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_circles.py b/release/scripts/freestyle/style_modules/blueprint_circles.py
deleted file mode 100755
index 7f3a7564cfe..00000000000
--- a/release/scripts/freestyle/style_modules/blueprint_circles.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Filename : blueprint_circles.py
-# Author : Emmanuel Turquin
-# Date : 04/08/2005
-# Purpose : Produces a blueprint using circular contour strokes
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
-bpred = SameShapeIdBP1D()
-Operators.select(upred)
-Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
-Operators.select(pyHigherLengthUP1D(200))
-shaders_list = [
- ConstantThicknessShader(5),
- pyBluePrintCirclesShader(3),
- pyPerlinNoise1DShader(0.1, 15, 8),
- TextureAssignerShader(4),
- IncreasingColorShader(0.8, 0.8, 0.3, 0.4, 0.3, 0.3, 0.3, 0.1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_ellipses.py b/release/scripts/freestyle/style_modules/blueprint_ellipses.py
deleted file mode 100755
index a5cfe4ec30b..00000000000
--- a/release/scripts/freestyle/style_modules/blueprint_ellipses.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Filename : blueprint_ellipses.py
-# Author : Emmanuel Turquin
-# Date : 04/08/2005
-# Purpose : Produces a blueprint using elliptic contour strokes
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
-bpred = SameShapeIdBP1D()
-Operators.select(upred)
-Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
-Operators.select(pyHigherLengthUP1D(200))
-shaders_list = [
- ConstantThicknessShader(5),
- pyBluePrintEllipsesShader(3),
- pyPerlinNoise1DShader(0.1, 10, 8),
- TextureAssignerShader(4),
- IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.3, 0.3, 0.3, 0.1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_squares.py b/release/scripts/freestyle/style_modules/blueprint_squares.py
deleted file mode 100755
index 7798acc7d47..00000000000
--- a/release/scripts/freestyle/style_modules/blueprint_squares.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Filename : blueprint_squares.py
-# Author : Emmanuel Turquin
-# Date : 04/08/2005
-# Purpose : Produces a blueprint using square contour strokes
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
-bpred = SameShapeIdBP1D()
-Operators.select(upred)
-Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
-Operators.select(pyHigherLengthUP1D(200))
-shaders_list = [
- ConstantThicknessShader(8),
- pyBluePrintSquaresShader(2, 20),
- pyPerlinNoise1DShader(0.07, 10, 8),
- TextureAssignerShader(4),
- IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.6, 0.3, 0.3, 0.3),
- ConstantThicknessShader(4)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/cartoon.py b/release/scripts/freestyle/style_modules/cartoon.py
deleted file mode 100755
index 6ace7e0585a..00000000000
--- a/release/scripts/freestyle/style_modules/cartoon.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : cartoon.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws colored lines. The color is automatically
-# infered from each object's material in a cartoon-like
-# fashion.
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- BezierCurveShader(3),
- ConstantThicknessShader(4),
- pyMaterialColorShader(0.8)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/contour.py b/release/scripts/freestyle/style_modules/contour.py
deleted file mode 100755
index c4b3a0f0827..00000000000
--- a/release/scripts/freestyle/style_modules/contour.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : contour.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws each object's visible contour
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D() ) )
-bpred = SameShapeIdBP1D();
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- ConstantThicknessShader(5.0),
- IncreasingColorShader(0.8,0,0,1,0.1,0,0,1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/curvature2d.py b/release/scripts/freestyle/style_modules/curvature2d.py
deleted file mode 100755
index f699e2186ef..00000000000
--- a/release/scripts/freestyle/style_modules/curvature2d.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Filename : curvature2d.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : The stroke points are colored in gray levels and depending
-# on the 2d curvature value
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-class py2DCurvatureColorShader(StrokeShader):
- def getName(self):
- return "py2DCurvatureColorShader"
-
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- func = Curvature2DAngleF0D()
- while it.isEnd() == 0:
- it0D = it.castToInterface0DIterator()
- sv = it.getObject()
- att = sv.attribute()
- c = func(it0D)
- if (c<0):
- print "negative 2D curvature"
- color = 10.0 * c/3.1415
- att.setColor(color,color,color);
- it.increment()
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
- ConstantThicknessShader(5),
- py2DCurvatureColorShader()
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour.py b/release/scripts/freestyle/style_modules/external_contour.py
deleted file mode 100755
index 2a39b79a410..00000000000
--- a/release/scripts/freestyle/style_modules/external_contour.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : external_contour.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the external contour of the scene
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from ChainingIterators import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
-Operators.select(upred )
-bpred = TrueBP1D();
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
-shaders_list = [
- ConstantThicknessShader(3),
- ConstantColorShader(0.0, 0.0, 0.0,1)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/external_contour_sketchy.py b/release/scripts/freestyle/style_modules/external_contour_sketchy.py
deleted file mode 100755
index 8a4c570b279..00000000000
--- a/release/scripts/freestyle/style_modules/external_contour_sketchy.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Filename : external_contour_sketchy.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the external contour of the scene using a sketchy
-# chaining iterator (in particular each ViewEdge can be drawn
-# several times
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
-Operators.select(upred)
-Operators.bidirectionalChain(pySketchyChainingIterator(), NotUP1D(upred))
-shaders_list = [
- SamplingShader(4),
- SpatialNoiseShader(10, 150, 2, 1, 1),
- IncreasingThicknessShader(4, 10),
- SmoothingShader(400, 0.1, 0, 0.2, 0, 0, 0, 1),
- IncreasingColorShader(1,0,0,1,0,1,0,1),
- TextureAssignerShader(4)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour_smooth.py b/release/scripts/freestyle/style_modules/external_contour_smooth.py
deleted file mode 100755
index 201dc271388..00000000000
--- a/release/scripts/freestyle/style_modules/external_contour_smooth.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Filename : external_contour_smooth.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws a smooth external contour
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-from ChainingIterators import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
-Operators.select(upred)
-bpred = TrueBP1D();
-Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
-shaders_list = [
- SamplingShader(2),
- IncreasingThicknessShader(4,20),
- IncreasingColorShader(1.0, 0.0, 0.5,1, 0.5,1, 0.3, 1),
- SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/extra-lines.sml b/release/scripts/freestyle/style_modules/extra-lines.sml
deleted file mode 100755
index c63cd40945d..00000000000
--- a/release/scripts/freestyle/style_modules/extra-lines.sml
+++ /dev/null
@@ -1,3 +0,0 @@
-1suggestive.py
-1ridges.py
-1nor_suggestive_or_ridges.py
diff --git a/release/scripts/freestyle/style_modules/freestyle_init.py b/release/scripts/freestyle/style_modules/freestyle_init.py
deleted file mode 100644
index 5103cde1048..00000000000
--- a/release/scripts/freestyle/style_modules/freestyle_init.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from Blender.Freestyle import *
-from Blender.Mathutils import Vector
diff --git a/release/scripts/freestyle/style_modules/haloing.py b/release/scripts/freestyle/style_modules/haloing.py
deleted file mode 100755
index afa46173d54..00000000000
--- a/release/scripts/freestyle/style_modules/haloing.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Filename : haloing.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : This style module selects the lines that
-# are connected (in the image) to a specific
-# object and trims them in order to produce
-# a haloing effect around the target shape
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesB1D import *
-from shaders import *
-
-# id corresponds to the id of the target object
-# (accessed by SHIFT+click)
-id = Id(3,0)
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0) , pyIsOccludedByUP1D(id))
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- IncreasingThicknessShader(3, 5),
- IncreasingColorShader(1,0,0, 1,0,1,0,1),
- SamplingShader(1.0),
- pyTVertexRemoverShader(),
- TipRemoverShader(3.0)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
deleted file mode 100755
index ff6efa89ade..00000000000
--- a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Filename : ignore_small_oclusions.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : The strokes are drawn through small occlusions
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-#Operators.bidirectionalChain(pyFillOcclusionsChainingIterator(0.1))
-Operators.bidirectionalChain(pyFillOcclusionsAbsoluteChainingIterator(12))
-shaders_list = [
- SamplingShader(5.0),
- ConstantThicknessShader(3),
- ConstantColorShader(0.0,0.0,0.0),
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/invisible_lines.py b/release/scripts/freestyle/style_modules/invisible_lines.py
deleted file mode 100755
index ea509463bfd..00000000000
--- a/release/scripts/freestyle/style_modules/invisible_lines.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : invisible_lines.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws all lines whose Quantitative Invisibility
-# is different from 0
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-upred = NotUP1D(QuantitativeInvisibilityUP1D(0))
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- SamplingShader(5.0),
- ConstantThicknessShader(3.0),
- ConstantColorShader(0.7,0.7,0.7)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/japanese_bigbrush.py b/release/scripts/freestyle/style_modules/japanese_bigbrush.py
deleted file mode 100755
index 7f109598aaa..00000000000
--- a/release/scripts/freestyle/style_modules/japanese_bigbrush.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Filename : japanese_bigbrush.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Simulates a big brush fr oriental painting
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesB1D import *
-from Functions0D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
-## Splits strokes at points of highest 2D curavture
-## when there are too many abrupt turns in it
-func = pyInverseCurvature2DAngleF0D()
-Operators.recursiveSplit(func, pyParameterUP0D(0.2,0.8), NotUP1D(pyHigherNumberOfTurnsUP1D(3, 0.5)), 2)
-## Keeps only long enough strokes
-Operators.select(pyHigherLengthUP1D(100))
-## Sorts so as to draw the longest strokes first
-## (this will be done using the causal density)
-Operators.sort(pyLengthBP1D())
-shaders_list = [
- pySamplingShader(10),
- BezierCurveShader(30),
- SamplingShader(50),
- ConstantThicknessShader(10),
- pyNonLinearVaryingThicknessShader(4,25, 0.6),
- TextureAssignerShader(6),
- ConstantColorShader(0.2, 0.2, 0.2,1.0),
- TipRemoverShader(10)
- ]
-
-## Use the causal density to avoid cluttering
-Operators.create(pyDensityUP1D(8,0.4, IntegrationType.MEAN), shaders_list)
-
-
diff --git a/release/scripts/freestyle/style_modules/logical_operators.py b/release/scripts/freestyle/style_modules/logical_operators.py
deleted file mode 100755
index 0ecf6623697..00000000000
--- a/release/scripts/freestyle/style_modules/logical_operators.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from freestyle_init import *
-
-class AndUP1D(UnaryPredicate1D):
- def __init__(self, pred1, pred2):
- UnaryPredicate1D.__init__(self)
- self.__pred1 = pred1
- self.__pred2 = pred2
-
- def getName(self):
- return "AndUP1D"
-
- def __call__(self, inter):
- return self.__pred1(inter) and self.__pred2(inter)
-
-class OrUP1D(UnaryPredicate1D):
- def __init__(self, pred1, pred2):
- UnaryPredicate1D.__init__(self)
- self.__pred1 = pred1
- self.__pred2 = pred2
-
- def getName(self):
- return "OrUP1D"
-
- def __call__(self, inter):
- return self.__pred1(inter) or self.__pred2(inter)
-
-class NotUP1D(UnaryPredicate1D):
- def __init__(self, pred):
- UnaryPredicate1D.__init__(self)
- self.__pred = pred
-
- def getName(self):
- return "NotUP1D"
-
- def __call__(self, inter):
- return self.__pred(inter) == 0
diff --git a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
deleted file mode 100755
index 52bb2dd1170..00000000000
--- a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Filename : long_anisotropically_dense.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Selects the lines that are long and have a high anisotropic
-# a priori density and uses causal density
-# to draw without cluttering. Ideally, half of the
-# selected lines are culled using the causal density.
-#
-# ********************* WARNING *************************************
-# ******** The Directional a priori density maps must ******
-# ******** have been computed prior to using this style module ******
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesU0D import *
-from PredicatesB1D import *
-from Functions0D import *
-from Functions1D import *
-from shaders import *
-
-## custom density predicate
-class pyDensityUP1D(UnaryPredicate1D):
- def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._wsize = wsize
- self._threshold = threshold
- self._integration = integration
- self._func = DensityF1D(self._wsize, self._integration, sampling)
- self._func2 = DensityF1D(self._wsize, IntegrationType.MAX, sampling)
-
- def getName(self):
- return "pyDensityUP1D"
-
- def __call__(self, inter):
- c = self._func(inter)
- m = self._func2(inter)
- if(c < self._threshold):
- return 1
- if( m > 4* c ):
- if ( c < 1.5*self._threshold ):
- return 1
- return 0
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
-Operators.select(pyHigherLengthUP1D(40))
-## selects lines having a high anisotropic a priori density
-Operators.select(pyHighDensityAnisotropyUP1D(0.3,4))
-Operators.sort(pyLengthBP1D())
-shaders_list = [
- SamplingShader(2.0),
- ConstantThicknessShader(2),
- ConstantColorShader(0.2,0.2,0.25,1),
- ]
-## uniform culling
-Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list)
-
-
diff --git a/release/scripts/freestyle/style_modules/multiple_parameterization.py b/release/scripts/freestyle/style_modules/multiple_parameterization.py
deleted file mode 100755
index 3f0409db5fa..00000000000
--- a/release/scripts/freestyle/style_modules/multiple_parameterization.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Filename : multiple_parameterization.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : The thickness and the color of the strokes vary continuously
-# independently from occlusions although only
-# visible lines are actually drawn. This is equivalent
-# to assigning the thickness using a parameterization covering
-# the complete silhouette (visible+invisible) and drawing
-# the strokes using a second parameterization that only
-# covers the visible portions.
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-## Chain following the same nature, but without the restriction
-## of staying inside the selection (0).
-Operators.bidirectionalChain(ChainSilhouetteIterator(0))
-shaders_list = [
- SamplingShader(20),
- IncreasingThicknessShader(1.5, 30),
- ConstantColorShader(0.0,0.0,0.0),
- IncreasingColorShader(1,0,0,1,0,1,0,1),
- TextureAssignerShader(-1),
- pyHLRShader() ## this shader draws only visible portions
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/nature.py b/release/scripts/freestyle/style_modules/nature.py
deleted file mode 100755
index b5481a8e519..00000000000
--- a/release/scripts/freestyle/style_modules/nature.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : nature.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Uses the NatureUP1D predicate to select the lines
-# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS,
-# Nature.BORDERS).
-# The suggestive contours must have been enabled in the
-# options dialog to appear in the View Map.
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(pyNatureUP1D(Nature.SILHOUETTE))
-Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D( pyNatureUP1D( Nature.SILHOUETTE) ) )
-shaders_list = [
- IncreasingThicknessShader(3, 10),
- IncreasingColorShader(0.0,0.0,0.0, 1, 0.8,0,0,1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/near_lines.py b/release/scripts/freestyle/style_modules/near_lines.py
deleted file mode 100755
index 565bca1fe1f..00000000000
--- a/release/scripts/freestyle/style_modules/near_lines.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Filename : near_lines.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the lines that are "closer" than a threshold
-# (between 0 and 1)
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, IntegrationType.MEAN))
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- TextureAssignerShader(-1),
- ConstantThicknessShader(5),
- ConstantColorShader(0.0, 0.0, 0.0)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
deleted file mode 100755
index 09ce39d5dd6..00000000000
--- a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Filename : occluded_by_specific_object.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws only the lines that are occluded by a given object
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from shaders import *
-
-## the id of the occluder (use SHIFT+click on the ViewMap to
-## retrieve ids)
-id = Id(3,0)
-upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)),
-pyIsInOccludersListUP1D(id))
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- SamplingShader(5),
- ConstantThicknessShader(3),
- ConstantColorShader(0.3,0.3,0.3,1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/polygonalize.py b/release/scripts/freestyle/style_modules/polygonalize.py
deleted file mode 100755
index 4446c4c1dcc..00000000000
--- a/release/scripts/freestyle/style_modules/polygonalize.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Filename : polygonalize.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Make the strokes more "polygonal"
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(2.0),
- ConstantThicknessShader(3),
- ConstantColorShader(0.0,0.0,0.0),
- PolygonalizationShader(8)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/qi0.py b/release/scripts/freestyle/style_modules/qi0.py
deleted file mode 100755
index d35d23cb7c3..00000000000
--- a/release/scripts/freestyle/style_modules/qi0.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Filename : qi0.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the visible lines (chaining follows same nature lines)
-# (most basic style module)
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(5.0),
- ConstantThicknessShader(4.0),
- ConstantColorShader(0.0,0.0,0.0)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
deleted file mode 100755
index eed41af32b4..00000000000
--- a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : qi0_not_external_contour.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the visible lines (chaining follows same nature lines)
-# that do not belong to the external contour of the scene
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-
-upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- SamplingShader(4),
- SpatialNoiseShader(4, 150, 2, True, True),
- IncreasingThicknessShader(2, 5),
- BackboneStretcherShader(20),
- IncreasingColorShader(1,0,0,1,0,1,0,1),
- TextureAssignerShader(4)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi1.py b/release/scripts/freestyle/style_modules/qi1.py
deleted file mode 100755
index 8d248376138..00000000000
--- a/release/scripts/freestyle/style_modules/qi1.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : qi1.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws lines hidden by one surface.
-# *** Quantitative Invisibility must have been
-# enabled in the options dialog to use this style module ****
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(1))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(1)))
-shaders_list = [
- SamplingShader(5.0),
- ConstantThicknessShader(3),
- ConstantColorShader(0.5,0.5,0.5, 1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi2.py b/release/scripts/freestyle/style_modules/qi2.py
deleted file mode 100755
index ba5e97b6982..00000000000
--- a/release/scripts/freestyle/style_modules/qi2.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : qi2.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws lines hidden by two surfaces.
-# *** Quantitative Invisibility must have been
-# enabled in the options dialog to use this style module ****
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(2))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(2)))
-shaders_list = [
- SamplingShader(10),
- ConstantThicknessShader(1.5),
- ConstantColorShader(0.7,0.7,0.7, 1)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
deleted file mode 100755
index 53fa03103aa..00000000000
--- a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# Filename : sequentialsplit_sketchy.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Use the sequential split with two different
-# predicates to specify respectively the starting and
-# the stopping extremities for strokes
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesU0D import *
-from Functions0D import *
-
-## Predicate to tell whether a TVertex
-## corresponds to a change from 0 to 1 or not.
-class pyBackTVertexUP0D(UnaryPredicate0D):
- def __init__(self):
- UnaryPredicate0D.__init__(self)
- self._getQI = QuantitativeInvisibilityF0D()
- def getName(self):
- return "pyBackTVertexUP0D"
- def __call__(self, iter):
- v = iter.getObject()
- nat = v.getNature()
- if(nat & Nature.T_VERTEX == 0):
- return 0
- if(self._getQI(iter) != 0):
- return 1
- return 0
-
-
-upred = QuantitativeInvisibilityUP1D(0)
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-## starting and stopping predicates:
-start = pyVertexNatureUP0D(Nature.NON_T_VERTEX)
-stop = pyBackTVertexUP0D()
-Operators.sequentialSplit(start, stop, 10)
-shaders_list = [
- SpatialNoiseShader(7, 120, 2, True, True),
- IncreasingThicknessShader(5, 8),
- ConstantColorShader(0.2, 0.2, 0.2, 1),
- TextureAssignerShader(4)
- ]
-Operators.create(TrueUP1D(), shaders_list)
-
diff --git a/release/scripts/freestyle/style_modules/shaders.py b/release/scripts/freestyle/style_modules/shaders.py
deleted file mode 100755
index f07e5b5ad12..00000000000
--- a/release/scripts/freestyle/style_modules/shaders.py
+++ /dev/null
@@ -1,1286 +0,0 @@
-from freestyle_init import *
-from PredicatesU0D import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from logical_operators import *
-from ChainingIterators import *
-from random import *
-from math import *
-
-## thickness modifiers
-######################
-
-class pyDepthDiscontinuityThicknessShader(StrokeShader):
- def __init__(self, min, max):
- StrokeShader.__init__(self)
- self.__min = float(min)
- self.__max = float(max)
- self.__func = ZDiscontinuityF0D()
- def getName(self):
- return "pyDepthDiscontinuityThicknessShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- z_min=0.0
- z_max=1.0
- a = (self.__max - self.__min)/(z_max-z_min)
- b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- z = self.__func(it.castToInterface0DIterator())
- thickness = a*z+b
- it.getObject().attribute().setThickness(thickness, thickness)
- it.increment()
-
-class pyConstantThicknessShader(StrokeShader):
- def __init__(self, thickness):
- StrokeShader.__init__(self)
- self._thickness = thickness
-
- def getName(self):
- return "pyConstantThicknessShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- t = self._thickness/2.0
- att.setThickness(t, t)
- it.increment()
-
-class pyFXSThicknessShader(StrokeShader):
- def __init__(self, thickness):
- StrokeShader.__init__(self)
- self._thickness = thickness
-
- def getName(self):
- return "pyFXSThicknessShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- t = self._thickness/2.0
- att.setThickness(t, t)
- it.increment()
-
-class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
- def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
- StrokeShader.__init__(self)
- self.wsize= wsize
- self.threshold_min= threshold_min
- self.threshold_max= threshold_max
- self._thicknessMin = thicknessMin
- self._thicknessMax = thicknessMax
-
- def getName(self):
- return "pyVaryingThicknessWithDensityShader"
- def shade(self, stroke):
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- func = DensityF0D(self.wsize)
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- toto = it.castToInterface0DIterator()
- c= func(toto)
- if (c < self.threshold_min ):
- c = self.threshold_min
- if (c > self.threshold_max ):
- c = self.threshold_max
-## t = (c - self.threshold_min)/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
- t = (self.threshold_max - c )/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
- att.setThickness(t/2.0, t/2.0)
- i = i+1
- it.increment()
-class pyIncreasingThicknessShader(StrokeShader):
- def __init__(self, thicknessMin, thicknessMax):
- StrokeShader.__init__(self)
- self._thicknessMin = thicknessMin
- self._thicknessMax = thicknessMax
-
- def getName(self):
- return "pyIncreasingThicknessShader"
- def shade(self, stroke):
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- c = float(i)/float(n)
- if(i < float(n)/2.0):
- t = (1.0 - c)*self._thicknessMin + c * self._thicknessMax
- else:
- t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
- att.setThickness(t/2.0, t/2.0)
- i = i+1
- it.increment()
-
-class pyConstrainedIncreasingThicknessShader(StrokeShader):
- def __init__(self, thicknessMin, thicknessMax, ratio):
- StrokeShader.__init__(self)
- self._thicknessMin = thicknessMin
- self._thicknessMax = thicknessMax
- self._ratio = ratio
-
- def getName(self):
- return "pyConstrainedIncreasingThicknessShader"
- def shade(self, stroke):
- slength = stroke.getLength2D()
- tmp = self._ratio*slength
- maxT = 0.0
- if(tmp < self._thicknessMax):
- maxT = tmp
- else:
- maxT = self._thicknessMax
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- c = float(i)/float(n)
- if(i < float(n)/2.0):
- t = (1.0 - c)*self._thicknessMin + c * maxT
- else:
- t = (1.0 - c)*maxT + c * self._thicknessMin
- att.setThickness(t/2.0, t/2.0)
- if(i == n-1):
- att.setThickness(self._thicknessMin/2.0, self._thicknessMin/2.0)
- i = i+1
- it.increment()
-
-class pyDecreasingThicknessShader(StrokeShader):
- def __init__(self, thicknessMax, thicknessMin):
- StrokeShader.__init__(self)
- self._thicknessMin = thicknessMin
- self._thicknessMax = thicknessMax
-
- def getName(self):
- return "pyDecreasingThicknessShader"
- def shade(self, stroke):
- l = stroke.getLength2D()
- tMax = self._thicknessMax
- if(self._thicknessMax > 0.33*l):
- tMax = 0.33*l
- tMin = self._thicknessMin
- if(self._thicknessMin > 0.1*l):
- tMin = 0.1*l
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- c = float(i)/float(n)
- t = (1.0 - c)*tMax +c*tMin
- att.setThickness(t/2.0, t/2.0)
- i = i+1
- it.increment()
-
-def smoothC( a, exp ):
- c = pow(float(a),exp)*pow(2.0,exp)
- return c
-
-class pyNonLinearVaryingThicknessShader(StrokeShader):
- def __init__(self, thicknessExtremity, thicknessMiddle, exponent):
- StrokeShader.__init__(self)
- self._thicknessMin = thicknessMiddle
- self._thicknessMax = thicknessExtremity
- self._exponent = exponent
-
- def getName(self):
- return "pyNonLinearVaryingThicknessShader"
- def shade(self, stroke):
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- if(i < float(n)/2.0):
- c = float(i)/float(n)
- else:
- c = float(n-i)/float(n)
- c = smoothC(c, self._exponent)
- t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
- att.setThickness(t/2.0, t/2.0)
- i = i+1
- it.increment()
-
-## Spherical linear interpolation (cos)
-class pySLERPThicknessShader(StrokeShader):
- def __init__(self, thicknessMin, thicknessMax, omega=1.2):
- StrokeShader.__init__(self)
- self._thicknessMin = thicknessMin
- self._thicknessMax = thicknessMax
- self._omega = omega
-
- def getName(self):
- return "pySLERPThicknessShader"
- def shade(self, stroke):
- slength = stroke.getLength2D()
- tmp = 0.33*slength
- maxT = self._thicknessMax
- if(tmp < self._thicknessMax):
- maxT = tmp
-
- n = stroke.strokeVerticesSize()
- i = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- c = float(i)/float(n)
- if(i < float(n)/2.0):
- t = sin((1-c)*self._omega)/sinh(self._omega)*self._thicknessMin + sin(c*self._omega)/sinh(self._omega) * maxT
- else:
- t = sin((1-c)*self._omega)/sinh(self._omega)*maxT + sin(c*self._omega)/sinh(self._omega) * self._thicknessMin
- att.setThickness(t/2.0, t/2.0)
- i = i+1
- it.increment()
-
-class pyTVertexThickenerShader(StrokeShader): ## FIXME
- def __init__(self, a=1.5, n=3):
- StrokeShader.__init__(self)
- self._a = a
- self._n = n
-
- def getName(self):
- return "pyTVertexThickenerShader"
-
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
- while it.isEnd() == 0:
- if(predTVertex(it) == 1):
- it2 = StrokeVertexIterator(it)
- it2.increment()
- if not(it.isBegin() or it2.isEnd()):
- it.increment()
- continue
- n = self._n
- a = self._a
- if(it.isBegin()):
- it3 = StrokeVertexIterator(it)
- count = 0
- while (it3.isEnd() == 0 and count < n):
- att = it3.getObject().attribute()
- tr = att.getThicknessR();
- tl = att.getThicknessL();
- r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
- #r = (1.0-a)/float(n-1)*count + a
- att.setThickness(r*tr, r*tl)
- it3.increment()
- count = count + 1
- if(it2.isEnd()):
- it4 = StrokeVertexIterator(it)
- count = 0
- while (it4.isBegin() == 0 and count < n):
- att = it4.getObject().attribute()
- tr = att.getThicknessR();
- tl = att.getThicknessL();
- r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
- #r = (1.0-a)/float(n-1)*count + a
- att.setThickness(r*tr, r*tl)
- it4.decrement()
- count = count + 1
- if ((it4.isBegin() == 1)):
- att = it4.getObject().attribute()
- tr = att.getThicknessR();
- tl = att.getThicknessL();
- r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
- #r = (1.0-a)/float(n-1)*count + a
- att.setThickness(r*tr, r*tl)
- it.increment()
-
-class pyImportance2DThicknessShader(StrokeShader):
- def __init__(self, x, y, w, kmin, kmax):
- StrokeShader.__init__(self)
- self._x = x
- self._y = y
- self._w = float(w)
- self._kmin = float(kmin)
- self._kmax = float(kmax)
-
- def getName(self):
- return "pyImportanceThicknessShader"
- def shade(self, stroke):
- origin = Vector(self._x, self._y)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v = it.getObject()
- p = Vector(v.getProjectedX(), v.getProjectedY())
- d = (p-origin).length
- if(d>self._w):
- k = self._kmin
- else:
- k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
- att = v.attribute()
- tr = att.getThicknessR()
- tl = att.getThicknessL()
- att.setThickness(k*tr/2.0, k*tl/2.0)
- it.increment()
-
-class pyImportance3DThicknessShader(StrokeShader):
- def __init__(self, x, y, z, w, kmin, kmax):
- StrokeShader.__init__(self)
- self._x = x
- self._y = y
- self._z = z
- self._w = float(w)
- self._kmin = float(kmin)
- self._kmax = float(kmax)
-
- def getName(self):
- return "pyImportance3DThicknessShader"
- def shade(self, stroke):
- origin = Vector(self._x, self._y, self._z)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v = it.getObject()
- p = Vector(v.getX(), v.getY(), v.getZ())
- d = (p-origin).length
- if(d>self._w):
- k = self._kmin
- else:
- k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
- att = v.attribute()
- tr = att.getThicknessR()
- tl = att.getThicknessL()
- att.setThickness(k*tr/2.0, k*tl/2.0)
- it.increment()
-
-class pyZDependingThicknessShader(StrokeShader):
- def __init__(self, min, max):
- StrokeShader.__init__(self)
- self.__min = min
- self.__max = max
- self.__func = GetProjectedZF0D()
- def getName(self):
- return "pyZDependingThicknessShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- z_min = 1
- z_max = 0
- while it.isEnd() == 0:
- z = self.__func(it.castToInterface0DIterator())
- if z < z_min:
- z_min = z
- elif z > z_max:
- z_max = z
- it.increment()
- z_diff = 1 / (z_max - z_min)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- z = (self.__func(it.castToInterface0DIterator()) - z_min) * z_diff
- thickness = (1 - z) * self.__max + z * self.__min
- it.getObject().attribute().setThickness(thickness, thickness)
- it.increment()
-
-
-## color modifiers
-##################
-
-class pyConstantColorShader(StrokeShader):
- def __init__(self,r,g,b, a = 1):
- StrokeShader.__init__(self)
- self._r = r
- self._g = g
- self._b = b
- self._a = a
- def getName(self):
- return "pyConstantColorShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- att.setColor(self._r, self._g, self._b)
- att.setAlpha(self._a)
- it.increment()
-
-#c1->c2
-class pyIncreasingColorShader(StrokeShader):
- def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
- StrokeShader.__init__(self)
- self._c1 = [r1,g1,b1,a1]
- self._c2 = [r2,g2,b2,a2]
- def getName(self):
- return "pyIncreasingColorShader"
- def shade(self, stroke):
- n = stroke.strokeVerticesSize() - 1
- inc = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- c = float(inc)/float(n)
-
- att.setColor( (1-c)*self._c1[0] + c*self._c2[0],
- (1-c)*self._c1[1] + c*self._c2[1],
- (1-c)*self._c1[2] + c*self._c2[2],)
- att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],)
- inc = inc+1
- it.increment()
-
-# c1->c2->c1
-class pyInterpolateColorShader(StrokeShader):
- def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
- StrokeShader.__init__(self)
- self._c1 = [r1,g1,b1,a1]
- self._c2 = [r2,g2,b2,a2]
- def getName(self):
- return "pyInterpolateColorShader"
- def shade(self, stroke):
- n = stroke.strokeVerticesSize() - 1
- inc = 0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- u = float(inc)/float(n)
- c = 1-2*(fabs(u-0.5))
- att.setColor( (1-c)*self._c1[0] + c*self._c2[0],
- (1-c)*self._c1[1] + c*self._c2[1],
- (1-c)*self._c1[2] + c*self._c2[2],)
- att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],)
- inc = inc+1
- it.increment()
-
-class pyMaterialColorShader(StrokeShader):
- def __init__(self, threshold=50):
- StrokeShader.__init__(self)
- self._threshold = threshold
-
- def getName(self):
- return "pyMaterialColorShader"
-
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- func = MaterialF0D()
- xn = 0.312713
- yn = 0.329016
- Yn = 1.0
- un = 4.* xn/ ( -2.*xn + 12.*yn + 3. )
- vn= 9.* yn/ ( -2.*xn + 12.*yn +3. )
- while it.isEnd() == 0:
- toto = it.castToInterface0DIterator()
- mat = func(toto)
-
- r = mat.diffuseR()
- g = mat.diffuseG()
- b = mat.diffuseB()
-
- X = 0.412453*r + 0.35758 *g + 0.180423*b
- Y = 0.212671*r + 0.71516 *g + 0.072169*b
- Z = 0.019334*r + 0.119193*g + 0.950227*b
-
- if((X == 0) and (Y == 0) and (Z == 0)):
- X = 0.01
- Y = 0.01
- Z = 0.01
- u = 4.*X / (X + 15.*Y + 3.*Z)
- v = 9.*Y / (X + 15.*Y + 3.*Z)
-
- L= 116. * pow((Y/Yn),(1./3.)) -16
- U = 13. * L * (u - un)
- V = 13. * L * (v - vn)
-
- if (L > self._threshold):
- L = L/1.3
- U = U+10
- else:
- L = L +2.5*(100-L)/5.
- U = U/3.0
- V = V/3.0
- u = U / (13. * L) + un
- v = V / (13. * L) + vn
-
- Y = Yn * pow( ((L+16.)/116.), 3.)
- X = -9. * Y * u / ((u - 4.)* v - u * v)
- Z = (9. * Y - 15*v*Y - v*X) /( 3. * v)
-
- r = 3.240479 * X - 1.53715 * Y - 0.498535 * Z
- g = -0.969256 * X + 1.875991 * Y + 0.041556 * Z
- b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z
-
- att = it.getObject().attribute()
- att.setColor(r, g, b)
- it.increment()
-
-class pyRandomColorShader(StrokeShader):
- def getName(self):
- return "pyRandomColorShader"
- def __init__(self, s=1):
- StrokeShader.__init__(self)
- seed(s)
- def shade(self, stroke):
- ## pick a random color
- c0 = float(uniform(15,75))/100.0
- c1 = float(uniform(15,75))/100.0
- c2 = float(uniform(15,75))/100.0
- print c0, c1, c2
- it = stroke.strokeVerticesBegin()
- while(it.isEnd() == 0):
- it.getObject().attribute().setColor(c0,c1,c2)
- it.increment()
-
-class py2DCurvatureColorShader(StrokeShader):
- def getName(self):
- return "py2DCurvatureColorShader"
-
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- func = Curvature2DAngleF0D()
- while it.isEnd() == 0:
- toto = it.castToInterface0DIterator()
- sv = it.getObject()
- att = sv.attribute()
- c = func(toto)
- if (c<0):
- print "negative 2D curvature"
- color = 10.0 * c/3.1415
- print color
- att.setColor(color,color,color);
- it.increment()
-
-class pyTimeColorShader(StrokeShader):
- def __init__(self, step=0.01):
- StrokeShader.__init__(self)
- self._t = 0
- self._step = step
- def shade(self, stroke):
- c = self._t*1.0
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- att = it.getObject().attribute()
- att.setColor(c,c,c)
- it.increment()
- self._t = self._t+self._step
-
-## geometry modifiers
-
-class pySamplingShader(StrokeShader):
- def __init__(self, sampling):
- StrokeShader.__init__(self)
- self._sampling = sampling
- def getName(self):
- return "pySamplingShader"
- def shade(self, stroke):
- stroke.Resample(float(self._sampling))
-
-class pyBackboneStretcherShader(StrokeShader):
- def __init__(self, l):
- StrokeShader.__init__(self)
- self._l = l
- def getName(self):
- return "pyBackboneStretcherShader"
- def shade(self, stroke):
- it0 = stroke.strokeVerticesBegin()
- it1 = StrokeVertexIterator(it0)
- it1.increment()
- itn = stroke.strokeVerticesEnd()
- itn.decrement()
- itn_1 = StrokeVertexIterator(itn)
- itn_1.decrement()
- v0 = it0.getObject()
- v1 = it1.getObject()
- vn_1 = itn_1.getObject()
- vn = itn.getObject()
- p0 = Vector(v0.getProjectedX(), v0.getProjectedY())
- pn = Vector(vn.getProjectedX(), vn.getProjectedY())
- p1 = Vector(v1.getProjectedX(), v1.getProjectedY())
- pn_1 = Vector(vn_1.getProjectedX(), vn_1.getProjectedY())
- d1 = p0-p1
- d1.normalize()
- dn = pn-pn_1
- dn.normalize()
- newFirst = p0+d1*float(self._l)
- newLast = pn+dn*float(self._l)
- v0.setPoint(newFirst)
- vn.setPoint(newLast)
-
-class pyLengthDependingBackboneStretcherShader(StrokeShader):
- def __init__(self, l):
- StrokeShader.__init__(self)
- self._l = l
- def getName(self):
- return "pyBackboneStretcherShader"
- def shade(self, stroke):
- l = stroke.getLength2D()
- stretch = self._l*l
- it0 = stroke.strokeVerticesBegin()
- it1 = StrokeVertexIterator(it0)
- it1.increment()
- itn = stroke.strokeVerticesEnd()
- itn.decrement()
- itn_1 = StrokeVertexIterator(itn)
- itn_1.decrement()
- v0 = it0.getObject()
- v1 = it1.getObject()
- vn_1 = itn_1.getObject()
- vn = itn.getObject()
- p0 = Vector(v0.getProjectedX(), v0.getProjectedY())
- pn = Vector(vn.getProjectedX(), vn.getProjectedY())
- p1 = Vector(v1.getProjectedX(), v1.getProjectedY())
- pn_1 = Vector(vn_1.getProjectedX(), vn_1.getProjectedY())
- d1 = p0-p1
- d1.normalize()
- dn = pn-pn_1
- dn.normalize()
- newFirst = p0+d1*float(stretch)
- newLast = pn+dn*float(stretch)
- v0.setPoint(newFirst)
- vn.setPoint(newLast)
-
-
-## Shader to replace a stroke by its corresponding tangent
-class pyGuidingLineShader(StrokeShader):
- def getName(self):
- return "pyGuidingLineShader"
- ## shading method
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin() ## get the first vertex
- itlast = stroke.strokeVerticesEnd() ##
- itlast.decrement() ## get the last one
- t = itlast.getObject().getPoint() - it.getObject().getPoint() ## tangent direction
- itmiddle = StrokeVertexIterator(it) ##
- while(itmiddle.getObject().u()<0.5): ## look for the stroke middle vertex
- itmiddle.increment() ##
- it = StrokeVertexIterator(itmiddle)
- it.increment()
- while(it.isEnd() == 0): ## position all the vertices along the tangent for the right part
- it.getObject().setPoint(itmiddle.getObject().getPoint() \
- +t*(it.getObject().u()-itmiddle.getObject().u()))
- it.increment()
- it = StrokeVertexIterator(itmiddle)
- it.decrement()
- while(it.isBegin() == 0): ## position all the vertices along the tangent for the left part
- it.getObject().setPoint(itmiddle.getObject().getPoint() \
- -t*(itmiddle.getObject().u()-it.getObject().u()))
- it.decrement()
- it.getObject().setPoint(itmiddle.getObject().getPoint()-t*(itmiddle.getObject().u())) ## first vertex
-
-
-class pyBackboneStretcherNoCuspShader(StrokeShader):
- def __init__(self, l):
- StrokeShader.__init__(self)
- self._l = l
- def getName(self):
- return "pyBackboneStretcherNoCuspShader"
- def shade(self, stroke):
- it0 = stroke.strokeVerticesBegin()
- it1 = StrokeVertexIterator(it0)
- it1.increment()
- itn = stroke.strokeVerticesEnd()
- itn.decrement()
- itn_1 = StrokeVertexIterator(itn)
- itn_1.decrement()
- v0 = it0.getObject()
- v1 = it1.getObject()
- if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)):
- p0 = v0.getPoint()
- p1 = v1.getPoint()
- d1 = p0-p1
- d1.normalize()
- newFirst = p0+d1*float(self._l)
- v0.setPoint(newFirst)
- vn_1 = itn_1.getObject()
- vn = itn.getObject()
- if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)):
- pn = vn.getPoint()
- pn_1 = vn_1.getPoint()
- dn = pn-pn_1
- dn.normalize()
- newLast = pn+dn*float(self._l)
- vn.setPoint(newLast)
-
-normalInfo=Normal2DF0D()
-curvatureInfo=Curvature2DAngleF0D()
-
-def edgestopping(x, sigma):
- return exp(- x*x/(2*sigma*sigma))
-
-class pyDiffusion2Shader(StrokeShader):
- def __init__(self, lambda1, nbIter):
- StrokeShader.__init__(self)
- self._lambda = lambda1
- self._nbIter = nbIter
- self._normalInfo = Normal2DF0D()
- self._curvatureInfo = Curvature2DAngleF0D()
- def getName(self):
- return "pyDiffusionShader"
- def shade(self, stroke):
- for i in range (1, self._nbIter):
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v=it.getObject()
- p1 = v.getPoint()
- p2 = self._normalInfo(it.castToInterface0DIterator())*self._lambda*self._curvatureInfo(it.castToInterface0DIterator())
- v.setPoint(p1+p2)
- it.increment()
-
-class pyTipRemoverShader(StrokeShader):
- def __init__(self, l):
- StrokeShader.__init__(self)
- self._l = l
- def getName(self):
- return "pyTipRemoverShader"
- def shade(self, stroke):
- originalSize = stroke.strokeVerticesSize()
- if(originalSize<4):
- return
- verticesToRemove = []
- oldAttributes = []
- it = stroke.strokeVerticesBegin()
- while(it.isEnd() == 0):
- v = it.getObject()
- if((v.curvilinearAbscissa() < self._l) or (v.strokeLength()-v.curvilinearAbscissa() < self._l)):
- verticesToRemove.append(v)
- oldAttributes.append(StrokeAttribute(v.attribute()))
- it.increment()
- if(originalSize-len(verticesToRemove) < 2):
- return
- for sv in verticesToRemove:
- stroke.RemoveVertex(sv)
- stroke.Resample(originalSize)
- if(stroke.strokeVerticesSize() != originalSize):
- print "pyTipRemover: Warning: resampling problem"
- it = stroke.strokeVerticesBegin()
- for a in oldAttributes:
- if(it.isEnd() == 1):
- break
- v = it.getObject()
- v.setAttribute(a)
- it.increment()
-
-class pyTVertexRemoverShader(StrokeShader):
- def getName(self):
- return "pyTVertexRemoverShader"
- def shade(self, stroke):
- if(stroke.strokeVerticesSize() <= 3 ):
- return
- predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
- it = stroke.strokeVerticesBegin()
- itlast = stroke.strokeVerticesEnd()
- itlast.decrement()
- if(predTVertex(it) == 1):
- stroke.RemoveVertex(it.getObject())
- if(predTVertex(itlast) == 1):
- stroke.RemoveVertex(itlast.getObject())
-
-class pyExtremitiesOrientationShader(StrokeShader):
- def __init__(self, x1,y1,x2=0,y2=0):
- StrokeShader.__init__(self)
- self._v1 = Vector(x1,y1)
- self._v2 = Vector(x2,y2)
- def getName(self):
- return "pyExtremitiesOrientationShader"
- def shade(self, stroke):
- print self._v1.x,self._v1.y
- stroke.setBeginningOrientation(self._v1.x,self._v1.y)
- stroke.setEndingOrientation(self._v2.x,self._v2.y)
-
-def getFEdge(it1, it2):
- return it1.getFEdge(it2)
-
-class pyHLRShader(StrokeShader):
- def getName(self):
- return "pyHLRShader"
- def shade(self, stroke):
- originalSize = stroke.strokeVerticesSize()
- if(originalSize<4):
- return
- it = stroke.strokeVerticesBegin()
- invisible = 0
- it2 = StrokeVertexIterator(it)
- it2.increment()
- fe = getFEdge(it.getObject(), it2.getObject())
- if(fe.viewedge().qi() != 0):
- invisible = 1
- while(it2.isEnd() == 0):
- v = it.getObject()
- vnext = it2.getObject()
- if(v.getNature() & Nature.VIEW_VERTEX):
- #if(v.getNature() & Nature.T_VERTEX):
- fe = getFEdge(v,vnext)
- qi = fe.viewedge().qi()
- if(qi != 0):
- invisible = 1
- else:
- invisible = 0
- if(invisible == 1):
- v.attribute().setVisible(0)
- it.increment()
- it2.increment()
-
-class pyTVertexOrientationShader(StrokeShader):
- def __init__(self):
- StrokeShader.__init__(self)
- self._Get2dDirection = Orientation2DF1D()
- def getName(self):
- return "pyTVertexOrientationShader"
- ## finds the TVertex orientation from the TVertex and
- ## the previous or next edge
- def findOrientation(self, tv, ve):
- mateVE = tv.mate(ve)
- if((ve.qi() != 0) or (mateVE.qi() != 0)):
- ait = AdjacencyIterator(tv,1,0)
- winner = None
- incoming = 1
- while(ait.isEnd() == 0):
- ave = ait.getObject()
- if((ave.getId() != ve.getId()) and (ave.getId() != mateVE.getId())):
- winner = ait.getObject()
- if(ait.isIncoming() == 0):
- incoming = 0
- break
- ait.increment()
- if(winner != None):
- if(incoming != 0):
- direction = self._Get2dDirection(winner.fedgeB())
- else:
- direction = self._Get2dDirection(winner.fedgeA())
- return direction
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it2 = StrokeVertexIterator(it)
- it2.increment()
- ## case where the first vertex is a TVertex
- v = it.getObject()
- if(v.getNature() & Nature.T_VERTEX):
- tv = v.castToTVertex()
- ve = getFEdge(v, it2.getObject()).viewedge()
- if(tv != None):
- dir = self.findOrientation(tv, ve)
- #print dir.x, dir.y
- v.attribute().setAttributeVec2f("orientation", dir)
- while(it2.isEnd() == 0):
- vprevious = it.getObject()
- v = it2.getObject()
- if(v.getNature() & Nature.T_VERTEX):
- tv = v.castToTVertex()
- ve = getFEdge(vprevious, v).viewedge()
- if(tv != None):
- dir = self.findOrientation(tv, ve)
- #print dir.x, dir.y
- v.attribute().setAttributeVec2f("orientation", dir)
- it.increment()
- it2.increment()
- ## case where the last vertex is a TVertex
- v = it.getObject()
- if(v.getNature() & Nature.T_VERTEX):
- itPrevious = StrokeVertexIterator(it)
- itPrevious.decrement()
- tv = v.castToTVertex()
- ve = getFEdge(itPrevious.getObject(), v).viewedge()
- if(tv != None):
- dir = self.findOrientation(tv, ve)
- #print dir.x, dir.y
- v.attribute().setAttributeVec2f("orientation", dir)
-
-class pySinusDisplacementShader(StrokeShader):
- def __init__(self, f, a):
- StrokeShader.__init__(self)
- self._f = f
- self._a = a
- self._getNormal = Normal2DF0D()
-
- def getName(self):
- return "pySinusDisplacementShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v = it.getObject()
- #print self._getNormal.getName()
- n = self._getNormal(it.castToInterface0DIterator())
- p = v.getPoint()
- u = v.u()
- a = self._a*(1-2*(fabs(u-0.5)))
- n = n*a*cos(self._f*u*6.28)
- #print n.x, n.y
- v.setPoint(p+n)
- #v.setPoint(v.getPoint()+n*a*cos(f*v.u()))
- it.increment()
-
-class pyPerlinNoise1DShader(StrokeShader):
- def __init__(self, freq = 10, amp = 10, oct = 4):
- StrokeShader.__init__(self)
- self.__noise = FrsNoise()
- self.__freq = freq
- self.__amp = amp
- self.__oct = oct
- def getName(self):
- return "pyPerlinNoise1DShader"
- def shade(self, stroke):
- i = randint(0, 50)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v = it.getObject()
- nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct)
- v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres)
- i = i+1
- it.increment()
-
-class pyPerlinNoise2DShader(StrokeShader):
- def __init__(self, freq = 10, amp = 10, oct = 4):
- StrokeShader.__init__(self)
- self.__noise = FrsNoise()
- self.__freq = freq
- self.__amp = amp
- self.__oct = oct
- def getName(self):
- return "pyPerlinNoise2DShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- v = it.getObject()
- vec = Vector(v.getProjectedX(), v.getProjectedY())
- nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
- v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres)
- it.increment()
-
-class pyBluePrintCirclesShader(StrokeShader):
- def __init__(self, turns = 1):
- StrokeShader.__init__(self)
- self.__turns = turns
- def getName(self):
- return "pyBluePrintCirclesShader"
- def shade(self, stroke):
- p_min = Vector(10000, 10000)
- p_max = Vector(0, 0)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- p = it.getObject().getPoint()
- if (p.x < p_min.x):
- p_min.x = p.x
- if (p.x > p_max.x):
- p_max.x = p.x
- if (p.y < p_min.y):
- p_min.y = p.y
- if (p.y > p_max.y):
- p_max.y = p.y
- it.increment()
- stroke.Resample(32 * self.__turns)
- sv_nb = stroke.strokeVerticesSize()
-# print "min :", p_min.x, p_min.y # DEBUG
-# print "mean :", p_sum.x, p_sum.y # DEBUG
-# print "max :", p_max.x, p_max.y # DEBUG
-# print "----------------------" # DEBUG
-#######################################################
- sv_nb = sv_nb / self.__turns
- center = (p_min + p_max) / 2
- radius = (center.x - p_min.x + center.y - p_min.y) / 2
- p_new = Vector(0, 0)
-#######################################################
- it = stroke.strokeVerticesBegin()
- for j in range(self.__turns):
- radius = radius + randint(-3, 3)
- center.x = center.x + randint(-5, 5)
- center.y = center.y + randint(-5, 5)
- i = 0
- while i < sv_nb:
- p_new.x = center.x + radius * cos(2 * pi * float(i) / float(sv_nb - 1))
- p_new.y = center.y + radius * sin(2 * pi * float(i) / float(sv_nb - 1))
- it.getObject().setPoint(p_new)
- i = i + 1
- it.increment()
- while it.isEnd() == 0:
- stroke.RemoveVertex(it.getObject())
- it.increment()
-
-
-class pyBluePrintEllipsesShader(StrokeShader):
- def __init__(self, turns = 1):
- StrokeShader.__init__(self)
- self.__turns = turns
- def getName(self):
- return "pyBluePrintEllipsesShader"
- def shade(self, stroke):
- p_min = Vector(10000, 10000)
- p_max = Vector(0, 0)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- p = it.getObject().getPoint()
- if (p.x < p_min.x):
- p_min.x = p.x
- if (p.x > p_max.x):
- p_max.x = p.x
- if (p.y < p_min.y):
- p_min.y = p.y
- if (p.y > p_max.y):
- p_max.y = p.y
- it.increment()
- stroke.Resample(32 * self.__turns)
- sv_nb = stroke.strokeVerticesSize()
-# print "min :", p_min.x, p_min.y # DEBUG
-# print "mean :", p_sum.x, p_sum.y # DEBUG
-# print "max :", p_max.x, p_max.y # DEBUG
-# print "----------------------" # DEBUG
-#######################################################
- sv_nb = sv_nb / self.__turns
- center = (p_min + p_max) / 2
- radius_x = center.x - p_min.x
- radius_y = center.y - p_min.y
- p_new = Vector(0, 0)
-#######################################################
- it = stroke.strokeVerticesBegin()
- for j in range(self.__turns):
- radius_x = radius_x + randint(-3, 3)
- radius_y = radius_y + randint(-3, 3)
- center.x = center.x + randint(-5, 5)
- center.y = center.y + randint(-5, 5)
- i = 0
- while i < sv_nb:
- p_new.x = center.x + radius_x * cos(2 * pi * float(i) / float(sv_nb - 1))
- p_new.y = center.y + radius_y * sin(2 * pi * float(i) / float(sv_nb - 1))
- it.getObject().setPoint(p_new)
- i = i + 1
- it.increment()
- while it.isEnd() == 0:
- stroke.RemoveVertex(it.getObject())
- it.increment()
-
-
-class pyBluePrintSquaresShader(StrokeShader):
- def __init__(self, turns = 1, bb_len = 10):
- StrokeShader.__init__(self)
- self.__turns = turns
- self.__bb_len = bb_len
- def getName(self):
- return "pyBluePrintSquaresShader"
- def shade(self, stroke):
- p_min = Vector(10000, 10000)
- p_max = Vector(0, 0)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- p = it.getObject().getPoint()
- if (p.x < p_min.x):
- p_min.x = p.x
- if (p.x > p_max.x):
- p_max.x = p.x
- if (p.y < p_min.y):
- p_min.y = p.y
- if (p.y > p_max.y):
- p_max.y = p.y
- it.increment()
- stroke.Resample(32 * self.__turns)
- sv_nb = stroke.strokeVerticesSize()
-#######################################################
- sv_nb = sv_nb / self.__turns
- first = sv_nb / 4
- second = 2 * first
- third = 3 * first
- fourth = sv_nb
- vec_first = Vector(p_max.x - p_min.x + 2 * self.__bb_len, 0)
- vec_second = Vector(0, p_max.y - p_min.y + 2 * self.__bb_len)
- vec_third = vec_first * -1
- vec_fourth = vec_second * -1
- p_first = Vector(p_min.x - self.__bb_len, p_min.y)
- p_second = Vector(p_max.x, p_min.y - self.__bb_len)
- p_third = Vector(p_max.x + self.__bb_len, p_max.y)
- p_fourth = Vector(p_min.x, p_max.y + self.__bb_len)
-#######################################################
- it = stroke.strokeVerticesBegin()
- visible = 1
- for j in range(self.__turns):
- i = 0
- while i < sv_nb:
- if i < first:
- p_new = p_first + vec_first * float(i)/float(first - 1)
- if i == first - 1:
- visible = 0
- elif i < second:
- p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
- if i == second - 1:
- visible = 0
- elif i < third:
- p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
- if i == third - 1:
- visible = 0
- else:
- p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
- if i == fourth - 1:
- visible = 0
- it.getObject().setPoint(p_new)
- it.getObject().attribute().setVisible(visible)
- if visible == 0:
- visible = 1
- i = i + 1
- it.increment()
- while it.isEnd() == 0:
- stroke.RemoveVertex(it.getObject())
- it.increment()
-
-
-class pyBluePrintDirectedSquaresShader(StrokeShader):
- def __init__(self, turns = 1, bb_len = 10, mult = 1):
- StrokeShader.__init__(self)
- self.__mult = mult
- self.__turns = turns
- self.__bb_len = 1 + float(bb_len) / 100
- def getName(self):
- return "pyBluePrintDirectedSquaresShader"
- def shade(self, stroke):
- stroke.Resample(32 * self.__turns)
- p_mean = Vector(0, 0)
- p_min = Vector(10000, 10000)
- p_max = Vector(0, 0)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- p = it.getObject().getPoint()
- p_mean = p_mean + p
-## if (p.x < p_min.x):
-## p_min.x = p.x
-## if (p.x > p_max.x):
-## p_max.x = p.x
-## if (p.y < p_min.y):
-## p_min.y = p.y
-## if (p.y > p_max.y):
-## p_max.y = p.y
- it.increment()
- sv_nb = stroke.strokeVerticesSize()
- p_mean = p_mean / sv_nb
- p_var_xx = 0
- p_var_yy = 0
- p_var_xy = 0
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- p = it.getObject().getPoint()
- p_var_xx = p_var_xx + pow(p.x - p_mean.x, 2)
- p_var_yy = p_var_yy + pow(p.y - p_mean.y, 2)
- p_var_xy = p_var_xy + (p.x - p_mean.x) * (p.y - p_mean.y)
- it.increment()
- p_var_xx = p_var_xx / sv_nb
- p_var_yy = p_var_yy / sv_nb
- p_var_xy = p_var_xy / sv_nb
-## print p_var_xx, p_var_yy, p_var_xy
- trace = p_var_xx + p_var_yy
- det = p_var_xx * p_var_yy - p_var_xy * p_var_xy
- sqrt_coeff = sqrt(trace * trace - 4 * det)
- lambda1 = (trace + sqrt_coeff) / 2
- lambda2 = (trace - sqrt_coeff) / 2
-## print lambda1, lambda2
- theta = atan(2 * p_var_xy / (p_var_xx - p_var_yy)) / 2
-## print theta
- if p_var_yy > p_var_xx:
- e1 = Vector(cos(theta + pi / 2), sin(theta + pi / 2)) * sqrt(lambda1) * self.__mult
- e2 = Vector(cos(theta + pi), sin(theta + pi)) * sqrt(lambda2) * self.__mult
- else:
- e1 = Vector(cos(theta), sin(theta)) * sqrt(lambda1) * self.__mult
- e2 = Vector(cos(theta + pi / 2), sin(theta + pi / 2)) * sqrt(lambda2) * self.__mult
-#######################################################
- sv_nb = sv_nb / self.__turns
- first = sv_nb / 4
- second = 2 * first
- third = 3 * first
- fourth = sv_nb
- bb_len1 = self.__bb_len
- bb_len2 = 1 + (bb_len1 - 1) * sqrt(lambda1 / lambda2)
- p_first = p_mean - e1 - e2 * bb_len2
- p_second = p_mean - e1 * bb_len1 + e2
- p_third = p_mean + e1 + e2 * bb_len2
- p_fourth = p_mean + e1 * bb_len1 - e2
- vec_first = e2 * bb_len2 * 2
- vec_second = e1 * bb_len1 * 2
- vec_third = vec_first * -1
- vec_fourth = vec_second * -1
-#######################################################
- it = stroke.strokeVerticesBegin()
- visible = 1
- for j in range(self.__turns):
- i = 0
- while i < sv_nb:
- if i < first:
- p_new = p_first + vec_first * float(i)/float(first - 1)
- if i == first - 1:
- visible = 0
- elif i < second:
- p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
- if i == second - 1:
- visible = 0
- elif i < third:
- p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
- if i == third - 1:
- visible = 0
- else:
- p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
- if i == fourth - 1:
- visible = 0
- it.getObject().setPoint(p_new)
- it.getObject().attribute().setVisible(visible)
- if visible == 0:
- visible = 1
- i = i + 1
- it.increment()
- while it.isEnd() == 0:
- stroke.RemoveVertex(it.getObject())
- it.increment()
-
-class pyModulateAlphaShader(StrokeShader):
- def __init__(self, min = 0, max = 1):
- StrokeShader.__init__(self)
- self.__min = min
- self.__max = max
- def getName(self):
- return "pyModulateAlphaShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- alpha = it.getObject().attribute().getAlpha()
- p = it.getObject().getPoint()
- alpha = alpha * p.y / 400
- if alpha < self.__min:
- alpha = self.__min
- elif alpha > self.__max:
- alpha = self.__max
- it.getObject().attribute().setAlpha(alpha)
- it.increment()
-
-
-## various
-class pyDummyShader(StrokeShader):
- def getName(self):
- return "pyDummyShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- it_end = stroke.strokeVerticesEnd()
- while it.isEnd() == 0:
- toto = it.castToInterface0DIterator()
- att = it.getObject().attribute()
- att.setColor(0.3, 0.4, 0.4)
- att.setThickness(0, 5)
- it.increment()
-
-class pyDebugShader(StrokeShader):
- def getName(self):
- return "pyDebugShader"
-
- def shade(self, stroke):
- fe = GetSelectedFEdgeCF()
- id1=fe.vertexA().getId()
- id2=fe.vertexB().getId()
- #print id1.getFirst(), id1.getSecond()
- #print id2.getFirst(), id2.getSecond()
- it = stroke.strokeVerticesBegin()
- found = 0
- foundfirst = 0
- foundsecond = 0
- while it.isEnd() == 0:
- cp = it.getObject()
- if((cp.A().getId() == id1) or (cp.B().getId() == id1)):
- foundfirst = 1
- if((cp.A().getId() == id2) or (cp.B().getId() == id2)):
- foundsecond = 1
- if((foundfirst != 0) and (foundsecond != 0)):
- found = 1
- break
- it.increment()
- if(found != 0):
- print "The selected Stroke id is: ", stroke.getId().getFirst(), stroke.getId().getSecond()
-
diff --git a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
deleted file mode 100755
index 163c891fa90..00000000000
--- a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Filename : sketchy_multiple_parameterization.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Builds sketchy strokes whose topology relies on a
-# parameterization that covers the complete lines (visible+invisible)
-# whereas only the visible portions are actually drawn
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-## 0: don't restrict to selection
-Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,0))
-shaders_list = [
- SamplingShader(2),
- SpatialNoiseShader(15, 120, 2, 1, 1),
- IncreasingThicknessShader(5, 30),
- SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1),
- IncreasingColorShader(0,0.2,0,1,0.2,0.7,0.2,1),
- TextureAssignerShader(6),
- pyHLRShader()
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_broken.py b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
deleted file mode 100755
index 9cbb2725132..00000000000
--- a/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#
-# Filename : sketchy_topology_broken.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : The topology of the strokes is, first, built
-# independantly from the 3D topology of objects,
-# and, second, so as to chain several times the same ViewEdge.
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-## Backbone stretcher that leaves cusps intact to avoid cracks
-class pyBackboneStretcherNoCuspShader(StrokeShader):
- def __init__(self, l):
- StrokeShader.__init__(self)
- self._l = l
- def getName(self):
- return "pyBackboneStretcherNoCuspShader"
- def shade(self, stroke):
- it0 = stroke.strokeVerticesBegin()
- it1 = StrokeVertexIterator(it0)
- it1.increment()
- itn = stroke.strokeVerticesEnd()
- itn.decrement()
- itn_1 = StrokeVertexIterator(itn)
- itn_1.decrement()
- v0 = it0.getObject()
- v1 = it1.getObject()
- if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)):
- p0 = v0.getPoint()
- p1 = v1.getPoint()
- d1 = p0-p1
- d1.normalize()
- newFirst = p0+d1*float(self._l)
- v0.setPoint(newFirst)
- else:
- print "got a v0 cusp"
- vn_1 = itn_1.getObject()
- vn = itn.getObject()
- if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)):
- pn = vn.getPoint()
- pn_1 = vn_1.getPoint()
- dn = pn-pn_1
- dn.normalize()
- newLast = pn+dn*float(self._l)
- vn.setPoint(newLast)
- else:
- print "got a vn cusp"
-
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-## Chain 3 times each ViewEdge indpendantly from the
-## initial objects topology
-Operators.bidirectionalChain(pySketchyChainingIterator(3))
-shaders_list = [
- SamplingShader(4),
- SpatialNoiseShader(6, 120, 2, 1, 1),
- IncreasingThicknessShader(4, 10),
- SmoothingShader(100, 0.1, 0, 0.2, 0, 0, 0, 1),
- pyBackboneStretcherNoCuspShader(20),
- #ConstantColorShader(0.0,0.0,0.0)
- IncreasingColorShader(0.2,0.2,0.2,1,0.5,0.5,0.5,1),
- #IncreasingColorShader(1,0,0,1,0,1,0,1),
- TextureAssignerShader(4)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
deleted file mode 100755
index 85e11af38b9..00000000000
--- a/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Filename : sketchy_topology_preserved.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : The topology of the strokes is built
-# so as to chain several times the same ViewEdge.
-# The topology of the objects is preserved
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = QuantitativeInvisibilityUP1D(0)
-Operators.select(upred)
-Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,1))
-shaders_list = [
- SamplingShader(4),
- SpatialNoiseShader(20, 220, 2, 1, 1),
- IncreasingThicknessShader(4, 8),
- SmoothingShader(300, 0.05, 0, 0.2, 0, 0, 0, 0.5),
- ConstantColorShader(0.6,0.2,0.0),
- TextureAssignerShader(4),
- ]
-
-Operators.create(TrueUP1D(), shaders_list)
-
diff --git a/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
deleted file mode 100755
index 52cc10a9c60..00000000000
--- a/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Filename : split_at_highest_2d_curvature.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the visible lines (chaining follows same nature lines)
-# (most basic style module)
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU0D import *
-from PredicatesU1D import *
-from Functions0D import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-func = pyInverseCurvature2DAngleF0D()
-Operators.recursiveSplit(func, pyParameterUP0D(0.4,0.6), NotUP1D(pyHigherLengthUP1D(100)), 2)
-shaders_list = [ConstantThicknessShader(10), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)]
-Operators.create(TrueUP1D(), shaders_list)
-
diff --git a/release/scripts/freestyle/style_modules/split_at_tvertices.py b/release/scripts/freestyle/style_modules/split_at_tvertices.py
deleted file mode 100755
index 78f781dd290..00000000000
--- a/release/scripts/freestyle/style_modules/split_at_tvertices.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : split_at_tvertices.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws strokes that starts and stops at Tvertices (visible or not)
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesU0D import *
-from Functions0D import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-start = pyVertexNatureUP0D(Nature.T_VERTEX)
-## use the same predicate to decide where to start and where to stop
-## the strokes:
-Operators.sequentialSplit(start, start, 10)
-shaders_list = [ConstantThicknessShader(5), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)]
-Operators.create(TrueUP1D(), shaders_list)
-
diff --git a/release/scripts/freestyle/style_modules/stroke_texture.py b/release/scripts/freestyle/style_modules/stroke_texture.py
deleted file mode 100755
index afebbe30a90..00000000000
--- a/release/scripts/freestyle/style_modules/stroke_texture.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : stroke_texture.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader)
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-from ChainingIterators import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(3),
- BezierCurveShader(4),
- StrokeTextureShader("washbrushAlpha.bmp", Stroke.DRY_MEDIUM, 1),
- ConstantThicknessShader(40),
- ConstantColorShader(0,0,0,1),
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/suggestive.py b/release/scripts/freestyle/style_modules/suggestive.py
deleted file mode 100755
index 39d8515ed6c..00000000000
--- a/release/scripts/freestyle/style_modules/suggestive.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Filename : suggestive.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Draws the suggestive contours.
-# ***** The suggestive contours must be enabled
-# in the options dialog *****
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from PredicatesU1D import *
-from shaders import *
-
-upred = AndUP1D(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR), QuantitativeInvisibilityUP1D(0))
-Operators.select(upred)
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred))
-shaders_list = [
- IncreasingThicknessShader(1, 3),
- ConstantColorShader(0.2,0.2,0.2, 1)
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
deleted file mode 100755
index 21f6c7bdf35..00000000000
--- a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Filename : thickness_fof_depth_discontinuity.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Assigns to strokes a thickness that depends on the depth discontinuity
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-class pyDepthDiscontinuityThicknessShader(StrokeShader):
- def __init__(self, min, max):
- StrokeShader.__init__(self)
- self.__min = float(min)
- self.__max = float(max)
- self.__func = ZDiscontinuityF0D()
- def getName(self):
- return "pyDepthDiscontinuityThicknessShader"
- def shade(self, stroke):
- it = stroke.strokeVerticesBegin()
- z_min=0.0
- z_max=1.0
- a = (self.__max - self.__min)/(z_max-z_min)
- b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
- it = stroke.strokeVerticesBegin()
- while it.isEnd() == 0:
- z = self.__func(it.castToInterface0DIterator())
- thickness = a*z+b
- it.getObject().attribute().setThickness(thickness, thickness)
- it.increment()
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(1),
- ConstantThicknessShader(3),
- ConstantColorShader(0.0,0.0,0.0),
- pyDepthDiscontinuityThicknessShader(0.8, 6)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/tipremover.py b/release/scripts/freestyle/style_modules/tipremover.py
deleted file mode 100755
index 3e495b7d332..00000000000
--- a/release/scripts/freestyle/style_modules/tipremover.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : tipremover.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Removes strokes extremities
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from ChainingIterators import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- SamplingShader(5),
- ConstantThicknessShader(3),
- ConstantColorShader(0,0,0),
- TipRemoverShader(20)
- ]
-Operators.create(TrueUP1D(), shaders_list) \ No newline at end of file
diff --git a/release/scripts/freestyle/style_modules/tvertex_remover.py b/release/scripts/freestyle/style_modules/tvertex_remover.py
deleted file mode 100755
index c328f4c98ec..00000000000
--- a/release/scripts/freestyle/style_modules/tvertex_remover.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Filename : tvertex_remover.py
-# Author : Stephane Grabli
-# Date : 04/08/2005
-# Purpose : Removes TVertices
-#
-#############################################################################
-#
-# Copyright (C) : Please refer to the COPYRIGHT file distributed
-# with this source distribution.
-#
-# 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.
-#
-#############################################################################
-
-
-from freestyle_init import *
-from logical_operators import *
-from PredicatesB1D import *
-from shaders import *
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
-shaders_list = [
- IncreasingThicknessShader(3, 5),
- ConstantColorShader(0.2,0.2,0.2, 1),
- SamplingShader(10.0),
- pyTVertexRemoverShader()
- ]
-Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
deleted file mode 100755
index 4b1a8bef9df..00000000000
--- a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from freestyle_init import *
-from logical_operators import *
-from PredicatesU1D import *
-from PredicatesU0D import *
-from PredicatesB1D import *
-from Functions0D import *
-from Functions1D import *
-from shaders import *
-
-class pyDensityUP1D(UnaryPredicate1D):
- def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
- UnaryPredicate1D.__init__(self)
- self._wsize = wsize
- self._threshold = threshold
- self._integration = integration
- self._func = DensityF1D(self._wsize, self._integration, sampling)
-
- def getName(self):
- return "pyDensityUP1D"
-
- def __call__(self, inter):
- d = self._func(inter)
- print "For Chain ", inter.getId().getFirst(), inter.getId().getSecond(), "density is ", d
- if(d < self._threshold):
- return 1
- return 0
-
-Operators.select(QuantitativeInvisibilityUP1D(0))
-Operators.bidirectionalChain(ChainSilhouetteIterator())
-#Operators.sequentialSplit(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2)
-Operators.sort(pyZBP1D())
-shaders_list = [
- StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0),
- ConstantThicknessShader(3),
- SamplingShader(5.0),
- ConstantColorShader(0,0,0,1)
- ]
-Operators.create(pyDensityUP1D(2,0.05, IntegrationType.MEAN,4), shaders_list)
-#Operators.create(pyDensityFunctorUP1D(8,0.03, pyGetInverseProjectedZF1D(), 0,1, IntegrationType.MEAN), shaders_list)
-
diff --git a/release/scripts/freestyle/style_modules/vector.py b/release/scripts/freestyle/style_modules/vector.py
deleted file mode 100755
index 039f262546b..00000000000
--- a/release/scripts/freestyle/style_modules/vector.py
+++ /dev/null
@@ -1,241 +0,0 @@
-# This module defines 3d geometrical vectors with the standard
-# operations on them.
-#
-# Written by: Konrad Hinsen
-# Last revision: 1996-1-26
-#
-
-"""This module defines three-dimensional geometrical vectors. Vectors support
-the usual mathematical operations (v1, v2: vectors, s: scalar):
- v1+v2 addition
- v1-v2 subtraction
- v1*v2 scalar product
- s*v1 multiplication with a scalar
- v1/s division by a scalar
- v1.cross(v2) cross product
- v1.length() length
- v1.normal() normal vector in direction of v1
- v1.angle(v2) angle between two vectors
- v1.x(), v1[0] first element
- v1.y(), v1[1] second element
- v1.z(), v1[2] third element
-
-The module offers the following items for export:
- Vec3D(x,y,z) the constructor for vectors
- isVector(x) a type check function
- ex, ey, ez unit vectors along the x-, y-, and z-axes (predefined constants)
-
-Note: vector elements can be any kind of numbers on which the operations
-addition, subtraction, multiplication, division, comparison, sqrt, and acos
-are defined. Integer elements are treated as floating point elements.
-"""
-
-import math, types
-
-class Vec3:
-
- isVec3 = 1
-
- def __init__(self, x=0., y=0., z=0.):
- self.data = [x,y,z]
-
- def __repr__(self):
- return 'Vec3(%s,%s,%s)' % (`self.data[0]`,\
- `self.data[1]`,`self.data[2]`)
-
- def __str__(self):
- return `self.data`
-
- def __add__(self, other):
- return Vec3(self.data[0]+other.data[0],\
- self.data[1]+other.data[1],self.data[2]+other.data[2])
- __radd__ = __add__
-
- def __neg__(self):
- return Vec3(-self.data[0], -self.data[1], -self.data[2])
-
- def __sub__(self, other):
- return Vec3(self.data[0]-other.data[0],\
- self.data[1]-other.data[1],self.data[2]-other.data[2])
-
- def __rsub__(self, other):
- return Vec3(other.data[0]-self.data[0],\
- other.data[1]-self.data[1],other.data[2]-self.data[2])
-
- def __mul__(self, other):
- if isVec3(other):
- return reduce(lambda a,b: a+b,
- map(lambda a,b: a*b, self.data, other.data))
- else:
- return Vec3(self.data[0]*other, self.data[1]*other,
- self.data[2]*other)
-
- def __rmul__(self, other):
- if isVec3(other):
- return reduce(lambda a,b: a+b,
- map(lambda a,b: a*b, self.data, other.data))
- else:
- return Vec3(other*self.data[0], other*self.data[1],
- other*self.data[2])
-
- def __div__(self, other):
- if isVec3(other):
- raise TypeError, "Can't divide by a vector"
- else:
- return Vec3(_div(self.data[0],other), _div(self.data[1],other),
- _div(self.data[2],other))
-
- def __rdiv__(self, other):
- raise TypeError, "Can't divide by a vector"
-
- def __cmp__(self, other):
- return cmp(self.data[0],other.data[0]) \
- or cmp(self.data[1],other.data[1]) \
- or cmp(self.data[2],other.data[2])
-
- def __getitem__(self, index):
- return self.data[index]
-
- def x(self):
- return self.data[0]
- def y(self):
- return self.data[1]
- def z(self):
- return self.data[2]
-
- def length(self):
- return math.sqrt(self*self)
-
- def normal(self):
- len = self.length()
- if len == 0:
- raise ZeroDivisionError, "Can't normalize a zero-length vector"
- return self/len
-
- def cross(self, other):
- if not isVec3(other):
- raise TypeError, "Cross product with non-vector"
- return Vec3(self.data[1]*other.data[2]-self.data[2]*other.data[1],
- self.data[2]*other.data[0]-self.data[0]*other.data[2],
- self.data[0]*other.data[1]-self.data[1]*other.data[0])
-
- def angle(self, other):
- if not isVec3(other):
- raise TypeError, "Angle between vector and non-vector"
- cosa = (self*other)/(self.length()*other.length())
- cosa = max(-1.,min(1.,cosa))
- return math.acos(cosa)
-
-
-class Vec2:
-
- isVec2 = 1
-
- def __init__(self, x=0., y=0.):
- self.data = [x,y]
-
- def __repr__(self):
- return 'Vec2(%s,%s,%s)' % (`self.data[0]`,\
- `self.data[1]`)
-
- def __str__(self):
- return `self.data`
-
- def __add__(self, other):
- return Vec2(self.data[0]+other.data[0],\
- self.data[1]+other.data[1])
- __radd__ = __add__
-
- def __neg__(self):
- return Vec2(-self.data[0], -self.data[1])
-
- def __sub__(self, other):
- return Vec2(self.data[0]-other.data[0],\
- self.data[1]-other.data[1])
-
- def __rsub__(self, other):
- return Vec2(other.data[0]-self.data[0],\
- other.data[1]-self.data[1])
-
- def __mul__(self, other):
- if isVec2(other):
- return reduce(lambda a,b: a+b,
- map(lambda a,b: a*b, self.data, other.data))
- else:
- return Vec2(self.data[0]*other, self.data[1]*other)
-
- def __rmul__(self, other):
- if isVec2(other):
- return reduce(lambda a,b: a+b,
- map(lambda a,b: a*b, self.data, other.data))
- else:
- return Vec2(other*self.data[0], other*self.data[1])
-
- def __div__(self, other):
- if isVec2(other):
- raise TypeError, "Can't divide by a vector"
- else:
- return Vec2(_div(self.data[0],other), _div(self.data[1],other))
-
- def __rdiv__(self, other):
- raise TypeError, "Can't divide by a vector"
-
- def __cmp__(self, other):
- return cmp(self.data[0],other.data[0]) \
- or cmp(self.data[1],other.data[1])
-
- def __getitem__(self, index):
- return self.data[index]
-
- def x(self):
- return self.data[0]
- def y(self):
- return self.data[1]
-
- def length(self):
- return math.sqrt(self*self)
-
- def normal(self):
- len = self.length()
- if len == 0:
- raise ZeroDivisionError, "Can't normalize a zero-length vector"
- return self/len
-
- #def cross(self, other):
-# if not isVec2(other):
-# raise TypeError, "Cross product with non-vector"
-# return Vec2(self.data[1]*other.data[2]-self.data[2]*other.data[1],
-# self.data[2]*other.data[0]-self.data[0]*other.data[2],
-# self.data[0]*other.data[1]-self.data[1]*other.data[0])
-
- def angle(self, other):
- if not isVec2(other):
- raise TypeError, "Angle between vector and non-vector"
- cosa = (self*other)/(self.length()*other.length())
- cosa = max(-1.,min(1.,cosa))
- return math.acos(cosa)
-
-
-
-# Type check
-
-def isVec3(x):
- return hasattr(x,'isVec3')
-
-def isVec2(x):
- return hasattr(x,'isVec2')
-
-# "Correct" division for arbitrary number types
-
-def _div(a,b):
- if type(a) == types.IntType and type(b) == types.IntType:
- return float(a)/float(b)
- else:
- return a/b
-
-
-# Some useful constants
-
-ex = Vec3(1.,0.,0.)
-ey = Vec3(0.,1.,0.)
-ez = Vec3(0.,0.,1.)
diff --git a/release/scripts/help_bpy_api.py b/release/scripts/help_bpy_api.py
index 484663b32b3..e8d77ed8452 100644
--- a/release/scripts/help_bpy_api.py
+++ b/release/scripts/help_bpy_api.py
@@ -1,17 +1,17 @@
#!BPY
"""
Name: 'Blender/Python Scripting API'
-Blender: 244
+Blender: 248
Group: 'Help'
Tooltip: 'The Blender Python API reference manual'
"""
__author__ = "Matt Ebb"
__url__ = ("blender", "blenderartist")
-__version__ = "1.0"
+__version__ = "1.0.1"
__bpydoc__ = """\
This script opens the user's default web browser at http://www.blender.org's
-"Blenders Python API" page.
+"Blender Python API Reference" page.
"""
# --------------------------------------------------------------------------
@@ -36,6 +36,12 @@ This script opens the user's default web browser at http://www.blender.org's
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
-import Blender, webbrowser
-version = str(int(Blender.Get('version')))
-webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/index.html')
+import Blender
+try: import webbrowser
+except: webbrowser = None
+
+if webbrowser:
+ version = str(int(Blender.Get('version')))
+ webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/')
+else:
+ Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py
index b27e266f368..c207a12068f 100644
--- a/release/scripts/help_browser.py
+++ b/release/scripts/help_browser.py
@@ -8,7 +8,7 @@ Tooltip: 'Show help information about a chosen installed script.'
"""
__author__ = "Willian P. Germano"
-__version__ = "0.1 11/02/04"
+__version__ = "0.3 01/21/09"
__email__ = ('scripts', 'Author, wgermano:ig*com*br')
__url__ = ('blender', 'blenderartists.org')
@@ -47,8 +47,6 @@ Hotkeys:<br>
# $Id$
#
# --------------------------------------------------------------------------
-# sysinfo.py version 0.1 Jun 09, 2004
-# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
@@ -69,6 +67,9 @@ Hotkeys:<br>
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
+# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation)
+# for the "run" button; Jean-Michel Soler for pointing a parsing error
+# with multilines using triple single quotes.
import Blender
from Blender import sys as bsys, Draw, Window, Registry
@@ -355,7 +356,12 @@ def parse_pyobj(var, lines, i):
l = "ERROR"
elif l[0] == "'":
- if l[-1] == '\\':
+ if l[1:3] == "''": # '''
+ if l.find("'''", 3) < 0: # multiline
+ l2, i = parse_pyobj_close("'''", lines, i)
+ if l[-1] == '\\': l = l[:-1]
+ l = "%s%s" % (l, l2)
+ elif l[-1] == '\\':
l2, i = parse_pyobj_close("'", lines, i)
l = "%s%s" % (l, l2)
elif l[-1] == "'" and l[-2] != '\\': # single line: '...'
@@ -543,6 +549,7 @@ BEVT_GMENU = range(100, len_gmenus + 100)
BEVT_VIEWSOURCE = 1
BEVT_EXIT = 2
BEVT_BACK = 3
+BEVT_EXEC = 4 # Executes Script
# gui callbacks:
@@ -551,7 +558,7 @@ def gui(): # drawing the screen
global SCREEN, START_SCREEN, SCRIPT_SCREEN
global SCRIPT_INFO, AllGroups, GROUP_MENUS
global BEVT_EMAIL, BEVT_LINK
- global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU
+ global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC
global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE
theme = Theme.Get()[0]
@@ -674,8 +681,11 @@ def gui(): # drawing the screen
'View this script\'s source code in the Text Editor (hotkey: S)')
Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh,
'Exit from Scripts Help Browser (hotkey: Q)')
- if not FMODE: Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh,
+ if not FMODE:
+ Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh,
'Back to scripts selection screen (hotkey: ESC)')
+ Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script')
+
BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
BGL.glRasterPos2i(x, 5)
Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small')
@@ -766,6 +776,14 @@ def button_event(evt): # gui button events
SCRIPT_INFO = None
SCROLL_DOWN = 0
Draw.Redraw()
+ elif evt == BEVT_EXEC: # Execute script
+ exec_line = ''
+ if SCRIPT_INFO.script.userdir:
+ exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname)
+ else:
+ exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname)
+
+ Blender.Run(exec_line)
keepon = True
FMODE = False # called by Blender.ShowHelp(name) API function ?
diff --git a/release/scripts/help_getting_started.py b/release/scripts/help_getting_started.py
deleted file mode 100644
index 81b002da4e4..00000000000
--- a/release/scripts/help_getting_started.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!BPY
-"""
-Name: 'Getting Started'
-Blender: 234
-Group: 'Help'
-Tooltip: 'Help for new users'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"Getting Started" page.
-"""
-
-# $Id$
-#
-# --------------------------------------------------------------------------
-# Getting Started Help Menu Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import Blender, webbrowser
-version = str(Blender.Get('version'))
-webbrowser.open('http://www.blender3d.org/Help/?pg=GettingStarted&ver=' + version)
diff --git a/release/scripts/help_manual.py b/release/scripts/help_manual.py
deleted file mode 100644
index cf293bf7c2c..00000000000
--- a/release/scripts/help_manual.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!BPY
-"""
-Name: 'Manual'
-Blender: 234
-Group: 'Help'
-Tooltip: 'The Blender reference manual'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"Blender Manual" page.
-"""
-
-# --------------------------------------------------------------------------
-# Manual Help Menu Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import Blender, webbrowser
-version = str(Blender.Get('version'))
-webbrowser.open('http://www.blender3d.org/Help/?pg=Manual&ver=' + version)
diff --git a/release/scripts/help_release_notes.py b/release/scripts/help_release_notes.py
deleted file mode 100644
index af7a7042489..00000000000
--- a/release/scripts/help_release_notes.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!BPY
-"""
-Name: 'Release Notes'
-Blender: 234
-Group: 'Help'
-Tooltip: 'Information about the changes in this version of Blender'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"Release Notes" page.
-"""
-
-# --------------------------------------------------------------------------
-# Release Notes Help Menu Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import Blender, webbrowser
-version = str(Blender.Get('version'))
-webbrowser.open('http://www.blender3d.org/Help/?pg=ReleaseNotes&ver=' + version)
diff --git a/release/scripts/help_tutorials.py b/release/scripts/help_tutorials.py
deleted file mode 100644
index 04d6c799455..00000000000
--- a/release/scripts/help_tutorials.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!BPY
-
-"""
-Name: 'Tutorials'
-Blender: 234
-Group: 'Help'
-Tooltip: 'Tutorials for learning to use Blender'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"Blender Tutorials" page.
-"""
-
-# --------------------------------------------------------------------------
-# Tutorials Help Menu Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import Blender, webbrowser
-version = str(Blender.Get('version'))
-webbrowser.open('http://www.blender3d.org/Help/?pg=Tutorials&ver=' + version)
diff --git a/release/scripts/help_web_devcomm.py b/release/scripts/help_web_devcomm.py
deleted file mode 100644
index 344622cc113..00000000000
--- a/release/scripts/help_web_devcomm.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!BPY
-
-"""
-Name: 'Developer Community'
-Blender: 234
-Group: 'HelpWebsites'
-Tooltip: 'Get involved with Blender development'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender.org, the
-Blender development portal.
-"""
-
-# --------------------------------------------------------------------------
-# Blender Website Help Menu -> Websites Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import webbrowser
-webbrowser.open('http://www.blender.org')
diff --git a/release/scripts/help_web_eshop.py b/release/scripts/help_web_eshop.py
deleted file mode 100644
index 451fd735150..00000000000
--- a/release/scripts/help_web_eshop.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!BPY
-
-"""
-Name: 'Blender E-Shop'
-Blender: 234
-Group: 'HelpWebsites'
-Tooltip: 'Buy official Blender resources and merchandise online'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"E-Shop" section.
-"""
-
-# --------------------------------------------------------------------------
-# Blender Website Help Menu -> Websites Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import Blender, webbrowser
-webbrowser.open('http://www.blender3d.org/e-shop')
diff --git a/release/scripts/help_web_usercomm.py b/release/scripts/help_web_usercomm.py
deleted file mode 100644
index fbe19956eb7..00000000000
--- a/release/scripts/help_web_usercomm.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!BPY
-
-"""
-Name: 'User Community'
-Blender: 234
-Group: 'HelpWebsites'
-Tooltip: 'Get involved with other Blender users'
-"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at www.blender3d.org's
-"User Community" page.
-"""
-
-# --------------------------------------------------------------------------
-# Blender Website Help Menu -> Websites Item
-# --------------------------------------------------------------------------
-# ***** 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 *****
-# --------------------------------------------------------------------------
-
-import webbrowser
-webbrowser.open('http://www.blender3d.org/Community')
diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py
new file mode 100644
index 00000000000..16d0805256b
--- /dev/null
+++ b/release/scripts/image_2d_cutout.py
@@ -0,0 +1,559 @@
+#!BPY
+
+"""
+Name: '2D Cutout Image Importer'
+Blender: 249
+Group: 'Image'
+Tooltip: 'Batch UV Map images to Planes'
+"""
+
+__author__ = "Kevin Morgan (forTe)"
+__url__ = ("Home page, http://gamulabs.freepgs.com")
+__version__ = "1.2.1"
+__bpydoc__ = """\
+This Script will take an image and
+UV map it to a plane sharing the same width to height ratio as the image.
+Import options allow for the image to be a still or sequence type image
+<br><br>
+Imports can be single images or whole directories of images depending on the chosen
+option.
+"""
+
+####################################################
+#Copyright (C) 2008: Kevin Morgan
+####################################################
+#-------------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 hopes 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>.
+####################################################
+####################################################
+#V1.0
+#Basic Functionality
+#Published June 28, 2007
+####################################################
+#V1.1
+#Added Support for enabling viewport transparency
+#Added more options to the UI for materials
+#Added Proportionality code (Pixels per unit)
+#Added GPL License Block
+#Published June 29, 2007
+####################################################
+#V1.2
+#Added Support for Copying Existing Materials
+#Import Images as Sequences
+#Refreshed GUI - now with more clutter :(
+#Miscellaneous and Housekeeping
+#Published June 16, 2008
+####################################################
+#V1.2.1
+#Added Extend Texture Mode option at request of a user
+#Published September 24, 2008
+####################################################
+
+import Blender
+from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window
+from Blender.Mathutils import *
+import bpy
+
+# Global Constants
+DIR = 0
+SINGLE = 1
+CUROFFS = 0
+
+# GUI CONSTANTS
+NO_EVT = 0
+SINGLE_IMG = 1
+DIRECTORY_IMG = 2
+CLR_PATH = 3
+CHG_EXT = 4
+EXIT = 5
+DO_SCRIPT = 6
+
+VERSIONSTRING = '1.2.1'
+
+# Note the two parameter dicts could be combined, I just, liked them seperate...
+# GUI Buttons Dict
+GUIPARAMS = {
+ 'Path': Draw.Create(''),
+ 'ImageExt': Draw.Create(''),
+ 'Seq': Draw.Create(0),
+ 'PackImage': Draw.Create(0),
+ 'PPU': Draw.Create(50),
+ 'VPTransp': Draw.Create(1),
+ 'XOff': Draw.Create(0.0),
+ 'YOff': Draw.Create(0.0),
+ 'ZOff': Draw.Create(0.0),
+ 'CopyMat': Draw.Create(0),
+ 'MatId': Draw.Create(0),
+ 'MatCol': Draw.Create(1.0, 0.0, 0.0),
+ 'Ref': Draw.Create(0.8),
+ 'Spec': Draw.Create(0.5),
+ 'Hard': Draw.Create(50),
+ 'Alpha': Draw.Create(1.0),
+ 'ZTransp': Draw.Create(1),
+ 'Shadeless': Draw.Create(0),
+ 'TexChan': Draw.Create(1),
+ 'MPTCol': Draw.Create(1),
+ 'MPTAlpha': Draw.Create(1),
+ 'UseAlpha': Draw.Create(1),
+ 'CalcAlpha': Draw.Create(0),
+ 'ExtendMode': Draw.Create(0),
+ 'AutoRefresh': Draw.Create(0),
+ 'Cyclic': Draw.Create(0),
+ 'Frames': Draw.Create(100),
+ 'Offs': Draw.Create(0),
+ 'StartFr': Draw.Create(1),
+ 'RedrawImp': Draw.Create(0)
+}
+
+# Script Execution Paramaters
+PARAMS = {
+ 'ImagePaths': [], # Path to images to import
+ 'ImportType': SINGLE, # Import a Directory or a Single Image?
+ 'ImageProp': Image.Sources.STILL, # What sources for the image, still or sequence
+ 'PackImage': 0, # Pack the Image(s)?
+ 'PPU': 20, # Pixels Per Blender Unit
+ 'MakeTransp': 1, # Make face transparent in viewport
+
+ 'NewMat': 1, # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes
+ 'MaterialId': 0, # ID to take from the Materials list upon copy
+ 'Materials': None, # Materials in Scene
+ 'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1},
+
+ 'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties
+ 'TexChannel': 0, # Texture Channel
+ 'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha
+ 'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1},
+ 'ObOffset': Vector(1, 0, 0) # Offset by this vector upon creation for multifile import
+}
+
+# Get the Active Scene, of course
+scn = bpy.data.scenes.active
+
+##########################################
+# MAIN SCRIPT FUNCTIONS
+##########################################
+
+def imgImport(imgPath):
+ global CUROFFS, PARAMS
+ ######################################
+ # Load the image
+ ######################################
+ try:
+ img = Image.Load(imgPath)
+ imgDimensions = img.getSize() # do this to ensure the data is available
+ except:
+ Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"')
+ return
+
+ if PARAMS['PackImage']:
+ img.pack()
+ name = Blender.sys.makename(imgPath, strip = 1)
+
+ ######################################
+ # Construct the mesh
+ ######################################
+
+ me = Mesh.New(name)
+
+ # Calculate Dimensions from Image Size
+ dim = [float(i)/PARAMS['PPU'] for i in imgDimensions]
+ v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]]
+ me.verts.extend(v)
+ me.faces.extend([0, 1, 2, 3])
+
+ me.faces[0].image = img
+ me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
+
+ if PARAMS['MakeTransp']:
+ me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
+
+ ######################################
+ # Modify the Material
+ ######################################
+
+ mat = None
+ if not PARAMS['NewMat']:
+ mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__()
+ mat.setName(name)
+ else:
+ mat = Material.New(name)
+ properties = PARAMS['MatProps']
+ mat.setRGBCol(properties['Col'])
+ mat.setRef(properties['Ref'])
+ mat.setSpec(properties['Spec'])
+ mat.setHardness(properties['Hard'])
+ mat.setAlpha(properties['Alpha'])
+
+ if properties['Shadeless']:
+ mat.mode |= Material.Modes.SHADELESS
+ if properties['ZTransp']:
+ mat.mode |= Material.Modes.ZTRANSP
+
+ properties = PARAMS['TexProps']
+
+ tex = Texture.New(name)
+ tex.setType('Image')
+ tex.setImage(img)
+ if properties['UseAlpha']:
+ tex.useAlpha = Texture.ImageFlags.USEALPHA
+
+ if properties['CalcAlpha']:
+ tex.calcAlpha = Texture.ImageFlags.CALCALPHA
+
+ if properties['ExtendMode']:
+ tex.setExtend('Extend')
+
+ if PARAMS['ImageProp'] == Image.Sources.SEQUENCE:
+ properties = PARAMS['SeqProps']
+
+ img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize()
+
+ tex.animStart = properties['StartFr']
+ tex.animOffset = properties['Offs']
+ tex.animFrames = properties['Frames']
+ tex.autoRefresh = properties['AutoRefresh']
+ tex.cyclic = properties['Cyclic']
+
+ texMapSetters = Texture.TexCo.UV
+
+ # PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work
+ texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha']
+
+ mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters)
+ me.materials += [mat]
+
+ ######################################
+ # Object Construction
+ ######################################
+
+ ob = scn.objects.new(me, name)
+ p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it
+ ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p)
+
+ return
+
+def translateParams():
+ # Translates (or assigns for the most part) GUI values to those that can be read by the
+ # Import Function
+
+ global GUIPARAMS, PARAMS
+
+ if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR:
+ PARAMS['ImageProp'] = Image.Sources.SEQUENCE
+
+ PARAMS['PackImage'] = GUIPARAMS['PackImage'].val
+ PARAMS['PPU'] = GUIPARAMS['PPU'].val
+ PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val
+ PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val)
+
+ PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val
+ PARAMS['MaterialId'] = GUIPARAMS['MatId'].val
+ PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val)
+ PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val
+ PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val
+ PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val
+ PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val
+ PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val
+ PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val
+
+ PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10
+ PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val
+ PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val
+ PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val
+ PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val
+ PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val
+
+ PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val
+ PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val
+ PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val
+ PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val
+ PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val
+ return
+
+def doScript():
+ # Main script Function
+ # Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
+
+ global CUROFFS
+
+ translateParams()
+
+ total = len(PARAMS['ImagePaths'])
+ broken = 0
+
+ if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
+ for i, path in enumerate(PARAMS['ImagePaths']):
+ CUROFFS = i # Could be passed to the import Function, but I chose a global instead
+ Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
+ imgImport(path)
+ Blender.Redraw()
+ if Blender.Get('version') >= 246:
+ if Window.TestBreak():
+ broken = 1
+ break
+ else:
+ for i, path in enumerate(PARAMS['ImagePaths']):
+ CUROFFS = i
+ Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
+ imgImport(path)
+ if Blender.Get('version') >= 246:
+ if Window.TestBreak():
+ broken = 1
+ break
+
+ if broken:
+ Window.DrawProgressBar(1.0, "Script Execution Aborted")
+ else:
+ Window.DrawProgressBar(1.0, "Finished Importing")
+
+ Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
+
+ return
+
+##########################################
+# PATH SETTERS AND CHANGERS
+##########################################
+
+def setSinglePath(filename):
+ global GUIPARAMS, PARAMS
+ GUIPARAMS['Path'].val = filename
+ PARAMS['ImagePaths'] = [filename]
+ return
+
+def setDirPath(filename):
+ global GUIPARAMS, PARAMS
+
+ try:
+ import os
+ except:
+ Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+ Draw.Exit()
+ return
+
+ path = os.path.dirname(filename) # Blender.sys.dirname fails on '/'
+ GUIPARAMS['Path'].val = path
+
+ ext_lower = GUIPARAMS['ImageExt'].val.lower()
+ for f in os.listdir(path):
+ if f.lower().endswith(ext_lower):
+ PARAMS['ImagePaths'].append(os.path.join(path, f))
+
+ return
+
+def changeExtension():
+ global GUIPARAMS, PARAMS
+
+ if PARAMS['ImportType'] == SINGLE:
+ return
+
+ try:
+ import os
+ except:
+ Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+ Draw.Exit()
+ return
+
+ PARAMS['ImagePaths'] = []
+
+ ext_lower = GUIPARAMS['ImageExt'].val.lower()
+ for f in os.listdir(GUIPARAMS['Path'].val):
+ if f.lower().endswith(ext_lower):
+ PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f))
+
+ return
+
+##########################################
+# INTERFACE FUNCTIONS
+##########################################
+def compileMaterialList():
+ # Pretty straight forward, just grabs the materials in the blend file and constructs
+ # an appropriate string for use as a menu
+
+ mats = [mat for mat in bpy.data.materials]
+ PARAMS['Materials'] = mats
+ title = 'Materials%t|'
+ menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)]
+ return title + ''.join(menStrs)
+
+def event(evt, val):
+ # Disabled, since Esc is often used from the file browser
+ #if evt == Draw.ESCKEY:
+ # Draw.Exit()
+
+ return
+
+def bevent(evt):
+ global GUIPARAMS, PARAMS
+
+ if evt == NO_EVT:
+ Draw.Redraw()
+
+ elif evt == SINGLE_IMG:
+ Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//'))
+ Draw.Redraw()
+ PARAMS['ImportType'] = SINGLE
+
+ elif evt == DIRECTORY_IMG:
+ Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//'))
+ Draw.Redraw()
+ PARAMS['ImportType'] = DIR
+
+ elif evt == CLR_PATH:
+ GUIPARAMS['Path'].val = ''
+ PARAMS['ImagePaths'] = []
+ GUIPARAMS['ImageExt'].val = ''
+ Draw.Redraw()
+
+ elif evt == CHG_EXT:
+ changeExtension()
+ Draw.Redraw()
+
+ elif evt == EXIT:
+ Draw.Exit()
+
+ elif evt == DO_SCRIPT:
+ doScript()
+
+ else:
+ print "ERROR: UNEXPECTED BUTTON EVENT"
+
+ return
+
+# GUI Colors ######
+ScreenColor = [0.7, 0.7, 0.7]
+BackgroundColor = [0.8, 0.8, 0.8]
+TitleBG = [0.6, 0.6, 0.6]
+TitleCol = [1.0, 1.0, 1.0]
+ErrCol = [1.0, 0.0, 0.0]
+TextCol = [0.4, 0.4, 0.5]
+###################
+
+def GUI():
+ global GUIPARAMS, PARAMS
+
+ BGL.glClearColor(*(ScreenColor + [1.0]))
+ BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+
+ minx = 5
+ maxx = 500
+ miny = 5
+ maxy = 450
+
+ lineheight = 24
+ buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them
+
+ lP = 5 # Left Padding
+ rP = 5 # Right Padding
+
+ # Draw Background Box
+ BGL.glColor3f(*BackgroundColor)
+ BGL.glRecti(minx, miny, maxx, maxy)
+
+ # Draw Title
+ BGL.glColor3f(*TitleBG)
+ BGL.glRecti(minx, maxy - (lineheight), maxx, maxy)
+ BGL.glColor3f(*TitleCol)
+
+ title = "2D Cutout Image Importer v" + VERSIONSTRING
+ BGL.glRasterPos2i(minx + lP, maxy - 15)
+ Draw.Text(title, 'large')
+
+ Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script")
+
+ # Path Buttons
+ if GUIPARAMS['Path'].val == '':
+ Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import")
+ Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import")
+
+ else:
+ Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options")
+
+ GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From')
+ if PARAMS['ImportType'] == DIR:
+ GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19, GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)')
+ GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File')
+
+ # Geometry and Viewport Options
+ BGL.glColor3f(*TextCol)
+ BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1)
+ BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3)
+ Draw.Text('Geometry and Display Options', 'small')
+
+ GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations')
+ GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight), (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport')
+
+ GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images')
+ GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images')
+ GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images')
+
+ # Material and Texture Options
+ BGL.glColor3f(*TextCol)
+ BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1)
+ BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3)
+ Draw.Text('Material and Texture Options', 'small')
+
+ half = (maxx-minx-lP-rP)/2
+ GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material')
+ if GUIPARAMS['CopyMat'].val:
+ menStr = compileMaterialList()
+ GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From')
+ else:
+ GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material')
+ GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials')
+ GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials')
+ GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials')
+ GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials')
+
+ GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency')
+ GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless')
+
+ GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture')
+
+ GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel')
+ GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel')
+
+ third = int((maxx-minx-lP-rP)/6)
+ GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values")
+ GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values")
+ GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used")
+ GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still')
+
+ if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR:
+ GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh')
+ GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`')
+
+ GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use')
+ GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation')
+ GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie')
+ elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR:
+ BGL.glColor3f(*ErrCol)
+ BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5)
+ Draw.Text('Sequence only available for Single Image Import', 'small')
+
+ # Import Options
+ BGL.glColor3f(*TextCol)
+ BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1)
+ BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3)
+ Draw.Text('Import', 'small')
+
+ if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE:
+ Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)")
+ else:
+ BGL.glColor3f(*ErrCol)
+ BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5)
+ Draw.Text('A path and image type must be specified to import images')
+
+ GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import')
+
+Draw.Register(GUI, event, bevent) \ No newline at end of file
diff --git a/release/scripts/image_auto_layout.py b/release/scripts/image_auto_layout.py
index 19ee396c3b1..d19ba1da662 100644
--- a/release/scripts/image_auto_layout.py
+++ b/release/scripts/image_auto_layout.py
@@ -9,7 +9,7 @@ Tooltip: 'Pack all texture images into 1 image and remap faces.'
__author__ = "Campbell Barton"
__url__ = ("blender", "blenderartists.org")
-__version__ = "1.1 2007/02/15"
+__version__ = "1.1a 2009/04/01"
__bpydoc__ = """\
This script makes a new image from the used areas of all the images mapped to the selected mesh objects.
@@ -265,18 +265,22 @@ def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PR
render_context.setRenderWinSize(100)
render_context.setImageType(Render.PNG)
render_context.enableExtensions(True)
- render_context.enableSky() # No alpha needed.
- render_context.enableRGBColor()
+ render_context.enablePremultiply() # No alpha needed.
+ render_context.enableRGBAColor()
render_context.threads = 2
#Render.EnableDispView() # Broken??
# New Mesh and Object
render_mat= B.Material.New()
- render_mat.mode |= B.Material.Modes.SHADELESS
- render_mat.mode |= B.Material.Modes.TEXFACE
-
+ render_mat.mode |= \
+ B.Material.Modes.SHADELESS | \
+ B.Material.Modes.TEXFACE | \
+ B.Material.Modes.TEXFACE_ALPHA | \
+ B.Material.Modes.ZTRANSP
+ render_mat.setAlpha(0.0)
+
render_me= B.Mesh.New()
render_me.verts.extend([Vector(0,0,0)]) # Stupid, dummy vert, preverts errors. when assigning UV's/
render_ob= B.Object.New('Mesh')
@@ -419,7 +423,7 @@ def main():
PREF_IMAGE_PATH= PREF_IMAGE_PATH.val
PREF_IMAGE_SIZE= PREF_IMAGE_SIZE.val
- PREF_IMAGE_MARGIN= PREF_IMAGE_MARGIN.val
+ PREF_IMAGE_MARGIN= float(PREF_IMAGE_MARGIN.val) # important this is a float otherwise division wont work properly
PREF_KEEP_ASPECT= PREF_KEEP_ASPECT.val
PREF_ALL_SEL_OBS= PREF_ALL_SEL_OBS.val
diff --git a/release/scripts/image_edit.py b/release/scripts/image_edit.py
index a7132a4f986..cae40b74097 100644
--- a/release/scripts/image_edit.py
+++ b/release/scripts/image_edit.py
@@ -1,6 +1,6 @@
#!BPY
"""
-Name: 'Edit Externaly'
+Name: 'Edit Externally'
Blender: 242a
Group: 'Image'
Tooltip: 'Open in an application for editing. (hold Shift to configure)'
@@ -9,22 +9,23 @@ Tooltip: 'Open in an application for editing. (hold Shift to configure)'
__author__ = "Campbell Barton"
__url__ = ["blender", "blenderartists.org"]
__version__ = "1.0"
-
__bpydoc__ = """\
This script opens the current image in an external application for editing.
-Useage:
+Usage:
Choose an image for editing in the UV/Image view.
-To configure the application to open the image with, hold Shift as you click on
-this menu item.
+To configure the application to open the image with, hold Shift as you
+click on this menu item.
-For first time users try running the default application for your operating system.
-If the application does not open you can type in the full path.
-You can choose that the last entered application will be saved as a default.
+For first time users try running the default application for your
+operating system. If the application does not open you can type in
+the full path. You can choose that the last entered application will
+be saved as a default.
-* Note, default commants for opening an image are "start" for win32 and "open" for macos.
-This will use the system default assosiated application.
+* Note, default commants for opening an image are "start" for win32
+and "open" for macos. This will use the system default associated
+application.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
@@ -48,17 +49,36 @@ This will use the system default assosiated application.
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
+import Blender
+from Blender import Image, sys, Draw, Registry
try:
- import os
+ import subprocess
import sys as py_sys
platform = py_sys.platform
except:
- Draw.PupMenu('Error, python not installed')
- os=None
+ Draw.PupMenu('Error: Recent version of Python not installed.')
+ subprocess=None
-import Blender
-from Blender import Image, sys, Draw, Registry
+def os_run(appstring, filename):
+ '''
+ Run the app, take into account different python versions etc
+ looks like python 2.6 wants a list for
+ '''
+
+ # evil trick, temp replace spaces so we can allow spaces in filenames
+ # also allows multiple instances of %f
+ appstring = appstring.replace(' ', '\t')
+ appstring = appstring.replace('%f', filename)
+ appstring = appstring.split('\t')
+
+ print ' '.join(appstring)
+
+ try: # only python 2.6 wants a list?
+ p = subprocess.Popen(appstring)
+ except:
+ p = subprocess.Popen(' '.join(appstring))
+
def edit_extern(image=None):
@@ -66,7 +86,7 @@ def edit_extern(image=None):
image = Image.GetCurrent()
if not image: # Image is None
- Draw.PupMenu('ERROR: You must select an active Image.')
+ Draw.PupMenu('ERROR: Please select active Image.')
return
if image.packed:
Draw.PupMenu('ERROR: Image is packed, unpack before editing.')
@@ -94,16 +114,19 @@ def edit_extern(image=None):
if new_text:
pupblock.append('first time, set path.')
if platform == 'win32':
- appstring = 'start "" /B "%f"'
+ # Example of path to popular image editor... ;-)
+ # appstring = '"C:\\Program Files\\Adobe\\Photoshop CS\\photoshop.exe" "%f"'
+ # Have to add "cmd /c" to make sure we're using Windows shell.
+ appstring = 'cmd /c start "" /B "%f"'
elif platform == 'darwin':
appstring = 'open "%f"'
else:
- appstring = 'gimp-remote "%f"'
+ appstring = 'gimp %f'
appstring_but = Draw.Create(appstring)
save_default_but = Draw.Create(0)
- pupblock.append(('editor: ', appstring_but, 0, 48, 'Path to application, %f will be replaced with the image path.'))
+ pupblock.append(('editor: ', appstring_but, 0, 99, 'Path to application, %f will be replaced with the image path.'))
pupblock.append(('Set Default', save_default_but, 'Store this path in the blender registry.'))
# Only configure if Shift is held,
@@ -118,19 +141,18 @@ def edit_extern(image=None):
Registry.SetKey('ExternalImageEditor', {'path':appstring}, True)
if appstring.find('%f') == -1:
- Draw.PupMenu('ERROR: The comment you entered did not contain the filename ("%f")')
+ Draw.PupMenu('ERROR: No filename specified! ("%f")')
return
# -------------------------------
- appstring = appstring.replace('%f', imageFileName)
- print '\tediting image with command "%s"' % appstring
- os.system(appstring)
+ os_run(appstring, imageFileName)
+
def main():
edit_extern()
-if __name__ == '__main__' and os != None:
- main() \ No newline at end of file
+if __name__ == '__main__' and subprocess:
+ main()
diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py
index bb0119a9a81..b3bee11c464 100644
--- a/release/scripts/import_dxf.py
+++ b/release/scripts/import_dxf.py
@@ -1,21 +1,22 @@
#!BPY
"""
-Name: 'Autodesk DXF (.dxf)'
-Blender: 246
+Name: 'Autodesk DXF (.dxf .dwg)'
+Blender: 249
Group: 'Import'
-Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).'
+Tooltip: 'Import for DWG/DXF geometry data.'
"""
__author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)'
-__version__ = '1.12 - 2008.08.03 by migius'
+__version__ = '1.12 - 2009.06.16 by migius'
__url__ = ["http://blenderartists.org/forum/showthread.php?t=84319",
"http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"]
__email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"]
__bpydoc__ = """\
-This script imports objects from DXF (2d/3d) into Blender.
+This script imports objects from DWG/DXF (2d/3d) into Blender.
This script imports 2d and 3d geometery from DXF files.
-Supported DXF format versions: from (r2.5) r12 up to 2008.
+It supports DWG format too, with help of an external converter.
+Supported DXF format versions: from (r2.5) r12 up to r2008.
Enhanced features are:
- configurable object filtering and geometry manipulation,
- configurable material pre-processing,
@@ -32,7 +33,7 @@ MINSERT (=array of blocks),
CIRCLE,
ARC,
3DFACE,
-2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline),
+2d-POLYLINE (=in plane, incl. arc, variable-width, curve, spline),
3d-POLYLINE (=non-plane),
3d-POLYMESH,
3d-POLYFACE,
@@ -43,8 +44,8 @@ Supported DXF>r12 objects:
ELLIPSE,
LWPOLYLINE (LightWeight Polyline),
SPLINE,
-(wip v1.13) MLINE,
-(wip v1.13) MTEXT
+(todo v1.13) MLINE,
+(todo v1.13) MTEXT
Unsupported objects:
DXF r12: DIMENSION.
@@ -57,7 +58,7 @@ Supported layout modes:
"model space" is default,
"paper space" as option (= "layout views")
-Supported scene definition objescts produced with AVE_RENDER:
+Supported scene definition objects produced with AVE_RENDER:
scene: selection of lights assigned to the camera,
lights: DIRECT, OVERHEAD, SH_SPOT,
(wip v1.13 import of AVE_RENDER material definitions)
@@ -73,7 +74,7 @@ thickness,
width,
color,
layer,
-(wip v1.13: XDATA, grouped status)
+(todo v1.13: XDATA, grouped status)
It is recommended to use DXF-object properties for assign Blender materials.
Notes:
@@ -88,7 +89,7 @@ in creating new objects in scene database - probably a database management probl
"""
History:
- v1.0 - 2007/2008 by migius
+ v1.0 - 2007/2008/2009 by migius
planned tasks:
-- (to see more, search for "--todo--" in script code)
-- command-line-mode/batch-mode
@@ -99,7 +100,7 @@ History:
-- better support for long dxf-layer-names
-- add configuration file.ini handles multiple material setups
-- added f_layerFilter
- -- to-check: obj/mat/group/_mapping-idea from ideasman42:
+ -- to-check: obj/mat/group/_mapping-idea from ideasman42
-- curves: added "fill/non-fill" option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs
-- "normalize Z" option to correct non-planar figures
-- LINEs need "width" in 3d-space incl vGroups
@@ -107,10 +108,26 @@ History:
-- add better support for color_index BYLAYER=256, BYBLOCK=0
-- bug: "oneMesh" produces irregularly errors
-- bug: Registry recall from hd_cache ?? only win32 bug??
- -- support DXF-definitions of scene, lights and cameras
+ -- support DXF-definitions of autoshade: scene, lights and cameras
-- support ortho mode for VIEWs and VPORTs as cameras
-
+ v1.12 - 2009.06.16 by migius
+ d7 fix for ignored BLOCKs (e.g. *X) which are members of other BLOCKs
+ v1.12 - 2009.05.27 by migius
+ d6 bugfix negative scaled INSERTs - isLeftHand(Matrix) check
+ v1.12 - 2009.05.26 by migius
+ d5 changed to the new 2.49 method Vector.cross()
+ d5 bugfix WORLDY(1,1,0) to (0,1,0)
+ v1.12 - 2009.04.11 by migius
+ d4 added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter
+ v1.12 - 2009.03.14 by migius
+ d3 removed all set()functions (problem with osx/python<2.4 reported by Blinkozo)
+ d3 code-cleaning
+ v1.12 - 2009.01.14 by migius
+ d2 temp patch for noname BLOCKS (*X,*U,*D)
+ v1.12 - 2008.11.16 by migius
+ d1 remove try_finally: cause not supported in python <2.5
+ d1 add Bezier curves bevel radius support (default 1.0)
v1.12 - 2008.08.03 by migius
c2 warningfix: relocating of globals: layersmap, oblist
c2 modif UI: buttons newScene+targetLayer moved to start panel
@@ -146,7 +163,7 @@ History:
a4 added to analyzeTool: report about VIEWs, VPORTs, unused/xref BLOCKs
a4 bugfix: individual support for 2D/3DPOLYLINE/POLYMESH
a4 added to UI: (*wip)BLOCK-(F): name filtering for BLOCKs
- a4 added to UI: BLOCK-(n): filter anoname/hatch BLOCKs *X...
+ a4 added to UI: BLOCK-(n): filter noname/hatch BLOCKs *X...
a2 g_scale_as is no more GUI_A-variable
a2 bugfix "material": negative sign color_index
a2 added support for BLOCKs defined with origin !=(0,0,0)
@@ -297,21 +314,31 @@ History:
# --------------------------------------------------------------------------
import Blender
-from Blender import *
+from Blender import Mathutils, BezTriple, Draw, Registry, sys,\
+Text3d, Window, Mesh, Material, Group, Curve
#from Blender.Mathutils import Vector, Matrix
-import bpy
+#import bpy #not used yet
#import BPyMessages
from dxfReader import readDXF
#from dxfReader import get_name, get_layer
from dxfReader import Object as dxfObject
from dxfColorMap import color_map
-
-from math import *
-
-try:
- import os
- if os.name:# != 'mac':
+from math import log10, sqrt, radians, degrees, atan, cos, sin
+
+# osx-patch by Blinkozo
+#todo: avoid additional modules, prefer Blender-build-in test routines
+#import platform
+#if platform.python_version() < '2.4':
+# from sets import Set as set
+#from sys import version_info
+#ver = '%s.%s' % version_info[0:2]
+# end osx-patch
+
+import subprocess
+import os
+if os.name != 'mac':
+ try:
import psyco
psyco.log(Blender.Get('tempdir')+"/blender.log-psyco")
#psyco.log()
@@ -319,18 +346,15 @@ try:
psyco.profile(0.05, memory=100)
psyco.profile(0.2)
#print 'psyco imported'
-except ImportError:
- #print 'psyco not imported'
- pass
-
-#try: Curve.orderU
+ except ImportError:
+ print 'psyco not imported'
print '\n\n\n'
-print 'DXF-Importer v%s *** start ***' %(__version__) #---------------------
+print 'DXF/DWG-Importer v%s *** start ***' %(__version__) #---------------------
SCENE = None
WORLDX = Mathutils.Vector((1,0,0))
-WORLDY = Mathutils.Vector((1,1,0))
+WORLDY = Mathutils.Vector((0,1,0))
WORLDZ = Mathutils.Vector((0,0,1))
G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data
@@ -346,7 +370,7 @@ THIN_RESOLUTION = 8 #(4-64) thin_cylinder arc_resolution - number of segments
MIN_THICK = MIN_DIST * 10.0 #minimal thickness by forced thickness
MIN_WIDTH = MIN_DIST * 10.0 #minimal width by forced width
TRIM_LIMIT = 3.0 #limit for triming of polylines-wide-segments (values:0.0 - 5.0)
-ELEVATION = 0.0 #standard elevation = coordinate Z
+ELEVATION = 0.0 #standard elevation = coordinate Z value
BYBLOCK = 0
BYLAYER = 256
@@ -355,7 +379,7 @@ GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-
LAYER_DEF_NAME = 'AAAA' #default layer name
LAYER_DEF_COLOR = 4 #default layer color
E_M = 0
-LAB = "*) parts under construction"
+LAB = ". wip .. todo" #"*) parts under construction"
M_OBJ = 0
FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE)
@@ -370,6 +394,42 @@ FREE = BezTriple.HandleTypes.FREE
VECT = BezTriple.HandleTypes.VECT
ALIGN = BezTriple.HandleTypes.ALIGN
+UI_MODE = True #activates UI-popup-print, if not multiple files imported
+
+#---- migration to 2.49-------------------------------------------------
+if 'cross' in dir(Mathutils.Vector()):
+ #Draw.PupMenu('DXF exporter: Abort%t|This script version works for Blender up 2.49 only!')
+ def M_CrossVecs(v1,v2):
+ return v1.cross(v2) #for up2.49
+ def M_DotVecs(v1,v2):
+ return v1.dot(v2) #for up2.49
+else:
+ def M_CrossVecs(v1,v2):
+ return Mathutils.CrossVecs(v1,v2) #for pre2.49
+ def M_DotVecs(v1,v2):
+ return Mathutils.DotVecs(v1,v2) #for pre2.49
+
+
+#-------- DWG support ------------------------------------------
+extCONV_OK = True
+extCONV = 'DConvertCon.exe'
+extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV)
+if not os.path.isfile(extCONV_PATH):
+ extCONV_OK = False
+ extCONV_TEXT = 'DWG-Importer cant find external DWG-converter (%s) in Blender script directory.|\
+More details in online Help.' %extCONV
+else:
+ if not os.sys.platform.startswith('win'):
+ # check if Wine installed:
+ if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip():
+ extCONV_PATH = 'wine %s'%extCONV_PATH
+ else:
+ extCONV_OK = False
+ extCONV_TEXT = 'The external DWG-converter (%s) needs Wine installed on your system.|\
+More details in online Help.' %extCONV
+#print 'extCONV_PATH = ', extCONV_PATH
+
+
class View: #-----------------------------------------------------------------
"""Class for objects representing dxf VIEWs.
@@ -738,7 +798,7 @@ class Solid: #-----------------------------------------------------------------
if settings.var['vGroup_on'] and not M_OBJ:
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
- replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.ADD/REPLACE
+ replace = Mesh.AssignModes.ADD #or .AssignModes.ADD/REPLACE
if vg_left: me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace)
if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
if vg_top: me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace)
@@ -817,6 +877,7 @@ class Line: #-----------------------------------------------------------------
curve.append(BezTriple.New(points[1]))
for point in curve:
point.handleTypes = [VECT, VECT]
+ point.radius = 1.0
curve.flagU = 0 # 0 sets the curve not cyclic=open
c.setResolu(settings.var['curve_res'])
c.update() #important for handles calculation
@@ -882,7 +943,7 @@ class Line: #-----------------------------------------------------------------
ob.link(me) # link mesh to that object
vG_name = 'color_%s' %self.color_index
if edges: faces = edges
- replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD
+ replace = Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD
try:
me.assignVertsToGroup(vG_name, faces[0], 1.0, replace)
#print 'deb: existed vGroup:', vG_name #---------------------
@@ -946,7 +1007,7 @@ class Point: #-----------------------------------------------------------------
if thic < settings.var['dist_min']: thic = settings.var['dist_min']
if points_as in [1,3,4,5]:
- if True: # points_as in [1,5]: # as 'empty'
+ if points_as in [1,5]: # as 'empty'
c = 'Empty'
elif points_as == 3: # as 'thin sphere'
res = settings.var['thin_res']
@@ -1272,66 +1333,6 @@ class Polyline: #--------------------------------------------------------------
pline = Curve.New(obname) # create new curve data
#pline.setResolu(24) #--todo-----
- if False: #old self.spline: # NURBSplines-----OK-----
- #print 'deb:polyline2dCurve.draw self.spline!' #---------------
- weight1 = 0.5
- weight2 = 1.0
- if self.curvQuadrati:
- # Bezier-curve form simulated in NURBS-curve
- # generate middlepoints except start/end-segments ---
- #print 'deb:polyline2dCurve.draw extraQBspline!' #---------------
- temp_points = []
- point = d_points[0].loc
- point.append(weight1)
- temp_points.append(point)
- for i in xrange(1,len(d_points)-2):
- point1 = d_points[i].loc
- point2 = d_points[i+1].loc
- mpoint = list((Mathutils.Vector(point1) + Mathutils.Vector(point2)) * 0.5)
- mpoint.append(weight2)
- point1.append(weight1)
- temp_points.append(point1)
- temp_points.append(mpoint)
- point2.append(weight1)
- temp_points.append(point2)
- point = d_points[-1].loc
- point.append(weight1)
- temp_points.append(point)
- d_points = temp_points
- else:
- temp_points = []
- for d in d_points:
- d = d.loc
- d.append(weight1)
- temp_points.append(d)
- d_points = temp_points
-
- if not self.closed:
- # generate extended startpoint and endpoint------
- point1 = Mathutils.Vector(d_points[0][:3])
- point2 = Mathutils.Vector(d_points[1][:3])
- startpoint = list(point1 - point2 + point1)
- startpoint.append(weight1)
- point1 = Mathutils.Vector(d_points[-1][:3])
- point2 = Mathutils.Vector(d_points[-2][:3])
- endpoint = list(point1 - point2 + point1)
- endpoint.append(weight1)
- temp_points = []
- temp_points.append(startpoint)
- temp_points.extend(d_points)
- d_points = temp_points
- d_points.append(endpoint)
-
- point = d_points[0]
- curve = pline.appendNurb(point)
- curve.setType(4) #NURBS curve
- for point in d_points[1:]:
- curve.append(point)
- if self.closed:
- curve.flagU = 1 # Set curve cyclic=close
- else:
- curve.flagU = 0 # Set curve not cyclic=open
-
if self.spline: # NURBSplines-----OK-----
#print 'deb:polyline2dCurve.draw self.spline!' #---------------
nurbs_points = []
@@ -1341,9 +1342,11 @@ class Polyline: #--------------------------------------------------------------
nurbs_points.append(pkt)
firstpoint = nurbs_points[0]
curve = pline.appendNurb(firstpoint)
- curve.setType(4) # set curvetype NURBS
+ curve.setType(4) # set curve_type NURBS
+ print 'deb: dir(curve):', dir(curve[-1]) #----------------
for point in nurbs_points[1:]:
curve.append(point)
+ #TODO: what is the trick for bevel radius? curve[-1].radius = 1.0
if self.closed:
curve.flagU = 1+0 # Set curve cyclic=close and uni
else:
@@ -1352,20 +1355,6 @@ class Polyline: #--------------------------------------------------------------
except AttributeError: pass
#print 'deb: dir(curve):', dir(curve) #----------------
- elif False: #orig self.curved: #--Bezier-curves---OK-------
- #print 'deb:polyline2dCurve.draw self.curved!' #---------------
- curve = pline.appendNurb(BezTriple.New(d_points[0]))
- for p in d_points[1:]:
- curve.append(BezTriple.New(p))
- for point in curve:
- point.handleTypes = [AUTO, AUTO]
- if self.closed:
- curve.flagU = 1 # Set curve cyclic=close
- else:
- curve.flagU = 0 # Set curve not cyclic=open
- curve[0].handleTypes = [FREE, ALIGN] #remi--todo-----
- curve[-1].handleTypes = [ALIGN, FREE] #remi--todo-----
-
elif self.curved: #--SPLINE as Bezier-curves---wip------
#print 'deb:polyline2dCurve.draw self.curved!' #---------------
begtangent, endtangent = None, None
@@ -1380,6 +1369,7 @@ class Polyline: #--------------------------------------------------------------
curve.append(BezTriple.New(p))
for point in curve:
point.handleTypes = [AUTO, AUTO]
+ point.radius = 1.0
#curve.setType(1) #Bezier curve
if self.closed:
curve.flagU = 5 #1 # Set curve cyclic=close
@@ -1392,6 +1382,7 @@ class Polyline: #--------------------------------------------------------------
p0h1 = [p0h1[i]+begtangent[i] for i in range(3)]
curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2))
curve[0].handleTypes = [FREE, ALIGN] #remi--todo-----
+ curve[0].radius = 1.0
if endtangent:
#print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #-----
#print 'deb:polyline2dCurve.draw endtangent:', endtangent #-----
@@ -1401,6 +1392,7 @@ class Polyline: #--------------------------------------------------------------
curve.__setitem__(-1,BezTriple.New(p0h1+p0+p0h2))
#print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #-----
curve[-1].handleTypes = [ALIGN, FREE] #remi--todo-----
+ curve[-1].radius = 1.0
@@ -1414,61 +1406,48 @@ class Polyline: #--------------------------------------------------------------
for i in xrange(len(d_points)):
point1 = d_points[i]
#point2 = d_points[i+1]
- if False: #-----outdated!- standard calculation ----------------------------------
- if point1.bulge and (i < len(d_points)-2 or self.closed):
- verts, center = calcBulge(point1, point2, arc_res, triples=False)
- if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0]))
- else: curve.append(BezTriple.New(verts[0]))
- curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents
- for p in verts[1:]:
- curve.append(BezTriple.New(p))
- curve[-1].handleTypes = [AUTO, AUTO]
+ #----- optimised Bezier-Handles calculation --------------------------------
+ #print 'deb:drawPlineCurve: i:', i #---------
+ if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed):
+ if i == len(d_points)-1: point2 = d_points[0]
+ else: point2 = d_points[i+1]
+
+
+ # calculate additional points for bulge
+ VectorTriples = calcBulge(point1, point2, arc_res, triples=True)
+
+ if prevHandleType == FREE:
+ #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
+ VectorTriples[0][:3] = prevHandleVect
+ #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
+
+ if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0]))
+ else: curve.append(BezTriple.New(VectorTriples[0]))
+ curve[-1].handleTypes = [prevHandleType, FREE]
+ curve[-1].radius = 1.0
+
+ for p in VectorTriples[1:-1]:
+ curve.append(BezTriple.New(p))
+ curve[-1].handleTypes = [FREE, FREE]
+ curve[-1].radius = 1.0
+
+ prevHandleVect = VectorTriples[-1][:3]
+ prevHandleType = FREE
+ #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #---------
+ else:
+ #print 'deb:drawPlineCurve: else' #----------
+ if prevHandleType == FREE:
+ VectorTriples = prevHandleVect + list(point1) + list(point1)
+ #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #---------
+ curve.append(BezTriple.New(VectorTriples))
+ curve[-1].handleTypes = [FREE, VECT]
+ prevHandleType = VECT
+ curve[-1].radius = 1.0
else:
if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc))
else: curve.append(BezTriple.New(point1.loc))
- curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents
-
- elif True: #----- optimised Bezier-Handles calculation --------------------------------
- #print 'deb:drawPlineCurve: i:', i #---------
- if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed):
- if i == len(d_points)-1: point2 = d_points[0]
- else: point2 = d_points[i+1]
-
-
- # calculate additional points for bulge
- VectorTriples = calcBulge(point1, point2, arc_res, triples=True)
-
- if prevHandleType == FREE:
- #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
- VectorTriples[0][:3] = prevHandleVect
- #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #---------
-
- if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0]))
- else: curve.append(BezTriple.New(VectorTriples[0]))
- curve[-1].handleTypes = [prevHandleType, FREE]
-
- for p in VectorTriples[1:-1]:
- curve.append(BezTriple.New(p))
- curve[-1].handleTypes = [FREE, FREE]
-
- prevHandleVect = VectorTriples[-1][:3]
- prevHandleType = FREE
- #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #---------
- else:
- #print 'deb:drawPlineCurve: else' #----------
- if prevHandleType == FREE:
- VectorTriples = prevHandleVect + list(point1) + list(point1)
- #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #---------
- curve.append(BezTriple.New(VectorTriples))
- curve[-1].handleTypes = [FREE, VECT]
- prevHandleType = VECT
- else:
- if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc))
- else: curve.append(BezTriple.New(point1.loc))
- curve[-1].handleTypes = [VECT, VECT]
-
-
-
+ curve[-1].handleTypes = [VECT, VECT]
+ curve[-1].radius = 1.0
#print 'deb:drawPlineCurve: curve[-1].vec[0]', curve[-1].vec[0] #----------
if self.closed:
@@ -1486,10 +1465,12 @@ class Polyline: #--------------------------------------------------------------
curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2))
curve[0].handleTypes = [FREE,prevHandleType2]
+ curve[0].radius = 1.0
#print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #----------
#print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #----------
else:
curve[0].handleTypes[0] = VECT
+ curve[0].radius = 1.0
else:
curve.flagU = 0 # Set curve not cyclic=open
@@ -1565,23 +1546,6 @@ class Polyline: #--------------------------------------------------------------
d_points = self.doubles_out(settings, d_points)
#print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------
- """# routine to sort out of "double.vertices" ------------------------------------
- minimal_dist = settings.var['dist_min'] * 0.1
- temp_points = []
- for i in xrange(len(d_points)-1):
- point = d_points[i]
- point2 = d_points[i+1]
- #print 'deb:double.vertex p1,p2', point, point2 #------------------------
- delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc)
- if delta.length > minimal_dist:
- temp_points.append(point)
- #else: print 'deb:drawPoly2d double.vertex sort out!' #------------------------
- temp_points.append(d_points[-1]) #------ incl. last vertex -------------
- #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex -------------
- d_points = temp_points #-----vertex.list without "double.vertices"
- #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------
- """
-
#print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------
if len(d_points) < 2: #if too few vertex, then return
#print 'deb:drawPoly2d corrupted Vertices' #---------
@@ -1777,29 +1741,6 @@ class Polyline: #--------------------------------------------------------------
# clean corner intersection
pointsLc.append(cornerpointL)
pointsRc.append(cornerpointR)
- elif False: # the standard no-intersection
- # --todo-- not optimal, because produces X-face
- pointsLc.extend((pointsLe[i],pointsLs[i+1]))
- pointsRc.extend((pointsRe[i],pointsRs[i+1]))
- elif False: # --todo-- the optimised non-intersection
- if (cornerpointL - vecL1).length < (cornerpointR - vecR1).length:
- left_angle = True
- else:
- left_angle = False
- limit_dist = settings.var['dist_min']
- if left_angle: # if left turning angle
- #print 'deb:drawPoly2d it is left turning angle' #-------------
- # to avoid triangelface/doubleVertex
- delta1 = (cornerpointL - vecL1).normalize() * limit_dist
- delta4 = (cornerpointL - vecL4).normalize() * limit_dist
- pointsLc.extend((cornerpointL - delta1, cornerpointL - delta4))
- pointsRc.extend((pointsRe[i],pointsRs[i+1]))
- else: # if right turning angle
- #print 'deb:drawPoly2d right turning angle' #-------------
- delta1 = (cornerpointR - vecR1).normalize() * limit_dist
- delta4 = (cornerpointR - vecR4).normalize() * limit_dist
- pointsRc.extend((cornerpointR - delta1, cornerpointR - delta4))
- pointsLc.extend((pointsLe[i],pointsLs[i+1]))
else:
pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1]))
pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1]))
@@ -1836,14 +1777,10 @@ class Polyline: #--------------------------------------------------------------
vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1]
if bulg_points[i] != None:
#compute left- and right-cornerpoints
- if True:
- cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4)
- cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4)
- pointsLc.append(cornerpointL[0])
- pointsRc.append(cornerpointR[0])
- else:
- pointVec = Mathutils.Vector(point[i])
-
+ cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4)
+ cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4)
+ pointsLc.append(cornerpointL[0])
+ pointsRc.append(cornerpointR[0])
else: # IF non-bulg
pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1]))
pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1]))
@@ -1899,27 +1836,26 @@ class Polyline: #--------------------------------------------------------------
# which may be linked to more than one object.
if settings.var['vGroup_on'] and not M_OBJ:
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
- replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD
+ replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD
vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
for v in f_left: vg_left.extend(v)
for v in f_right: vg_right.extend(v)
for v in f_top: vg_top.extend(v)
for v in f_bottom: vg_bottom.extend(v)
- me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace)
- me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace)
- me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace)
- me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
+ me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace)
+ me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
+ me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace)
+ me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace)
if not self.closed:
me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace)
me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace)
if settings.var['meshSmooth_on']: # left and right side become smooth ----------------------
#if self.spline or self.curved:
- if True:
- smooth_len = len(f_left) + len(f_right)
- for i in xrange(smooth_len):
- me.faces[i].smooth = True
- #me.Modes(AUTOSMOOTH)
+ smooth_len = len(f_left) + len(f_right)
+ for i in xrange(smooth_len):
+ me.faces[i].smooth = True
+ #me.Modes(AUTOSMOOTH)
# 2.level:IF width, but no-thickness ---------------------
else:
@@ -1958,10 +1894,9 @@ class Polyline: #--------------------------------------------------------------
if settings.var['meshSmooth_on']: # left and right side become smooth ----------------------
#if self.spline or self.curved:
- if True:
- for i in xrange(len(faces)):
- me.faces[i].smooth = True
- #me.Modes(AUTOSMOOTH)
+ for i in xrange(len(faces)):
+ me.faces[i].smooth = True
+ #me.Modes(AUTOSMOOTH)
# 1.level:IF no-width and no-thickness ---------------------
else:
@@ -2177,9 +2112,10 @@ DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entr
self.ctrlpk_len = getit(obj, 73, 0) # Number of control points
self.fit_pk_len = getit(obj, 74, 0) # Number of fit points (if any)
+ #TODO: import SPLINE as Bezier curve directly, possible?
#print 'deb:Spline self.fit_pk_len=', self.fit_pk_len #------------------------
#self.fit_pk_len = 0 # temp for debug
- if self.fit_pk_len and 'spline_as'==5:
+ if self.fit_pk_len and settings.var['splines_as']==5:
self.spline = False
self.curved = True
else:
@@ -2318,7 +2254,6 @@ class LWpolyline(Polyline): #--------------------------------------------------
self.spline = False
self.curved = False
-
#print 'deb:LWpolyline.obj.data:\n', obj.data #------------------------
#print 'deb:LWpolyline.ENDinit:----------------' #------------------------
@@ -2664,36 +2599,17 @@ class Circle: #----------------------------------------------------------------
cyl_rad = 0.5 * settings.var['width_min']
if settings.var['lines_as'] == 5: # draw CIRCLE as curve -------------
- if True: # universal version
- arc_res = settings.var['curve_arc']
- #arc_res = 3
- start, end = 0.0, 360.0
- VectorTriples = calcArc(None, radius, start, end, arc_res, True)
- c = Curve.New(obname) # create new curve data
- curve = c.appendNurb(BezTriple.New(VectorTriples[0]))
- for p in VectorTriples[1:-1]:
- curve.append(BezTriple.New(p))
- for point in curve:
- point.handleTypes = [FREE, FREE]
- else: # standard version
- c = Curve.New(obname) # create new curve data
- p1 = (0, -radius, 0)
- p2 = (radius, 0, 0)
- p3 = (0, radius, 0)
- p4 = (-radius, 0, 0)
-
- p1 = BezTriple.New(p1)
- p2 = BezTriple.New(p2)
- p3 = BezTriple.New(p3)
- p4 = BezTriple.New(p4)
-
- curve = c.appendNurb(p1)
- curve.append(p2)
- curve.append(p3)
- curve.append(p4)
- for point in curve:
- point.handleTypes = [AUTO, AUTO]
-
+ arc_res = settings.var['curve_arc']
+ #arc_res = 3
+ start, end = 0.0, 360.0
+ VectorTriples = calcArc(None, radius, start, end, arc_res, True)
+ c = Curve.New(obname) # create new curve data
+ curve = c.appendNurb(BezTriple.New(VectorTriples[0]))
+ for p in VectorTriples[1:-1]:
+ curve.append(BezTriple.New(p))
+ for point in curve:
+ point.handleTypes = [FREE, FREE]
+ point.radius = 1.0
curve.flagU = 1 # 1 sets the curve cyclic=closed
if settings.var['fill_on']:
c.setFlag(6) # 2+4 set top and button caps
@@ -2715,24 +2631,6 @@ class Circle: #----------------------------------------------------------------
ob.SizeZ *= abs(thic)
return ob
- elif False: # create a new mesh_object with buildin_circle_primitive
- verts_num = settings.var['arc_res'] * sqrt(radius / settings.var['arc_rad'])
- if verts_num > 100: verts_num = 100 # Blender accepts only values [3:500]
- if verts_num < 4: verts_num = 4 # Blender accepts only values [3:500]
- if thic != 0:
- loc2 = thic * 0.5 #-----blenderAPI draw Cylinder with 2*thickness
- self.loc[2] += loc2 #---new location for the basis of cylinder
- #print 'deb:circleDraw:self.loc2:', self.loc #-----------------------
- c = Mesh.Primitives.Cylinder(int(verts_num), radius*2, abs(thic))
- else:
- c = Mesh.Primitives.Circle(int(verts_num), radius*2)
-
- #c.update()
- ob = SCENE.objects.new(c, obname) # create a new circle_mesh_object
- ob.loc = tuple(self.loc)
- transform(self.extrusion, 0, ob)
- return ob
-
else: # draw CIRCLE as mesh -----------------------------------------------
if M_OBJ: obname, me, ob = makeNewObject()
else:
@@ -2785,15 +2683,16 @@ class Circle: #----------------------------------------------------------------
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
if settings.var['vGroup_on'] and not M_OBJ:
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
- replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD
+ replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD
vg_band, vg_top, vg_bottom = [], [], []
for v in f_band: vg_band.extend(v)
- me.addVertGroup('side.band') ; me.assignVertsToGroup('side.band', list(set(vg_band)), 1.0, replace)
+ me.addVertGroup('side.band') ; me.assignVertsToGroup('side.band', vg_band, 1.0, replace)
+
if settings.var['fill_on']:
for v in f_top: vg_top.extend(v)
for v in f_bottom: vg_bottom.extend(v)
- me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace)
- me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
+ me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace)
+ me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace)
else: # if thic == 0
if settings.var['fill_on']:
@@ -2893,6 +2792,7 @@ class Arc: #-----------------------------------------------------------------
curve.append(BezTriple.New(p))
for point in curve:
point.handleTypes = [FREE, FREE]
+ point.radius = 1.0
curve.flagU = 0 # 0 sets the curve not cyclic=open
arc.setResolu(settings.var['curve_res'])
@@ -2963,16 +2863,16 @@ class Arc: #-----------------------------------------------------------------
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
if settings.var['vGroup_on'] and not M_OBJ:
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
- replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD
+ replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD
vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
for v in f_left: vg_left.extend(v)
for v in f_right: vg_right.extend(v)
for v in f_top: vg_top.extend(v)
for v in f_bottom: vg_bottom.extend(v)
- me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace)
- me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace)
- me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace)
- me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
+ me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace)
+ me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
+ me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace)
+ me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace)
me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace)
me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace)
@@ -3224,8 +3124,6 @@ class Insert: #----------------------------------------------------------------
if a_data.key == 'SCENE': # define set of lights as blender group
scene_lights = 1
- elif False: # define set of lights as blender group
- scene_lights = 1
return
elif name == 'ave_global':
if settings.var['lights_on']: #if lights support activated
@@ -3386,35 +3284,12 @@ class Ellipse: #---------------------------------------------------------------
obname = obname[:MAX_NAMELENGTH]
center = self.loc
- if True:
- start = degrees(self.start_angle)
- end = degrees(self.end_angle)
- if abs(end - 360.0) < 0.00001: end = 360.0
- ellipse_closed = False
- if end - start == 360.0: ellipse_closed = True
+ start = degrees(self.start_angle)
+ end = degrees(self.end_angle)
+ if abs(end - 360.0) < 0.00001: end = 360.0
+ ellipse_closed = False
+ if end - start == 360.0: ellipse_closed = True
- else: # bug in AutoCAD_2002 dxf-exporter into r12 for ELLIPSE->POLYLINE_ARC
- #print 'deb:calcEllipse---------:\n start=%s\n end=%s' %(self.start_angle, self.end_angle) #---------
- if self.start_angle > pi+pi: self.start_angle %= pi+pi
- if self.end_angle > pi+pi: self.end_angle %= pi+pi
- if abs(self.end_angle - pi - pi) < 0.00001: self.end_angle = pi + pi
- ellipse_closed = False
- if abs(self.end_angle - self.start_angle) == pi + pi: ellipse_closed = True
- test = self.start_angle % pi
- if test < 0.001 or pi - test < 0.001: start = self.start_angle
- else:
- start = atan(tan(self.start_angle) * self.ratio)
- if start < 0.0: start += pi
- if self.start_angle > pi: start += pi
- test = self.end_angle % pi
- if test < 0.001 or pi - test < 0.001: end = self.end_angle
- else:
- end = atan(tan(self.end_angle) * self.ratio)
- if end < 0.0: end += pi
- if self.end_angle > pi: end += pi
- start = degrees(start)
- end = degrees(end)
-
# rotation = Angle between major and WORLDX
# doesnt work, couse produces always positive value: rotation = Mathutils.AngleBetweenVecs(major, WORLDX)
if self.major[0] == 0:
@@ -3449,6 +3324,7 @@ class Ellipse: #---------------------------------------------------------------
curve.append(BezTriple.New(p))
for point in curve:
point.handleTypes = [FREE, FREE]
+ point.radius = 1.0
curve.flagU = 1 # 0 sets the curve not cyclic=open
if settings.var['fill_on']:
arc.setFlag(6) # 2+4 set top and button caps
@@ -3459,6 +3335,7 @@ class Ellipse: #---------------------------------------------------------------
curve.append(BezTriple.New(p))
for point in curve:
point.handleTypes = [FREE, FREE]
+ point.radius = 1.0
curve.flagU = 0 # 0 sets the curve not cyclic=open
arc.setResolu(settings.var['curve_res'])
@@ -3487,8 +3364,6 @@ class Ellipse: #---------------------------------------------------------------
verts = calcArc(None, radius, start, end, arc_res, False)
#verts = [list(point) for point in verts]
- if False: #--todo--: if ellipse_closed:
- verts = verts[:-1] #list without last point/edge (cause closed curve)
len1 = len(verts)
#print 'deb:len1:', len1 #-----------------------
if width != 0:
@@ -3532,16 +3407,16 @@ class Ellipse: #---------------------------------------------------------------
me.faces[i].smooth = True
if settings.var['vGroup_on'] and not M_OBJ:
# each MeshSide becomes vertexGroup for easier material assignment ---------------------
- replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD
+ replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD
vg_left, vg_right, vg_top, vg_bottom = [], [], [], []
for v in f_left: vg_left.extend(v)
for v in f_right: vg_right.extend(v)
for v in f_top: vg_top.extend(v)
for v in f_bottom: vg_bottom.extend(v)
- me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace)
- me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace)
- me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace)
- me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace)
+ me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace)
+ me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace)
+ me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace)
+ me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace)
me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace)
me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace)
@@ -3685,7 +3560,7 @@ class Face: #-----------------------------------------------------------------
ob.link(me) # link mesh to that object
vG_name = 'color_%s' %self.color_index
if edges: faces = edges
- replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD
+ replace = Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD
try:
me.assignVertsToGroup(vG_name, faces[0], 1.0, replace)
#print 'deb: existed vGroup:', vG_name #---------------------
@@ -4190,10 +4065,8 @@ class Settings: #--------------------------------------------------------------
"""Wraps the built-in print command in a optimization check.
"""
if self.var['optimization'] <= self.MID:
- if newline:
- print text
- else:
- print text,
+ if newline: print text
+ else: print text,
def redraw(self):
@@ -4235,9 +4108,9 @@ def analyzeDXF(dxfFile): #---------------------------------------
"""
Window.WaitCursor(True) # Let the user know we are thinking
print 'reading DXF file: %s.' % dxfFile
- time1 = Blender.sys.time() #time marker1
+ time1 = sys.time() #time marker1
drawing = readDXF(dxfFile, objectify)
- print 'finish reading in %.4f sec.' % (Blender.sys.time()-time1)
+ print 'finish reading in %.4f sec.' % (sys.time()-time1)
# First sort out all the section_items
sections = dict([(item.name, item) for item in drawing.data])
@@ -4353,8 +4226,9 @@ def analyzeDXF(dxfFile): #---------------------------------------
for item2 in drawing.entities.data:
if type(item2) != list and item2.type == 'insert':
- if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen
- blocksmap[item2.name][0] = True # marked as world used BLOCK
+ if item2.name in blocksmap.keys():
+ if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen
+ blocksmap[item2.name][0] = True # marked as world used BLOCK
key_list = blocksmap.keys()
key_list.reverse()
@@ -4397,8 +4271,7 @@ def analyzeDXF(dxfFile): #---------------------------------------
Draw.PupMenu('DXF importer: report saved in INF-file:%t|' + '\'%s\'' %infFile)
except:
Draw.PupMenu('DXF importer: ERROR by writing report in INF-file:%t|' + '\'%s\'' %infFile)
- finally:
- f.close()
+ #finally: f.close()
@@ -4417,7 +4290,8 @@ def main(dxfFile): #---------------#############################-----------
global cur_COUNTER #counter for progress_bar
cur_COUNTER = 0
- try:
+ #try:
+ if 1:
#print "Getting settings..."
global GUI_A, GUI_B, g_scale_as
if not GUI_A['g_scale_on'].val:
@@ -4449,10 +4323,45 @@ def main(dxfFile): #---------------#############################-----------
if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile):
Window.WaitCursor(True) # Let the user know we are thinking
print 'reading file: %s.' % dxfFile
- time1 = Blender.sys.time() #time marker1
+ time1 = sys.time() #time marker1
drawing = readDXF(dxfFile, objectify)
- print 'reading finished in %.4f sec.' % (Blender.sys.time()-time1)
+ print 'reading finished in %.4f sec.' % (sys.time()-time1)
Window.WaitCursor(False)
+ elif dxfFile.lower().endswith('.dwg') and sys.exists(dxfFile):
+ if not extCONV_OK:
+ Draw.PupMenu(extCONV_TEXT)
+ Window.WaitCursor(False)
+ if editmode: Window.EditMode(1) # and put things back how we fond them
+ return None
+ else:
+ Window.WaitCursor(True) # Let the user know we are thinking
+ #todo: issue: in DConvertCon.exe the output filename is fixed to dwg_name.dxf
+
+ if 0: # works only for Windows
+ dwgTemp = 'temp_01.dwg'
+ dxfTemp = 'temp_01.dxf'
+ os.system('copy %s %s' %(dxfFile,dwgTemp))
+ else:
+ dwgTemp = dxfFile
+ dxfTemp = dxfFile[:-3]+'dxf'
+ #print 'temp. converting: %s\n to: %s' %(dxfFile, dxfTemp)
+ #os.system('%s %s -acad11 -dxf' %(extCONV_PATH, dxfFile))
+ os.system('%s %s -dxf' %(extCONV_PATH, dwgTemp))
+ #os.system('%s %s -dxf' %(extCONV_PATH, dxfFile_temp))
+ if sys.exists(dxfTemp):
+ print 'reading file: %s.' % dxfTemp
+ time1 = sys.time() #time marker1
+ drawing = readDXF(dxfTemp, objectify)
+ #os.remove(dwgTemp)
+ os.remove(dxfTemp) # clean up
+ print 'reading finished in %.4f sec.' % (sys.time()-time1)
+ Window.WaitCursor(False)
+ else:
+ if UI_MODE: Draw.PupMenu('DWG importer: nothing imported!%t|No valid DXF-representation found!')
+ print 'DWG importer: nothing imported. No valid DXF-representation found.'
+ Window.WaitCursor(False)
+ if editmode: Window.EditMode(1) # and put things back how we fond them
+ return None
else:
if UI_MODE: Draw.PupMenu('DXF importer: Alert!%t| no valid DXF-file selected!')
print "DXF importer: Alert! - no valid DXF-file selected."
@@ -4462,7 +4371,7 @@ def main(dxfFile): #---------------#############################-----------
# Draw all the know entity types in the current scene
oblist = [] # a list of all created AND linked objects for final f_globalScale
- time2 = Blender.sys.time() #time marker2
+ time2 = sys.time() #time marker2
Window.WaitCursor(True) # Let the user know we are thinking
settings.write("\n\nDrawing entities...")
@@ -4489,7 +4398,7 @@ def main(dxfFile): #---------------#############################-----------
#SCENE.objects.selected = SCENE.objects #select all objects in current scene
Blender.Redraw()
- time_text = Blender.sys.time() - time2
+ time_text = sys.time() - time2
Window.WaitCursor(False)
if settings.var['paper_space_on']: space = 'from paper space'
else: space = 'from model space'
@@ -4500,7 +4409,7 @@ def main(dxfFile): #---------------#############################-----------
#settings.write(message)
if UI_MODE: Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % time_text)
- finally:
+ #finally:
# restore state even if things didn't work
#print 'deb:drawEntities finally!' #-----------------------
Window.WaitCursor(False)
@@ -4526,11 +4435,11 @@ def getOCS(az): #--------------------------------------------------------------
cap = 0.015625 # square polar cap value (1/64.0)
if abs(az.x) < cap and abs(az.y) < cap:
- ax = Mathutils.CrossVecs(WORLDY, az)
+ ax = M_CrossVecs(WORLDY,az)
else:
- ax = Mathutils.CrossVecs(WORLDZ, az)
+ ax = M_CrossVecs(WORLDZ,az)
ax = ax.normalize()
- ay = Mathutils.CrossVecs(az, ax)
+ ay = M_CrossVecs(az, ax)
ay = ay.normalize()
return ax, ay, az
@@ -4613,7 +4522,7 @@ def getBlocksmap(drawing, layersmap, layFrozen_on=False): #--------------------
item2str = [item2.name, item2.layer]
childList.append(item2str)
try: usedblocks[item.name] = [used, childList]
- except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item)
+ except KeyError: print 'Cannot find "%s" Block!' %(item.name)
#print 'deb:getBlocksmap: usedblocks=' , usedblocks #-------------
#print 'deb:getBlocksmap: layersmap=' , layersmap #-------------
@@ -4621,7 +4530,7 @@ def getBlocksmap(drawing, layersmap, layFrozen_on=False): #--------------------
if type(item) != list and item.type == 'insert':
if not layersmap or (not layersmap[item.layer].frozen or layFrozen_on): #if insert_layer is not frozen
try: usedblocks[item.name][0] = True
- except: pass
+ except KeyError: print 'Cannot find "%s" Block!' %(item.name)
key_list = usedblocks.keys()
key_list.reverse()
@@ -4629,7 +4538,8 @@ def getBlocksmap(drawing, layersmap, layFrozen_on=False): #--------------------
if usedblocks[key][0]: #if parent used, then set used also all child blocks
for child in usedblocks[key][1]:
if not layersmap or (layersmap and not layersmap[child[1]].frozen): #if insert_layer is not frozen
- usedblocks[child[0]][0] = True # marked as used BLOCK
+ try: usedblocks[child[0]][0] = True # marked as used BLOCK
+ except KeyError: print 'Cannot find "%s" Block!' %(child[0])
usedblocks = [i for i in usedblocks.keys() if usedblocks[i][0]]
#print 'deb:getBlocksmap: usedblocks=' , usedblocks #-------------
@@ -4738,7 +4648,7 @@ def drawer(_type, entities, settings, block_def): #----------------------------
activObjectLayer = ''
activObjectName = ''
- message = "Drawing dxf\'%ss\'..." %_type
+ message = "Drawing dxf \'%ss\'..." %_type
cur_COUNTER += len_temp - len(entities)
settings.write(message, False)
settings.progress(cur_COUNTER, message)
@@ -4764,10 +4674,12 @@ def drawer(_type, entities, settings, block_def): #----------------------------
group = getGroup('l:%s' % layernamesmap[entity.layer])
if _type == 'insert': #---- INSERT and MINSERT=array --------------------
- if not settings.var['block_nn'] and entity.name.startswith('*X'): #---- support for noname BLOCKs
- #print 'deb:drawer entity.name:', entity.name #------------
- continue
- elif settings.var['blockFilter_on'] and not settings.accepted_block(entity.name):
+ if not settings.var['block_nn']: #----turn off support for noname BLOCKs
+ prefix = entity.name[:2]
+ if prefix in ('*X', '*U', '*D'):
+ #print 'deb:drawer entity.name:', entity.name #------------
+ continue
+ if settings.var['blockFilter_on'] and not settings.accepted_block(entity.name):
continue
#print 'deb:insert entity.loc:', entity.loc #----------------
@@ -5190,6 +5102,7 @@ def drawCurveCircle(circle): #--- no more used --------------------------------
curve.append(p4)
for point in curve:
point.handleTypes = [AUTO, AUTO]
+ point.radius = 1.0
curve.flagU = 1 # Set curve cyclic
c.update()
@@ -5231,6 +5144,7 @@ def drawCurveArc(self): #---- only for ELLIPSE --------------------------------
curve.append(p4)
for point in curve:
point.handleTypes = [AUTO, AUTO]
+ point.radius = 1.0
curve.flagU = 1 # Set curve cyclic
a.update()
@@ -5241,7 +5155,7 @@ def drawCurveArc(self): #---- only for ELLIPSE --------------------------------
# GUI STUFF -----#################################################-----------------
-from Blender.BGL import *
+from Blender.BGL import glColor3f, glRecti, glClear, glRasterPos2d
EVENT_NONE = 1
EVENT_START = 2
@@ -5269,17 +5183,17 @@ GUI_B = {} # GUI-buttons dictionary for drawingTypes
# settings default, initialize ------------------------
-points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|*curve.vertex %x5"
-lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-mlines_as_menu = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x|*curve %x5"
-plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-splines_as_menu = "convert to: %t|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
-plmesh_as_menu = "convert to: %t|*edge %x1|mesh %x2|NURBS-surface %x6"
-solids_as_menu = "convert to: %t|*edge %x1|mesh %x2"
-blocks_as_menu = "convert to: %t|dupliGroup %x1|*real.Group %x2|*exploded %x3"
-texts_as_menu = "convert to: %t|text %x1|*mesh %x2|*curve %x5"
-material_from_menu= "material from: %t|*LINESTYLE %x7|COLOR %x1|LAYER %x2|*LAYER+COLOR %x3|*BLOCK %x4|*XDATA %x5|*INI-File %x6"
+points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|..curve.vertex %x5"
+lines_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|thin box %x4|Bezier-curve %x5|..NURBS-curve %x6"
+mlines_as_menu = "convert to: %t|..edge %x1|..mesh %x2|..thin cylinder %x3|..thin box %x|..curve %x5"
+plines_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
+splines_as_menu = "convert to: %t|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
+plines3_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6"
+plmesh_as_menu = "convert to: %t|..edge %x1|mesh %x2|..NURBS-surface %x6"
+solids_as_menu = "convert to: %t|..edge %x1|mesh %x2"
+blocks_as_menu = "convert to: %t|dupliGroup %x1|..real.Group %x2|..exploded %x3"
+texts_as_menu = "convert to: %t|text %x1|..mesh %x2|..curve %x5"
+material_from_menu= "material from: %t|..LINESTYLE %x7|COLOR %x1|LAYER %x2|..LAYER+COLOR %x3|..BLOCK %x4|..XDATA %x5|..INI-File %x6"
g_scale_list = ''.join((
'scale factor: %t',
'|user def. %x12',
@@ -5456,11 +5370,9 @@ def saveConfig(): #--todo-----------------------------------------------
else:
#if BPyMessages.Warning_SaveOver(iniFile): #<- remi find it too abstarct
if sys.exists(iniFile):
- try:
- f = file(iniFile, 'r')
- try: header_str = f.readline()
- finally: f.close()
- except: pass
+ f = file(iniFile, 'r')
+ header_str = f.readline()
+ f.close()
if header_str.startswith(INIFILE_HEADER[0:13]):
if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1:
save_ok = True
@@ -5480,10 +5392,9 @@ def saveConfig(): #--todo-----------------------------------------------
output_str = '{\n'.join(output_str.split('{'))
try:
f = file(iniFile, 'w')
- try:
- f.write(INIFILE_HEADER + '\n# this is a comment line\n')
- f.write(output_str)
- finally: f.close()
+ f.write(INIFILE_HEADER + '\n# this is a comment line\n')
+ f.write(output_str)
+ f.close()
#Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile)
except:
Draw.PupMenu('DXF importer: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile)
@@ -5508,25 +5419,22 @@ def loadConfig(): #remi--todo-----------------------------------------------
update_RegistryKey('iniFileName', iniFile)
#print 'deb:loadConfig iniFile: ', iniFile #----------------------
if iniFile.lower().endswith(INIFILE_EXTENSION) and sys.exists(iniFile):
- try:
- f = file(iniFile, 'r')
- try:
- header_str = f.readline()
- if header_str.startswith(INIFILE_HEADER):
- data_str = f.read()
- f.close()
- #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-----------------
- data = eval(data_str)
- for k, v in data[0].iteritems():
- try: GUI_A[k].val = v
- except: GUI_A[k] = Draw.Create(v)
- for k, v in data[1].iteritems():
- try: GUI_B[k].val = v
- except: GUI_B[k] = Draw.Create(v)
- else:
- Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile)
- finally: f.close()
- except: pass
+ f = file(iniFile, 'r')
+ header_str = f.readline()
+ if header_str.startswith(INIFILE_HEADER):
+ data_str = f.read()
+ f.close()
+ #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-----------------
+ data = eval(data_str)
+ for k, v in data[0].iteritems():
+ try: GUI_A[k].val = v
+ except: GUI_A[k] = Draw.Create(v)
+ for k, v in data[1].iteritems():
+ try: GUI_B[k].val = v
+ except: GUI_B[k] = Draw.Create(v)
+ else:
+ f.close()
+ Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile)
else:
Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid INI-file selected!')
print "DXF importer: Alert!: no valid INI-file selected."
@@ -5746,7 +5654,7 @@ def draw_UI(): #---------------------------------------------------------------
y += 30
colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin)
- Draw.Label("DXF-Importer v" + __version__, but0c, y, menu_w, 20)
+ Draw.Label("DXF/DWG-Importer v" + __version__, but0c, y, menu_w, 20)
if config_UI.val:
b0, b0_ = but0c, but_0c + butt_margin
@@ -5771,7 +5679,7 @@ def draw_UI(): #---------------------------------------------------------------
y -= 20
Draw.BeginAlign()
- GUI_B['mline'] = Draw.Toggle('*MLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['mline'].val, "(*wip)support dxf-MLINE on/off")
+ GUI_B['mline'] = Draw.Toggle('..MLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['mline'].val, "(*todo)support dxf-MLINE on/off")
if GUI_B['mline'].val:
GUI_A['mlines_as'] = Draw.Menu(mlines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['mlines_as'].val, "select target Blender-object")
Draw.EndAlign()
@@ -5822,7 +5730,7 @@ def draw_UI(): #---------------------------------------------------------------
y -= 20
GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, b0, y, b0_, 20, GUI_B['text'].val, "support dxf-TEXT on/off")
- GUI_B['mtext'] = Draw.Toggle('*MTEXT', EVENT_NONE, b1, y, b1_, 20, GUI_B['mtext'].val, "(*wip)support dxf-MTEXT on/off")
+ GUI_B['mtext'] = Draw.Toggle('..MTEXT', EVENT_NONE, b1, y, b1_, 20, GUI_B['mtext'].val, "(*todo)support dxf-MTEXT on/off")
# GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object")
y -= 20
@@ -5841,8 +5749,8 @@ def draw_UI(): #---------------------------------------------------------------
Draw.BeginAlign()
GUI_A['views_on'] = Draw.Toggle('views', EVENT_NONE, b0, y, b0_-25, 20, GUI_A['views_on'].val, "imports VIEWs and VIEWPORTs as cameras on/off")
- GUI_A['cams_on'] = Draw.Toggle('*cams', EVENT_NONE, b1-25, y, b1_-25, 20, GUI_A['cams_on'].val, "(*wip) support ASHADE cameras on/off")
- GUI_A['lights_on'] = Draw.Toggle('*lights', EVENT_NONE, b1+25, y, b1_-25, 20, GUI_A['lights_on'].val, "(*wip) support AVE_RENDER lights on/off")
+ GUI_A['cams_on'] = Draw.Toggle('..cams', EVENT_NONE, b1-25, y, b1_-25, 20, GUI_A['cams_on'].val, "(*todo) support ASHADE cameras on/off")
+ GUI_A['lights_on'] = Draw.Toggle('..lights', EVENT_NONE, b1+25, y, b1_-25, 20, GUI_A['lights_on'].val, "(*todo) support AVE_RENDER lights on/off")
Draw.EndAlign()
@@ -5858,10 +5766,10 @@ def draw_UI(): #---------------------------------------------------------------
Draw.BeginAlign()
GUI_A['paper_space_on'] = Draw.Toggle('paper', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['paper_space_on'].val, "import only from Paper-Space on/off")
GUI_A['layFrozen_on'] = Draw.Toggle ('frozen', EVENT_NONE, b0+but_*1, y, but_, 20, GUI_A['layFrozen_on'].val, "import also from frozen LAYERs on/off")
- GUI_A['layerFilter_on'] = Draw.Toggle('layer', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['layerFilter_on'].val, "(*wip) LAYER filtering on/off")
- GUI_A['colorFilter_on'] = Draw.Toggle('color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*wip) COLOR filtering on/off")
- GUI_A['groupFilter_on'] = Draw.Toggle('group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*wip) GROUP filtering on/off")
- GUI_A['blockFilter_on'] = Draw.Toggle('block', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['blockFilter_on'].val, "(*wip) BLOCK filtering on/off")
+ GUI_A['layerFilter_on'] = Draw.Toggle('..layer', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['layerFilter_on'].val, "(*todo) LAYER filtering on/off")
+ GUI_A['colorFilter_on'] = Draw.Toggle('..color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*todo) COLOR filtering on/off")
+ GUI_A['groupFilter_on'] = Draw.Toggle('..group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*todo) GROUP filtering on/off")
+ GUI_A['blockFilter_on'] = Draw.Toggle('..block', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['blockFilter_on'].val, "(*todo) BLOCK filtering on/off")
#GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off")
Draw.EndAlign()
@@ -5962,7 +5870,7 @@ def draw_UI(): #---------------------------------------------------------------
y -= 10
y -= 20
Draw.BeginAlign()
- GUI_A['Z_force_on'] = Draw.Toggle('*elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, "*set objects Z-coordinates to elevation on/off")
+ GUI_A['Z_force_on'] = Draw.Toggle('.elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, ".set objects Z-coordinates to elevation on/off")
if GUI_A['Z_force_on'].val:
GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['Z_elev'].val, -1000, 1000, "set default elevation(Z-coordinate)")
Draw.EndAlign()
@@ -6022,9 +5930,9 @@ def draw_UI(): #---------------------------------------------------------------
#y -= 10
Draw.BeginAlign()
- Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file from project directory')
- dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF-file or type *.dxf for multi-import")
- Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'import all dxf files from this directory')
+ Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF/DWG-file for import')
+ dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF/DWG-file or type *.dxf/*.dwg for multiple files")
+ Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'set filter for import all files from this directory')
Draw.EndAlign()
y -= 30
@@ -6071,8 +5979,9 @@ def colorbox(x,y,xright,bottom):
def dxf_callback(input_filename):
global dxfFileName
- dxfFileName.val=input_filename
-# dirname == Blender.sys.dirname(Blender.Get('filename'))
+ if input_filename.lower()[-3:] in ('dwg','dxf'):
+ dxfFileName.val=input_filename
+# dirname == sys.dirname(Blender.Get('filename'))
# update_RegistryKey('DirName', dirname)
# update_RegistryKey('dxfFileName', input_filename)
@@ -6082,17 +5991,17 @@ def ini_callback(input_filename):
def event(evt, val):
if evt in (Draw.QKEY, Draw.ESCKEY) and not val:
- Blender.Draw.Exit()
+ Draw.Exit()
def bevent(evt):
# global EVENT_NONE,EVENT_LOAD_DXF,EVENT_LOAD_INI,EVENT_SAVE_INI,EVENT_EXIT
global config_UI, user_preset
- global GUI_A
+ global GUI_A, UI_MODE
######### Manages GUI events
if (evt==EVENT_EXIT):
- Blender.Draw.Exit()
- print 'DXF-Importer *** exit ***' #---------------------
+ Draw.Exit()
+ print 'DXF/DWG-Importer *** exit ***' #---------------------
elif (evt==EVENT_CHOOSE_INI):
Window.FileSelector(ini_callback, "INI-file Selection", '*.ini')
elif (evt==EVENT_REDRAW):
@@ -6149,13 +6058,14 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D')
Draw.Redraw()
elif (evt==EVENT_DXF_DIR):
dxfFile = dxfFileName.val
+ dxfFileExt = '*'+dxfFile.lower()[-4:] #can be .dxf or .dwg
dxfPathName = ''
if '/' in dxfFile:
dxfPathName = '/'.join(dxfFile.split('/')[:-1]) + '/'
elif '\\' in dxfFile:
dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\'
- dxfFileName.val = dxfPathName + '*.dxf'
-# dirname == Blender.sys.dirname(Blender.Get('filename'))
+ dxfFileName.val = dxfPathName + dxfFileExt
+# dirname == sys.dirname(Blender.Get('filename'))
# update_RegistryKey('DirName', dirname)
# update_RegistryKey('dxfFileName', dxfFileName.val)
GUI_A['newScene_on'].val = 1
@@ -6163,45 +6073,55 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D')
elif (evt==EVENT_CHOOSE_DXF):
filename = '' # '*.dxf'
if dxfFileName.val: filename = dxfFileName.val
- Window.FileSelector(dxf_callback, "DXF-file Selection", filename)
+ Window.FileSelector(dxf_callback, "DXF/DWG-file Selection", filename)
elif (evt==EVENT_START):
dxfFile = dxfFileName.val
#print 'deb: dxfFile file: ', dxfFile #----------------------
if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode
update_RegistryKey('dxfFileName', dxfFileName.val)
if dxfFile.lower().endswith('*.dxf'):
- if Draw.PupMenu('DXF importer: OK?|will import all DXF-files from:|%s' % dxfFile) == 1:
- global UI_MODE
+ if Draw.PupMenu('DXF importer will import all DXF-files from:|%s|OK?' % dxfFile) != -1:
UI_MODE = False
- multi_import(dxfFile[:-5]) # cut last 5 characters '*.dxf'
+ multi_import(dxfFile)
+ UI_MODE = True
Draw.Redraw()
- #Draw.Exit()
- else:
+
+ elif dxfFile.lower().endswith('*.dwg'):
+ if not extCONV_OK: Draw.PupMenu(extCONV_TEXT)
+ elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|OK?' % dxfFile) != -1:
+ #elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|Caution! overwrites existing DXF-files!| OK?' % dxfFile) != -1:
+ UI_MODE = False
+ multi_import(dxfFile)
+ UI_MODE = True
Draw.Redraw()
- elif dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile):
- print '\nStandard Mode: active'
- if GUI_A['newScene_on'].val:
- _dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
- _dxf_file = _dxf_file[:-4] # cut last char:'.dxf'
- _dxf_file = _dxf_file[:MAX_NAMELENGTH] #? [-MAX_NAMELENGTH:])
- global SCENE
- SCENE = Blender.Scene.New(_dxf_file)
- SCENE.makeCurrent()
- Blender.Redraw()
- #or so? Blender.Scene.makeCurrent(_dxf_file)
- #sce = bpy.data.scenes.new(_dxf_file)
- #bpy.data.scenes.active = sce
+
+ elif sys.exists(dxfFile) and dxfFile.lower()[-4:] in ('.dxf','.dwg'):
+ if dxfFile.lower().endswith('.dwg') and (not extCONV_OK):
+ Draw.PupMenu(extCONV_TEXT)
else:
- SCENE = Blender.Scene.GetCurrent()
- SCENE.objects.selected = [] # deselect all
- main(dxfFile)
- #SCENE.objects.selected = SCENE.objects
- #Window.RedrawAll()
- #Blender.Redraw()
- #Draw.Redraw()
+ #print '\nStandard Mode: active'
+ if GUI_A['newScene_on'].val:
+ _dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
+ _dxf_file = _dxf_file[:-4] # cut last char:'.dxf'
+ _dxf_file = _dxf_file[:MAX_NAMELENGTH] #? [-MAX_NAMELENGTH:])
+ global SCENE
+ SCENE = Blender.Scene.New(_dxf_file)
+ SCENE.makeCurrent()
+ Blender.Redraw()
+ #or so? Blender.Scene.makeCurrent(_dxf_file)
+ #sce = bpy.data.scenes.new(_dxf_file)
+ #bpy.data.scenes.active = sce
+ else:
+ SCENE = Blender.Scene.GetCurrent()
+ SCENE.objects.selected = [] # deselect all
+ main(dxfFile)
+ #SCENE.objects.selected = SCENE.objects
+ #Window.RedrawAll()
+ #Blender.Redraw()
+ #Draw.Redraw()
else:
- Draw.PupMenu('DXF importer: Alert!%t|no valid DXF-file selected!')
- print "DXF importer: error, no valid DXF-file selected! try again"
+ Draw.PupMenu('DXF importer: nothing imported!%t|no valid DXF-file selected!')
+ print "DXF importer: nothing imported, no valid DXF-file selected! try again"
Draw.Redraw()
@@ -6212,20 +6132,25 @@ def multi_import(DIR):
"""
global SCENE
- batchTIME = Blender.sys.time()
+ batchTIME = sys.time()
#if #DIR == "": DIR = os.path.curdir
- if DIR == "": DIR = Blender.sys.dirname(Blender.Get('filename'))
- print 'Multifiles Import from %s' %DIR
+ if DIR == "":
+ DIR = sys.dirname(Blender.Get('filename'))
+ EXT = '.dxf'
+ else:
+ EXT = DIR[-4:] # get last 4 characters '.dxf'
+ DIR = DIR[:-5] # cut last 5 characters '*.dxf'
+ print 'importing multiple %s files from %s' %(EXT,DIR)
files = \
- [sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')]
+ [sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith(EXT)]
if not files:
- print '...None DXF-files found. Abort!'
+ print '...None %s-files found. Abort!' %EXT
return
i = 0
for dxfFile in files:
i += 1
- print '\nDXF-file', i, 'of', len(files) #,'\nImporting', dxfFile
+ print '\n%s-file' %EXT, i, 'of', len(files) #,'\nImporting', dxfFile
if GUI_A['newScene_on'].val:
_dxf_file = dxfFile.split('/')[-1].split('\\')[-1]
_dxf_file = _dxf_file[:-4] # cut last char:'.dxf'
@@ -6241,21 +6166,20 @@ def multi_import(DIR):
main(dxfFile)
#Blender.Redraw()
- print 'TOTAL TIME: %.6f' % (Blender.sys.time() - batchTIME)
+ print 'TOTAL TIME: %.6f' % (sys.time() - batchTIME)
print '\a\r', # beep when done
+ Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % (sys.time() - batchTIME))
-
-UI_MODE = True
-
if __name__ == "__main__":
+ #Draw.PupMenu('DXF importer: Abort%t|This script version works for Blender up 2.49 only!')
UI_MODE = True
# recall last used DXF-file and INI-file names
dxffilename = check_RegistryKey('dxfFileName')
#print 'deb:start dxffilename:', dxffilename #----------------
if dxffilename: dxfFileName.val = dxffilename
else:
- dirname = Blender.sys.dirname(Blender.Get('filename'))
+ dirname = sys.dirname(Blender.Get('filename'))
#print 'deb:start dirname:', dirname #----------------
dxfFileName.val = sys.join(dirname, '')
inifilename = check_RegistryKey('iniFileName')
@@ -6268,7 +6192,7 @@ if __name__ == "__main__":
if 1:
# DEBUG ONLY
UI_MODE = False
- TIME= Blender.sys.time()
+ TIME= sys.time()
#DIR = '/dxf_r12_testfiles/'
DIR = '/metavr/'
import os
@@ -6297,5 +6221,5 @@ if 1:
dxfFileName.val = _dxf
main(_dxf)
- print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
+ print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
""" \ No newline at end of file
diff --git a/release/scripts/import_edl.py b/release/scripts/import_edl.py
new file mode 100644
index 00000000000..8c5d041b34c
--- /dev/null
+++ b/release/scripts/import_edl.py
@@ -0,0 +1,961 @@
+#!BPY
+
+"""
+Name: 'Video Sequence (.edl)...'
+Blender: 248
+Group: 'Import'
+Tooltip: 'Load a CMX formatted EDL into the sequencer'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2009: Campbell Barton, ideasman42@gmail.com
+#
+# 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,
+# --------------------------------------------------------------------------
+
+class TimeCode(object):
+ '''
+ Simple timecode class
+ also supports conversion from other time strings used by EDL
+ '''
+ def __init__(self, data, fps):
+ self.fps= fps
+ if type(data)==str:
+ self.fromString(data)
+ frame = self.asFrame()
+ self.fromFrame(frame)
+ else:
+ self.fromFrame(data)
+
+ def fromString(self, text):
+ # hh:mm:ss:ff
+ # No dropframe support yet
+
+ if text.lower().endswith('mps'): # 5.2mps
+ return self.fromFrame( int( float(text[:-3]) * self.fps ) )
+ elif text.lower().endswith('s'): # 5.2s
+ return self.fromFrame( int( float(text[:-1]) * self.fps ) )
+ elif text.isdigit(): # 1234
+ return self.fromFrame( int(text) )
+ elif ':' in text: # hh:mm:ss:ff
+ text= text.replace(';', ':').replace(',', ':').replace('.', ':')
+ text= text.split(':')
+
+ self.hours= int(text[0])
+ self.minutes= int(text[1])
+ self.seconds= int(text[2])
+ self.frame= int(text[3])
+ return self
+ else:
+ print 'ERROR: could not convert this into timecode "%s"' % test
+ return self
+
+
+ def fromFrame(self, frame):
+
+ if frame < 0:
+ frame = -frame;
+ neg=True
+ else:
+ neg=False
+
+ fpm = 60 * self.fps
+ fph = 60 * fpm
+
+ if frame < fph:
+ self.hours= 0
+ else:
+ self.hours= int(frame/fph)
+ frame = frame % fph
+
+ if frame < fpm:
+ self.minutes= 0
+ else:
+ self.minutes= int(frame/fpm)
+ frame = frame % fpm
+
+ if frame < self.fps:
+ self.seconds= 0
+ else:
+ self.seconds= int(frame/self.fps)
+ frame = frame % self.fps
+
+ self.frame= frame
+
+ if neg:
+ self.frame = -self.frame
+ self.seconds = -self.seconds
+ self.minutes = -self.minutes
+ self.hours = -self.hours
+
+ return self
+
+ def asFrame(self):
+ abs_frame= self.frame
+ abs_frame += self.seconds * self.fps
+ abs_frame += self.minutes * 60 * self.fps
+ abs_frame += self.hours * 60 * 60 * self.fps
+
+ return abs_frame
+
+ def asString(self):
+ self.fromFrame(int(self))
+ return '%.2d:%.2d:%.2d:%.2d' % (self.hours, self.minutes, self.seconds, self.frame)
+
+ def __repr__(self):
+ return self.asString()
+
+ # Numeric stuff, may as well have this
+ def __neg__(self): return TimeCode(-int(self), self.fps)
+ def __int__(self): return self.asFrame()
+ def __sub__(self, other): return TimeCode(int(self)-int(other), self.fps)
+ def __add__(self, other): return TimeCode(int(self)+int(other), self.fps)
+ def __mul__(self, other): return TimeCode(int(self)*int(other), self.fps)
+ def __div__(self, other): return TimeCode(int(self)/int(other), self.fps)
+ def __abs__(self): return TimeCode(abs(int(self)), self.fps)
+ def __iadd__(self, other): return self.fromFrame(int(self)+int(other))
+ def __imul__(self, other): return self.fromFrame(int(self)*int(other))
+ def __idiv__(self, other): return self.fromFrame(int(self)/int(other))
+# end timecode
+
+
+'''Comments
+Comments can appear at the beginning of the EDL file (header) or between the edit lines in the EDL. The first block of comments in the file is defined to be the header comments and they are associated with the EDL as a whole. Subsequent comments in the EDL file are associated with the first edit line that appears after them.
+Edit Entries
+<filename|tag> <EditMode> <TransitionType>[num] [duration] [srcIn] [srcOut] [recIn] [recOut]
+
+ * <filename|tag>: Filename or tag value. Filename can be for an MPEG file, Image file, or Image file template. Image file templates use the same pattern matching as for command line glob, and can be used to specify images to encode into MPEG. i.e. /usr/data/images/image*.jpg
+ * <EditMode>: 'V' | 'A' | 'VA' | 'B' | 'v' | 'a' | 'va' | 'b' which equals Video, Audio, Video_Audio edits (note B or b can be used in place of VA or va).
+ * <TransitonType>: 'C' | 'D' | 'E' | 'FI' | 'FO' | 'W' | 'c' | 'd' | 'e' | 'fi' | 'fo' | 'w'. which equals Cut, Dissolve, Effect, FadeIn, FadeOut, Wipe.
+ * [num]: if TransitionType = Wipe, then a wipe number must be given. At the moment only wipe 'W0' and 'W1' are supported.
+ * [duration]: if the TransitionType is not equal to Cut, then an effect duration must be given. Duration is in frames.
+ * [srcIn]: Src in. If no srcIn is given, then it defaults to the first frame of the video or the first frame in the image pattern. If srcIn isn't specified, then srcOut, recIn, recOut can't be specified.
+ * [srcOut]: Src out. If no srcOut is given, then it defaults to the last frame of the video - or last image in the image pattern. if srcOut isn't given, then recIn and recOut can't be specified.
+ * [recIn]: Rec in. If no recIn is given, then it is calculated based on its position in the EDL and the length of its input.
+ [recOut]: Rec out. If no recOut is given, then it is calculated based on its position in the EDL and the length of its input. first frame of the video.
+
+For srcIn, srcOut, recIn, recOut, the values can be specified as either timecode, frame number, seconds, or mps seconds. i.e.
+[tcode | fnum | sec | mps], where:
+
+ * tcode : SMPTE timecode in hh:mm:ss:ff
+ * fnum : frame number (the first decodable frame in the video is taken to be frame 0).
+ * sec : seconds with 's' suffix (e.g. 5.2s)
+ * mps : seconds with 'mps' suffix (e.g. 5.2mps). This corresponds to the 'seconds' value displayed by Windows MediaPlayer.
+
+More notes,
+Key
+
+'''
+
+enum= 0
+TRANSITION_UNKNOWN= enum
+TRANSITION_CUT= enum; enum+=1
+TRANSITION_DISSOLVE= enum; enum+=1
+TRANSITION_EFFECT= enum; enum+=1
+TRANSITION_FADEIN= enum; enum+=1
+TRANSITION_FADEOUT= enum; enum+=1
+TRANSITION_WIPE= enum; enum+=1
+TRANSITION_KEY= enum; enum+=1
+
+TRANSITION_DICT={ \
+ 'c':TRANSITION_CUT,
+ 'd':TRANSITION_DISSOLVE,
+ 'e':TRANSITION_EFFECT,
+ 'fi':TRANSITION_FADEIN,
+ 'fo':TRANSITION_FADEOUT,
+ 'w':TRANSITION_WIPE,
+ 'k':TRANSITION_KEY,
+ }
+
+enum= 0
+EDIT_UNKNOWN= 1<<enum; enum+=1
+EDIT_VIDEO= 1<<enum; enum+=1
+EDIT_AUDIO= 1<<enum; enum+=1
+EDIT_AUDIO_STEREO= 1<<enum; enum+=1
+EDIT_VIDEO_AUDIO= 1<<enum; enum+=1
+
+EDIT_DICT= { \
+ 'v':EDIT_VIDEO,
+ 'a':EDIT_AUDIO,
+ 'aa':EDIT_AUDIO_STEREO,
+ 'va':EDIT_VIDEO_AUDIO,
+ 'b':EDIT_VIDEO_AUDIO
+ }
+
+
+enum= 0
+WIPE_UNKNOWN= enum
+WIPE_0= enum; enum+=1
+WIPE_1= enum; enum+=1
+
+enum= 0
+KEY_UNKNOWN= enum
+KEY_BG= enum; enum+=1 # K B
+KEY_IN= enum; enum+=1 # This is assumed if no second type is set
+KEY_OUT= enum; enum+=1 # K O
+
+
+'''
+Most sytems:
+Non-dropframe: 1:00:00:00 - colon in last position
+Dropframe: 1:00:00;00 - semicolon in last position
+PAL/SECAM: 1:00:00:00 - colon in last position
+
+SONY:
+Non-dropframe: 1:00:00.00 - period in last position
+Dropframe: 1:00:00,00 - comma in last position
+PAL/SECAM: 1:00:00.00 - period in last position
+'''
+
+'''
+t = abs(timecode('-124:-12:-43:-22', 25))
+t /= 2
+print t
+'''
+
+def editFlagsToText(flag):
+ items = []
+ for item, val in EDIT_DICT.items():
+ if val & flag:
+ items.append(item)
+ return '/'.join(items)
+
+
+class EditDecision(object):
+ def __init__(self, text= None, fps= 25):
+ # print text
+ self.number = -1
+ self.reel = '' # Uniqie name for this 'file' but not filename, when BL signifies black
+ self.transition_duration= 0
+ self.edit_type= EDIT_UNKNOWN
+ self.transition_type= TRANSITION_UNKNOWN
+ self.wipe_type = WIPE_UNKNOWN
+ self.key_type = KEY_UNKNOWN
+ self.key_fade = -1 # true/false
+ self.srcIn = None # Where on the original field recording the event begins
+ self.srcOut = None # Where on the original field recording the event ends
+ self.recIn = None # Beginning of the original event in the edited program
+ self.recOut = None # End of the original event in the edited program
+ self.m2 = None # fps set by the m2 command
+ self.filename = ''
+
+ self.custom_data= [] # use for storing any data you want (blender strip for eg)
+
+ if text != None:
+ self.read(text, fps)
+
+ def __repr__(self):
+ txt= 'num: %d, ' % self.number
+ txt += 'reel: %s, ' % self.reel
+ txt += 'edit_type: '
+ txt += editFlagsToText(self.edit_type) + ', '
+
+ txt += 'trans_type: '
+ for item, val in TRANSITION_DICT.items():
+ if val == self.transition_type:
+ txt += item + ', '
+ break
+
+
+ txt += 'm2: '
+ if self.m2:
+ txt += '%g' % float(self.m2.fps)
+ txt += '\n\t'
+ txt += self.m2.data
+ else:
+ txt += 'nil'
+
+ txt += ', '
+ txt += 'recIn: ' + str(self.recIn) + ', '
+ txt += 'recOut: ' + str(self.recOut) + ', '
+ txt += 'srcIn: ' + str(self.srcIn) + ', '
+ txt += 'srcOut: ' + str(self.srcOut) + ', '
+
+ return txt
+
+
+ def read(self, line, fps):
+ line= line.split()
+ index= 0
+ self.number= int(line[index]); index+=1
+ self.reel= line[index].lower(); index+=1
+
+ # AA/V can be an edit type
+ self.edit_type= 0
+ for edit_type in line[index].lower().split('/'):
+ self.edit_type |= EDIT_DICT[edit_type];
+ index+=1
+
+ tx_name = ''.join([c for c in line[index].lower() if not c.isdigit()])
+ self.transition_type= TRANSITION_DICT[tx_name]; # advance the index later
+
+ if self.transition_type== TRANSITION_WIPE:
+ tx_num = ''.join([c for c in line[index].lower() if c.isdigit()])
+ if tx_num: tx_num = int(tx_num)
+ else: tx_num = 0
+
+ self.wipe_type= tx_num
+
+ elif self.transition_type== TRANSITION_KEY: # UNTESTED
+
+ val= line[index+1].lower()
+
+ if val == 'b':
+ self.key_type= KEY_BG
+ index+=1
+ elif val == 'o':
+ self.key_type= KEY_OUT
+ index+=1
+ else:
+ self.key_type= KEY_IN # if no args given
+
+ # there may be an (F) after, eg 'K B (F)'
+ # in the docs this should only be after K B but who knows, it may be after K O also?
+ val= line[index+1].lower()
+ if val == '(f)':
+ index+=1
+ self.key_fade = True
+ else:
+ self.key_fade = False
+
+ index+=1
+
+ if self.transition_type in (TRANSITION_DISSOLVE, TRANSITION_EFFECT, TRANSITION_FADEIN, TRANSITION_FADEOUT, TRANSITION_WIPE):
+ self.transition_duration= TimeCode(line[index], fps); index+=1
+
+ if index < len(line):
+ self.srcIn= TimeCode(line[index], fps); index+=1
+ if index < len(line):
+ self.srcOut= TimeCode(line[index], fps); index+=1
+
+ if index < len(line):
+ self.recIn= TimeCode(line[index], fps); index+=1
+ if index < len(line):
+ self.recOut= TimeCode(line[index], fps); index+=1
+
+ def renumber(self):
+ self.edits.sort( key=lambda e: int(e.recIn) )
+ for i, edit in enumerate(self.edits):
+ edit.number= i
+
+ def clean(self):
+ '''
+ Clean up double ups
+ '''
+ self.renumber()
+
+ # TODO
+ def asName(self):
+ cut_type = 'nil'
+ for k,v in TRANSITION_DICT.iteritems():
+ if v==self.transition_type:
+ cut_type = k
+ break
+
+ return '%d_%s_%s' % (self.number, self.reel, cut_type)
+
+class M2(object):
+ def __init__(self):
+ self.reel = None
+ self.fps = None
+ self.time = None
+ self.data = None
+
+ self.index = -1
+ self.tot = -1
+
+ def read(self, line, fps):
+
+ # M2 TAPEC 050.5 00:08:11:08
+ words = line.split()
+
+ self.reel= words[1].lower()
+ self.fps= float(words[2])
+ self.time= TimeCode(words[3], fps)
+
+ self.data = line
+
+class EditList(object):
+ def __init__(self):
+ self.edits= []
+ self.title= ''
+
+ def parse(self, filename, fps):
+ try:
+ file= open(filename, 'rU')
+ except:
+ return False
+
+ self.edits= []
+ edits_m2 = [] # edits with m2's
+
+ has_m2 = False
+
+ for line in file:
+ line= ' '.join(line.split())
+
+ if not line or line.startswith('*') or line.startswith('#'):
+ continue
+ elif line.startswith('TITLE:'):
+ self.title= ' '.join(line.split()[1:])
+ elif line.split()[0].lower() == 'm2':
+ has_m2 = True
+ m2 = M2()
+ m2.read(line, fps)
+ edits_m2.append( m2 )
+ elif not line.split()[0].isdigit():
+ print 'Ignoring:', line
+ else:
+ self.edits.append( EditDecision(line, fps) )
+ edits_m2.append( self.edits[-1] )
+
+ if has_m2:
+ # Group indexes
+ i = 0
+ for item in edits_m2:
+ if isinstance(item, M2):
+ item.index = i
+ i += 1
+ else:
+ # not an m2
+ i = 0
+
+ # Set total group indexes
+ for item in reversed(edits_m2):
+ if isinstance(item, M2):
+ if tot_m2 == -1:
+ tot_m2 = item.index + 1
+
+ item.tot = tot_m2
+ else:
+ # not an m2
+ tot_m2 = -1
+
+
+ for i, item in enumerate(edits_m2):
+ if isinstance(item, M2):
+ # make a list of all items that match the m2's reel name
+ edits_m2_tmp = [item_tmp for item_tmp in edits_m2 if (isinstance(item, M2) or item_tmp.reel == item.reel)]
+
+ # get the new index
+ i_tmp = edits_m2_tmp.index(item)
+
+ # Seek back to get the edit.
+ edit = edits_m2[i_tmp-item.tot]
+
+ # Note, docs say time should also match with edit start time
+ # but from final cut pro, this seems not to be the case
+ if not isinstance(edit, EditDecision):
+ print "ERROR!", 'M2 incorrect'
+ else:
+ edit.m2 = item
+
+
+ return True
+
+ def testOverlap(self, edit_test):
+ recIn= int(edit_test.recIn)
+ recOut= int(edit_test.recOut)
+
+ for edit in self.edits:
+ if edit is edit_test:
+ break
+
+ recIn_other= int(edit.recIn)
+ recOut_other= int(edit.recOut)
+
+ if recIn_other < recIn < recOut_other:
+ return True
+ if recIn_other < recOut < recOut_other:
+ return True
+
+ if recIn < recIn_other < recOut:
+ return True
+ if recIn < recOut_other < recOut:
+ return True
+
+ return False
+
+ def getReels(self):
+ reels = {}
+ for edit in self.edits:
+ reels.setdefault(edit.reel, []).append(edit)
+
+ return reels
+
+
+
+# from DNA
+SEQ_IMAGE= 0
+SEQ_META= 1
+SEQ_SCENE= 2
+SEQ_MOVIE= 3
+SEQ_RAM_SOUND= 4
+SEQ_HD_SOUND= 5
+SEQ_MOVIE_AND_HD_SOUND= 6
+
+SEQ_EFFECT= 8
+SEQ_CROSS= 8
+SEQ_ADD= 9
+SEQ_SUB= 10
+SEQ_ALPHAOVER= 11
+SEQ_ALPHAUNDER= 12
+SEQ_GAMCROSS= 13
+SEQ_MUL= 14
+SEQ_OVERDROP= 15
+SEQ_PLUGIN= 24
+SEQ_WIPE= 25
+SEQ_GLOW= 26
+SEQ_TRANSFORM= 27
+SEQ_COLOR= 28
+SEQ_SPEED= 29
+
+# Blender spesific stuff starts here
+import bpy
+import Blender
+
+def scale_meta_speed(seq, mov, scale):
+ # Add an effect
+ speed= seq.new((SEQ_SPEED, mov,), 199, mov.channel+1)
+ speed.speedEffectFrameBlending = True
+ meta= seq.new([mov, speed], 199, mov.channel)
+
+ if scale >= 1.0:
+ mov.endStill = int(mov.length * (scale - 1.0))
+ else:
+ speed.speedEffectGlobalSpeed = 1.0/scale
+ meta.endOffset = mov.length - int(mov.length*scale)
+
+ speed.update()
+ meta.update()
+ return meta
+
+def apply_dissolve_ipo(mov, blendin):
+ len_disp = float(mov.endDisp - mov.startDisp)
+
+ if len_disp <= 0.0:
+ print 'Error, strip is zero length'
+ return
+
+ mov.ipo= ipo= bpy.data.ipos.new("fade", "Sequence")
+ icu= ipo.addCurve('Fac')
+
+ icu.interpolation= Blender.IpoCurve.InterpTypes.LINEAR
+ icu.append((0, 0))
+ icu.append(((int(blendin)/len_disp) * 100, 1))
+
+ if mov.type not in (SEQ_HD_SOUND, SEQ_RAM_SOUND):
+ mov.blendMode = Blender.Scene.Sequence.BlendModes.ALPHAOVER
+
+
+def replace_ext(path, ext):
+ return path[:path.rfind('.')+1] + ext
+
+def load_edl(filename, reel_files, reel_offsets):
+ '''
+ reel_files - key:reel <--> reel:filename
+ '''
+
+ # For test file
+ # frame_offset = -769
+
+
+ sce= bpy.data.scenes.active
+ fps= sce.render.fps
+
+ elist= EditList()
+ if not elist.parse(filename, fps):
+ return 'Unable to parse "%s"' % filename
+ # elist.clean()
+
+
+ seq= sce.sequence
+
+ track= 0
+
+ edits = elist.edits[:]
+ # edits.sort(key = lambda edit: int(edit.recIn))
+
+ prev_edit = None
+ for edit in edits:
+ print edit
+ frame_offset = reel_offsets[edit.reel]
+
+
+ src_start= int(edit.srcIn) + frame_offset
+ src_end= int(edit.srcOut) + frame_offset
+ src_length= src_end-src_start
+
+ rec_start= int(edit.recIn) + 1
+ rec_end= int(edit.recOut) + 1
+ rec_length= rec_end-rec_start
+
+ # print src_length, rec_length, src_start
+
+ if edit.m2 != None: scale = fps/float(edit.m2.fps)
+ else: scale = 1.0
+
+ unedited_start= rec_start - src_start
+ offset_start = src_start - int(src_start*scale) # works for scaling up AND down
+
+ if edit.transition_type == TRANSITION_CUT and (not elist.testOverlap(edit)):
+ track = 1
+
+ strip= None
+ final_strips = []
+ if edit.reel.lower()=='bw':
+ strip= seq.new((0,0,0), rec_start, track+1)
+ strip.length= rec_length # for color its simple
+ final_strips.append(strip)
+ else:
+
+ path_full = reel_files[edit.reel]
+ path_fileonly= path_full.split('/')[-1].split('\\')[-1] # os.path.basename(full)
+ path_dironly= path_full[:-len(path_fileonly)] # os.path.dirname(full)
+
+ if edit.edit_type & EDIT_VIDEO: #and edit.transition_type == TRANSITION_CUT:
+
+ try:
+ strip= seq.new((path_fileonly, path_dironly, path_full, 'movie'), unedited_start + offset_start, track+1)
+ except:
+ return 'Invalid input for movie'
+
+ # Apply scaled rec in bounds
+ if scale != 1.0:
+ meta = scale_meta_speed(seq, strip, scale)
+ final_strip = meta
+ else:
+ final_strip = strip
+
+
+ final_strip.update()
+ final_strip.startOffset= rec_start - final_strip.startDisp
+ final_strip.endOffset= rec_end- final_strip.endDisp
+ final_strip.update()
+ final_strip.endOffset += (final_strip.endDisp - rec_end)
+ final_strip.update()
+
+
+ if edit.transition_duration:
+ if not prev_edit:
+ print "Error no previous strip"
+ else:
+ new_end = rec_start + int(edit.transition_duration)
+ for other in prev_edit.custom_data:
+ if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND:
+ other.endOffset += (other.endDisp - new_end)
+ other.update()
+
+ # Apply disolve
+ if edit.transition_type == TRANSITION_DISSOLVE:
+ apply_dissolve_ipo(final_strip, edit.transition_duration)
+
+ if edit.transition_type == TRANSITION_WIPE:
+ other_track = track + 2
+ for other in prev_edit.custom_data:
+ if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND:
+
+ strip_wipe= seq.new((SEQ_WIPE, other, final_strip), 1, other_track)
+
+ if edit.wipe_type == WIPE_0:
+ strip_wipe.wipeEffectAngle = 90
+ else:
+ strip_wipe.wipeEffectAngle = -90
+
+ other_track += 1
+
+
+
+ # strip.endOffset= strip.length - int(edit.srcOut)
+ #end_offset= (unedited_start+strip.length) - end
+ # print start, end, end_offset
+ #strip.endOffset = end_offset
+
+ # break
+ # print strip
+
+ final_strips.append(final_strip)
+
+
+ if edit.edit_type & (EDIT_AUDIO | EDIT_AUDIO_STEREO | EDIT_VIDEO_AUDIO):
+
+ if scale == 1.0: # TODO - scaled audio
+
+ try:
+ strip= seq.new((path_fileonly, path_dironly, path_full, 'audio_hd'), unedited_start + offset_start, track+6)
+ except:
+
+ # See if there is a wave file there
+ path_full_wav = replace_ext(path_full, 'wav')
+ path_fileonly_wav = replace_ext(path_fileonly, 'wav')
+
+ #try:
+ strip= seq.new((path_fileonly_wav, path_dironly, path_full_wav, 'audio_hd'), unedited_start + offset_start, track+6)
+ #except:
+ # return 'Invalid input for audio'
+
+ final_strip = strip
+
+ # Copied from above
+ final_strip.update()
+ final_strip.startOffset= rec_start - final_strip.startDisp
+ final_strip.endOffset= rec_end- final_strip.endDisp
+ final_strip.update()
+ final_strip.endOffset += (final_strip.endDisp - rec_end)
+ final_strip.update()
+
+ if edit.transition_type == TRANSITION_DISSOLVE:
+ apply_dissolve_ipo(final_strip, edit.transition_duration)
+
+ final_strips.append(final_strip)
+
+ # strip= seq.new((0.6, 0.6, 0.6), start, track+1)
+
+ if final_strips:
+ for strip in final_strips:
+ # strip.length= length
+ final_strip.name = edit.asName()
+ edit.custom_data[:]= final_strips
+ # track = not track
+ prev_edit = edit
+ track += 1
+
+ #break
+
+
+ def recursive_update(s):
+ s.update(1)
+ for s_kid in s:
+ recursive_update(s_kid)
+
+
+ for s in seq:
+ recursive_update(s)
+
+ return ''
+
+
+
+#load_edl('/fe/edl/EP30CMXtrk1.edl') # /tmp/test.edl
+#load_edl('/fe/edl/EP30CMXtrk2.edl') # /tmp/test.edl
+#load_edl('/fe/edl/EP30CMXtrk3.edl') # /tmp/test.edl
+#load_edl('/root/vid/rush/blender_edl.edl', ['/root/vid/rush/rushes3.avi',]) # /tmp/test.edl
+
+
+
+
+# ---------------------- Blender UI part
+from Blender import Draw, Window
+import BPyWindow
+
+if 0:
+ DEFAULT_FILE_EDL = '/root/vid/rush/blender_edl.edl'
+ DEFAULT_FILE_MEDIA = '/root/vid/rush/rushes3_wav.avi'
+ DEFAULT_FRAME_OFFSET = -769
+else:
+ DEFAULT_FILE_EDL = ''
+ DEFAULT_FILE_MEDIA = ''
+ DEFAULT_FRAME_OFFSET = 0
+
+B_EVENT_IMPORT = 1
+B_EVENT_RELOAD = 2
+B_EVENT_FILESEL_EDL = 3
+B_EVENT_NOP = 4
+
+B_EVENT_FILESEL = 100 # or greater
+
+class ReelItemUI(object):
+ __slots__ = 'filename_but', 'offset_but', 'ui_text'
+ def __init__(self):
+ self.filename_but = Draw.Create(DEFAULT_FILE_MEDIA)
+ self.offset_but = Draw.Create(DEFAULT_FRAME_OFFSET)
+ self.ui_text = ''
+
+
+
+REEL_UI = {} # reel:ui_string
+
+
+#REEL_FILENAMES = {} # reel:filename
+#REEL_OFFSETS = {} # reel:filename
+
+PREF = {}
+
+PREF['filename'] = Draw.Create(DEFAULT_FILE_EDL)
+PREF['reel_act'] = ''
+
+def edl_reload():
+ Window.WaitCursor(1)
+ filename = PREF['filename'].val
+ sce= bpy.data.scenes.active
+ fps= sce.render.fps
+
+ elist= EditList()
+
+ if filename:
+ if not elist.parse(filename, fps):
+ Draw.PupMenu('Error%t|Could not open the file "' + filename + '"')
+ reels = elist.getReels()
+ else:
+ reels = {}
+
+ REEL_UI.clear()
+ for reel_key, edits in reels.iteritems():
+
+ if reel_key == 'bw':
+ continue
+
+ flag = 0
+ for edit in edits:
+ flag |= edit.edit_type
+
+ reel_item = REEL_UI[reel_key] = ReelItemUI()
+
+ reel_item.ui_text = '%s (%s): ' % (reel_key, editFlagsToText(flag))
+
+ Window.WaitCursor(0)
+
+def edl_set_path(filename):
+ PREF['filename'].val = filename
+ edl_reload()
+ Draw.Redraw()
+
+def edl_set_path_reel(filename):
+ REEL_UI[PREF['reel_act']].filename_but.val = filename
+ Draw.Redraw()
+
+def edl_reel_keys():
+ reel_keys = REEL_UI.keys()
+
+ if 'bw' in reel_keys:
+ reel_keys.remove('bw')
+
+ reel_keys.sort()
+ return reel_keys
+
+def edl_draw():
+
+ MARGIN = 4
+ rect = BPyWindow.spaceRect()
+ but_width = int((rect[2]-MARGIN*2)/4.0) # 72
+ # Clamp
+ if but_width>100: but_width = 100
+ but_height = 17
+
+ x=MARGIN
+ y=rect[3]-but_height-MARGIN
+ xtmp = x
+
+
+
+ # ---------- ---------- ---------- ----------
+ Blender.Draw.BeginAlign()
+ PREF['filename'] = Draw.String('edl path: ', B_EVENT_RELOAD, xtmp, y, (but_width*3)-20, but_height, PREF['filename'].val, 256, 'EDL Path'); xtmp += (but_width*3)-20;
+ Draw.PushButton('..', B_EVENT_FILESEL_EDL, xtmp, y, 20, but_height, 'Select an EDL file'); xtmp += 20;
+ Blender.Draw.EndAlign()
+
+ Draw.PushButton('Reload', B_EVENT_RELOAD, xtmp + MARGIN, y, but_width - MARGIN, but_height, 'Read the ID Property settings from the active curve object'); xtmp += but_width;
+ y-=but_height + MARGIN
+ xtmp = x
+ # ---------- ---------- ---------- ----------
+
+ reel_keys = edl_reel_keys()
+
+
+
+ if reel_keys: text = 'Reel file list...'
+ elif PREF['filename'].val == '': text = 'No EDL loaded.'
+ else: text = 'No reels found!'
+
+ Draw.Label(text, xtmp + MARGIN, y, but_width*4, but_height); xtmp += but_width*4;
+
+ y-=but_height + MARGIN
+ xtmp = x
+
+ # ---------- ---------- ---------- ----------
+
+
+ for i, reel_key in enumerate(reel_keys):
+ reel_item = REEL_UI[reel_key]
+
+ Blender.Draw.BeginAlign()
+ REEL_UI[reel_key].filename_but = Draw.String(reel_item.ui_text, B_EVENT_NOP, xtmp, y, (but_width*3)-20, but_height, REEL_UI[reel_key].filename_but.val, 256, 'Select the reel path'); xtmp += (but_width*3)-20;
+ Draw.PushButton('..', B_EVENT_FILESEL + i, xtmp, y, 20, but_height, 'Media path to use for this reel'); xtmp += 20;
+ Blender.Draw.EndAlign()
+
+ reel_item.offset_but= Draw.Number('ofs:', B_EVENT_NOP, xtmp + MARGIN, y, but_width - MARGIN, but_height, reel_item.offset_but.val, -100000, 100000, 'Start offset in frames when applying timecode'); xtmp += but_width - MARGIN;
+
+ y-=but_height + MARGIN
+ xtmp = x
+
+ # ---------- ---------- ---------- ----------
+
+ Draw.PushButton('Import CMX-EDL Sequencer Strips', B_EVENT_IMPORT, xtmp + MARGIN, MARGIN, but_width*4 - MARGIN, but_height, 'Load the EDL file into the sequencer'); xtmp += but_width*4;
+ y-=but_height + MARGIN
+ xtmp = x
+
+
+def edl_event(evt, val):
+ pass
+
+def edl_bevent(evt):
+
+ if evt == B_EVENT_NOP:
+ pass
+ elif evt == B_EVENT_IMPORT:
+ '''
+ Load the file into blender with UI settings
+ '''
+ filename = PREF['filename'].val
+
+ reel_files = {}
+ reel_offsets = {}
+
+ for reel_key, reel_item in REEL_UI.iteritems():
+ reel_files[reel_key] = reel_item.filename_but.val
+ reel_offsets[reel_key] = reel_item.offset_but.val
+
+ error = load_edl(filename, reel_files, reel_offsets)
+ if error != '':
+ Draw.PupMenu('Error%t|' + error)
+ else:
+ Window.RedrawAll()
+
+ elif evt == B_EVENT_RELOAD:
+ edl_reload()
+ Draw.Redraw()
+
+ elif evt == B_EVENT_FILESEL_EDL:
+ filename = PREF['filename'].val
+ if not filename: filename = Blender.sys.join(Blender.sys.expandpath('//'), '*.edl')
+
+ Window.FileSelector(edl_set_path, 'Select EDL', filename)
+
+ elif evt >= B_EVENT_FILESEL:
+ reel_keys = edl_reel_keys()
+ reel_key = reel_keys[evt - B_EVENT_FILESEL]
+
+ filename = REEL_UI[reel_key].filename_but.val
+ if not filename: filename = Blender.sys.expandpath('//')
+
+ PREF['reel_act'] = reel_key # so file set path knows which one to set
+ Window.FileSelector(edl_set_path_reel, 'Reel Media', filename)
+
+
+
+if __name__ == '__main__':
+ Draw.Register(edl_draw, edl_event, edl_bevent)
+ edl_reload()
+
diff --git a/release/scripts/import_lightwave_motion.py b/release/scripts/import_lightwave_motion.py
index c242a9f6bd3..20c87dfd5c6 100644
--- a/release/scripts/import_lightwave_motion.py
+++ b/release/scripts/import_lightwave_motion.py
@@ -22,7 +22,7 @@ Be sure to set the framerate correctly
"""
-# $Id: export_lightwave_motion.py 9924 2007-01-27 02:15:14Z campbellbarton $
+# $Id$
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py
index 3aad0800cf7..81230bfcf03 100644
--- a/release/scripts/import_obj.py
+++ b/release/scripts/import_obj.py
@@ -2,14 +2,14 @@
"""
Name: 'Wavefront (.obj)...'
-Blender: 248
+Blender: 249
Group: 'Import'
Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.'
"""
-__author__= "Campbell Barton", "Jiri Hnidek"
+__author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone"
__url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org']
-__version__= "2.1"
+__version__= "2.13"
__bpydoc__= """\
This script imports a Wavefront OBJ files to Blender.
@@ -21,7 +21,8 @@ Note, This loads mesh objects and materials only, nurbs and curves are not suppo
# ***** BEGIN GPL LICENSE BLOCK *****
#
-# Script copyright (C) Campbell J Barton 2007
+# Script copyright (C) Campbell J Barton 2007-2009
+# - V2.12- bspline import/export added (funded by PolyDimensions GmbH)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -40,7 +41,7 @@ Note, This loads mesh objects and materials only, nurbs and curves are not suppo
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
-from Blender import *
+from Blender import Mesh, Draw, Window, Texture, Material, sys
import bpy
import BPyMesh
import BPyImage
@@ -49,7 +50,6 @@ import BPyMessages
try: import os
except: os= False
-
# Generic path functions
def stripFile(path):
'''Return directory, where the file is'''
@@ -125,6 +125,16 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
image= obj_image_load(imagepath, DIR, IMAGE_SEARCH)
has_data = image.has_data
texture.image = image
+
+ if not has_data:
+ try:
+ # first time using this image. We need to load it first
+ image.glLoad()
+ except:
+ # probably the image is crashed
+ pass
+ else:
+ has_data = image.has_data
# Adds textures for materials (rendering)
if type == 'Kd':
@@ -167,12 +177,13 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
del temp_mtl
#Create new materials
- for name in unique_materials.iterkeys():
- unique_materials[name]= bpy.data.materials.new(name)
-
- unique_material_images[name]= None, False # assign None to all material images to start with, add to later.
+ for name in unique_materials: # .keys()
+ if name != None:
+ unique_materials[name]= bpy.data.materials.new(name)
+ unique_material_images[name]= None, False # assign None to all material images to start with, add to later.
unique_materials[None]= None
+ unique_material_images[None]= None, False
for libname in material_libs:
mtlpath= DIR + libname
@@ -207,6 +218,7 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3
elif line_lower.startswith('d') or line_lower.startswith('tr'):
context_material.setAlpha(float(line_split[1]))
+ context_material.mode |= Material.Modes.ZTRANSP
elif line_lower.startswith('map_ka'):
img_filepath= line_value(line.split())
if img_filepath:
@@ -320,7 +332,7 @@ def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP,
return [(value[0], value[1], value[2], key_to_name(key)) for key, value in face_split_dict.iteritems()]
-def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, dataname):
+def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname):
'''
Takes all the data gathered and generates a mesh, adding the new object to new_objects
deals with fgons, sharp edges and assigning materials
@@ -424,8 +436,8 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l
sharp_edges[key]= None
- # mat the material names to an index
- material_mapping= dict([(name, i) for i, name in enumerate(unique_materials.keys())])
+ # map the material names to an index
+ material_mapping= dict([(name, i) for i, name in enumerate(unique_materials)]) # enumerate over unique_materials keys()
materials= [None] * len(unique_materials)
@@ -530,6 +542,105 @@ def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_l
ob= scn.objects.new(me)
new_objects.append(ob)
+ # Create the vertex groups. No need to have the flag passed here since we test for the
+ # content of the vertex_groups. If the user selects to NOT have vertex groups saved then
+ # the following test will never run
+ for group_name, group_indicies in vertex_groups.iteritems():
+ me.addVertGroup(group_name)
+ me.assignVertsToGroup(group_name, group_indicies,1.00, Mesh.AssignModes.REPLACE)
+
+
+def create_nurbs(scn, context_nurbs, vert_loc, new_objects):
+ '''
+ Add nurbs object to blender, only support one type at the moment
+ '''
+ deg = context_nurbs.get('deg', (3,))
+ curv_range = context_nurbs.get('curv_range', None)
+ curv_idx = context_nurbs.get('curv_idx', [])
+ parm_u = context_nurbs.get('parm_u', [])
+ parm_v = context_nurbs.get('parm_v', [])
+ name = context_nurbs.get('name', 'ObjNurb')
+ cstype = context_nurbs.get('cstype', None)
+
+ if cstype == None:
+ print '\tWarning, cstype not found'
+ return
+ if cstype != 'bspline':
+ print '\tWarning, cstype is not supported (only bspline)'
+ return
+ if not curv_idx:
+ print '\tWarning, curv argument empty or not set'
+ return
+ if len(deg) > 1 or parm_v:
+ print '\tWarning, surfaces not supported'
+ return
+
+ cu = bpy.data.curves.new(name, 'Curve')
+ cu.flag |= 1 # 3D curve
+
+ nu = None
+ for pt in curv_idx:
+
+ pt = vert_loc[pt]
+ pt = (pt[0], pt[1], pt[2], 1.0)
+
+ if nu == None:
+ nu = cu.appendNurb(pt)
+ else:
+ nu.append(pt)
+
+ nu.orderU = deg[0]+1
+
+ # get for endpoint flag from the weighting
+ if curv_range and len(parm_u) > deg[0]+1:
+ do_endpoints = True
+ for i in xrange(deg[0]+1):
+
+ if abs(parm_u[i]-curv_range[0]) > 0.0001:
+ do_endpoints = False
+ break
+
+ if abs(parm_u[-(i+1)]-curv_range[1]) > 0.0001:
+ do_endpoints = False
+ break
+
+ else:
+ do_endpoints = False
+
+ if do_endpoints:
+ nu.flagU |= 2
+
+
+ # close
+ '''
+ do_closed = False
+ if len(parm_u) > deg[0]+1:
+ for i in xrange(deg[0]+1):
+ #print curv_idx[i], curv_idx[-(i+1)]
+
+ if curv_idx[i]==curv_idx[-(i+1)]:
+ do_closed = True
+ break
+
+ if do_closed:
+ nu.flagU |= 1
+ '''
+
+ ob = scn.objects.new(cu)
+ new_objects.append(ob)
+
+
+def strip_slash(line_split):
+ if line_split[-1][-1]== '\\':
+ if len(line_split[-1])==1:
+ line_split.pop() # remove the \ item
+ else:
+ line_split[-1]= line_split[-1][:-1] # remove the \ from the end last number
+ return True
+ return False
+
+
+
def get_float_func(filepath):
'''
find the float function for this obj file
@@ -537,6 +648,7 @@ def get_float_func(filepath):
'''
file= open(filepath, 'rU')
for line in file: #.xreadlines():
+ line = line.lstrip()
if line.startswith('v'): # vn vt v
if ',' in line:
return lambda f: float(f.replace(',', '.'))
@@ -546,7 +658,17 @@ def get_float_func(filepath):
# incase all vert values were ints
return float
-def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS= True, CREATE_EDGES= True, SPLIT_OBJECTS= True, SPLIT_GROUPS= True, SPLIT_MATERIALS= True, IMAGE_SEARCH=True):
+def load_obj(filepath,
+ CLAMP_SIZE= 0.0,
+ CREATE_FGONS= True,
+ CREATE_SMOOTH_GROUPS= True,
+ CREATE_EDGES= True,
+ SPLIT_OBJECTS= True,
+ SPLIT_GROUPS= True,
+ SPLIT_MATERIALS= True,
+ ROTATE_X90= True,
+ IMAGE_SEARCH=True,
+ POLYGROUPS=False):
'''
Called by the user interface or another script.
load_obj(path) - should give acceptable results.
@@ -555,13 +677,16 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
'''
print '\nimporting obj "%s"' % filepath
+ if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS:
+ POLYGROUPS = False
+
time_main= sys.time()
verts_loc= []
verts_tex= []
faces= [] # tuples of the faces
material_libs= [] # filanems to material libs this uses
-
+ vertex_groups = {} # when POLYGROUPS is true
# Get the string to float conversion func for this file- is 'float' for almost all files.
float_func= get_float_func(filepath)
@@ -570,7 +695,13 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
context_material= None
context_smooth_group= None
context_object= None
+ context_vgroup = None
+ # Nurbs
+ context_nurbs = {}
+ nurbs = []
+ context_parm = '' # used by nurbs too but could be used elsewhere
+
has_ngons= False
# has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0
@@ -584,12 +715,14 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
# it means they are multiline-
# since we use xreadline we cant skip to the next line
# so we need to know weather
- multi_line_face= False
+ context_multi_line= ''
- print '\tpassing obj file "%s"...' % filepath,
+ print '\tparsing obj file "%s"...' % filepath,
time_sub= sys.time()
+
file= open(filepath, 'rU')
for line in file: #.xreadlines():
+ line = line.lstrip() # rare cases there is white space at the start of the line
if line.startswith('v '):
line_split= line.split()
@@ -605,12 +738,11 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
# Handel faces lines (as faces) and the second+ lines of fa multiline face here
# use 'f' not 'f ' because some objs (very rare have 'fo ' for faces)
- elif line.startswith('f') or (line.startswith('l ') and CREATE_EDGES) or multi_line_face:
+ elif line.startswith('f') or context_multi_line == 'f':
- if multi_line_face:
+ if context_multi_line:
# use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
line_split= line.split()
- multi_line_face= False
else:
line_split= line[2:].split()
@@ -626,19 +758,19 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
context_object\
))
- if line_split[-1][-1]== '\\':
- multi_line_face= True
- if len(line_split[-1])==1:
- line_split.pop() # remove the \ item
- else:
- line_split[-1]= line_split[-1][:-1] # remove the \ from the end last number
-
- isline= line.startswith('l')
+ if strip_slash(line_split):
+ context_multi_line = 'f'
+ else:
+ context_multi_line = ''
for v in line_split:
obj_vert= v.split('/')
vert_loc_index= int(obj_vert[0])-1
+ # Add the vertex to the current group
+ # *warning*, this wont work for files that have groups defined around verts
+ if POLYGROUPS and context_vgroup:
+ vertex_groups[context_vgroup].append(vert_loc_index)
# Make relative negative vert indicies absolute
if vert_loc_index < 0:
@@ -646,24 +778,60 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
face_vert_loc_indicies.append(vert_loc_index)
- if not isline:
- if len(obj_vert)>1 and obj_vert[1]:
- # formatting for faces with normals and textures us
- # loc_index/tex_index/nor_index
-
- vert_tex_index= int(obj_vert[1])-1
- # Make relative negative vert indicies absolute
- if vert_tex_index < 0:
- vert_tex_index= len(verts_tex) + vert_tex_index + 1
-
- face_vert_tex_indicies.append(vert_tex_index)
- else:
- # dummy
- face_vert_tex_indicies.append(0)
+ if len(obj_vert)>1 and obj_vert[1]:
+ # formatting for faces with normals and textures us
+ # loc_index/tex_index/nor_index
+
+ vert_tex_index= int(obj_vert[1])-1
+ # Make relative negative vert indicies absolute
+ if vert_tex_index < 0:
+ vert_tex_index= len(verts_tex) + vert_tex_index + 1
+
+ face_vert_tex_indicies.append(vert_tex_index)
+ else:
+ # dummy
+ face_vert_tex_indicies.append(0)
if len(face_vert_loc_indicies) > 4:
has_ngons= True
+
+ elif CREATE_EDGES and (line.startswith('l ') or context_multi_line == 'l'):
+ # very similar to the face load function above with some parts removed
+ if context_multi_line:
+ # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face
+ line_split= line.split()
+
+ else:
+ line_split= line[2:].split()
+ face_vert_loc_indicies= []
+ face_vert_tex_indicies= []
+
+ # Instance a face
+ faces.append((\
+ face_vert_loc_indicies,\
+ face_vert_tex_indicies,\
+ context_material,\
+ context_smooth_group,\
+ context_object\
+ ))
+
+ if strip_slash(line_split):
+ context_multi_line = 'l'
+ else:
+ context_multi_line = ''
+
+ isline= line.startswith('l')
+
+ for v in line_split:
+ vert_loc_index= int(v)-1
+
+ # Make relative negative vert indicies absolute
+ if vert_loc_index < 0:
+ vert_loc_index= len(verts_loc) + vert_loc_index + 1
+
+ face_vert_loc_indicies.append(vert_loc_index)
+
elif line.startswith('s'):
if CREATE_SMOOTH_GROUPS:
context_smooth_group= line_value(line.split())
@@ -682,12 +850,75 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
context_object= line_value(line.split())
# print 'context_object', context_object
# unique_obects[context_object]= None
+ elif POLYGROUPS:
+ context_vgroup = line_value(line.split())
+ if context_vgroup and context_vgroup != '(null)':
+ vertex_groups.setdefault(context_vgroup, [])
+ else:
+ context_vgroup = None # dont assign a vgroup
elif line.startswith('usemtl'):
context_material= line_value(line.split())
unique_materials[context_material]= None
elif line.startswith('mtllib'): # usemap or usemat
material_libs.extend( line.split()[1:] ) # can have multiple mtllib filenames per line
+
+
+ # Nurbs support
+ elif line.startswith('cstype '):
+ context_nurbs['cstype']= line_value(line.split()) # 'rat bspline' / 'bspline'
+ elif line.startswith('curv ') or context_multi_line == 'curv':
+ line_split= line.split()
+
+ curv_idx = context_nurbs['curv_idx'] = context_nurbs.get('curv_idx', []) # incase were multiline
+
+ if not context_multi_line:
+ context_nurbs['curv_range'] = float_func(line_split[1]), float_func(line_split[2])
+ line_split[0:3] = [] # remove first 3 items
+
+ if strip_slash(line_split):
+ context_multi_line = 'curv'
+ else:
+ context_multi_line = ''
+
+
+ for i in line_split:
+ vert_loc_index = int(i)-1
+
+ if vert_loc_index < 0:
+ vert_loc_index= len(verts_loc) + vert_loc_index + 1
+
+ curv_idx.append(vert_loc_index)
+
+ elif line.startswith('parm') or context_multi_line == 'parm':
+ line_split= line.split()
+
+ if context_multi_line:
+ context_multi_line = ''
+ else:
+ context_parm = line_split[1]
+ line_split[0:2] = [] # remove first 2
+
+ if strip_slash(line_split):
+ context_multi_line = 'parm'
+ else:
+ context_multi_line = ''
+
+ if context_parm.lower() == 'u':
+ context_nurbs.setdefault('parm_u', []).extend( [float_func(f) for f in line_split] )
+ elif context_parm.lower() == 'v': # surfaces not suported yet
+ context_nurbs.setdefault('parm_v', []).extend( [float_func(f) for f in line_split] )
+ # else: # may want to support other parm's ?
+
+ elif line.startswith('deg '):
+ context_nurbs['deg']= [int(i) for i in line.split()[1:]]
+ elif line.startswith('end'):
+ # Add the nurbs curve
+ if context_object:
+ context_nurbs['name'] = context_object
+ nurbs.append(context_nurbs)
+ context_nurbs = {}
+ context_parm = ''
''' # How to use usemap? depricated?
elif line.startswith('usema'): # usemap or usemat
@@ -707,6 +938,8 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
print '%.4f sec' % (time_new-time_sub)
time_sub= time_new
+ if not ROTATE_X90:
+ verts_loc[:] = [(v[0], v[2], -v[1]) for v in verts_loc]
# deselect all
scn = bpy.data.scenes.active
@@ -719,8 +952,13 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
else: SPLIT_OB_OR_GROUP = False
for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS):
- # Create meshes from the data
- create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc_split, verts_tex, faces_split, unique_materials_split, unique_material_images, unique_smooth_groups, dataname)
+ # Create meshes from the data, warning 'vertex_groups' wont support splitting
+ create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc_split, verts_tex, faces_split, unique_materials_split, unique_material_images, unique_smooth_groups, vertex_groups, dataname)
+
+ # nurbs support
+ for context_nurbs in nurbs:
+ create_nurbs(scn, context_nurbs, verts_loc, new_objects)
+
axis_min= [ 1000000000]*3
axis_max= [-1000000000]*3
@@ -743,6 +981,11 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS
for ob in new_objects:
ob.setSize(scale, scale, scale)
+ # Better rotate the vert locations
+ #if not ROTATE_X90:
+ # for ob in new_objects:
+ # ob.RotX = -1.570796326794896558
+
time_new= sys.time()
print '%.4f sec' % (time_new-time_sub)
@@ -756,7 +999,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
if BPyMessages.Error_NoFile(filepath):
return
- global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, KEEP_VERT_ORDER
+ global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
CREATE_SMOOTH_GROUPS= Draw.Create(0)
CREATE_FGONS= Draw.Create(1)
@@ -766,7 +1009,9 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
SPLIT_MATERIALS= Draw.Create(0)
CLAMP_SIZE= Draw.Create(10.0)
IMAGE_SEARCH= Draw.Create(1)
+ POLYGROUPS= Draw.Create(0)
KEEP_VERT_ORDER= Draw.Create(1)
+ ROTATE_X90= Draw.Create(1)
# Get USER Options
@@ -815,9 +1060,10 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
GLOBALS['EVENT'] = e
def do_split(e,v):
- global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER
+ global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS
if SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val:
KEEP_VERT_ORDER.val = 0
+ POLYGROUPS.val = 0
else:
KEEP_VERT_ORDER.val = 1
@@ -829,6 +1075,11 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
if not (SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val):
KEEP_VERT_ORDER.val = 1
+ def do_polygroups(e,v):
+ global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS
+ if POLYGROUPS.val:
+ SPLIT_OBJECTS.val = SPLIT_GROUPS.val = SPLIT_MATERIALS.val = 0
+
def do_help(e,v):
url = __url__[0]
print 'Trying to open web browser with documentation at this address...'
@@ -847,7 +1098,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
ui_x -= 165
ui_y -= 90
- global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, KEEP_VERT_ORDER
+ global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90
Draw.Label('Import...', ui_x+9, ui_y+159, 220, 21)
Draw.BeginAlign()
@@ -858,17 +1109,20 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
Draw.Label('Separate objects by OBJ...', ui_x+9, ui_y+110, 220, 20)
Draw.BeginAlign()
- SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 70, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split)
- SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+79, ui_y+89, 70, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split)
- SPLIT_MATERIALS = Draw.Toggle('Material', EVENT_REDRAW, ui_x+149, ui_y+89, 70, 21, SPLIT_MATERIALS.val, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)', do_split)
+ SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 55, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split)
+ SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+64, ui_y+89, 55, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split)
+ SPLIT_MATERIALS = Draw.Toggle('Material', EVENT_REDRAW, ui_x+119, ui_y+89, 60, 21, SPLIT_MATERIALS.val, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)', do_split)
Draw.EndAlign()
# Only used for user feedback
- KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+229, ui_y+89, 110, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder)
+ KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+184, ui_y+89, 113, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder)
+
+ ROTATE_X90 = Draw.Toggle('-X90', EVENT_REDRAW, ui_x+302, ui_y+89, 38, 21, ROTATE_X90.val, 'Rotate X 90.')
Draw.Label('Options...', ui_x+9, ui_y+60, 211, 20)
- CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 211, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)')
- IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+229, ui_y+39, 110, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)')
+ CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 130, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)')
+ POLYGROUPS = Draw.Toggle('Poly Groups', EVENT_REDRAW, ui_x+144, ui_y+39, 90, 21, POLYGROUPS.val, 'Import OBJ groups as vertex groups.', do_polygroups)
+ IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+239, ui_y+39, 100, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)')
Draw.BeginAlign()
Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 21, 'Load the wiki page for this script', do_help)
Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 21, '', obj_ui_set_event)
@@ -918,7 +1172,9 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
SPLIT_OBJECTS.val,\
SPLIT_GROUPS.val,\
SPLIT_MATERIALS.val,\
+ ROTATE_X90.val,\
IMAGE_SEARCH.val,\
+ POLYGROUPS.val
)
else: # Normal load
@@ -930,7 +1186,9 @@ def load_obj_ui(filepath, BATCH_LOAD= False):
SPLIT_OBJECTS.val,\
SPLIT_GROUPS.val,\
SPLIT_MATERIALS.val,\
+ ROTATE_X90.val,\
IMAGE_SEARCH.val,\
+ POLYGROUPS.val
)
Window.WaitCursor(0)
@@ -947,34 +1205,28 @@ if __name__=='__main__' and not DEBUG:
else:
Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj')
-
+ # For testing compatibility
'''
-# For testing compatibility
else:
# DEBUG ONLY
TIME= sys.time()
+ DIR = '/fe/obj'
import os
print 'Searching for files'
- os.system('find /fe/obj -iname "*.obj" > /tmp/temp3ds_list')
-
- print '...Done'
- file= open('/tmp/temp3ds_list', 'rU')
- lines= file.readlines()
- file.close()
-
- def between(v,a,b):
- if v <= max(a,b) and v >= min(a,b):
- return True
- return False
-
- for i, _obj in enumerate(lines):
- if between(i, 0,20):
- _obj= _obj[:-1]
- print 'Importing', _obj, '\nNUMBER', i, 'of', len(lines)
- _obj_file= _obj.split('/')[-1].split('\\')[-1]
- newScn= bpy.data.scenes.new(_obj_file)
+ def fileList(path):
+ for dirpath, dirnames, filenames in os.walk(path):
+ for filename in filenames:
+ yield os.path.join(dirpath, filename)
+
+ files = [f for f in fileList(DIR) if f.lower().endswith('.obj')]
+ files.sort()
+
+ for i, obj_file in enumerate(files):
+ if 0 < i < 20:
+ print 'Importing', obj_file, '\nNUMBER', i, 'of', len(files)
+ newScn= bpy.data.scenes.new(os.path.basename(obj_file))
newScn.makeCurrent()
- load_obj(_obj, False)
+ load_obj(obj_file, False, IMAGE_SEARCH=0)
print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
'''
diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py
index 9447f15fb79..a5547506dc7 100755..100644
--- a/release/scripts/import_web3d.py
+++ b/release/scripts/import_web3d.py
@@ -36,6 +36,8 @@ __bpydoc__ = """\
This script is an importer for the X3D and VRML97 file formats.
"""
+DEBUG = False
+
# This should work without a blender at all
try:
from Blender.sys import exists
@@ -48,6 +50,27 @@ def baseName(path):
def dirName(path):
return path[:-len(baseName(path))]
+def imageConvertCompat(path):
+
+ try: import os
+ except: return path
+ if os.sep=='\\': return path # assime win32 has quicktime, dont convert
+
+ if path.lower().endswith('.gif'):
+ path_to = path[:-3] + 'png'
+
+ '''
+ if exists(path_to):
+ return path_to
+ '''
+ # print '\n'+path+'\n'+path_to+'\n'
+ os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick
+
+ if exists(path_to):
+ return path_to
+
+ return path
+
# notes
# transform are relative
# order dosnt matter for loc/size/rot
@@ -62,7 +85,7 @@ def dirName(path):
def vrmlFormat(data):
'''
- Keep this as a valid vrml file, but format in a way we can pradict.
+ Keep this as a valid vrml file, but format in a way we can predict.
'''
# Strip all commends - # not in strings - warning multiline strings are ignored.
def strip_comment(l):
@@ -78,6 +101,7 @@ def vrmlFormat(data):
return l
# Most cases accounted for! if we have a comment at the end of the line do this...
+ #j = l.find('url "')
j = l.find('"')
if j == -1: # simple no strings
@@ -96,7 +120,39 @@ def vrmlFormat(data):
data = '\n'.join([strip_comment(l) for l in data.split('\n') ]) # remove all whitespace
+ EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/
+
+ if EXTRACT_STRINGS:
+ # We need this so we can detect URL's
+ data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace
+
+ string_ls = []
+
+ #search = 'url "'
+ search = '"'
+
+ ok = True
+ last_i = 0
+ while ok:
+ ok = False
+ i = data.find(search, last_i)
+ if i != -1:
+
+ start = i + len(search) # first char after end of search
+ end = data.find('"', start)
+ if end != -1:
+ item = data[start:end]
+ string_ls.append( item )
+ data = data[:start] + data[end:]
+ ok = True # keep looking
+
+ last_i = (end - len(item)) + 1
+ # print last_i, item, '|' + data[last_i] + '|'
+
+ # done with messy extracting strings part
+
+
# Bad, dont take strings into account
'''
data = data.replace('#', '\n#')
@@ -108,6 +164,28 @@ def vrmlFormat(data):
data = data.replace(']', '\n]\n')
data = data.replace(',', ' , ') # make sure comma's seperate
+ if EXTRACT_STRINGS:
+ # add strings back in
+
+ search = '"' # fill in these empty strings
+
+ ok = True
+ last_i = 0
+ while ok:
+ ok = False
+ i = data.find(search + '"', last_i)
+ # print i
+ if i != -1:
+ start = i + len(search) # first char after end of search
+ item = string_ls.pop(0)
+ # print item
+ data = data[:start] + item + data[start:]
+
+ last_i = start + len(item) + 1
+
+ ok = True
+
+
# More annoying obscure cases where USE or DEF are placed on a newline
# data = data.replace('\nDEF ', ' DEF ')
# data = data.replace('\nUSE ', ' USE ')
@@ -125,6 +203,7 @@ def vrmlFormat(data):
NODE_NORMAL = 1 # {}
NODE_ARRAY = 2 # []
NODE_REFERENCE = 3 # USE foobar
+# NODE_PROTO = 4 #
lines = []
@@ -135,6 +214,10 @@ def getNodePreText(i, words):
if i>=len(lines):
break
+ '''
+ elif lines[i].startswith('PROTO'):
+ return NODE_PROTO, i+1
+ '''
elif lines[i]=='{':
# words.append(lines[i]) # no need
# print "OK"
@@ -168,6 +251,23 @@ def is_nodeline(i, words):
if not lines[i][0].isalpha():
return 0, 0
+ #if lines[i].startswith('field'):
+ # return 0, 0
+
+ # Is this a prototype??
+ if lines[i].startswith('PROTO'):
+ words[:] = lines[i].split()
+ return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that
+ if lines[i].startswith('EXTERNPROTO'):
+ words[:] = lines[i].split()
+ return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that
+
+ '''
+ proto_type, new_i = is_protoline(i, words, proto_field_defs)
+ if new_i != -1:
+ return proto_type, new_i
+ '''
+
# Simple "var [" type
if lines[i+1] == '[':
if lines[i].count('"') % 2 == 0:
@@ -177,6 +277,7 @@ def is_nodeline(i, words):
node_type, new_i = getNodePreText(i, words)
if not node_type:
+ if DEBUG: print "not node_type", lines[i]
return 0, 0
# Ok, we have a { after some values
@@ -199,21 +300,46 @@ def is_numline(i):
'''
Does this line start with a number?
'''
+
+ # Works but too slow.
+ '''
+ l = lines[i]
+ for w in l.split():
+ if w==',':
+ pass
+ else:
+ try:
+ float(w)
+ return True
+
+ except:
+ return False
+
+ return False
+ '''
+
l = lines[i]
+
+ line_start = 0
+
+ if l.startswith(', '):
+ line_start += 2
+
line_end = len(l)-1
- line_end_new = l.find(' ') # comma's always have a space before them
+ line_end_new = l.find(' ', line_start) # comma's always have a space before them
if line_end_new != -1:
line_end = line_end_new
try:
- float(l[:line_end]) # works for a float or int
+ float(l[line_start:line_end]) # works for a float or int
return True
except:
return False
+
class vrmlNode(object):
- __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode'
+ __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode'
def __init__(self, parent, node_type, lineno):
self.id = None
self.node_type = node_type
@@ -228,10 +354,17 @@ class vrmlNode(object):
# This is only set from the root nodes.
# Having a filename also denotes a root node
self.filename = None
+ self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1"
# Store in the root node because each inline file needs its own root node and its own namespace
self.DEF_NAMESPACE = None
+ self.ROUTE_IPO_NAMESPACE = None
+ '''
self.FIELD_NAMESPACE = None
+ '''
+
+
+ self.PROTO_NAMESPACE = None
self.reference = None
@@ -241,28 +374,52 @@ class vrmlNode(object):
return
self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict
+
+ self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1"
+ self.proto_fields = [] # proto field usage "diffuseColor IS seatColor"
self.children = []
self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types
# Only available from the root node
+ '''
def getFieldDict(self):
if self.FIELD_NAMESPACE != None:
return self.FIELD_NAMESPACE
else:
return self.parent.getFieldDict()
+ '''
+ def getProtoDict(self):
+ if self.PROTO_NAMESPACE != None:
+ return self.PROTO_NAMESPACE
+ else:
+ return self.parent.getProtoDict()
def getDefDict(self):
if self.DEF_NAMESPACE != None:
return self.DEF_NAMESPACE
else:
return self.parent.getDefDict()
+
+ def getRouteIpoDict(self):
+ if self.ROUTE_IPO_NAMESPACE != None:
+ return self.ROUTE_IPO_NAMESPACE
+ else:
+ return self.parent.getRouteIpoDict()
def setRoot(self, filename):
self.filename = filename
- self.FIELD_NAMESPACE = {}
- self.DEF_NAMESPACE= {}
-
+ # self.FIELD_NAMESPACE = {}
+ self.DEF_NAMESPACE = {}
+ self.ROUTE_IPO_NAMESPACE = {}
+ self.PROTO_NAMESPACE = {}
+
+ def isRoot(self):
+ if self.filename == None:
+ return False
+ else:
+ return True
+
def getFilename(self):
if self.filename:
return self.filename
@@ -284,15 +441,36 @@ class vrmlNode(object):
except:
return None
- def getDefName(self):
+ def findSpecRecursive(self, spec):
self_real = self.getRealNode()
+ if spec == self_real.getSpec():
+ return self
- if 'DEF' in self_real.id:
- # print self_real.id
- return self_real.id[ list(self_real.id).index('DEF')+1 ]
- else:
- return None
+ for child in self_real.children:
+ if child.findSpecRecursive(spec):
+ return child
+
+ return None
+
+ def getPrefix(self):
+ if self.id:
+ return self.id[0]
+ return None
+
+ def getSpecialTypeName(self, typename):
+ self_real = self.getRealNode()
+ try: return self_real.id[ list(self_real.id).index(typename)+1 ]
+ except: return None
+
+
+ def getDefName(self):
+ return self.getSpecialTypeName('DEF')
+
+ def getProtoName(self):
+ return self.getSpecialTypeName('PROTO')
+ def getExternprotoName(self):
+ return self.getSpecialTypeName('EXTERNPROTO')
def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance
self_real = self.getRealNode()
@@ -329,7 +507,26 @@ class vrmlNode(object):
ancestry.append(self)
for child in self.getRealNode().children:
if child not in ancestry:
- child.getSerialized(results, ancestry)
+ # We dont want to load proto's, they are only references
+ # We could enforce this elsewhere
+
+ # Only add this in a very special case
+ # where the parent of this object is not the real parent
+ # - In this case we have added the proto as a child to a node instancing it.
+ # This is a bit arbitary, but its how Proto's are done with this importer.
+ if child.getProtoName() == None and child.getExternprotoName() == None:
+ child.getSerialized(results, ancestry)
+ else:
+
+ if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec()
+
+ self_spec = self.getSpec()
+
+ if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec:
+ if DEBUG: "FoundProto!"
+ child.getSerialized(results, ancestry)
+
+
return results
@@ -342,7 +539,7 @@ class vrmlNode(object):
child.searchNodeTypeID(node_spec, results)
return results
- def getFieldName(self, field):
+ def getFieldName(self, field, ancestry, AS_CHILD=False):
self_real = self.getRealNode() # incase we're an instance
for f in self_real.fields:
@@ -350,14 +547,81 @@ class vrmlNode(object):
if f and f[0] == field:
# print '\tfound field', f
- return f[1:]
+ if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor'
+ field_id = f[2]
+
+ # print "\n\n\n\n\n\nFOND IS!!!"
+ f_proto_lookup = None
+ f_proto_child_lookup = None
+ i = len(ancestry)
+ while i:
+ i -= 1
+ node = ancestry[i]
+ node = node.getRealNode()
+
+ # proto settings are stored in "self.proto_node"
+ if node.proto_node:
+ # Get the default value from the proto, this can be overwridden by the proto instace
+ # 'field SFColor legColor .8 .4 .7'
+ if AS_CHILD:
+ for child in node.proto_node.children:
+ #if child.id and len(child.id) >= 3 and child.id[2]==field_id:
+ if child.id and ('point' in child.id or 'points' in child.id):
+ f_proto_child_lookup = child
+
+ else:
+ for f_def in node.proto_node.proto_field_defs:
+ if len(f_def) >= 4:
+ if f_def[0]=='field' and f_def[2]==field_id:
+ f_proto_lookup = f_def[3:]
+
+ # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent.
+ # This is the setting as defined by the instance, including this setting is optional,
+ # and will override the default PROTO value
+ # eg: 'legColor 1 0 0'
+ if AS_CHILD:
+ for child in node.children:
+ if child.id and child.id[0]==field_id:
+ f_proto_child_lookup = child
+ else:
+ for f_def in node.fields:
+ if len(f_def) >= 2:
+ if f_def[0]==field_id:
+ if DEBUG: print "getFieldName(), found proto", f_def
+ f_proto_lookup = f_def[1:]
+
+
+ if AS_CHILD:
+ if f_proto_child_lookup:
+ if DEBUG:
+ print "getFieldName() - AS_CHILD=True, child found"
+ print f_proto_child_lookup
+ return f_proto_child_lookup
+ else:
+ return f_proto_lookup
+ else:
+ if AS_CHILD:
+ return None
+ else:
+ # Not using a proto
+ return f[1:]
+
# print '\tfield not found', field
+
+
+ # See if this is a proto name
+ if AS_CHILD:
+ child_array = None
+ for child in self_real.children:
+ if child.id and len(child.id) == 1 and child.id[0] == field:
+ return child
+
return None
- def getFieldAsInt(self, field, default):
+ def getFieldAsInt(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -371,10 +635,10 @@ class vrmlNode(object):
print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field)
return default
- def getFieldAsFloat(self, field, default):
+ def getFieldAsFloat(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -388,10 +652,10 @@ class vrmlNode(object):
print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field)
return default
- def getFieldAsFloatTuple(self, field, default):
+ def getFieldAsFloatTuple(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
# if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -412,10 +676,10 @@ class vrmlNode(object):
print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field)
return default
- def getFieldAsBool(self, field, default):
+ def getFieldAsBool(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -431,10 +695,10 @@ class vrmlNode(object):
print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field)
return default
- def getFieldAsString(self, field, default=None):
+ def getFieldAsString(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if len(f) < 1:
print '\t"%s" wrong length for string conversion for field "%s"' % (f, field)
@@ -456,22 +720,22 @@ class vrmlNode(object):
print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field)
return default
- def getFieldAsArray(self, field, group):
+ def getFieldAsArray(self, field, group, ancestry):
'''
For this parser arrays are children
'''
self_real = self.getRealNode() # incase we're an instance
- child_array = None
- for child in self_real.children:
- if child.id and len(child.id) == 1 and child.id[0] == field:
- child_array = child
- break
+ child_array = self_real.getFieldName(field, ancestry, True)
+ #if type(child_array)==list: # happens occasionaly
+ # array_data = child_array
+
if child_array==None:
+
# For x3d, should work ok with vrml too
# for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad.
- data_split = self.getFieldName(field)
+ data_split = self.getFieldName(field, ancestry)
if not data_split:
return []
array_data = ' '.join(data_split)
@@ -489,9 +753,12 @@ class vrmlNode(object):
print '\tWarning, could not parse array data from field'
array_data = []
else:
-
+ # print child_array
# Normal vrml
array_data = child_array.array_data
+
+
+ # print 'array_data', array_data
if group==-1 or len(array_data)==0:
return array_data
@@ -520,8 +787,6 @@ class vrmlNode(object):
# We requested a flat array
if group == 0:
return flat_array
-
-
new_array = []
sub_array = []
@@ -537,6 +802,30 @@ class vrmlNode(object):
return new_array
+ def getFieldAsStringArray(self, field, ancestry):
+ '''
+ Get a list of strings
+ '''
+ self_real = self.getRealNode() # incase we're an instance
+
+ child_array = None
+ for child in self_real.children:
+ if child.id and len(child.id) == 1 and child.id[0] == field:
+ child_array = child
+ break
+ if not child_array:
+ return []
+
+ # each string gets its own list, remove ""'s
+ try:
+ new_array = [f[0][1:-1] for f in child_array.fields]
+ except:
+ print '\twarning, string array could not be made'
+ new_array = []
+
+ return new_array
+
+
def getLevel(self):
# Ignore self_real
level = 0
@@ -551,7 +840,6 @@ class vrmlNode(object):
def __repr__(self):
level = self.getLevel()
ind = ' ' * level
-
if self.node_type==NODE_REFERENCE:
brackets = ''
elif self.node_type==NODE_NORMAL:
@@ -564,38 +852,102 @@ class vrmlNode(object):
else:
text = ''
- text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + ('lineno %d\n' % self.lineno)
+ text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + (' lineno %d\n' % self.lineno)
if self.node_type==NODE_REFERENCE:
+ text += ind + "(reference node)\n"
return text
- for item in self.fields:
+ if self.proto_node:
+ text += ind + 'PROTO NODE...\n'
+ text += str(self.proto_node)
+ text += ind + 'PROTO NODE_DONE\n'
+
+ text += ind + 'FIELDS:' + str(len(self.fields)) + '\n'
+
+ for i,item in enumerate(self.fields):
+ text += ind + 'FIELD:\n'
text += ind + str(item) +'\n'
+
+ text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n'
- #text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n'
- text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n'
+ for i,item in enumerate(self.proto_field_defs):
+ text += ind + 'PROTO_FIELD:\n'
+ text += ind + str(item) +'\n'
+
+ text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n'
+ #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n'
text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n'
- for child in self.children:
+ for i, child in enumerate(self.children):
+ text += ind + ('CHILD%d:\n' % i)
text += str(child)
text += '\n' + ind + brackets[1]
return text
- def parse(self, i):
- new_i = self.__parse(i)
+ def parse(self, i, IS_PROTO_DATA=False):
+ new_i = self.__parse(i, IS_PROTO_DATA)
# print self.id, self.getFilename()
- # If we were an inline then try load the file
+ # Check if this node was an inline or externproto
+
+ url_ls = []
+
if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline':
- url = self.getFieldAsString('url', None)
+ ancestry = [] # Warning! - PROTO's using this wont work at all.
+ url = self.getFieldAsString('url', None, ancestry)
+ if url:
+ url_ls = [(url, None)]
+ del ancestry
+
+ elif self.getExternprotoName():
+ # externproto
+ url_ls = []
+ for f in self.fields:
+
+ if type(f)==str:
+ f = [f]
+
+ for ff in f:
+ for f_split in ff.split('"'):
+ # print f_split
+ # "someextern.vrml#SomeID"
+ if '#' in f_split:
+
+ f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway
+
+ url_ls.append( (f_split, f_split_id) )
+ else:
+ url_ls.append( (f_split, None) )
+
+
+ # Was either an Inline or an EXTERNPROTO
+ if url_ls:
+
+ # print url_ls
- if url != None:
- if not exists(url):
- url = dirName(self.getFilename()) + baseName(url)
- if not exists(url):
+ for url, extern_key in url_ls:
+ print url
+ urls = []
+ urls.append( url )
+ urls.append( BPySys.caseInsensitivePath(urls[-1]) )
+
+ urls.append( dirName(self.getFilename()) + url )
+ urls.append( BPySys.caseInsensitivePath(urls[-1]) )
+
+ urls.append( dirName(self.getFilename()) + baseName(url) )
+ urls.append( BPySys.caseInsensitivePath(urls[-1]) )
+
+ try:
+ url = [url for url in urls if exists(url)][0]
+ url_found = True
+ except:
+ url_found = False
+
+ if not url_found:
print '\tWarning: Inline URL could not be found:', url
else:
if url==self.getFilename():
@@ -603,12 +955,12 @@ class vrmlNode(object):
else:
try:
- f = open(url, 'rU')
+ data = gzipOpen(url)
except:
print '\tWarning: cant open the file:', url
- f = None
+ data = None
- if f:
+ if data:
# Tricky - inline another VRML
print '\tLoading Inline:"%s"...' % url
@@ -616,26 +968,50 @@ class vrmlNode(object):
lines_old = lines[:]
- lines[:] = vrmlFormat( f.read() )
- f.close()
+ lines[:] = vrmlFormat( data )
lines.insert(0, '{')
lines.insert(0, 'root_node____')
lines.append('}')
+ '''
+ ff = open('/tmp/test.txt', 'w')
+ ff.writelines([l+'\n' for l in lines])
+ '''
child = vrmlNode(self, NODE_NORMAL, -1)
child.setRoot(url) # initialized dicts
child.parse(0)
+ # if self.getExternprotoName():
+ if self.getExternprotoName():
+ if not extern_key: # if none is spesified - use the name
+ extern_key = self.getSpec()
+
+ if extern_key:
+
+ self.children.remove(child)
+ child.parent = None
+
+ extern_child = child.findSpecRecursive(extern_key)
+
+ if extern_child:
+ self.children.append(extern_child)
+ extern_child.parent = self
+
+ if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key
+ else:
+ print "\tEXTERNPROTO ID not found!:", extern_key
+
# Watch it! - restore lines
lines[:] = lines_old
-
return new_i
- def __parse(self, i):
- # print 'parsing at', i,
- # print i, self.id, self.lineno
+ def __parse(self, i, IS_PROTO_DATA=False):
+ '''
+ print 'parsing at', i,
+ print i, self.id, self.lineno
+ '''
l = lines[i]
if l=='[':
@@ -644,9 +1020,11 @@ class vrmlNode(object):
i+=1
else:
words = []
+
node_type, new_i = is_nodeline(i, words)
if not node_type: # fail for parsing new node.
- raise "error"
+ print "Failed to parse new node"
+ raise ValueError
if self.node_type==NODE_REFERENCE:
# Only assign the reference and quit
@@ -660,40 +1038,72 @@ class vrmlNode(object):
# fill in DEF/USE
key = self.getDefName()
-
if key != None:
self.getDefDict()[ key ] = self
+ key = self.getProtoName()
+ if not key: key = self.getExternprotoName()
+
+ proto_dict = self.getProtoDict()
+ if key != None:
+ proto_dict[ key ] = self
+
+ # Parse the proto nodes fields
+ self.proto_node = vrmlNode(self, NODE_ARRAY, new_i)
+ new_i = self.proto_node.parse(new_i)
+
+ self.children.remove(self.proto_node)
+
+ # print self.proto_node
+
+ new_i += 1 # skip past the {
+
+
+ else: # If we're a proto instance, add the proto node as our child.
+ spec = self.getSpec()
+ try:
+ self.children.append( proto_dict[spec] )
+ #pass
+ except:
+ pass
+
+ del spec
+
+ del proto_dict, key
+
i = new_i
# print self.id
ok = True
while ok:
+ if i>=len(lines):
+ return len(lines)-1
+
l = lines[i]
- # print '\t', i, l
+ # print '\tDEBUG:', i, self.node_type, l
if l=='':
i+=1
continue
if l=='}':
- if self.node_type != NODE_NORMAL:
- print 'wrong node ending, expected an } ' + str(i)
- raise ""
+ if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too.
+ print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type)
+ if DEBUG:
+ raise ValueError
### print "returning", i
return i+1
if l==']':
if self.node_type != NODE_ARRAY:
- print 'wrong node ending, expected a ] ' + str(i)
- raise ""
+ print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type)
+ if DEBUG:
+ raise ValueError
### print "returning", i
return i+1
node_type, new_i = is_nodeline(i, [])
if node_type: # check text\n{
- ### print '\t\tgroup', i
child = vrmlNode(self, node_type, i)
i = child.parse(i)
- # print child.id, 'YYY'
elif l=='[': # some files have these anonymous lists
child = vrmlNode(self, NODE_ARRAY, i)
@@ -723,7 +1133,9 @@ class vrmlNode(object):
values = l_split
# This should not extend over multiple lines however it is possible
- self.array_data.extend( values )
+ # print self.array_data
+ if values:
+ self.array_data.extend( values )
i+=1
else:
words = l.split()
@@ -774,6 +1186,7 @@ class vrmlNode(object):
# this IS a key but the previous value was not a key, ot it was a defined field.
if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')):
field_list.append(field_context)
+
field_context = [value[j]]
else:
# The last item was not a value, multiple keys are needed in some cases.
@@ -796,18 +1209,9 @@ class vrmlNode(object):
if value[0]=='field':
# field SFFloat creaseAngle 4
- self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values
+ self.proto_field_defs.append(value)
else:
- # Get referenced field
- if len(value) >= 3 and value[1]=='IS':
- try:
- value = [ value[0] ] + self.getFieldDict()[ value[2] ]
- except:
- print '\tWarning, field could not be found:', value, 'TODO add support for exposedField'
- print '\t', self.getFieldDict()
- self.fields.append(value)
- else:
- self.fields.append(value)
+ self.fields.append(value)
i+=1
def gzipOpen(path):
@@ -843,12 +1247,13 @@ def vrml_parse(path):
lines.insert(0, '{')
lines.insert(0, 'dymmy_node')
lines.append('}')
-
# Use for testing our parsed output, so we can check on line numbers.
- ## ff = open('m:\\test.txt', 'w')
- ## ff.writelines([l+'\n' for l in lines])
-
+ '''
+ ff = open('/tmp/test.txt', 'w')
+ ff.writelines([l+'\n' for l in lines])
+ ff.close()
+ '''
# Now evaluate it
node_type, new_i = is_nodeline(0, [])
@@ -866,9 +1271,13 @@ def vrml_parse(path):
# Parse recursively
root.parse(0)
- # print root
+ # This prints a load of text
+ if DEBUG:
+ print root
+
return root, ''
+
# ====================== END VRML
@@ -881,7 +1290,7 @@ class x3dNode(vrmlNode):
vrmlNode.__init__(self, parent, node_type, -1)
self.x3dNode = x3dNode
- def parse(self):
+ def parse(self, IS_PROTO_DATA=False):
# print self.x3dNode.tagName
define = self.x3dNode.getAttributeNode('DEF')
@@ -923,7 +1332,9 @@ class x3dNode(vrmlNode):
# Other funcs operate from vrml, but this means we can wrap XML fields, still use nice utility funcs
# getFieldAsArray getFieldAsBool etc
- def getFieldName(self, field):
+ def getFieldName(self, field, ancestry, AS_CHILD=False):
+ # ancestry and AS_CHILD are ignored, only used for VRML now
+
self_real = self.getRealNode() # incase we're an instance
field_xml = self.x3dNode.getAttributeNode(field)
if field_xml:
@@ -996,6 +1407,9 @@ for i, f in enumerate(files):
# -----------------------------------------------------------------------------------
import bpy
import BPyImage
+import BPySys
+reload(BPySys)
+reload(BPyImage)
import Blender
from Blender import Texture, Material, Mathutils, Mesh, Types, Window
from Blender.Mathutils import TranslationMatrix
@@ -1018,12 +1432,12 @@ def translateScale(sca):
mat[2][2] = sca[2]
return mat
-def translateTransform(node):
- cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0, 0.0)
- rot = node.getFieldAsFloatTuple('rotation', None) # (0.0, 0.0, 1.0, 0.0)
- sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0, 1.0)
- scaori = node.getFieldAsFloatTuple('scaleOrientation', None) # (0.0, 0.0, 1.0, 0.0)
- tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0, 0.0)
+def translateTransform(node, ancestry):
+ cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0)
+ rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0)
+ sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0)
+ scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0)
+ tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0)
if cent:
cent_mat = TranslationMatrix(Vector(cent)).resize4x4()
@@ -1055,11 +1469,11 @@ def translateTransform(node):
return new_mat
-def translateTexTransform(node):
- cent = node.getFieldAsFloatTuple('center', None) # (0.0, 0.0)
- rot = node.getFieldAsFloat('rotation', None) # 0.0
- sca = node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0)
- tx = node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0)
+def translateTexTransform(node, ancestry):
+ cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0)
+ rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0
+ sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0)
+ tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0)
if cent:
@@ -1090,6 +1504,7 @@ def translateTexTransform(node):
return new_mat
+
def getFinalMatrix(node, mtx, ancestry):
transform_nodes = [node_tx for node_tx in ancestry if node_tx.getSpec() == 'Transform']
@@ -1101,17 +1516,17 @@ def getFinalMatrix(node, mtx, ancestry):
mtx = Matrix()
for node_tx in transform_nodes:
- mat = translateTransform(node_tx)
+ mat = translateTransform(node_tx, ancestry)
mtx = mtx * mat
return mtx
-def importMesh_IndexedFaceSet(geom, bpyima):
+def importMesh_IndexedFaceSet(geom, bpyima, ancestry):
# print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys()
- ccw = geom.getFieldAsBool('ccw', True)
- ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True) # per vertex or per face
- ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True)
+ ccw = geom.getFieldAsBool('ccw', True, ancestry)
+ ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face
+ ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry)
# This is odd how point is inside Coordinate
@@ -1120,14 +1535,14 @@ def importMesh_IndexedFaceSet(geom, bpyima):
coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml
- if coord: ifs_points = coord.getFieldAsArray('point', 3)
+ if coord: ifs_points = coord.getFieldAsArray('point', 3, ancestry)
else: coord = []
if not coord:
print '\tWarnint: IndexedFaceSet has no points'
return None, ccw
- ifs_faces = geom.getFieldAsArray('coordIndex', 0)
+ ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry)
coords_tex = None
if ifs_faces: # In rare cases this causes problems - no faces but UVs???
@@ -1137,8 +1552,8 @@ def importMesh_IndexedFaceSet(geom, bpyima):
coords_tex = geom.getChildBySpec('TextureCoordinate')
if coords_tex:
- ifs_texpoints = coords_tex.getFieldAsArray('point', 2)
- ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0)
+ ifs_texpoints = coords_tex.getFieldAsArray('point', 2, ancestry)
+ ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0, ancestry)
if not ifs_texpoints:
# IF we have no coords, then dont bother
@@ -1151,11 +1566,12 @@ def importMesh_IndexedFaceSet(geom, bpyima):
vcolor_spot = None # spot color when we dont have an array of colors
if vcolor:
# float to char
- ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3)]
- ifs_color_index = geom.getFieldAsArray('colorIndex', 0)
+ ifs_vcol = [(0,0,0)] # EEKADOODLE - vertex start at 1
+ ifs_vcol.extend([[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)])
+ ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry)
if not ifs_vcol:
- vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [])]
+ vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)]
# Convert faces into somthing blender can use
edges = []
@@ -1338,12 +1754,18 @@ def importMesh_IndexedFaceSet(geom, bpyima):
fv = f.verts
for i,c in enumerate(fcol):
color_index = fv[i].index # color index is vert index
- if ifs_color_index: color_index = ifs_color_index[color_index]
+ if ifs_color_index:
+ try:
+ color_index = ifs_color_index[color_index]
+ except:
+ print '\tWarning: per vertex color index out of range'
+ continue
- if len(ifs_vcol) < color_index:
+ if color_index < len(ifs_vcol):
c.r, c.g, c.b = ifs_vcol[color_index]
else:
- print '\tWarning: per face color index out of range'
+ #print '\tWarning: per face color index out of range'
+ pass
else:
if vcolor_spot: # use 1 color, when ifs_vcol is []
for c in fcol:
@@ -1361,24 +1783,27 @@ def importMesh_IndexedFaceSet(geom, bpyima):
col = ifs_vcol[color_index]
for i,c in enumerate(fcol):
- c.r, c.g, c.b = col
+ try:
+ c.r, c.g, c.b = col
+ except:
+ pass # incase its not between 0 and 255
bpymesh.verts.delete([0,]) # EEKADOODLE
return bpymesh, ccw
-def importMesh_IndexedLineSet(geom):
+def importMesh_IndexedLineSet(geom, ancestry):
# VRML not x3d
#coord = geom.getChildByName('coord') # 'Coordinate'
coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml
- if coord: points = coord.getFieldAsArray('point', 3)
+ if coord: points = coord.getFieldAsArray('point', 3, ancestry)
else: points = []
if not points:
print '\tWarning: IndexedLineSet had no points'
return None
- ils_lines = geom.getFieldAsArray('coordIndex', 0)
+ ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry)
lines = []
line = []
@@ -1417,11 +1842,11 @@ def importMesh_IndexedLineSet(geom):
return bpycurve
-def importMesh_PointSet(geom):
+def importMesh_PointSet(geom, ancestry):
# VRML not x3d
#coord = geom.getChildByName('coord') # 'Coordinate'
coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml
- if coord: points = coord.getFieldAsArray('point', 3)
+ if coord: points = coord.getFieldAsArray('point', 3, ancestry)
else: points = []
# vcolor = geom.getChildByName('color') # blender dosnt have per vertex color
@@ -1435,26 +1860,26 @@ GLOBALS['CIRCLE_DETAIL'] = 12
MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x')
-def importMesh_Sphere(geom):
+def importMesh_Sphere(geom, ancestry):
# bpymesh = bpy.data.meshes.new()
- diameter = geom.getFieldAsFloat('radius', 0.5) * 2 # * 2 for the diameter
+ diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter
bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter)
bpymesh.transform(MATRIX_Z_TO_Y)
return bpymesh
-def importMesh_Cylinder(geom):
+def importMesh_Cylinder(geom, ancestry):
# bpymesh = bpy.data.meshes.new()
- diameter = geom.getFieldAsFloat('radius', 1.0) * 2 # * 2 for the diameter
- height = geom.getFieldAsFloat('height', 2)
+ diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter
+ height = geom.getFieldAsFloat('height', 2, ancestry)
bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height)
bpymesh.transform(MATRIX_Z_TO_Y)
# Warning - Rely in the order Blender adds verts
# not nice design but wont change soon.
- bottom = geom.getFieldAsBool('bottom', True)
- side = geom.getFieldAsBool('side', True)
- top = geom.getFieldAsBool('top', True)
+ bottom = geom.getFieldAsBool('bottom', True, ancestry)
+ side = geom.getFieldAsBool('side', True, ancestry)
+ top = geom.getFieldAsBool('top', True, ancestry)
if not top: # last vert is top center of tri fan.
bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1])
@@ -1468,18 +1893,18 @@ def importMesh_Cylinder(geom):
return bpymesh
-def importMesh_Cone(geom):
+def importMesh_Cone(geom, ancestry):
# bpymesh = bpy.data.meshes.new()
- diameter = geom.getFieldAsFloat('bottomRadius', 1.0) * 2 # * 2 for the diameter
- height = geom.getFieldAsFloat('height', 2)
+ diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter
+ height = geom.getFieldAsFloat('height', 2, ancestry)
bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height)
bpymesh.transform(MATRIX_Z_TO_Y)
# Warning - Rely in the order Blender adds verts
# not nice design but wont change soon.
- bottom = geom.getFieldAsBool('bottom', True)
- side = geom.getFieldAsBool('side', True)
+ bottom = geom.getFieldAsBool('bottom', True, ancestry)
+ side = geom.getFieldAsBool('side', True, ancestry)
if not bottom: # last vert is on the bottom
bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1])
@@ -1488,10 +1913,10 @@ def importMesh_Cone(geom):
return bpymesh
-def importMesh_Box(geom):
+def importMesh_Box(geom, ancestry):
# bpymesh = bpy.data.meshes.new()
- size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0))
+ size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0), ancestry)
bpymesh = Mesh.Primitives.Cube(1.0)
# Scale the box to the size set
@@ -1517,6 +1942,9 @@ def importShape(node, ancestry):
bpymat = None
bpyima = None
texmtx = None
+
+ depth = 0 # so we can set alpha face flag later
+
if appr:
#mat = appr.getChildByName('material') # 'Material'
@@ -1532,7 +1960,7 @@ def importShape(node, ancestry):
textx = appr.getChildBySpec('TextureTransform')
if textx:
- texmtx = translateTexTransform(textx)
+ texmtx = translateTexTransform(textx, ancestry)
@@ -1544,29 +1972,34 @@ def importShape(node, ancestry):
# all values between 0.0 and 1.0, defaults from VRML docs
bpymat = bpy.data.materials.new()
- bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2)
- bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8])
+ bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry)
+ bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry)
# NOTE - blender dosnt support emmisive color
# Store in mirror color and approximate with emit.
- emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0])
+ emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry)
bpymat.mirCol = emit
bpymat.emit = (emit[0]+emit[1]+emit[2])/3.0
- bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2))) # 0-1 -> 1-511
- bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0])
- bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0)
+ bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511
+ bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry)
+ bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry)
if bpymat.alpha < 0.999:
bpymat.mode |= Material.Modes.ZTRANSP
if ima:
- # print ima
- ima_url = ima.getFieldAsString('url')
+
+ ima_url = ima.getFieldAsString('url', None, ancestry)
+
+ if ima_url==None:
+ try: ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images.
+ except: ima_url = None
+
if ima_url==None:
print "\twarning, image with no URL, this is odd"
else:
- bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False)
+ bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False, CONVERT_CALLBACK= imageConvertCompat)
if bpyima:
texture= bpy.data.textures.new()
texture.setType('Image')
@@ -1585,10 +2018,11 @@ def importShape(node, ancestry):
else:
bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL)
- ima_repS = ima.getFieldAsBool('repeatS', True)
- ima_repT = ima.getFieldAsBool('repeatT', True)
+ ima_repS = ima.getFieldAsBool('repeatS', True, ancestry)
+ ima_repT = ima.getFieldAsBool('repeatT', True, ancestry)
- texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512)
+ # To make this work properly we'd need to scale the UV's too, better to ignore th
+ # texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512)
if not ima_repS: bpyima.clampX = True
if not ima_repT: bpyima.clampY = True
@@ -1597,19 +2031,19 @@ def importShape(node, ancestry):
geom_spec = geom.getSpec()
ccw = True
if geom_spec == 'IndexedFaceSet':
- bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima)
+ bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima, ancestry)
elif geom_spec == 'IndexedLineSet':
- bpydata = importMesh_IndexedLineSet(geom)
+ bpydata = importMesh_IndexedLineSet(geom, ancestry)
elif geom_spec == 'PointSet':
- bpydata = importMesh_PointSet(geom)
+ bpydata = importMesh_PointSet(geom, ancestry)
elif geom_spec == 'Sphere':
- bpydata = importMesh_Sphere(geom)
+ bpydata = importMesh_Sphere(geom, ancestry)
elif geom_spec == 'Box':
- bpydata = importMesh_Box(geom)
+ bpydata = importMesh_Box(geom, ancestry)
elif geom_spec == 'Cylinder':
- bpydata = importMesh_Cylinder(geom)
+ bpydata = importMesh_Cylinder(geom, ancestry)
elif geom_spec == 'Cone':
- bpydata = importMesh_Cone(geom)
+ bpydata = importMesh_Cone(geom, ancestry)
else:
print '\tWarning: unsupported type "%s"' % geom_spec
return
@@ -1622,8 +2056,8 @@ def importShape(node, ancestry):
bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata)
if type(bpydata) == Types.MeshType:
- is_solid = geom.getFieldAsBool('solid', True)
- creaseAngle = geom.getFieldAsFloat('creaseAngle', None)
+ is_solid = geom.getFieldAsBool('solid', True, ancestry)
+ creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry)
if creaseAngle != None:
bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG))
@@ -1632,15 +2066,22 @@ def importShape(node, ancestry):
# Only ever 1 material per shape
if bpymat: bpydata.materials = [bpymat]
- if bpydata.faceUV and texmtx:
- # Apply texture transform?
- uv_copy = Vector()
- for f in bpydata.faces:
- for uv in f.uv:
- uv_copy.x = uv.x
- uv_copy.y = uv.y
-
- uv.x, uv.y = (uv_copy * texmtx)[0:2]
+ if bpydata.faceUV:
+
+ if depth==32: # set the faces alpha flag?
+ transp = Mesh.FaceTranspModes.ALPHA
+ for f in bpydata.faces:
+ f.transp = transp
+
+ if texmtx:
+ # Apply texture transform?
+ uv_copy = Vector()
+ for f in bpydata.faces:
+ for uv in f.uv:
+ uv_copy.x = uv.x
+ uv_copy.y = uv.y
+
+ uv.x, uv.y = (uv_copy * texmtx)[0:2]
# Done transforming the texture
@@ -1657,17 +2098,17 @@ def importShape(node, ancestry):
bpyob.setMatrix( getFinalMatrix(node, None, ancestry) )
-def importLamp_PointLight(node):
+def importLamp_PointLight(node, ancestry):
vrmlname = node.getDefName()
if not vrmlname: vrmlname = 'PointLight'
- # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO
- # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO
- color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
- intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
- location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0))
- # is_on = node.getFieldAsBool('on', True) # TODO
- radius = node.getFieldAsFloat('radius', 100.0)
+ # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO
+ # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO
+ color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
+ intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
+ location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry)
+ # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
+ radius = node.getFieldAsFloat('radius', 100.0, ancestry)
bpylamp = bpy.data.lamps.new()
bpylamp.setType('Lamp')
@@ -1679,15 +2120,15 @@ def importLamp_PointLight(node):
return bpylamp, mtx
-def importLamp_DirectionalLight(node):
+def importLamp_DirectionalLight(node, ancestry):
vrmlname = node.getDefName()
if not vrmlname: vrmlname = 'DirectLight'
# ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO
- color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
- direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0))
- intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
- # is_on = node.getFieldAsBool('on', True) # TODO
+ color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
+ direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry)
+ intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
+ # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
bpylamp = bpy.data.lamps.new(vrmlname)
bpylamp.setType('Sun')
@@ -1701,20 +2142,20 @@ def importLamp_DirectionalLight(node):
# looks like default values for beamWidth and cutOffAngle were swapped in VRML docs.
-def importLamp_SpotLight(node):
+def importLamp_SpotLight(node, ancestry):
vrmlname = node.getDefName()
if not vrmlname: vrmlname = 'SpotLight'
- # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0) # TODO
- # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO
- beamWidth = node.getFieldAsFloat('beamWidth', 1.570796) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
- color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
- cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
- direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0))
- intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
- location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0))
- # is_on = node.getFieldAsBool('on', True) # TODO
- radius = node.getFieldAsFloat('radius', 100.0)
+ # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO
+ # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO
+ beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
+ color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
+ cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
+ direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry)
+ intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
+ location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry)
+ # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
+ radius = node.getFieldAsFloat('radius', 100.0, ancestry)
bpylamp = bpy.data.lamps.new(vrmlname)
bpylamp.setType('Spot')
@@ -1733,21 +2174,21 @@ def importLamp_SpotLight(node):
# Convert
# lamps have their direction as -z, y==up
- mtx = TranslationMatrix(Vector(location)) * Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4()
+ mtx = Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4() * TranslationMatrix(Vector(location))
return bpylamp, mtx
def importLamp(node, spec, ancestry):
if spec=='PointLight':
- bpylamp,mtx = importLamp_PointLight(node)
+ bpylamp,mtx = importLamp_PointLight(node, ancestry)
elif spec=='DirectionalLight':
- bpylamp,mtx = importLamp_DirectionalLight(node)
+ bpylamp,mtx = importLamp_DirectionalLight(node, ancestry)
elif spec=='SpotLight':
- bpylamp,mtx = importLamp_SpotLight(node)
+ bpylamp,mtx = importLamp_SpotLight(node, ancestry)
else:
print "Error, not a lamp"
- raise ""
+ raise ValueError
bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp)
bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) )
@@ -1757,17 +2198,17 @@ def importViewpoint(node, ancestry):
name = node.getDefName()
if not name: name = 'Viewpoint'
- fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
- # jump = node.getFieldAsBool('jump', True)
- orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0))
- position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 10.0))
- description = node.getFieldAsString('description', '')
+ fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
+ # jump = node.getFieldAsBool('jump', True, ancestry)
+ orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry)
+ position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry)
+ description = node.getFieldAsString('description', '', ancestry)
bpycam = bpy.data.cameras.new(name)
bpycam.angle = fieldOfView
- mtx = TranslationMatrix(Vector(position)) * translateRotation(orientation) * MATRIX_Z_TO_Y
+ mtx = translateRotation(orientation) * TranslationMatrix(Vector(position))
bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpycam)
@@ -1781,6 +2222,173 @@ def importTransform(node, ancestry):
bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name)
bpyob.setMatrix( getFinalMatrix(node, None, ancestry) )
+ # so they are not too annoying
+ bpyob.emptyShape= Blender.Object.EmptyShapes.AXES
+ bpyob.drawSize= 0.2
+
+
+#def importTimeSensor(node):
+
+
+def translatePositionInterpolator(node, ipo, ancestry):
+ key = node.getFieldAsArray('key', 0, ancestry)
+ keyValue = node.getFieldAsArray('keyValue', 3, ancestry)
+
+ try:
+ loc_x = ipo.addCurve('LocX')
+ loc_y = ipo.addCurve('LocY')
+ loc_z = ipo.addCurve('LocZ')
+ except ValueError:
+ return
+
+ loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+
+ for i, time in enumerate(key):
+ try: x,y,z = keyValue[i]
+ except: continue
+
+ loc_x.append((time,x))
+ loc_y.append((time,y))
+ loc_z.append((time,z))
+
+def translateOrientationInterpolator(node, ipo, ancestry):
+ key = node.getFieldAsArray('key', 0, ancestry)
+ keyValue = node.getFieldAsArray('keyValue', 4, ancestry)
+
+ try:
+ rot_x = ipo.addCurve('RotX')
+ rot_y = ipo.addCurve('RotY')
+ rot_z = ipo.addCurve('RotZ')
+ except ValueError:
+ return
+
+ rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+
+ for i, time in enumerate(key):
+ try: x,y,z,w = keyValue[i]
+ except: continue
+
+ mtx = translateRotation((x,y,z,w))
+ eul = mtx.toEuler()
+ rot_x.append((time,eul.x/10.0))
+ rot_y.append((time,eul.y/10.0))
+ rot_z.append((time,eul.z/10.0))
+
+# Untested!
+def translateScalarInterpolator(node, ipo, ancestry):
+ key = node.getFieldAsArray('key', 0, ancestry)
+ keyValue = node.getFieldAsArray('keyValue', 4, ancestry)
+
+ try:
+ sca_x = ipo.addCurve('ScaleX')
+ sca_y = ipo.addCurve('ScaleY')
+ sca_z = ipo.addCurve('ScaleZ')
+ except ValueError:
+ return
+
+ sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+
+ for i, time in enumerate(key):
+ try: x,y,z = keyValue[i]
+ except: continue
+ sca_x.append((time,x/10.0))
+ sca_y.append((time,y/10.0))
+ sca_z.append((time,z/10.0))
+
+def translateTimeSensor(node, ipo, ancestry):
+ '''
+ Apply a time sensor to an IPO, VRML has many combinations of loop/start/stop/cycle times
+ to give different results, for now just do the basics
+ '''
+
+ time_cu = ipo.addCurve('Time')
+ time_cu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+
+ cycleInterval = node.getFieldAsFloat('cycleInterval', None, ancestry)
+
+ startTime = node.getFieldAsFloat('startTime', 0.0, ancestry)
+ stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry)
+
+ if cycleInterval != None:
+ stopTime = startTime+cycleInterval
+
+ loop = node.getFieldAsBool('loop', False, ancestry)
+
+ time_cu.append((1+startTime, 0.0))
+ time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10
+
+
+ if loop:
+ time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST,
+
+
+def importRoute(node, ancestry):
+ '''
+ Animation route only at the moment
+ '''
+
+ if not hasattr(node, 'fields'):
+ return
+
+ routeIpoDict = node.getRouteIpoDict()
+
+ def getIpo(id):
+ try: ipo = routeIpoDict[id]
+ except: ipo = routeIpoDict[id] = bpy.data.ipos.new('web3d_ipo', 'Object')
+ return ipo
+
+ # for getting definitions
+ defDict = node.getDefDict()
+ '''
+ Handles routing nodes to eachother
+
+ROUTE vpPI.value_changed TO champFly001.set_position
+ROUTE vpOI.value_changed TO champFly001.set_orientation
+ROUTE vpTs.fraction_changed TO vpPI.set_fraction
+ROUTE vpTs.fraction_changed TO vpOI.set_fraction
+ROUTE champFly001.bindTime TO vpTs.set_startTime
+ '''
+
+ #from_id, from_type = node.id[1].split('.')
+ #to_id, to_type = node.id[3].split('.')
+
+ #value_changed
+ set_position_node = None
+ set_orientation_node = None
+ time_node = None
+
+ for field in node.fields:
+ if field and field[0]=='ROUTE':
+ try:
+ from_id, from_type = field[1].split('.')
+ to_id, to_type = field[3].split('.')
+ except:
+ print "Warning, invalid ROUTE", field
+ continue
+
+ if from_type == 'value_changed':
+ if to_type == 'set_position':
+ ipo = getIpo(to_id)
+ set_data_from_node = defDict[from_id]
+ translatePositionInterpolator(set_data_from_node, ipo, ancestry)
+
+ if to_type in ('set_orientation', 'rotation'):
+ ipo = getIpo(to_id)
+ set_data_from_node = defDict[from_id]
+ translateOrientationInterpolator(set_data_from_node, ipo, ancestry)
+
+ if to_type == 'set_scale':
+ ipo = getIpo(to_id)
+ set_data_from_node = defDict[from_id]
+ translateScalarInterpolator(set_data_from_node, ipo, ancestry)
+
+ elif from_type =='bindTime':
+ ipo = getIpo(from_id)
+ time_node = defDict[to_id]
+ translateTimeSensor(time_node, ipo, ancestry)
+
+
+
def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None):
@@ -1809,6 +2417,16 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None):
# continue
spec = node.getSpec()
+ '''
+ prefix = node.getPrefix()
+ if prefix=='PROTO':
+ pass
+ else
+ '''
+ if HELPER_FUNC and HELPER_FUNC(node, ancestry):
+ # Note, include this function so the VRML/X3D importer can be extended
+ # by an external script. - gets first pick
+ pass
if spec=='Shape':
importShape(node, ancestry)
elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'):
@@ -1818,14 +2436,38 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None):
elif spec=='Transform':
# Only use transform nodes when we are not importing a flat object hierarchy
if PREF_FLAT==False:
- importTransform(node, ancestry)
- else:
-
- # Note, include this function so the VRML/X3D importer can be extended
- # by an external script.
- if HELPER_FUNC:
- HELPER_FUNC(node, ancestry)
+ importTransform(node, ancestry)
+ '''
+ # These are delt with later within importRoute
+ elif spec=='PositionInterpolator':
+ ipo = bpy.data.ipos.new('web3d_ipo', 'Object')
+ translatePositionInterpolator(node, ipo)
+ '''
+
+
+
+ # After we import all nodes, route events - anim paths
+ for node, ancestry in all_nodes:
+ importRoute(node, ancestry)
+
+ for node, ancestry in all_nodes:
+ if node.isRoot():
+ # we know that all nodes referenced from will be in
+ # routeIpoDict so no need to run node.getDefDict() for every node.
+ routeIpoDict = node.getRouteIpoDict()
+ defDict = node.getDefDict()
+ for key, ipo in routeIpoDict.iteritems():
+
+ # Assign anim curves
+ node = defDict[key]
+ if node.blendObject==None: # Add an object if we need one for animation
+ node.blendObject = bpy.data.scenes.active.objects.new('Empty', 'AnimOb') # , name)
+
+ node.blendObject.setIpo(ipo)
+
+
+
# Add in hierarchy
if PREF_FLAT==False:
child_dict = {}
@@ -1886,7 +2528,7 @@ def load_ui(path):
if __name__ == '__main__':
Window.FileSelector(load_ui, 'Import X3D/VRML97')
-
+
# Testing stuff
# load_web3d('/test.x3d')
@@ -1921,24 +2563,32 @@ if __name__ == '__main__':
# load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs
-'''
-import os
-# files = os.popen('find /fe/wrl -iname "*.wrl"').readlines()
-# files = os.popen('find /fe/x3d -iname "*.x3d"').readlines()
-files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines()
-files.sort()
-tot = len(files)
-for i, f in enumerate(files):
- if i < 12803 or i > 1000000:
- continue
- #if i != 12686:
- # continue
+
+def test():
+ import os
- f = f.strip()
- print f, i, tot
- sce = bpy.data.scenes.new(f.split('/')[-1])
- bpy.data.scenes.active = sce
- # Window.
- load_web3d(f, PREF_FLAT=True)
-''' \ No newline at end of file
+ files = os.popen('find /fe/wrl -iname "*.wrl"').readlines()
+ # files = os.popen('find /fe/x3d -iname "*.x3d"').readlines()
+ # files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines()
+
+ files.sort()
+ tot = len(files)
+ for i, f in enumerate(files):
+ if i < 124 or i > 1000000:
+ continue
+
+ #if i != 1068:
+ # continue
+
+ #if i != 12686:
+ # continue
+
+ f = f.strip()
+ print f, i, tot
+ sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1])
+ bpy.data.scenes.active = sce
+ # Window.
+ load_web3d(f, PREF_FLAT=True)
+
+# test()
diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py
index 458e61f3a28..bbfb9649c69 100644
--- a/release/scripts/lightwave_export.py
+++ b/release/scripts/lightwave_export.py
@@ -68,8 +68,13 @@ v5.5 format.
# ***** END GPL LICENCE BLOCK *****
import Blender
-import struct, cStringIO, operator
import BPyMesh
+try: import struct
+except: struct = None
+try: import cStringIO
+except: cStringIO = None
+try: import operator
+except: operator = None
VCOL_NAME = "\251 Per-Face Vertex Colors"
DEFAULT_NAME = "\251 Blender Default"
@@ -95,12 +100,16 @@ def write(filename):
icon = "" #generate_icon()
meshes = []
+ mesh_object_name_lookup = {} # for name lookups only
+
for obj in objects:
mesh = BPyMesh.getMeshFromObject(obj, None, True, False, scn)
if mesh:
mesh.transform(obj.matrixWorld)
meshes.append(mesh)
-
+ mesh_object_name_lookup[mesh] = obj.name
+ del obj
+
material_names = get_used_material_names(meshes)
tags = generate_tags(material_names)
surfs = generate_surfs(material_names)
@@ -111,7 +120,7 @@ def write(filename):
layer_index = 0
for mesh in meshes:
- layr = generate_layr(obj.name, layer_index)
+ layr = generate_layr(mesh_object_name_lookup[mesh], layer_index)
pnts = generate_pnts(mesh)
bbox = generate_bbox(mesh)
pols = generate_pols(mesh)
@@ -149,7 +158,9 @@ def write(filename):
layer_index += 1
mesh.verts = None # save some ram
-
+
+ del mesh_object_name_lookup
+
for surf in surfs:
chunks.append(surf)
@@ -345,23 +356,28 @@ def generate_vmad_vc(mesh):
# === Generate Per-Face UV Coords (VMAD Chunk) ===
# ================================================
def generate_vmad_uv(mesh):
- data = cStringIO.StringIO()
- data.write("TXUV") # type
- data.write(struct.pack(">H", 2)) # dimension
- data.write(generate_nstring("Blender's UV Coordinates")) # name
+ layers = mesh.getUVLayerNames()
+ org_uv = mesh.activeUVLayer
+ for l in layers:
+ mesh.activeUVLayer = l
+ data = cStringIO.StringIO()
+ data.write("TXUV") # type
+ data.write(struct.pack(">H", 2)) # dimension
+ data.write(generate_nstring(l)) # name
+ for i, f in enumerate(mesh.faces):
+ if not i%100:
+ Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates")
+
+ uv = f.uv
+ f_v = f.v
+ for j in xrange(len(f)-1, -1, -1): # Reverse order
+ U,V = uv[j]
+ v = f_v[j].index
+ data.write(struct.pack(">H", v)) # vertex index
+ data.write(struct.pack(">H", i)) # face index
+ data.write(struct.pack(">ff", U, V))
- for i, f in enumerate(mesh.faces):
- if not i%100:
- Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates")
-
- uv = f.uv
- f_v = f.v
- for j in xrange(len(f)-1, -1, -1): # Reverse order
- U,V = uv[j]
- v = f_v[j].index
- data.write(struct.pack(">H", v)) # vertex index
- data.write(struct.pack(">H", i)) # face index
- data.write(struct.pack(">ff", U, V))
+ mesh.activeUVLayer = org_uv
return data.getvalue()
# ======================================
@@ -685,4 +701,7 @@ def fs_callback(filename):
if not filename.lower().endswith('.lwo'): filename += '.lwo'
write(filename)
-Blender.Window.FileSelector(fs_callback, "Export LWO", Blender.sys.makename(ext='.lwo'))
+if struct and cStringIO and operator:
+ Blender.Window.FileSelector(fs_callback, "Export LWO", Blender.sys.makename(ext='.lwo'))
+else:
+ Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
diff --git a/release/scripts/md2_export.py b/release/scripts/md2_export.py
index 588336ed447..f0fe6b9af40 100644
--- a/release/scripts/md2_export.py
+++ b/release/scripts/md2_export.py
@@ -612,29 +612,9 @@ class md2_obj:
######################################################
# Validation
######################################################
+
def validation(object):
global user_frame_list
-
- #move the object to the origin if it's not already there
- if object.getLocation('worldspace')!=(0.0, 0.0, 0.0):
- print "Model not centered at origin"
- result=Blender.Draw.PupMenu("Model not centered at origin%t|Center (will not work with animations!)|Do not center")
- if result==1:
- object.setLocation(0.0,0.0,0.0)
-
- #resize the object in case it is not the right size
- if object.getSize('worldspace')!=(1.0,1.0,1.0):
- print "Object is scaled-You should scale the mesh verts, not the object"
- result=Blender.Draw.PupMenu("Object is scaled-You should scale the mesh verts, not the object%t|Fix scale (will not work with animations!)|Do not scale")
- if result==1:
- object.setSize(1.0,1.0,1.0)
-
- if object.getEuler('worldspace')!=Blender.Mathutils.Euler(0.0,0.0,0.0):
- print "object.rot: ", object.getEuler('worldspace')
- print "Object is rotated-You should rotate the mesh verts, not the object"
- result=Blender.Draw.PupMenu("Object is rotated-You should rotate the mesh verts, not the object%t|Fix rotation (will not work with animations!)|Do not rotate")
- if result==1:
- object.setEuler([0.0,0.0,0.0])
#get access to the mesh data
mesh=object.getData(False, True) #get the object (not just name) and the Mesh, not NMesh
@@ -696,7 +676,8 @@ def validation(object):
result=Blender.Draw.PupMenu("Model has more than 1 texture map assigned%t|Quit")
#return False
if mesh_image:
- size=mesh_image.getSize()
+ try: size=mesh_image.getSize()
+ except: size= 256,256 # No image data
#is this really what the user wants
if (size[0]!=256 or size[1]!=256):
print "Texture map size is non-standard (not 256x256), it is: ",size[0],"x",size[1]
@@ -753,6 +734,8 @@ def fill_md2(md2, object):
#create the vertex list from the first frame
Blender.Set("curframe", 1)
+ has_uvs = mesh.faceUV
+
#header information
md2.ident=844121161
md2.version=8
@@ -761,9 +744,11 @@ def fill_md2(md2, object):
#get the skin information
#use the first faces' image for the texture information
- if mesh.faceUV:
+ if has_uvs:
mesh_image=mesh.faces[0].image
- size=mesh_image.getSize()
+ try: size=mesh_image.getSize()
+ except: size= 256,256
+
md2.skin_width=size[0]
md2.skin_height=size[1]
md2.num_skins=1
@@ -777,12 +762,14 @@ def fill_md2(md2, object):
#put texture information in the md2 structure
#build UV coord dictionary (prevents double entries-saves space)
+ if not has_uvs:
+ t=(0,0)
+
for face in mesh.faces:
for i in xrange(0,3):
- if mesh.faceUV:
+ if has_uvs:
t=(face.uv[i])
- else:
- t=(0,0)
+
tex_key=(t[0],t[1])
if not tex_list.has_key(tex_key):
tex_list[tex_key]=tex_count
@@ -798,16 +785,25 @@ def fill_md2(md2, object):
#put faces in the md2 structure
#for each face in the model
+
+ if not has_uvs:
+ uv_coords=[(0,0)]*3
+
for this_face in xrange(0, md2.num_faces):
md2.faces.append(md2_face())
+ mf = mesh.faces[this_face]
+ mf_v = mf.v
+ if has_uvs:
+ uv_coords = mf.uv
+
for i in xrange(0,3):
#blender uses indexed vertexes so this works very well
- md2.faces[this_face].vertex_index[i]=mesh.faces[this_face].verts[i].index
+ md2.faces[this_face].vertex_index[i] = mf_v[i].index
#lookup texture index in dictionary
- if mesh.faceUV:
- uv_coord=(mesh.faces[this_face].uv[i])
- else:
- uv_coord=(0,0)
+ if has_uvs:
+ uv_coord = uv_coords[i]
+ # otherwise we set it before
+
tex_key=(uv_coord[0],uv_coord[1])
tex_index=tex_list[tex_key]
md2.faces[this_face].texture_index[i]=tex_index
@@ -837,13 +833,18 @@ def fill_md2(md2, object):
for frame_counter in xrange(0,md2.num_frames):
progress+=progressIncrement
- Blender.Window.DrawProgressBar(progress, "Calculating Frame: "+str(frame_counter))
+ Blender.Window.DrawProgressBar(progress, "Calculating Frame: %d of %d" % (frame_counter, md2.num_frames))
#add a frame
md2.frames.append(md2_frame())
#update the mesh objects vertex positions for the animation
Blender.Set("curframe", frame_counter) #set blender to the correct frame
- mesh.getFromObject(object.name) #update the mesh to make verts current
+
+
+
+
+ mesh.getFromObject(object) #update the mesh to make verts current
+ mesh.transform(object.matrixWorld)
#each frame has a scale and transform value that gets the vertex value between 0-255
#since the scale and transform are the same for the all the verts in the frame, we only need
@@ -862,13 +863,14 @@ def fill_md2(md2, object):
frame_max_z=-100000.0
for face in mesh.faces:
- for vert in face.verts:
- if frame_min_x>vert.co[1]: frame_min_x=vert.co[1]
- if frame_max_x<vert.co[1]: frame_max_x=vert.co[1]
- if frame_min_y>vert.co[0]: frame_min_y=vert.co[0]
- if frame_max_y<vert.co[0]: frame_max_y=vert.co[0]
- if frame_min_z>vert.co[2]: frame_min_z=vert.co[2]
- if frame_max_z<vert.co[2]: frame_max_z=vert.co[2]
+ for vert in face:
+ co = vert.co
+ if frame_min_x>co[1]: frame_min_x=co[1]
+ if frame_max_x<co[1]: frame_max_x=co[1]
+ if frame_min_y>co[0]: frame_min_y=co[0]
+ if frame_max_y<co[0]: frame_max_y=co[0]
+ if frame_min_z>co[2]: frame_min_z=co[2]
+ if frame_max_z<co[2]: frame_max_z=co[2]
#the scale is the difference between the min and max (on that axis) / 255
frame_scale_x=(frame_max_x-frame_min_x)/255
@@ -896,9 +898,10 @@ def fill_md2(md2, object):
#then translates the point so it's not less than 0
#then scale it so it's between 0..255
#print "frame scale : ", frame_scale_x, " ", frame_scale_y, " ", frame_scale_z
- new_x=int((mesh.verts[vert_counter].co[1]-frame_trans_x)/frame_scale_x)
- new_y=int((mesh.verts[vert_counter].co[0]-frame_trans_y)/frame_scale_y)
- new_z=int((mesh.verts[vert_counter].co[2]-frame_trans_z)/frame_scale_z)
+ co = mesh.verts[vert_counter].co
+ new_x=int((co[1]-frame_trans_x)/frame_scale_x)
+ new_y=int((co[0]-frame_trans_y)/frame_scale_y)
+ new_z=int((co[2]-frame_trans_z)/frame_scale_z)
#put them in the structure
md2.frames[frame_counter].vertices[vert_counter].vertices=(new_x, new_y, new_z)
@@ -908,19 +911,20 @@ def fill_md2(md2, object):
#swap y and x for difference in axis orientation
- x1=-mesh.verts[vert_counter].no[1]
- y1=mesh.verts[vert_counter].no[0]
- z1=mesh.verts[vert_counter].no[2]
+ no = mesh.verts[vert_counter].no
+ x1= -no[1]
+ y1= no[0]
+ z1= no[2]
+
for j in xrange(0,162):
#dot = (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
- dot = (x1*MD2_NORMALS[j][0]+
- y1*MD2_NORMALS[j][1]+
- z1*MD2_NORMALS[j][2]);
+ dot = (x1*MD2_NORMALS[j][0] + y1*MD2_NORMALS[j][1]+ z1*MD2_NORMALS[j][2]);
if (dot > maxdot):
maxdot = dot;
maxdotindex = j;
- md2.frames[frame_counter].vertices[vert_counter].lightnormalindex=maxdotindex+2
+ # See patch [#19206], gives good info on this line below.
+ md2.frames[frame_counter].vertices[vert_counter].lightnormalindex=maxdotindex
del maxdot, maxdotindex
del new_x, new_y, new_z
diff --git a/release/scripts/mesh_edges2curves.py b/release/scripts/mesh_edges2curves.py
index 006bdf10b49..670165dda51 100644
--- a/release/scripts/mesh_edges2curves.py
+++ b/release/scripts/mesh_edges2curves.py
@@ -112,7 +112,7 @@ def mesh2polys():
Window.EditMode(0)
me = meshOb.getData(mesh=1)
polygons= polysFromMesh(me)
- w=t=1
+ w = 1.0
cu= Curve.New()
cu.name = me.name
cu.setFlag(1)
@@ -128,7 +128,7 @@ def mesh2polys():
vIdx= 0
v= poly[vIdx]
- cu.appendNurb([v.co.x, v.co.y, v.co.z, w, t])
+ cu.appendNurb((v.co.x, v.co.y, v.co.z, w))
vIdx += 1
cu[i].type= 0 # Poly Line
@@ -139,7 +139,7 @@ def mesh2polys():
# Add all the points in the polyline.
while vIdx<len(poly):
v= poly[vIdx]
- cu.appendPoint(i, [v.co.x, v.co.y, v.co.z, w])
+ cu.appendPoint(i, (v.co.x, v.co.y, v.co.z, w))
vIdx+=1
i+=1
Window.WaitCursor(0)
diff --git a/release/scripts/mesh_mirror_tool.py b/release/scripts/mesh_mirror_tool.py
index 33ce6936c7f..8e22e26cd53 100644
--- a/release/scripts/mesh_mirror_tool.py
+++ b/release/scripts/mesh_mirror_tool.py
@@ -3,7 +3,7 @@
Name: 'Mirror Vertex Locations & Weight'
Blender: 241
Group: 'Mesh'
-Tooltip: 'Snap Verticies to X mirrord locations and weights.'
+Tooltip: 'Snap Verticies to X mirrored locations and weights.'
"""
__author__ = "Campbell Barton aka ideasman42"
@@ -11,11 +11,11 @@ __url__ = ["www.blender.org", "blenderartists.org", "www.python.org"]
__version__= '1.0'
__bpydoc__= '''\
This script is used to mirror vertex locations and weights
-It is usefull if you have a model that was made symetrical
+It is useful if you have a model that was made symmetrical
but has verts that have moved from their mirrored locations slightly,
-casuing blenders X-Mirror options not to work.
+causing blenders X-Mirror options not to work.
-Weights can be mirrored too, this is usefull if you want to model 1 side of a mesh, copy the mesh and flip it.
+Weights can be mirrored too, this is useful if you want to model 1 side of a mesh, copy the mesh and flip it.
You can then use this script to mirror to the copy, even creating new flipped vertex groups, renaming group name left to right or .L to .R
Vertex positions are mirrored by doing a locational lookup,
diff --git a/release/scripts/mesh_poly_reduce_grid.py b/release/scripts/mesh_poly_reduce_grid.py
new file mode 100644
index 00000000000..2903909027a
--- /dev/null
+++ b/release/scripts/mesh_poly_reduce_grid.py
@@ -0,0 +1,351 @@
+#!BPY
+"""
+Name: 'Poly Reduce Selection (Unsubsurf)'
+Blender: 245
+Group: 'Mesh'
+Tooltip: 'predictable mesh simplifaction maintaining face loops'
+"""
+
+from Blender import Scene, Mesh, Window, sys
+import BPyMessages
+import bpy
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Script copyright (C) Campbell J Barton
+#
+# 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 *****
+# --------------------------------------------------------------------------
+
+
+def my_mesh_util(me):
+ me_verts = me.verts
+
+ vert_faces = [ [] for v in me_verts]
+ vert_faces_corner = [ [] for v in me_verts]
+
+
+ # Ignore topology where there are not 2 faces connected to an edge.
+ edge_count = {}
+ for f in me.faces:
+ for edkey in f.edge_keys:
+ try:
+ edge_count[edkey] += 1
+ except:
+ edge_count[edkey] = 1
+
+ for edkey, count in edge_count.iteritems():
+
+ # Ignore verts that connect to edges with more than 2 faces.
+ if count != 2:
+ vert_faces[edkey[0]] = None
+ vert_faces[edkey[1]] = None
+ # Done
+
+
+
+ def faces_set_verts(face_ls):
+ unique_verts = set()
+ for f in face_ls:
+ for v in f:
+ unique_verts.add(v.index)
+ return unique_verts
+
+ for f in me.faces:
+ for corner, v in enumerate(f):
+ i = v.index
+ if vert_faces[i] != None:
+ vert_faces[i].append(f)
+ vert_faces_corner[i].append( corner )
+
+ grid_data_ls = []
+
+ for vi, face_ls in enumerate(vert_faces):
+ if face_ls != None:
+ if len(face_ls) == 4:
+ if face_ls[0].sel and face_ls[1].sel and face_ls[2].sel and face_ls[3].sel:
+ # Support triangles also
+ unique_vert_count = len(faces_set_verts(face_ls))
+ quads = 0
+ for f in face_ls:
+ if len(f) ==4:
+ quads += 1
+ if unique_vert_count==5+quads: # yay we have a grid
+ grid_data_ls.append( (vi, face_ls) )
+
+ elif len(face_ls) == 3:
+ if face_ls[0].sel and face_ls[1].sel and face_ls[2].sel:
+ unique_vert_count = len(faces_set_verts(face_ls))
+ if unique_vert_count==4: # yay we have 3 triangles to make into a bigger triangle
+ grid_data_ls.append( (vi, face_ls) )
+
+
+
+ # Now sort out which grid faces to use
+
+
+ # This list will be used for items we can convert, vertex is key, faces are values
+ grid_data_dict = {}
+
+ if not grid_data_ls:
+ print "doing nothing"
+ return
+
+ # quick lookup for the opposing corner of a qiad
+ quad_diag_mapping = 2,3,0,1
+
+ verts_used = [0] * len(me_verts) # 0 == untouched, 1==should touch, 2==touched
+ verts_used[grid_data_ls[0][0]] = 1 # start touching 1!
+
+ # From the corner vert, get the 2 edges that are not the corner or its opposing vert, this edge will make a new face
+ quad_edge_mapping = (1,3), (2,0), (1,3), (0,2) # hi-low, low-hi order is intended
+ tri_edge_mapping = (1,2), (0,2), (0,1)
+
+ done_somthing = True
+ while done_somthing:
+ done_somthing = False
+ grid_data_ls_index = -1
+
+ for vi, face_ls in grid_data_ls:
+ grid_data_ls_index += 1
+ if len(face_ls) == 3:
+ grid_data_dict[vi] = face_ls
+ grid_data_ls.pop( grid_data_ls_index )
+ break
+ elif len(face_ls) == 4:
+ # print vi
+ if verts_used[vi] == 1:
+ verts_used[vi] = 2 # dont look at this again.
+ done_somthing = True
+
+ grid_data_dict[vi] = face_ls
+
+ # Tag all faces verts as used
+
+ for i, f in enumerate(face_ls):
+ # i == face index on vert, needed to recall which corner were on.
+ v_corner = vert_faces_corner[vi][i]
+ fv =f.v
+
+ if len(f) == 4:
+ v_other = quad_diag_mapping[v_corner]
+ # get the 2 other corners
+ corner1, corner2 = quad_edge_mapping[v_corner]
+ if verts_used[fv[v_other].index] == 0:
+ verts_used[fv[v_other].index] = 1 # TAG for touching!
+ else:
+ corner1, corner2 = tri_edge_mapping[v_corner]
+
+ verts_used[fv[corner1].index] = 2 # Dont use these, they are
+ verts_used[fv[corner2].index] = 2
+
+
+ # remove this since we have used it.
+ grid_data_ls.pop( grid_data_ls_index )
+
+ break
+
+ if done_somthing == False:
+ # See if there are any that have not even been tagged, (probably on a different island), then tag them.
+
+ for vi, face_ls in grid_data_ls:
+ if verts_used[vi] == 0:
+ verts_used[vi] = 1
+ done_somthing = True
+ break
+
+
+ # Now we have all the areas we will fill, calculate corner triangles we need to fill in.
+ new_faces = []
+ quad_del_vt_map = (1,2,3), (0,2,3), (0,1,3), (0,1,2)
+ for vi, face_ls in grid_data_dict.iteritems():
+ for i, f in enumerate(face_ls):
+ if len(f) == 4:
+ # i == face index on vert, needed to recall which corner were on.
+ v_corner = vert_faces_corner[vi][i]
+ v_other = quad_diag_mapping[v_corner]
+ fv =f.v
+
+ #print verts_used[fv[v_other].index]
+ #if verts_used[fv[v_other].index] != 2: # DOSNT WORK ALWAYS
+
+ if 1: # THIS IS LAzY - some of these faces will be removed after adding.
+ # Ok we are removing half of this face, add the other half
+
+ # This is probably slower
+ # new_faces.append( [fv[ii].index for ii in (0,1,2,3) if ii != v_corner ] )
+
+ # do this instead
+ new_faces.append( (fv[quad_del_vt_map[v_corner][0]], fv[quad_del_vt_map[v_corner][1]], fv[quad_del_vt_map[v_corner][2]]) )
+
+ del grid_data_ls
+
+
+ # me.sel = 0
+ def faceCombine4(vi, face_ls):
+ edges = []
+
+ for i, f in enumerate(face_ls):
+ fv = f.v
+ v_corner = vert_faces_corner[vi][i]
+ if len(f)==4: ed = quad_edge_mapping[v_corner]
+ else: ed = tri_edge_mapping[v_corner]
+
+ edges.append( [fv[ed[0]].index, fv[ed[1]].index] )
+
+ # get the face from the edges
+ face = edges.pop()
+ while len(face) != 4:
+ # print len(edges), edges, face
+ for ed_idx, ed in enumerate(edges):
+ if face[-1] == ed[0] and (ed[1] != face[0]):
+ face.append(ed[1])
+ elif face[-1] == ed[1] and (ed[0] != face[0]):
+ face.append(ed[0])
+ else:
+ continue
+
+ edges.pop(ed_idx) # we used the edge alredy
+ break
+
+ return face
+
+ for vi, face_ls in grid_data_dict.iteritems():
+ if len(face_ls) == 4:
+ new_faces.append( faceCombine4(vi, face_ls) )
+ #pass
+ if len(face_ls) == 3: # 3 triangles
+ face = list(faces_set_verts(face_ls))
+ face.remove(vi)
+ new_faces.append( face )
+
+
+ # Now remove verts surounded by 3 triangles
+
+
+
+ # print new_edges
+ # me.faces.extend(new_faces, ignoreDups=True)
+
+ '''
+ faces_remove = []
+ for vi, face_ls in grid_data_dict.iteritems():
+ faces_remove.extend(face_ls)
+ '''
+
+ orig_facelen = len(me.faces)
+
+ orig_faces = list(me.faces)
+ me.faces.extend(new_faces, ignoreDups=True)
+ new_faces = list(me.faces)[len(orig_faces):]
+
+
+
+
+
+ if me.faceUV:
+ uvnames = me.getUVLayerNames()
+ act_uvlay = me.activeUVLayer
+
+ vert_faces_uvs = []
+ vert_faces_images = []
+
+
+ act_uvlay = me.activeUVLayer
+
+ for uvlay in uvnames:
+ me.activeUVLayer = uvlay
+ vert_faces_uvs[:] = [None] * len(me.verts)
+ vert_faces_images[:] = vert_faces_uvs[:]
+
+ for i,f in enumerate(orig_faces):
+ img = f.image
+ fv = f.v
+ uv = f.uv
+ mat = f.mat
+ for i,v in enumerate(fv):
+ vi = v.index
+ vert_faces_uvs[vi] = uv[i] # no nice averaging
+ vert_faces_images[vi] = img
+
+
+ # Now copy UVs across
+ for f in new_faces:
+ fi = [v.index for v in f.v]
+ f.image = vert_faces_images[fi[0]]
+ uv = f.uv
+ for i,vi in enumerate(fi):
+ uv[i][:] = vert_faces_uvs[vi]
+
+ if len(me.materials) > 1:
+ vert_faces_mats = [None] * len(me.verts)
+ for i,f in enumerate(orig_faces):
+ mat = f.mat
+ for i,v in enumerate(f.v):
+ vi = v.index
+ vert_faces_mats[vi] = mat
+
+ # Now copy UVs across
+ for f in new_faces:
+ print vert_faces_mats[f.v[0].index]
+ f.mat = vert_faces_mats[f.v[0].index]
+
+
+ me.verts.delete(grid_data_dict.keys())
+
+ # me.faces.delete(1, faces_remove)
+
+ if me.faceUV:
+ me.activeUVLayer = act_uvlay
+
+ me.calcNormals()
+
+def main():
+
+ # Gets the current scene, there can be many scenes in 1 blend file.
+ sce = bpy.data.scenes.active
+
+ # Get the active object, there can only ever be 1
+ # and the active object is always the editmode object.
+ ob_act = sce.objects.active
+
+ if not ob_act or ob_act.type != 'Mesh':
+ BPyMessages.Error_NoMeshActive()
+ return
+
+ is_editmode = Window.EditMode()
+ if is_editmode: Window.EditMode(0)
+
+ Window.WaitCursor(1)
+ me = ob_act.getData(mesh=1) # old NMesh api is default
+ t = sys.time()
+
+ # Run the mesh editing function
+ my_mesh_util(me)
+
+ # Restore editmode if it was enabled
+ if is_editmode: Window.EditMode(1)
+
+ # Timing the script is a good way to be aware on any speed hits when scripting
+ print 'My Script finished in %.2f seconds' % (sys.time()-t)
+ Window.WaitCursor(0)
+
+
+# This lets you can import the script without running it
+if __name__ == '__main__':
+ main()
+
diff --git a/release/scripts/mesh_skin.py b/release/scripts/mesh_skin.py
index a554e128b41..4a330a516fb 100644
--- a/release/scripts/mesh_skin.py
+++ b/release/scripts/mesh_skin.py
@@ -52,7 +52,7 @@ A pop-up will provide further options, if the results of a method are not adequa
import Blender
import bpy
from Blender import Window
-from Blender.Mathutils import MidpointVecs, Vector, CrossVecs
+from Blender.Mathutils import MidpointVecs, Vector
from Blender.Mathutils import AngleBetweenVecs as _AngleBetweenVecs_
import BPyMessages
@@ -119,7 +119,7 @@ class edgeLoop(object):
# GENERATE AN AVERAGE NORMAL FOR THE WHOLE LOOP.
self.normal = Vector()
for e in self.edges:
- n = CrossVecs(self.centre-e.co1, self.centre-e.co2)
+ n = (self.centre-e.co1).cross(self.centre-e.co2)
# Do we realy need tot normalize?
n.normalize()
self.normal += n
@@ -149,7 +149,7 @@ class edgeLoop(object):
a = n1-n2
b = n1-n3
- normal1 = CrossVecs(a,b)
+ normal1 = a.cross(b)
normal1.normalize()
n1 = e.co2
@@ -159,7 +159,7 @@ class edgeLoop(object):
a = n1-n2
b = n1-n3
- normal2 = CrossVecs(a,b)
+ normal2 = a.cross(b)
normal2.normalize()
# Reuse normal1 var
diff --git a/release/scripts/mesh_unfolder.py b/release/scripts/mesh_unfolder.py
index 906e0f0a300..f5c19a92bd0 100644
--- a/release/scripts/mesh_unfolder.py
+++ b/release/scripts/mesh_unfolder.py
@@ -164,8 +164,8 @@ class Fold:
sangle = Mathutils.AngleBetweenVecs(self.refPolyNormal, self.polyNormal)
if(sangle!=sangle):
sangle=0.0
- ncp = Mathutils.CrossVecs(self.refPolyNormal, self.polyNormal)
- dp = Mathutils.DotVecs(ncp, self.edge.vector)
+ ncp = self.refPolyNormal.cross(self.polyNormal)
+ dp = ncp.dot(self.edge.vector)
if(dp>0.0):
return +sangle
else:
@@ -855,7 +855,7 @@ class Poly:
p.resize3D()
q = a-c
q.resize3D()
- return CrossVecs(p,q)
+ return p.cross(q)
def makeEdges(self):
self.edges = []
for i in xrange(self.nPoints()):
diff --git a/release/scripts/help_web_blender.py b/release/scripts/object_active_to_other.py
index 0f9e32dea0e..68aa6a3a039 100644
--- a/release/scripts/help_web_blender.py
+++ b/release/scripts/object_active_to_other.py
@@ -1,26 +1,15 @@
#!BPY
-
-"""
-Name: 'Blender Website'
-Blender: 234
-Group: 'HelpWebsites'
-Tooltip: 'The official Blender website'
"""
-
-__author__ = "Matt Ebb"
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.0"
-__bpydoc__ = """\
-This script opens the user's default web browser at Blender's main site,
-www.blender3d.org.
+Name: 'Copy Active to Selected'
+Blender: 249
+Group: 'Object'
+Tooltip: 'For every selected object, copy the active to their loc/size/rot'
"""
-
-# --------------------------------------------------------------------------
-# Blender Website Help Menu -> Websites Item
-# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
+# Script copyright (C) Campbell Barton
+#
# 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
@@ -38,5 +27,32 @@ www.blender3d.org.
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
-import Blender, webbrowser
-webbrowser.open('http://www.blender3d.org/')
+
+from Blender import Window, sys, Draw
+import bpy
+
+def my_object_util(sce):
+ ob_act = sce.objects.active
+
+ if not ob_act:
+ Draw.PupMenu('Error%t|No active object selected')
+ return
+
+ mats = [(ob, ob.matrixWorld) for ob in sce.objects.context if ob != ob_act]
+
+ for ob, m in mats:
+ ob_copy = ob_act.copy()
+ sce.objects.link(ob_copy)
+ ob_copy.setMatrix(m)
+ ob_copy.Layers = ob.Layers & (1<<20)-1
+
+
+def main():
+ sce = bpy.data.scenes.active
+
+ Window.WaitCursor(1)
+ my_object_util(sce)
+ Window.WaitCursor(0)
+
+if __name__ == '__main__':
+ main()
diff --git a/release/scripts/object_cookie_cutter.py b/release/scripts/object_cookie_cutter.py
index 2a6e0ad6b2e..4950c18c0f4 100644
--- a/release/scripts/object_cookie_cutter.py
+++ b/release/scripts/object_cookie_cutter.py
@@ -10,7 +10,7 @@ __url__= ["blender", "blenderartist"]
__version__= "1.0"
__bpydoc__= """\
-This script takes the selected mesh objects, devides them into 2 groups
+This script takes the selected mesh objects, divides them into 2 groups
Cutters and The objects to be cut.
Cutters are meshes with no faces, just edge loops. and any meshes with faces will be cut.
@@ -128,14 +128,14 @@ def sorted_indicies(i1, i2):
def fake_length2d(pt1, pt2):
'''
- Only used for comparison so dont sqrt
+ Only used for comparison so don't sqrt
'''
#return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2)))
return pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2)
def length2d(pt1, pt2):
'''
- Only used for comparison so dont sqrt
+ Only used for comparison so don't sqrt
'''
#return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2)))
return sqrt(pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2))
@@ -150,7 +150,7 @@ def tri_area_2d(v1, v2, v3):
return 0.25 * sqrt(abs(p*(p-2*e1)*(p-2*e2)*(p-2*e3)))
def tri_pt_find_z_2d(pt, tri):
- """ Takes a face and 3d vector and assigns teh vectors Z to its on the face"""
+ """ Takes a face and 3d vector and assigns the vectors Z to its on the face"""
l1= tri_area_2d(tri[1], tri[2], pt)
l2= tri_area_2d(tri[0], tri[2], pt)
@@ -170,7 +170,7 @@ def tri_pt_find_z_2d(pt, tri):
def tri_pt_find_uv_2d(pt, tri, uvs):
- """ Takes a face and 3d vector and assigns teh vectors Z to its on the face"""
+ """ Takes a face and 3d vector and assigns the vectors Z to its on the face"""
l1= tri_area_2d(tri[1], tri[2], pt)
l2= tri_area_2d(tri[0], tri[2], pt)
@@ -288,12 +288,12 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
# Loop through the cutter edges.
for ei_c, ed_c in enumerate(me_c.edges):
# If the cutter edge has 2 verts inside the same face then we can ignore it
- # Bothe are different faces or None
+ # Both are different faces or None
if cut_vert_terrain_faces[ed_c.v1.index] != cut_vert_terrain_faces[ed_c.v2.index] or\
cut_vert_terrain_faces[ed_c.v1.index] == cut_vert_terrain_faces[ed_c.v2.index] == None:
eb_c= c.edge_bounds[ei_c]
if bounds_intersect(eb_t, eb_c): # face/edge bounds intersect?
- # Now we know the 2 edges might intersect, we'll do a propper test
+ # Now we know the 2 edges might intersect, we'll do a proper test
x= LineIntersect2D(ed_t.v1.co, ed_t.v2.co, ed_c.v1.co, ed_c.v2.co)
if x:
@@ -340,7 +340,7 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
for f in faces:
faces_intersecting.setdefault(f.index, []).append(ed_isect)
- # this list is used to store edges that are totaly inside a face ( no intersections with terrain)
+ # this list is used to store edges that are totally inside a face ( no intersections with terrain)
# we can remove these as we
face_containing_edges= [[] for i in xrange(len(me_t.faces))]
for ed_c in me_c.edges:
@@ -412,8 +412,8 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
- # edges that dont have a vert in the face have to span between to intersection points
- # since we dont know the other point at any 1 time we need to remember edges that
+ # edges that don't have a vert in the face have to span between to intersection points
+ # since we don't know the other point at any 1 time we need to remember edges that
# span a face and add them once we'v collected both
# first add outline edges
edge_span_face= {}
@@ -507,7 +507,7 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
# 0,2,3
f_uv_mod= f_uv[0], f_uv[2], f_uv[3]
f_vco_mod= f_vco[0], f_vco[2], f_vco[3]
- # else - side of 0,1,2 - dont modify the quad
+ # else - side of 0,1,2 - don't modify the quad
uvs[i]= tri_pt_find_uv_2d(v_co, f_vco_mod, f_uv_mod)
@@ -579,7 +579,7 @@ def main():
for ob in obs:
if ob.type == 'Mesh':
me= ob.getData(mesh=1)
- elif ob.data.flag & 1: # Is the curve 3D? else dont use.
+ elif ob.data.flag & 1: # Is the curve 3D? else don't use.
me= BPyMesh.getMeshFromObject(ob) # get the curve
else:
continue
diff --git a/release/scripts/object_drop.py b/release/scripts/object_drop.py
index f4803e62d98..19cc1f8d15a 100644
--- a/release/scripts/object_drop.py
+++ b/release/scripts/object_drop.py
@@ -1,13 +1,13 @@
#!BPY
"""
Name: 'Drop Onto Ground'
-Blender: 245
+Blender: 249
Group: 'Object'
Tooltip: 'Drop the selected objects onto "ground" objects'
"""
__author__= "Campbell Barton"
__url__= ["blender.org", "blenderartists.org"]
-__version__= "1.0"
+__version__= "1.1"
__bpydoc__= """
"""
@@ -36,6 +36,7 @@ __bpydoc__= """
from Blender import Draw, Geometry, Mathutils, Window
+from Blender.Mathutils import Vector, AngleBetweenVecs, RotationMatrix
import bpy
@@ -44,6 +45,8 @@ GLOBALS['GROUND_SOURCE'] = [Draw.Create(1), Draw.Create(0)]
GLOBALS['GROUND_GROUP_NAME'] = Draw.Create('terrain')
GLOBALS['DROP_AXIS'] = [Draw.Create(1), Draw.Create(0)] # on what axis will we drop?
GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Create(1) # is the terrain a single skin?
+GLOBALS['DROP_ORIENT'] = Draw.Create(1)
+GLOBALS['DROP_ORIENT_VALUE'] = Draw.Create(100.0)
GLOBALS['EVENT'] = 2
GLOBALS['MOUSE'] = None
@@ -52,19 +55,18 @@ def collect_terrain_triangles(obs_terrain):
me = bpy.data.meshes.new()
for ob in obs_terrain:
- # this matrix takes the object and drop matrix into account
- ob_mat = ob.matrixWorld # * drop_matrix
-
def blend_face_to_terrain_tris(f):
- cos = [v.co*ob_mat for v in f]
- if len(cos) == 4: return [(cos[0], cos[1], cos[2]), (cos[0], cos[2], cos[3])]
- else: return [(cos[0], cos[1], cos[2]), ]
+ no = f.no
+ cos = [v.co for v in f]
+ if len(cos) == 4: return [(cos[0], cos[1], cos[2], no), (cos[0], cos[2], cos[3], no)]
+ else: return [(cos[0], cos[1], cos[2], no), ]
# Clear
me.verts = None
try: me.getFromObject(ob)
except: pass
+ me.transform(ob.matrixWorld)
for f in me.faces: # may be [], thats ok
terrain_tris.extend( blend_face_to_terrain_tris(f) )
@@ -72,30 +74,34 @@ def collect_terrain_triangles(obs_terrain):
return terrain_tris
def calc_drop_loc(ob, terrain_tris, axis):
- pt = Mathutils.Vector(ob.loc)
+ pt = Vector(ob.loc)
isect = None
isect_best = None
+ isect_best_no = None
isect_best_len = 0.0
- for t1,t2,t3 in terrain_tris:
+ for t1,t2,t3, no in terrain_tris:
#if Geometry.PointInTriangle2D(pt, t1,t2,t3):
isect = Mathutils.Intersect(t1, t2, t3, axis, pt, 1) # 1==clip
if isect:
if not GLOBALS['DROP_OVERLAP_CHECK'].val:
# Find the first location
- return isect
+ return isect, no
else:
if isect_best:
isect_len = (pt-isect).length
if isect_len < isect_best_len:
isect_best_len = isect_len
isect_best = isect
+ isect_best_no = no
else:
isect_best_len = (pt-isect).length
isect_best = isect;
- return isect_best
+ isect_best_no = no
+
+ return isect_best, isect_best_no
def error_nogroup():
@@ -135,13 +141,28 @@ def terrain_clamp(event, value):
if GLOBALS['DROP_AXIS'][0].val:
- axis = Mathutils.Vector(0,0,-1)
+ axis = Vector(0,0,-1)
else:
- axis = Mathutils.Vector(Window.GetViewVector())
+ axis = Vector(Window.GetViewVector())
+
+ do_orient = GLOBALS['DROP_ORIENT'].val
+ do_orient_val = GLOBALS['DROP_ORIENT_VALUE'].val/100.0
+ if not do_orient_val: do_orient = False
for ob in obs_clamp:
- loc = calc_drop_loc(ob, terrain_tris, axis)
+ loc, no = calc_drop_loc(ob, terrain_tris, axis)
if loc:
+ if do_orient:
+ try: ang = AngleBetweenVecs(no, axis)
+ except:ang = 0.0
+ if ang > 90.0:
+ no = -no
+ ang = 180.0-ang
+
+ if ang > 0.0001:
+ ob_matrix = ob.matrixWorld * RotationMatrix(ang * do_orient_val, 4, 'r', axis.cross(no))
+ ob.setMatrix(ob_matrix)
+
ob.loc = loc
# to make the while loop exist
@@ -175,7 +196,8 @@ def do_ground_group_name(e,v):
if not g: error_nogroup()
GLOBALS['EVENT'] = e
-
+def do_dummy(e,v):
+ GLOBALS['EVENT'] = e
EVENT_NONE = 0
EVENT_EXIT = 1
@@ -185,7 +207,7 @@ def terain_clamp_ui():
# Only to center the UI
x,y = GLOBALS['MOUSE']
x-=40
- y-=60
+ y-=70
Draw.Label('Drop Axis', x-70,y+120, 60, 20)
Draw.BeginAlign()
@@ -204,7 +226,13 @@ def terain_clamp_ui():
GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Toggle('Overlapping Terrain', EVENT_NONE, x-70, y+20, 190, 20, GLOBALS['DROP_OVERLAP_CHECK'].val, "Check all terrain triangles and use the top most (slow)")
- Draw.PushButton('Drop Objects', EVENT_EXIT, x+20, y-10, 100, 20, 'Drop the selected objects', terrain_clamp)
+ Draw.BeginAlign()
+ GLOBALS['DROP_ORIENT'] = Draw.Toggle('Orient Normal', EVENT_REDRAW, x-70, y-10, 110, 20, GLOBALS['DROP_ORIENT'].val, "Rotate objects to the face normal", do_dummy)
+ if GLOBALS['DROP_ORIENT'].val:
+ GLOBALS['DROP_ORIENT_VALUE'] = Draw.Number('', EVENT_NONE, x+40, y-10, 80, 20, GLOBALS['DROP_ORIENT_VALUE'].val, 0.0, 100.0, "Percentage to orient 0.0 - 100.0")
+ Draw.EndAlign()
+
+ Draw.PushButton('Drop Objects', EVENT_EXIT, x+20, y-40, 100, 20, 'Drop the selected objects', terrain_clamp)
# So moving the mouse outside the popup exits the while loop
GLOBALS['EVENT'] = EVENT_EXIT
diff --git a/release/scripts/ply_export.py b/release/scripts/ply_export.py
deleted file mode 100644
index 46d08050302..00000000000
--- a/release/scripts/ply_export.py
+++ /dev/null
@@ -1,228 +0,0 @@
-#!BPY
-
-"""
-Name: 'Stanford PLY (*.ply)...'
-Blender: 241
-Group: 'Export'
-Tooltip: 'Export active object to Stanford PLY format'
-"""
-
-import bpy
-import Blender
-from Blender import Mesh, Scene, Window, sys, Image, Draw
-import BPyMesh
-
-__author__ = "Bruce Merry"
-__version__ = "0.93"
-__bpydoc__ = """\
-This script exports Stanford PLY files from Blender. It supports normals,
-colours, and texture coordinates per face or per vertex.
-Only one mesh can be exported at a time.
-"""
-
-# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
-#
-# 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.
-# Vector rounding se we can use as keys
-#
-# Updated on Aug 11, 2008 by Campbell Barton
-# - added 'comment' prefix to comments - Needed to comply with the PLY spec.
-#
-# Updated on Jan 1, 2007 by Gabe Ghearing
-# - fixed normals so they are correctly smooth/flat
-# - fixed crash when the model doesn't have uv coords or vertex colors
-# - fixed crash when the model has vertex colors but doesn't have uv coords
-# - changed float32 to float and uint8 to uchar for compatibility
-# Errata/Notes as of Jan 1, 2007
-# - script exports texture coords if they exist even if TexFace isn't selected (not a big deal to me)
-# - ST(R) should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
-#
-# Updated on Jan 3, 2007 by Gabe Ghearing
-# - fixed "sticky" vertex UV exporting
-# - added pupmenu to enable/disable exporting normals, uv coords, and colors
-# Errata/Notes as of Jan 3, 2007
-# - ST(R) coords should probably be renamed UV(T) like in most PLY files (importer needs to be updated to take either)
-# - edges should be exported since PLY files support them
-# - code is getting spaghettish, it should be refactored...
-#
-
-
-def rvec3d(v): return round(v[0], 6), round(v[1], 6), round(v[2], 6)
-def rvec2d(v): return round(v[0], 6), round(v[1], 6)
-
-def file_callback(filename):
-
- if not filename.lower().endswith('.ply'):
- filename += '.ply'
-
- scn= bpy.data.scenes.active
- ob= scn.objects.active
- if not ob:
- Blender.Draw.PupMenu('Error%t|Select 1 active object')
- return
-
- file = open(filename, 'wb')
-
- EXPORT_APPLY_MODIFIERS = Draw.Create(1)
- EXPORT_NORMALS = Draw.Create(1)
- EXPORT_UV = Draw.Create(1)
- EXPORT_COLORS = Draw.Create(1)
- #EXPORT_EDGES = Draw.Create(0)
-
- pup_block = [\
- ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\
- ('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\
- ('UVs', EXPORT_UV, 'Export texface UV coords.'),\
- ('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\
- #('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\
- ]
-
- if not Draw.PupBlock('Export...', pup_block):
- return
-
- is_editmode = Blender.Window.EditMode()
- if is_editmode:
- Blender.Window.EditMode(0, '', 0)
-
- Window.WaitCursor(1)
-
- EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
- EXPORT_NORMALS = EXPORT_NORMALS.val
- EXPORT_UV = EXPORT_UV.val
- EXPORT_COLORS = EXPORT_COLORS.val
- #EXPORT_EDGES = EXPORT_EDGES.val
-
- mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn)
-
- if not mesh:
- Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object')
- return
-
- mesh.transform(ob.matrixWorld)
-
- faceUV = mesh.faceUV
- vertexUV = mesh.vertexUV
- vertexColors = mesh.vertexColors
-
- if (not faceUV) and (not vertexUV): EXPORT_UV = False
- if not vertexColors: EXPORT_COLORS = False
-
- if not EXPORT_UV: faceUV = vertexUV = False
- if not EXPORT_COLORS: vertexColors = False
-
- # incase
- color = uvcoord = uvcoord_key = normal = normal_key = None
-
- verts = [] # list of dictionaries
- # vdict = {} # (index, normal, uv) -> new index
- vdict = [{} for i in xrange(len(mesh.verts))]
- vert_count = 0
- for i, f in enumerate(mesh.faces):
- smooth = f.smooth
- if not smooth:
- normal = tuple(f.no)
- normal_key = rvec3d(normal)
-
- if faceUV: uv = f.uv
- if vertexColors: col = f.col
- for j, v in enumerate(f):
- if smooth:
- normal= tuple(v.no)
- normal_key = rvec3d(normal)
-
- if faceUV:
- uvcoord= uv[j][0], 1.0-uv[j][1]
- uvcoord_key = rvec2d(uvcoord)
- elif vertexUV:
- uvcoord= v.uvco[0], 1.0-v.uvco[1]
- uvcoord_key = rvec2d(uvcoord)
-
- if vertexColors: color= col[j].r, col[j].g, col[j].b
-
-
- key = normal_key, uvcoord_key, color
-
- vdict_local = vdict[v.index]
-
- if (not vdict_local) or (not vdict_local.has_key(key)):
- vdict_local[key] = vert_count;
- verts.append( (tuple(v.co), normal, uvcoord, color) )
- vert_count += 1
-
-
- file.write('ply\n')
- file.write('format ascii 1.0\n')
- file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
-
- file.write('element vertex %d\n' % len(verts))
-
- file.write('property float x\n')
- file.write('property float y\n')
- file.write('property float z\n')
- if EXPORT_NORMALS:
- file.write('property float nx\n')
- file.write('property float ny\n')
- file.write('property float nz\n')
-
- if EXPORT_UV:
- file.write('property float s\n')
- file.write('property float t\n')
- if EXPORT_COLORS:
- file.write('property uchar red\n')
- file.write('property uchar green\n')
- file.write('property uchar blue\n')
-
- file.write('element face %d\n' % len(mesh.faces))
- file.write('property list uchar uint vertex_indices\n')
- file.write('end_header\n')
-
- for i, v in enumerate(verts):
- file.write('%.6f %.6f %.6f ' % v[0]) # co
- if EXPORT_NORMALS:
- file.write('%.6f %.6f %.6f ' % v[1]) # no
-
- if EXPORT_UV:
- file.write('%.6f %.6f ' % v[2]) # uv
- if EXPORT_COLORS:
- file.write('%u %u %u' % v[3]) # col
- file.write('\n')
-
- for (i, f) in enumerate(mesh.faces):
- file.write('%d ' % len(f))
- smooth = f.smooth
- if not smooth: no = rvec3d(f.no)
-
- if faceUV: uv = f.uv
- if vertexColors: col = f.col
- for j, v in enumerate(f):
- if f.smooth: normal= rvec3d(v.no)
- else: normal= no
- if faceUV: uvcoord= rvec2d((uv[j][0], 1.0-uv[j][1]))
- elif vertexUV: uvcoord= rvec2d((v.uvco[0], 1.0-v.uvco[1]))
- if vertexColors: color= col[j].r, col[j].g, col[j].b
-
- file.write('%d ' % vdict[v.index][normal, uvcoord, color])
-
- file.write('\n')
- file.close()
-
- if is_editmode:
- Blender.Window.EditMode(1, '', 0)
-
-def main():
- Blender.Window.FileSelector(file_callback, 'PLY Export', Blender.sys.makename(ext='.ply'))
-
-if __name__=='__main__':
- main()
diff --git a/release/scripts/ply_import.py b/release/scripts/ply_import.py
index 302e21a0a43..29e8ce48361 100644
--- a/release/scripts/ply_import.py
+++ b/release/scripts/ply_import.py
@@ -149,6 +149,7 @@ def read(filename):
'uint8': 'B',
'int16': 'h',
'uint16': 'H',
+ 'ushort': 'H',
'int': 'i',
'int32': 'i',
'uint': 'I',
@@ -156,17 +157,21 @@ def read(filename):
'float': 'f',
'float32': 'f',
'float64': 'd',
+ 'double': 'd',
'string': 's'}
obj_spec = object_spec()
try:
- file = open(filename, 'rb')
+ file = open(filename, 'rU') # Only for parsing the header, not binary data
signature = file.readline()
- if (signature != 'ply\n'):
+
+ if not signature.startswith('ply'):
print 'Signature line was invalid'
return None
+
while 1:
tokens = re.split(r'[ \n]+', file.readline())
+
if (len(tokens) == 0):
continue
if (tokens[0] == 'end_header'):
@@ -197,14 +202,22 @@ def read(filename):
obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]]))
else:
obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]]))
+
+ if format != 'ascii':
+ file.close() # was ascii, now binary
+ file = open(filename, 'rb')
+
+ # skip the header...
+ while not file.readline().startswith('end_header'):
+ pass
+
obj = obj_spec.load(format_specs[format], file)
-
+
except IOError, (errno, strerror):
try: file.close()
except: pass
return None
-
try: file.close()
except: pass
diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py
index a48d065813a..d013343c05c 100644
--- a/release/scripts/rvk1_torvk2.py
+++ b/release/scripts/rvk1_torvk2.py
@@ -2,7 +2,7 @@
# coding: utf-8
""" Registration info for Blender menus: <- these words are ignored
Name: 'Deformed mesh to Rvk'
-Blender: 243
+Blender: 248
Group: 'Mesh'
Tip: 'Copy deform data (not surf. subdiv) of active obj to rvk of the 2nd selected obj'
"""
@@ -11,21 +11,24 @@ __author__ = "Jean-Michel Soler (jms)"
__url__ = ("blender", "blenderartists.org",
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "2007/04/27"
+__version__ = "2009/05/18"
__bpydoc__ = """\
-"DEFORM to RVK2" copies deform data (except EDGESPLIT,DECIMATE,SUBSURF,BOOLEAN,
-BUILD,MIRROR,ARRAY) of the active object to the RVK (relative vertex key) of
-the other selected object.
+"DEFORM to RVK2" copies deformed data (except all data with not exactly
+the same number of vertices like EDGESPLIT,DECIMATE,SUBSURF, BOOLEAN,
+BUILD, MIRROR, ARRAY) of the active object to the RVK (relative vertex
+key, now called Shapes key) of the other selected object.
It is presupposed that the second mesh object is built exactly like the first
one. In fact, it is better to use a true copy with at least one basic shape
-key.
+key. If there is no other object selected, the script can create a copy.
The new version of this scrit (Blender 2.43) manages the modifier changes.
There are a lot of modifiers but only the ones which just deforms the shape
-can be used : LATTICE, CURVE, WAVE, ARMATURE. You can unset these modifiers
-from the script.
+can be used : LATTICE, CURVE, WAVE, ARMATURE, CAST, DISPLACE, SMOOTH.
+SIMPLEDEFORM and SHRINKWRAP are not correctly seen before Blender 2.49, but
+they can be copied too. You can unset one or more of these modifiers from
+the script.
Usage:
@@ -37,9 +40,9 @@ the rvk it will also ask whether it should replace or add a new vertex group.
"""
-
#----------------------------------------------
-# jm soler (c) 2004-2007 : 'Deformed mesh to Rvk' released under GPL licence
+# jm soler (c) 2004-2009 : 'Deformed mesh to Rvk'
+# released under GPL licence
#----------------------------------------------
"""
Ce programme est libre, vous pouvez le redistribuer et/ou
@@ -72,11 +75,6 @@ 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 St, Fifth Floor, Boston, MA 02110-1301 USA
"""
-# Copy the rvk (1, or armature, lattice, or
-# any mesh deformation except surface
-# sbdivision) of the active object to rvk (2) of
-# the second selected object. Create rvk or modify
-# absolute key if needed.
#----------------------------------------------
# official Page :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm
@@ -90,7 +88,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Communiquer les problemes et erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
#---------------------------------------------
-#---------------------------------------------
import Blender
from Blender import NMesh,Draw,Object,Modifier
@@ -99,175 +96,246 @@ DEBUG=0
def Value(t):
exec "t=Modifier.Types.%s"%t
- return t
+ return t
-def deform2rvk():
+def copy_shapes(RVK1,RVK2):
POSSMOD_list=['EDGESPLIT',
- 'DECIMATE',
- 'SUBSURF',
- 'BOOLEAN',
- 'BUILD',
- 'MIRROR',
- 'ARRAY']
+ 'DECIMATE',
+ 'SUBSURF',
+ 'BOOLEAN',
+ 'BUILD',
+ 'MIRROR',
+ 'ARRAY',
+ 'BEVEL',
+ 'EXPLODE']
AUTHMOD_list=['LATTICE',
- 'CURVE',
- 'WAVE',
- 'ARMATURE']
-
- MODIFIERS=0
+ 'CURVE',
+ 'WAVE',
+ 'ARMATURE',
+ 'SMOOTH',
+ 'SIMPLEDEFORM',
+ 'SHRINKWRAP',
+ 'CAST',
+ 'DISPLACE',
+ 'MESHDEFORM']
+
BMOD=[['Possible Modifiers'],
- ['Allowed Modifiers']]
-
- # =================================================================
- # at leat 2 objects ===============================================
- # =================================================================
- if len(Object.GetSelected())>1 :
- RVK1=Object.GetSelected()[0]
- RVK2=Object.GetSelected()[1]
- # =============================================================
- # must be 2 meshes ============================================
- # =============================================================
- if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh':
- FRAME=Blender.Get('curframe')
+ ['Allowed Modifiers']]
+ # =============================================================
+ # must be 2 meshes ============================================
+ # =============================================================
+ if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh':
+ #MODIFIERS=0
+ FRAME=Blender.Get('curframe')
+ DATA2=RVK2.getData()
+ if DEBUG: print DATA2.getKey()
+ # ============================================================
+ # at least the second must have a shape key ==================
+ # ============================================================
+ def select_modifier(RVK1, RVK2, DATA2):
+ # ======================================================
+ # in case of modifiers, use =============================
+ # ======================================================
+ if RVK1.modifiers:
+ #MODIFIERS=1
+ POSSMOD=[Value(t) for t in POSSMOD_list]
+ AUTHMOD=[Value(t) for t in AUTHMOD_list]
+ if DEBUG: print 'POSSMOD:',POSSMOD,'\nAUTHMOD:', AUTHMOD
+ MODRVK1=RVK1.modifiers
+ block = []
+ # ===================================================
+ # === Bloc Menu Modifiers ===1 doc =================
+ # ===================================================
+ m=0
+ for mod in MODRVK1:
+ if DEBUG: print mod.type
+ if mod.type in POSSMOD:
+ BMOD[0].append([Draw.Create(0),mod.type,
+ m,
+ POSSMOD_list[POSSMOD.index(mod.type)],
+ mod[Modifier.Settings.RENDER]==1,
+ mod[Modifier.Settings.EDITMODE]==1
+ ])
+ elif mod.type in AUTHMOD:
+ BMOD[1].append([Draw.Create(1),
+ mod.type,
+ m,
+ AUTHMOD_list[AUTHMOD.index(mod.type)],
+ mod[Modifier.Settings.RENDER]==1,
+ mod[Modifier.Settings.EDITMODE]==1
+ ])
+ m+=1
+ # ===================================================
+ # === Bloc Menu Modifiers ===2 display =============
+ # ===================================================
+ block.append(BMOD[1][0])
+ for B in BMOD[1][1:]:
+ block.append((B[3],B[0],""))
+ block.append(BMOD[0][0])
+ block.append("not alredy implemented")
+ block.append("in this script.")
+ for B in BMOD[0][1:]:
+ block.append((B[3],B[0],""))
+ retval = Blender.Draw.PupBlock("MESH 2 RVK", block)
+ # ===================================================
+ # === unset Modifiers =============================
+ # ===================================================
+ for B in BMOD[0][1:]:
+ if DEBUG: print B[2]
+ MODRVK1[B[2]][Modifier.Settings.RENDER]=0
+ for B in BMOD[1]:
+ if not B[1]:
+ MODRVK1[B[2]][Modifier.Settings.RENDER]=0
+ # ===================================================
+ # === update Modifiers =============================
+ # ===================================================
+ #RVK1.makeDisplayList()
+ # =======================================================
+ # === get deformed mesh ================================
+ # =======================================================
+ RVK1NAME=Object.GetSelected()[0].getName()
+ meshrvk1=NMesh.GetRawFromObject(RVK1NAME)
+ if DEBUG: print len(meshrvk1.verts)
+ # =======================================================
+ # === get normal mesh for vertex group =================
+ # =======================================================
+ DATA1=RVK1.getData()
+ # =======================================================
+ # === get destination mesh ============================
+ # =======================================================
DATA2=RVK2.getData()
- if DEBUG: print DATA2.getKey()
- # ============================================================
- # at least the second must have a shape key ==================
- # ============================================================
- if DATA2.getKey():
- # ======================================================
- # in case of modifiers use =============================
- # ======================================================
+ if DEBUG: print len(meshrvk1.verts)
+ if DEBUG: print len(DATA2.verts)
+ # ========================================================
+ # ===== is there the same number of vertices =============
+ # ========================================================
+ if len(meshrvk1.verts)==len(DATA2.verts):
+ name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 "
+ result = Draw.PupMenu(name)
+ if result==1:
+ # =====================================================
+ # ===== Do we save vertex groups ? ===================
+ # =====================================================
+ GROUPNAME2=DATA2.getVertGroupNames()
+ if len(GROUPNAME2)!=0:
+ for GROUP2 in GROUPNAME2:
+ DATA2.removeVertGroup(GROUP2)
+ GROUPNAME1=DATA1.getVertGroupNames()
+ if len(GROUPNAME1)!=0:
+ for GROUP1 in GROUPNAME1:
+ DATA2.addVertGroup(GROUP1)
+ DATA2.assignVertsToGroup(GROUP1,DATA1.getVertsFromGroup(GROUP1),1.0,'replace')
+ # ========================================================
+ # ===== now copy the vertices coords =====================
+ # ========================================================
+ for v in meshrvk1.verts:
+ i= meshrvk1.verts.index(v)
+ v1=DATA2.verts[i]
+ for n in [0,1,2]:
+ v1.co[n]=v.co[n]
+ DATA2.update()
+ DATA2.insertKey(FRAME,'relative')
+ DATA2.update()
+ RVK2.makeDisplayList()
+
if RVK1.modifiers:
- MODIFIERS=1
- POSSMOD=[Value(t) for t in POSSMOD_list]
- AUTHMOD=[Value(t) for t in AUTHMOD_list]
- if DEBUG: print 'POSSMOD:',POSSMOD,'\nAUTHMOD:', AUTHMOD
- MODRVK1=RVK1.modifiers
- block = []
- # ===================================================
- # === Bloc Menu Modifiers ===1 doc =================
- # ===================================================
- m=0
- for mod in MODRVK1:
- if DEBUG: print mod.type
- if mod.type in POSSMOD:
- BMOD[0].append([Draw.Create(0),mod.type,
- m,
- POSSMOD_list[POSSMOD.index(mod.type)],
- mod[Modifier.Settings.RENDER]==1,
- mod[Modifier.Settings.EDITMODE]==1
- ])
- elif mod.type in AUTHMOD:
- BMOD[1].append([Draw.Create(1),
- mod.type,
- m,
- AUTHMOD_list[AUTHMOD.index(mod.type)],
- mod[Modifier.Settings.RENDER]==1,
- mod[Modifier.Settings.EDITMODE]==1
- ])
- m+=1
- # ===================================================
- # === Bloc Menu Modifiers ===2 display =============
- # ===================================================
- block.append(BMOD[1][0])
- for B in BMOD[1][1:]:
- block.append((B[3],B[0],""))
- block.append(BMOD[0][0])
- block.append("not alredy implemented")
- block.append("in this script.")
- for B in BMOD[0][1:]:
- block.append((B[3],B[0],""))
- retval = Blender.Draw.PupBlock("MESH 2 RVK", block)
# ===================================================
# === unset Modifiers =============================
# ===================================================
for B in BMOD[0][1:]:
- if DEBUG: print B[2]
- MODRVK1[B[2]][Modifier.Settings.RENDER]=0
+ MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2]
for B in BMOD[1]:
if not B[1]:
- MODRVK1[B[2]][Modifier.Settings.RENDER]=0
- # ===================================================
- # === update Modifiers =============================
- # ===================================================
- #RVK1.makeDisplayList()
- # =======================================================
- # === get deformed mesh ================================
- # =======================================================
- RVK1NAME=Object.GetSelected()[0].getName()
- meshrvk1=NMesh.GetRawFromObject(RVK1NAME)
- if DEBUG: print len(meshrvk1.verts)
- # =======================================================
- # === get normal mesh for vertex group =================
- # =======================================================
- DATA1=RVK1.getData()
- # =======================================================
- # === get destination mesh ============================
- # =======================================================
- DATA2=RVK2.getData()
- if DEBUG: print len(meshrvk1.verts)
- if DEBUG: print len(DATA2.verts)
- # ========================================================
- # ===== is there the same number of vertices =============
- # ========================================================
- if len(meshrvk1.verts)==len(DATA2.verts):
- name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 "
- result = Draw.PupMenu(name)
- if result==1:
- # =====================================================
- # ===== Do we save vertex groups ? ===================
- # =====================================================
- GROUPNAME2=DATA2.getVertGroupNames()
- if len(GROUPNAME2)!=0:
- for GROUP2 in GROUPNAME2:
- DATA2.removeVertGroup(GROUP2)
- GROUPNAME1=DATA1.getVertGroupNames()
- if len(GROUPNAME1)!=0:
- for GROUP1 in GROUPNAME1:
- DATA2.addVertGroup(GROUP1)
- DATA2.assignVertsToGroup(GROUP1,DATA1.getVertsFromGroup(GROUP1),1.0,'replace')
- # ========================================================
- # ===== now copy the vertices coords =====================
- # ========================================================
- for v in meshrvk1.verts:
- i= meshrvk1.verts.index(v)
- v1=DATA2.verts[i]
- for n in [0,1,2]:
- v1.co[n]=v.co[n]
- DATA2.update()
- DATA2.insertKey(FRAME,'relative')
- DATA2.update()
- RVK2.makeDisplayList()
- if MODIFIERS:
- # ===================================================
- # === unset Modifiers =============================
- # ===================================================
- for B in BMOD[0][1:]:
MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2]
- for B in BMOD[1]:
- if not B[1]:
- MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2]
- else:
- name = "Meshes Objects must the same number of vertices %t| Ok. %x1"
- result = Draw.PupMenu(name)
- return
+
else:
- name = "Second Object must have at least a shape key %t| Ok. %x1"
+ name = "Meshes Objects must have the same number of vertices %t|Ok. %x1"
result = Draw.PupMenu(name)
- return
+ return
+ if DATA2.getKey():
+ select_modifier(RVK1, RVK2, DATA2)
else:
- name = "Object must be Meshes %t| Ok. %x1"
+ name = "Second Object must have at least a shape key %t| Ok. %x1| Add one ? %x2"
result = Draw.PupMenu(name)
+ if result :
+ RVK2.insertShapeKey()
+ DATA2=RVK2.getData()
+ select_modifier(RVK1, RVK2, DATA2)
+ else:
+ return
+ else:
+ name = "Object must be Meshes %t| Ok. %x1"
+ result = Draw.PupMenu(name)
+ return
+
+def deform2rvk():
+ scn = Blender.Scene.GetCurrent()
+ # =================================================================
+ # at leat 2 objects ===============================================
+ # =================================================================
+ if len(scn.objects.selected) >1 :
+ RVK1 = Object.GetSelected()[0]
+ RVK2=Object.GetSelected()[1]
+ if RVK2.getType()=='Mesh' :
+ copy_shapes(RVK1,RVK2)
+ # =================================================================
+ # ... but if only one...===========================================
+ # =================================================================
+ elif len(scn.objects.selected)==1:
+ name = "At least 2 Meshes must be selected %t| Ok. %x1| Add one ? %x2"
+ result = Draw.PupMenu(name)
+ RVK1 = Object.GetSelected()[0]
+ if result and RVK1.getType()=='Mesh' :
+ Blender.Object.Duplicate(mesh=1)
+ RVK2=scn.objects.active
+ mod = RVK2.modifiers
+ for m in mod :
+ RVK2.modifiers.remove(m)
+ RVK2.LocX+=2.0
+ copy_shapes(RVK1,RVK2)
+ scn.objects.selected=[]
+ RVK2.sel=1
+ RVK1.sel=1
+ # ================================================================
+ # ... and not a mesh...===========================================
+ # ================================================================
+ elif result:
+ name = "Selected object must be a mesh %t| Ok. %x1"
+ result = Draw.PupMenu(name)
+ return
+ else :
return
- else :
- name = "At least 2 Meshes as to be selected %t| Ok. %x1"
+ # ================================================================
+ # ... if not object at all. =====================================
+ # ================================================================
+ else:
+ name = "At least one Mesh object must be selected %t| Ok. %x1"
result = Draw.PupMenu(name)
return
+
Blender.Redraw()
+
EDITMODE=Blender.Window.EditMode()
Blender.Window.EditMode(0)
-deform2rvk()
-Blender.Window.EditMode(EDITMODE) \ No newline at end of file
+END = 0
+DEFAULT= Blender.Get('curframe')
+
+while not END:
+ deform2rvk()
+ name = "Do you want to copy at a new frame %t| Yes ? %x1| No ? %x2"
+ result = Draw.PupMenu(name)
+ if result == 1:
+ msg = "Frame :"
+ inputresult = Draw.PupIntInput(msg, DEFAULT , Blender.Get('staframe'), Blender.Get('endframe'))
+ print inputresult
+ if inputresult != None:
+ Blender.Set('curframe',inputresult)
+ Blender.Window.RedrawAll()
+ else:
+ END = 1
+ else:
+ END = 1
+
+Blender.Window.EditMode(EDITMODE)
diff --git a/release/scripts/scripttemplate_background_job.py b/release/scripts/scripttemplate_background_job.py
new file mode 100644
index 00000000000..86b58991849
--- /dev/null
+++ b/release/scripts/scripttemplate_background_job.py
@@ -0,0 +1,124 @@
+#!BPY
+"""
+Name: 'Background Job Example'
+Blender: 248
+Group: 'ScriptTemplate'
+Tooltip: 'Script template for automating tasks from the command line with blender'
+"""
+
+from Blender import Window
+import bpy
+
+script_data = \
+'''# This script is an example of how you can run blender from the command line (in background mode with no interface)
+# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it.
+# This example also shows how you can parse command line options to python scripts.
+#
+# Example usage for this test.
+# blender -b -P $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend"
+#
+# Notice all python args are after the '--' argument.
+
+import Blender
+import bpy
+
+def example_function(body_text, save_path, render_path):
+
+ sce= bpy.data.scenes.active
+
+ txt_data= bpy.data.curves.new('MyText', 'Text3d')
+
+ # Text Object
+ txt_ob = sce.objects.new(txt_data) # add the data to the scene as an object
+ txt_data.setText(body_text) # set the body text to the command line arg given
+ txt_data.setAlignment(Blender.Text3d.MIDDLE)# center text
+
+ # Camera
+ cam_data= bpy.data.cameras.new('MyCam') # create new camera data
+ cam_ob= sce.objects.new(cam_data) # add the camera data to the scene (creating a new object)
+ sce.objects.camera= cam_ob # set the active camera
+ cam_ob.loc= 0,0,10
+
+ # Lamp
+ lamp_data= bpy.data.lamps.new('MyLamp')
+ lamp_ob= sce.objects.new(lamp_data)
+ lamp_ob.loc= 2,2,5
+
+ if save_path:
+ try:
+ f= open(save_path, 'w')
+ f.close()
+ ok= True
+ except:
+ print 'Cannot save to path "%s"' % save_path
+ ok= False
+
+ if ok:
+ Blender.Save(save_path, 1)
+
+ if render_path:
+ render= sce.render
+ render.extensions= True
+ render.renderPath = render_path
+ render.sFrame= 1
+ render.eFrame= 1
+ render.renderAnim()
+
+
+
+import sys # to get command line args
+import optparse # to parse options for us and print a nice help message
+
+script_name= 'background_job.py'
+
+def main():
+
+ # get the args passed to blender after "--", all of which are ignored by blender specifically
+ # so python may receive its own arguments
+ argv= sys.argv
+
+ if '--' not in argv:
+ argv = [] # as if no args are passed
+ else:
+ argv = argv[argv.index('--')+1: ] # get all args after "--"
+
+ # When --help or no args are given, print this help
+ usage_text = 'Run blender in background mode with this script:\n'
+ usage_text += ' blender -b -P ' + script_name + ' -- [options]'
+
+ parser = optparse.OptionParser(usage = usage_text)
+
+
+ # Example background utility, add some text and renders or saves it (with options)
+ # Possible types are: string, int, long, choice, float and complex.
+ parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image', type='string')
+
+ parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE')
+ parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE')
+
+ options, args = parser.parse_args(argv) # In this example we wont use the args
+
+ if not argv:
+ parser.print_help()
+ return
+
+ if not options.body_text:
+ print 'Error: --text="some string" argument not given, aborting.\n'
+ parser.print_help()
+ return
+
+ # Run the example function
+ example_function(options.body_text, options.save_path, options.render_path)
+
+ print 'batch job finished, exiting'
+
+
+if __name__ == '__main__':
+ main()
+'''
+
+new_text = bpy.data.texts.new('background_job.py')
+new_text.write(script_data)
+bpy.data.texts.active = new_text
+Window.RedrawAll()
+
diff --git a/release/scripts/scripttemplate_camer_object.py b/release/scripts/scripttemplate_camera_object.py
index cacc35ed1a5..cacc35ed1a5 100644
--- a/release/scripts/scripttemplate_camer_object.py
+++ b/release/scripts/scripttemplate_camera_object.py
diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py
index 17095251155..577847c0dda 100644
--- a/release/scripts/scripttemplate_gamelogic.py
+++ b/release/scripts/scripttemplate_gamelogic.py
@@ -1,7 +1,7 @@
#!BPY
"""
Name: 'GameLogic Example'
-Blender: 245
+Blender: 249
Group: 'ScriptTemplate'
Tooltip: 'Script template with examples of how to use game logic'
"""
@@ -11,6 +11,9 @@ import bpy
script_data = \
'''
+# This script must be assigned to a python controller
+# where it can access the object that owns it and the sensors/actuators that it connects to.
+
# GameLogic has been added to the global namespace no need to import
# for keyboard event comparison
@@ -26,64 +29,65 @@ def main():
cont = GameLogic.getCurrentController()
# The KX_GameObject that owns this controller.
- own = cont.getOwner()
+ own = cont.owner
# for scripts that deal with spacial logic
- own_pos = own.getPosition()
+ own_pos = own.worldPosition
# Some example functions, remove to write your own script.
# check for a positive sensor, will run on any object without errors.
- print 'Logic info for KX_GameObject', own.getName()
+ print 'Logic info for KX_GameObject', own.name
input = False
- for sens in cont.getSensors():
+ for sens in cont.sensors:
# The sensor can be on another object, we may want to use it
- own_sens = sens.getOwner()
- print ' sensor:', sens.getName(),
- if sens.isPositive():
+ own_sens = sens.owner
+ print ' sensor:', sens.name,
+ if sens.positive:
print '(true)'
input = True
else:
print '(false)'
- for actu in cont.getActuators():
+ for actu in cont.actuators:
# The actuator can be on another object, we may want to use it
- own_actu = actu.getOwner()
- print ' actuator:', sens.getName()
+ own_actu = actu.owner
+ print ' actuator:', actu.name
# This runs the actuator or turns it off
# note that actuators will continue to run unless explicitly turned off.
if input:
- GameLogic.addActiveActuator(actu, True)
+ cont.activate(actu)
else:
- GameLogic.addActiveActuator(actu, False)
+ cont.deactivate(actu)
- # Its also good practice to get sensors and actuators by names
- # so any changes to their order wont break the script.
+ # Its also good practice to get sensors and actuators by name
+ # rather then index so any changes to their order wont break the script.
- # sens_key = cont.getSensor('key_sensor')
- # actu_motion = cont.getActuator('motion')
+ # sens_key = cont.sensors['key_sensor']
+ # actu_motion = cont.actuators['motion']
# Loop through all other objects in the scene
sce = GameLogic.getCurrentScene()
- print 'Scene Objects:', sce.getName()
- for ob in sce.getObjectList():
- print ' ', ob.getName(), ob.getPosition()
+ print 'Scene Objects:', sce.name
+ for ob in sce.objects:
+ print ' ', ob.name, ob.worldPosition
# Example where collision objects are checked for their properties
# adding to our objects "life" property
"""
- actu_collide = cont.getSensor('collision_sens')
- for ob in actu_collide.getHitObjectList():
+ actu_collide = cont.sensors['collision_sens']
+ for ob in actu_collide.objectHitList:
# Check to see the object has this property
- if hasattr(ob, 'life'):
- own.life += ob.life
- ob.life = 0
- print own.life
- """
+ if ob.has_key('life'):
+ own['life'] += ob['life']
+ ob['life'] = 0
+ print own['life']
+ """
+
main()
'''
diff --git a/release/scripts/scripttemplate_gamelogic_basic.py b/release/scripts/scripttemplate_gamelogic_basic.py
index 1584659d317..fd404d5c8a4 100644
--- a/release/scripts/scripttemplate_gamelogic_basic.py
+++ b/release/scripts/scripttemplate_gamelogic_basic.py
@@ -1,7 +1,7 @@
#!BPY
"""
Name: 'GameLogic Template'
-Blender: 245
+Blender: 249
Group: 'ScriptTemplate'
Tooltip: 'Basic template for new game logic scripts'
"""
@@ -14,15 +14,15 @@ script_data = \
def main():
cont = GameLogic.getCurrentController()
- own = cont.getOwner()
+ own = cont.owner
- sens = cont.getSensor('mySensor')
- actu = cont.getActuator('myActuator')
+ sens = cont.sensors['mySensor']
+ actu = cont.actuators['myActuator']
- if sens.isPositive():
- GameLogic.addActiveActuator(actu, True)
+ if sens.positive:
+ cont.activate(actu)
else:
- GameLogic.addActiveActuator(actu, False)
+ cont.deactivate(actu)
main()
'''
diff --git a/release/scripts/scripttemplate_gamelogic_module.py b/release/scripts/scripttemplate_gamelogic_module.py
new file mode 100644
index 00000000000..2ef4950917b
--- /dev/null
+++ b/release/scripts/scripttemplate_gamelogic_module.py
@@ -0,0 +1,45 @@
+#!BPY
+"""
+Name: 'GameLogic Module'
+Blender: 249
+Group: 'ScriptTemplate'
+Tooltip: 'Basic template for new game logic modules'
+"""
+
+from Blender import Window
+import bpy
+
+script_data = \
+'''
+# This module can be accessed by a python controller with
+# its execution method set to 'Module'
+# * Set the module string to "gamelogic_module.main" (without quotes)
+# * When renaming the script it MUST have a .py extension
+# * External text modules are supported as long as they are at
+# the same location as the blendfile or one of its libraries.
+
+import GameLogic
+
+# variables defined here will only be set once when the
+# module is first imported. Set object spesific vars
+# inside the function if you intend to use the module
+# with multiple objects.
+
+def main(cont):
+ own = cont.owner
+
+ sens = cont.sensors['mySensor']
+ actu = cont.actuators['myActuator']
+
+ if sens.positive:
+ cont.activate(actu)
+ else:
+ cont.deactivate(actu)
+
+# dont call main(GameLogic.getCurrentController()), the py controller will
+'''
+
+new_text = bpy.data.texts.new('gamelogic_module.py')
+new_text.write(script_data)
+bpy.data.texts.active = new_text
+Window.RedrawAll()
diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py
new file mode 100644
index 00000000000..fb17367d622
--- /dev/null
+++ b/release/scripts/textplugin_convert_ge.py
@@ -0,0 +1,863 @@
+#!BPY
+"""
+Name: 'Convert BGE 2.49'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: ''
+Tooltip: 'Attemps to update deprecated usage of game engine API.'
+"""
+
+#
+# Copyright 2009 Alex Fraser <alex@phatcore.com>
+#
+# 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/>.
+#
+
+#
+# This script updates game engine scripts that were designed for pre-2.49
+# versions of Blender to run with the new API. Deprecated function calls are
+# listed in attributeRenameDict. This script searches for instances of the keys
+# in a target script and re-writes them.
+#
+# Some deprecated functions are complicated to re-write. The most common
+# conversions have been implemented, but some have not. Running this will reduce
+# the number of deprecation warnings in your scripts, but may not eliminate them
+# entirely.
+#
+# NOTE: The conversion is not guaranteed to be perfect. It is strongly
+# recommended that you review all changes after running this script.
+#
+# TODO: The following attributes are either ambiguous or need special processing
+# to handle parameters. Deprecated attributes that map to multiple target
+# attributes will require a refactor of the main conversion loop in the
+# convert248to249 function: currently, it doesn't allow any conversion to
+# advance the row index by more than one.
+#
+# getLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setAction (BL_ShapeActionActuator, BL_ActionActuator)
+# `reset' argument has no conversion target.
+# set (KX_VisibilityActuator, KX_IpoActuator)
+# Different numbers of arguments.
+# Arguments map to multiple attributes.
+# getIndex (SCA_JoystickSensor)
+# Incompatible values: Old = 1-based index; new = 0-based.
+# getMesh (KX_SCA_ReplaceMeshActuator)
+# Return types differ. Need to call object.name.
+# getObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
+# KX_TrackToActuator, KX_ParentActuator)
+# Default return type differs between classes.
+# setIndex (SCA_JoystickSensor)
+# Incompatible values: Old = 1-based index; new = 0-based.
+# setObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
+# KX_TrackToActuator, KX_ParentActuator)
+# Incompatible types: Old = KX_GameObject or String; new =
+# KX_GameObject.
+# setOperation (KX_SCA_DynamicActuator, KX_StateActuator)
+# Ambiguous: different target names.
+# getDRot (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setDRot (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getDLoc (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setDLoc (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getTorque (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setTorque (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getForce (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setForce (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# position (KX_GameObject)
+# Conflicts with KX_SoundActuator.
+# orientation (KX_GameObject)
+# Conflicts with KX_SoundActuator.
+#
+
+import string
+import re
+
+COMMENTCHAR = '#'
+
+class ParseError(Exception): pass
+class ConversionError(Exception): pass
+
+def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'):
+ """Finds a balanced pair of parentheses, searching from lines[row][col].
+ The opening parenthesis must be on the starting line.
+
+ Returns two tuples containing the row and column of the opening paren, and
+ the row and column of the matching paren.
+
+ Throws a ParseError if the first character is not openChar, or if a matching
+ paren cannot be found."""
+
+ #
+ # Find the opening coordinates.
+ #
+ oRow = row
+ oCol = col
+ line = lines[oRow]
+ while oCol < len(line):
+ if line[oCol] == openChar:
+ break
+ elif line[oCol] == COMMENTCHAR:
+ break
+ oCol = oCol + 1
+
+ if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]):
+ raise ParseError, "Can't find opening parenthesis. '%s'" % openChar
+
+ #
+ # Find the closing coordinates.
+ #
+ eRow = oRow
+ eCol = oCol + 1
+ level = 1
+ while eRow < len(lines) and level > 0:
+ line = lines[eRow]
+ while eCol < len(line) and level > 0:
+ c = line[eCol]
+ if c == openChar:
+ # Found a nested paren.
+ level = level + 1
+ elif c == closeChar:
+ # Exiting one level of nesting.
+ level = level - 1
+ if level == 0:
+ # Back to top level!
+ return (oRow, oCol), (eRow, eCol)
+ elif c == COMMENTCHAR:
+ # Comment. Skip the rest of the line.
+ break
+ eCol = eCol + 1
+ eRow = eRow + 1
+ eCol = 0
+ raise ParseError, "Couldn't find closing parenthesis."
+
+def findLastAssignment(lines, row, attrName):
+ """Finds the most recent assignment of `attrName' before `row'. Returns
+ everything after the '=' sign or None, if there was no match."""
+ contRegex = re.compile(r'[^#]*?' + # Don't search in comments.
+ attrName +
+ r'\s*=\s*(.*)') # Assignment
+
+ cRow = row - 1
+ while cRow >= 0:
+ match = contRegex.search(lines[cRow])
+ if match:
+ return match.group(1)
+ cRow = cRow - 1
+ return None
+
+def replaceSubstr(s, start, end, newSubStr):
+ """Replace the contents of `s' between `start' and `end' with
+ `newSubStr'."""
+ return s[:start] + newSubStr + s[end:]
+
+def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar,
+ oldOpenChar = '(', oldCloseChar = ')'):
+ """Replace the next set of parentheses with different characters. The
+ opening parenthesis must be located on line `row', and on or after
+ `colStart'. The closing parenthesis may be on the same line or any following
+ line. The strings are edited in-place.
+
+ Throws a ParseError if the set of parentheses can't be found. In this case,
+ the strings in `lines' will be untouched."""
+ try:
+ pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar,
+ oldCloseChar)
+ except ParseError:
+ raise
+
+ # Replacement may change string length. Replace closing paren first.
+ r, c = pClose
+ lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar)
+ # Replace opening paren.
+ r, c = pOpen
+ lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar)
+
+def replaceSimpleGetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a simple getter function with a reference to a
+ property, e.g. foo.getBar() -> foo.bar
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceSimpleSetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a simple setter function with a reference to a
+ property, e.g. foo.setBar(baz) -> foo.bar = baz
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+
+def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a multi-agument setter function with a reference to a
+ list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ]
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+
+
+def replaceKeyedGetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a keyed getter function with a reference to a
+ property, e.g. foo.getBar(baz) -> foo.bar[baz]
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceGetXYPosition(lines, row, colStart, colEnd, axis):
+ '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition.
+ This is like a keyed getter, but the key is embedded in the attribute
+ name.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched.'''
+ try:
+ (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines,
+ row, colEnd)
+ except ParseError:
+ raise ConversionError, "Deprecated function reference."
+ if closeRow != row:
+ raise ConversionError, "Can't modify multiple lines."
+
+ lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1,
+ "[%s]" % axis)
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position')
+
+def replaceRename(lines, row, colStart, colEnd, newName):
+ """Replace an identifier with another, e.g.
+ foo.getBar() -> foo.getBaz()
+ foo.bar -> foo.baz
+
+ The identifier being replaced must be on line `row' and between `colStart'
+ and `colEnd'."""
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceAddActiveActuator(lines, row, colStart, colEnd, closure):
+ '''Extra work needs to be done here to find out the name of the controller,
+ and whether the actuator should be activated or deactivated.
+
+ Throws a ConversionError if the actuator, controller or condition can't be
+ found. In this case the content of `lines' will be untouched.'''
+ try:
+ (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd)
+ except ParseError:
+ ConversionError, "Can't find arguments."
+
+ if closeRow != openRow:
+ raise ConversionError, ("Can't perform conversion: arguments span multiple lines.")
+
+ args = lines[row][openCol + 1:closeCol]
+ match = re.search(r'([a-zA-Z_]\w*)' # Actuator identifier
+ r',\s*'
+ r'([0-9a-zA-Z_]\w*)', # Condition (boolean)
+ args)
+ if not match:
+ raise ConversionError, "Can't find arguments."
+
+ actuator = match.group(1)
+ condition = match.group(2)
+ controller = None
+
+ assn = findLastAssignment(lines, row, actuator)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ controller = match.group(1)
+
+ if not controller:
+ raise ConversionError, "Can't find actuator's controller."
+
+ gameLogicStart = lines[row].rfind("GameLogic", 0, colStart)
+ if gameLogicStart < 0:
+ raise ConversionError, "Can't find GameLogic identifier."
+
+ newExpr = None
+ if condition in ['1', 'True']:
+ newExpr = "%s.activate(%s)" % (controller, actuator)
+ elif condition in ['0', 'False']:
+ newExpr = "%s.deactivate(%s)" % (controller, actuator)
+ else:
+ newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % (
+ condition, controller, actuator, controller, actuator)
+ lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr)
+
+def getObject(line, attributeStart):
+ '''Get the object that an attribute belongs to. `attributeStart' is the
+ index of the first character of the attribute name in the string `line'.
+ Returns: the identifier preceding `attributeStart', or None if one can't be
+ found.'''
+ match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart])
+ if not match:
+ return None
+ return match.group(1)
+
+def replaceGetActuator(lines, row, colStart, colEnd, closure):
+ '''getActuator is ambiguous: it could belong to SCA_IController or
+ SCA_ActuatorSensor. Try to resolve and then convert.
+
+ Raises a ConversionError if the parentheses can't be found, or if the
+ ambiguity can't be resolved.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is a controller.
+ assn = findLastAssignment(lines, row, obName)
+ if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn):
+ # It is (probably) a controller!
+ replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators')
+ return
+
+ raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)."
+
+def replaceSetOrientation(lines, row, colStart, colEnd, closure):
+ '''setOrientation is ambiguous: it could belong to KX_SoundActuator or
+ KX_GameObject. Try to resolve and then convert. If the type can't be
+ determined, it is assumed to be a KX_GameObject. Currently, only the
+ conversion for KX_GameObject is implemented.
+
+ Raises a ConversionError if the parentheses can't be found, or if the
+ object is found to be a KX_SoundActuator.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is an actuator.
+ assn = findLastAssignment(lines, row, obName)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ # It's probably a KX_SoundActuator.
+ raise ConversionError, "Not implemented: Can't convert arguments to matrix."
+
+ # It's probably a KX_GameObject.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation')
+
+def replaceSetPosition(lines, row, colStart, colEnd, closure):
+ '''setPosition is ambiguous: it could belong to KX_SoundActuator or
+ KX_GameObject. Try to resolve and then convert. If the type can't be
+ determined, it is assumed to be a KX_GameObject.
+
+ Raises a ConversionError if the parentheses can't be found.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is an actuator.
+ assn = findLastAssignment(lines, row, obName)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ # It's probably a KX_SoundActuator.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'position')
+
+ # It's probably a KX_GameObject.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition')
+
+def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)):
+ '''Some property attributes behave differently when being written to or read
+ from. Try to determine the operation, and replace accordingly. E.G.
+ o.position = foo -> o.localPosition = foo # set
+ foo = o.position -> foo = o.worldPosition # get
+
+ This implementation can not handle cases where the object is returned from
+ a function, e.g.
+ foo = bar.getObject().position # Error!
+
+ Raises a ConversionError if the operation can't be determined, or if the
+ object is returned from a function.'''
+ assnRegex = re.compile(r'(=\s*)?' # Getter
+ r'[a-zA-Z_]\w*' # Object identifier
+ r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes
+ r'(\s*=)?') # Setter
+ match = assnRegex.search(lines[row])
+
+ if not match:
+ raise ConversionError, "Can't determine operation (getting or setting)."
+
+ setting = False
+ getting = False
+ if match.group(1):
+ getting = True
+ if match.group(3):
+ setting = True
+ if (getting and setting) or ((not getting) and (not setting)):
+ raise ConversionError, "Can't determine operation (getting or setting)."
+
+ if getting:
+ replaceRename(lines, row, colStart, colEnd, newGetter)
+ else:
+ replaceRename(lines, row, colStart, colEnd, newSetter)
+
+def notImplemented(lines, row, colStart, colEnd, classNames):
+ message = "Conversion not implemented. See documentation for " +\
+ string.join(classNames, ', ')
+ raise ConversionError, message
+
+#
+# Deprecated attribute information. The format is:
+# deprecatedAttributeName: (conversionFunction, closure)
+# Usually the closure will be the name of the superceding attribute.
+#
+# Since each deprecated attribute can appear in this dictionary only once, it is
+# the conversion function's responsibility to resolve ambiguity.
+#
+attributeRenameDict = {
+ # Special cases
+ 'addActiveActuator': (replaceAddActiveActuator, None), #
+ 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor
+ 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor
+ 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor
+ 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator
+ 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator
+
+ # Keyed getters/setters
+ 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController
+
+ # Multi-arg -> List setter
+ 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor
+ 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator
+ 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator
+ 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor
+ 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator
+ 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator
+
+ # Straight rename
+ 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor
+
+ # Split properties
+ 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject
+
+ # Simple getters/setters
+ 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController
+ 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController
+ 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera
+ 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor
+ 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor
+ 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor
+ 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor
+ 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator
+ 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor
+ 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor
+ 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator
+ 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator
+ 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor
+ 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator
+ 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor
+ 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick
+ 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator
+ 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator
+ 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator
+ 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator
+ 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator
+ 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor
+ 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor
+ 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator
+ 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor
+ 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator
+ 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor
+ 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor
+ 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor
+ 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor
+ 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor
+ 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator
+ 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor
+ 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator
+ 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor
+ 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene
+ 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator
+ 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject
+ 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator
+ 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator
+ 'getName': (replaceSimpleGetter, 'name'), # KX_Scene
+ 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor
+ 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor
+ 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor
+ 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene
+ 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator
+ 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject
+ 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick
+ 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator
+ 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator
+ 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject
+ 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator
+ 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator
+ 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject
+ 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera
+ 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor
+ 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor
+ 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor
+ 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator
+ 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator
+ 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController
+ 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator
+ 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject
+ 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor
+ 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor
+ 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor
+ 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor
+ 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor
+ 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator
+ 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor
+ 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor
+ 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator
+ 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject
+ 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator
+ 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor
+ 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor
+ 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor
+ 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor
+ 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator
+ 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator
+ 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor
+ 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator
+ 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator
+ 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator
+ 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor
+ 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor
+ 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick
+ 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator
+ 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator
+ 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator
+ 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor
+ 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator
+ 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator
+ 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor
+ 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor
+ 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor
+ 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator
+ 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor
+ 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor
+ 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator
+ 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator
+ 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator
+ 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator
+ 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator
+ 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator
+ 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera
+ 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor
+ 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator
+ 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator
+ 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController
+ 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator
+ 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject
+ 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator
+ 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor
+ 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor
+ 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator
+ 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor
+ 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator
+ 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor
+ 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor
+ 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator
+ 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator
+
+ # Unimplemented!
+ 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']),
+ 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']),
+ 'getIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']),
+ 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']),
+ 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'getDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'setDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'getDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'setDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getForce': (notImplemented, ['KX_ObjectActuator']),
+ 'setForce': (notImplemented, ['KX_ObjectActuator']),
+}
+
+def convert248to249(lines, log = True, logErrors = True, fileName = None):
+ # Regular expression for finding attributes. For the string 'a.b', this
+ # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name.
+ attrRegex = re.compile(r'\.\s*' # Dot
+ r'([a-zA-Z_]\w*)') # Identifier
+
+ fileIdStr = ""
+ if fileName:
+ fileIdStr = fileName + ": "
+ row = 0
+ col = 0
+ nconverted = 0
+ nerrors = 0
+ while row < len(lines):
+ originalLine = lines[row]
+ changed = False
+ while col < len(lines[row]):
+ # Don't search past comment. We have to check each iteration
+ # because the line contents may have changed.
+ commentStart = lines[row].find('#', col)
+ if commentStart < 0:
+ commentStart = len(lines[row])
+
+ # Search for an attribute identifier.
+ match = attrRegex.search(lines[row], col, commentStart)
+ if not match:
+ break
+
+ attrName = match.group(1)
+ if attributeRenameDict.has_key(attrName):
+ # name is deprecated.
+ func, closure = attributeRenameDict[attrName]
+ try:
+ # Convert!
+ func(lines, row, match.start(1), match.end(1), closure)
+ except ConversionError, e:
+ # Insert a comment saying the conversion failed.
+ print "ERROR: %sline %d, %s: %s\n" % (
+ fileIdStr, row + 1, attrName, e)
+ if logErrors:
+ lines.insert(row,
+ "##248## ERROR: %s: %s\n" %
+ (attrName, e))
+ row = row + 1
+ nerrors = nerrors + 1
+ else:
+ changed = True
+ nconverted = nconverted + 1
+ # Search the rest of this line.
+ col = match.start(1)
+
+ if changed and log:
+ # Insert a comment to showing difference in lines.
+ if originalLine[-1] != '\n':
+ originalLine = originalLine + '\n'
+ lines.insert(row, "##248##%s" % originalLine)
+ row = row + 1
+
+ row = row + 1
+ col = 0
+ return nconverted, nerrors
+
+def usage():
+ print "Usage: blender248to249.py [options] <infile> [outfile]"
+ print "Options:"
+ print "\t--nolog Don't include old lines as comments."
+ print "\t--quieterrors Don't insert errors as comments."
+
+def runAsConsoleScript():
+ '''Called when being run as a console script.'''
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"])
+ except getopt.GetoptError, err:
+ # print help information and exit:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+ log = True
+ logErrors = True
+ for o, a in opts:
+ if o == "--nolog":
+ log = False
+ elif o == "--quieterrors":
+ logErrors = False
+
+ try:
+ inpath = args.pop(0)
+ except IndexError:
+ usage()
+ sys.exit(2)
+ try:
+ outpath = args.pop(0)
+ except IndexError:
+ outpath = inpath
+
+ infile = io.FileIO(inpath, 'r')
+ # arbitrary file size of around 100kB
+ lines = infile.readlines(100000)
+ infile.close()
+
+ nconverted, nerrors = convert248to249(lines, log, logErrors)
+
+ outfile = io.FileIO(outpath, 'w')
+ outfile.writelines(lines)
+ outfile.close()
+ print "Conversion finished. Modified %d attributes." % nconverted
+ print "There were %d errors." % nerrors
+ print "Please review all the changes."
+
+def runAsTextPlugin():
+ '''Called when run as a text plugin.'''
+
+ import Blender
+ from Blender import Window, sys, Draw
+ import BPyTextPlugin, bpy
+
+ message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|"
+ "Run on active script only%x1|"
+ "Run on ALL text buffers%x2")
+ convertAllBuffers = Draw.PupMenu(message) == 2
+
+ Window.WaitCursor(1)
+ try:
+ nconverted = 0
+ nerrors = 0
+
+ if convertAllBuffers:
+ texts = bpy.data.texts
+ else:
+ if not bpy.data.texts.active:
+ Draw.PupMenu("No active buffer.")
+ return
+ texts = [bpy.data.texts.active]
+
+ Blender.SaveUndoState('Convert BGE 2.49')
+
+ for txt in texts:
+ bufName = txt.name
+ if txt.lib:
+ bufName = txt.lib + '/' + bufName
+ lines = txt.asLines()
+ for i in range(0, len(lines)):
+ if not lines[i].endswith('\n'):
+ lines[i] = lines[i] + '\n'
+
+ nc, ne = convert248to249(lines, fileName = bufName)
+ nconverted = nconverted + nc
+ nerrors = nerrors + ne
+ txt.clear()
+ for line in lines:
+ txt.write(line)
+
+ finally:
+ Window.WaitCursor(0)
+
+ message = "Converted %d attributes." % nconverted
+ if nerrors == 1:
+ message = message + " There was 1 error (see console)."
+ if nerrors > 1:
+ message = message + " There were %d errors (see console)." % nerrors
+ message = message + "|Please review all the changes."
+ Draw.PupMenu(message)
+
+def main():
+ try:
+ import Blender
+ except ImportError:
+ runAsConsoleScript()
+ else:
+ runAsTextPlugin()
+
+# This lets you import the script without running it
+if __name__ == "__main__":
+ import sys
+ import getopt
+ import io
+ main()
diff --git a/release/scripts/uvcalc_follow_active_coords.py b/release/scripts/uvcalc_follow_active_coords.py
index 79a445329cc..83df200991f 100644
--- a/release/scripts/uvcalc_follow_active_coords.py
+++ b/release/scripts/uvcalc_follow_active_coords.py
@@ -42,28 +42,15 @@ from Blender import *
import bpy
import BPyMesh
-def extend():
- sce = bpy.data.scenes.active
- ob = sce.objects.active
-
- # print ob, ob.type
- if ob == None or ob.type != 'Mesh':
- Draw.PupMenu('ERROR: No mesh object.')
+def extend(EXTEND_MODE,ob):
+ if EXTEND_MODE == -1:
return
-
- # Toggle Edit mode
+ me = ob.getData(mesh=1)
+ me_verts = me.verts
+ # Toggle Edit mode
is_editmode = Window.EditMode()
if is_editmode:
Window.EditMode(0)
-
- me = ob.getData(mesh=1)
- me_verts = me.verts
-
- # 0:normal extend, 1:edge length
- EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0")
- if EXTEND_MODE == -1:
- return
-
Window.WaitCursor(1)
t = sys.time()
edge_average_lengths = {}
@@ -153,8 +140,7 @@ def extend():
uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
if not me.faceUV:
- Draw.PupMenu('ERROR: Mesh has no face UV coords.')
- return
+ me.faceUV= True
face_act = me.activeFace
if face_act == -1:
@@ -247,7 +233,22 @@ def extend():
Window.RedrawAll()
Window.WaitCursor(0)
-if __name__ == '__main__':
- extend()
+
+def main():
+ sce = bpy.data.scenes.active
+ ob = sce.objects.active
+
+ # print ob, ob.type
+ if ob == None or ob.type != 'Mesh':
+ Draw.PupMenu('ERROR: No mesh object.')
+ return
- \ No newline at end of file
+
+
+ # 0:normal extend, 1:edge length
+ EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0")
+ extend(EXTEND_MODE,ob)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/release/scripts/uvcalc_quad_clickproj.py b/release/scripts/uvcalc_quad_clickproj.py
index 0bba747e010..298103e4d5f 100644
--- a/release/scripts/uvcalc_quad_clickproj.py
+++ b/release/scripts/uvcalc_quad_clickproj.py
@@ -46,7 +46,7 @@ import BPyWindow
mouseViewRay= BPyWindow.mouseViewRay
from Blender import Mathutils, Window, Scene, Draw, sys
-from Blender.Mathutils import CrossVecs, Vector, Matrix, LineIntersect, Intersect #, AngleBetweenVecs, Intersect
+from Blender.Mathutils import Vector, Matrix, LineIntersect, Intersect #, AngleBetweenVecs, Intersect
LMB= Window.MButs.L
RMB= Window.MButs.R
@@ -171,6 +171,9 @@ def main():
f_uv = f.uv
return [(v.co-face_corner_main, f_uv[i]) for i,v in enumerate(f.v)]
+ if me.faceUV==False:
+ me.faceUV= True
+
coords = [ (co,uv) for f in me.faces if f.sel for co, uv in get_face_coords(f)]
coords_orig = [uv.copy() for co, uv in coords]
@@ -226,7 +229,7 @@ def main():
y_axis_length = line_a_len
x_axis_length = (line_isect_b_pair[1]-face_corner_main).length
- proj_y_component = CrossVecs(proj_x_component, proj_z_component)
+ proj_y_component = proj_x_component.cross(proj_z_component)
proj_y_component.length = 1/y_axis_length
proj_x_component.length = 1/x_axis_length
@@ -264,4 +267,5 @@ def main():
if __name__=='__main__':
main()
- Window.DrawProgressBar(1.0, '') \ No newline at end of file
+ Window.DrawProgressBar(1.0, '')
+
diff --git a/release/scripts/uvcalc_smart_project.py b/release/scripts/uvcalc_smart_project.py
index d622e1a2af8..9d9bd2aaefd 100644
--- a/release/scripts/uvcalc_smart_project.py
+++ b/release/scripts/uvcalc_smart_project.py
@@ -43,7 +43,7 @@ selected faces, or all faces.
from Blender import Object, Draw, Window, sys, Mesh, Geometry
-from Blender.Mathutils import CrossVecs, Matrix, Vector, RotationMatrix, DotVecs
+from Blender.Mathutils import Matrix, Vector, RotationMatrix
import bpy
from math import cos
@@ -96,7 +96,7 @@ def pointInTri2D(v, v1, v2, v3):
side1 = v2 - v1
side2 = v3 - v1
- nor = CrossVecs(side1, side2)
+ nor = side1.cross(side2)
l1 = [side1[0], side1[1], side1[2]]
l2 = [side2[0], side2[1], side2[2]]
@@ -804,11 +804,11 @@ def VectoMat(vec):
a3 = vec.__copy__().normalize()
up = Vector(0,0,1)
- if abs(DotVecs(a3, up)) == 1.0:
+ if abs(a3.dot(up)) == 1.0:
up = Vector(0,1,0)
- a1 = CrossVecs(a3, up).normalize()
- a2 = CrossVecs(a3, a1)
+ a1 = a3.cross(up).normalize()
+ a2 = a3.cross(a1)
return Matrix([a1[0], a1[1], a1[2]], [a2[0], a2[1], a2[2]], [a3[0], a3[1], a3[2]])
@@ -870,7 +870,7 @@ def main():
'UV Layout',\
('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
('Stretch to bounds', USER_STRETCH_ASPECT, 'Stretch the final output to texture bounds.'),\
- ('Island Margin:', USER_ISLAND_MARGIN, 0.0, 0.25, 'Margin to reduce bleed from adjacent islands.'),\
+ ('Island Margin:', USER_ISLAND_MARGIN, 0.0, 0.5, 'Margin to reduce bleed from adjacent islands.'),\
'Fill in empty areas',\
('Fill Holes', USER_FILL_HOLES, 'Fill in empty areas reduced texture waistage (slow).'),\
('Fill Quality:', USER_FILL_HOLES_QUALITY, 1, 100, 'Depends on fill holes, how tightly to fill UV holes, (higher is slower)'),\
@@ -1001,7 +1001,7 @@ def main():
for fIdx in xrange(len(tempMeshFaces)-1, -1, -1):
# Use half the angle limit so we dont overweight faces towards this
# normal and hog all the faces.
- if DotVecs(newProjectVec, tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
+ if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
newProjectMeshFaces.append(tempMeshFaces.pop(fIdx))
# Add the average of all these faces normals as a projectionVec
@@ -1027,7 +1027,7 @@ def main():
# Get the closest vec angle we are to.
for p in projectVecs:
- temp_angle_diff= DotVecs(p, tempMeshFaces[fIdx].no)
+ temp_angle_diff= p.dot(tempMeshFaces[fIdx].no)
if angleDifference < temp_angle_diff:
angleDifference= temp_angle_diff
@@ -1066,14 +1066,14 @@ def main():
i = len(projectVecs)
# Initialize first
- bestAng = DotVecs(fvec, projectVecs[0])
+ bestAng = fvec.dot(projectVecs[0])
bestAngIdx = 0
# Cycle through the remaining, first alredy done
while i-1:
i-=1
- newAng = DotVecs(fvec, projectVecs[i])
+ newAng = fvec.dot(projectVecs[i])
if newAng > bestAng: # Reverse logic for dotvecs
bestAng = newAng
bestAngIdx = i
diff --git a/release/scripts/vertexpaint_from_material.py b/release/scripts/vertexpaint_from_material.py
index 2df5b7e721f..9668c521f3a 100644
--- a/release/scripts/vertexpaint_from_material.py
+++ b/release/scripts/vertexpaint_from_material.py
@@ -27,6 +27,7 @@ def matcol(mat):
int(mat.R*255),\
int(mat.G*255),\
int(mat.B*255)
+ else:
return None
def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR):
@@ -47,7 +48,7 @@ def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR):
me= ob.getData(mesh=1)
try:
- me.faceUV=True
+ me.vertexColors=True
except: # no faces
continue
diff --git a/release/scripts/vertexpaint_selfshadow_ao.py b/release/scripts/vertexpaint_selfshadow_ao.py
index 95ba7d2fb23..3554e016f79 100644
--- a/release/scripts/vertexpaint_selfshadow_ao.py
+++ b/release/scripts/vertexpaint_selfshadow_ao.py
@@ -43,9 +43,8 @@ import bpy
import BPyMesh
-def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY):
+def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_STRENGTH, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY):
Window.WaitCursor(1)
- DotVecs = Mathutils.DotVecs
Ang= Mathutils.AngleBetweenVecs
BPyMesh.meshCalcNormals(me)
@@ -63,7 +62,7 @@ def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PRE
for v in f.v:
vno=v.no # get a scaled down normal.
- dot= DotVecs(vno, v.co) - DotVecs(vno, fc)
+ dot= vno.dot(v.co) - vno.dot(fc)
vert_tone_count[v.index]+=1
try:
a= Ang(vno, fno)
@@ -84,32 +83,34 @@ def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PRE
if vert_tone_count[i]:
vert_tone[i] = vert_tone[i] / vert_tone_count[i]
+
+ # Below we use edges to blur along so the edges need counting, not the faces
+ vert_tone_count= [0] * len(me.verts)
+ for ed in me.edges:
+ vert_tone_count[ed.v1.index] += 1
+ vert_tone_count[ed.v2.index] += 1
+
- # BLUR TONE
- edge_lengths= [ ed.length for ed in me.edges]
+ # Blur tone
+ blur = PREF_BLUR_STRENGTH
+ blur_inv = 1.0 - PREF_BLUR_STRENGTH
for i in xrange(PREF_BLUR_ITERATIONS):
+
+ # backup the original tones
orig_vert_tone= list(vert_tone)
- for ii, ed in enumerate(me.edges):
+
+ for ed in me.edges:
+
i1= ed.v1.index
i2= ed.v2.index
- l= edge_lengths[ii]
+
+ val1= (orig_vert_tone[i2]*blur) + (orig_vert_tone[i1]*blur_inv)
+ val2= (orig_vert_tone[i1]*blur) + (orig_vert_tone[i2]*blur_inv)
- f=1.0
- if l > PREF_MIN_EDLEN and l < PREF_BLUR_RADIUS:
- f= l/PREF_BLUR_RADIUS
-
- len_vert_tone_list_i1 = vert_tone_count[i1]
- len_vert_tone_list_i2 = vert_tone_count[i2]
-
- if not len_vert_tone_list_i1: len_vert_tone_list_i1=1
- if not len_vert_tone_list_i2: len_vert_tone_list_i2=1
-
- val1= (orig_vert_tone[i2]/len_vert_tone_list_i1)/ f
- val2= (orig_vert_tone[i1]/len_vert_tone_list_i2)/ f
-
- vert_tone[i1]+= val1
- vert_tone[i2]+= val2
+ # Apply the ton divided by the number of faces connected
+ vert_tone[i1]+= val1 / max(vert_tone_count[i1], 1)
+ vert_tone[i2]+= val2 / max(vert_tone_count[i2], 1)
min_tone= min(vert_tone)
@@ -145,21 +146,19 @@ def main():
me= ob.getData(mesh=1)
- PREF_BLUR_ITERATIONS= Draw.Create(1)
- PREF_BLUR_RADIUS= Draw.Create(0.05)
- PREF_MIN_EDLEN= Draw.Create(0.01)
+ PREF_BLUR_ITERATIONS= Draw.Create(1)
+ PREF_BLUR_STRENGTH= Draw.Create(0.5)
PREF_CLAMP_CONCAVE= Draw.Create(90)
PREF_CLAMP_CONVEX= Draw.Create(20)
PREF_SHADOW_ONLY= Draw.Create(0)
PREF_SEL_ONLY= Draw.Create(0)
pup_block= [\
'Post AO Blur',\
- (' Iterations:', PREF_BLUR_ITERATIONS, 0, 40, 'Number times to blur the colors. (higher blurs more)'),\
- (' Blur Radius:', PREF_BLUR_RADIUS, 0.01, 40.0, 'How much distance effects blur transfur (higher blurs more).'),\
- (' Min EdgeLen:', PREF_MIN_EDLEN, 0.00001, 1.0, 'Minimim edge length to blur (very low values can cause errors).'),\
+ ('Strength:', PREF_BLUR_STRENGTH, 0, 1, 'Blur strength per iteration'),\
+ ('Iterations:', PREF_BLUR_ITERATIONS, 0, 40, 'Number times to blur the colors. (higher blurs more)'),\
'Angle Clipping',\
- (' Highlight Angle:', PREF_CLAMP_CONVEX, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
- (' Shadow Angle:', PREF_CLAMP_CONCAVE, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
+ ('Highlight Angle:', PREF_CLAMP_CONVEX, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
+ ('Shadow Angle:', PREF_CLAMP_CONCAVE, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
('Shadow Only', PREF_SHADOW_ONLY, 'Dont calculate highlights for convex areas.'),\
('Sel Faces Only', PREF_SEL_ONLY, 'Only apply to UV/Face selected faces (mix vpain/uvface select).'),\
]
@@ -167,19 +166,20 @@ def main():
if not Draw.PupBlock('SelfShadow...', pup_block):
return
- PREF_BLUR_ITERATIONS= PREF_BLUR_ITERATIONS.val
- PREF_BLUR_RADIUS= PREF_BLUR_RADIUS.val
- PREF_MIN_EDLEN= PREF_MIN_EDLEN.val
- PREF_CLAMP_CONCAVE= PREF_CLAMP_CONCAVE.val
- PREF_CLAMP_CONVEX= PREF_CLAMP_CONVEX.val
- PREF_SHADOW_ONLY= PREF_SHADOW_ONLY.val
- PREF_SEL_ONLY= PREF_SEL_ONLY.val
-
if not me.vertexColors:
me.vertexColors= 1
t= sys.time()
- vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY)
+ vertexFakeAO(me, PREF_BLUR_ITERATIONS.val, \
+ PREF_BLUR_STRENGTH.val, \
+ PREF_CLAMP_CONCAVE.val, \
+ PREF_CLAMP_CONVEX.val, \
+ PREF_SHADOW_ONLY.val, \
+ PREF_SEL_ONLY.val)
+
+ if ob.modifiers:
+ me.update()
+
print 'done in %.6f' % (sys.time()-t)
if __name__=='__main__':
main()
diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py
new file mode 100644
index 00000000000..2d653b211d5
--- /dev/null
+++ b/release/scripts/wizard_bolt_factory.py
@@ -0,0 +1,2811 @@
+#!BPY
+# -*- coding: latin-1 -*-
+"""
+Name: 'Bolt Factory'
+Blender: 248
+Group: 'Wizards'
+Tooltip: 'Create models of various types of screw fasteners.'
+"""
+
+__author__ = " Aaron Keith (Spudmn) "
+__version__ = "2.02 2009/06/10"
+__url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"]
+__bpydoc__ = """\
+Bolt_Factory.py
+
+Bolt Factory is a Python script for Blender 3D.
+
+The script allows the user to create models of various types of screw fasteners.
+
+For best results set the material to smooth and apply a Edge Split modifier
+with default settings.
+
+
+History:
+ V2.02 10/06/09 by Aaron Keith
+
+ -Added changes made by the Blender team.
+
+ V2.01 26/05/09 by Aaron Keith
+
+ - Fixed normal's on Lock Nut
+
+V2.00 22/05/09 by Aaron Keith
+
+- Better error checking.
+- Lock Nut and Hex Nut meshes added.
+- Pre-sets for common metric bolts and nuts.
+- Improved GUI.
+- Meshes scaled to a smaller size
+- Fixed bug when using crest and root percent other than 10%
+- Can now create meshes in Edit Mode. This will add to the
+ current mesh and align with the current view.
+
+V1.00 01/04/08 by Aaron Keith
+
+- This version is very much a work in progress.
+- This is my first attempt to program in Python. This version is
+ unpolished and doesn't do much error checking. Therefore
+ if the user sets strange variable the model created will be
+ as equally strange.
+
+- To Do:
+- Better error checking.
+- More Head and Bit types.
+- Better documentation.
+
+
+"""
+
+# --------------------------------------------------------------------------
+# Bolt_Factory.py
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2009: Aaron Keith
+#
+# 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 *****
+# --------------------------------------------------------------------------
+
+
+
+
+import Blender
+from Blender import Draw, BGL,Mesh
+from Blender import *
+from math import *
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+
+#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
+Global_NutRad = 0.0
+MAX_INPUT_NUMBER = 50
+
+No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17) # this is like a ENUM
+
+
+Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""],
+ 'CAP' : [Draw.Create(0),On_Cap_Click,""],
+ 'DOME': [Draw.Create(0),On_Dome_Click,""],
+ 'PAN' : [Draw.Create(0),On_Pan_Click,""]}
+
+
+Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""],
+ 'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""],
+ 'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]}
+
+Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"],
+ 'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]}
+
+Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""],
+ 'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]}
+
+
+Phillips_Bit_Depth = Draw.Create(3.27)
+Philips_Bit_Dia = Draw.Create(5.20)
+
+Allen_Bit_Depth = Draw.Create(4.0)
+Allen_Bit_Flat_Distance = Draw.Create(6.0)
+
+Hex_Head_Height = Draw.Create(5.3)
+Hex_Head_Flat_Distance = Draw.Create(13.0)
+
+Cap_Head_Dia = Draw.Create(13.5)
+Cap_Head_Height = Draw.Create(8.0)
+
+Dome_Head_Dia = Draw.Create(16.0)
+
+Pan_Head_Dia = Draw.Create(16.0)
+
+Shank_Dia = Draw.Create(8.0)
+Shank_Length = Draw.Create(0.0)
+
+Thread_Length = Draw.Create(16.0)
+Major_Dia = Draw.Create(8.0)
+Minor_Dia = Draw.Create(6.917)
+Pitch = Draw.Create(1.0)
+Crest_Percent = Draw.Create(10)
+Root_Percent = Draw.Create(10)
+
+Hex_Nut_Height = Draw.Create(8.0)
+Hex_Nut_Flat_Distance = Draw.Create(13.0)
+
+Preset_Menu = Draw.Create(5)
+
+
+##########################################################################################
+##########################################################################################
+## Miscellaneous Utilities
+##########################################################################################
+##########################################################################################
+
+# Returns a list of verts rotated by the given matrix. Used by SpinDup
+def Rot_Mesh(verts,matrix):
+ return [list(Vector(v) * matrix) for v in verts]
+
+# 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 xrange(int(DIVISIONS)):
+ rotmat = Mathutils.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):
+ return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS]
+
+
+# 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
+
+
+##########################################################################################
+##########################################################################################
+## 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 y
+
+##########################################################################################
+##########################################################################################
+## Error Checking
+##########################################################################################
+##########################################################################################
+
+
+def Error_Check():
+
+ #global Phillips_Bit_Depth
+ #global Philips_Bit_Dia
+
+ #global Allen_Bit_Depth
+ #global Allen_Bit_Flat_Distance
+
+ #global Hex_Head_Height
+ #global Hex_Head_Flat_Distance
+
+ #global Cap_Head_Dia
+ #global Cap_Head_Height
+
+
+ #global Dome_Head_Dia
+
+ #global Pan_Head_Dia
+
+ #global Shank_Dia
+ #global Shank_Length
+
+ global Thread_Length
+ global Major_Dia
+ global Minor_Dia
+ global Pitch
+ global Hex_Nut_Flat_Distance
+ global Model_Type
+ #global Crest_Percent
+ #global Root_Percent
+
+ Error_Result = 0
+
+ if Minor_Dia.val >= Major_Dia.val:
+ error_txt = "Error%t|Major Dia must be larger than Minor Dia"
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ Error_Result = TRUE
+
+ elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val):
+ error_txt = "Error%t|Thread length must be at least 7 times the Pitch"
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ Error_Result = TRUE
+
+ elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val):
+ error_txt = "Error%t|Nut Flat Distance must be greater than Major Dia"
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ Error_Result = TRUE
+
+ elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val):
+ error_txt = "Error%t|Nut Height must be greater than 2.5 * Pitch"
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ Error_Result = TRUE
+
+ elif (Model_Type['BOLT'][0].val):
+ Check_Head_Height = None
+ Check_Bit_Height = None
+ if (Bit_Type['ALLEN'][0].val):
+ Check_Bit_Height = Allen_Bit_Depth.val
+ if (Bit_Type['PHILLIPS'][0].val):
+ Check_Bit_Height = Phillips_Bit_Depth.val
+ if (Head_Type['HEX'][0].val):
+ Check_Head_Height = Hex_Head_Height.val
+ if (Head_Type['CAP'][0].val):
+ Check_Head_Height = Cap_Head_Height.val
+
+ if Check_Head_Height != None and Check_Bit_Height != None :
+ if Check_Bit_Height > Check_Head_Height:
+ error_txt = "Error%t|Bit Depth must not be greater that Head Height"
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ Error_Result = TRUE
+
+
+ return Error_Result
+
+
+
+##########################################################################################
+##########################################################################################
+## 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((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((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((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((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_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 Bolt
+##########################################################################################
+##########################################################################################
+
+
+
+def MakeBolt():
+ global Phillips_Bit_Depth
+ global Philips_Bit_Dia
+
+ global Allen_Bit_Depth
+ global Allen_Bit_Flat_Distance
+
+ global Hex_Head_Height
+ global Hex_Head_Flat_Distance
+
+ global Cap_Head_Dia
+ global Cap_Head_Height
+
+
+ global Dome_Head_Dia
+
+ global Pan_Head_Dia
+
+ global Shank_Dia
+ global Shank_Length
+
+ global Thread_Length
+ global Major_Dia
+ global Minor_Dia
+ global Pitch
+ global Crest_Percent
+ global Root_Percent
+
+ verts = []
+ faces = []
+ Bit_Verts = []
+ Bit_Faces = []
+ Bit_Dia = 0.001
+ Head_Verts = []
+ Head_Faces= []
+ Head_Height = 0.0
+ ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val # set default
+
+
+ Head_Height = Hex_Head_Height.val # will be changed by the Head Functions
+
+ if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val:
+ #need to size Allen bit if it is too big.
+ if Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val):
+ ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05
+ print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance
+
+ #bit Mesh
+ if Bit_Type['ALLEN'][0].val:
+ Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val)
+
+ if Bit_Type['PHILLIPS'][0].val:
+ Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val)
+
+
+ #Head Mesh
+ if Head_Type['HEX'][0].val:
+ Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val)
+
+ elif Head_Type['CAP'][0].val:
+ Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0))
+
+ elif Head_Type['DOME'][0].val:
+ Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
+
+ elif Head_Type['PAN'][0].val:
+ Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,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(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val)
+
+ 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
+
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+## 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
+
+
+
+##########################################################################################
+##########################################################################################
+## 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
+ 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])
+ 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 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,1))
+
+ 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
+
+
+
+def Nut_Mesh():
+
+ verts = []
+ faces = []
+ Head_Verts = []
+ Head_Faces= []
+
+ Face_Start = len(verts)
+ Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,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(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height)
+ verts.extend((Head_Verts))
+ faces.extend(Copy_Faces(Head_Faces,Face_Start))
+
+ LowZ = 0 - New_Nut_Height
+
+ if Nut_Type['LOCK'][0].val:
+ 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
+
+
+
+##################################################################################################
+
+
+def Create_Nut():
+
+ verts = []
+ faces = []
+
+
+ if Error_Check() :
+ return
+
+
+ verts, faces = Nut_Mesh()
+ Add_Mesh_To_Scene('Nut', verts, faces)
+
+
+##################################################################################################
+
+
+def Create_Bolt():
+ verts = []
+ faces = []
+
+
+ if Error_Check() :
+ return
+
+ verts, faces = MakeBolt()
+ Add_Mesh_To_Scene('Bolt', verts, faces)
+
+
+
+def Remove_Doubles_From_Mesh(verts,faces):
+ Ret_verts = []
+ Ret_faces = []
+
+ is_editmode = Window.EditMode() # Store edit mode state
+ if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
+
+ Temp_mesh = Mesh.New('MeshTemp') # create a new mesh
+
+ Temp_mesh.verts.extend(verts) # add vertices to mesh
+ Temp_mesh.faces.extend(faces) # add faces to the mesh (also adds edges)
+
+ scn = Scene.GetCurrent() # link object to current scene
+ Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp')
+
+ Temp_mesh.remDoubles(0.010)
+ Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
+ Ret_verts[:] = [v.co for v in Temp_mesh.verts]
+ Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces]
+
+ #delete temp mesh
+ scn.objects.unlink(Temp_Object)
+ scn.update(0)
+
+ if is_editmode: Window.EditMode(1)
+ return Ret_verts,Ret_faces
+
+
+
+def Add_Mesh_To_Scene(name, verts, faces):
+
+ scn = Scene.GetCurrent()
+ if scn.lib: return
+ ob_act = scn.objects.active
+
+ is_editmode = Window.EditMode()
+
+ cursor = Window.GetCursorPos()
+ quat = None
+
+ if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well
+ try: quat = Blender.Mathutils.Quaternion(Window.GetViewQuat())
+ except: pass
+
+
+ # Exist editmode for non mesh types
+ if ob_act and ob_act.type != 'Mesh' and is_editmode:
+ EditMode(0)
+
+ # We are in mesh editmode
+ if Window.EditMode():
+ me = ob_act.getData(mesh=1)
+
+ if me.multires:
+ error_txt = 'Error%t|Unable to complete action with multires enabled'
+ Blender.Draw.PupMenu(error_txt)
+ print error_txt
+ return
+
+ #Don't want to remove doubles and scale the existing
+ # mesh so we need to get the verts and the faces from
+ # a mesh that has been scaled.
+ verts,faces = Remove_Doubles_From_Mesh(verts, faces)
+
+ # Add to existing mesh
+ # must exit editmode to modify mesh
+ Window.EditMode(0)
+
+ me.sel = False
+
+ vert_offset = len(me.verts)
+ face_offset = len(me.faces)
+
+
+ # transform the verts
+ txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor))
+ if quat:
+ mat = quat.toMatrix()
+ mat.invert()
+ mat.resize4x4()
+ txmat = mat * txmat
+
+ txmat = txmat * ob_act.matrixWorld.copy().invert()
+
+
+ me.verts.extend(verts)
+ # Transform the verts by the cursor and view rotation
+ me.transform(txmat, selected_only=True)
+
+ if vert_offset:
+ me.faces.extend([[i+vert_offset for i in f] for f in faces])
+ else:
+ # Mesh with no data, unlikely
+ me.faces.extend(faces)
+ else:
+
+ # Object mode add new
+ me = Mesh.New(name)
+ me.verts.extend(verts)
+ me.faces.extend(faces)
+
+
+ me.sel = True
+
+ # Object creation and location
+ scn.objects.selected = []
+ ob_act = scn.objects.new(me, name)
+
+ me.remDoubles(0.010)
+ me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
+
+ scn.objects.active = ob_act
+
+ if quat:
+ mat = quat.toMatrix()
+ mat.invert()
+ mat.resize4x4()
+ ob_act.setMatrix(mat)
+
+ ob_act.loc = cursor
+
+ me.calcNormals()
+
+ if is_editmode or Blender.Get('add_editmode'):
+ Window.EditMode(1)
+
+ Blender.Redraw(-1)#Redraw all
+
+##################################################################################################
+
+
+
+def Load_Preset():
+
+ global Preset_Menu
+ global Shank_Dia
+ global Shank_Length
+ global Thread_Length
+ global Major_Dia
+ global Minor_Dia
+ global Pitch
+ global Crest_Percent
+ global Root_Percent
+ global Allen_Bit_Flat_Distance
+ global Allen_Bit_Depth
+ global Head_Height
+ global Hex_Head_Flat_Distance
+ global Head_Dia
+ global Dome_Head_Dia
+ global Pan_Head_Dia
+ global Philips_Bit_Dia
+ global Phillips_Bit_Depth
+ global Cap_Head_Height
+
+ global Hex_Nut_Height
+ global Hex_Nut_Flat_Distance
+
+
+ if Preset_Menu.val == 1 : #M3
+ Shank_Dia.val = 3.0
+ #Pitch.val = 0.5 #Coarse
+ Pitch.val = 0.35 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 3.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 5.5
+ Hex_Head_Height.val = 2.0
+ Cap_Head_Dia.val = 5.5
+ Cap_Head_Height.val = 3.0
+ Allen_Bit_Flat_Distance.val = 2.5
+ Allen_Bit_Depth.val = 1.5
+ Pan_Head_Dia.val = 5.6
+ Dome_Head_Dia.val = 5.6
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 2.4
+ Hex_Nut_Flat_Distance.val = 5.5
+ Thread_Length.val = 6
+ Shank_Length.val = 0.0
+
+
+ if Preset_Menu.val == 2 : #M4
+ Shank_Dia.val = 4.0
+ #Pitch.val = 0.7 #Coarse
+ Pitch.val = 0.5 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 4.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 7.0
+ Hex_Head_Height.val = 2.8
+ Cap_Head_Dia.val = 7.0
+ Cap_Head_Height.val = 4.0
+ Allen_Bit_Flat_Distance.val = 3.0
+ Allen_Bit_Depth.val = 2.0
+ Pan_Head_Dia.val = 8.0
+ Dome_Head_Dia.val = 8.0
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 3.2
+ Hex_Nut_Flat_Distance.val = 7.0
+ Thread_Length.val = 8
+ Shank_Length.val = 0.0
+
+
+ if Preset_Menu.val == 3 : #M5
+ Shank_Dia.val = 5.0
+ #Pitch.val = 0.8 #Coarse
+ Pitch.val = 0.5 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 5.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 8.0
+ Hex_Head_Height.val = 3.5
+ Cap_Head_Dia.val = 8.5
+ Cap_Head_Height.val = 5.0
+ Allen_Bit_Flat_Distance.val = 4.0
+ Allen_Bit_Depth.val = 2.5
+ Pan_Head_Dia.val = 9.5
+ Dome_Head_Dia.val = 9.5
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 4.0
+ Hex_Nut_Flat_Distance.val = 8.0
+ Thread_Length.val = 10
+ Shank_Length.val = 0.0
+
+
+ if Preset_Menu.val == 4 : #M6
+ Shank_Dia.val = 6.0
+ #Pitch.val = 1.0 #Coarse
+ Pitch.val = 0.75 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 6.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 10.0
+ Hex_Head_Height.val = 4.0
+ Cap_Head_Dia.val = 10.0
+ Cap_Head_Height.val = 6.0
+ Allen_Bit_Flat_Distance.val = 5.0
+ Allen_Bit_Depth.val = 3.0
+ Pan_Head_Dia.val = 12.0
+ Dome_Head_Dia.val = 12.0
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 5.0
+ Hex_Nut_Flat_Distance.val = 10.0
+ Thread_Length.val = 12
+ Shank_Length.val = 0.0
+
+
+ if Preset_Menu.val == 5 : #M8
+ Shank_Dia.val = 8.0
+ #Pitch.val = 1.25 #Coarse
+ Pitch.val = 1.00 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 8.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 13.0
+ Hex_Head_Height.val = 5.3
+ Cap_Head_Dia.val = 13.5
+ Cap_Head_Height.val = 8.0
+ Allen_Bit_Flat_Distance.val = 6.0
+ Allen_Bit_Depth.val = 4.0
+ Pan_Head_Dia.val = 16.0
+ Dome_Head_Dia.val = 16.0
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 6.5
+ Hex_Nut_Flat_Distance.val = 13.0
+ Thread_Length.val = 16
+ Shank_Length.val = 0.0
+
+ if Preset_Menu.val == 6 : #M10
+ Shank_Dia.val = 10.0
+ #Pitch.val = 1.5 #Coarse
+ Pitch.val = 1.25 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 10.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 17.0
+ Hex_Head_Height.val = 6.4
+ Cap_Head_Dia.val = 16.0
+ Cap_Head_Height.val = 10.0
+ Allen_Bit_Flat_Distance.val = 8.0
+ Allen_Bit_Depth.val = 5.0
+ Pan_Head_Dia.val = 20.0
+ Dome_Head_Dia.val = 20.0
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 8.0
+ Hex_Nut_Flat_Distance.val = 17.0
+ Thread_Length.val = 20
+ Shank_Length.val = 0.0
+
+
+ if Preset_Menu.val == 7 : #M12
+ #Pitch.val = 1.75 #Coarse
+ Pitch.val = 1.50 #Fine
+ Crest_Percent.val = 10
+ Root_Percent.val = 10
+ Major_Dia.val = 12.0
+ Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+ Hex_Head_Flat_Distance.val = 19.0
+ Hex_Head_Height.val = 7.5
+ Cap_Head_Dia.val = 18.5
+ Cap_Head_Height.val = 12.0
+ Allen_Bit_Flat_Distance.val = 10.0
+ Allen_Bit_Depth.val = 6.0
+ Pan_Head_Dia.val = 24.0
+ Dome_Head_Dia.val = 24.0
+ Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+ Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+ Hex_Nut_Height.val = 10.0
+ Hex_Nut_Flat_Distance.val = 19.0
+ Shank_Dia.val = 12.0
+ Shank_Length.val = 33.0
+ Thread_Length.val = 32.0
+
+##############################################################################################
+
+def Test():
+ verts = []
+ faces = []
+
+ if Error_Check() :
+ return
+
+ verts, faces = MakeBolt()
+
+ Add_Mesh_To_Scene("TestBolt", verts,faces)
+
+ Window.Redraw(-1)
+
+
+
+
+def event(evt, val): # the function to handle input events
+
+ if evt == Draw.ESCKEY:
+ Draw.Exit() # exit when user presses ESC
+ return
+
+
+def button_event(evt): # the function to handle Draw Button events
+
+ if evt == On_Exit_Click:
+ Draw.Exit() # exit when user presses ESC
+ return
+
+ if evt == On_Test_Click:
+ Test()
+ Draw.Redraw(1)
+
+ if evt == On_Preset_Click:
+ Load_Preset()
+ Draw.Redraw(1)
+
+ if evt == On_Create_Click:
+ if Model_Type['BOLT'][0].val:
+ Create_Bolt()
+ if Model_Type['NUT'][0].val:
+ Create_Nut()
+ Draw.Redraw(1)
+
+ elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]):
+ for k in Head_Type.iterkeys():
+ if Head_Type[k][1]!=evt:
+ Head_Type[k][0].val=0
+ else:
+ Head_Type[k][0].val=1
+ Draw.Redraw(1)
+
+ elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]):
+ for k in Bit_Type.iterkeys():
+ if Bit_Type[k][1]!=evt:
+ Bit_Type[k][0].val=0
+ else:
+ Bit_Type[k][0].val=1
+ Draw.Redraw(1)
+
+ elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]):
+ for k in Model_Type.iterkeys():
+ if Model_Type[k][1]!=evt:
+ Model_Type[k][0].val=0
+ else:
+ Model_Type[k][0].val=1
+ Draw.Redraw(1)
+
+ elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]):
+ for k in Nut_Type.iterkeys():
+ if Nut_Type[k][1]!=evt:
+ Nut_Type[k][0].val=0
+ else:
+ Nut_Type[k][0].val=1
+ Draw.Redraw(1)
+
+#####################################################################################
+
+
+def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+ INDENT = 3
+
+ BGL.glColor3f(1.0,1.0,1.0)
+ BGL.glBegin(BGL.GL_LINES)
+ BGL.glVertex2i(X1+INDENT,Y1-INDENT) #top line
+ BGL.glVertex2i(X2-INDENT,Y1-INDENT)
+
+ BGL.glVertex2i(X1+INDENT,Y1-INDENT) #left line
+ BGL.glVertex2i(X1+INDENT,Y2+INDENT)
+ BGL.glEnd()
+
+ BGL.glColor3f(0.5,0.5,0.5)
+ BGL.glBegin(BGL.GL_LINES)
+ BGL.glVertex2i(X2-INDENT,Y1-INDENT) #Right line
+ BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+
+ BGL.glVertex2i(X1+INDENT,Y2+INDENT) #bottom line
+ BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+ BGL.glEnd()
+
+
+
+
+def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+
+ BIT_BUTTON_WIDTH = 55
+ BIT_BUTTON_HEIGHT = 18
+ TITLE_HEIGHT = 15
+ INDENT = 6
+ BUTTON_GAP = 4
+
+ BGL.glColor3f(0.75, 0.75, 0.75)
+ BGL.glRecti(X1,Y1,X2,Y2)
+
+ Draw_Border(X1,Y1,X2,Y2);
+
+ BGL.glColor3f(0.0,0.0,0.0)
+ BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT)
+ Draw.Text(Title)
+
+ Button_X = X1 + INDENT
+ Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8
+
+ #Nut_Number_X = Nut_Button_X
+ #Nut_Number_Y = Nut_Button_Y - 25
+ if (Buttons != 0):
+ key= Buttons.keys()
+ for k in key:
+ Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2])
+ Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP
+
+
+
+def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT):
+ CONTROL_WIDTH = 250
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.02",Model_Type)
+
+
+
+def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT):
+ CONTROL_WIDTH = 250
+ BUTTON_Y_OFFSET = 40
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0)
+
+ name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7"
+
+ global Preset_Menu
+ Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.")
+ Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.")
+
+
+def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT):
+
+ CONTROL_WIDTH = 250
+ NUMBER_HEIGHT = 18
+ NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
+
+ Bit_Number_X = 3+3+3
+ Bit_Number_Y = Y_POS - 64
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type)
+
+ if Bit_Type['NONE'][0].val:
+ DoNothing = 1;
+
+ elif Bit_Type['ALLEN'][0].val:
+ global Allen_Bit_Depth
+ Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '')
+ Bit_Number_Y -= NUMBER_HEIGHT
+ global Allen_Bit_Flat_Distance
+ Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '')
+ Bit_Number_Y -= NUMBER_HEIGHT
+
+ elif Bit_Type['PHILLIPS'][0].val:
+ global Phillips_Bit_Depth
+ Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '')
+ Bit_Number_Y -= NUMBER_HEIGHT
+ global Philips_Bit_Dia
+ Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '')
+ Bit_Number_Y -= NUMBER_HEIGHT
+
+
+
+def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT):
+
+ CONTROL_WIDTH = 250
+ NUMBER_HEIGHT = 18
+ NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
+
+ Number_X = 3+3+3
+ Number_Y_Pos = Y_POS - 40
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0)
+
+ global Shank_Length
+ Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Shank_Dia
+ Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+
+
+def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT):
+
+ CONTROL_WIDTH = 250
+ NUMBER_HEIGHT = 18
+ NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
+
+
+ Number_X = 3+3+3
+ Number_Y_Pos = Y_POS - 40
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0)
+
+ global Thread_Length
+ if Model_Type['BOLT'][0].val:
+ Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Major_Dia
+ Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Minor_Dia
+ Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Pitch
+ Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Crest_Percent
+ Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+ global Root_Percent
+ Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '')
+ Number_Y_Pos -= NUMBER_HEIGHT
+
+
+
+
+def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT):
+
+ CONTROL_WIDTH = 250
+ NUMBER_HEIGHT = 18
+ NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
+
+ Head_Number_X = 3+3+3
+ Head_Number_Y = Y_POS - 64
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type)
+
+ if Head_Type['HEX'][0].val:
+ global Hex_Head_Height
+ Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+ global Hex_Head_Flat_Distance
+ Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+
+ elif Head_Type['CAP'][0].val:
+ global Cap_Head_Height
+ Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+ global Cap_Head_Dia
+ Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+
+ elif Head_Type['DOME'][0].val:
+ global Dome_Head_Dia
+ Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+
+ elif Head_Type['PAN'][0].val:
+ global Pan_Head_Dia
+ Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+ Head_Number_Y -= NUMBER_HEIGHT
+
+
+
+
+def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT):
+
+ CONTROL_WIDTH = 250
+ NUMBER_HEIGHT = 18
+ NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3
+
+ Nut_Number_X = 3+3+3
+ Nut_Number_Y = Y_POS - 64
+
+ Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type)
+
+ #if Nut_Type['HEX'][0].val:
+ global Hex_Nut_Height
+ Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '')
+ Nut_Number_Y -= NUMBER_HEIGHT
+ global Hex_Nut_Flat_Distance
+ Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+ Nut_Number_Y -= NUMBER_HEIGHT
+
+
+def Dispaly_Bolt_Tab():
+
+ Dispaly_Shank_Tab(284,66)
+ Dispaly_Head_Tab(374,90)
+ Dispaly_Bit_Tab(464,90)
+
+
+##########################################################################################
+
+def gui(): # the function to draw the screen
+
+ CONTROL_WIDTH = 250
+
+ BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
+ BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+
+ BGL.glColor3f(0.75, 0.75, 0.75)
+ BGL.glRecti(3,30,CONTROL_WIDTH,3)
+
+ Dispaly_Title_Bar(514,50);
+
+ if Model_Type['BOLT'][0].val:
+ Dispaly_Bolt_Tab();
+
+ if Model_Type['NUT'][0].val:
+ Dispaly_Nut_Tab(464,246);
+
+ Dispaly_Thread_Tab(218,138)
+
+ Dispaly_Preset_Tab(80,50)
+
+ Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt")
+ Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18)
+
+# Draw.Button("Test",On_Test_Click,150,10,55,20)
+
+Load_Preset()
+Draw.Register(gui, event, button_event) # registering the 3 callbacks
diff --git a/release/scripts/wizard_curve2tree.py b/release/scripts/wizard_curve2tree.py
index 1965f9a5070..07b45c1986f 100644
--- a/release/scripts/wizard_curve2tree.py
+++ b/release/scripts/wizard_curve2tree.py
@@ -39,7 +39,7 @@ __bpydoc__ = """\
import bpy
import Blender
import BPyMesh
-from Blender.Mathutils import Vector, Matrix, CrossVecs, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
+from Blender.Mathutils import Vector, Matrix, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand
from Blender.Geometry import ClosestPointOnLine
from Blender.Noise import randuvec
@@ -496,12 +496,12 @@ class tree:
# Align this with the existing branch
angle = AngleBetweenVecsSafe(zup, parent_pt.no)
- cross = CrossVecs(zup, parent_pt.no)
+ cross = zup.cross(parent_pt.no)
mat_align = RotationMatrix(angle, 3, 'r', cross)
# Use the bend on the point to work out which way to make the branch point!
- if parent_pt.prev: cross = CrossVecs(parent_pt.no, parent_pt.prev.no - parent_pt.no)
- else: cross = CrossVecs(parent_pt.no, parent_pt.next.no - parent_pt.no)
+ if parent_pt.prev: cross = parent_pt.no.cross(parent_pt.prev.no - parent_pt.no)
+ else: cross = parent_pt.no.cross(parent_pt.next.no - parent_pt.no)
if parent_pt.branch.parent_pt:
angle = AngleBetweenVecsSafe(parent_pt.branch.parent_pt.no, parent_pt.no)
@@ -1065,8 +1065,8 @@ class tree:
l = line_normal.length
- cross1 = CrossVecs( seg.no, line_normal )
- cross2 = CrossVecs( pt.no, line_normal )
+ cross1 = seg.no.cross(line_normal)
+ cross2 = pt.no.cross(line_normal)
angle_line = min(AngleBetweenVecsSafe(cross1, cross2), AngleBetweenVecsSafe(cross1, -cross2))
angle_leaf_no_diff = min(AngleBetweenVecsSafe(line_normal, seg.no), AngleBetweenVecsSafe(line_normal, -seg.no))
@@ -1914,8 +1914,8 @@ class tree:
# endpoints dont rotate
if pt.next != None:
- cross1 = CrossVecs(zup, pt.no) # use this to offset the leaf later
- cross2 = CrossVecs(cross1, pt.no)
+ cross1 = zup.cross(pt.no) # use this to offset the leaf later
+ cross2 = cross1.cross(pt.no)
if odd_even ==0:
mat_yaw = RotationMatrix(leaf_branch_angle, 3, 'r', cross2)
else:
@@ -1939,7 +1939,7 @@ class tree:
# Randomize pitch and roll for the leaf
# work out the axis to pitch and roll
- cross1 = CrossVecs(zup, leaf_no) # use this to offset the leaf later
+ cross1 = zup.cross(leaf_no) # use this to offset the leaf later
if leaf_branch_pitch_rand or leaf_branch_pitch_angle:
angle = -leaf_branch_pitch_angle
@@ -2480,7 +2480,7 @@ class bpoint(object):
def calcVerts(self):
if self.prev == None:
if self.branch.parent_pt:
- cross = CrossVecs(self.no, self.branch.parent_pt.no) * RotationMatrix(-45, 3, 'r', self.no)
+ cross = self.no.cross(self.branch.parent_pt.no) * RotationMatrix(-45, 3, 'r', self.no)
else:
# parentless branch - for best results get a cross thats not the same as the normal, in rare cases this happens.
@@ -2493,9 +2493,9 @@ class bpoint(object):
else: cross = xup
else:
- cross = CrossVecs(self.prev.vecs[0], self.no)
+ cross = self.prev.vecs[0].cross(self.no)
- self.vecs[0] = Blender.Mathutils.CrossVecs(self.no, cross)
+ self.vecs[0] = self.no.cross(cross)
self.vecs[0].length = abs(self.radius)
mat = RotationMatrix(90, 3, 'r', self.no)
self.vecs[1] = self.vecs[0] * mat
@@ -2660,8 +2660,8 @@ class branch:
self_normal = self.bpoints[1].co - self.parent_pt.co
# We only want the angle in relation to the parent points normal
# modify self_normal to make this so
- cross = CrossVecs(self_normal, self.parent_pt.no)
- self_normal = CrossVecs(self.parent_pt.no, cross) # CHECK
+ cross = self_normal.cross(self.parent_pt.no)
+ self_normal = self.parent_pt.no.cross(cross) # CHECK
#try: angle = AngleBetweenVecs(parent_normal, self_normal)
#except: return 0.0
@@ -2670,7 +2670,7 @@ class branch:
# see if we need to rotate positive or negative
# USE DOT PRODUCT!
- cross = CrossVecs(parent_normal, self_normal)
+ cross = parent_normal.cross(self_normal)
if AngleBetweenVecsSafe(cross, self.parent_pt.no) > 90:
angle = -angle
@@ -3018,7 +3018,7 @@ class branch:
scales = []
for cos_ls in (cos1, cos2):
- cross = CrossVecs(cos_ls[-1], zup)
+ cross = cos_ls[-1].cross(zup)
mat = RotationMatrix(AngleBetweenVecsSafe(cos_ls[-1], zup), 3, 'r', cross)
cos_ls[:] = [co*mat for co in cos_ls]
@@ -3029,7 +3029,7 @@ class branch:
for co in cos_ls:
xy_nor.x += co.x
xy_nor.y += co.y
- cross = CrossVecs(xy_nor, xup)
+ cross = xy_nor.cross(xup)
# Also scale them here so they are 1.0 tall always
scale = 1.0/(cos_ls[0]-cos_ls[-1]).length
diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py
new file mode 100644
index 00000000000..405c06432ca
--- /dev/null
+++ b/release/scripts/wizard_landscape_ant.py
@@ -0,0 +1,2148 @@
+#!BPY
+"""
+Name: 'Landscape Generator (A.N.T)'
+Blender: 248
+Group: 'Wizards'
+Tip: 'Create landscape mesh.'
+"""
+
+__author__ = "Jimmy Hazevoet"
+__url__ = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun')
+__version__ = "v.1.05 03-2007"
+__bpydoc__ = """\
+
+Another Noise Tool 'Landscape' v.1.05
+
+This script uses noise functions to create a terrain from a grid mesh.
+
+Usage:
+
+Make new terrain: press the "Add New Grid" button, change some noise settings and press the "Update" button.
+
+Work on previous made grid: select the grid/terrain in the 3D view, and press the "Assign" button.
+
+Tip: use a low resolution grid mesh and add some Multires levels for detail
+
+Note: when using Multires materials can get weird,
+only apply materials when your terrain is ready, or not use Multires.
+
+This Script creates a landscape mesh.
+Press the Auto button when you start the script.
+Then the Generate Button & read it's tooltip.
+The mesh created is average 16000 verts.
+To me the mesh appears quite small in the 3d view.
+Just Press S in the 3d view to scale it up.
+This saves overhead drawing the Mesh.
+
+Known Issues:
+If the mesh is not drawn in the 3d view first time,
+Move your mouse to the 3d view, or press the button again.
+
+Not really an issue, more to be aware.
+Due to the complex nature & design of the script, it only creates one mesh at a time.
+When you press Generate or Reset,
+Even if you have Closed then Opened the script or .blend file,
+The mesh Will be Overwritten.
+To create Multiple Landscapes you Must Re-Name or save the Mesh
+in Blender's F7 menu Links & Materials Panel.
+
+Readme:
+v.1.04:
+_ New G.U.I.
+_ New noise types like:
+Double_Terrain,
+StatsByAlt_Terrain,
+slickRock,
+ditorted_heteroTerrain,
+vlNoise_turbulence,
+and many more.
+
+New fractalized Effect functions.
+Effect types such as: gradient,
+waves and bumps, dome, piramide,
+squares, grid, shattered rocks,
+lunar, and many more.
+
+Bias types: Sin, Cos, Tri, Saw,
+and Default(no bias).
+
+For example the 'Rings' effect
+with 'Sin Bias' makes 'Rings'
+and 'Default Bias' makes 'Dome'.
+The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible,
+-1.0=noise, 0.0=average, 1.0=effect
+this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+
+Image effect: mix image with noise
+_ IPOCurve Filter: use Ipo curve to filter terrain height.
+I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+Usage:
+Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+(use the 'Pin' option to keep the curves visible while other objects are selected)
+Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+A curve filter is very versatile when it comes to 'height' filtering.
+
+_ PreView in UV/Image Editor Window:
+The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+
+_ VertexColours: use any image as colour gradient.
+This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result)
+Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+
+_ Mesh Tiles: Create large scale terrains.
+
+_ Vertices Selection: select flat areas.
+
+_ Keyboard HotKeys:
+SPACE = Update mesh.
+R = Randomise.
+V = Redraw preview.
+
+_ and more...
+
+"""
+
+
+
+
+###
+#
+# Alt+P to start script.
+#
+###
+# scroll down to see info about updates
+##
+################################################################################################################
+# Another Noise Tool 'Landscape'
+# Jimmy Hazevoet
+# license: Do whatever you want with it.
+################################################################################################################
+
+################################################################################################################
+# v.1.04:
+#
+# _ New G.U.I.
+# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more.
+# _ New fractalized Effect functions.
+# Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more.
+# Bias types: Sin, Cos, Tri, Saw, and Default(no bias).
+# For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'.
+# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect
+# this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+# _ Image effect: mix image with noise
+# _ IPOCurve Filter: use Ipo curve to filter terrain height.
+# I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+# the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+# Usage:
+# Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+# move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+# Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+# (use the 'Pin' option to keep the curves visible while other objects are selected)
+# Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+# A curve filter is very versatile when it comes to 'height' filtering.
+# _ PreView in UV/Image Editor Window:
+# The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+# you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+# now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+# ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+# _ VertexColours: use any image as colour gradient.
+# This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+# Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+# you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result)
+# Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+# _ Mesh Tiles: Create large scale terrains.
+# _ Vertices Selection: select flat areas.
+# _ Keyboard HotKeys:
+# SPACE = Update mesh.
+# R = Randomise.
+# V = Redraw preview.
+# _ and more...
+################################################################################################################
+
+################################################################################################################
+# BugFix: Sept./2006 v.1.04a
+#-----------------------------
+# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image).
+#
+################################################################################################################
+
+
+################################################################################################################
+# UPDATE: v.1.05 03-2007
+#---------------------------------------------------------------------------------------------------------------
+#
+# _ New: Save and Load function, save your settings to a .ant file.
+# __NOTE: when saving/loading settings to/from a file,
+# make sure the filename/path is not too long!
+# __HOTKEY__ Load from file: L
+# __HOTKEY__ Save to file : S
+#
+# _ New mesh code, uses Mesh instead of NMesh,
+# this gives a small speed improvement and alows you to use Multires.
+#
+# Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another.
+#
+# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section.
+# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff
+#
+# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel),
+# create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size.
+#
+# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished.
+#
+###############################################################################################################
+
+
+###############################################################################################################
+#
+## Execute Script: Alt P
+#
+
+
+import Blender
+from Blender import *
+from math import *
+from Blender.Noise import *
+from Blender.Draw import *
+from Blender.BGL import *
+from Blender import Image
+import string
+from string import strip
+import BPyMathutils
+from BPyMathutils import genrand
+from random import choice
+scene = Scene.GetCurrent()
+
+###---------------------------------------------------------------------------
+
+CurVersion = 'A.N.T.Landscape v.1.05'
+
+##---------------------------------------------------------------------------
+# Customise default settings: ----------------------------------------------
+
+# Names:
+antfilename = 'Terrain' # Default filename
+previewname = Create('') # Default preview Image name
+DefaultIpoName = '' # Default Ipo DataBlock name (for height filter)
+# G.U.I.:
+FullScreen = Create( 0 ) # FullScreen on/off
+# gui colors:
+ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ]
+#ledcolor = [ 1.0, 0.5, 0.0 ]
+lightgrey = [ 0.76, 0.76, 0.76 ] # gui col.
+grey = [ 0.6, 0.6, 0.6 ] # panel col.
+background = [ 0.7, 0.7, 0.7, 1.0 ] # background col.
+black = [ 0.0, 0.0, 0.0 ] # text col.
+white = [ 1.0, 1.0, 1.0 ]
+# gui size
+size_x = 320 # gui x size
+size_y = 280 # gui y size
+# tabs
+guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ] # gui Tabs
+# How long does it take to generate a mesh or image ?
+print_time = 0 # 1 = Print time in console.
+
+# end customise. ----------------------------------------------------------
+##--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+####--------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+
+dirpath=Blender.sys.dirname(Blender.Get('filename'))
+fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant'
+txtFile = Create( fname )
+
+###---------------------------------------------------------------------------
+columns = 10 # gui columns
+rows = 13 # gui rows
+actob = [] # active object
+actme = [] # active mesh
+ipoblockname=''
+thiscurve=[]
+selectedcurve=0
+phi=3.14159265359
+# events
+App_Evt = 144
+New_Evt = 166
+SelFile_Evt = 71
+LoadFile_Evt = 72
+SaveFile_Evt = 73
+UseMe_Evt = 74
+No_Evt = 1
+Btn_Evt = 2
+Msh_Evt = 12
+Upd_Evt = 3
+Rndm_Evt = 4
+Load_Evt = 5
+Sel_Evt = 6
+Save_Evt = 7
+Rend_Evt = 8
+End_Evt = 9
+Scrn_Evt = 15
+Im_Evt = 16
+gt0_Evt = 20
+gt1_Evt = 21
+gt2_Evt = 22
+gt3_Evt = 23
+gt4_Evt = 24
+Ipo_Evt = 17
+New_Ipo_Evt=700
+
+###---------------------------------------------------------------------------
+# menus
+noisetypemenu = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21"
+noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9"
+voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6"
+tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3"
+effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ]
+mixtypemenu = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11']
+biastypemenu = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4"
+sharptypemenu = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2"
+filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3"
+filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12"
+falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9"
+randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2"
+
+##--------------------------------------------------
+def Set_ReSet_Values():
+ global fileinfo, filemessage
+ global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo
+ global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo
+ global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+ global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName
+
+ filemessage = ''
+ fileinfo = ''
+ effect_image = 'Load and Select image.'
+ AutoUpd = Create( 0 )
+ PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ]
+ ## Coords controls:
+ WorldSpaceCo = Create(0)
+ iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ]
+ Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ]
+ Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ]
+ NSize = [ Create( 1.0 ), Create( 2.0 ) ]
+ Sx = [ Create( 1.0 ), Create( 1.0 ) ]
+ Sy = [ Create( 1.0 ), Create( 1.0 ) ]
+ Lx = [ Create( 0.0 ), Create( 0.0 ) ]
+ Ly = [ Create( 0.0 ), Create( 0.0 ) ]
+ ## Noise controls:
+ NType = Create( 3 )
+ Basis = [ Create( 0 ), Create( 0 ) ]
+ musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ]
+ vlnoi = [ Create( 1.0 ), Create( 0 ) ]
+ vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ]
+ voron = [ Create( 0 ), Create( 2.5 ) ]
+ turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+ marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+ tBasismod = Create(0)
+ ## Effect controls:
+ musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ]
+ turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+ marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+ Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ]
+ CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ]
+ ## Filter controls:
+ Min = Create( 0.0 )
+ Max = Create( 1.0 )
+ Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ]
+ Filter_Mode = Create( 0 )
+ Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ]
+ Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ]
+ Filter_Order = Create( 0 )
+ CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ]
+ ## Randomise noise buttons:
+ RandMod = Create( 1 )
+ RSeed = Create( 0 )
+ rand_I = Create( 0 )
+ rand_H = Create( 0 )
+ rand_S = Create( 0 )
+ rand_L = Create( 1 )
+
+##-------------------------
+Set_ReSet_Values()
+
+
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## G.U.I.: text,backpanel,panel
+#--------------------------------------------------
+def draw_Text( ( x, y ), text, color, size ):
+ glColor3f( color[0],color[1],color[2] )
+ glRasterPos2d(x,y)
+ txtsize = 'small', 'normal', 'large'
+ Text( text, txtsize[ size ] )
+def draw_BackPanel( text, x, y, w, h, colors ):
+ glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 )
+ glRecti( x, h, w, h+20 )
+ glColor3f( colors[0], colors[1], colors[2] )
+ glRecti( x, y, w, h )
+ glColor3f( colors[0], colors[1], colors[2] )
+ glRasterPos2d( x+10, h+5 )
+ Text( text, 'small' )
+def draw_Panel( x, y, w, h, colors ):
+ glColor3f( colors[0], colors[1], colors[2] )
+ glRecti( x,y, w,h )
+def draw_Frame( text, x, y, w, h, color ):
+ glColor3f( color[0], color[1], color[2] )
+ glRasterPos2i(x+3,h-3)
+ Text(text ,'small')
+ stringwidth = GetStringWidth( text,'small' )
+ glColor3f( color[0], color[1], color[2] )
+ glBegin(Blender.BGL.GL_LINE_STRIP)
+ glVertex2i(x,h)
+ glVertex2i(x,y)
+ glVertex2i(w,y)
+ glVertex2i(w,h)
+ glVertex2i(x+stringwidth+10,h)
+ glEnd()
+def draw_Led( x, y, colors ):
+ glColor3f( colors[0], colors[1], colors[2] )
+ glRecti( x,y, x+4,y+4 )
+
+
+###----------------------------------------------------------------------------------------------------
+## G.U.I. Buttons:
+#----------------------------------------------------------------------------------------------------
+
+###-------------------------
+## Main / Mesh Buttons:
+#
+def MeshButtons( col, row, width, height ):
+ global actme, actob, AutoUpd, txtFile, filemessage, fileinfo
+
+ PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." )
+ draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 )
+ txtFile = String("", No_Evt, col[0], row[2], width[9], height[1], txtFile.val, 256, "File: Full path and filename" )
+ PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" )
+ PushButton( "Load", LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" )
+ PushButton( "Save", SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" )
+
+ activeobname = ''
+ if actme !=[]:
+ activeobname = actob[0].name
+ draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 )
+ PushButton( "Add New Grid", New_Evt, col[0], row[6], width[4], height[2] )
+ PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain')
+
+###-------------------------
+## Noise Buttons:
+#
+def NoiseButtons( col, row, width, height ):
+ global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo
+ global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod
+ global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne
+ global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I
+
+ bth = height[1]/2+5
+ iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val, -10.0, 10.0 , "Noise: Intensity Scale." )
+ Invert[0] = Toggle("Inv.", Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert")
+ Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val, -10.0, 10.0 , "Noise: Offset " )
+ NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" )
+ Sx[0] = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val, 0.001, 10.0 , "Size X" )
+ Sy[0] = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val, 0.001, 10.0 , "Size Y" )
+ Lx[0] = Number("Loc X:", Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val, -10000.0, 10000.0 , "Loc X" )
+ Ly[0] = Number("Loc Y:", Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val, -10000.0, 10000.0 , "Loc Y" )
+ WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " )
+
+ NType = Menu( noisetypemenu, Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" )
+ if NType.val == 6:
+ voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" )
+ else:
+ if NType.val != 9:
+ Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" )
+
+ if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]:
+ musgr[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val, 0.0, 3.0, 0 , "H" )
+ musgr[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val, 0.0, 6.0, 0 , "Lacunarity" )
+ musgr[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val, 0, 12, 0 , "Octaves" )
+ if NType.val in [1,2,3,13,14,15,18,19,20,21]:
+ musgr[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val, 0.0, 6.0, 0 , "Offset" )
+ if NType.val in [1,2,13,15,18]:
+ musgr[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val, 0.0, 6.0, 0 , "Gain" )
+ if NType.val == 19:
+ musgr[5] = Slider( "Thresh: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val, 0.001, 2.0, 0 , "Threshold" )
+ if NType.val in [5,6,7,16]:
+ turbOne[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves")
+ turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val, "Soft noise / Hard noise")
+ turbOne[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ")
+ turbOne[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale")
+ if NType.val in [18,19]:
+ tBasismod = Menu( tBasismodemenu, Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.")
+ if NType.val == 6:
+ if voron[0].val == 6:
+ voron[1] = Slider( "Exp: ", Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent")
+ if NType.val in [7,11,12,14,20,21]:
+ vlnoi[0] = Slider( "Dist: ", Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val, 0.0, 10.0, 0 , "Distort" )
+ if NType.val in [7,13,14,15,21]:
+ vlnoi[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise")
+ if NType.val == 10:
+ marbleOne[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves")
+ marbleOne[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val, 0.0,20.0, 0, "Turbulence ")
+ marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias")
+ marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val, 0.0,20.0, 0, "ReScale")
+ if marbleOne[3].val != 4:
+ marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen")
+
+ RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" )
+ rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )")
+ rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height")
+ rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size")
+ rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location")
+
+###-------------------------
+## Effect Buttons:
+#
+def EffectButtons( col, row, width, height ):
+ global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX
+ global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+ global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo
+
+ Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" )
+ if Effect_Ctrl[0].val != 0:
+ Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ), Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" )
+ if Effect_Ctrl[1].val in [10,11]:
+ Effect_Ctrl[2] = Slider("Warp: ", Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+ else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+
+ iScale[1] = Number("iScale:", Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val, -20.0, 20.0 , "Effect: Intensity Scale " )
+ Invert[1] = Toggle("Inv.", Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert")
+ Offset[1] = Number("Offset:", Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val, -20.0, 20.0 , "Effect: Offset " )
+ NSize[1] = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" )
+ Sx[1] = Number("Freq X:", Btn_Evt, col[5], row[7], width[4], height[1], Sx[1].val, -50.0, 50.0 , "Effect Frequency X ( ScaleX )" )
+ Sy[1] = Number("Freq Y:", Btn_Evt, col[5], row[8], width[4], height[1], Sy[1].val, -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" )
+ Lx[1] = Number("Loc X:", Btn_Evt, col[5], row[9], width[4], height[1], Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" )
+ Ly[1] = Number("Loc Y:", Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" )
+
+ if Effect_Ctrl[0].val == 1:
+ PushButton("Load Image", Load_Evt, col[0], row[4], width[4], height[2] , "Load Image")
+ PushButton("Select Image", Sel_Evt, col[0], row[6], width[4], height[3] , "Select Image")
+ draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 )
+
+ if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]:
+ Basis[1] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" )
+
+ if Effect_Ctrl[0].val == 2:
+ turbTwo[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves")
+ turbTwo[1] = Toggle("Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val, "Hard noise")
+ turbTwo[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ")
+ turbTwo[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale")
+ if Effect_Ctrl[0].val == 3:
+ vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise")
+ vlnoiTwo[0] = Slider( "Dist: ", Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val, 0.0, 10.0, 0 , "Distort" )
+ if Effect_Ctrl[0].val == 4:
+ marbleTwo[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves")
+ marbleTwo[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val, 0.0,20.0, 0, "Turbulence")
+ marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias")
+ marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val, 0.0,20.0, 0, "ReScale")
+ if marbleTwo[3].val != 4:
+ marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen")
+
+ if Effect_Ctrl[0].val in [5,6,7,8,9]:
+ musgrTwo[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val, 0.0, 3.0, 0 , "H" )
+ musgrTwo[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val, 0.0, 6.0, 0 , "Lacunarity" )
+ musgrTwo[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val, 0, 12, 0 , "Octaves" )
+ if Effect_Ctrl[0].val in [6,7,8]:
+ musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val, 0.0, 6.0, 0 , "Offset" )
+ if Effect_Ctrl[0].val in [6,7]:
+ musgrTwo[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val, 0.0, 6.0, 0 , "Gain" )
+
+ if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+ Effect_Ctrl[5] = Number("Depth:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val, 0, 12 , "Fractalize Effect: Octaves" )
+ Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 , "Distort Effect: Amount" )
+ Effect_Ctrl[6] = Slider("Freq:", Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" )
+ Effect_Ctrl[7] = Slider("Amp:", Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" )
+ if Effect_Ctrl[0].val < 22:
+ Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias")
+ if Effect_Ctrl[0].val in [31,32]:
+ Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" )
+ if Effect_Ctrl[0].val == 33:
+ draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+ CustomFX[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" )
+ CustomFX[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" )
+ CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" )
+
+###-------------------------
+## Filter / Height Buttons:
+#
+def FilterButtons( col, row, width, height ):
+ global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt
+ global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order
+
+ iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val, -10.0, 10.0 , "Terrain Height: Scale" )
+ Invert[2] = Toggle("Inv.", Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height: Invert")
+ Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val, -10.0, 10.0 , "Terrain Height: Offset" )
+ Max = Number( "Plateau:", Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height: Clamp Max. ( Plateau )" )
+ Min = Number( "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height: Clamp Min. ( Sealevel )" )
+ Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height: Edge falloff")
+ if Falloff[0].val !=0:
+ Falloff[1] = Number("X:", Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff: X Size" )
+ Falloff[2] = Number("Y:", Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff: Y Size" )
+ Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff: Invert")
+ Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff: Edge at Sealevel")
+
+ Filter_Mode = Menu( filtermodemenu, No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter: Mode")
+ if Filter_Mode.val ==1:
+ Def_Filter_Ctrl[0] = Menu( filtertypemenu, Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter: Type")
+ Def_Filter_Ctrl[1] = Number("Amount: ", Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter: Amount" )
+
+ if Filter_Mode.val ==2:
+ Ipo_Filter_Ctrl[0] = String("IP:", Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" )
+ if Ipo_Filter_Ctrl[0].val !='':
+ Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" )
+ Ipo_Filter_Ctrl[2] = Number("Curve Length:", Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." )
+ Ipo_Filter_Ctrl[3] = Number("Curve Height:", Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." )
+ else:
+ draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 )
+ draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 )
+ PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter")
+
+ if Filter_Mode.val ==3:
+ draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+ CustomFilt[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" )
+ CustomFilt[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" )
+ CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" )
+ if Filter_Mode.val !=0:
+ Filter_Order = Toggle("Change Filter Order", Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.")
+
+###-------------------------
+## Option / Generate Image Buttons:
+#
+def OptionButtons( col, row, width, height ):
+ global PreView, previewname
+
+ PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)")
+ if PreView[0].val !=0:
+ previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" )
+ PreView[1] = Number("", Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale")
+ PreView[2] = Number("", Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset")
+ PushButton( "Draw Image", Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )")
+ draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 )
+ draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 )
+ draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 )
+ draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 )
+
+####--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+## Draw G.U.I. -------------------------------------------------------------
+#--------------------------------------------------------------------------
+def drawgui():
+ global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage
+ global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I
+
+ glClearColor(background[0],background[1],background[2],background[3])
+ glClear(GL_COLOR_BUFFER_BIT)
+ scissorbox=Buffer(GL_FLOAT,4)
+ glGetFloatv(GL_SCISSOR_BOX,scissorbox)
+ scissbleft=int(scissorbox[0])
+ scissbbase=int(scissorbox[1])
+ scissbwidth=int(scissorbox[2])
+ scissbheight=int(scissorbox[3])
+ xstart = 5
+ ystart = 5
+ xgap = 5
+ ygap = 5
+ if FullScreen.val==1:
+ guiwidth = scissbwidth-10
+ guiheight = scissbheight-25
+ if guiwidth < size_x/2:
+ guiwidth = size_x/2
+ if guiheight < size_y/2:
+ guiheight = size_y/2
+ else:
+ guiwidth = size_x
+ guiheight = size_y
+ col,row = [],[]
+ xpart = ( ( guiwidth-xstart ) / columns )
+ ypart = ( ( guiheight-ystart ) / rows )
+ width = []
+ for c in xrange( columns ):
+ col.append( xgap + xpart * c + xstart )
+ width.append( xpart*(c+1)-xgap )
+ height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2 ]
+ for r in xrange( rows ):
+ row.append( ygap + ypart * r + ystart )
+ row.reverse()
+
+ ###-------------------------
+ ## Draw G.U.I.:
+ draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey )
+
+ FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" )
+ PushButton( "X", End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" )
+ draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 )
+
+ # gui tabs
+ guitabs[0] = Toggle("Main", gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" )
+ guitabs[1] = Toggle("Noise", gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" )
+ guitabs[2] = Toggle("Effect", gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" )
+ guitabs[3] = Toggle("Height", gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" )
+ guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" )
+
+ if guitabs[0].val !=0: MeshButtons( col, row, width, height )
+ elif guitabs[1].val !=0: NoiseButtons( col, row, width, height )
+ elif guitabs[2].val !=0: EffectButtons( col, row, width, height )
+ elif guitabs[3].val !=0: FilterButtons( col, row, width, height )
+ elif guitabs[4].val !=0: OptionButtons( col, row, width, height )
+ else: # some info
+ draw_Panel( col[0], row[0]-5, col[9]+width[0], row[10]-10, black )
+ draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05', ledcolors[0], 2 )
+ draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007', ledcolors[1], 2 )
+ draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 )
+ draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------', ledcolors[3], 2 )
+ draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh', ledcolors[4], 2 )
+ draw_Text( ( col[0]+5, row[6] ), 'V = Update Image', ledcolors[5], 2 )
+ draw_Text( ( col[0]+5, row[7] ), 'R = Randomise', ledcolors[6], 2 )
+ draw_Text( ( col[0]+5, row[8] ), 'L = Load from file', ledcolors[7], 2 )
+ draw_Text( ( col[0]+5, row[9] ), 'S = Save to file', ledcolors[8], 2 )
+ draw_Text( ( col[0]+5, row[10] ),'Q = Quit', ledcolors[9], 2 )
+
+ # auto/generate/randomise buttons
+ rand_on_off = 0
+ if rand_H.val !=0: rand_on_off = 1
+ elif rand_I.val !=0: rand_on_off = 1
+ elif rand_S.val !=0: rand_on_off = 1
+ elif rand_L.val !=0: rand_on_off = 1
+ else: rand_on_off = 0
+ if rand_on_off != 0:
+ if RandMod.val in [1,2]:
+ PushButton( "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )")
+ else: RSeed = Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val, 0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." )
+ AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+ PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )")
+ else:
+ AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+ PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )")
+ ####---------------------------------------------------------------------------
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Key Events:
+
+def events(evt, val):
+ global PreView, txtFile, AutoUpd, PreView
+
+ ## hotkey: Q = Quit
+ if (evt == QKEY and not val):
+ name = "Quit ?%t|No %x0|Yes %x1"
+ result = Blender.Draw.PupMenu(name)
+ if result==1:
+ Exit()
+
+ ## hotkey: Space = Generate/Update terrain
+ if (evt == SPACEKEY and not val):
+ do_it()
+
+ ## hotkey: R = Randomise noise
+ if (evt in [ RKEY ] and not val):
+ if AutoUpd.val != 0:
+ do_it_random()
+ else:
+ randomiseNoise()
+ Draw()
+
+ ## hotkey: V = Update image
+ if PreView[0].val != 0:
+ if (evt in [ VKEY, RKEY ] and not val):
+ do_it_preview()
+
+ ## hotkey: L = Load from file
+ if (evt == LKEY and not val):
+ loadmenu = "Load file ?%t|" + txtFile.val
+ loadresult = Blender.Draw.PupMenu(loadmenu)
+ if loadresult==1:
+ LoadPreset(txtFile.val)
+ if AutoUpd.val != 0:
+ do_it()
+ else: Draw()
+
+ ## hotkey: S = Save to file
+ if (evt == SKEY and not val):
+ savemenu = "Save file ?%t|" + txtFile.val
+ saveresult = Blender.Draw.PupMenu(savemenu)
+ if saveresult==1:
+ SavePreset(txtFile.val)
+ Draw()
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Button events:
+
+def bevents(evt):
+ global txtFile, effect_image, PreView, fileinfo, filemessage
+ global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve
+ global antfilename, terrainname
+ global actob, actme
+
+ # quit/reset event
+ if (evt == End_Evt ):
+ name = "OK ?%t|Reset %x1|Quit %x2"
+ result = Blender.Draw.PupMenu(name)
+ if result==1:
+ Set_ReSet_Values()
+ Draw()
+ elif result==2:
+ Exit()
+
+ ## file info string event
+ if (evt == UseMe_Evt ):
+ result = Blender.Draw.PupStrInput("Info: ", fileinfo, 96)
+ if result:
+ fileinfo = result
+ Draw()
+ else: return
+
+ ## none event
+ if (evt in [No_Evt, Scrn_Evt] ):
+ Draw()
+
+ ## image event
+ if (evt == Im_Evt ):
+ do_it_preview()
+
+ ## generate/update event
+ if (evt == Upd_Evt ):
+ if PreView[0].val != 0:
+ do_it_preview()
+ do_it()
+
+ ## mesh button event
+ if (evt == Msh_Evt):
+ if AutoUpd.val != 0:
+ do_it()
+ else: Draw()
+
+ ## button event
+ if (evt == Btn_Evt ):
+ if AutoUpd.val != 0:
+ if PreView[0].val != 0:
+ do_it_preview()
+ do_it()
+ else: Draw()
+
+ ## randomise event
+ if (evt == Rndm_Evt ):
+ if AutoUpd.val != 0:
+ do_it_random()
+ else:
+ randomiseNoise()
+ if PreView[0].val != 0:
+ do_it_preview()
+ Draw()
+
+ ###---------------------------------------------------------
+ ## Effect Image Load/Select:
+ if (evt == Load_Evt ):
+ Blender.Window.FileSelector ( load_image, 'LOAD IMAGE')
+ if (evt == Sel_Evt ):
+ try: effect_image = Image_Menu()
+ except: pass
+ if AutoUpd.val != 0:
+ do_it()
+ else: Draw()
+
+ ###---------------------------------------------------------
+ ## Make New IPOCurve to use as Filter:
+ if (evt == New_Ipo_Evt ):
+ objname = Create("ANT_Ipo_Empty")
+ iponame = Create("ANT_IPO")
+ block = []
+ block.append("Enter new names")
+ block.append("and hit OK button")
+ block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')"))
+ block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name"))
+ block.append("Open IpoCurveEditor")
+ block.append("select Ipo DataBlock" )
+ block.append("'Pin' the view" )
+ block.append("and edit the curves." )
+ retval = PupBlock("Make A.N.T. IpoCurve Object", block)
+ if retval !=0:
+ ANTAutoIpo( objname.val, iponame.val )
+ Ipo_Filter_Ctrl[0].val = iponame.val
+
+ ###---------------------------------------------------------
+ ## get IPOCurve to use as Filter:
+ if (evt in [Ipo_Evt, New_Ipo_Evt] ):
+ if Filter_Mode.val == 2:
+ if AutoUpd.val != 0:
+ try:
+ ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+ thiscurve = ipoblockname.getCurves()
+ selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+ if PreView[0].val != 0:
+ do_it_preview()
+ #if AutoUpd.val != 0:
+ do_it()
+ except: pass
+ else:
+ try:
+ ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+ thiscurve = ipoblockname.getCurves()
+ selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+ if PreView[0].val != 0:
+ do_it_preview()
+ else:
+ Draw()
+ except: pass
+
+ ###---------------------------------------------------------
+ ## gui tabs
+ if (evt == gt0_Evt ):
+ if guitabs[0].val == 1:
+ guitabs[1].val = ( 0 )
+ guitabs[2].val = ( 0 )
+ guitabs[3].val = ( 0 )
+ guitabs[4].val = ( 0 )
+ Draw()
+ if (evt == gt1_Evt ):
+ if guitabs[1].val == 1:
+ guitabs[0].val = ( 0 )
+ guitabs[2].val = ( 0 )
+ guitabs[3].val = ( 0 )
+ guitabs[4].val = ( 0 )
+ Draw()
+ if (evt == gt2_Evt ):
+ if guitabs[2].val == 1:
+ guitabs[0].val = ( 0 )
+ guitabs[1].val = ( 0 )
+ guitabs[3].val = ( 0 )
+ guitabs[4].val = ( 0 )
+ Draw()
+ if (evt == gt3_Evt ):
+ if guitabs[3].val == 1:
+ guitabs[0].val = ( 0 )
+ guitabs[1].val = ( 0 )
+ guitabs[2].val = ( 0 )
+ guitabs[4].val = ( 0 )
+ Draw()
+ if (evt == gt4_Evt ):
+ if guitabs[4].val == 1:
+ guitabs[0].val = ( 0 )
+ guitabs[1].val = ( 0 )
+ guitabs[2].val = ( 0 )
+ guitabs[3].val = ( 0 )
+ Draw()
+
+ ###---------------------------------------------------------
+ ## load and save all settings:
+ if (evt == SelFile_Evt ):
+ Blender.Window.FileSelector ( callback, "Select .ant File")
+ if (evt == LoadFile_Evt ):
+ loadmenu = "Load file ?%t|" + txtFile.val
+ loadresult = Blender.Draw.PupMenu(loadmenu)
+ if loadresult==1:
+ LoadPreset(txtFile.val)
+ Draw()
+ if AutoUpd.val != 0:
+ do_it()
+ if (evt == SaveFile_Evt ):
+ savemenu = "Save file ?%t|" + txtFile.val
+ saveresult = Blender.Draw.PupMenu(savemenu)
+ if saveresult==1:
+ SavePreset(txtFile.val)
+ Draw()
+
+ ###---------------------------------------------------------
+ # New Grid
+ ###-------------------------
+ if (evt == New_Evt):
+ scn = Blender.Scene.GetCurrent()
+ gridname = Create("Terrain")
+ gridres = Create(256)
+ curspos = Create(0)
+ block = []
+ block.append(("OB: ", gridname, 0, 30, "New Object Name."))
+ block.append(("Resol: ", gridres, 4, 1024, "New grid resolution"))
+ block.append(("At Cursor", curspos, "New grid at cursor position"))
+ retval = PupBlock("New Grid Mesh", block)
+ if retval !=0:
+ MakeGridMesh( gridres.val, gridname.val, curspos.val, scn )
+ obj = scn.objects.active
+ if obj.type == 'Mesh':
+ actob=[]
+ actme=[]
+ actob.append( obj )
+ actme.append( actob[0].getData(mesh=1) )
+ Blender.Redraw()
+
+ ###---------------------------------------------------------
+ # Assign Grid
+ ###-------------------------
+ if (evt == App_Evt):
+ scn = Blender.Scene.GetCurrent()
+ obj = scn.objects.active
+ if obj:
+ if obj.type == 'Mesh':
+ actob=[]
+ actme=[]
+ actob.append( obj )
+ actme.append( actob[0].getData(mesh=1) )
+ Draw()
+
+ ###-------------------------
+ if (evt not in [LoadFile_Evt,SaveFile_Evt] ):
+ filemessage = ''
+ #Draw()
+
+ ### end events. -------------------------
+
+####-------------------------------------------------------------------------------------
+###-------------------------------------------------------------------------------------
+##-------------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------------
+
+##----------------------------------
+# A.N.T. Auto Ipo generator:
+def ANTAutoIpo( objname, iponame ):
+ scn=Scene.GetCurrent()
+ # Deselect all objects:
+ scn.objects.selected=[]
+ # Create new 'ANT_IPO_OBJECT':
+ obj = scn.objects.new('Empty', objname )
+ obj.setDrawMode(8)
+ obj.select(1)
+ obj.layers = Window.ViewLayers()
+ # Set current frame at 1:
+ frame = Get('curframe')
+ if frame !=1:
+ Set('curframe',1)
+ frame = Get('curframe')
+ # Insert IpoKeys:
+ obj.setLocation(0.0, 0.0, 0.0)
+ obj.insertIpoKey(0)
+ Set('curframe',101)
+ obj.setLocation(100.0, 100.0, 100.0)
+ obj.insertIpoKey(0)
+ Set('curframe',1)
+ # Set Ipo name:
+ ip = obj.getIpo()
+ ip.name = iponame
+ #-------------------------
+ print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!"
+ #-------------------------
+
+##-------------------------------------------------------------------------------------
+
+##-------------------------
+# Generate random numbers:
+def randnum(low,high):
+ global RandMod, RSeed
+ if RandMod.val == 0:
+ # Noise.random setRandomSeed
+ s = Noise.setRandomSeed( RSeed.val )
+ num = Noise.random()
+ num = num*(high-low)
+ num = num+low
+ elif RandMod.val == 1:
+ # Mathutils.Rand
+ num = Mathutils.Rand(low,high)
+ else:
+ # BPyMathutils Mersenne Twister genrand
+ num = genrand()
+ num = num*(high-low)
+ num = num+low
+ return num
+
+##-------------------------
+# Randomise noise: height, size and location:
+def randomiseNoise():
+ global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+
+ if rand_I.val !=0:
+ iScale[0] = Create( randnum( 0.2 , 3.0 ) )
+ Offset[0] = Create( randnum(-1.0 , 1.0 ) )
+ if rand_H.val !=0:
+ iScale[2] = Create( randnum( 0.10 , 1.0 ) )
+ Offset[2] = Create( randnum(-0.25 , 0.25 ) )
+ if rand_S.val !=0:
+ NSize[0] = Create( randnum( 0.25 , 2.5 ) )
+ #Sx[0] = Create( randnum( 0.5 , 1.5 ) )
+ #Sy[0] = Create( randnum( 0.5 , 1.5 ) )
+ if rand_L.val !=0:
+ Lx[0] = Create( randnum( -10000 , 10000 ) )
+ Ly[0] = Create( randnum( -10000 , 10000 ) )
+
+##-------------------------------------------------------------------------------------
+
+###--------------------------
+# Load Image:
+def load_image( ImageFileName ):
+ Image.Load( ImageFileName )
+
+###--------------------------
+# Select Image Menu:
+def Image_Menu():
+ try:
+ names=[]
+ imagelist = Image.Get()
+ imagelist.reverse()
+ for numbers, obnames in enumerate( imagelist ):
+ n = obnames.getName()
+ names.append( n )
+ imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key) for key in xrange(numbers+1) ], '' )
+ image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText )
+ if image_menu == -1:
+ return ''
+ return imagelist[ image_menu ].getName()
+ except:
+ return 'No image found!'
+
+###--------------------------
+# Get Image Pixels:
+def Image_Func( x,y ):
+ try:
+ pic = Image.Get( effect_image )
+ except:
+ return 0.0
+ w, h = pic.getSize()
+ x, y = x,-y
+ x = int(w * ((x + 1.0) % 2.0) / 2.0)
+ y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0)
+ c = pic.getPixelF( x,y )
+ return ( c[0] + c[1] + c[2] ) / 3.0
+
+##-------------------------------------------------------------------------------------
+
+# Transpose noise coords:
+def Trans((x,y,z), size, loc ):
+ x = ( x / size[1] / size[0] + loc[0] )
+ y = ( y / size[2] / size[0] + loc[1] )
+ z = 0.0 #( z / size[3] / size[0] + loc[2] )
+ return x,y,z
+
+# Transpose effect coords:
+def Trans_Effect((x,y,z), size, loc ):
+ x = ( x * size[1] * size[0] + loc[0] )
+ y = ( y * size[2] * size[0] + loc[1] )
+ z = 0.0
+ return x,y,z
+
+# Height scale:
+def HeightScale( input, iscale, offset, invert ):
+ if invert !=0:
+ return (1.0-input) * iscale + offset
+ else:
+ return input * iscale + offset
+
+# dist.
+def Dist(x,y):
+ return sqrt( (x*x)+(y*y) )
+
+##-----------------------------------
+# bias types:
+def no_bias(a):
+ return a
+def sin_bias(a):
+ return 0.5 + 0.5 * sin(a)
+def cos_bias(a):
+ return 0.5 + 0.5 * cos(a)
+def tri_bias(a):
+ b = 2 * phi
+ a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b)))
+ return a
+def saw_bias(a):
+ b = 2 * phi
+ n = int(a/b)
+ a -= n * b
+ if a < 0: a += b
+ return a / b
+# sharpen types:
+def soft(a):
+ return a
+def sharp(a):
+ return a**0.5
+def sharper(a):
+ return sharp(sharp(a))
+Bias_Types = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ]
+Sharp_Types = [ soft, sharp, sharper ]
+
+##-----------------------------------
+# clamp height
+def clamp( height, min, max ):
+ if ( height < min ): height = min
+ if ( height > max ): height = max
+ return height
+
+##-----------------------------------
+# Mix modes
+def maximum( a, b ):
+ if ( a > b ): b = a
+ return b
+def minimum( a, b ):
+ if ( a < b ): b = a
+ return b
+
+def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ):
+ a = a * ( 1.0 - mixfactor )
+ b = b * ( 1.0 + mixfactor )
+ if mode == 0: return ( b ) #0 effect only
+ elif mode == 1: return ( a*(1.0-0.5) + (b*0.5) ) #1 mix
+ elif mode == 2: return ( a + b ) #2 add
+ elif mode == 3: return ( a - b ) #3 sub.
+ elif mode == 4: return ( a * b ) #4 mult.
+ elif mode == 5: return (abs( a - b )) #5 abs diff.
+ elif mode == 6: return 1.0-((1.0-a)*(1.0-b)/1.0) #6 screen
+ elif mode == 7: return ( a + b ) % 1.0 #7 addmodulo
+ elif mode == 8: return min( a, b ) #8 min.
+ elif mode == 9: return max( a, b ) #9 max.
+ elif mode == 10: #10 warp: effect
+ noise = mixfactor * Noise_Function(x,y,z)
+ return Effects( (i,j),(x+noise,y+noise,z) )
+ elif mode == 11: #11 warp: noise
+ effect = mixfactor * Effects( (i,j),(x,y,z) )
+ return Noise_Function( x+effect, y+effect, z )
+ else: return a
+
+###----------------------------------------------------------------------
+# Effect functions:
+
+# Effect_Basis_Function:
+def Effect_Basis_Function((x,y), type, bias ):
+
+ iscale = 1.0
+ offset = 0.0
+ ## gradient:
+ if type == 0:
+ effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) )
+ ## waves / bumps:
+ if type == 1:
+ effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) )
+ ## zigzag:
+ if type == 2:
+ effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) )
+ ## wavy:
+ if type == 3:
+ effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) )
+ ## sine bump:
+ if type == 4:
+ effect = offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) ))
+ ## dots:
+ if type == 5:
+ effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5
+ ## rings / dome:
+ if type == 6:
+ effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) )
+ ## spiral:
+ if type == 7:
+ effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5
+ ## square / piramide:
+ if type == 8:
+ effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1)
+ ## blocks:
+ if type == 9:
+ effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+ if effect > 0.0: effect = 1.0
+ effect = offset + iscale * effect
+ ## grid:
+ if type == 10:
+ effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+ if effect > 0.0: effect = 1.0
+ effect = offset + iscale * effect
+ ## tech:
+ if type == 11:
+ a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) ))
+ b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) ))
+ effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0
+ if effect > 0.5: effect = 1.0
+ effect = offset + iscale * effect
+
+ ## crackle:
+ if type == 12:
+ t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25
+ effect = vlNoise(( x, y, t ), 0.25, 0, 8 )
+ if effect > 0.5: effect = 0.5
+ effect = offset + iscale * ( effect )
+ ## sparse cracks noise:
+ if type == 13:
+ effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1
+ if effect > 0.25: effect = 0.25
+ effect = offset + iscale * ( effect * 2.5 )
+ ## shattered rock noise:
+ if type == 14:
+ effect = 0.5 + noise((x,y,0), 7 )
+ if effect > 0.75: effect = 0.75
+ effect = offset + iscale * effect
+ ## lunar noise:
+ if type == 15:
+ effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0]
+ if effect > 0.5: effect = 0.5
+ effect = offset + iscale * ( effect * 2.0 )
+ ## cosine noise:
+ if type == 16:
+ effect = cos( 5*noise(( x, y, 0 ), 0 ) )
+ effect = offset + iscale * ( effect*0.5 )
+ ## spikey noise:
+ if type == 17:
+ n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 )
+ effect = ( ( n*n )**5 )
+ effect = offset + iscale * effect
+ ## stone noise:
+ if type == 18:
+ effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75)
+ ## Flat Turb:
+ if type == 19:
+ t = turbulence(( x, y, 0 ), 6, 0, 0 )
+ effect = t*2.0
+ if effect > 0.25: effect = 0.25
+ effect = offset + iscale * ( effect )
+ ## Flat Voroni:
+ if type == 20:
+ t = 1-noise(( x, y, 0 ), 3 )
+ effect = t*2-1.75
+ if effect > 0.25: effect = 0.25
+ effect = offset + iscale * ( effect )
+
+ if effect < 0.0: effect = 0.0
+ return effect
+
+# fractalize Effect_Basis_Function: ------------------------------
+def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ):
+
+ ## effect distortion:
+ if turb != 0.0:
+ t = vTurbulence(( x, y, 0 ), 6, 0, 0 )
+ x = x + ( 0.5 + 0.5 * t[0] ) * turb
+ y = y + ( 0.5 + 0.5 * t[1] ) * turb
+
+ result = Effect_Basis_Function((x,y), type, bias )
+ ## fractalize effect:
+ if depth != 0:
+ i=0
+ while i < depth:
+ i+=1
+ x *= frequency
+ y *= frequency
+ amplitude = amplitude / i
+ result += Effect_Basis_Function( (x,y), type, bias ) * amplitude
+ return result
+
+###--------------------------------------------------
+# Custom effect:
+def CustomEffect( x,y,z,h ):
+ global CustomFX
+ try:
+ a = eval( CustomFX[0].val )
+ b = eval( CustomFX[1].val )
+ result = eval( CustomFX[2].val )
+ return result
+ except:
+ return 0.0
+
+###--------------------------------------------------
+## Effect Selector:
+
+def Effects( (i,j),(x,y,z), h=0.0 ):
+ global Effect_Type, Effect_Ctrl, iScale, Offset, Invert
+ global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo
+
+ x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 ) )
+ basis = Basis[1].val
+ if basis == 9: basis = 14
+ vbasis = vlnoiTwo[1].val
+ if vbasis == 9: vbasis = 14
+ if Effect_Ctrl[0].val == 1:
+ try: effect = Image_Func( x,y )
+ except: effect = 0.0
+ elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val )
+ elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis )
+ elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val )
+ elif Effect_Ctrl[0].val == 5: effect = 0.5*multiFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )
+ elif Effect_Ctrl[0].val == 6: effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+ elif Effect_Ctrl[0].val == 7: effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+ elif Effect_Ctrl[0].val == 8: effect = 0.5*heteroTerrain(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5
+ elif Effect_Ctrl[0].val == 9: effect = 0.5*fBm(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5
+ elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+ effect = Effect_Function((x,y), Effect_Ctrl[0].val-10, Effect_Ctrl[3].val, Effect_Ctrl[4].val, Effect_Ctrl[5].val, Effect_Ctrl[6].val, Effect_Ctrl[7].val )
+ elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random()
+ elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val
+ elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h )
+ effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val )
+ return effect*2.0
+
+###----------------------------------------------------------------------
+# Noise:
+##-----------------------------------
+
+## voronoi_turbulence:
+def voroTurbMode((x,y,z), voro, mode ):
+ if mode == 0: # soft
+ return voronoi(( x,y,z ),voro[0], voro[1] )[0][0]
+ if mode == 1: # hard
+ return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5
+def voronoi_turbulence((x,y,z), voro, tur ):
+ result = voroTurbMode((x,y,z), voro, tur[1] )
+ depth = tur[0]
+ amp = tur[2]
+ freq = tur[3]
+ i=0
+ for i in xrange( depth ):
+ i+=1
+ result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i )
+ return (result*4.0-2.0)
+
+## DistortedNoise / vlNoise_turbulence:
+def vlnTurbMode((x,y,z), vlno, basis, mode ):
+ if mode == 0: # soft
+ return vlNoise(( x,y,z ),vlno[0], vlno[1], basis )
+ if mode == 1: # hard
+ return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) )
+def vlNoise_turbulence((x,y,z), vlno, tur, basis ):
+ result = vlnTurbMode((x,y,z), vlno, basis, tur[1] )
+ depth = tur[0]
+ amp = tur[2]
+ freq = tur[3]
+ i=0
+ for i in xrange( depth ):
+ i+=1
+ result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i )
+ return result*2.0+0.5
+
+## marbleNoise:
+def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ):
+ m = ( x * rescale + y * rescale + z ) * 5
+ height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 )
+ height = Bias_Types[ bias ]( height )
+ if bias != 4:
+ height = Sharp_Types[ sharpnes ]( height )
+ return height*2.0
+
+## lava_multiFractal:
+def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ):
+ m = multiFractal( ( x,y,z ), Ha, La, Oc, Basis)
+ d = m * distort
+ m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis)
+ return (m * m2)**0.5
+
+## slopey_noise:
+def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ):
+ x=x*2
+ y=y*2
+ turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5
+ map = 0.5 + noise( ( x+turb, y+turb, z ), basis )
+ result = map + turb * distort
+ return result
+
+## duo_multiFractal:
+def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+ n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset
+ n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain
+ result = ( n1*n1 + n2*n2 )*0.5
+ return result
+
+## distorted_heteroTerrain:
+def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+ h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 )
+ h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 )
+ result = ( h1*h1 + h2*h2 )
+ return result
+
+## SlickRock:
+def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+ n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] )
+ r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5
+ return n+(n*r)
+
+## terra_turbulence:
+def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ):
+ t2 = turbulence( ( x, y, z ), depth, hard , basis, amp, freq )
+ return (t2*t2*t2)+0.5
+
+## rocky_fBm:
+def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ):
+ turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25
+ coords = ( x+turb, y+turb, z )
+ map = noise( coords, 7 )
+ result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0
+ return result
+
+## Shattered_hTerrain:
+def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+ d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25
+ t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 )
+ t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) )
+ return (( t0*t2 )+t2*0.5)*0.75
+
+## vlhTerrain
+def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ):
+ ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5
+ vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5
+ return vl * ht
+
+####---------------------------------------.
+### StatsByAlt, double terrain basis mode:
+def TerrainBasisMode((x,y,z), basis, mode ):
+ if mode == 0: # noise
+ return noise((x,y,z),basis)
+ if mode == 1: # noise ridged
+ return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5
+ if mode == 2: # vlNoise
+ return vlNoise((x,y,z), 1.0, 0, basis )
+ else: # vlNoise ridged
+ return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5
+
+#### StatsByAlt terrain:
+def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ):
+ result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+ octs = int( octs )
+ i = 0
+ for i in xrange( 1, octs ):
+ i += 1
+ result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+ x *= lacu
+ y *= lacu
+ amp /= ( exp * 0.5 ) * i
+ return result
+
+##### double terrain:
+def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ):
+ result = amp = freq = 1.0
+ #octs = int( octs )
+ offset*=0.5
+ i = 1
+ signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+ for i in xrange( 1, octs ):
+ i += 1
+ x = x * lacu
+ y = y * lacu
+ freq *= lacu
+ amp = pow( freq, -exp )
+ amp *= i
+ weight = signal / threshold
+ if weight > 1.0: weight = 1.0
+ if weight < 0.0: weigth = 0.0
+ signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) )
+ result += amp * signal
+ return result * 2.0
+
+##------------------------------------------------------------
+# Noise Functions:
+def Noise_Function(x,y,z):
+ global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod
+ global vlBasis, Distort, VFunc, VExp, VDep
+ global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy
+
+ x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 ) )
+ basis = Basis[0].val
+ if basis == 9: basis = 14
+ vbasis = vlnoi[1].val
+ if vbasis == 9: vbasis = 14
+ if NType.val == 0: z = multiFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+ elif NType.val == 1: z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+ elif NType.val == 2: z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+ elif NType.val == 3: z = heteroTerrain(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5
+ elif NType.val == 4: z = fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5
+ elif NType.val == 5: z = turbulence(( x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5
+ elif NType.val == 6: z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5
+ elif NType.val == 7: z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5
+ elif NType.val == 8: z = noise(( x,y,z ),basis )+0.5
+ elif NType.val == 9: z = cellNoise(( x,y,z ))+0.5
+ elif NType.val == 10: z = marbleNoise(( x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val )
+ elif NType.val == 11: z = lava_multiFractal(( x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )
+ elif NType.val == 12: z = slopey_noise(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5
+ elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
+ elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) )
+ elif NType.val == 15: z = SlickRock(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
+ elif NType.val == 16: z = terra_turbulence(( x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )
+ elif NType.val == 17: z = rocky_fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+ elif NType.val == 18: z = StatsByAltTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val )
+ elif NType.val == 19: z = doubleTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val )
+ elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis )
+ elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val )
+ else: z = 0.0
+ return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val )
+
+###----------------------------------------------------------------------
+##-----------------------------------
+# Filter functions:
+
+##-----------------------------------
+# Filter: Clamp height
+def Clamp_Max( height, max ):
+ if ( height > max ): height = max
+ return height
+def Clamp_Min( height, min ):
+ if ( height < min ): height = min
+ return height
+
+##-----------------------------------
+# Filters: terrace / posterise / peaked / bias:
+def Def_Filter((x,y,z), input, numb, type ):
+ if type == 0:
+ s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) )
+ return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+ elif type == 1:
+ s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+ return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+ elif type == 2:
+ s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+ return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+ elif type == 3:
+ numb = numb*0.5
+ s = ( int( input*numb ) * 1.0/numb )
+ return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+ elif type == 4:
+ numb = numb*0.5
+ s = ( int( input*numb ) * 1.0/numb )
+ return ( s ) * 2.0
+ elif type == 5:
+ s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) )
+ l = ( input * (1.0-0.5) + s*0.5 ) * 2.0
+ p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2
+ return ( l * (1.0-0.5) + p*0.5 ) * 2.0
+ elif type == 6:
+ return ( input*numb*0.25 )**4
+ elif type == 7:
+ return 2.0-exp( 1.0-(input*numb/3.0) )
+ elif type == 8:
+ return sin_bias( input*numb )*2.0
+ elif type == 9:
+ return cos_bias( input*numb )*2.0
+ elif type == 10:
+ return tri_bias( input*numb )*2.0
+ elif type == 11:
+ return saw_bias( input*numb )*2.0
+ elif type == 12:
+ return Clamp_Max( input, numb )
+ else:
+ return input
+
+##-----------------------------------
+# Filter: Edge falloff
+def EdgeFalloff( (x,y,z), height, type ):
+ global Falloff, iScale, Offset
+
+ x = x / Falloff[1].val
+ y = y / Falloff[2].val
+
+ if Falloff[3].val != 0:
+ sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val
+ else:
+ sealevel = 0.0
+
+ falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) )
+
+ dist = falltypes[ type ]
+ if Falloff[4].val != 0:
+ dist = 1.0 - dist
+ radius = 1.0
+ height = height - sealevel
+ if( dist < radius ):
+ dist = dist / radius
+ dist = ( (dist) * (dist) * ( 3-2*(dist) ) )
+ height = ( height - height * dist ) + sealevel
+ else:
+ height = sealevel
+
+ if Falloff[3].val != 0:
+ height = Clamp_Min( height, sealevel )
+ else:
+ height = Clamp_Min( height, Min.val )
+
+ return height
+
+##-----------------------------------
+# Filter: Custom height filter:
+def CustomFilter( x,y,z, h ):
+ global CustomFilt
+ try:
+ a = eval(CustomFilt[0].val)
+ b = eval(CustomFilt[1].val)
+ result = eval(CustomFilt[2].val)
+ return result
+ except:
+ return 0.0
+
+#####-------------------------------------------------------------------------------------#####
+####-------------------------------------------------------------------------------------####
+### Combine Functions: (get noise, Add effect, filter height and return result) ###
+##-------------------------------------------------------------------------------------##
+
+def Combine_Functions( (i,j),(x,y,z) ):
+ global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+ global iScale, Offset, Invert, Min, Max, Falloff
+
+ # get noise height:
+ height = Noise_Function(x,y,0.0)
+
+ ### Filter On
+ if Filter_Mode.val !=0:
+ ### 0= Default Filter Order: Noise>Effect>Filter ---------------------
+ if Filter_Order.val ==0:
+ # mix noise with effect:
+ if Effect_Ctrl[0].val !=0:
+ height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+ # edge fallof:
+ if Falloff[0].val !=0:
+ height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+ #else: pass
+
+ if Filter_Mode.val !=0:
+ # height Def_Filter (Terrace/peaked/bias):
+ if Filter_Mode.val ==1:
+ height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val )
+
+ ## 'IPOCurve' height filter:
+ elif Filter_Mode.val ==2:
+ try:
+ height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val
+ except:
+ height = height
+
+ ## Custom filter:
+ elif Filter_Mode.val ==3:
+ height = CustomFilter( x,y,z, height )
+
+ ### 1= Changed Filter Order: Noise>Filter>Effect ---------------------
+ if Filter_Order.val !=0:
+ # mix noise with effect:
+ if Effect_Ctrl[0].val !=0:
+ height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+ # edge fallof:
+ if Falloff[0].val !=0:
+ height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+ #else: pass
+
+ ### Filter Off ---------------------
+ else:
+ # mix noise with effect:
+ if Effect_Ctrl[0].val !=0:
+ height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+ # edge fallof:
+ if Falloff[0].val !=0:
+ height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+
+ # height scale:
+ height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val )
+
+ # clamp height min. max.:
+ if Falloff[0].val !=1:
+ height = Clamp_Min( height, Min.val )
+ height = Clamp_Max( height, Max.val )
+
+ # return height:
+ return height
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+### Render Noise to a Image('NAME') (you must create one first)
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+def HeightFieldImage():
+ global PreView, previewname
+
+ iname = previewname.val
+ try:
+ pic = Image.Get( iname )
+ except:
+ #print iname, ' No Image with this name'
+ PupMenu( 'No Image with this name' )
+ return
+ res = pic.getMaxXY()
+ for i in xrange( res[0] ):
+ x = i - (res[0]) / 2.0
+ x = (x*2.0) / (res[0])
+ for j in xrange( res[1] ):
+ y = j - (res[1]) / 2.0
+ y = (y*2.0) / (res[1])
+ height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) )
+ if height > 1.0: height = 1.0
+ if height < 0.0: height = 0.0
+ pic.setPixelF( i, j, ( height,height,height, 1.0 ) )
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+### Mesh
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+#------------------------------------------------------------
+## Mesh: make new grid
+###------------------------------------------------------------
+
+def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ):
+ # scene, object, mesh ---------------------------------------
+ if not SCENE:
+ SCENE = Blender.Scene.GetCurrent()
+ SCENE.objects.selected=[]
+ newme = Blender.Mesh.New( NAME )
+ newob = SCENE.objects.new( newme, NAME )
+ n = RESOL
+ # verts ---------------------------------------
+ v=[]
+ for i in xrange( n ):
+ x = i-(n-1)/2.0
+ x = x*2.0/(n-1)
+ for j in xrange( n ):
+ y = j-(n-1)/2.0
+ y = y*2.0/(n-1)
+ v.append( [ x, y, 0 ] )
+ newme.verts.extend(v)
+ # faces ---------------------------------------
+ f=[]
+ for i in xrange( n-1 ):
+ for j in xrange( n-1 ):
+ f.append( [ i*n+j,\
+ (i+1)*n+j,\
+ (i+1)*n+j+1,\
+ i*n+j+1 ] )
+
+ newme.faces.extend(f, smooth=True)
+ #---------------------------------------
+ newme.calcNormals()
+ #---------------------------------------
+ if CURSORPOS !=0:
+ newob.loc = Window.GetCursorPos()
+ newob.select(1)
+
+#------------------------------------------------------------
+## Mesh: Grid vert displace / update terrain
+###------------------------------------------------------------
+
+def displace( OB, ME, WORLD=0 ):
+ if WORLD == 1:
+ wx,wy,wz = OB.getLocation( 'worldspace' )
+ elif WORLD ==2:
+ l = OB.getLocation( 'worldspace' )
+ w = Window.GetCursorPos()
+ wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2]
+ else:
+ wx,wy,wz = 0,0,0
+
+ for v in ME.verts:
+ co = v.co
+ co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) )
+ ME.update()
+ ME.calcNormals()
+ #OB.makeDisplayList()
+
+
+#----------------------------------------------------------------------------------------------------
+##----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## Do_it:
+#--------------------------------------
+
+#--------------------------------------
+def do_it():
+ global PreView, actme, actob, WorldSpaceCo
+ if actme !=[]:
+ if print_time !=0:
+ t= sys.time()
+ Window.WaitCursor(1)
+ in_editmode = Window.EditMode()
+ if in_editmode: Window.EditMode(0)
+ if PreView[0].val != 0:
+ do_it_preview()
+ displace( actob[0], actme[0], WorldSpaceCo.val )
+ Window.RedrawAll()
+ else:
+ displace( actob[0], actme[0], WorldSpaceCo.val )
+ Window.RedrawAll()
+ if in_editmode: Window.EditMode(1)
+ Window.WaitCursor(0)
+ if print_time !=0:
+ print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_random():
+ global PreView, actme, actob
+ if actme !=[]:
+ if print_time !=0:
+ t= sys.time()
+ Window.WaitCursor(1)
+ in_editmode = Window.EditMode()
+ if in_editmode: Window.EditMode(0)
+ randomiseNoise()
+ if PreView[0].val != 0:
+ do_it_preview()
+ displace( actob[0], actme[0], WorldSpaceCo.val )
+ Window.RedrawAll()
+ else:
+ displace( actob[0], actme[0], WorldSpaceCo.val )
+ Window.RedrawAll()
+ if in_editmode: Window.EditMode(1)
+ Window.WaitCursor(0)
+ if print_time !=0:
+ print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_preview():
+ if print_time !=0:
+ t= sys.time()
+ HeightFieldImage()
+ Window.RedrawAll()
+ if print_time !=0:
+ print 'Generate Image: done in %.6f' % (sys.time()-t)
+
+###---------------------------------------------------------
+###---------------------------------------------------------
+## load and save:
+#-------------------------
+
+def callback( filename ):
+ txtFile.val = filename
+ Register(drawgui, events, bevents)
+def writeln(f,x):
+ f.write(str(x))
+ f.write("\n")
+def readint(f):
+ return int(f.readline())
+def readfloat(f):
+ return float(f.readline())
+def readstr(f):
+ s = (f.readline())
+ return strip(s)
+
+#--------------------------------------------------
+# Save settings to .ant file
+def SavePreset(FName):
+ global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+ global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+ global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+ global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+ try:
+ f = open(FName,'w')
+ writeln(f,CurVersion)
+ except:
+ filemessage = "Unable to save file."
+ return
+
+ writeln(f,fileinfo)
+ writeln(f,iScale[0].val)
+ writeln(f,iScale[1].val)
+ writeln(f,iScale[2].val)
+ writeln(f,Offset[0].val)
+ writeln(f,Offset[1].val)
+ writeln(f,Offset[2].val)
+ writeln(f,Invert[0].val)
+ writeln(f,Invert[1].val)
+ writeln(f,Invert[2].val)
+ writeln(f,NSize[0].val)
+ writeln(f,NSize[1].val)
+ writeln(f,Sx[0].val)
+ writeln(f,Sx[1].val)
+ writeln(f,Sy[0].val)
+ writeln(f,Sy[1].val)
+ writeln(f,Lx[0].val)
+ writeln(f,Lx[1].val)
+ writeln(f,Ly[0].val)
+ writeln(f,Ly[1].val)
+ writeln(f,NType.val)
+ writeln(f,Basis[0].val)
+ writeln(f,Basis[1].val)
+ writeln(f,musgr[0].val)
+ writeln(f,musgr[1].val)
+ writeln(f,musgr[2].val)
+ writeln(f,musgr[3].val)
+ writeln(f,musgr[4].val)
+ writeln(f,musgr[5].val)
+ writeln(f,tBasismod.val)
+ writeln(f,vlnoi[0].val)
+ writeln(f,vlnoi[1].val)
+ writeln(f,vlnoiTwo[0].val)
+ writeln(f,vlnoiTwo[1].val)
+ writeln(f,voron[0].val)
+ writeln(f,voron[1].val)
+ writeln(f,turbOne[0].val)
+ writeln(f,turbOne[1].val)
+ writeln(f,turbOne[2].val)
+ writeln(f,turbOne[3].val)
+ writeln(f,turbTwo[0].val)
+ writeln(f,turbTwo[1].val)
+ writeln(f,turbTwo[2].val)
+ writeln(f,turbTwo[3].val)
+ writeln(f,marbleOne[0].val)
+ writeln(f,marbleOne[1].val)
+ writeln(f,marbleOne[2].val)
+ writeln(f,marbleOne[3].val)
+ writeln(f,marbleOne[4].val)
+ writeln(f,marbleOne[5].val)
+ writeln(f,marbleTwo[0].val)
+ writeln(f,marbleTwo[1].val)
+ writeln(f,marbleTwo[2].val)
+ writeln(f,marbleTwo[3].val)
+ writeln(f,marbleTwo[4].val)
+ writeln(f,marbleTwo[5].val)
+ writeln(f,musgrTwo[0].val)
+ writeln(f,musgrTwo[1].val)
+ writeln(f,musgrTwo[2].val)
+ writeln(f,musgrTwo[3].val)
+ writeln(f,musgrTwo[4].val)
+ writeln(f,effect_image)
+ writeln(f,Effect_Ctrl[0].val)
+ writeln(f,Effect_Ctrl[1].val)
+ writeln(f,Effect_Ctrl[2].val)
+ writeln(f,Effect_Ctrl[3].val)
+ writeln(f,Effect_Ctrl[4].val)
+ writeln(f,Effect_Ctrl[5].val)
+ writeln(f,Effect_Ctrl[6].val)
+ writeln(f,Effect_Ctrl[7].val)
+ writeln(f,Effect_Ctrl[8].val)
+ writeln(f,CustomFX[0].val)
+ writeln(f,CustomFX[1].val)
+ writeln(f,CustomFX[2].val)
+ writeln(f,Min.val)
+ writeln(f,Max.val)
+ writeln(f,Falloff[0].val)
+ writeln(f,Falloff[1].val)
+ writeln(f,Falloff[2].val)
+ writeln(f,Falloff[3].val)
+ writeln(f,Falloff[4].val)
+ writeln(f,Filter_Mode.val)
+ writeln(f,Filter_Order.val)
+ writeln(f,CustomFilt[0].val)
+ writeln(f,CustomFilt[1].val)
+ writeln(f,CustomFilt[2].val)
+ writeln(f,Def_Filter_Ctrl[0].val)
+ writeln(f,Def_Filter_Ctrl[1].val)
+ writeln(f,Ipo_Filter_Ctrl[0].val)
+ writeln(f,Ipo_Filter_Ctrl[1].val)
+ writeln(f,Ipo_Filter_Ctrl[2].val)
+ writeln(f,Ipo_Filter_Ctrl[3].val)
+ writeln(f,RandMod.val)
+ writeln(f,RSeed.val)
+ writeln(f,rand_H.val)
+ writeln(f,rand_I.val)
+ writeln(f,rand_S.val)
+ writeln(f,rand_L.val)
+ filemessage = 'Settings saved to file.'
+ f.close()
+
+#--------------------------------------------------
+# load settings from .ant file
+def LoadPreset(FName):
+ global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+ global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+ global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+ global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+ try:
+ f = open(FName,'r')
+ FVersion = readstr(f)
+ except:
+ filemessage = "Unable to open file."
+ return
+
+ fileinfo = readstr(f)
+ iScale[0].val = readfloat(f)
+ iScale[1].val = readfloat(f)
+ iScale[2].val = readfloat(f)
+ Offset[0].val = readfloat(f)
+ Offset[1].val = readfloat(f)
+ Offset[2].val = readfloat(f)
+ Invert[0].val = readint(f)
+ Invert[1].val = readint(f)
+ Invert[2].val = readint(f)
+ NSize[0].val = readfloat(f)
+ NSize[1].val = readfloat(f)
+ Sx[0].val = readfloat(f)
+ Sx[1].val = readfloat(f)
+ Sy[0].val = readfloat(f)
+ Sy[1].val = readfloat(f)
+ Lx[0].val = readfloat(f)
+ Lx[1].val = readfloat(f)
+ Ly[0].val = readfloat(f)
+ Ly[1].val = readfloat(f)
+ NType.val = readint(f)
+ Basis[0].val = readint(f)
+ Basis[1].val = readint(f)
+ musgr[0].val = readfloat(f)
+ musgr[1].val = readfloat(f)
+ musgr[2].val = readint(f)
+ musgr[3].val = readfloat(f)
+ musgr[4].val = readfloat(f)
+ musgr[5].val = readfloat(f)
+ tBasismod.val = readint(f)
+ vlnoi[0].val = readfloat(f)
+ vlnoi[1].val = readint(f)
+ vlnoiTwo[0].val = readfloat(f)
+ vlnoiTwo[1].val = readint(f)
+ voron[0].val = readint(f)
+ voron[1].val = readfloat(f)
+ turbOne[0].val = readint(f)
+ turbOne[1].val = readint(f)
+ turbOne[2].val = readfloat(f)
+ turbOne[3].val = readfloat(f)
+ turbTwo[0].val = readint(f)
+ turbTwo[1].val = readint(f)
+ turbTwo[2].val = readfloat(f)
+ turbTwo[3].val = readfloat(f)
+ marbleOne[0].val = readint(f)
+ marbleOne[1].val = readint(f)
+ marbleOne[2].val = readfloat(f)
+ marbleOne[3].val = readint(f)
+ marbleOne[4].val = readint(f)
+ marbleOne[5].val = readfloat(f)
+ marbleTwo[0].val = readint(f)
+ marbleTwo[1].val = readint(f)
+ marbleTwo[2].val = readfloat(f)
+ marbleTwo[3].val = readint(f)
+ marbleTwo[4].val = readint(f)
+ marbleTwo[5].val = readfloat(f)
+ musgrTwo[0].val = readfloat(f)
+ musgrTwo[1].val = readfloat(f)
+ musgrTwo[2].val = readint(f)
+ musgrTwo[3].val = readfloat(f)
+ musgrTwo[4].val = readfloat(f)
+ effect_image = readstr(f)
+ Effect_Ctrl[0].val = readint(f)
+ Effect_Ctrl[1].val = readint(f)
+ Effect_Ctrl[2].val = readfloat(f)
+ Effect_Ctrl[3].val = readint(f)
+ Effect_Ctrl[4].val = readfloat(f)
+ Effect_Ctrl[5].val = readint(f)
+ Effect_Ctrl[6].val = readfloat(f)
+ Effect_Ctrl[7].val = readfloat(f)
+ Effect_Ctrl[8].val = readfloat(f)
+ CustomFX[0].val = readstr(f)
+ CustomFX[1].val = readstr(f)
+ CustomFX[2].val = readstr(f)
+ Min.val = readfloat(f)
+ Max.val = readfloat(f)
+ Falloff[0].val = readint(f)
+ Falloff[1].val = readfloat(f)
+ Falloff[2].val = readfloat(f)
+ Falloff[3].val = readint(f)
+ Falloff[4].val = readint(f)
+ Filter_Mode.val = readint(f)
+ Filter_Order.val = readint(f)
+ CustomFilt[0].val = readstr(f)
+ CustomFilt[1].val = readstr(f)
+ CustomFilt[2].val = readstr(f)
+ Def_Filter_Ctrl[0].val = readint(f)
+ Def_Filter_Ctrl[1].val = readfloat(f)
+ Ipo_Filter_Ctrl[0].val = readstr(f)
+ Ipo_Filter_Ctrl[1].val = readint(f)
+ Ipo_Filter_Ctrl[2].val = readfloat(f)
+ Ipo_Filter_Ctrl[3].val = readfloat(f)
+ RandMod.val = readint(f)
+ RSeed.val = readint(f)
+ rand_H.val = readint(f)
+ rand_I.val = readint(f)
+ rand_S.val = readint(f)
+ rand_L.val = readint(f)
+ filemessage = 'Settings loaded from file.'
+ f.close()
+
+##---------------------------------------------------------------------------
+# Register:
+
+Register( drawgui, events, bevents )
+###--------------------------------------------------------------------------
+ \ No newline at end of file
diff --git a/release/scripts/xfig_export.py b/release/scripts/xfig_export.py
deleted file mode 100644
index ddc0dd4dcea..00000000000
--- a/release/scripts/xfig_export.py
+++ /dev/null
@@ -1,234 +0,0 @@
-#!BPY
-"""
-Name: 'xfig export (.fig)'
-Blender: 244
-Group: 'Export'
-Tooltip: 'Export selected mesh to xfig Format (.fig)'
-"""
-
-__author__ = 'Dino Ghilardi', 'Campbell Barton AKA Ideasman42'
-__url__ = ("blender", "blenderartists.org")
-__version__ = "1.1"
-
-__bpydoc__ = """\
- This script exports the selected mesh to xfig (www.xfig.org) file format (i.e.: .fig)
-
- The starting point of this script was Anthony D'Agostino's raw triangle format export.
- (some code is still here and there, cut'n pasted from his script)
-
- Usage:<br>
- Select the mesh to be exported and run this script from "File->Export" menu.
- The toggle button 'export 3 files' enables the generation of 4 files: one global
- and three with the three different views of the object.
- This script is licensed under the GPL license. (c) Dino Ghilardi, 2005
-
-"""
-
-# .fig export, mostly brutally cut-n pasted from the
-# 'Raw triangle export' (Anthony D'Agostino, http://www.redrival.com/scorpius)|
-
-import Blender
-from Blender import Draw
-import BPyObject
-#, meshtools
-import sys
-import bpy
-#import time
-
-# =================================
-# === Write xfig Format.===
-# =================================
-
-def collect_edges(edges):
- """Gets the max-min coordinates of the mesh"""
-
- """Getting the extremes of the mesh to be exported"""
-
- maxX=maxY=maxZ = -1000000000
- minX=minY=minZ = 1000000000
-
- FGON= Blender.Mesh.EdgeFlags.FGON
-
- me = bpy.data.meshes.new()
- for ob_base in bpy.data.scenes.active.objects.context:
- for ob in BPyObject.getDerivedObjects(ob_base):
- me.verts = None
- try: me.getFromObject(ob[0])
- except: pass
-
- if me.edges:
- me.transform(ob[1])
-
- for ed in me.edges:
- if not ed.flag & FGON:
- x,y,z = v1 = tuple(ed.v1.co)
- maxX = max(maxX, x)
- maxY = max(maxY, y)
- maxZ = max(maxZ, z)
- minX = min(minX, x)
- minY = min(minY, y)
- minZ = min(minZ, z)
-
- x,y,z = v2 = tuple(ed.v2.co)
- maxX = max(maxX, x)
- maxY = max(maxY, y)
- maxZ = max(maxZ, z)
- minX = min(minX, x)
- minY = min(minY, y)
- minZ = min(minZ, z)
-
- edges.append( (v1, v2) )
-
- me.verts = None # free memory
- return maxX,maxY,maxZ,minX,minY,minZ
-
-def xfigheader(file):
- file.write('#FIG 3.2 Produced by xfig version 3.2.5-alpha5\n')
- file.write('Landscape\n')
- file.write('Center\n')
- file.write('Metric\n')
- file.write('A4\n')
- file.write('100.00\n')
- file.write('Single\n')
- file.write('-2\n')
- file.write('1200 2\n')
-
-def figdata(file, edges, expview, bounds, scale, space):
- maxX,maxY,maxZ,minX,minY,minZ = bounds
-
- def xytransform(ed):
- """gives the face vertexes coordinates in the xfig format/translation (view xy)"""
- x1,y1,z1 = ed[0]
- x2,y2,z2 = ed[1]
- y1=-y1; y2=-y2
- return x1,y1,z1,x2,y2,z2
-
- def xztransform(ed):
- """gives the face vertexes coordinates in the xfig format/translation (view xz)"""
- x1,y1,z1 = ed[0]
- x2,y2,z2 = ed[1]
- y1=-y1
- y2=-y2
-
- z1=-z1+maxZ-minY +space
- z2=-z2+maxZ-minY +space
- return x1,y1,z1,x2,y2,z2
-
- def yztransform(ed):
- """gives the face vertexes coordinates in the xfig format/translation (view xz)"""
- x1,y1,z1 = ed[0]
- x2,y2,z2 = ed[1]
- y1=-y1; y2=-y2
- z1=-(z1-maxZ-maxX-space)
- z2=-(z2-maxZ-maxX-space)
- return x1,y1,z1,x2,y2,z2
-
- def transform(ed, expview, scale):
- if expview=='xy':
- x1,y1,z1,x2,y2,z2 = xytransform(ed)
- return int(x1*scale),int(y1*scale),int(x2*scale),int(y2*scale)
- elif expview=='xz':
- x1,y1,z1,x2,y2,z2 = xztransform(ed)
- return int(x1*scale),int(z1*scale),int(x2*scale),int(z2*scale)
- elif expview=='yz':
- x1,y1,z1,x2,y2,z2 = yztransform(ed)
- return int(z1*scale),int(y1*scale),int(z2*scale),int(y2*scale)
-
-
- """Prints all the xfig data (no header)"""
- for ed in edges:
- file.write('2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n')
- file.write('\t %i %i %i %i\n' % transform(ed, expview, scale))
-
-def writexy(edges, bounds, filename, scale, space):
- """writes the x-y view file exported"""
-
- file = open(filename, 'wb')
- xfigheader(file)
- figdata(file, edges, 'xy', bounds, scale, space)
- file.close()
- print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writexz(edges, bounds, filename, scale, space):
- """writes the x-z view file exported"""
- #start = time.clock()
- file = open(filename, 'wb')
- xfigheader(file)
- figdata(file, edges, 'xz', bounds, scale, space)
- file.close()
- print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writeyz(edges, bounds, filename, scale, space):
- """writes the y-z view file exported"""
-
- #start = time.clock()
- file = open(filename, 'wb')
- xfigheader(file)
- figdata(file, edges, 'yz', bounds, scale, space)
- file.close()
- #end = time.clock()
- #seconds = " in %.2f %s" % (end-start, "seconds")
- print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-def writeall(edges, bounds, filename, scale=450, space=2.0):
- """writes all 3 views
-
- Every view is a combined object in the resulting xfig. file."""
-
- maxX,maxY,maxZ,minX,minY,minZ = bounds
-
- file = open(filename, 'wb')
-
- xfigheader(file)
- file.write('#upper view (7)\n')
- file.write('6 % i % i % i % i ')
- file.write('%.6f %.6f %.6f %.6f\n' % (minX, minY, maxX, maxY))
-
- figdata(file, edges, 'xy', bounds, scale, space)
- file.write('-6\n')
- file.write('#bottom view (1)\n')
- file.write('6 %i %i %i %i ')
- file.write('%.6f %.6f %.6f %.6f\n' % (minX, -minZ+maxZ-minY +space, maxX,-maxZ+maxZ-minY +space))
-
- figdata(file, edges, 'xz', bounds, scale, space)
- file.write('-6\n')
-
- file.write('#right view (3)\n')
- file.write('6 %i %i %i %i ')
- file.write('%.6f %.6f %.6f %.6f\n' % (minX, -minZ+maxZ-minY +space, maxX,-maxZ+maxZ-minY +space))
- figdata(file, edges, 'yz', bounds, scale, space)
- file.write('-6\n')
-
- file.close()
- print 'Successfully exported ', Blender.sys.basename(filename)# + seconds
-
-import BPyMessages
-
-def write_ui(filename):
- if filename.lower().endswith('.fig'): filename = filename[:-4]
-
- PREF_SEP= Draw.Create(0)
- PREF_SCALE= Draw.Create(1200)
- PREF_SPACE= Draw.Create(2.0)
-
- block = [\
- ("Separate Files", PREF_SEP, "Export each view axis as a seperate file"),\
- ("Space: ", PREF_SPACE, 0.0, 10.0, "Space between views in blender units"),\
- ("Scale: ", PREF_SCALE, 10, 100000, "Scale, 1200 is a good default")]
-
- if not Draw.PupBlock("Export FIG", block):
- return
-
- edges = []
- bounds = collect_edges(edges)
-
- if PREF_SEP.val:
- writexy(edges, bounds, filename + '_XY.fig', PREF_SCALE.val, PREF_SPACE.val)
- writexz(edges, bounds, filename + '_XZ.fig', PREF_SCALE.val, PREF_SPACE.val)
- writeyz(edges, bounds, filename + '_YZ.fig', PREF_SCALE.val, PREF_SPACE.val)
-
- writeall(edges, bounds, filename + '.fig', PREF_SCALE.val, PREF_SPACE.val)
-
-if __name__ == '__main__':
- Blender.Window.FileSelector(write_ui, 'Export XFIG', Blender.sys.makename(ext='.fig'))
- \ No newline at end of file