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:
-rw-r--r--SConstruct2
-rw-r--r--config/win32-vc-config.py2
-rw-r--r--intern/elbeem/intern/elbeem.h262
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h44
-rw-r--r--intern/guardedalloc/Makefile15
-rw-r--r--intern/guardedalloc/SConscript2
-rw-r--r--intern/guardedalloc/intern/mallocn.c76
-rw-r--r--intern/guardedalloc/intern/mmap_win.c2
-rw-r--r--intern/guardedalloc/make/msvc_6_0/guardedalloc.dsp228
-rw-r--r--projectfiles_vc9/blender/blender.sln71
-rw-r--r--projectfiles_vc9/blender/blender.vcproj2
-rw-r--r--projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj14
-rw-r--r--projectfiles_vc9/blender/editors/ED_editors.vcproj18
-rw-r--r--projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj6
-rw-r--r--[-rwxr-xr-x]release/beos-4.5-i386/specific.sh0
-rw-r--r--[-rwxr-xr-x]release/beos-5.0-i386/specific.sh0
-rw-r--r--[-rwxr-xr-x]release/irix-6.2-mips/specific.sh0
-rw-r--r--release/scripts/bpymodules/dxfImportObjects.py1326
-rw-r--r--release/scripts/export_cal3d.py1112
-rw-r--r--release/scripts/uv_from_adjacent.py129
-rw-r--r--release/ui/buttons_physics_field.py66
-rw-r--r--release/ui/buttons_physics_fluid.py223
-rw-r--r--release/ui/buttons_physics_softbody.py219
-rw-r--r--release/ui/space_buttons.py36
-rw-r--r--release/ui/space_filebrowser.py67
-rw-r--r--release/ui/space_image.py397
-rw-r--r--release/ui/space_info.py119
-rw-r--r--release/ui/space_logic.py88
-rw-r--r--release/ui/space_view3d.py106
-rw-r--r--release/ui/space_view3d_toolbar.py254
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h131
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h24
-rw-r--r--source/blender/blenkernel/BKE_customdata.h10
-rw-r--r--source/blender/blenkernel/BKE_mesh.h4
-rw-r--r--source/blender/blenkernel/BKE_modifier.h7
-rw-r--r--source/blender/blenkernel/BKE_multires.h3
-rw-r--r--source/blender/blenkernel/BKE_tessmesh.h66
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h47
-rw-r--r--source/blender/blenkernel/BKE_verse.h586
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c13
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c2
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c385
-rw-r--r--source/blender/blenkernel/intern/anim.c27
-rw-r--r--source/blender/blenkernel/intern/booleanops.c28
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c8
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c540
-rw-r--r--source/blender/blenkernel/intern/cloth.c8
-rw-r--r--source/blender/blenkernel/intern/constraint.c1
-rw-r--r--source/blender/blenkernel/intern/customdata.c88
-rw-r--r--source/blender/blenkernel/intern/displist.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedbmesh.c1526
-rw-r--r--source/blender/blenkernel/intern/exotic.c4
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c15
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c1197
-rw-r--r--source/blender/blenkernel/intern/mesh.c65
-rw-r--r--source/blender/blenkernel/intern/modifier.c327
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c568
-rw-r--r--source/blender/blenkernel/intern/multires.c4
-rw-r--r--source/blender/blenkernel/intern/object.c8
-rw-r--r--source/blender/blenkernel/intern/particle.c42
-rw-r--r--source/blender/blenkernel/intern/particle_system.c20
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c9
-rw-r--r--source/blender/blenkernel/intern/softbody.c10
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c387
-rw-r--r--source/blender/blenkernel/intern/verse_bitmap_node.c451
-rw-r--r--source/blender/blenkernel/intern/verse_geometry_node.c2101
-rw-r--r--source/blender/blenkernel/intern/verse_method.c523
-rw-r--r--source/blender/blenkernel/intern/verse_node.c750
-rw-r--r--source/blender/blenkernel/intern/verse_object_node.c620
-rw-r--r--source/blender/blenkernel/intern/verse_session.c480
-rw-r--r--source/blender/blenkernel/nla_private.h85
-rw-r--r--source/blender/blenlib/BLI_arithb.h3
-rw-r--r--source/blender/blenlib/BLI_editVert.h3
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c13
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c4
-rw-r--r--source/blender/blenlib/intern/arithb.c51
-rw-r--r--source/blender/blenlib/intern/edgehash.c19
-rw-r--r--source/blender/blenloader/intern/readfile.c157
-rw-r--r--source/blender/blenloader/intern/writefile.c2
-rw-r--r--source/blender/bmesh/SConscript38
-rw-r--r--source/blender/bmesh/bmesh.h355
-rw-r--r--source/blender/bmesh/bmesh_error.h53
-rw-r--r--source/blender/bmesh/bmesh_filters.h4
-rw-r--r--source/blender/bmesh/bmesh_iterators.h70
-rw-r--r--source/blender/bmesh/bmesh_marking.h16
-rw-r--r--source/blender/bmesh/bmesh_operator_api.h338
-rw-r--r--source/blender/bmesh/bmesh_operators.h40
-rw-r--r--source/blender/bmesh/bmesh_queries.h86
-rw-r--r--source/blender/bmesh/bmesh_walkers.h64
-rw-r--r--source/blender/bmesh/editmesh_tools.c7244
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c566
-rw-r--r--source/blender/bmesh/intern/bmesh_eulers.c1186
-rw-r--r--source/blender/bmesh/intern/bmesh_filters.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c246
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c393
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c307
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c277
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c417
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c324
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c1305
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h38
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c838
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h84
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c548
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c775
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h100
-rw-r--r--source/blender/bmesh/intern/bmesh_to_editmesh.c312
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c667
-rw-r--r--source/blender/bmesh/intern/editmesh_to_bmesh.c473
-rw-r--r--source/blender/bmesh/intern/in-progress/BME_conversions.c478
-rw-r--r--source/blender/bmesh/operators/bmesh_dupeops.c570
-rw-r--r--source/blender/bmesh/operators/connectops.c126
-rw-r--r--source/blender/bmesh/operators/createops.c156
-rw-r--r--source/blender/bmesh/operators/dissolveops.c430
-rw-r--r--source/blender/bmesh/operators/extrudeops.c190
-rw-r--r--source/blender/bmesh/operators/mesh_conv.c308
-rw-r--r--source/blender/bmesh/operators/removedoubles.c309
-rw-r--r--source/blender/bmesh/operators/subdivideop.c825
-rw-r--r--source/blender/bmesh/operators/subdivideop.h38
-rw-r--r--source/blender/bmesh/operators/triangulateop.c55
-rw-r--r--source/blender/bmesh/operators/utils.c91
-rw-r--r--source/blender/bmesh/tools/BME_bevel.c918
-rw-r--r--source/blender/bmesh/tools/BME_dupe_ops.c318
-rw-r--r--source/blender/bmesh/tools/BME_duplicate.c307
-rw-r--r--source/blender/bmesh/tools/BME_extrude.c216
-rw-r--r--source/blender/bmesh/tools/BME_weld.c333
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c679
-rw-r--r--source/blender/editors/armature/meshlaplacian.c8
-rw-r--r--source/blender/editors/armature/reeb.c9
-rw-r--r--source/blender/editors/include/ED_mesh.h79
-rw-r--r--source/blender/editors/include/ED_view3d.h14
-rw-r--r--source/blender/editors/mesh/SConscript1
-rw-r--r--source/blender/editors/mesh/bmesh_select.c1424
-rw-r--r--source/blender/editors/mesh/bmesh_selecthistory.c270
-rw-r--r--source/blender/editors/mesh/bmesh_tools.c1321
-rw-r--r--source/blender/editors/mesh/bmeshutils.c523
-rw-r--r--source/blender/editors/mesh/editmesh.c374
-rw-r--r--source/blender/editors/mesh/editmesh_add.c209
-rw-r--r--source/blender/editors/mesh/editmesh_lib.c143
-rw-r--r--source/blender/editors/mesh/editmesh_loop.c249
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c787
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c269
-rw-r--r--source/blender/editors/mesh/mesh_intern.h61
-rw-r--r--source/blender/editors/mesh/mesh_layers.c76
-rw-r--r--source/blender/editors/mesh/meshtools.c85
-rw-r--r--source/blender/editors/object/SConscript2
-rw-r--r--source/blender/editors/object/object_edit.c76
-rw-r--r--source/blender/editors/physics/editparticle.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/space_buttons/SConscript2
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c14
-rw-r--r--source/blender/editors/space_image/image_header.c1
-rw-r--r--source/blender/editors/space_view3d/SConscript2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c346
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c26
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c157
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c90
-rw-r--r--source/blender/editors/transform/SConscript2
-rw-r--r--source/blender/editors/transform/transform.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c159
-rw-r--r--source/blender/editors/transform/transform_generics.c18
-rw-r--r--source/blender/editors/transform/transform_manipulator.c17
-rw-r--r--source/blender/editors/transform/transform_ops.c23
-rw-r--r--source/blender/editors/transform/transform_orientations.c94
-rw-r--r--source/blender/editors/transform/transform_snap.c71
-rw-r--r--source/blender/editors/util/ed_util.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c3
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c5
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h6
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h31
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h21
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/intern/SConscript8
-rw-r--r--source/blender/makesrna/SConscript2
-rw-r--r--source/blender/makesrna/intern/Makefile1
-rw-r--r--source/blender/makesrna/intern/SConscript2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c81
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c3
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c241
-rw-r--r--source/blender/makesrna/intern/rna_nla.c460
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c83
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c282
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c56
-rw-r--r--source/blender/nodes/intern/TEX_nodes/TEX_at.c70
-rw-r--r--source/blender/python/BPY_extern.h8
-rw-r--r--source/blender/python/BPY_menus.c1118
-rw-r--r--source/blender/python/BPY_menus.h128
-rw-r--r--source/blender/python/CMakeLists.txt4
-rw-r--r--source/blender/python/Makefile4
-rw-r--r--source/blender/python/SConscript6
-rw-r--r--source/blender/python/generic/BGL.c1610
-rwxr-xr-xsource/blender/python/generic/BGL.h338
-rw-r--r--source/blender/python/generic/Geometry.c542
-rw-r--r--source/blender/python/generic/Geometry.h39
-rw-r--r--source/blender/python/generic/Makefile66
-rw-r--r--source/blender/python/generic/Mathutils.c1266
-rw-r--r--source/blender/python/generic/Mathutils.h116
-rw-r--r--source/blender/python/generic/bpy_internal_import.c341
-rw-r--r--source/blender/python/generic/bpy_internal_import.h50
-rw-r--r--source/blender/python/generic/euler.c651
-rw-r--r--source/blender/python/generic/euler.h60
-rw-r--r--source/blender/python/generic/matrix.c1358
-rw-r--r--source/blender/python/generic/matrix.h66
-rw-r--r--source/blender/python/generic/quat.c879
-rw-r--r--source/blender/python/generic/quat.h60
-rw-r--r--source/blender/python/generic/vector.c2078
-rw-r--r--source/blender/python/generic/vector.h55
-rw-r--r--source/blender/python/intern/Makefile3
-rw-r--r--source/blender/python/intern/bpy_compat.h26
-rw-r--r--source/blender/python/intern/bpy_interface.c216
-rw-r--r--source/blender/python/intern/bpy_operator.c15
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c203
-rw-r--r--source/blender/python/intern/bpy_rna.c1295
-rw-r--r--source/blender/python/intern/bpy_rna.h2
-rw-r--r--source/blender/python/intern/bpy_ui.c2
-rw-r--r--source/blender/python/intern/bpy_util.c120
-rw-r--r--source/blender/python/intern/bpy_util.h3
-rw-r--r--source/blender/readblenfile/intern/BLO_readblenfile.c1
-rw-r--r--source/blender/render/intern/source/convertblender.c26
-rw-r--r--source/blender/render/intern/source/shadeoutput.c19
-rw-r--r--source/blender/render/intern/source/strand.c4
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp10
-rw-r--r--source/gameengine/PyDoc/Makefile13
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h150
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/EXT_separate_specular_color.h12
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/glext.h6495
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/mkglext.py630
-rw-r--r--tools/Blender.py28
-rwxr-xr-xtools/btools.py5
238 files changed, 49629 insertions, 18743 deletions
diff --git a/SConstruct b/SConstruct
index b85bc799ea5..dab4dde08a3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -575,7 +575,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc'):
dllsources.append('#release/windows/extra/python' + ver + '.zip')
dllsources.append('#release/windows/extra/zlib.pyd')
- if env['BF_DEBUG']:
+ if env['BF_DEBUG'] and not env["BF_NO_PYDEBUG"]:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_LIB}_d.dll')
else:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_LIB}.dll')
diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py
index 82babeb1a3a..a559d76a56c 100644
--- a/config/win32-vc-config.py
+++ b/config/win32-vc-config.py
@@ -165,7 +165,7 @@ CXX_WARN = []
LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid']
-PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/ENTRY:mainCRTStartup','/INCREMENTAL:NO','/NODEFAULTLIB:"msvcprt.lib"','/NODEFAULTLIB:"glut32.lib"','/NODEFAULTLIB:"libc.lib"','/NODEFAULTLIB:"libcd.lib"','/NODEFAULTLIB:"libcpd.lib"','/NODEFAULTLIB:"libcp.lib"','/LARGEADDRESSAWARE']
+PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/ENTRY:mainCRTStartup','/INCREMENTAL:YES','/NODEFAULTLIB:"msvcprt.lib"','/NODEFAULTLIB:"glut32.lib"','/NODEFAULTLIB:"libc.lib"','/NODEFAULTLIB:"libcd.lib"','/NODEFAULTLIB:"libcpd.lib"','/NODEFAULTLIB:"libcp.lib"','/LARGEADDRESSAWARE']
# # Todo
# BF_PROFILE_CCFLAGS = ['-pg', '-g ']
diff --git a/intern/elbeem/intern/elbeem.h b/intern/elbeem/intern/elbeem.h
new file mode 100644
index 00000000000..e29890aba44
--- /dev/null
+++ b/intern/elbeem/intern/elbeem.h
@@ -0,0 +1,262 @@
+/******************************************************************************
+ *
+ * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
+ * All code distributed as part of El'Beem is covered by the version 2 of the
+ * GNU General Public License. See the file COPYING for details.
+ * Copyright 2003-2006 Nils Thuerey
+ *
+ * API header
+ */
+#ifndef ELBEEM_API_H
+#define ELBEEM_API_H
+
+
+// simulation run callback function type (elbeemSimulationSettings->runsimCallback)
+// best use with FLUIDSIM_CBxxx defines below.
+// >parameters
+// return values: 0=continue, 1=stop, 2=abort
+// data pointer: user data pointer from elbeemSimulationSettings->runsimUserData
+// status integer: 1=running simulation, 2=new frame saved
+// frame integer: if status is 1, contains current frame number
+typedef int (*elbeemRunSimulationCallback)(void *data, int status, int frame);
+#define FLUIDSIM_CBRET_CONTINUE 0
+#define FLUIDSIM_CBRET_STOP 1
+#define FLUIDSIM_CBRET_ABORT 2
+#define FLUIDSIM_CBSTATUS_STEP 1
+#define FLUIDSIM_CBSTATUS_NEWFRAME 2
+
+
+// global settings for the simulation
+typedef struct elbeemSimulationSettings {
+ /* version number */
+ short version;
+ /* id number of simulation domain, needed if more than a
+ * single domain should be simulated */
+ short domainId; // unused within blender
+
+ /* geometrical extent */
+ float geoStart[3], geoSize[3];
+
+ /* resolutions */
+ short resolutionxyz;
+ short previewresxyz;
+ /* size of the domain in real units (meters along largest resolution x,y,z extent) */
+ float realsize;
+
+ /* fluid properties */
+ double viscosity;
+ /* gravity strength */
+ float gravity[3];
+ /* anim start end time */
+ float animStart, aniFrameTime;
+ /* no. of frames to simulate & output */
+ short noOfFrames;
+ /* g star param (LBM compressibility) */
+ float gstar;
+ /* activate refinement? */
+ short maxRefine;
+ /* probability for surface particle generation (0.0=off) */
+ float generateParticles;
+ /* amount of tracer particles to generate (0=off) */
+ int numTracerParticles;
+
+ /* store output path, and file prefix for baked fluid surface */
+ char outputPath[160+80];
+
+ /* channel for frame time, visc & gravity animations */
+ int channelSizeFrameTime;
+ float *channelFrameTime;
+ int channelSizeViscosity;
+ float *channelViscosity;
+ int channelSizeGravity;
+ float *channelGravity; // vector
+
+ /* boundary types and settings for domain walls */
+ short domainobsType;
+ float domainobsPartslip;
+ /* generate speed vectors for vertices (e.g. for image based motion blur)*/
+ short generateVertexVectors;
+ /* strength of surface smoothing */
+ float surfaceSmoothing;
+ /* no. of surface subdivisions */
+ int surfaceSubdivs;
+
+ /* global transformation to apply to fluidsim mesh */
+ float surfaceTrafo[4*4];
+
+ /* development variables, testing for upcoming releases...*/
+ float farFieldSize;
+
+ /* callback function to notify calling program of performed simulation steps
+ * or newly available frame data, if NULL it is ignored */
+ elbeemRunSimulationCallback runsimCallback;
+ /* pointer passed to runsimCallback for user data storage */
+ void* runsimUserData;
+
+} elbeemSimulationSettings;
+
+
+// defines for elbeemMesh->type below
+/* please keep in sync with DNA_object_fluidsim.h */
+#define OB_FLUIDSIM_FLUID 4
+#define OB_FLUIDSIM_OBSTACLE 8
+#define OB_FLUIDSIM_INFLOW 16
+#define OB_FLUIDSIM_OUTFLOW 32
+#define OB_FLUIDSIM_PARTICLE 64
+#define OB_FLUIDSIM_CONTROL 128
+
+// defines for elbeemMesh->obstacleType below
+#define FLUIDSIM_OBSTACLE_NOSLIP 1
+#define FLUIDSIM_OBSTACLE_PARTSLIP 2
+#define FLUIDSIM_OBSTACLE_FREESLIP 3
+
+#define OB_VOLUMEINIT_VOLUME 1
+#define OB_VOLUMEINIT_SHELL 2
+#define OB_VOLUMEINIT_BOTH (OB_VOLUMEINIT_SHELL|OB_VOLUMEINIT_VOLUME)
+
+// a single mesh object
+typedef struct elbeemMesh {
+ /* obstacle,fluid or inflow or control ... */
+ short type;
+ /* id of simulation domain it belongs to */
+ short parentDomainId;
+
+ /* vertices */
+ int numVertices;
+ float *vertices; // = float[n][3];
+ /* animated vertices */
+ int channelSizeVertices;
+ float *channelVertices; // = float[channelSizeVertices* (n*3+1) ];
+
+ /* triangles */
+ int numTriangles;
+ int *triangles; // = int[][3];
+
+ /* animation channels */
+ int channelSizeTranslation;
+ float *channelTranslation;
+ int channelSizeRotation;
+ float *channelRotation;
+ int channelSizeScale;
+ float *channelScale;
+
+ /* active channel */
+ int channelSizeActive;
+ float *channelActive;
+ /* initial velocity channel (e.g. for inflow) */
+ int channelSizeInitialVel;
+ float *channelInitialVel; // vector
+ /* use initial velocity in object coordinates? (e.g. for rotation) */
+ short localInivelCoords;
+ /* boundary types and settings */
+ short obstacleType;
+ float obstaclePartslip;
+ /* amount of force transfer from fluid to obj, 0=off, 1=normal */
+ float obstacleImpactFactor;
+ /* init volume, shell or both? use OB_VOLUMEINIT_xxx defines above */
+ short volumeInitType;
+
+ /* name of the mesh, mostly for debugging */
+ const char *name;
+
+ /* fluid control settings */
+ float cpsTimeStart;
+ float cpsTimeEnd;
+ float cpsQuality;
+
+ int channelSizeAttractforceStrength;
+ float *channelAttractforceStrength;
+ int channelSizeAttractforceRadius;
+ float *channelAttractforceRadius;
+ int channelSizeVelocityforceStrength;
+ float *channelVelocityforceStrength;
+ int channelSizeVelocityforceRadius;
+ float *channelVelocityforceRadius;
+} elbeemMesh;
+
+// API functions
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+
+// reset elbeemSimulationSettings struct with defaults
+void elbeemResetSettings(struct elbeemSimulationSettings*);
+
+// start fluidsim init (returns !=0 upon failure)
+int elbeemInit(void);
+
+// frees fluidsim
+int elbeemFree(void);
+
+// start fluidsim init (returns !=0 upon failure)
+int elbeemAddDomain(struct elbeemSimulationSettings*);
+
+// get failure message during simulation or init
+// if an error occured (the string is copied into buffer,
+// max. length = 256 chars )
+void elbeemGetErrorString(char *buffer);
+
+// reset elbeemMesh struct with zeroes
+void elbeemResetMesh(struct elbeemMesh*);
+
+// add mesh as fluidsim object
+int elbeemAddMesh(struct elbeemMesh*);
+
+// do the actual simulation
+int elbeemSimulate(void);
+
+// continue a previously stopped simulation
+int elbeemContinueSimulation(void);
+
+
+// helper functions
+
+// simplify animation channels
+// returns if the channel and its size changed
+int elbeemSimplifyChannelFloat(float *channel, int *size);
+int elbeemSimplifyChannelVec3(float *channel, int *size);
+
+// helper functions implemented in utilities.cpp
+
+/* set elbeem debug output level (0=off to 10=full on) */
+void elbeemSetDebugLevel(int level);
+/* elbeem debug output function, prints if debug level >0 */
+void elbeemDebugOut(char *msg);
+
+/* estimate how much memory a given setup will require */
+double elbeemEstimateMemreq(int res,
+ float sx, float sy, float sz,
+ int refine, char *retstr);
+
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+
+/******************************************************************************/
+// internal defines, do not use for initializing elbeemMesh
+// structs, for these use OB_xxx defines above
+
+/*! fluid geometry init types */
+// type "int" used, so max is 8
+#define FGI_FLAGSTART 16
+#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0))
+#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1))
+#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2))
+#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3))
+#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4))
+#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5))
+#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
+#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
+#define FGI_CONTROL (1<<(FGI_FLAGSTART+ 8))
+
+// all boundary types at once
+#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW )
+
+
+#endif // ELBEEM_API_H
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 1d4c753802b..6cead013895 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -74,7 +74,11 @@ extern "C" {
* Release memory previously allocatred by this module.
*/
short MEM_freeN(void *vmemh);
-
+ short WMEM_freeN(void *vmemh);
+
+ short _MEM_freeN(void *vmemh, char *file, int line);
+ #define MEM_freeN(vmemh) _MEM_freeN(vmemh, __FILE__, __LINE__)
+
/**
* Duplicates a block of memory, and returns a pointer to the
* newly allocated block. */
@@ -130,6 +134,44 @@ extern "C" {
uintptr_t MEM_get_mapped_memory_in_use(void);
int MEM_get_memory_blocks_in_use(void);
+/********* Internal structs. They're only here for the MEM_OVERHEAD macro.*********/
+
+/* --------------------------------------------------------------------- */
+/* Data definition */
+/* --------------------------------------------------------------------- */
+/* all memory chunks are put in linked lists */
+typedef struct localLink
+{
+ struct localLink *next,*prev;
+} localLink;
+
+typedef struct localListBase
+{
+ void *first, *last;
+} localListBase;
+
+ /* note: keep this struct aligned (e.g., irix/gcc) - Hos */
+typedef struct MemHead {
+ int tag1;
+ int len;
+ struct MemHead *next,*prev;
+ const char * name;
+ const char * nextname;
+ int tag2;
+ int mmap; /* if true, memory was mmapped */
+} MemHead;
+
+typedef struct MemTail {
+ int tag3, pad;
+} MemTail;
+
+/*memory bias to hopefully account
+ for allocation overhead from
+ the system allocator.*/
+#define MEM_OVERHEADBIAS 32
+
+#define MEM_OVERHEAD (sizeof(MemHead) + sizeof(MemTail) + MEM_OVERHEADBIAS)
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/guardedalloc/Makefile b/intern/guardedalloc/Makefile
index 55894d54c8e..f0cef3d222c 100644
--- a/intern/guardedalloc/Makefile
+++ b/intern/guardedalloc/Makefile
@@ -1,5 +1,3 @@
-# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
-# vim: tabstop=8
#
# $Id$
#
@@ -24,7 +22,7 @@
#
# The Original Code is: all of this file.
#
-# Contributor(s): Hans Lambermont, GSR
+# Contributor(s): Hans Lambermont
#
# ***** END GPL LICENSE BLOCK *****
# decimation main makefile.
@@ -40,13 +38,16 @@ TESTDIRS = test
include nan_subdirs.mk
-install: $(ALL_OR_DEBUG)
+install: all debug
@[ -d $(NAN_GUARDEDALLOC) ] || mkdir $(NAN_GUARDEDALLOC)
@[ -d $(NAN_GUARDEDALLOC)/include ] || mkdir $(NAN_GUARDEDALLOC)/include
- @[ -d $(NAN_GUARDEDALLOC)/lib/$(DEBUG_DIR) ] || mkdir $(NAN_GUARDEDALLOC)/lib/$(DEBUG_DIR)
- @../tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/$(DEBUG_DIR)
+ @[ -d $(NAN_GUARDEDALLOC)/lib ] || mkdir $(NAN_GUARDEDALLOC)/lib
+ @[ -d $(NAN_GUARDEDALLOC)/lib/debug ] || mkdir $(NAN_GUARDEDALLOC)/lib/debug
+ @../tools/cpifdiff.sh $(DIR)/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/
+ @../tools/cpifdiff.sh $(DIR)/debug/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/debug/
ifeq ($(OS),darwin)
- ranlib $(NAN_GUARDEDALLOC)/lib/$(DEBUG_DIR)libguardedalloc.a
+ ranlib $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a
+ ranlib $(NAN_GUARDEDALLOC)/lib/debug/libguardedalloc.a
endif
@../tools/cpifdiff.sh *.h $(NAN_GUARDEDALLOC)/include/
diff --git a/intern/guardedalloc/SConscript b/intern/guardedalloc/SConscript
index 0184ddd9785..ef6c6b49266 100644
--- a/intern/guardedalloc/SConscript
+++ b/intern/guardedalloc/SConscript
@@ -5,4 +5,4 @@ Import('env')
sources = env.Glob('intern/*.c')
incs = '.'
-env.BlenderLib ('bf_guardedalloc', sources, Split(incs), defines=[], libtype=['intern', 'player'], priority = [5, 175] )
+env.BlenderLib ('bf_guardedalloc', sources, Split(incs), defines=[], libtype=['intern', 'player'], priority = [10, 175] )
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 3b5f6a0caf9..b7f10ff92e1 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -49,36 +49,6 @@
#include "MEM_guardedalloc.h"
/* --------------------------------------------------------------------- */
-/* Data definition */
-/* --------------------------------------------------------------------- */
-/* all memory chunks are put in linked lists */
-typedef struct localLink
-{
- struct localLink *next,*prev;
-} localLink;
-
-typedef struct localListBase
-{
- void *first, *last;
-} localListBase;
-
- /* note: keep this struct aligned (e.g., irix/gcc) - Hos */
-typedef struct MemHead {
- int tag1;
- int len;
- struct MemHead *next,*prev;
- const char * name;
- const char * nextname;
- int tag2;
- int mmap; /* if true, memory was mmapped */
-} MemHead;
-
-typedef struct MemTail {
- int tag3, pad;
-} MemTail;
-
-
-/* --------------------------------------------------------------------- */
/* local functions */
/* --------------------------------------------------------------------- */
@@ -467,35 +437,55 @@ void MEM_printmemlist_pydict( void ) {
MEM_printmemlist_internal(1);
}
-short MEM_freeN(void *vmemh) /* anders compileertie niet meer */
+#ifdef MEM_freeN
+#undef MEM_freeN
+#endif
+
+short MEM_freeN(void *vmemh)
+{
+ return _MEM_freeN(vmemh, "(called through C stub function)", -1);
+}
+
+short WMEM_freeN(void *vmemh)
+{
+ return _MEM_freeN(vmemh, "(called through C stub function)", -1);
+}
+
+/*special macro-wrapped MEM_freeN that keeps track of where MEM_freeN is called.*/
+short _MEM_freeN(void *vmemh, char *file, int line) /* anders compileertie niet meer */
{
short error = 0;
MemTail *memt;
MemHead *memh= vmemh;
const char *name;
-
+ char str1[90];
+
if (memh == NULL){
- MemorY_ErroR("free","attempt to free NULL pointer");
+ sprintf(str1, "Error in %s on line %d: attempt to free NULL pointer", file, line);
+ MemorY_ErroR("free", str1);
/* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
return(-1);
}
if(sizeof(intptr_t)==8) {
if (((intptr_t) memh) & 0x7) {
- MemorY_ErroR("free","attempt to free illegal pointer");
+ sprintf(str1, "Error in %s on line %d: attempt to free illegal pointer", file, line);
+ MemorY_ErroR("free", str1);
return(-1);
}
}
else {
if (((intptr_t) memh) & 0x3) {
- MemorY_ErroR("free","attempt to free illegal pointer");
+ sprintf(str1, "Error in %s on line %d: attempt to free illegal pointer", file, line);
+ MemorY_ErroR("free", str1);
return(-1);
}
}
memh--;
if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
- MemorY_ErroR(memh->name,"double free");
+ sprintf(str1, "Error in %s on line %d: double free", file, line);
+ MemorY_ErroR(memh->name, str1);
return(-1);
}
@@ -519,15 +509,19 @@ short MEM_freeN(void *vmemh) /* anders compileertie niet meer */
MemorY_ErroR(memh->name,"end corrupt");
name = check_memlist(memh);
if (name != 0){
- if (name != memh->name) MemorY_ErroR(name,"is also corrupt");
+ sprintf(str1, "Error in %s on line %d: %s is also corrupt", file, line, name);
+ if (name != memh->name) MemorY_ErroR(name, str1);
}
} else{
error = -1;
name = check_memlist(memh);
- if (name == 0)
- MemorY_ErroR("free","pointer not in memlist");
- else
- MemorY_ErroR(name,"error in header");
+ if (name == 0) {
+ sprintf(str1, "Error in %s on line %d: pointer not in memlist", file, line);
+ MemorY_ErroR("free", str1);
+ } else {
+ sprintf(str1, "Error in %s on line %d: error in header", file, line);
+ MemorY_ErroR(name, str1);
+ }
}
totblock--;
diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c
index 979e77ebbed..824dfa62f2a 100644
--- a/intern/guardedalloc/intern/mmap_win.c
+++ b/intern/guardedalloc/intern/mmap_win.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/intern/guardedalloc/make/msvc_6_0/guardedalloc.dsp b/intern/guardedalloc/make/msvc_6_0/guardedalloc.dsp
index 1c02b639a30..21cc20e14f1 100644
--- a/intern/guardedalloc/make/msvc_6_0/guardedalloc.dsp
+++ b/intern/guardedalloc/make/msvc_6_0/guardedalloc.dsp
@@ -1,114 +1,114 @@
-# Microsoft Developer Studio Project File - Name="guardedalloc" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=guardedalloc - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "guardedalloc.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "guardedalloc.mak" CFG="guardedalloc - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "guardedalloc - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "guardedalloc - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "guardedalloc - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\..\..\obj\windows\intern\guardedalloc\"
-# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\guardedalloc\"
-# PROP Target_Dir ""
-LINK32=link.exe -lib
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\intern\guardedalloc\libguardedalloc.lib"
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\guardedalloc\include\ ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\guardedalloc\*.lib ..\..\..\..\..\lib\windows\guardedalloc\lib\*.a ECHO Done
-# End Special Build Tool
-
-!ELSEIF "$(CFG)" == "guardedalloc - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "..\..\..\..\obj\windows\intern\guardedalloc\debug"
-# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\guardedalloc\debug"
-# PROP Target_Dir ""
-LINK32=link.exe -lib
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\intern\guardedalloc\debug\libguardedalloc.lib"
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\guardedalloc\include\ ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\guardedalloc\debug\*.lib ..\..\..\..\..\lib\windows\guardedalloc\lib\debug\*.a ECHO Done
-# End Special Build Tool
-
-!ENDIF
-
-# Begin Target
-
-# Name "guardedalloc - Win32 Release"
-# Name "guardedalloc - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\intern\mallocn.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Group "extern"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\..\MEM_guardedalloc.h
-# End Source File
-# End Group
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="guardedalloc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=guardedalloc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "guardedalloc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "guardedalloc.mak" CFG="guardedalloc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "guardedalloc - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "guardedalloc - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "guardedalloc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\..\..\obj\windows\intern\guardedalloc\"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\guardedalloc\"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\intern\guardedalloc\libguardedalloc.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\guardedalloc\include\ ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\guardedalloc\*.lib ..\..\..\..\..\lib\windows\guardedalloc\lib\*.a ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "guardedalloc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\intern\guardedalloc\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\guardedalloc\debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\..\..\obj\windows\intern\guardedalloc\debug\libguardedalloc.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\guardedalloc\include\ ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\guardedalloc\debug\*.lib ..\..\..\..\..\lib\windows\guardedalloc\lib\debug\*.a ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "guardedalloc - Win32 Release"
+# Name "guardedalloc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\mallocn.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\MEM_guardedalloc.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/projectfiles_vc9/blender/blender.sln b/projectfiles_vc9/blender/blender.sln
index b8a47867115..1396564d578 100644
--- a/projectfiles_vc9/blender/blender.sln
+++ b/projectfiles_vc9/blender/blender.sln
@@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
+# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj", "{F78B7FC9-DE32-465E-9F26-BB0B6B7A2EAF}"
ProjectSection(ProjectDependencies) = postProject
{E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F} = {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F}
@@ -9,7 +9,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{98330220-47A6-42E0-9DE4-AD0FF5D204D6} = {98330220-47A6-42E0-9DE4-AD0FF5D204D6}
{BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE} = {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE}
{C66F722C-46BE-40C9-ABAE-2EAC7A697EB8} = {C66F722C-46BE-40C9-ABAE-2EAC7A697EB8}
- {D1A9312F-4557-4982-A0F4-4D08508235F4} = {D1A9312F-4557-4982-A0F4-4D08508235F4}
{884D8731-654C-4C7F-9A75-8F37A305BE1E} = {884D8731-654C-4C7F-9A75-8F37A305BE1E}
{E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}
@@ -291,6 +290,34 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WM_windowmanager", "windowm
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ED_editors", "editors\ED_editors.vcproj", "{FB88301F-F725-401B-ACD7-D2ABBF333B71}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F} = {E5F2F004-C704-4DCC-A08F-6EB1E38EAB9F}
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25} = {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}
+ {F9850C15-FF0A-429E-9D47-89FB433C9BD8} = {F9850C15-FF0A-429E-9D47-89FB433C9BD8}
+ {884D8731-654C-4C7F-9A75-8F37A305BE1E} = {884D8731-654C-4C7F-9A75-8F37A305BE1E}
+ {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}
+ {FFD3C64A-30E2-4BC7-BC8F-51818C320400} = {FFD3C64A-30E2-4BC7-BC8F-51818C320400}
+ {31628053-825D-4C06-8A21-D13883489718} = {31628053-825D-4C06-8A21-D13883489718}
+ {EADC3C5A-6C51-4F03-8038-1553E7D7F740} = {EADC3C5A-6C51-4F03-8038-1553E7D7F740}
+ {DB6BE55D-B6D9-494D-856A-8764FF7BA91D} = {DB6BE55D-B6D9-494D-856A-8764FF7BA91D}
+ {3D310C60-6771-48E4-BCCA-D2718CDED898} = {3D310C60-6771-48E4-BCCA-D2718CDED898}
+ {E013786A-9575-4F34-81B2-33290357EE87} = {E013786A-9575-4F34-81B2-33290357EE87}
+ {138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
+ {415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
+ {106AE171-0083-41D6-A949-20DB0E8DC251} = {106AE171-0083-41D6-A949-20DB0E8DC251}
+ {4C3AB78A-52CA-4276-A041-39776E52D8C8} = {4C3AB78A-52CA-4276-A041-39776E52D8C8}
+ {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
+ {9C71A793-C177-4CAB-8EC5-923D500B39F8} = {9C71A793-C177-4CAB-8EC5-923D500B39F8}
+ {BB6AA598-B336-4F8B-9DF9-8CAE7BE71C23} = {BB6AA598-B336-4F8B-9DF9-8CAE7BE71C23}
+ {BAC615B0-F1AF-418B-8D23-A10FD8870D6A} = {BAC615B0-F1AF-418B-8D23-A10FD8870D6A}
+ {9991A3C3-83FE-4AFE-9E18-9D01CB57E879} = {9991A3C3-83FE-4AFE-9E18-9D01CB57E879}
+ {0112CAD5-3584-412A-A2E5-1315A00437B4} = {0112CAD5-3584-412A-A2E5-1315A00437B4}
+ {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49} = {2AE0D2D9-6A7A-44DE-9EFF-99C9E3257B49}
+ {5A2EA6DC-1A53-4E87-9166-52870CE3B4EA} = {5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}
+ {9A307EE5-CD77-47BC-BD87-62508C7E19D8} = {9A307EE5-CD77-47BC-BD87-62508C7E19D8}
+ {B83C6BED-11EC-46C8-AFFA-121EEDE94373} = {B83C6BED-11EC-46C8-AFFA-121EEDE94373}
+ {524264F4-DF21-4B79-847F-E7CA643ECD0B} = {524264F4-DF21-4B79-847F-E7CA643ECD0B}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RNA_makesrna", "makesrna\RNA_makesrna.vcproj", "{8C2BCCF8-4D9E-46D3-BABF-C1545A332CE6}"
ProjectSection(ProjectDependencies) = postProject
@@ -307,7 +334,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DNA_dna", "makesdna\DNA_dna
{E013786A-9575-4F34-81B2-33290357EE87} = {E013786A-9575-4F34-81B2-33290357EE87}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BLF_blenfont", "blenfont\BLF_blenfont.vcproj", "{D1A9312F-4557-4982-A0F4-4D08508235F4}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BL_bmesh", "..\BL_bmesh\BL_bmesh.vcproj", "{6A51010A-9393-4D77-84B4-5BBCDA6E7C25}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}
+ {31628053-825D-4C06-8A21-D13883489718} = {31628053-825D-4C06-8A21-D13883489718}
+ {E013786A-9575-4F34-81B2-33290357EE87} = {E013786A-9575-4F34-81B2-33290357EE87}
+ {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1217,22 +1250,22 @@ Global
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}.Debug|Win32.Build.0 = Blender Debug|Win32
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}.Release|Win32.ActiveCfg = Blender Release|Win32
{7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}.Release|Win32.Build.0 = Blender Release|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.3D Plugin Debug|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.3D Plugin Debug|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.3D Plugin Release|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.3D Plugin Release|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Blender Debug|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Blender Debug|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Blender Release|Win32.ActiveCfg = Blender Release|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Blender Release|Win32.Build.0 = Blender Release|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.BlenderPlayer Debug|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.BlenderPlayer Debug|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.BlenderPlayer Release|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.BlenderPlayer Release|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Debug|Win32.ActiveCfg = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Debug|Win32.Build.0 = Blender Debug|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Release|Win32.ActiveCfg = Blender Release|Win32
- {D1A9312F-4557-4982-A0F4-4D08508235F4}.Release|Win32.Build.0 = Blender Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.3D Plugin Debug|Win32.ActiveCfg = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.3D Plugin Debug|Win32.Build.0 = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.3D Plugin Release|Win32.ActiveCfg = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.3D Plugin Release|Win32.Build.0 = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Blender Debug|Win32.ActiveCfg = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Blender Debug|Win32.Build.0 = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Blender Release|Win32.ActiveCfg = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Blender Release|Win32.Build.0 = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.BlenderPlayer Debug|Win32.ActiveCfg = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.BlenderPlayer Debug|Win32.Build.0 = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.BlenderPlayer Release|Win32.ActiveCfg = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.BlenderPlayer Release|Win32.Build.0 = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Debug|Win32.Build.0 = Debug|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Release|Win32.ActiveCfg = Release|Win32
+ {6A51010A-9393-4D77-84B4-5BBCDA6E7C25}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/projectfiles_vc9/blender/blender.vcproj b/projectfiles_vc9/blender/blender.vcproj
index 37824155bb7..08132fc5627 100644
--- a/projectfiles_vc9/blender/blender.vcproj
+++ b/projectfiles_vc9/blender/blender.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="blender"
ProjectGUID="{F78B7FC9-DE32-465E-9F26-BB0B6B7A2EAF}"
RootNamespace="blender"
diff --git a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
index 8b1b8949b04..0402710d0d0 100644
--- a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
+++ b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="BKE_blenkernel"
ProjectGUID="{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}"
RootNamespace="BKE_blenkernel"
@@ -594,6 +594,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenkernel\intern\editderivedbmesh.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenkernel\intern\effect.c"
>
</File>
@@ -674,6 +678,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenkernel\intern\modifiers_bmesh.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenkernel\intern\multires.c"
>
</File>
@@ -1059,6 +1067,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenkernel\BKE_tessmesh.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenkernel\BKE_text.h"
>
</File>
diff --git a/projectfiles_vc9/blender/editors/ED_editors.vcproj b/projectfiles_vc9/blender/editors/ED_editors.vcproj
index 497560b4a5a..80fe2361443 100644
--- a/projectfiles_vc9/blender/editors/ED_editors.vcproj
+++ b/projectfiles_vc9/blender/editors/ED_editors.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="ED_editors"
ProjectGUID="{FB88301F-F725-401B-ACD7-D2ABBF333B71}"
RootNamespace="BL_editors"
@@ -1147,6 +1147,22 @@
Name="mesh"
>
<File
+ RelativePath="..\..\..\source\blender\editors\mesh\bmesh_select.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\editors\mesh\bmesh_selecthistory.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\editors\mesh\bmesh_tools.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\editors\mesh\bmeshutils.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\editors\mesh\editface.c"
>
</File>
diff --git a/projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj b/projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj
index 81449aa489d..96de0231363 100644
--- a/projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj
+++ b/projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="DNA_makesdna"
ProjectGUID="{E013786A-9575-4F34-81B2-33290357EE87}"
RootNamespace="DNA_makesdna"
@@ -702,6 +702,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\makesdna\DNA_meshdata_types.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\makesdna\DNA_meta_types.h"
>
</File>
diff --git a/release/beos-4.5-i386/specific.sh b/release/beos-4.5-i386/specific.sh
index 9ce063b27a9..9ce063b27a9 100755..100644
--- a/release/beos-4.5-i386/specific.sh
+++ b/release/beos-4.5-i386/specific.sh
diff --git a/release/beos-5.0-i386/specific.sh b/release/beos-5.0-i386/specific.sh
index 9ce063b27a9..9ce063b27a9 100755..100644
--- a/release/beos-5.0-i386/specific.sh
+++ b/release/beos-5.0-i386/specific.sh
diff --git a/release/irix-6.2-mips/specific.sh b/release/irix-6.2-mips/specific.sh
index 1b053ce6a3e..1b053ce6a3e 100755..100644
--- a/release/irix-6.2-mips/specific.sh
+++ b/release/irix-6.2-mips/specific.sh
diff --git a/release/scripts/bpymodules/dxfImportObjects.py b/release/scripts/bpymodules/dxfImportObjects.py
new file mode 100644
index 00000000000..960c4c1ac15
--- /dev/null
+++ b/release/scripts/bpymodules/dxfImportObjects.py
@@ -0,0 +1,1326 @@
+"""This module provides wrapper objects for dxf entities.
+
+ The wrappers expect a "dxf object" as input. The dxf object is
+ an object with a type and a data attribute. Type is a lowercase
+ string matching the 0 code of a dxf entity. Data is a list containing
+ dxf objects or lists of [code, data] pairs.
+
+ This module is not general, and is only for dxf import.
+"""
+
+# --------------------------------------------------------------------------
+# DXF Import Objects v0.8 by Ed Blake (AKA Kitsu)
+# --------------------------------------------------------------------------
+# ***** 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 *****
+# --------------------------------------------------------------------------
+from math import *
+
+
+# from Stani's dxf writer v1.1 (c)www.stani.be (GPL)
+#---color values
+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
+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)
+
+#---mtext flags
+#attachment point
+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
+#drawing direction
+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
+
+#---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
+
+#---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
+#vertical
+BASELINE = 0
+BOTTOM = 1
+MIDDLE = 2
+TOP = 3
+class Object:
+ """Empty container class for dxf objects"""
+
+ def __init__(self, _type=''):
+ """_type expects a string value."""
+ self.type = _type
+ self.name = ''
+ self.data = []
+
+ def __str__(self):
+ if self.name:
+ return self.name
+ else:
+ return self.type
+
+ def __repr__(self):
+ return str(self.data)
+
+ def get_type(self, kind=''):
+ """Despite the name, this method actually returns all objects of type 'kind' from self.data."""
+ if type:
+ objects = []
+ for item in self.data:
+ if type(item) != list and item.type == kind:
+ # we want this type of object
+ objects.append(item)
+ elif type(item) == list and item[0] == kind:
+ # we want this type of data
+ objects.append(item[1])
+ return objects
+
+
+class Layer:
+ """Class for objects representing dxf layers."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type line as input."""
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ self.name = obj.get_type(2)[0]
+ self.color = obj.get_type(62)[0]
+ self.flags = obj.get_type(70)[0]
+ self.frozen = self.flags&1
+
+
+
+ def __repr__(self):
+ return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color)
+
+
+
+class Line:
+ """Class for objects representing dxf lines."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type line as input."""
+ if not obj.type == 'line':
+ raise TypeError, "Wrong type %s for line object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+
+ self.points = self.get_points(obj.data)
+
+
+
+
+ def get_points(self, data):
+ """Gets start and end points for a line type object.
+
+ Lines have a fixed number of points (two) and fixed codes for each value.
+ """
+
+ # start x, y, z and end x, y, z = 0
+ sx, sy, sz, ex, ey, ez = 0, 0, 0, 0, 0, 0
+ for item in data:
+ if item[0] == 10: # 10 = x
+ sx = item[1]
+ elif item[0] == 20: # 20 = y
+ sy = item[1]
+ elif item[0] == 30: # 30 = z
+ sz = item[1]
+ elif item[0] == 11: # 11 = x
+ ex = item[1]
+ elif item[0] == 21: # 21 = y
+ ey = item[1]
+ elif item[0] == 31: # 31 = z
+ ez = item[1]
+ return [[sx, sy, sz], [ex, ey, ez]]
+
+
+
+ def __repr__(self):
+ return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
+
+
+
+class LWpolyline:
+ """Class for objects representing dxf LWpolylines."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type lwpolyline as input."""
+ if not obj.type == 'lwpolyline':
+ raise TypeError, "Wrong type %s for polyline object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.num_points = obj.get_type(90)[0]
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ self.elevation = obj.get_type(38)
+ if self.elevation:
+ self.elevation = self.elevation[0]
+ else:
+ self.elevation = 0
+
+ self.flags = obj.get_type(70)
+ if self.flags:
+ self.flags = self.flags[0]
+ else:
+ self.flags = 0
+
+ self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.points = self.get_points(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+
+ def get_points(self, data):
+ """Gets points for a polyline type object.
+
+ Polylines have no fixed number of verts, and
+ each vert can have a number of properties.
+ Verts should be coded as
+ 10:xvalue
+ 20:yvalue
+ 40:startwidth or 0
+ 41:endwidth or 0
+ 42:bulge or 0
+ for each vert
+ """
+ num = self.num_points
+ point = None
+ points = []
+ for item in data:
+ if item[0] == 10: # 10 = x
+ if point:
+ points.append(point)
+ point = Vertex()
+ point.x = item[1]
+ elif item[0] == 20: # 20 = y
+ point.y = item[1]
+ elif item[0] == 40: # 40 = start width
+ point.swidth = item[1]
+ elif item[0] == 41: # 41 = end width
+ point.ewidth = item[1]
+ elif item[0] == 42: # 42 = bulge
+ point.bulge = item[1]
+ points.append(point)
+ return points
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
+
+
+
+class Polyline:
+ """Class for objects representing dxf LWpolylines."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type polyline as input."""
+ if not obj.type == 'polyline':
+ raise TypeError, "Wrong type %s for polyline object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+ self.points = []
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ self.elevation = obj.get_type(30)
+ if self.elevation:
+ self.elevation = self.elevation[0]
+ else:
+ self.elevation = 0
+
+ self.flags = obj.get_type(70)
+ if self.flags:
+ self.flags = self.flags[0]
+ else:
+ self.flags = 0
+
+ self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
+
+
+
+class Vertex(object):
+ """Generic vertex object used by polylines (and maybe others)."""
+
+ def __init__(self, obj=None):
+ """Initializes vertex data.
+
+ The optional obj arg is an entity object of type vertex.
+ """
+ self.loc = [0,0,0]
+ self.bulge = 0
+ self.swidth = 0
+ self.ewidth = 0
+ self.flags = 0
+
+ if obj is not None:
+ if not obj.type == 'vertex':
+ raise TypeError, "Wrong type %s for vertex object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ self.get_props(obj.data)
+
+
+ def get_props(self, data):
+ """Gets coords for a vertex type object.
+
+ Each vert can have a number of properties.
+ Verts should be coded as
+ 10:xvalue
+ 20:yvalue
+ 40:startwidth or 0
+ 41:endwidth or 0
+ 42:bulge or 0
+ """
+ for item in data:
+ if item[0] == 10: # 10 = x
+ self.x = item[1]
+ elif item[0] == 20: # 20 = y
+ self.y = item[1]
+ elif item[0] == 30: # 30 = z
+ self.z = item[1]
+ elif item[0] == 40: # 40 = start width
+ self.swidth = item[1]
+ elif item[0] == 41: # 41 = end width
+ self.ewidth = item[1]
+ elif item[0] == 42: # 42 = bulge
+ self.bulge = item[1]
+ elif item[0] == 70: # 70 = vert flags
+ self.flags = item[1]
+
+
+ def __len__(self):
+ return 3
+
+
+ def __getitem__(self, key):
+ return self.loc[key]
+
+
+ def __setitem__(self, key, value):
+ if key in [0,1,2]:
+ self.loc[key]
+
+
+ def __iter__(self):
+ return self.loc.__iter__()
+
+
+ def __str__(self):
+ return str(self.loc)
+
+
+ def __repr__(self):
+ return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s" %(self.loc, self.swidth, self.ewidth, self.bulge)
+
+
+ def getx(self):
+ return self.loc[0]
+
+ def setx(self, value):
+ self.loc[0] = value
+
+ x = property(getx, setx)
+
+
+ def gety(self):
+ return self.loc[1]
+
+ def sety(self, value):
+ self.loc[1] = value
+
+ y = property(gety, sety)
+
+
+ def getz(self):
+ return self.loc[2]
+
+ def setz(self, value):
+ self.loc[2] = value
+
+ z = property(getz, setz)
+
+
+
+class Text:
+ """Class for objects representing dxf Text."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type text as input."""
+ if not obj.type == 'text':
+ raise TypeError, "Wrong type %s for text object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.height = obj.get_type(40)[0]
+ self.value = obj.get_type(1)[0] # The text string value
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ self.rotation = obj.get_type(50) # radians?
+ if not self.rotation:
+ self.rotation = 0
+ else:
+ self.rotation = self.rotation[0]
+
+ self.width_factor = obj.get_type(41) # Scaling factor along local x axis
+ if not self.width_factor:
+ self.width_factor = 1
+ else:
+ self.width_factor = self.width_factor[0]
+
+ self.oblique = obj.get_type(51) # skew in degrees -90 <= oblique <= 90
+ if not self.oblique:
+ self.oblique = 0
+ else:
+ self.oblique = self.oblique[0]
+
+ self.halignment = obj.get_type(72) # horiz. alignment
+ if not self.halignment: # 0=left, 1=center, 2=right, 3=aligned, 4=middle, 5=fit
+ self.halignment = 0
+ else:
+ self.halignment = self.halignment[0]
+
+ self.valignment = obj.get_type(73) # vert. alignment
+ if not self.valignment: # 0=baseline, 1=bottom, 2=middle, 3=top
+ self.valignment = 0
+ else:
+ self.valignment = self.valignment[0]
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data, self.halignment, self.valignment)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+ def get_loc(self, data, halign, valign):
+ """Gets adjusted location for text type objects.
+
+ If group 72 and/or 73 values are nonzero then the first alignment point values
+ are ignored and AutoCAD calculates new values based on the second alignment
+ point and the length and height of the text string itself (after applying the
+ text style). If the 72 and 73 values are zero or missing, then the second
+ alignment point is meaningless.
+
+ I don't know how to calc text size...
+ """
+ # bottom left x, y, z and justification x, y, z = 0
+ x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0
+ for item in data:
+ if item[0] == 10: # 10 = x
+ x = item[1]
+ elif item[0] == 20: # 20 = y
+ y = item[1]
+ elif item[0] == 30: # 30 = z
+ z = item[1]
+ elif item[0] == 11: # 11 = x
+ jx = item[1]
+ elif item[0] == 21: # 21 = y
+ jy = item[1]
+ elif item[0] == 31: # 31 = z
+ jz = item[1]
+
+ if halign or valign:
+ x, y, z = jx, jy, jz
+ return [x, y, z]
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
+
+
+
+class Mtext:
+ """Class for objects representing dxf Mtext."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type mtext as input."""
+ if not obj.type == 'mtext':
+ raise TypeError, "Wrong type %s for mtext object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.height = obj.get_type(40)[0]
+ self.width = obj.get_type(41)[0]
+ self.alignment = obj.get_type(71)[0] # alignment 1=TL, 2=TC, 3=TR, 4=ML, 5=MC, 6=MR, 7=BL, 8=BC, 9=BR
+ self.value = self.get_text(obj.data) # The text string value
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ self.rotation = obj.get_type(50) # radians
+ if not self.rotation:
+ self.rotation = 0
+ else:
+ self.rotation = self.rotation[0]
+
+ self.width_factor = obj.get_type(42) # Scaling factor along local x axis
+ if not self.width_factor:
+ self.width_factor = 1
+ else:
+ self.width_factor = self.width_factor[0]
+
+ self.line_space = obj.get_type(44) # percentage of default
+ if not self.line_space:
+ self.line_space = 1
+ else:
+ self.line_space = self.line_space[0]
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+ def get_text(self, data):
+ """Reconstructs mtext data from dxf codes."""
+ primary = ''
+ secondary = []
+ for item in data:
+ if item[0] == 1: # There should be only one primary...
+ primary = item[1]
+ elif item[0] == 3: # There may be any number of extra strings (in order)
+ secondary.append(item[1])
+ if not primary:
+ #raise ValueError, "Empty Mtext Object!"
+ string = "Empty Mtext Object!"
+ if not secondary:
+ string = primary.replace(r'\P', '\n')
+ else:
+ string = ''.join(secondary)+primary
+ string = string.replace(r'\P', '\n')
+ return string
+ def get_loc(self, data):
+ """Gets location for a mtext type objects.
+
+ Mtext objects have only one point indicating location.
+ """
+ loc = [0,0,0]
+ for item in data:
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value)
+
+
+
+class Circle:
+ """Class for objects representing dxf Circles."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type circle as input."""
+ if not obj.type == 'circle':
+ raise TypeError, "Wrong type %s for circle object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.radius = obj.get_type(40)[0]
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+ def get_loc(self, data):
+ """Gets the center location for circle type objects.
+
+ Circles have a single coord location.
+ """
+ loc = [0, 0, 0]
+ for item in data:
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
+
+
+
+class Arc:
+ """Class for objects representing dxf arcs."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type arc as input."""
+ if not obj.type == 'arc':
+ raise TypeError, "Wrong type %s for arc object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.radius = obj.get_type(40)[0]
+ self.start_angle = obj.get_type(50)[0]
+ self.end_angle = obj.get_type(51)[0]
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+ def get_loc(self, data):
+ """Gets the center location for arc type objects.
+
+ Arcs have a single coord location.
+ """
+ loc = [0, 0, 0]
+ for item in data:
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
+
+
+
+class BlockRecord:
+ """Class for objects representing dxf block_records."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type block_record as input."""
+ if not obj.type == 'block_record':
+ raise TypeError, "Wrong type %s for block_record object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.name = obj.get_type(2)[0]
+
+ # optional data (with defaults)
+ self.insertion_units = obj.get_type(70)
+ if not self.insertion_units:
+ self.insertion_units = None
+ else:
+ self.insertion_units = self.insertion_units[0]
+
+ self.insert_units = obj.get_type(1070)
+ if not self.insert_units:
+ self.insert_units = None
+ else:
+ self.insert_units = self.insert_units[0]
+
+
+
+
+
+
+ def __repr__(self):
+ return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units)
+
+
+
+
+class Block:
+ """Class for objects representing dxf blocks."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type block as input."""
+ if not obj.type == 'block':
+ raise TypeError, "Wrong type %s for block object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.flags = obj.get_type(70)[0]
+ self.entities = Object('block_contents')
+ self.entities.data = objectify([ent for ent in obj.data if type(ent) != list])
+
+ # optional data (with defaults)
+ self.name = obj.get_type(3)
+ if self.name:
+ self.name = self.name[0]
+ else:
+ self.name = ''
+
+ self.path = obj.get_type(1)
+ if self.path:
+ self.path = self.path[0]
+ else:
+ self.path = ''
+
+ self.discription = obj.get_type(4)
+ if self.discription:
+ self.discription = self.discription[0]
+ else:
+ self.discription = ''
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+
+
+
+
+
+ def get_loc(self, data):
+ """Gets the insert point of the block."""
+ loc = [0, 0, 0]
+ for item in data:
+ if type(item) != list:
+ continue
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def __repr__(self):
+ return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path)
+
+
+
+
+class Insert:
+ """Class for objects representing dxf inserts."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type insert as input."""
+ if not obj.type == 'insert':
+ raise TypeError, "Wrong type %s for insert object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.block = obj.get_type(2)[0]
+
+ # optional data (with defaults)
+ self.rotation = obj.get_type(50)
+ if self.rotation:
+ self.rotation = self.rotation[0]
+ else:
+ self.rotation = 0
+
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+ self.scale = self.get_scale(obj.data)
+ self.rows, self.columns = self.get_array(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+
+
+
+
+
+ def get_loc(self, data):
+ """Gets the center location for circle type objects.
+
+ Circles have a single coord location.
+ """
+ loc = [0, 0, 0]
+ for item in data:
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def get_scale(self, data):
+ """Gets the x/y/z scale factor for the block.
+ """
+ scale = [1, 1, 1]
+ for item in data:
+ if item[0] == 41: # 41 = x scale
+ scale[0] = item[1]
+ elif item[0] == 42: # 42 = y scale
+ scale[1] = item[1]
+ elif item[0] == 43: # 43 = z scale
+ scale[2] = item[1]
+ return scale
+
+
+
+ def get_array(self, data):
+ """Returns the pair (row number, row spacing), (column number, column spacing)."""
+ columns = 1
+ rows = 1
+ cspace = 0
+ rspace = 0
+ for item in data:
+ if item[0] == 70: # 70 = columns
+ columns = item[1]
+ elif item[0] == 71: # 71 = rows
+ rows = item[1]
+ if item[0] == 44: # 44 = columns
+ cspace = item[1]
+ elif item[0] == 45: # 45 = rows
+ rspace = item[1]
+ return (rows, rspace), (columns, cspace)
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, block - %s" %(self.__class__.__name__, self.layer, self.block)
+
+
+
+
+class Ellipse:
+ """Class for objects representing dxf ellipses."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type ellipse as input."""
+ if not obj.type == 'ellipse':
+ raise TypeError, "Wrong type %s for ellipse object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # required data
+ self.ratio = obj.get_type(40)[0]
+ self.start_angle = obj.get_type(41)[0]
+ self.end_angle = obj.get_type(42)[0]
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.loc = self.get_loc(obj.data)
+ self.major = self.get_major(obj.data)
+ self.extrusion = self.get_extrusion(obj.data)
+ self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2)
+
+
+
+
+ def get_loc(self, data):
+ """Gets the center location for arc type objects.
+
+ Arcs have a single coord location.
+ """
+ loc = [0, 0, 0]
+ for item in data:
+ if item[0] == 10: # 10 = x
+ loc[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ loc[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def get_major(self, data):
+ """Gets the major axis for ellipse type objects.
+
+ The ellipse major axis defines the rotation of the ellipse and its radius.
+ """
+ loc = [0, 0, 0]
+ for item in data:
+ if item[0] == 11: # 11 = x
+ loc[0] = item[1]
+ elif item[0] == 21: # 21 = y
+ loc[1] = item[1]
+ elif item[0] == 31: # 31 = z
+ loc[2] = item[1]
+ return loc
+
+
+
+ def get_extrusion(self, data):
+ """Find the axis of extrusion.
+
+ Used to get the objects Object Coordinate System (ocs).
+ """
+ vec = [0,0,1]
+ for item in data:
+ if item[0] == 210: # 210 = x
+ vec[0] = item[1]
+ elif item[0] == 220: # 220 = y
+ vec[1] = item[1]
+ elif item[0] == 230: # 230 = z
+ vec[2] = item[1]
+ return vec
+
+
+ def __repr__(self):
+ return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius)
+
+
+
+class Face:
+ """Class for objects representing dxf 3d faces."""
+
+ def __init__(self, obj):
+ """Expects an entity object of type 3dfaceplot as input."""
+ if not obj.type == '3dface':
+ raise TypeError, "Wrong type %s for 3dface object!" %obj.type
+ self.type = obj.type
+ self.data = obj.data[:]
+
+ # optional data (with defaults)
+ self.space = obj.get_type(67)
+ if self.space:
+ self.space = self.space[0]
+ else:
+ self.space = 0
+
+ self.color_index = obj.get_type(62)
+ if self.color_index:
+ self.color_index = self.color_index[0]
+ else:
+ self.color_index = BYLAYER
+
+ discard, self.layer, discard_index = get_layer(obj.data)
+ del obj.data[discard_index]
+ self.points = self.get_points(obj.data)
+
+
+
+
+ def get_points(self, data):
+ """Gets 3-4 points for a 3d face type object.
+
+ Faces have three or optionally four verts.
+ """
+
+ a = [0, 0, 0]
+ b = [0, 0, 0]
+ c = [0, 0, 0]
+ d = False
+ for item in data:
+ # ----------- a -------------
+ if item[0] == 10: # 10 = x
+ a[0] = item[1]
+ elif item[0] == 20: # 20 = y
+ a[1] = item[1]
+ elif item[0] == 30: # 30 = z
+ a[2] = item[1]
+ # ----------- b -------------
+ elif item[0] == 11: # 11 = x
+ b[0] = item[1]
+ elif item[0] == 21: # 21 = y
+ b[1] = item[1]
+ elif item[0] == 31: # 31 = z
+ b[2] = item[1]
+ # ----------- c -------------
+ elif item[0] == 12: # 12 = x
+ c[0] = item[1]
+ elif item[0] == 22: # 22 = y
+ c[1] = item[1]
+ elif item[0] == 32: # 32 = z
+ c[2] = item[1]
+ # ----------- d -------------
+ elif item[0] == 13: # 13 = x
+ d = [0, 0, 0]
+ d[0] = item[1]
+ elif item[0] == 23: # 23 = y
+ d[1] = item[1]
+ elif item[0] == 33: # 33 = z
+ d[2] = item[1]
+ out = [a,b,c]
+ if d:
+ out.append(d)
+ return out
+
+
+ def __repr__(self):
+ return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points)
+
+
+def get_name(data):
+ """Get the name of an object from its object data.
+
+ Returns a pair of (data_item, name) where data_item is the list entry where the name was found
+ (the data_item can be used to remove the entry from the object data). Be sure to check
+ name not None before using the returned values!
+ """
+ value = None
+ for i, item in enumerate(data):
+ if item[0] == 2:
+ value = item[1]
+ break
+ return item, value, i
+
+def get_layer(data):
+ """Expects object data as input.
+
+ Returns (entry, layer_name, entry_index) where entry is the data item that provided the layer name.
+ """
+ value = None
+ for i, item in enumerate(data):
+ if item[0] == 8:
+ value = item[1]
+ break
+ return item, value, i
+
+
+# type to object map
+type_map = {
+ 'line':Line,
+ 'lwpolyline':LWpolyline,
+ 'text':Text,
+ 'mtext':Mtext,
+ 'circle':Circle,
+ 'arc':Arc,
+ 'layer':Layer,
+ 'block_record':BlockRecord,
+ 'block':Block,
+ 'insert':Insert,
+ 'ellipse':Ellipse,
+ '3dface':Face
+}
+
+def objectify(data):
+ """Expects a section type object's data as input.
+
+ Maps object data to the correct object type.
+ """
+ objects = [] # colector for finished objects
+ known_types = type_map.keys() # so we don't have to call foo.keys() every iteration
+ index = 0
+ while index < len(data):
+ item = data[index]
+ if type(item) != list and item.type in known_types:
+ # proccess the object and append the resulting object
+ objects.append(type_map[item.type](item))
+ elif type(item) != list and item.type == 'table':
+ item.data = objectify(item.data) # tables have sub-objects
+ objects.append(item)
+ elif type(item) != list and item.type == 'polyline':
+ pline = Polyline(item)
+ while 1:
+ index += 1
+ item = data[index]
+ if item.type == 'vertex':
+ v = Vertex(item)
+ pline.points.append(v)
+ elif item.type == 'seqend':
+ break
+ else:
+ print "Error: non-vertex found before seqend!"
+ index -= 1
+ break
+ objects.append(pline)
+ else:
+ # we will just let the data pass un-harrased
+ objects.append(item)
+ index += 1
+ return objects
+if __name__ == "__main__":
+ print "No example yet!" \ No newline at end of file
diff --git a/release/scripts/export_cal3d.py b/release/scripts/export_cal3d.py
new file mode 100644
index 00000000000..990ac480e3d
--- /dev/null
+++ b/release/scripts/export_cal3d.py
@@ -0,0 +1,1112 @@
+#!BPY
+"""
+Name: 'Cal3D (.cfg .xaf .xsf .xmf .xrf)...'
+Blender: 243
+Group: 'Export'
+Tip: 'Export armature/bone/mesh/action data to the Cal3D format.'
+"""
+
+# export_cal3d.py
+# Copyright (C) 2003-2004 Jean-Baptiste LAMY -- jibalamy@free.fr
+# Copyright (C) 2004 Matthias Braun -- matze@braunis.de
+#
+# 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
+
+
+__version__ = '0.9f'
+__author__ = 'Jean-Baptiste, Jiba, Lamy, Campbell Barton (Ideasman42)'
+__email__ = ['Authors email, jibalamy:free*fr']
+__url__ = ['Soya3ds homepage, http://home.gna.org/oomadness/en/soya/', 'Cal3d, http://cal3d.sourceforge.net']
+__bpydoc__ =\
+'''This script is a Blender => Cal3D converter.
+(See http://blender.org and http://cal3d.sourceforge.net)
+
+USAGE:
+
+To install it, place the script in your $HOME/.blender/scripts directory.
+
+Then open the File->Export->Cal3d v0.9 menu. And select the filename of the .cfg file.
+The exporter will create a set of other files with same prefix (ie. bla.cfg, bla.xsf,
+bla_Action1.xaf, bla_Action2.xaf, ...).
+
+You should be able to open the .cfg file in cal3d_miniviewer.
+
+
+NOT (YET) SUPPORTED:
+
+ - Rotation, translation, or stretching Blender objects is still quite
+buggy, so AVOID MOVING / ROTATING / RESIZE OBJECTS (either mesh or armature) !
+Instead, edit the object (with tab), select all points / bones (with "a"),
+and move / rotate / resize them.<br>
+ - no support for exporting springs yet<br>
+ - no support for exporting material colors (most games should only use images
+I think...)
+
+
+KNOWN ISSUES:
+
+ - Cal3D versions <=0.9.1 have a bug where animations aren't played when the root bone
+is not animated;<br>
+ - Cal3D versions <=0.9.1 have a bug where objects that aren't influenced by any bones
+are not drawn (fixed in Cal3D CVS).
+
+
+NOTES:
+
+It requires a very recent version of Blender (>= 2.44).
+
+Build a model following a few rules:<br>
+ - Use only a single armature;<br>
+ - Use only a single rootbone (Cal3D doesn't support floating bones);<br>
+ - Use only locrot keys (Cal3D doesn't support bone's size change);<br>
+ - Don't try to create child/parent constructs in blender object, that gets exported
+incorrectly at the moment;<br>
+ - Objects or animations whose names start by "_" are not exported (hidden object).
+
+You can pass as many parameters as you want at the end, "EXPORT_FOR_SOYA=1" is just an
+example. The parameters are the same as below.
+'''
+
+# True (=1) to export for the Soya 3D engine
+# (http://oomadness.tuxfamily.org/en/soya).
+# (=> rotate meshes and skeletons so as X is right, Y is top and -Z is front)
+# EXPORT_FOR_SOYA = 0
+
+# Enables LODs computation. LODs computation is quite slow, and the algo is
+# surely not optimal :-(
+LODS = 0
+
+# Scale the model (not supported by Soya).
+
+# See also BASE_MATRIX below, if you want to rotate/scale/translate the model at
+# the exportation.
+
+#########################################################################################
+# Code starts here.
+# The script should be quite re-useable for writing another Blender animation exporter.
+# Most of the hell of it is to deal with Blender's head-tail-roll bone's definition.
+
+import math
+import Blender
+import BPyMesh
+import BPySys
+import BPyArmature
+import BPyObject
+import bpy
+
+def best_armature_root(armature):
+ '''
+ Find the armature root bone with the most children, return that bone
+ '''
+
+ bones = [bone for bone in armature.bones.values() if bone.hasChildren() == True]
+ if len(bones) == 1:
+ return bones[0]
+
+ # Get the best root since we have more then 1
+ bones = [(len(bone.getAllChildren()), bone) for bone in bones]
+ bones.sort()
+ return bones[-1][1] # bone with most children
+
+
+Vector = Blender.Mathutils.Vector
+Quaternion = Blender.Mathutils.Quaternion
+Matrix = Blender.Mathutils.Matrix
+
+# HACK -- it seems that some Blender versions don't define sys.argv,
+# which may crash Python if a warning occurs.
+# if not hasattr(sys, 'argv'): sys.argv = ['???']
+
+def matrix_multiply(b, a):
+ return [ [
+ a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0],
+ a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1],
+ a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2],
+ 0.0,
+ ], [
+ a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0],
+ a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1],
+ a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2],
+ 0.0,
+ ], [
+ a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0],
+ a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1],
+ a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2],
+ 0.0,
+ ], [
+ a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + b[3][0],
+ a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + b[3][1],
+ a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + b[3][2],
+ 1.0,
+ ] ]
+
+# multiplies 2 quaternions in x,y,z,w notation
+def quaternion_multiply(q1, q2):
+ return Quaternion(\
+ q2[3] * q1[0] + q2[0] * q1[3] + q2[1] * q1[2] - q2[2] * q1[1],
+ q2[3] * q1[1] + q2[1] * q1[3] + q2[2] * q1[0] - q2[0] * q1[2],
+ q2[3] * q1[2] + q2[2] * q1[3] + q2[0] * q1[1] - q2[1] * q1[0],
+ q2[3] * q1[3] - q2[0] * q1[0] - q2[1] * q1[1] - q2[2] * q1[2],\
+ )
+
+def matrix_translate(m, v):
+ m[3][0] += v[0]
+ m[3][1] += v[1]
+ m[3][2] += v[2]
+ return m
+
+def matrix2quaternion(m):
+ s = math.sqrt(abs(m[0][0] + m[1][1] + m[2][2] + m[3][3]))
+ if s == 0.0:
+ x = abs(m[2][1] - m[1][2])
+ y = abs(m[0][2] - m[2][0])
+ z = abs(m[1][0] - m[0][1])
+ if (x >= y) and (x >= z): return Quaternion(1.0, 0.0, 0.0, 0.0)
+ elif (y >= x) and (y >= z): return Quaternion(0.0, 1.0, 0.0, 0.0)
+ else: return Quaternion(0.0, 0.0, 1.0, 0.0)
+
+ q = Quaternion([
+ -(m[2][1] - m[1][2]) / (2.0 * s),
+ -(m[0][2] - m[2][0]) / (2.0 * s),
+ -(m[1][0] - m[0][1]) / (2.0 * s),
+ 0.5 * s,
+ ])
+ q.normalize()
+ #print q
+ return q
+
+def vector_by_matrix_3x3(p, m):
+ return [p[0] * m[0][0] + p[1] * m[1][0] + p[2] * m[2][0],
+ p[0] * m[0][1] + p[1] * m[1][1] + p[2] * m[2][1],
+ p[0] * m[0][2] + p[1] * m[1][2] + p[2] * m[2][2]]
+
+def vector_add(v1, v2):
+ return [v1[0]+v2[0], v1[1]+v2[1], v1[2]+v2[2]]
+
+def vector_sub(v1, v2):
+ return [v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]]
+
+def quaternion2matrix(q):
+ xx = q[0] * q[0]
+ yy = q[1] * q[1]
+ zz = q[2] * q[2]
+ xy = q[0] * q[1]
+ xz = q[0] * q[2]
+ yz = q[1] * q[2]
+ wx = q[3] * q[0]
+ wy = q[3] * q[1]
+ wz = q[3] * q[2]
+ return Matrix([1.0 - 2.0 * (yy + zz), 2.0 * (xy + wz), 2.0 * (xz - wy), 0.0],
+ [ 2.0 * (xy - wz), 1.0 - 2.0 * (xx + zz), 2.0 * (yz + wx), 0.0],
+ [ 2.0 * (xz + wy), 2.0 * (yz - wx), 1.0 - 2.0 * (xx + yy), 0.0],
+ [0.0 , 0.0 , 0.0 , 1.0])
+
+def matrix_invert(m):
+ det = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
+ - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
+ + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]))
+ if det == 0.0: return None
+ det = 1.0 / det
+ r = [ [
+ det * (m[1][1] * m[2][2] - m[2][1] * m[1][2]),
+ - det * (m[0][1] * m[2][2] - m[2][1] * m[0][2]),
+ det * (m[0][1] * m[1][2] - m[1][1] * m[0][2]),
+ 0.0,
+ ], [
+ - det * (m[1][0] * m[2][2] - m[2][0] * m[1][2]),
+ det * (m[0][0] * m[2][2] - m[2][0] * m[0][2]),
+ - det * (m[0][0] * m[1][2] - m[1][0] * m[0][2]),
+ 0.0
+ ], [
+ det * (m[1][0] * m[2][1] - m[2][0] * m[1][1]),
+ - det * (m[0][0] * m[2][1] - m[2][0] * m[0][1]),
+ det * (m[0][0] * m[1][1] - m[1][0] * m[0][1]),
+ 0.0,
+ ] ]
+ r.append([
+ -(m[3][0] * r[0][0] + m[3][1] * r[1][0] + m[3][2] * r[2][0]),
+ -(m[3][0] * r[0][1] + m[3][1] * r[1][1] + m[3][2] * r[2][1]),
+ -(m[3][0] * r[0][2] + m[3][1] * r[1][2] + m[3][2] * r[2][2]),
+ 1.0,
+ ])
+ return r
+
+
+def point_by_matrix(p, m):
+ return [p[0] * m[0][0] + p[1] * m[1][0] + p[2] * m[2][0] + m[3][0],
+ p[0] * m[0][1] + p[1] * m[1][1] + p[2] * m[2][1] + m[3][1],
+ p[0] * m[0][2] + p[1] * m[1][2] + p[2] * m[2][2] + m[3][2]]
+
+# Hack for having the model rotated right.
+# Put in BASE_MATRIX your own rotation if you need some.
+
+BASE_MATRIX = None
+
+
+# Cal3D data structures
+
+CAL3D_VERSION = 910
+MATERIALS = {} # keys are (mat.name, img.name)
+
+class Cal3DMaterial(object):
+ __slots__ = 'amb', 'diff', 'spec', 'shininess', 'maps_filenames', 'id'
+ def __init__(self, blend_world, blend_material, blend_images):
+
+ # Material Settings
+ if blend_world: amb = [ int(c*255) for c in blend_world.amb ]
+ else: amb = [0,0,0] # Default value
+
+ if blend_material:
+ self.amb = tuple([int(c*blend_material.amb) for c in amb] + [255])
+ self.diff = tuple([int(c*255) for c in blend_material.rgbCol] + [int(blend_material.alpha*255)])
+ self.spec = tuple([int(c*255) for c in blend_material.rgbCol] + [int(blend_material.alpha*255)])
+ self.shininess = (float(blend_material.hard)-1)/5.10
+ else:
+ self.amb = tuple(amb + [255])
+ self.diff = (255,255,255,255)
+ self.spec = (255,255,255,255)
+ self.shininess = 1.0
+
+ self.maps_filenames = []
+ for image in blend_images:
+ if image:
+ self.maps_filenames.append( image.filename.split('\\')[-1].split('/')[-1] )
+
+ self.id = len(MATERIALS)
+ MATERIALS[blend_material, blend_images] = self
+
+ # new xml format
+ def writeCal3D(self, file):
+ file.write('<?xml version="1.0"?>\n')
+ file.write('<HEADER MAGIC="XRF" VERSION="%i"/>\n' % CAL3D_VERSION)
+ file.write('<MATERIAL NUMMAPS="%s">\n' % len(self.maps_filenames))
+ file.write('\t<AMBIENT>%i %i %i %i</AMBIENT>\n' % self.amb)
+ file.write('\t<DIFFUSE>%i %i %i %i</DIFFUSE>\n' % self.diff)
+ file.write('\t<SPECULAR>%i %i %i %i</SPECULAR>\n' % self.spec)
+ file.write('\t<SHININESS>%.6f</SHININESS>\n' % self.shininess)
+
+ for map_filename in self.maps_filenames:
+ file.write('\t<MAP>%s</MAP>\n' % map_filename)
+
+ file.write('</MATERIAL>\n')
+
+
+class Cal3DMesh(object):
+ __slots__ = 'name', 'submeshes', 'matrix', 'matrix_normal'
+ def __init__(self, ob, blend_mesh, blend_world):
+ self.name = ob.name
+ self.submeshes = []
+
+ BPyMesh.meshCalcNormals(blend_mesh)
+
+ self.matrix = ob.matrixWorld
+ self.matrix_normal = self.matrix.copy().rotationPart()
+
+ #if BASE_MATRIX:
+ # matrix = matrix_multiply(BASE_MATRIX, matrix)
+
+ face_groups = {}
+ blend_materials = blend_mesh.materials
+ uvlayers = ()
+ mat = None # incase we have no materials
+ if blend_mesh.faceUV:
+ uvlayers = blend_mesh.getUVLayerNames()
+ if len(uvlayers) == 1:
+ for f in blend_mesh.faces:
+ image = (f.image,) # bit in a tuple so we can match multi UV code
+ if blend_materials: mat = blend_materials[f.mat] # if no materials, mat will always be None
+ face_groups.setdefault( (mat,image), (mat,image,[]) )[2].append( f )
+ else:
+ # Multi UV's
+ face_multi_images = [[] for i in xrange(len(blend_mesh.faces))]
+ face_multi_uvs = [[[] for i in xrange(len(f)) ] for f in blend_mesh.faces]
+ for uvlayer in uvlayers:
+ blend_mesh.activeUVLayer = uvlayer
+ for i, f in enumerate(blend_mesh.faces):
+ face_multi_images[i].append(f.image)
+ if f.image:
+ for j, uv in enumerate(f.uv):
+ face_multi_uvs[i][j].append( tuple(uv) )
+
+ # Convert UV's to tuples so they can be compared with eachother
+ # when creating new verts
+ for fuv in face_multi_uvs:
+ for i, uv in enumerate(fuv):
+ fuv[i] = tuple(uv)
+
+ for i, f in enumerate(blend_mesh.faces):
+ image = tuple(face_multi_images[i])
+ if blend_materials: mat = blend_materials[f.mat]
+ face_groups.setdefault( (mat,image), (mat,image,[]) )[2].append( f )
+ else:
+ # No UV's
+ for f in blend_mesh.faces:
+ if blend_materials: mat = blend_materials[f.mat]
+ face_groups.setdefault( (mat,()), (mat,(),[]) )[2].append( f )
+
+ for blend_material, blend_images, faces in face_groups.itervalues():
+
+ try: material = MATERIALS[blend_material, blend_images]
+ except: material = MATERIALS[blend_material, blend_images] = Cal3DMaterial(blend_world, blend_material, blend_images)
+
+ submesh = Cal3DSubMesh(self, material, len(self.submeshes))
+ self.submeshes.append(submesh)
+
+ # Check weather we need to write UVs, dont do it if theres no image
+ # Multilayer UV's have alredy checked that they have images when
+ # building face_multi_uvs
+ if len(uvlayers) == 1:
+ if blend_images == (None,):
+ write_single_layer_uvs = False
+ else:
+ write_single_layer_uvs = True
+
+
+ for face in faces:
+
+ if not face.smooth:
+ normal = face.no
+
+ face_vertices = []
+ face_v = face.v
+
+
+ if len(uvlayers)>1:
+ for i, blend_vert in enumerate(face_v):
+ if face.smooth: normal = blend_vert.no
+ vertex = submesh.getVertex(blend_mesh, blend_vert, normal, face_multi_uvs[face.index][i])
+ face_vertices.append(vertex)
+
+ elif len(uvlayers)==1:
+ if write_single_layer_uvs:
+ face_uv = face.uv
+
+ for i, blend_vert in enumerate(face_v):
+ if face.smooth: normal = blend_vert.no
+ if write_single_layer_uvs: uvs = (tuple(face_uv[i]),)
+ else: uvs = ()
+
+ vertex = submesh.getVertex(blend_mesh, blend_vert, normal, uvs )
+ face_vertices.append(vertex)
+ else:
+ # No UVs
+ for i, blend_vert in enumerate(face_v):
+ if face.smooth: normal = blend_vert.no
+ vertex = submesh.getVertex(blend_mesh, blend_vert, normal, () )
+ face_vertices.append(vertex)
+
+
+ # Split faces with more than 3 vertices
+ for i in xrange(1, len(face) - 1):
+ submesh.faces.append(Cal3DFace(face_vertices[0], face_vertices[i], face_vertices[i + 1]))
+
+ def writeCal3D(self, file):
+ file.write('<?xml version="1.0"?>\n')
+ file.write('<HEADER MAGIC="XMF" VERSION="%i"/>\n' % CAL3D_VERSION)
+ file.write('<MESH NUMSUBMESH="%i">\n' % len(self.submeshes))
+ for submesh in self.submeshes:
+ submesh.writeCal3D(file, self.matrix, self.matrix_normal)
+ file.write('</MESH>\n')
+
+
+class Cal3DSubMesh(object):
+ __slots__ = 'material', 'vertices', 'vert_mapping', 'vert_count', 'faces', 'nb_lodsteps', 'springs', 'id'
+ def __init__(self, mesh, material, id):
+ self.material = material
+ self.vertices = []
+ self.vert_mapping = {} # map original indicies to local
+ self.vert_count = 0
+ self.faces = []
+ self.nb_lodsteps = 0
+ self.springs = []
+ self.id = id
+
+ def getVertex(self, blend_mesh, blend_vert, normal, maps):
+ '''
+ Request a vertex, and create a new one or return a matching vertex
+ '''
+ blend_index = blend_vert.index
+ index_map = self.vert_mapping.get(blend_index)
+
+ if index_map == None:
+ vertex = Cal3DVertex(blend_vert.co, normal, maps, blend_mesh.getVertexInfluences(blend_index))
+ self.vertices.append([vertex])
+ self.vert_mapping[blend_index] = len(self.vert_mapping)
+ self.vert_count +=1
+ return vertex
+ else:
+ vertex_list = self.vertices[index_map]
+
+ for v in vertex_list:
+ if v.normal == normal and\
+ v.maps == maps:
+ return v # reusing
+
+ # No match, add a new vert
+ # Use the first verts influences
+ vertex = Cal3DVertex(blend_vert.co, normal, maps, vertex_list[0].influences)
+ vertex_list.append(vertex)
+ # self.vert_mapping[blend_index] = len(self.vert_mapping)
+ self.vert_count +=1
+ return vertex
+
+
+ def compute_lods(self):
+ '''Computes LODs info for Cal3D (there's no Blender related stuff here).'''
+
+ print 'Start LODs computation...'
+ vertex2faces = {}
+ for face in self.faces:
+ for vertex in (face.vertex1, face.vertex2, face.vertex3):
+ l = vertex2faces.get(vertex)
+ if not l: vertex2faces[vertex] = [face]
+ else: l.append(face)
+
+ couple_treated = {}
+ couple_collapse_factor = []
+ for face in self.faces:
+ for a, b in ((face.vertex1, face.vertex2), (face.vertex1, face.vertex3), (face.vertex2, face.vertex3)):
+ a = a.cloned_from or a
+ b = b.cloned_from or b
+ if a.id > b.id: a, b = b, a
+ if not couple_treated.has_key((a, b)):
+ # The collapse factor is simply the distance between the 2 points :-(
+ # This should be improved !!
+ if vector_dotproduct(a.normal, b.normal) < 0.9: continue
+ couple_collapse_factor.append((point_distance(a.loc, b.loc), a, b))
+ couple_treated[a, b] = 1
+
+ couple_collapse_factor.sort()
+
+ collapsed = {}
+ new_vertices = []
+ new_faces = []
+ for factor, v1, v2 in couple_collapse_factor:
+ # Determines if v1 collapses to v2 or v2 to v1.
+ # We choose to keep the vertex which is on the smaller number of faces, since
+ # this one has more chance of being in an extrimity of the body.
+ # Though heuristic, this rule yields very good results in practice.
+ if len(vertex2faces[v1]) < len(vertex2faces[v2]): v2, v1 = v1, v2
+ elif len(vertex2faces[v1]) == len(vertex2faces[v2]):
+ if collapsed.get(v1, 0): v2, v1 = v1, v2 # v1 already collapsed, try v2
+
+ if (not collapsed.get(v1, 0)) and (not collapsed.get(v2, 0)):
+ collapsed[v1] = 1
+ collapsed[v2] = 1
+
+ # Check if v2 is already colapsed
+ while v2.collapse_to: v2 = v2.collapse_to
+
+ common_faces = filter(vertex2faces[v1].__contains__, vertex2faces[v2])
+
+ v1.collapse_to = v2
+ v1.face_collapse_count = len(common_faces)
+
+ for clone in v1.clones:
+ # Find the clone of v2 that correspond to this clone of v1
+ possibles = []
+ for face in vertex2faces[clone]:
+ possibles.append(face.vertex1)
+ possibles.append(face.vertex2)
+ possibles.append(face.vertex3)
+ clone.collapse_to = v2
+ for vertex in v2.clones:
+ if vertex in possibles:
+ clone.collapse_to = vertex
+ break
+
+ clone.face_collapse_count = 0
+ new_vertices.append(clone)
+
+ # HACK -- all faces get collapsed with v1 (and no faces are collapsed with v1's
+ # clones). This is why we add v1 in new_vertices after v1's clones.
+ # This hack has no other incidence that consuming a little few memory for the
+ # extra faces if some v1's clone are collapsed but v1 is not.
+ new_vertices.append(v1)
+
+ self.nb_lodsteps += 1 + len(v1.clones)
+
+ new_faces.extend(common_faces)
+ for face in common_faces:
+ face.can_collapse = 1
+
+ # Updates vertex2faces
+ vertex2faces[face.vertex1].remove(face)
+ vertex2faces[face.vertex2].remove(face)
+ vertex2faces[face.vertex3].remove(face)
+ vertex2faces[v2].extend(vertex2faces[v1])
+
+ new_vertices.extend(filter(lambda vertex: not vertex.collapse_to, self.vertices))
+ new_vertices.reverse() # Cal3D want LODed vertices at the end
+ for i in xrange(len(new_vertices)): new_vertices[i].id = i
+ self.vertices = new_vertices
+
+ new_faces.extend(filter(lambda face: not face.can_collapse, self.faces))
+ new_faces.reverse() # Cal3D want LODed faces at the end
+ self.faces = new_faces
+
+ print 'LODs computed : %s vertices can be removed (from a total of %s).' % (self.nb_lodsteps, len(self.vertices))
+
+
+ def writeCal3D(self, file, matrix, matrix_normal):
+
+ file.write('\t<SUBMESH NUMVERTICES="%i" NUMFACES="%i" MATERIAL="%i" ' % \
+ (self.vert_count, len(self.faces), self.material.id))
+ file.write('NUMLODSTEPS="%i" NUMSPRINGS="%i" NUMTEXCOORDS="%i">\n' % \
+ (self.nb_lodsteps, len(self.springs),
+ len(self.material.maps_filenames)))
+
+ i = 0
+ for v in self.vertices:
+ for item in v:
+ item.id = i
+ item.writeCal3D(file, matrix, matrix_normal)
+ i += 1
+
+ for item in self.springs:
+ item.writeCal3D(file)
+ for item in self.faces:
+ item.writeCal3D(file)
+
+ file.write('\t</SUBMESH>\n')
+
+class Cal3DVertex(object):
+ __slots__ = 'loc','normal','collapse_to','face_collapse_count','maps','influences','weight','cloned_from','clones','id'
+ def __init__(self, loc, normal, maps, blend_influences):
+ self.loc = loc
+ self.normal = normal
+ self.collapse_to = None
+ self.face_collapse_count = 0
+ self.maps = maps
+ self.weight = None
+
+ self.cloned_from = None
+ self.clones = []
+
+ self.id = -1
+
+ if len(blend_influences) == 0 or isinstance(blend_influences[0], Cal3DInfluence):
+ # This is a copy from another vert
+ self.influences = blend_influences
+ else:
+ # Pass the blender influences
+
+ self.influences = []
+ # should this really be a warning? (well currently enabled,
+ # because blender has some bugs where it doesn't return
+ # influences in python api though they are set, and because
+ # cal3d<=0.9.1 had bugs where objects without influences
+ # aren't drawn.
+ #if not blend_influences:
+ # print 'A vertex of object "%s" has no influences.\n(This occurs on objects placed in an invisible layer, you can fix it by using a single layer)' % ob.name
+
+ # sum of influences is not always 1.0 in Blender ?!?!
+ sum = 0.0
+
+ for bone_name, weight in blend_influences:
+ sum += weight
+
+ for bone_name, weight in blend_influences:
+ bone = BONES.get(bone_name)
+ if not bone: # keys
+ # print 'Couldnt find bone "%s" which influences object "%s"' % (bone_name, ob.name)
+ continue
+
+ if weight:
+ self.influences.append(Cal3DInfluence(bone, weight / sum))
+
+
+ def writeCal3D(self, file, matrix, matrix_normal):
+ if self.collapse_to:
+ collapse_id = self.collapse_to.id
+ else:
+ collapse_id = -1
+ file.write('\t\t<VERTEX ID="%i" NUMINFLUENCES="%i">\n' % \
+ (self.id, len(self.influences)))
+ file.write('\t\t\t<POS>%.6f %.6f %.6f</POS>\n' % tuple(self.loc*matrix))
+ file.write('\t\t\t<NORM>%.6f %.6f %.6f</NORM>\n' % tuple( (self.normal*matrix_normal).normalize() ))
+ if collapse_id != -1:
+ file.write('\t\t\t<COLLAPSEID>%i</COLLAPSEID>\n' % collapse_id)
+ file.write('\t\t\t<COLLAPSECOUNT>%i</COLLAPSECOUNT>\n' % \
+ self.face_collapse_count)
+
+ for uv in self.maps:
+ # we cant have more UV's then our materials image maps
+ # check for this
+ file.write('\t\t\t<TEXCOORD>%.6f %.6f</TEXCOORD>\n' % uv)
+
+ for item in self.influences:
+ item.writeCal3D(file)
+
+ if self.weight != None:
+ file.write('\t\t\t<PHYSIQUE>%.6f</PHYSIQUE>\n' % len(self.weight))
+ file.write('\t\t</VERTEX>\n')
+
+class Cal3DInfluence(object):
+ __slots__ = 'bone', 'weight'
+ def __init__(self, bone, weight):
+ self.bone = bone
+ self.weight = weight
+
+ def writeCal3D(self, file):
+ file.write('\t\t\t<INFLUENCE ID="%i">%.6f</INFLUENCE>\n' % \
+ (self.bone.id, self.weight))
+
+class Cal3DSpring(object):
+ __slots__ = 'vertex1', 'vertex2', 'spring_coefficient', 'idlelength'
+ def __init__(self, vertex1, vertex2):
+ self.vertex1 = vertex1
+ self.vertex2 = vertex2
+ self.spring_coefficient = 0.0
+ self.idlelength = 0.0
+
+ def writeCal3D(self, file):
+ file.write('\t\t<SPRING VERTEXID="%i %i" COEF="%.6f" LENGTH="%.6f"/>\n' % \
+ (self.vertex1.id, self.vertex2.id, self.spring_coefficient, self.idlelength))
+
+class Cal3DFace(object):
+ __slots__ = 'vertex1', 'vertex2', 'vertex3', 'can_collapse',
+ def __init__(self, vertex1, vertex2, vertex3):
+ self.vertex1 = vertex1
+ self.vertex2 = vertex2
+ self.vertex3 = vertex3
+ self.can_collapse = 0
+
+ def writeCal3D(self, file):
+ file.write('\t\t<FACE VERTEXID="%i %i %i"/>\n' % \
+ (self.vertex1.id, self.vertex2.id, self.vertex3.id))
+
+class Cal3DSkeleton(object):
+ __slots__ = 'bones'
+ def __init__(self):
+ self.bones = []
+
+ def writeCal3D(self, file):
+ file.write('<?xml version="1.0"?>\n')
+ file.write('<HEADER MAGIC="XSF" VERSION="%i"/>\n' % CAL3D_VERSION)
+ file.write('<SKELETON NUMBONES="%i">\n' % len(self.bones))
+ for item in self.bones:
+ item.writeCal3D(file)
+
+ file.write('</SKELETON>\n')
+
+BONES = {}
+POSEBONES= {}
+class Cal3DBone(object):
+ __slots__ = 'head', 'tail', 'name', 'cal3d_parent', 'loc', 'quat', 'children', 'matrix', 'lloc', 'lquat', 'id'
+ def __init__(self, skeleton, blend_bone, arm_matrix, cal3d_parent=None):
+
+ # def treat_bone(b, parent = None):
+ head = blend_bone.head['BONESPACE']
+ tail = blend_bone.tail['BONESPACE']
+ #print parent.quat
+ # Turns the Blender's head-tail-roll notation into a quaternion
+ #quat = matrix2quaternion(blender_bone2matrix(head, tail, blend_bone.roll['BONESPACE']))
+ quat = matrix2quaternion(blend_bone.matrix['BONESPACE'].copy().resize4x4())
+
+ # Pose location
+ ploc = POSEBONES[blend_bone.name].loc
+
+ if cal3d_parent:
+ # Compute the translation from the parent bone's head to the child
+ # bone's head, in the parent bone coordinate system.
+ # The translation is parent_tail - parent_head + child_head,
+ # but parent_tail and parent_head must be converted from the parent's parent
+ # system coordinate into the parent system coordinate.
+
+ parent_invert_transform = matrix_invert(quaternion2matrix(cal3d_parent.quat))
+ parent_head = vector_by_matrix_3x3(cal3d_parent.head, parent_invert_transform)
+ parent_tail = vector_by_matrix_3x3(cal3d_parent.tail, parent_invert_transform)
+ ploc = vector_add(ploc, blend_bone.head['BONESPACE'])
+
+ # EDIT!!! FIX BONE OFFSET BE CAREFULL OF THIS PART!!! ??
+ #diff = vector_by_matrix_3x3(head, parent_invert_transform)
+ parent_tail= vector_add(parent_tail, head)
+ # DONE!!!
+
+ parentheadtotail = vector_sub(parent_tail, parent_head)
+ # hmm this should be handled by the IPos, but isn't for non-animated
+ # bones which are transformed in the pose mode...
+ loc = parentheadtotail
+
+ else:
+ # Apply the armature's matrix to the root bones
+ head = point_by_matrix(head, arm_matrix)
+ tail = point_by_matrix(tail, arm_matrix)
+
+ loc = head
+ quat = matrix2quaternion(matrix_multiply(arm_matrix, quaternion2matrix(quat))) # Probably not optimal
+
+ self.head = head
+ self.tail = tail
+
+ self.cal3d_parent = cal3d_parent
+ self.name = blend_bone.name
+ self.loc = loc
+ self.quat = quat
+ self.children = []
+
+ self.matrix = matrix_translate(quaternion2matrix(quat), loc)
+ if cal3d_parent:
+ self.matrix = matrix_multiply(cal3d_parent.matrix, self.matrix)
+
+ # lloc and lquat are the bone => model space transformation (translation and rotation).
+ # They are probably specific to Cal3D.
+ m = matrix_invert(self.matrix)
+ self.lloc = m[3][0], m[3][1], m[3][2]
+ self.lquat = matrix2quaternion(m)
+
+ self.id = len(skeleton.bones)
+ skeleton.bones.append(self)
+ BONES[self.name] = self
+
+ if not blend_bone.hasChildren(): return
+ for blend_child in blend_bone.children:
+ self.children.append(Cal3DBone(skeleton, blend_child, arm_matrix, self))
+
+
+ def writeCal3D(self, file):
+ file.write('\t<BONE ID="%i" NAME="%s" NUMCHILD="%i">\n' % \
+ (self.id, self.name, len(self.children)))
+ # We need to negate quaternion W value, but why ?
+ file.write('\t\t<TRANSLATION>%.6f %.6f %.6f</TRANSLATION>\n' % \
+ (self.loc[0], self.loc[1], self.loc[2]))
+ file.write('\t\t<ROTATION>%.6f %.6f %.6f %.6f</ROTATION>\n' % \
+ (self.quat[0], self.quat[1], self.quat[2], -self.quat[3]))
+ file.write('\t\t<LOCALTRANSLATION>%.6f %.6f %.6f</LOCALTRANSLATION>\n' % \
+ (self.lloc[0], self.lloc[1], self.lloc[2]))
+ file.write('\t\t<LOCALROTATION>%.6f %.6f %.6f %.6f</LOCALROTATION>\n' % \
+ (self.lquat[0], self.lquat[1], self.lquat[2], -self.lquat[3]))
+ if self.cal3d_parent:
+ file.write('\t\t<PARENTID>%i</PARENTID>\n' % self.cal3d_parent.id)
+ else:
+ file.write('\t\t<PARENTID>%i</PARENTID>\n' % -1)
+
+ for item in self.children:
+ file.write('\t\t<CHILDID>%i</CHILDID>\n' % item.id)
+
+ file.write('\t</BONE>\n')
+
+class Cal3DAnimation:
+ def __init__(self, name, duration = 0.0):
+ self.name = name
+ self.duration = duration
+ self.tracks = {} # Map bone names to tracks
+
+ def writeCal3D(self, file):
+ file.write('<?xml version="1.0"?>\n')
+ file.write('<HEADER MAGIC="XAF" VERSION="%i"/>\n' % CAL3D_VERSION)
+ file.write('<ANIMATION DURATION="%.6f" NUMTRACKS="%i">\n' % \
+ (self.duration, len(self.tracks)))
+
+ for item in self.tracks.itervalues():
+ item.writeCal3D(file)
+
+ file.write('</ANIMATION>\n')
+
+class Cal3DTrack(object):
+ __slots__ = 'bone', 'keyframes'
+ def __init__(self, bone):
+ self.bone = bone
+ self.keyframes = []
+
+ def writeCal3D(self, file):
+ file.write('\t<TRACK BONEID="%i" NUMKEYFRAMES="%i">\n' %
+ (self.bone.id, len(self.keyframes)))
+ for item in self.keyframes:
+ item.writeCal3D(file)
+ file.write('\t</TRACK>\n')
+
+class Cal3DKeyFrame(object):
+ __slots__ = 'time', 'loc', 'quat'
+ def __init__(self, time, loc, quat):
+ self.time = time
+ self.loc = loc
+ self.quat = quat
+
+ def writeCal3D(self, file):
+ file.write('\t\t<KEYFRAME TIME="%.6f">\n' % self.time)
+ file.write('\t\t\t<TRANSLATION>%.6f %.6f %.6f</TRANSLATION>\n' % \
+ (self.loc[0], self.loc[1], self.loc[2]))
+ # We need to negate quaternion W value, but why ?
+ file.write('\t\t\t<ROTATION>%.6f %.6f %.6f %.6f</ROTATION>\n' % \
+ (self.quat[0], self.quat[1], self.quat[2], -self.quat[3]))
+ file.write('\t\t</KEYFRAME>\n')
+
+def export_cal3d(filename, PREF_SCALE=0.1, PREF_BAKE_MOTION = True, PREF_ACT_ACTION_ONLY=True, PREF_SCENE_FRAMES=False):
+ if not filename.endswith('.cfg'):
+ filename += '.cfg'
+
+ file_only = filename.split('/')[-1].split('\\')[-1]
+ file_only_noext = file_only.split('.')[0]
+ base_only = filename[:-len(file_only)]
+
+ def new_name(dataname, ext):
+ return file_only_noext + '_' + BPySys.cleanName(dataname) + ext
+
+ #if EXPORT_FOR_SOYA:
+ # global BASE_MATRIX
+ # BASE_MATRIX = matrix_rotate_x(-math.pi / 2.0)
+ # Get the sce
+
+ sce = bpy.data.scenes.active
+ blend_world = sce.world
+ # ---- Export skeleton (armature) ----------------------------------------
+
+ skeleton = Cal3DSkeleton()
+ blender_armature = [ob for ob in sce.objects.context if ob.type == 'Armature']
+ if len(blender_armature) > 1: print "Found multiple armatures! using ",armatures[0].name
+ if blender_armature: blender_armature = blender_armature[0]
+ else:
+ # Try find a meshes armature
+ for ob in sce.objects.context:
+ blender_armature = BPyObject.getObjectArmature(ob)
+ if blender_armature:
+ break
+
+ if not blender_armature:
+ Blender.Draw.PupMenu('Aborting%t|No Armature in selection')
+ return
+
+ # we need pose bone locations
+ for pbone in blender_armature.getPose().bones.values():
+ POSEBONES[pbone.name] = pbone
+
+ Cal3DBone(skeleton, best_armature_root(blender_armature.getData()), blender_armature.matrixWorld)
+
+ # ---- Export Mesh data ---------------------------------------------------
+ meshes = []
+ for ob in sce.objects.context:
+ if ob.type != 'Mesh': continue
+ blend_mesh = ob.getData(mesh=1)
+
+ if not blend_mesh.faces: continue
+ meshes.append( Cal3DMesh(ob, blend_mesh, blend_world) )
+
+ # ---- Export animations --------------------------------------------------
+ backup_action = blender_armature.action
+
+ ANIMATIONS = []
+ SUPPORTED_IPOS = 'QuatW', 'QuatX', 'QuatY', 'QuatZ', 'LocX', 'LocY', 'LocZ'
+
+ if PREF_ACT_ACTION_ONLY: action_items = [(blender_armature.action.name, blender_armature.action)]
+ else: action_items = Blender.Armature.NLA.GetActions().items()
+
+ print len(action_items), 'action_items'
+
+ for animation_name, blend_action in action_items:
+
+ # get frame range
+ if PREF_SCENE_FRAMES:
+ action_start= Blender.Get('staframe')
+ action_end= Blender.Get('endframe')
+ else:
+ _frames = blend_action.getFrameNumbers()
+ action_start= min(_frames);
+ action_end= max(_frames);
+ del _frames
+
+ blender_armature.action = blend_action
+
+ if PREF_BAKE_MOTION:
+ # We need to set the action active if we are getting baked data
+ pose_data = BPyArmature.getBakedPoseData(blender_armature, action_start, action_end)
+
+ # Fake, all we need is bone names
+ blend_action_ipos_items = [(pbone, True) for pbone in POSEBONES.iterkeys()]
+ else:
+ # real (bone_name, ipo) pairs
+ blend_action_ipos_items = blend_action.getAllChannelIpos().items()
+
+ # Now we mau have some bones with no channels, easiest to add their names and an empty list here
+ # this way they are exported with dummy keyfraames at teh first used frame
+ action_bone_names = [name for name, ipo in blend_action_ipos_items]
+ for bone_name in BONES: # iterkeys
+ if bone_name not in action_bone_names:
+ blend_action_ipos_items.append( (bone_name, []) )
+
+ animation = Cal3DAnimation(animation_name)
+ # ----------------------------
+ ANIMATIONS.append(animation)
+ animation.duration = 0.0
+
+ for bone_name, ipo in blend_action_ipos_items:
+ # Baked bones may have no IPO's width motion still
+ if bone_name not in BONES:
+ print '\tNo Bone "' + bone_name + '" in (from Animation "' + animation_name + '") ?!?'
+ continue
+
+ # So we can loop without errors
+ if ipo==None: ipo = []
+
+ bone = BONES[bone_name]
+ track = animation.tracks[bone_name] = Cal3DTrack(bone)
+
+ if PREF_BAKE_MOTION:
+ for i in xrange(action_end - action_start):
+ cal3dtime = i / 25.0 # assume 25FPS by default
+
+ if cal3dtime > animation.duration:
+ animation.duration = cal3dtime
+
+ #print pose_data[i][bone_name], i
+ loc, quat = pose_data[i][bone_name]
+
+ loc = vector_by_matrix_3x3(loc, bone.matrix)
+ loc = vector_add(bone.loc, loc)
+ quat = quaternion_multiply(quat, bone.quat)
+ quat = Quaternion(quat)
+
+ quat.normalize()
+ quat = tuple(quat)
+
+ track.keyframes.append( Cal3DKeyFrame(cal3dtime, loc, quat) )
+
+ else:
+ #run 1: we need to find all time values where we need to produce keyframes
+ times = set()
+ for curve in ipo:
+ curve_name = curve.name
+ if curve_name in SUPPORTED_IPOS:
+ for p in curve.bezierPoints:
+ times.add( p.pt[0] )
+
+ times = list(times)
+ times.sort()
+
+ # Incase we have no keys here or ipo==None
+ if not times: times.append(action_start)
+
+ # run2: now create keyframes
+ for time in times:
+ cal3dtime = (time-1) / 25.0 # assume 25FPS by default
+ if cal3dtime > animation.duration:
+ animation.duration = cal3dtime
+
+ trans = Vector()
+ quat = Quaternion()
+
+ for curve in ipo:
+ val = curve.evaluate(time)
+ # val = 0.0
+ curve_name= curve.name
+ if curve_name == 'LocX': trans[0] = val
+ elif curve_name == 'LocY': trans[1] = val
+ elif curve_name == 'LocZ': trans[2] = val
+ elif curve_name == 'QuatW': quat[3] = val
+ elif curve_name == 'QuatX': quat[0] = val
+ elif curve_name == 'QuatY': quat[1] = val
+ elif curve_name == 'QuatZ': quat[2] = val
+
+ transt = vector_by_matrix_3x3(trans, bone.matrix)
+ loc = vector_add(bone.loc, transt)
+ quat = quaternion_multiply(quat, bone.quat)
+ quat = Quaternion(quat)
+
+ quat.normalize()
+ quat = tuple(quat)
+
+ track.keyframes.append( Cal3DKeyFrame(cal3dtime, loc, quat) )
+
+
+ if animation.duration <= 0:
+ print 'Ignoring Animation "' + animation_name + '": duration is 0.\n'
+ continue
+
+ # Restore the original armature
+ blender_armature.action = backup_action
+ # ------------------------------------- End Animation
+
+
+
+ cfg = open((filename), 'wb')
+ cfg.write('# Cal3D model exported from Blender with export_cal3d.py\n# from %s\n' % Blender.Get('filename'))
+
+ if PREF_SCALE != 1.0: cfg.write('scale=%.6f\n' % PREF_SCALE)
+
+ fname = file_only_noext + '.xsf'
+ file = open( base_only + fname, 'wb')
+ skeleton.writeCal3D(file)
+ file.close()
+
+ cfg.write('skeleton=%s\n' % fname)
+
+ for animation in ANIMATIONS:
+ if not animation.name.startswith('_'):
+ if animation.duration > 0.1: # Cal3D does not support animation with only one state
+ fname = new_name(animation.name, '.xaf')
+ file = open(base_only + fname, 'wb')
+ animation.writeCal3D(file)
+ file.close()
+ cfg.write('animation=%s\n' % fname)
+
+ for mesh in meshes:
+ if not mesh.name.startswith('_'):
+ fname = new_name(mesh.name, '.xmf')
+ file = open(base_only + fname, 'wb')
+ mesh.writeCal3D(file)
+ file.close()
+
+ cfg.write('mesh=%s\n' % fname)
+
+ materials = MATERIALS.values()
+ materials.sort(key = lambda a: a.id)
+ for material in materials:
+ # Just number materials, its less trouble
+ fname = new_name(str(material.id), '.xrf')
+
+ file = open(base_only + fname, 'wb')
+ material.writeCal3D(file)
+ file.close()
+
+ cfg.write('material=%s\n' % fname)
+
+ print 'Cal3D Saved to "%s.cfg"' % file_only_noext
+
+ # Warnings
+ if len(animation.tracks) < 2:
+ Blender.Draw.PupMenu('Warning, the armature has less then 2 tracks, file may not load in Cal3d')
+
+
+def export_cal3d_ui(filename):
+
+ PREF_SCALE= Blender.Draw.Create(1.0)
+ PREF_BAKE_MOTION = Blender.Draw.Create(1)
+ PREF_ACT_ACTION_ONLY= Blender.Draw.Create(1)
+ PREF_SCENE_FRAMES= Blender.Draw.Create(0)
+
+ block = [\
+ ('Scale: ', PREF_SCALE, 0.01, 100, 'The scale to set in the Cal3d .cfg file (unsupported by soya)'),\
+ ('Baked Motion', PREF_BAKE_MOTION, 'use final pose position instead of ipo keyframes (IK and constraint support)'),\
+ ('Active Action', PREF_ACT_ACTION_ONLY, 'Only export action applied to this armature, else export all actions.'),\
+ ('Scene Frames', PREF_SCENE_FRAMES, 'Use scene frame range, else the actions start/end'),\
+ ]
+
+ if not Blender.Draw.PupBlock('Cal3D Options', block):
+ return
+
+ Blender.Window.WaitCursor(1)
+ export_cal3d(filename, 1.0/PREF_SCALE.val, PREF_BAKE_MOTION.val, PREF_ACT_ACTION_ONLY.val, PREF_SCENE_FRAMES.val)
+ Blender.Window.WaitCursor(0)
+
+
+#import os
+if __name__ == '__main__':
+ Blender.Window.FileSelector(export_cal3d_ui, 'Cal3D Export', Blender.Get('filename').replace('.blend', '.cfg'))
+ #export_cal3d('/cally/data/skeleton/skeleton' + '.cfg', 1.0, True, False, False)
+ #export_cal3d('/test' + '.cfg')
+ #export_cal3d_ui('/test' + '.cfg')
+ #os.system('cd /; wine /cal3d_miniviewer.exe /skeleton.cfg')
+ #os.system('cd /cally/;wine cally')
diff --git a/release/scripts/uv_from_adjacent.py b/release/scripts/uv_from_adjacent.py
new file mode 100644
index 00000000000..dfdad3118d9
--- /dev/null
+++ b/release/scripts/uv_from_adjacent.py
@@ -0,0 +1,129 @@
+#!BPY
+"""
+Name: 'UVs from unselected adjacent'
+Blender: 242
+Group: 'UVCalculation'
+Tooltip: 'Assign UVs to selected faces from surrounding unselected faces.'
+"""
+__author__ = "Campbell Barton"
+__url__ = ("blender", "elysiun")
+__version__ = "1.0 2006/02/07"
+
+__bpydoc__ = """\
+This script sets the UV mapping and image of selected faces from adjacent unselected faces.
+
+Use this script in face select mode for texturing between textured faces.
+"""
+
+# ***** 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 *****
+# --------------------------------------------------------------------------
+
+
+from Blender import *
+import bpy
+
+def mostUsedImage(imageList): # Returns the image most used in the list.
+ if not imageList:
+ return None
+ elif len(imageList) < 3:
+ return imageList[0]
+
+ # 3+ Images, Get the most used image for surrounding faces.
+ imageCount = {}
+ for image in imageList:
+ if image:
+ image_key= image.name
+ else:
+ image_key = None
+
+ try:
+ imageCount[image_key]['imageCount'] +=1 # an extra user of this image
+ except:
+ imageCount[image_key] = {'imageCount':1, 'blenderImage':image} # start with 1 user.
+
+ # Now a list of tuples, (imageName, {imageCount, image})
+ imageCount = imageCount.items()
+
+ try: imageCount.sort(key=lambda a: a[1])
+ except: imageCount.sort(lambda a,b: cmp(a[1], b[1]))
+
+
+ return imageCount[-1][1]['blenderImage']
+
+
+def main():
+ sce = bpy.data.scenes.active
+ ob = sce.objects.active
+
+ if ob == None or ob.type != 'Mesh':
+ Draw.PupMenu('ERROR: No mesh object in face select mode.')
+ return
+ me = ob.getData(mesh=1)
+
+ if not me.faceUV:
+ Draw.PupMenu('ERROR: No mesh object in face select mode.')
+ return
+
+ selfaces = [f for f in me.faces if f.sel]
+ unselfaces = [f for f in me.faces if not f.sel]
+
+
+ # Gather per Vert UV and Image, store in vertUvAverage
+ vertUvAverage = [[[],[]] for i in xrange(len(me.verts))]
+
+ for f in unselfaces: # Unselected faces only.
+ fuv = f.uv
+ for i,v in enumerate(f):
+ vertUvAverage[v.index][0].append(fuv[i])
+ vertUvAverage[v.index][1].append(f.image)
+
+ # Average per vectex UV coords
+ for vertUvData in vertUvAverage:
+ uvList = vertUvData[0]
+ if uvList:
+ # Convert from a list of vectors into 1 vector.
+ vertUvData[0] = reduce(lambda a,b: a+b, uvList, Mathutils.Vector(0,0)) * (1.0/len(uvList))
+ else:
+ vertUvData[0] = None
+
+ # Assign to selected faces
+ TEX_FLAG = Mesh.FaceModes['TEX']
+ for f in selfaces:
+ uvlist = []
+ imageList = []
+ for i,v in enumerate(f):
+ uv, vImages = vertUvAverage[v.index]
+ uvlist.append( uv )
+ imageList.extend(vImages)
+
+ if None not in uvlist:
+ # all the faces images used by this faces vert. some faces will be added twice but thats ok.
+ # Get the most used image and assign to the face.
+ image = mostUsedImage(imageList)
+ f.uv = uvlist
+
+ if image:
+ f.image = image
+ f.mode |= TEX_FLAG
+ Window.RedrawAll()
+
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/release/ui/buttons_physics_field.py b/release/ui/buttons_physics_field.py
deleted file mode 100644
index 696de5e6d56..00000000000
--- a/release/ui/buttons_physics_field.py
+++ /dev/null
@@ -1,66 +0,0 @@
-
-import bpy
-
-class PhysicButtonsPanel(bpy.types.Panel):
- __space_type__ = "BUTTONS_WINDOW"
- __region_type__ = "WINDOW"
- __context__ = "physics"
-
- def poll(self, context):
- return (context.object != None)
-
-class PHYSICS_PT_field(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_field"
- __label__ = "Field"
-
- def draw(self, context):
- layout = self.layout
- ob = context.object
- field = ob.field
-
- layout.itemR(field, "type")
-
- if field.type != "NONE":
- layout.itemR(field, "strength")
-
- if field.type in ("HARMONIC", "SPHERICAL", "CHARGE", "LENNARDj"):
- if ob.type in ("MESH", "SURFACE", "FONT", "CURVE"):
- layout.itemR(field, "surface")
-
-class PHYSICS_PT_collision(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_collision"
- __label__ = "Collision"
- __default_closed__ = True
-
- def poll(self, context):
- ob = context.object
- return (ob and ob.type == 'MESH')
-
- def draw_header(self, context):
- settings = context.object.collision
- self.layout.itemR(settings, "enabled", text="")
-
- def draw(self, context):
- layout = self.layout
- md = context.collision
- settings = context.object.collision
-
- layout.active = settings.enabled
-
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Damping:")
- col.itemR(settings, "damping_factor", text="Factor");
- col.itemR(settings, "random_damping", text="Random");
-
- col = split.column()
- col.itemL(text="Friction:")
- col.itemR(settings, "friction_factor", text="Factor");
- col.itemR(settings, "random_friction", text="Random");
-
- layout.itemR(settings, "permeability");
- layout.itemR(settings, "kill_particles");
-
-bpy.types.register(PHYSICS_PT_field)
-bpy.types.register(PHYSICS_PT_collision)
diff --git a/release/ui/buttons_physics_fluid.py b/release/ui/buttons_physics_fluid.py
deleted file mode 100644
index 2ab33b4a416..00000000000
--- a/release/ui/buttons_physics_fluid.py
+++ /dev/null
@@ -1,223 +0,0 @@
-
-import bpy
-
-class PhysicButtonsPanel(bpy.types.Panel):
- __space_type__ = "BUTTONS_WINDOW"
- __region_type__ = "WINDOW"
- __context__ = "physics"
-
- def poll(self, context):
- ob = context.object
- return (ob and ob.type == 'MESH')
-
-class PHYSICS_PT_fluid(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_fluid"
- __label__ = "Fluid"
-
- def draw(self, context):
- layout = self.layout
- md = context.fluid
- ob = context.object
-
- split = layout.split()
- split.operator_context = "EXEC_DEFAULT"
-
- if md:
- # remove modifier + settings
- split.set_context_pointer("modifier", md)
- split.itemO("OBJECT_OT_modifier_remove", text="Remove")
-
- row = split.row(align=True)
- row.itemR(md, "render", text="")
- row.itemR(md, "realtime", text="")
- else:
- # add modifier
- split.item_enumO("OBJECT_OT_modifier_add", "type", "FLUID_SIMULATION", text="Add")
- split.itemL()
-
- if md:
- fluid = md.settings
-
- col = layout.column(align=True)
- row = col.row()
- row.item_enumR(fluid, "type", "DOMAIN")
- row.item_enumR(fluid, "type", "FLUID")
- row.item_enumR(fluid, "type", "OBSTACLE")
- row = col.row()
- row.item_enumR(fluid, "type", "INFLOW")
- row.item_enumR(fluid, "type", "OUTFLOW")
- row.item_enumR(fluid, "type", "PARTICLE")
- row.item_enumR(fluid, "type", "CONTROL")
-
- if fluid.type == 'DOMAIN':
- layout.itemO("FLUID_OT_bake", text="BAKE")
- layout.itemL(text="Required Memory: " + fluid.memory_estimate)
-
- layout.itemL(text="Resolution:")
-
- split = layout.split()
-
- col = split.column()
- colsub = col.column(align=True)
- colsub.itemR(fluid, "resolution", text="Final")
- colsub.itemR(fluid, "render_display_mode", text="")
- colsub = col.column(align=True)
- colsub.itemL(text="Time:")
- colsub.itemR(fluid, "start_time", text="Start")
- colsub.itemR(fluid, "end_time", text="End")
-
- col = split.column()
- colsub = col.column(align=True)
- colsub.itemR(fluid, "preview_resolution", text="Preview", slider=True)
- colsub.itemR(fluid, "viewport_display_mode", text="")
- colsub = col.column()
- colsub.itemR(fluid, "reverse_frames")
- colsub.itemR(fluid, "generate_speed_vectors")
- colsub.itemR(fluid, "path", text="")
-
- if fluid.type in ('FLUID', 'OBSTACLE', 'INFLOW', 'OUTFLOW'):
- layout.itemR(fluid, "volume_initialization")
-
- if fluid.type == 'FLUID':
- row = layout.row()
- row.column().itemR(fluid, "initial_velocity")
- row.itemR(fluid, "export_animated_mesh")
-
- if fluid.type == 'OBSTACLE':
- row = layout.row()
- row.itemL()
- row.itemR(fluid, "export_animated_mesh")
- layout.itemR(fluid, "slip_type", expand=True)
- if fluid.slip_type == 'PARTIALSLIP':
- layout.itemR(fluid, "partial_slip_amount", text="Amount")
-
- layout.itemR(fluid, "impact_factor")
-
- if fluid.type == 'INFLOW':
- row = layout.row()
- row.column().itemR(fluid, "inflow_velocity")
- row.itemR(fluid, "export_animated_mesh")
- layout.itemR(fluid, "local_coordinates")
-
- if fluid.type == 'OUTFLOW':
- row = layout.row()
- row.itemL()
- row.itemR(fluid, "export_animated_mesh")
-
- if fluid.type == 'PARTICLE':
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Type:")
- col.itemR(fluid, "drops")
- col.itemR(fluid, "floats")
- col.itemR(fluid, "tracer")
-
- col = split.column()
- col.itemL(text="Influence:")
- col.itemR(fluid, "particle_influence", text="Particle")
- col.itemR(fluid, "alpha_influence", text="Alpha")
-
- layout.itemR(fluid, "path")
-
- if fluid.type == 'CONTROL':
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Time:")
- col.itemR(fluid, "start_time", text="Start")
- col.itemR(fluid, "end_time", text="End")
-
- col = split.column()
- col.itemR(fluid, "quality", slider=True)
- col.itemR(fluid, "reverse_frames")
-
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Attraction:")
- col.itemR(fluid, "attraction_strength", text="Strength")
- col.itemR(fluid, "attraction_radius", text="Radius")
-
- col = split.column()
- col.itemL(text="Velocity:")
- col.itemR(fluid, "velocity_strength", text="Strength")
- col.itemR(fluid, "velocity_radius", text="Radius")
-
-class PHYSICS_PT_domain_gravity(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_domain_gravity"
- __label__ = "Domain World/Gravity"
- __default_closed__ = True
-
- def poll(self, context):
- md = context.fluid
- if md:
- return (md.settings.type == 'DOMAIN')
-
- def draw(self, context):
- layout = self.layout
- fluid = context.fluid.settings
-
- split = layout.split()
-
- col = split.column()
- col.itemR(fluid, "gravity")
-
- col = split.column(align=True)
- col.itemL(text="Viscosity:")
- col.itemR(fluid, "viscosity_preset", text="")
- if fluid.viscosity_preset == 'MANUAL':
- col.itemR(fluid, "viscosity_base", text="Base")
- col.itemR(fluid, "viscosity_exponent", text="Exponent")
-
- col = layout.column_flow()
- col.itemR(fluid, "real_world_size")
- col.itemR(fluid, "grid_levels")
- col.itemR(fluid, "compressibility")
-
-class PHYSICS_PT_domain_boundary(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_domain_boundary"
- __label__ = "Domain Boundary"
- __default_closed__ = True
-
- def poll(self, context):
- md = context.fluid
- if md:
- return (md.settings.type == 'DOMAIN')
-
- def draw(self, context):
- layout = self.layout
- fluid = context.fluid.settings
-
- layout.itemL(text="Slip:")
-
- layout.itemR(fluid, "slip_type", expand=True)
- if fluid.slip_type == 'PARTIALSLIP':
- layout.itemR(fluid, "partial_slip_amount", text="Amount")
-
- layout.itemL(text="Surface:")
- row = layout.row()
- row.itemR(fluid, "surface_smoothing", text="Smoothing")
- row.itemR(fluid, "surface_subdivisions", text="Subdivisions")
-
-class PHYSICS_PT_domain_particles(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_domain_particles"
- __label__ = "Domain Particles"
- __default_closed__ = True
-
- def poll(self, context):
- md = context.fluid
- if md:
- return (md.settings.type == 'DOMAIN')
-
- def draw(self, context):
- layout = self.layout
- fluid = context.fluid.settings
-
- layout.itemR(fluid, "tracer_particles")
- layout.itemR(fluid, "generate_particles")
-
-bpy.types.register(PHYSICS_PT_fluid)
-bpy.types.register(PHYSICS_PT_domain_gravity)
-bpy.types.register(PHYSICS_PT_domain_boundary)
-bpy.types.register(PHYSICS_PT_domain_particles)
diff --git a/release/ui/buttons_physics_softbody.py b/release/ui/buttons_physics_softbody.py
deleted file mode 100644
index 774f7f67979..00000000000
--- a/release/ui/buttons_physics_softbody.py
+++ /dev/null
@@ -1,219 +0,0 @@
-
-import bpy
-
-class PhysicButtonsPanel(bpy.types.Panel):
- __space_type__ = "BUTTONS_WINDOW"
- __region_type__ = "WINDOW"
- __context__ = "physics"
-
- def poll(self, context):
- ob = context.object
- return (ob and ob.type == 'MESH')
-
-class PHYSICS_PT_softbody(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_softbody"
- __label__ = "Soft Body"
-
- def draw(self, context):
- layout = self.layout
- md = context.soft_body
- ob = context.object
-
- split = layout.split()
- split.operator_context = "EXEC_DEFAULT"
-
- if md:
- # remove modifier + settings
- split.set_context_pointer("modifier", md)
- split.itemO("OBJECT_OT_modifier_remove", text="Remove")
-
- row = split.row(align=True)
- row.itemR(md, "render", text="")
- row.itemR(md, "realtime", text="")
- else:
- # add modifier
- split.item_enumO("OBJECT_OT_modifier_add", "type", "SOFTBODY", text="Add")
- split.itemL("")
-
- if md:
- softbody = md.settings
-
- # General
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Object:")
- col.itemR(softbody, "mass")
- col.itemR(softbody, "friction")
-
- col = split.column()
- col.itemL(text="Simulation:")
- col.itemR(softbody, "gravity")
- col.itemR(softbody, "speed")
-
-
-class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_softbody_goal"
- __label__ = "Soft Body Goal"
-
- def poll(self, context):
- return (context.soft_body != None)
-
- def draw_header(self, context):
- layout = self.layout
- softbody = context.soft_body.settings
-
- layout.itemR(softbody, "use_goal", text="")
-
- def draw(self, context):
- layout = self.layout
- md = context.soft_body
- ob = context.object
-
- split = layout.split()
-
- if md:
- softbody = md.settings
- layout.active = softbody.use_goal
-
- # Goal
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Goal Strengths:")
- col.itemR(softbody, "goal_default", text="Default")
- subcol = col.column(align=True)
- subcol.itemR(softbody, "goal_min", text="Minimum")
- subcol.itemR(softbody, "goal_max", text="Maximum")
-
- col = split.column()
- col.itemL(text="Goal Settings:")
- col.itemR(softbody, "goal_spring", text="Stiffness")
- col.itemR(softbody, "goal_friction", text="Damping")
- layout.item_pointerR(softbody, "goal_vertex_group", ob, "vertex_groups", text="Vertex Group")
-
-class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_softbody_edge"
- __label__ = "Soft Body Edges"
-
- def poll(self, context):
- return (context.soft_body != None)
-
- def draw_header(self, context):
- layout = self.layout
- softbody = context.soft_body.settings
-
- layout.itemR(softbody, "use_edges", text="")
-
- def draw(self, context):
- layout = self.layout
- md = context.soft_body
- ob = context.object
-
- split = layout.split()
-
- if md:
- softbody = md.settings
-
- layout.active = softbody.use_edges
-
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Springs:")
- col.itemR(softbody, "pull")
- col.itemR(softbody, "push")
- col.itemR(softbody, "damp")
- col.itemR(softbody, "plastic")
- col.itemR(softbody, "bending")
- col.itemR(softbody, "spring_length", text="Length")
-
- col = split.column()
- col.itemR(softbody, "stiff_quads")
- subcol = col.column()
- subcol.active = softbody.stiff_quads
- subcol.itemR(softbody, "shear")
-
- col.itemR(softbody, "new_aero", text="Aero")
- subcol = col.column()
- subcol.active = softbody.new_aero
- subcol.itemR(softbody, "aero", text="Factor", enabled=softbody.new_aero)
-
- col.itemL(text="Collision:")
- col.itemR(softbody, "edge_collision", text="Edge")
- col.itemR(softbody, "face_collision", text="Face")
-
-class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_softbody_collision"
- __label__ = "Soft Body Collision"
-
- def poll(self, context):
- return (context.soft_body != None)
-
- def draw_header(self, context):
- layout = self.layout
- softbody = context.soft_body.settings
-
- layout.itemR(softbody, "self_collision", text="")
-
- def draw(self, context):
- layout = self.layout
- md = context.soft_body
- ob = context.object
-
- split = layout.split()
-
- if md:
- softbody = md.settings
-
- layout.active = softbody.self_collision
- layout.itemL(text="Collision Type:")
- layout.itemR(softbody, "collision_type", expand=True)
-
- col = layout.column(align=True)
- col.itemL(text="Ball:")
- col.itemR(softbody, "ball_size", text="Size")
- col.itemR(softbody, "ball_stiff", text="Stiffness")
- col.itemR(softbody, "ball_damp", text="Dampening")
-
-class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
- __idname__ = "PHYSICS_PT_softbody_solver"
- __label__ = "Soft Body Solver"
-
- def poll(self, context):
- return (context.soft_body != None)
-
- def draw(self, context):
- layout = self.layout
- md = context.soft_body
- ob = context.object
-
- split = layout.split()
-
- if md:
- softbody = md.settings
-
- # Solver
- split = layout.split()
-
- col = split.column(align=True)
- col.itemL(text="Step Size:")
- col.itemR(softbody, "minstep")
- col.itemR(softbody, "maxstep")
- col.itemR(softbody, "auto_step", text="Auto-Step")
-
- col = split.column()
- col.itemR(softbody, "error_limit")
-
- col.itemL(text="Helpers:")
- col.itemR(softbody, "choke")
- col.itemR(softbody, "fuzzy")
-
- layout.itemL(text="Diagnostics:")
- layout.itemR(softbody, "diagnose")
-
-bpy.types.register(PHYSICS_PT_softbody)
-bpy.types.register(PHYSICS_PT_softbody_goal)
-bpy.types.register(PHYSICS_PT_softbody_edge)
-bpy.types.register(PHYSICS_PT_softbody_collision)
-bpy.types.register(PHYSICS_PT_softbody_solver)
diff --git a/release/ui/space_buttons.py b/release/ui/space_buttons.py
deleted file mode 100644
index cae9a813433..00000000000
--- a/release/ui/space_buttons.py
+++ /dev/null
@@ -1,36 +0,0 @@
-
-import bpy
-
-class Buttons_HT_header(bpy.types.Header):
- __space_type__ = "BUTTONS_WINDOW"
- __idname__ = "BUTTONS_HT_header"
-
- def draw(self, context):
- layout = self.layout
-
- so = context.space_data
- scene = context.scene
-
- layout.template_header()
-
- if context.area.show_menus:
- row = layout.row(align=True)
- row.itemM("Buttons_MT_view", text="View")
-
- row = layout.row()
- row.itemR(so, "buttons_context", expand=True, text="")
- row.itemR(scene, "current_frame")
-
-class Buttons_MT_view(bpy.types.Menu):
- __space_type__ = "BUTTONS_WINDOW"
- __label__ = "View"
-
- def draw(self, context):
- layout = self.layout
- so = context.space_data
-
- col = layout.column()
- col.itemR(so, "panel_alignment", expand=True)
-
-bpy.types.register(Buttons_HT_header)
-bpy.types.register(Buttons_MT_view)
diff --git a/release/ui/space_filebrowser.py b/release/ui/space_filebrowser.py
deleted file mode 100644
index 0c37e8c0816..00000000000
--- a/release/ui/space_filebrowser.py
+++ /dev/null
@@ -1,67 +0,0 @@
-
-import bpy
-
-
-class FILEBROWSER_HT_header(bpy.types.Header):
- __space_type__ = "FILE_BROWSER"
- __idname__ = "FILEBROWSER_HT_header"
-
- def draw(self, context):
- st = context.space_data
- layout = self.layout
-
- params = st.params
- layout.template_header()
-
- if context.area.show_menus:
- row = layout.row()
- row.itemM("FILEBROWSER_MT_directory")
- row.itemM("FILEBROWSER_MT_bookmarks")
-
- row = layout.row(align=True)
- row.itemO("FILE_OT_parent", text="", icon='ICON_FILE_PARENT')
- row.itemO("FILE_OT_refresh", text="", icon='ICON_FILE_REFRESH')
- row.itemO("FILE_OT_previous", text="", icon='ICON_PREV_KEYFRAME')
- row.itemO("FILE_OT_next", text="", icon='ICON_NEXT_KEYFRAME')
-
- layout.itemR(params, "display", expand=True, text="")
- layout.itemR(params, "sort", expand=True, text="")
-
- layout.itemR(params, "hide_dot")
- layout.itemR(params, "do_filter")
-
- row = layout.row(align=True)
- row.itemR(params, "filter_folder", text="");
- row.itemR(params, "filter_blender", text="");
- row.itemR(params, "filter_image", text="");
- row.itemR(params, "filter_movie", text="");
- row.itemR(params, "filter_script", text="");
- row.itemR(params, "filter_font", text="");
- row.itemR(params, "filter_sound", text="");
- row.itemR(params, "filter_text", text="");
-
- row.active = params.do_filter
-
-class FILEBROWSER_MT_directory(bpy.types.Menu):
- __space_type__ = "FILE_BROWSER"
- __label__ = "Directory"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("FILE_OT_refresh", text="Refresh", icon='ICON_FILE_REFRESH')
- layout.itemO("FILE_OT_parent", text="Parent", icon='ICON_FILE_PARENT')
-
-class FILEBROWSER_MT_bookmarks(bpy.types.Menu):
- __space_type__ = "FILE_BROWSER"
- __label__ = "Bookmarks"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("FILE_OT_add_bookmark", text="Add current directory", icon='ICON_BOOKMARKS')
-
-
-bpy.types.register(FILEBROWSER_HT_header)
-bpy.types.register(FILEBROWSER_MT_directory)
-bpy.types.register(FILEBROWSER_MT_bookmarks)
diff --git a/release/ui/space_image.py b/release/ui/space_image.py
deleted file mode 100644
index ce8257203dc..00000000000
--- a/release/ui/space_image.py
+++ /dev/null
@@ -1,397 +0,0 @@
-
-import bpy
-
-class IMAGE_MT_view(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "View"
-
- def draw(self, context):
- layout = self.layout
- sima = context.space_data
- uv = sima.uv_editor
- settings = context.scene.tool_settings
-
- show_uvedit = sima.show_uvedit
-
- layout.itemO("IMAGE_OT_properties", icon="ICON_MENU_PANEL")
-
- layout.itemS()
-
- layout.itemR(sima, "update_automatically")
- if show_uvedit:
- layout.itemR(settings, "uv_local_view") # Numpad /
-
- layout.itemS()
-
- layout.itemO("IMAGE_OT_view_zoom_in")
- layout.itemO("IMAGE_OT_view_zoom_out")
-
- layout.itemS()
-
- ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]];
-
- for a, b in ratios:
- text = "Zoom %d:%d" % (a, b)
- layout.item_floatO("IMAGE_OT_view_zoom_ratio", "ratio", a/b, text=text)
-
- layout.itemS()
-
- if show_uvedit:
- layout.itemO("IMAGE_OT_view_selected")
-
- layout.itemO("IMAGE_OT_view_all")
- layout.itemO("SCREEN_OT_screen_full_area")
-
-class IMAGE_MT_select(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Select"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("UV_OT_select_border")
- layout.item_booleanO("UV_OT_select_border", "pinned", True)
-
- layout.itemS()
-
- layout.itemO("UV_OT_select_all_toggle")
- layout.itemO("UV_OT_select_inverse")
- layout.itemO("UV_OT_unlink_selection")
-
- layout.itemS()
-
- layout.itemO("UV_OT_select_pinned")
- layout.itemO("UV_OT_select_linked")
-
-class IMAGE_MT_image(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Image"
-
- def draw(self, context):
- layout = self.layout
- sima = context.space_data
- ima = sima.image
-
- layout.itemO("IMAGE_OT_new")
- layout.itemO("IMAGE_OT_open")
-
- show_render = sima.show_render
-
- if ima:
- if show_render:
- layout.itemO("IMAGE_OT_replace")
- layout.itemO("IMAGE_OT_reload")
-
- layout.itemO("IMAGE_OT_save")
- layout.itemO("IMAGE_OT_save_as")
-
- if ima.source == "SEQUENCE":
- layout.itemO("IMAGE_OT_save_sequence")
-
- if not show_render:
- layout.itemS()
-
- if ima.packed_file:
- layout.itemO("IMAGE_OT_unpack")
- else:
- layout.itemO("IMAGE_OT_pack")
-
- # only for dirty && specific image types, perhaps
- # this could be done in operator poll too
- if ima.dirty:
- if ima.source in ("FILE", "GENERATED") and ima.type != "MULTILAYER":
- layout.item_booleanO("IMAGE_OT_pack", "as_png", True, text="Pack As PNG")
-
- layout.itemS()
-
- layout.itemR(sima, "image_painting")
-
-class IMAGE_MT_uvs_showhide(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Show/Hide Faces"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("UV_OT_reveal")
- layout.itemO("UV_OT_hide")
- layout.item_booleanO("UV_OT_hide", "unselected", True)
-
-class IMAGE_MT_uvs_transform(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Transform"
-
- def draw(self, context):
- layout = self.layout
-
- layout.item_enumO("TFM_OT_transform", "mode", "TRANSLATION")
- layout.item_enumO("TFM_OT_transform", "mode", "ROTATION")
- layout.item_enumO("TFM_OT_transform", "mode", "RESIZE")
-
-class IMAGE_MT_uvs_mirror(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Mirror"
-
- def draw(self, context):
- layout = self.layout
-
- layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_X") # "X Axis", M,
- layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_Y") # "Y Axis", M,
-
-class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "Weld/Align"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("UV_OT_weld") # W, 1
- layout.items_enumO("UV_OT_align", "axis") # W, 2/3/4
-
-
-class IMAGE_MT_uvs(bpy.types.Menu):
- __space_type__ = "IMAGE_EDITOR"
- __label__ = "UVs"
-
- def draw(self, context):
- layout = self.layout
- sima = context.space_data
- uv = sima.uv_editor
- settings = context.scene.tool_settings
-
- layout.itemR(uv, "snap_to_pixels")
- layout.itemR(uv, "constrain_to_image_bounds")
-
- layout.itemS()
-
- layout.itemR(uv, "live_unwrap")
- layout.itemO("UV_OT_unwrap")
- layout.item_booleanO("UV_OT_pin", "clear", True, text="Unpin")
- layout.itemO("UV_OT_pin")
-
- layout.itemS()
-
- layout.itemO("UV_OT_pack_islands")
- layout.itemO("UV_OT_average_islands_scale")
- layout.itemO("UV_OT_minimize_stretch")
- layout.itemO("UV_OT_stitch")
-
- layout.itemS()
-
- layout.itemM("IMAGE_MT_uvs_transform")
- layout.itemM("IMAGE_MT_uvs_mirror")
- layout.itemM("IMAGE_MT_uvs_weldalign")
-
- layout.itemS()
-
- layout.itemR(settings, "proportional_editing")
- layout.item_menu_enumR(settings, "proportional_editing_falloff")
-
- layout.itemS()
-
- layout.itemM("IMAGE_MT_uvs_showhide")
-
-class IMAGE_HT_header(bpy.types.Header):
- __space_type__ = "IMAGE_EDITOR"
-
- def draw(self, context):
- sima = context.space_data
- ima = sima.image
- iuser = sima.image_user
- layout = self.layout
- settings = context.scene.tool_settings
-
- show_render = sima.show_render
- show_paint = sima.show_paint
- show_uvedit = sima.show_uvedit
-
- layout.template_header()
-
- # menus
- if context.area.show_menus:
- row = layout.row()
- row.itemM("IMAGE_MT_view")
-
- if show_uvedit:
- row.itemM("IMAGE_MT_select")
-
- if ima and ima.dirty:
- row.itemM("IMAGE_MT_image", text="Image*")
- else:
- row.itemM("IMAGE_MT_image", text="Image")
-
- if show_uvedit:
- row.itemM("IMAGE_MT_uvs")
-
- layout.template_ID(sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
-
- """
- /* image select */
-
- pinflag= (show_render)? 0: UI_ID_PIN;
- xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)sima->image, ID_IM, &sima->pin, xco, yco,
- sima_idpoin_handle, UI_ID_BROWSE|UI_ID_BROWSE_RENDER|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE|pinflag);
- xco += 8;
- """
-
- """
- if(ima && !ELEM3(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_VIEWER) && ima->ok) {
- /* XXX this should not be a static var */
- static int headerbuttons_packdummy;
-
- headerbuttons_packdummy = 0;
-
- if (ima->packedfile) {
- headerbuttons_packdummy = 1;
- }
- if (ima->packedfile && ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
- uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMA_REPACK */, ICON_UGLYPACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Re-Pack this image as PNG");
- else
- uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMAPACKIMA */, ICON_PACKAGE, xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image");
-
- xco+= XIC+8;
- }
- """
-
- # uv editing
- if show_uvedit:
- uvedit = sima.uv_editor
-
- layout.itemR(uvedit, "pivot", text="")
- layout.itemR(settings, "uv_sync_selection", text="")
-
- if settings.uv_sync_selection:
- layout.itemR(settings, "mesh_selection_mode", text="", expand=True)
- else:
- layout.itemR(settings, "uv_selection_mode", text="", expand=True)
- layout.itemR(uvedit, "sticky_selection_mode", text="")
- pass
-
- row = layout.row(align=True)
- row.itemR(settings, "snap", text="")
- if settings.snap:
- row.itemR(settings, "snap_mode", text="")
-
- """
- mesh = context.edit_object.data
- row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_layers")
- """
-
- if ima:
- # layers
- layout.template_image_layers(ima, iuser)
-
- # painting
- layout.itemR(sima, "image_painting", text="")
-
- # draw options
- row = layout.row(align=True)
- row.itemR(sima, "draw_channels", text="", expand=True)
-
- row = layout.row(align=True)
- if ima.type == "COMPOSITE":
- row.itemO("IMAGE_OT_record_composite", icon="ICON_REC")
- if ima.type == "COMPOSITE" and ima.source in ("MOVIE", "SEQUENCE"):
- row.itemO("IMAGE_OT_play_composite", icon="ICON_PLAY")
-
- layout.itemR(sima, "update_automatically", text="")
-
-class IMAGE_PT_game_properties(bpy.types.Panel):
- __space_type__ = "IMAGE_EDITOR"
- __region_type__ = "UI"
- __label__ = "Game Properties"
-
- def poll(self, context):
- sima = context.space_data
- return (sima and sima.image)
-
- def draw(self, context):
- sima = context.space_data
- layout = self.layout
-
- ima = sima.image
-
- if ima:
- split = layout.split()
-
- col = split.column()
-
- subcol = col.column(align=True)
- subcol.itemR(ima, "clamp_x")
- subcol.itemR(ima, "clamp_y")
-
- col.itemR(ima, "mapping", expand=True)
- col.itemR(ima, "tiles")
-
- col = split.column()
-
- subcol = col.column(align=True)
- subcol.itemR(ima, "animated")
-
- subcol = subcol.column()
- subcol.itemR(ima, "animation_start", text="Start")
- subcol.itemR(ima, "animation_end", text="End")
- subcol.itemR(ima, "animation_speed", text="Speed")
- subcol.active = ima.animated
-
- subrow = col.row(align=True)
- subrow.itemR(ima, "tiles_x", text="X")
- subrow.itemR(ima, "tiles_y", text="Y")
- subrow.active = ima.tiles or ima.animated
-
-class IMAGE_PT_view_properties(bpy.types.Panel):
- __space_type__ = "IMAGE_EDITOR"
- __region_type__ = "UI"
- __label__ = "View Properties"
-
- def poll(self, context):
- sima = context.space_data
- return (sima and (sima.image or sima.show_uvedit))
-
- def draw(self, context):
- sima = context.space_data
- layout = self.layout
-
- ima = sima.image
- show_uvedit = sima.show_uvedit
- uvedit = sima.uv_editor
-
- split = layout.split()
-
- col = split.column()
- if ima:
- col.itemR(ima, "display_aspect")
-
- col = split.column()
- col.itemR(sima, "draw_repeated", text="Repeat")
- if show_uvedit:
- col.itemR(uvedit, "normalized_coordinates", text="Normalized")
- elif show_uvedit:
- col.itemR(uvedit, "normalized_coordinates", text="Normalized")
-
- if show_uvedit:
- col = layout.column()
- row = col.row()
- row.itemR(uvedit, "edge_draw_type", expand=True)
- row = col.row()
- row.itemR(uvedit, "draw_smooth_edges", text="Smooth")
- row.itemR(uvedit, "draw_modified_edges", text="Modified")
-
- row = col.row()
- row.itemR(uvedit, "draw_stretch", text="Stretch")
- row.itemR(uvedit, "draw_stretch_type", text="")
- #col.itemR(uvedit, "draw_edges")
- #col.itemR(uvedit, "draw_faces")
-
-bpy.types.register(IMAGE_MT_view)
-bpy.types.register(IMAGE_MT_select)
-bpy.types.register(IMAGE_MT_image)
-bpy.types.register(IMAGE_MT_uvs_showhide)
-bpy.types.register(IMAGE_MT_uvs_transform)
-bpy.types.register(IMAGE_MT_uvs_mirror)
-bpy.types.register(IMAGE_MT_uvs_weldalign)
-bpy.types.register(IMAGE_MT_uvs)
-bpy.types.register(IMAGE_HT_header)
-bpy.types.register(IMAGE_PT_game_properties)
-bpy.types.register(IMAGE_PT_view_properties)
-
diff --git a/release/ui/space_info.py b/release/ui/space_info.py
deleted file mode 100644
index de3346711e9..00000000000
--- a/release/ui/space_info.py
+++ /dev/null
@@ -1,119 +0,0 @@
-
-import bpy
-
-class INFO_HT_header(bpy.types.Header):
- __space_type__ = "USER_PREFERENCES"
- __idname__ = "INFO_HT_header"
-
- def draw(self, context):
- st = context.space_data
- layout = self.layout
-
- layout.template_header()
-
- if context.area.show_menus:
- row = layout.row()
- row.itemM("INFO_MT_file")
- row.itemM("INFO_MT_add")
- row.itemM("INFO_MT_timeline")
- row.itemM("INFO_MT_game")
- row.itemM("INFO_MT_render")
- row.itemM("INFO_MT_help")
-
- layout.template_ID(context.window, "screen") #, new="SCREEN_OT_new", open="SCREEN_OT_unlink")
- layout.template_ID(context.screen, "scene") #, new="SCENE_OT_new", unlink="SCENE_OT_unlink")
-
- layout.itemS()
-
- layout.template_operator_search()
- layout.template_running_jobs()
-
-class INFO_MT_file(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "File"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_context = "EXEC_AREA"
- layout.itemO("WM_OT_read_homefile")
- layout.operator_context = "INVOKE_AREA"
- layout.itemO("WM_OT_open_mainfile")
-
- layout.itemS()
-
- layout.operator_context = "EXEC_AREA"
- layout.itemO("WM_OT_save_mainfile")
- layout.operator_context = "INVOKE_AREA"
- layout.itemO("WM_OT_save_as_mainfile")
-
- layout.itemS()
-
- layout.itemM("INFO_MT_file_external_data")
-
-class INFO_MT_file_external_data(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "External Data"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("FILE_OT_pack_all", text="Pack into .blend file")
- layout.itemO("FILE_OT_unpack_all", text="Unpack into Files...")
-
- layout.itemS()
-
- layout.itemO("FILE_OT_make_paths_relative")
- layout.itemO("FILE_OT_make_paths_absolute")
- layout.itemO("FILE_OT_report_missing_files")
- layout.itemO("FILE_OT_find_missing_files")
-
-class INFO_MT_add(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "Add"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="Nothing yet")
-
-class INFO_MT_timeline(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "Timeline"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="Nothing yet")
-
-class INFO_MT_game(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "Game"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="Nothing yet")
-
-class INFO_MT_render(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "Render"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="Nothing yet")
-
-class INFO_MT_help(bpy.types.Menu):
- __space_type__ = "USER_PREFERENCES"
- __label__ = "Help"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="Nothing yet")
-
-bpy.types.register(INFO_HT_header)
-bpy.types.register(INFO_MT_file)
-bpy.types.register(INFO_MT_file_external_data)
-bpy.types.register(INFO_MT_add)
-bpy.types.register(INFO_MT_timeline)
-bpy.types.register(INFO_MT_game)
-bpy.types.register(INFO_MT_render)
-bpy.types.register(INFO_MT_help)
-
diff --git a/release/ui/space_logic.py b/release/ui/space_logic.py
deleted file mode 100644
index f862f6e2667..00000000000
--- a/release/ui/space_logic.py
+++ /dev/null
@@ -1,88 +0,0 @@
-import bpy
-
-class LOGIC_PT_physics(bpy.types.Panel):
- __space_type__ = "LOGIC_EDITOR"
- __region_type__ = "UI"
- __label__ = "Physics"
-
- def poll(self, context):
- ob = context.active_object
- return ob and ob.game
-
- def draw(self, context):
- layout = self.layout
- ob = context.active_object
-
- game = ob.game
-
- flow = layout.column_flow()
- flow.active = True
- flow.itemR(game, "physics_type")
- flow.itemR(game, "actor")
-
- row = layout.row()
- row.itemR(game, "ghost")
- row.itemR(ob, "restrict_render", text="Invisible") # out of place but useful
-
- flow = layout.column_flow()
- flow.itemR(game, "mass")
- flow.itemR(game, "radius")
- flow.itemR(game, "no_sleeping")
- flow.itemR(game, "damping")
- flow.itemR(game, "rotation_damping")
- flow.itemR(game, "minimum_velocity")
- flow.itemR(game, "maximum_velocity")
-
- row = layout.row()
- row.itemR(game, "do_fh")
- row.itemR(game, "rotation_fh")
-
- flow = layout.column_flow()
- flow.itemR(game, "form_factor")
- flow.itemR(game, "anisotropic_friction")
-
- flow = layout.column_flow()
- flow.active = game.anisotropic_friction
- flow.itemR(game, "friction_coefficients")
-
- split = layout.split()
- sub = split.column()
- sub.itemR(game, "lock_x_axis")
- sub.itemR(game, "lock_y_axis")
- sub.itemR(game, "lock_z_axis")
- sub = split.column()
- sub.itemR(game, "lock_x_rot_axis")
- sub.itemR(game, "lock_y_rot_axis")
- sub.itemR(game, "lock_z_rot_axis")
-
-
-class LOGIC_PT_collision_bounds(bpy.types.Panel):
- __space_type__ = "LOGIC_EDITOR"
- __region_type__ = "UI"
- __label__ = "Collision Bounds"
-
- def poll(self, context):
- ob = context.active_object
- return ob and ob.game
-
- def draw_header(self, context):
- layout = self.layout
- ob = context.active_object
- game = ob.game
-
- layout.itemR(game, "use_collision_bounds", text="")
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.scene.objects[0]
- game = ob.game
-
- flow = layout.column_flow()
- flow.active = game.use_collision_bounds
- flow.itemR(game, "collision_bounds")
- flow.itemR(game, "collision_compound")
- flow.itemR(game, "collision_margin")
-
-bpy.types.register(LOGIC_PT_physics)
-bpy.types.register(LOGIC_PT_collision_bounds)
diff --git a/release/ui/space_view3d.py b/release/ui/space_view3d.py
deleted file mode 100644
index c338241d5d7..00000000000
--- a/release/ui/space_view3d.py
+++ /dev/null
@@ -1,106 +0,0 @@
-
-import bpy
-
-class VIEW3D_MT_view_navigation(bpy.types.Menu):
- __space_type__ = "VIEW_3D"
- __label__ = "Navigation"
-
- def draw(self, context):
- layout = self.layout
-
- # layout.itemO("VIEW3D_OT_view_fly_mode")
- # layout.itemS()
-
- layout.items_enumO("VIEW3D_OT_view_orbit", "type")
-
- layout.itemS()
-
- layout.items_enumO("VIEW3D_OT_view_pan", "type")
-
- layout.itemS()
-
- layout.item_floatO("VIEW3D_OT_zoom", "delta", 1.0, text="Zoom In")
- layout.item_floatO("VIEW3D_OT_zoom", "delta", -1.0, text="Zoom Out")
-
-class VIEW3D_MT_view(bpy.types.Menu):
- __space_type__ = "VIEW_3D"
- __label__ = "View"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("VIEW3D_OT_properties", icon="ICON_MENU_PANEL")
- layout.itemO("VIEW3D_OT_toolbar", icon="ICON_MENU_PANEL")
-
- layout.itemS()
-
- layout.item_enumO("VIEW3D_OT_viewnumpad", "type", "CAMERA")
- layout.item_enumO("VIEW3D_OT_viewnumpad", "type", "TOP")
- layout.item_enumO("VIEW3D_OT_viewnumpad", "type", "FRONT")
- layout.item_enumO("VIEW3D_OT_viewnumpad", "type", "RIGHT")
-
- # layout.itemM("VIEW3D_MT_view_cameras", text="Cameras")
-
- layout.itemS()
-
- layout.itemO("VIEW3D_OT_view_persportho")
-
- layout.itemS()
-
- # layout.itemO("VIEW3D_OT_view_show_all_layers")
-
- # layout.itemS()
-
- # layout.itemO("VIEW3D_OT_view_local_view")
- # layout.itemO("VIEW3D_OT_view_global_view")
-
- # layout.itemS()
-
- layout.itemM("VIEW3D_MT_view_navigation")
- # layout.itemM("VIEW3D_MT_view_align", text="Align View")
-
- layout.itemS()
-
- layout.operator_context = "INVOKE_REGION_WIN"
-
- layout.itemO("VIEW3D_OT_clip_border")
- layout.itemO("VIEW3D_OT_zoom_border")
-
- layout.itemS()
-
- layout.itemO("VIEW3D_OT_view_center")
- layout.itemO("VIEW3D_OT_view_all")
-
- layout.itemS()
-
- layout.itemO("SCREEN_OT_screen_full_area")
-
-class VIEW3D_HT_header(bpy.types.Header):
- __space_type__ = "VIEW_3D"
-
- def draw(self, context):
- layout = self.layout
-
- layout.template_header()
-
- # menus
- if context.area.show_menus:
- row = layout.row()
- row.itemM("VIEW3D_MT_view")
-
- layout.template_header_3D()
-
-class VIEW3D_PT_random_panel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "UI"
- __label__ = "Random Panel"
-
- def draw(self, context):
- layout = self.layout
- layout.itemL(text="panel contents")
-
-bpy.types.register(VIEW3D_MT_view_navigation)
-bpy.types.register(VIEW3D_MT_view)
-bpy.types.register(VIEW3D_HT_header)
-bpy.types.register(VIEW3D_PT_random_panel)
-
diff --git a/release/ui/space_view3d_toolbar.py b/release/ui/space_view3d_toolbar.py
deleted file mode 100644
index 990ba1eb6b6..00000000000
--- a/release/ui/space_view3d_toolbar.py
+++ /dev/null
@@ -1,254 +0,0 @@
-
-import bpy
-
-# ********** default tools for objectmode ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "objectmode"
-
-class VIEW3D_PT_tools_objectmode(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_objectmode"
- __label__ = "Object Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("OBJECT_OT_duplicate")
- layout.row().itemO("OBJECT_OT_delete")
- layout.row().itemO("OBJECT_OT_mesh_add")
- layout.row().itemO("OBJECT_OT_curve_add")
- layout.row().itemO("OBJECT_OT_text_add")
- layout.row().itemO("OBJECT_OT_surface_add")
-
-# ********** default tools for editmode_mesh ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_mesh"
-
-class VIEW3D_PT_tools_editmode_mesh(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_mesh"
- __label__ = "Mesh Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("MESH_OT_duplicate")
- layout.row().itemO("MESH_OT_delete")
- layout.row().itemO("MESH_OT_spin")
- layout.row().itemO("MESH_OT_screw")
- layout.row().itemO("MESH_OT_primitive_plane_add")
- layout.row().itemO("MESH_OT_primitive_cube_add")
- layout.row().itemO("MESH_OT_primitive_circle_add")
- layout.row().itemO("MESH_OT_primitive_cylinder_add")
-
-# ********** default tools for editmode_curve ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_curve"
-
-class VIEW3D_PT_tools_editmode_curve(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_curve"
- __label__ = "Curve Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("CURVE_OT_duplicate")
- layout.row().itemO("CURVE_OT_delete")
- layout.row().itemO("OBJECT_OT_curve_add")
- layout.row().itemO("CURVE_OT_subdivide")
-
-# ********** default tools for editmode_surface ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_surface"
-
-class VIEW3D_PT_tools_editmode_surface(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_surface"
- __label__ = "Surface Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("CURVE_OT_duplicate")
- layout.row().itemO("CURVE_OT_delete")
- layout.row().itemO("OBJECT_OT_surface_add")
- layout.row().itemO("CURVE_OT_subdivide")
-
-# ********** default tools for editmode_text ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_text"
-
-class VIEW3D_PT_tools_editmode_text(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_text"
- __label__ = "Text Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("FONT_OT_text_copy")
- layout.row().itemO("FONT_OT_text_paste")
- layout.row().itemO("FONT_OT_case_set")
- layout.row().itemO("FONT_OT_style_toggle")
-
-# ********** default tools for editmode_armature ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_armature"
-
-class VIEW3D_PT_tools_editmode_armature(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_armature"
- __label__ = "Armature Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("ARMATURE_OT_duplicate_selected")
- layout.row().itemO("ARMATURE_OT_bone_primitive_add")
- layout.row().itemO("ARMATURE_OT_delete")
- layout.row().itemO("ARMATURE_OT_parent_clear")
-
-# ********** default tools for editmode_mball ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_mball"
-
-class VIEW3D_PT_tools_editmode_mball(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_mball"
- __label__ = "Meta Tools"
-
- def draw(self, context):
- layout = self.layout
-
- row = layout.row()
-
-# ********** default tools for editmode_lattice ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "editmode_lattice"
-
-class VIEW3D_PT_tools_editmode_lattice(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_editmode_lattice"
- __label__ = "Lattice Tools"
-
- def draw(self, context):
- layout = self.layout
-
- row = layout.row()
-
-# ********** default tools for posemode ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "posemode"
-
-class VIEW3D_PT_tools_posemode(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_posemode"
- __label__ = "Pose Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("POSE_OT_hide")
- layout.row().itemO("POSE_OT_reveal")
- layout.row().itemO("POSE_OT_rot_clear")
- layout.row().itemO("POSE_OT_loc_clear")
-
-# ********** default tools for sculptmode ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "sculptmode"
-
-class VIEW3D_PT_tools_sculptmode(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_sculptmode"
- __label__ = "Sculpt Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("SCULPT_OT_radial_control")
-
-# ********** default tools for weightpaint ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "weightpaint"
-
-class VIEW3D_PT_tools_weightpaint(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_weightpaint"
- __label__ = "Weight Paint Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("PAINT_OT_weight_paint_radial_control")
-
-# ********** default tools for vertexpaint ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "vertexpaint"
-
-class VIEW3D_PT_tools_vertexpaint(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_vertexpaint"
- __label__ = "Vertex Paint Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("PAINT_OT_vertex_paint_radial_control")
-
-# ********** default tools for texturepaint ****************
-
-class View3DPanel(bpy.types.Panel):
- __space_type__ = "VIEW_3D"
- __region_type__ = "TOOLS"
- __context__ = "texturepaint"
-
-class VIEW3D_PT_tools_texturepaint(View3DPanel):
- __idname__ = "VIEW3D_PT_tools_texturepaint"
- __label__ = "Texture Paint Tools"
-
- def draw(self, context):
- layout = self.layout
-
- layout.row().itemO("PAINT_OT_texture_paint_radial_control")
-
-
-bpy.types.register(VIEW3D_PT_tools_objectmode)
-bpy.types.register(VIEW3D_PT_tools_editmode_mesh)
-bpy.types.register(VIEW3D_PT_tools_editmode_curve)
-bpy.types.register(VIEW3D_PT_tools_editmode_surface)
-bpy.types.register(VIEW3D_PT_tools_editmode_text)
-bpy.types.register(VIEW3D_PT_tools_editmode_armature)
-bpy.types.register(VIEW3D_PT_tools_editmode_mball)
-bpy.types.register(VIEW3D_PT_tools_editmode_lattice)
-bpy.types.register(VIEW3D_PT_tools_posemode)
-bpy.types.register(VIEW3D_PT_tools_sculptmode)
-bpy.types.register(VIEW3D_PT_tools_weightpaint)
-bpy.types.register(VIEW3D_PT_tools_vertexpaint)
-bpy.types.register(VIEW3D_PT_tools_texturepaint)
-
-
diff --git a/source/blender/SConscript b/source/blender/SConscript
index a064850c170..cce0354643b 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -3,6 +3,7 @@ Import ('env')
import sys
SConscript(['avi/SConscript',
+ 'bmesh/SConscript',
'blenkernel/SConscript',
'blenlib/SConscript',
'blenloader/SConscript',
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 06103596be1..bb50056b7f2 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -43,6 +43,8 @@
*/
#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+
#include "BKE_customdata.h"
#include "BKE_bvhutils.h"
@@ -53,43 +55,87 @@ struct MTFace;
struct Object;
struct Scene;
struct Mesh;
-struct EditMesh;
+struct BMEditMesh;
struct ModifierData;
struct MCol;
struct ColorBand;
struct GPUVertexAttribs;
+struct BMEditMesh;
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
#define SUB_ELEMS_EDGE 2
-#define SUB_ELEMS_FACE 4
+#define SUB_ELEMS_FACE 50
+
+/*
+note: all mface interfaces now officially operate on tesselated data.
+*/
+
+/*DM Iterators. For now, first implement face iterators.
+ These are read-only, at least for now.*/
+
+typedef struct DMLoopIter {
+ void (*step)(void *self);
+ int done;
+
+ int index, vindex, eindex;
+ MVert v; /*copy of the associated vert's data*/
+
+ /*note: if layer is -1, then the active layer is retrieved.
+ loop refers to per-face-vertex data.*/
+ void *(*getLoopCDData)(void *self, int type, int layer);
+ void *(*getVertCDData)(void *self, int type, int layer);
+} DMLoopIter;
+
+typedef struct DMFaceIter {
+ void (*step)(void *self);
+ void (*free)(void *self);
+ int done;
+
+ int index;
+ int len;
+ int mat_nr;
+ int flags;
+
+ /*note: you may only use one
+ loop iterator at a time.*/
+ DMLoopIter *(*getLoopsIter)(void *self);
+
+ /*if layer is -1, returns active layer*/
+ void *(*getCDData)(void *self, int type, int layer);
+} DMFaceIter;
typedef struct DerivedMesh DerivedMesh;
struct DerivedMesh {
/* Private DerivedMesh data, only for internal DerivedMesh use */
- CustomData vertData, edgeData, faceData;
- int numVertData, numEdgeData, numFaceData;
+ CustomData vertData, edgeData, faceData, loopData, polyData;
+ int numVertData, numEdgeData, numFaceData, numLoopData, numPolyData;
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
BVHCache bvhCache;
/* Misc. Queries */
+
+ /*face iterator. initializes iter.*/
+ DMFaceIter *(*newFaceIter)(DerivedMesh *dm);
+
+ /*recalculates mesh tesselation*/
+ void (*recalcTesselation)(DerivedMesh *dm);
/* Also called in Editmode */
int (*getNumVerts)(DerivedMesh *dm);
- /* Also called in Editmode */
- int (*getNumFaces)(DerivedMesh *dm);
-
int (*getNumEdges)(DerivedMesh *dm);
+ int (*getNumTessFaces)(DerivedMesh *dm);
+ int (*getNumFaces) (DerivedMesh *dm);
- /* copy a single vert/edge/face from the derived mesh into
+ /* copy a single vert/edge/tesselated face from the derived mesh into
* *{vert/edge/face}_r. note that the current implementation
* of this function can be quite slow, iterating over all
* elements (editmesh)
*/
void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r);
void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r);
- void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r);
+ void (*getTessFace)(DerivedMesh *dm, int index, struct MFace *face_r);
/* return a pointer to the entire array of verts/edges/face from the
* derived mesh. if such an array does not exist yet, it will be created,
@@ -98,21 +144,21 @@ struct DerivedMesh {
*/
struct MVert *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
- struct MFace *(*getFaceArray)(DerivedMesh *dm);
+ struct MFace *(*getTessFaceArray)(DerivedMesh *dm);
/* copy all verts/edges/faces from the derived mesh into
* *{vert/edge/face}_r (must point to a buffer large enough)
*/
void (*copyVertArray)(DerivedMesh *dm, struct MVert *vert_r);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *edge_r);
- void (*copyFaceArray)(DerivedMesh *dm, struct MFace *face_r);
+ void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *face_r);
/* return a copy of all verts/edges/faces from the derived mesh
* it is the caller's responsibility to free the returned pointer
*/
struct MVert *(*dupVertArray)(DerivedMesh *dm);
struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
- struct MFace *(*dupFaceArray)(DerivedMesh *dm);
+ struct MFace *(*dupTessFaceArray)(DerivedMesh *dm);
/* return a pointer to a single element of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
@@ -120,7 +166,7 @@ struct DerivedMesh {
*/
void *(*getVertData)(DerivedMesh *dm, int index, int type);
void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
- void *(*getFaceData)(DerivedMesh *dm, int index, int type);
+ void *(*getTessFaceData)(DerivedMesh *dm, int index, int type);
/* return a pointer to the entire array of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
@@ -128,7 +174,20 @@ struct DerivedMesh {
*/
void *(*getVertDataArray)(DerivedMesh *dm, int type);
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
- void *(*getFaceDataArray)(DerivedMesh *dm, int type);
+ void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
+
+ /*retrieves the base CustomData structures for
+ verts/edges/tessfaces/loops/facdes*/
+ CustomData *(*getVertDataLayout)(DerivedMesh *dm);
+ CustomData *(*getEdgeDataLayout)(DerivedMesh *dm);
+ CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm);
+ CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
+ CustomData *(*getFaceDataLayout)(DerivedMesh *dm);
+
+ /*copies all customdata for an element source into dst at index dest*/
+ void (*copyFromVertCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
+ void (*copyFromEdgeCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
+ void (*copyFromFaceCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
/* Iterate over each mapped vertex in the derived mesh, calling the
* given function with the original vert and the mapped vert's new
@@ -299,13 +358,15 @@ void DM_init_funcs(DerivedMesh *dm);
* of vertices, edges and faces (doesn't allocate memory for them, just
* sets up the custom data layers)
*/
-void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces);
+void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* utility function to initialise a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
- int numVerts, int numEdges, int numFaces);
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* utility function to release a DerivedMesh's layers
* returns 1 if DerivedMesh has to be released by the backend, 0 otherwise
@@ -368,6 +429,10 @@ void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
+void DM_copy_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
@@ -377,8 +442,13 @@ void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
*/
void DM_free_vert_data(struct DerivedMesh *dm, int index, int count);
void DM_free_edge_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_loop_data(struct DerivedMesh *dm, int index, int count);
void DM_free_face_data(struct DerivedMesh *dm, int index, int count);
+/*sets up mpolys for a DM based on face iterators in source*/
+void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
+
/* interpolates vertex data from the vertices indexed by src_indices in the
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
@@ -408,12 +478,20 @@ void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
* vert_weights[i] multiplied by weights[i].
*/
typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
-void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+void DM_interp_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int *src_indices,
float *weights, FaceVertWeight *vert_weights,
int count, int dest_index);
-void DM_swap_face_data(struct DerivedMesh *dm, int index, int *corner_indices);
+void DM_swap_tessface_data(struct DerivedMesh *dm, int index, int *corner_indices);
+
+void DM_interp_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
+
+void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
/* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */
void vDM_ColorBand_store(struct ColorBand *coba);
@@ -434,6 +512,9 @@ DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object
DerivedMesh *mesh_create_derived_render(struct Scene *scene, struct Object *ob,
CustomDataMask dataMask);
+DerivedMesh *getEditDerivedBMesh(struct BMEditMesh *em, struct Object *ob,
+ float (*vertexCos)[3]);
+
DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index);
/* same as above but wont use render settings */
@@ -449,17 +530,17 @@ DerivedMesh *mesh_create_derived_no_deform_render(struct Scene *scene, struct Ob
DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
-DerivedMesh *editmesh_get_derived_base(struct Object *, struct EditMesh *em);
-DerivedMesh *editmesh_get_derived_cage(struct Scene *scene, struct Object *,
- struct EditMesh *em, CustomDataMask dataMask);
-DerivedMesh *editmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
- struct EditMesh *em, DerivedMesh **final_r,
+DerivedMesh *editbmesh_get_derived_base(struct Object *, struct BMEditMesh *em);
+DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, CustomDataMask dataMask);
+DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, DerivedMesh **final_r,
CustomDataMask dataMask);
-void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em, CustomDataMask dataMask);
+void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em, CustomDataMask dataMask);
/* returns an array of deform matrices for crazyspace correction, and the
number of modifiers left */
-int editmesh_get_first_deform_matrices(struct Object *, struct EditMesh *em, float (**deformmats)[3][3],
+int editbmesh_get_first_deform_matrices(struct Object *, struct BMEditMesh *em, float (**deformmats)[3][3],
float (**deformcos)[3]);
void weight_to_rgb(float input, float *fr, float *fg, float *fb);
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index a570b4fe598..36db9553c59 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -38,12 +38,14 @@
#include "BKE_DerivedMesh.h"
struct DerivedMesh;
+struct BMEditMesh;
struct EditMesh;
struct Mesh;
struct Object;
/* creates a new CDDerivedMesh */
-struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces);
+struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* creates a CDDerivedMesh from the given Mesh, this will reference the
original data in Mesh, but it is safe to apply vertex coordinates or
@@ -54,6 +56,9 @@ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob);
/* creates a CDDerivedMesh from the given EditMesh */
struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh *me);
+/* creates a CDDerivedMesh from the given BMEditMesh */
+DerivedMesh *CDDM_from_BMEditMesh(struct BMEditMesh *em, struct Mesh *me);
+
/* Copies the given DerivedMesh with verts, faces & edges stored as
* custom element data.
*/
@@ -64,7 +69,13 @@ struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
* elements are initialised to all zeros
*/
struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
- int numVerts, int numEdges, int numFaces);
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
+
+/*converts mfaces to mpolys. note things may break if there are not valid
+ *medges surrounding each mface.
+ */
+void CDDM_tessfaces_to_faces(struct DerivedMesh *dm);
/* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert
* layer is a referenced layer, it will be duplicate to not overwrite the
@@ -95,7 +106,9 @@ void CDDM_lower_num_faces(struct DerivedMesh *dm, int numFaces);
*/
struct MVert *CDDM_get_vert(struct DerivedMesh *dm, int index);
struct MEdge *CDDM_get_edge(struct DerivedMesh *dm, int index);
-struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index);
+struct MFace *CDDM_get_tessface(struct DerivedMesh *dm, int index);
+struct MLoop *CDDM_get_loop(struct DerivedMesh *dm, int index);
+struct MPoly *CDDM_get_face(struct DerivedMesh *dm, int index);
/* vertex/edge/face array access functions - return the array holding the
* desired data
@@ -104,6 +117,9 @@ struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index);
*/
struct MVert *CDDM_get_verts(struct DerivedMesh *dm);
struct MEdge *CDDM_get_edges(struct DerivedMesh *dm);
-struct MFace *CDDM_get_faces(struct DerivedMesh *dm);
+struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm);
+struct MLoop *CDDM_get_loops(struct DerivedMesh *dm);
+struct MPoly *CDDM_get_faces(struct DerivedMesh *dm);
+
#endif
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 95ee918a888..d442a57b525 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -69,6 +69,12 @@ void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem);
+/*bmesh version of CustomData_merge; merges the layouts of source and dest,
+ then goes through the mesh and makes sure all the customdata blocks are
+ consistent with the new layout.*/
+void CustomData_bmesh_merge(struct CustomData *source, struct CustomData *dest,
+ int mask, int alloctype, struct BMesh *bm, int type);
+
/* frees data associated with a CustomData object (doesn't free the object
* itself, though)
*/
@@ -179,6 +185,7 @@ void CustomData_swap(struct CustomData *data, int index, int *corner_indices);
* returns NULL if there is no layer of type
*/
void *CustomData_get(const struct CustomData *data, int index, int type);
+void *CustomData_get_n(const struct CustomData *data, int type, int index, int n);
void *CustomData_em_get(const struct CustomData *data, void *block, int type);
void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n);
void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type);
@@ -275,7 +282,8 @@ void CustomData_set_layer_unique_name(struct CustomData *data, int index);
int CustomData_verify_versions(struct CustomData *data, int index);
/*BMesh specific customdata stuff*/
-void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
+void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata,
+ struct CustomData *ldata, int totloop, int totpoly);
void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total);
void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize);
#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 24e7b3957a7..5a672ddc5b2 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -43,6 +43,7 @@ struct MFace;
struct MEdge;
struct MVert;
struct MCol;
+struct BMesh;
struct Object;
struct MTFace;
struct VecNor;
@@ -54,6 +55,7 @@ extern "C" {
struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me);
void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em);
+struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me);
void unlink_mesh(struct Mesh *me);
void free_mesh(struct Mesh *me);
@@ -135,8 +137,6 @@ int mesh_layers_menu_charlen(struct CustomData *data, int type); /* use this to
void mesh_layers_menu_concat(struct CustomData *data, int type, char *str);
int mesh_layers_menu(struct CustomData *data, int type);
-
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 144ed3bc624..b4efb742b27 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -43,6 +43,7 @@ struct ListBase;
struct LinkNode;
struct bArmature;
struct ModifierData;
+struct BMEditMesh;
typedef enum {
/* Should not be used, only for None modifier type */
@@ -134,13 +135,13 @@ typedef struct ModifierTypeInfo {
*/
void (*deformVertsEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData, struct DerivedMesh *derivedData,
+ struct BMEditMesh *editData, struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts);
/* Set deform matrix per vertex for crazyspace correction */
void (*deformMatricesEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData, struct DerivedMesh *derivedData,
+ struct BMEditMesh *editData, struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/********************* Non-deform modifier functions *********************/
@@ -178,7 +179,7 @@ typedef struct ModifierTypeInfo {
*/
struct DerivedMesh *(*applyModifierEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData,
+ struct BMEditMesh *editData,
struct DerivedMesh *derivedData);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 6558212519f..063f0ee96aa 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -40,7 +40,8 @@ typedef struct MultiresSubsurf {
/* MultiresDM */
struct Mesh *MultiresDM_get_mesh(struct DerivedMesh *dm);
-struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*, int, int, int);
+struct DerivedMesh *MultiresDM_new(struct MultiresSubsurf *, struct DerivedMesh*,
+ int, int, int, int, int);
void *MultiresDM_get_vertnorm(struct DerivedMesh *);
void *MultiresDM_get_orco(struct DerivedMesh *);
struct MVert *MultiresDM_get_subco(struct DerivedMesh *);
diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h
new file mode 100644
index 00000000000..c3ccf4b1e6a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -0,0 +1,66 @@
+#include "bmesh.h"
+
+struct BMesh;
+struct BMLoop;
+struct DerivedMesh;
+struct BMFace;
+
+/*
+ok: the EDBM module is for editmode bmesh stuff. in contrast, the
+ BMEdit module is for code shared with blenkernel that concerns
+ the BMEditMesh structure.
+*/
+
+typedef struct BMEditSelection
+{
+ struct BMEditSelection *next, *prev;
+ short type;
+ void *data;
+} BMEditSelection;
+
+/*this structure replaces EditMesh.
+
+ through this, you get access to both the edit bmesh,
+ it's tesselation, and various stuff that doesn't belong in the BMesh
+ struct itself.
+
+ the entire derivedmesh and modifier system works with this structure,
+ and not BMesh. Mesh->editbmesh will store a pointer to this structure.*/
+typedef struct BMEditMesh {
+ struct BMesh *bm;
+
+ /*this is for undoing failed operations*/
+ struct BMEditMesh *emcopy;
+
+ /*we store tesselations as triplets of three loops,
+ which each define a triangle.*/
+ struct BMLoop *(*looptris)[3];
+ int tottri;
+
+ /*derivedmesh stuff*/
+ struct DerivedMesh *derivedFinal, *derivedCage;
+ int lastDataMask;
+
+ /*retopo data pointer*/
+ struct RetopoPaintData *retopo_paint_data;
+
+ /*index tables, to map indices to elements via
+ EDBM_init_index_arrays and associated functions. don't
+ touch this or read it directly.*/
+ struct BMVert **vert_index;
+ struct BMEdge **edge_index;
+ struct BMFace **face_index;
+
+ /*selection order list*/
+ ListBase selected;
+
+ /*selection mode*/
+ int selectmode;
+
+ int mat_nr;
+} BMEditMesh;
+
+void BMEdit_RecalcTesselation(BMEditMesh *tm);
+BMEditMesh *BMEdit_Create(BMesh *bm);
+BMEditMesh *BMEdit_Copy(BMEditMesh *tm);
+void BMEdit_Free(BMEditMesh *em);
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index f6c305b202d..3c01f86dc02 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -113,6 +113,8 @@
#define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);}
#define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);}
#define VECSUB2D(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1);}
+#define VECMUL(v1, fac) {v1[0] *= fac; v1[1] *= fac; v1[2] *= fac;}
+
#define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);}
#define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);}
@@ -199,5 +201,50 @@
#define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i))
#define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i))
+/*little pointer array macro library. example of usage:
+
+int *arr = NULL;
+V_DECLARE(arr);
+int i;
+
+for (i=0; i<10; i++) {
+ V_GROW(arr);
+ arr[i] = something;
+}
+V_FREE(arr);
+
+arrays are buffered, using double-buffering (so on each reallocation,
+the array size is doubled). supposedly this should give good Big Oh
+behaviour, though it may not be the best in practice.
+*/
+
+#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp
+
+/*in the future, I plan on having V_DECLARE allocate stack memory it'll
+ use at first, and switch over to heap when it needs more. that'll mess
+ up cases where you'd want to use this API to build a dynamic list for
+ non-local use, so all such cases should use this macro.*/
+#define V_DYNDECLARE(vec) V_DECLARE(vec)
+
+/*this returns the entire size of the array, including any buffering.*/
+#define V_SIZE(vec) ((signed int)((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec)))
+
+/*this returns the logical size of the array, not including buffering.*/
+#define V_COUNT(vec) _##vec##_count
+
+/*grow the array by one. zeroes the new elements.*/
+#define V_GROW(vec) \
+ V_SIZE(vec) > _##vec##_count ? _##vec##_count++ : \
+ ((_##vec##_tmp = MEM_callocN(sizeof(*vec)*(_##vec##_count*2+2), #vec " " __FILE__ " ")),\
+ (vec && memcpy(_##vec##_tmp, vec, sizeof(*vec) * _##vec##_count)),\
+ (vec && (MEM_freeN(vec),1)),\
+ (vec = _##vec##_tmp),\
+ _##vec##_count++)
+
+#define V_FREE(vec) if (vec) MEM_freeN(vec);
+/*resets the logical size of an array to zero, but doesn't
+ free the memory.*/
+#define V_RESET(vec) _##vec##_count=0
+
#endif
diff --git a/source/blender/blenkernel/BKE_verse.h b/source/blender/blenkernel/BKE_verse.h
new file mode 100644
index 00000000000..ee22081b03f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_verse.h
@@ -0,0 +1,586 @@
+/**
+ * $Id: BKE_verse.h 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* #define WITH_VERSE */
+
+#ifndef BKE_VERSE_H
+#define BKE_VERSE_H
+
+#include "DNA_listBase.h"
+#include "BLI_dynamiclist.h"
+
+#include "verse.h"
+#include "verse_ms.h"
+
+struct VNode;
+struct VerseEdge;
+
+/*
+ * Verse Edge Hash (similar to edit edge hash)
+ */
+#define VEDHASHSIZE (512*512)
+#define VEDHASH(a, b) ((a<b ? a : b) % VEDHASHSIZE)
+
+/*
+ * verse data: 4 float value
+ */
+typedef struct quat_real32_item {
+ struct quat_real32_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ real32 value[4];
+} quat_real32_item;
+
+/*
+ * verse data: 4 uint32 values
+ */
+typedef struct quat_uint32_item {
+ struct quat_uint32_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ uint32 value[4];
+} quat_uint32_item;
+
+/*
+ * verse data: 3 float values
+ */
+typedef struct vec_real32_item {
+ struct vec_real32_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ real32 value[3];
+} vec_real32_item;
+
+/*
+ * verse data: float value (weight)
+ */
+typedef struct real32_item {
+ struct real32_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ real32 value;
+} real32_item;
+
+/*
+ * verse data: uint32 value
+ */
+typedef struct uint32_item {
+ struct uint32_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ uint32 value;
+} uint32_item;
+
+/*
+ * verse data: uint8 value
+ */
+typedef struct uint8_item {
+ struct uint8_item *next, *prev;
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of item */
+ uint8 value;
+} uint8_item;
+
+/*
+ * verse data: vertex
+ */
+typedef struct VerseVert {
+ struct VerseVert *next, *prev;
+ /* verse data */
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of vertex */
+ real32 co[3]; /* x,y,z-coordinates of vertex */
+ real32 no[3]; /* normal of vertex */
+ /* blender internals */
+ short flag; /* flags: VERT_DELETED, VERT_RECEIVED, etc. */
+ void *vertex; /* pointer at EditVert or MVert */
+ int counter; /* counter of VerseFaces using this VerseVert */
+ union {
+ unsigned int index; /* counter need during transformation to mesh */
+ struct VerseVert *vvert;
+ } tmp; /* pointer at new created verse vert, it is
+ * used during duplicating geometry node */
+ float *cos; /* modified coordinates of vertex */
+ float *nos; /* modified normal vector */
+} VerseVert;
+
+/*
+ * structture used for verse edge hash
+ */
+typedef struct HashVerseEdge {
+ struct VerseEdge *vedge;
+ struct HashVerseEdge *next;
+} HashVerseEdge;
+
+/*
+ * fake verse data: edge
+ */
+typedef struct VerseEdge {
+ struct VerseEdge *next, *prev;
+ uint32 v0, v1; /* indexes of verse vertexes */
+ int counter; /* counter of verse faces using this edge */
+ struct HashVerseEdge hash; /* hash table */
+ union {
+ unsigned int index; /* temporary index of edge */
+ } tmp;
+} VerseEdge;
+
+/*
+ * verse data: polygon
+ */
+typedef struct VerseFace {
+ struct VerseFace *next, *prev;
+ /* verse data */
+ struct VLayer *vlayer; /* pointer at VerseLayer */
+ uint32 id; /* id of face */
+ struct VerseVert *vvert0; /* pointer at 1st VerseVert */
+ struct VerseVert *vvert1; /* pointer at 2nd VerseVert */
+ struct VerseVert *vvert2; /* pointer at 3th VerseVert */
+ struct VerseVert *vvert3; /* pointer at 4th VerseVert */
+ unsigned int v0, v1, v2, v3; /* indexes of VerseVerts ... needed during receiving */
+ /* blender internals */
+ char flag; /* flags: FACE_SEND_READY, FACE_SENT, FACE_RECEIVED, FACE_CHANGED*/
+ short counter; /* counter of missed VerseVertexes */
+ void *face; /* pointer at EditFace */
+ float no[3]; /* normal vector */
+ float *nos; /* modified normal vector */
+} VerseFace;
+
+/*
+ * verse data: layer
+ */
+typedef struct VLayer {
+ struct VLayer *next, *prev;
+ /* verse data*/
+ struct VNode *vnode; /* pointer at VerseNode */
+ uint16 id; /* id of layer */
+ char *name; /* name of layer */
+ VNGLayerType type; /* type of layer (VN_G_LAYER_VERTEX_XYZ, VN_G_LAYER_POLYGON_CORNER_UINT32) */
+ uint32 def_int; /* default integer value */
+ real64 def_real; /* default float value */
+ /* blender internals */
+ char flag; /* flags: LAYER_SENT, LAYER_RECEIVED, LAYER_DELETED, LAYER_OBSOLETE */
+ short content; /* type of content (VERTEX_LAYER, POLYGON_LAYER) */
+ struct DynamicList dl; /* vertexes, polygons, etc. */
+ struct ListBase queue; /* queue of vertexes, polygons, etc. waiting for sending to verse server */
+ struct ListBase orphans; /* list of versedata (polygons, etc.), that can be added to the DynamicList
+ * due to not received VerseVerts */
+ unsigned int counter; /* counter of sent items */
+ /* client dependent methods */
+ void (*post_layer_create)(struct VLayer *vlayer);
+ void (*post_layer_destroy)(struct VLayer *vlayer);
+} VLayer;
+
+/*
+ * verse data: link
+ */
+typedef struct VLink{
+ struct VLink *next, *prev;
+ /* verse data */
+ struct VerseSession *session; /* session pointer */
+ struct VNode *source; /* object VerseNode "pointing" at some other VerseNode */
+ struct VNode *target; /* VerseNode linked with some object node */
+ unsigned int id; /* id of VerseLink */
+ unsigned int target_id; /* some unknow id */
+ char *label; /* name/label of VerseLink */
+ /* blender internals */
+ char flag; /* flags: LINK_SEND_READY */
+ /* client dependent methods */
+ void (*post_link_set)(struct VLink *vlink);
+ void (*post_link_destroy)(struct VLink *vlink);
+} VLink;
+
+/*
+ * bitmap layer
+ */
+typedef struct VBitmapLayer {
+ struct VBitmapLayer *next, *prev;
+ /* verse data */
+ struct VNode *vnode; /* pointer at Verse Node */
+ VLayerID id; /* id of layer */
+ char *name; /* name of layer */
+ VNBLayerType type; /* type of layer (bits per channel) 1, 8, 16, 32, 64 */
+ void *data; /* dynamic allocated data */
+ /* blender internals */
+ char flag;
+} VBitmapLayer;
+
+/*
+ * data of bitmap node
+ */
+typedef struct VBitmapData {
+ struct DynamicList layers; /* dynamic list with access array of bitmap layers */
+ struct ListBase queue; /* queue of layers waiting for receiving from verse server */
+ uint16 width; /* width of all verse layers */
+ uint16 height; /* height of all verse layers */
+ uint16 depth; /* depth of bitmap 1 is 2D bitmap, >1 is 3D bitmap */
+ /* blender internals */
+ uint16 t_width; /* = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */
+ uint16 t_height; /* = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */
+ void *image; /* pointer at image */
+ /* client dependent methods */
+ void (*post_bitmap_dimension_set)(struct VNode *vnode);
+ void (*post_bitmap_layer_create)(struct VBitmapLayer *vblayer);
+ void (*post_bitmap_layer_destroy)(struct VBitmapLayer *vblayer);
+ void (*post_bitmap_tile_set)(struct VBitmapLayer *vblayer, unsigned int xs, unsigned int ys);
+}VBitmapData;
+
+/*
+ * data of geometry node
+ */
+typedef struct VGeomData {
+ struct DynamicList layers; /* dynamic list with access array of Layers */
+ struct VLink *vlink; /* pointer at VerseLink connecting object node and geom node */
+ struct ListBase queue; /* queue of our layers waiting for receiving from verse server */
+ void *mesh; /* pointer at Mesh (object node) */
+ void *editmesh; /* pointer at EditMesh (edit mode) */
+ struct HashVerseEdge *hash; /* verse edge hash */
+ struct ListBase edges; /* list of fake verse edges */
+ /* client dependent methods */
+ void (*post_vertex_create)(struct VerseVert *vvert);
+ void (*post_vertex_set_xyz)(struct VerseVert *vvert);
+ void (*post_vertex_delete)(struct VerseVert *vvert);
+ void (*post_vertex_free_constraint)(struct VerseVert *vvert);
+ void (*post_polygon_create)(struct VerseFace *vface);
+ void (*post_polygon_set_corner)(struct VerseFace *vface);
+ void (*post_polygon_delete)(struct VerseFace *vface);
+ void (*post_polygon_free_constraint)(struct VerseFace *vface);
+ void (*post_geometry_free_constraint)(struct VNode *vnode);
+ void (*post_polygon_set_uint8)(struct VerseFace *vface);
+} VGeomData;
+
+/*
+ * data of object node
+ */
+typedef struct VObjectData {
+ struct DynamicList links; /* dynamic list with access array of links between other nodes */
+ struct ListBase queue; /* queue of links waiting for sending and receiving from verse server */
+ float pos[3]; /* position of object VerseNode */
+ float quat[4]; /* rotation of object VerseNode stored in quat */
+ float scale[3]; /* scale of object VerseNode */
+ void *object; /* pointer at object */
+ short flag; /* flag: POS_RECEIVE_READY, ROT_RECEIVE_READY. SCALE_RECEIVE_READY */
+ /* client dependent methods */
+/* void (*post_transform)(struct VNode *vnode);*/
+ void (*post_transform_pos)(struct VNode *vnode);
+ void (*post_transform_rot)(struct VNode *vnode);
+ void (*post_transform_scale)(struct VNode *vnode);
+ void (*post_object_free_constraint)(struct VNode *vnode);
+} VObjectData;
+
+/*
+ * Verse Tag
+ */
+typedef struct VTag {
+ struct VTag *next, *prev;
+ /* verse data*/
+ struct VTagGroup *vtaggroup; /* pointer at Verse Tag Group */
+ uint16 id; /* id of this tag */
+ char *name; /* name of this tag*/
+ VNTagType type; /* type: VN_TAG_BOOLEAN, VN_TAG_UINT32, VN_TAG_REAL64, VN_TAG_REAL64_VEC3,
+ VN_TAG_LINK, VN_TAG_ANIMATION, VN_TAG_BLOB */
+ VNTag *tag; /* pointer at value (enum: vboolean, vuint32, vreal64, vstring,
+ vreal64_vec3, vlink, vanimation, vblob)*/
+ /* blender internals */
+ void *value; /* pointer at blender value */
+} VTag;
+
+/*
+ * Verse Tag Group (verse tags are grouped in tag groups)
+ */
+typedef struct VTagGroup {
+ struct VTagGroup *next, *prev;
+ /* verse data*/
+ struct VNode *vnode; /* pointer at Verse Node */
+ uint16 id; /* id of this tag group */
+ char *name; /* name of this tag group */
+ /* blender internals */
+ struct DynamicList tags; /* dynamic list with access array containing tags */
+ struct ListBase queue; /* list of tags waiting for receiving from verse server */
+ /* client dependent methods */
+ void (*post_tag_change)(struct VTag *vatg);
+ void (*post_taggroup_create)(struct VTagGroup *vtaggroup);
+} VTagGroup;
+
+ /*
+ * Verse Method Group
+ */
+typedef struct VMethodGroup
+{
+ struct VMethodGroup *next, *prev;
+ uint16 group_id;
+ char name[16];
+ struct ListBase methods;
+} VMethodGroup;
+
+/*
+ * Verse Method
+ */
+typedef struct VMethod
+{
+ struct VMethod *next, *prev;
+ uint16 id;
+ char name[500];
+ uint8 param_count;
+ VNOParamType *param_type;
+ char **param_name;
+} VMethod;
+
+/*
+ * Verse Node
+ */
+typedef struct VNode {
+ struct VNode *next, *prev;
+ /* verse data*/
+ struct VerseSession *session; /* session pointer */
+ VNodeID id; /* node id */
+ VNodeID owner_id; /* owner's id of this node */
+ char *name; /* name of this node */
+ uint32 type; /* type of node (V_NT_OBJECT, V_NT_GEOMETRY, V_NT_BITMAP) */
+ /* blender internals */
+ char flag; /* flags: NODE_SENT, NODE_RECEIVED, NODE_DELTED, NODE_OBSOLETE */
+ struct DynamicList taggroups; /* dynamic list with access array of taggroups */
+ struct ListBase methodgroups; /* method groups */
+ struct ListBase queue; /* list of taggroups waiting for receiving from verse server */
+ void *data; /* generic pointer at some data (VObjectData, VGeomData, ...) */
+ int counter; /* counter of verse link pointing at this vnode (vlink->target) */
+ /* client dependent methods */
+ void (*post_node_create)(struct VNode *vnode);
+ void (*post_node_destroy)(struct VNode *vnode);
+ void (*post_node_name_set)(struct VNode *vnode);
+#ifdef VERSECHAT
+ /* verse chat */
+ int chat_flag; /* CHAT_LOGGED, CHAT_NOTLOGGED */
+#endif
+} VNode;
+
+
+/*
+ * Verse Session: verse client can be connected to several verse servers
+ * it is neccessary to store some information about each session
+ */
+typedef struct VerseSession {
+ struct VerseSession *next, *prev;
+ /* verse data */
+ VSession *vsession; /* pointer at VSeesion (verse.h) */
+ uint32 avatar; /* id of avatar */
+ char *address; /* string containg IP/domain name of verse server and number of port */
+ void *connection; /* no clue */
+ uint8 *host_id; /* no clue */
+ /* blender internals */
+ short flag; /* flag: VERSE_CONNECTING, VERSE_CONNECTED */
+ DynamicList nodes; /* list of verse nodes */
+ ListBase queue; /* list of nodes waiting for sending to verse server */
+ unsigned int counter; /* count of events, when connection wasn't accepted */
+ /* client dependent methods */
+ void (*post_connect_accept)(struct VerseSession *session);
+ void (*post_connect_terminated)(struct VerseSession *session);
+ void (*post_connect_update)(struct VerseSession *session);
+} VerseSession;
+
+typedef struct VerseServer {
+ struct VerseServer *next, *prev;
+ char *name; /* human-readable server name */
+ char *ip; /* string containing IP/domain name of verse server and number of port */
+ short flag; /* flag: VERSE_CONNECTING, VERSE_CONNECTED */
+ struct VerseSession *session; /* pointer to related session */
+} VerseServer;
+/*
+ * list of post callback functions
+ */
+typedef struct PostCallbackFunction {
+ void (*function)(void *arg);
+ void *param;
+} PostCallbackFunction;
+
+/* VerseSession->flag */
+#define VERSE_CONNECTING 1
+#define VERSE_CONNECTED 2
+#define VERSE_AUTOSUBSCRIBE 4
+
+/* max VerseSession->counter value */
+#define MAX_UNCONNECTED_EVENTS 100
+
+/* VNode flags */
+#define NODE_SENT 1
+#define NODE_RECEIVED 2
+#define NODE_DELTED 4
+#define NODE_OBSOLETE 8
+
+#ifdef VERSECHAT
+#define CHAT_NOTLOGGED 0
+#define CHAT_LOGGED 1
+#endif
+
+/* VLayer flags */
+#define LAYER_SENT 1
+#define LAYER_RECEIVED 2
+#define LAYER_DELETED 4
+#define LAYER_OBSOLETE 8
+
+/* VLink->flag */
+#define LINK_SEND_READY 1
+
+/* VObjectData->flag */
+#define POS_RECEIVE_READY 1
+#define ROT_RECEIVE_READY 2
+#define SCALE_RECEIVE_READY 4
+#define POS_SEND_READY 8
+#define ROT_SEND_READY 16
+#define SCALE_SEND_READY 32
+
+/* VLayer->content */
+#define VERTEX_LAYER 0
+#define POLYGON_LAYER 1
+
+/* VerseVert->flag */
+#define VERT_DELETED 1 /* vertex delete command was received from verse server */
+#define VERT_RECEIVED 2 /* VerseVert was received from verse server (is not in sending queue) */
+#define VERT_LOCKED 4 /* VerseVert is ready to send local position to verse server */
+#define VERT_POS_OBSOLETE 8 /* position of vertex was changed during sending to verse server */
+#define VERT_OBSOLETE 16 /* vertex delete command was sent to verse server; it means, that
+ * no information related to this vertex shoudln't be sent to verse
+ * until verse vertex is completely deleted ... then this vertex id
+ * can be reused again for new vertex */
+
+/* VerseFace->flag */
+#define FACE_SEND_READY 1 /* VerseFace is ready for sending to verse server */
+#define FACE_RECEIVED 2 /* VerseFace was received from verse server */
+#define FACE_SENT 4 /* VerseFace was sent to verse server and we expect receiving from verse server */
+#define FACE_DELETED 8 /* delete command was sent to verse server */
+#define FACE_CHANGED 16 /* VerseFace was only changed not created */
+#define FACE_OBSOLETE 32 /* VerseFace was changed during sending to verse server */
+
+/* Queue type */
+#define VERSE_NODE 1
+#define VERSE_LINK 2
+#define VERSE_LAYER 3
+#define VERSE_VERT 4
+#define VERSE_FACE 5
+
+#define VERSE_TAG 6
+#define VERSE_TAG_GROUP 7
+
+#define VERSE_VERT_UINT32 8
+#define VERSE_VERT_REAL32 9
+#define VERSE_VERT_VEC_REAL32 10
+
+#define VERSE_FACE_UINT8 11
+#define VERSE_FACE_UINT32 12
+#define VERSE_FACE_REAL32 13
+#define VERSE_FACE_QUAT_UINT32 14
+#define VERSE_FACE_QUAT_REAL32 15
+
+/* Verse Bitmap Layer flags */
+#define VBLAYER_SUBSCRIBED 1
+
+/* function prototypes */
+
+/* functions from verse_session.c */
+void set_verse_session_callbacks(void);
+struct VerseSession *versesession_from_vsession(VSession *vsession);
+struct VerseSession *current_verse_session(void);
+struct VerseSession *create_verse_session(const char *name, const char *pass, const char *address, uint8 *expected_key);
+void free_verse_session(struct VerseSession *session);
+void b_verse_update(void);
+void b_verse_ms_get(void);
+void b_verse_connect(char *address);
+void end_verse_session(struct VerseSession *session);
+void end_all_verse_sessions(void);
+
+/* functions from verse_node.c */
+void send_verse_tag(struct VTag *vtag);
+void send_verse_taggroup(struct VTagGroup *vtaggroup);
+void send_verse_node(struct VNode *vnode);
+void free_verse_node_data(struct VNode *vnode);
+void free_verse_node(struct VNode *vnode);
+struct VNode* lookup_vnode(VerseSession *session, VNodeID node_id);
+struct VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id);
+void set_node_callbacks(void);
+
+/* functions from verse_object_node.c */
+struct VLink *find_unsent_parent_vlink(struct VerseSession *session, struct VNode *vnode);
+struct VLink *find_unsent_child_vlink(struct VerseSession *session, struct VNode *vnode);
+struct VLink *create_verse_link(VerseSession *session, struct VNode *source, struct VNode *target, uint16 link_id, uint32 target_id, const char *label);
+void send_verse_object_position(struct VNode *vnode);
+void send_verse_object_rotation(struct VNode *vnode);
+void send_verse_object_scale(struct VNode *vnode);
+void send_verse_link(struct VLink *vlink);
+
+void free_object_data(struct VNode *vnode);
+void set_object_callbacks(void);
+struct VObjectData *create_object_data(void);
+
+
+/* functions from verse_method.c */
+void free_verse_methodgroup(VMethodGroup *vmg);
+#ifdef VERSECHAT
+void send_say(const char *chan, const char *utter);
+void send_login(struct VNode *vnode);
+void send_logout(struct VNode *vnode);
+void send_join(struct VNode *vnode, const char *chan);
+void send_leave(struct VNode *vnode, const char *chan);
+#endif
+void set_method_callbacks(void);
+
+/* functions from verse_geometry_node.c */
+struct VerseFace* create_verse_face(struct VLayer *vlayer, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+struct VerseVert* create_verse_vertex(struct VLayer *vlayer, uint32 vertex_id, real32 x, real32 y, real32 z);
+struct VLayer *create_verse_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real);
+struct VGeomData *create_geometry_data(void);
+
+void send_verse_layer(struct VLayer *vlayer);
+
+void send_verse_face_corner_quat_real32(struct quat_real32_item *item, short type);
+void send_verse_face_corner_quat_uint32(struct quat_uint32_item *item, short type);
+void send_verse_face_real32(struct real32_item *item, short type);
+void send_verse_face_uint32(struct uint32_item *item, short type);
+void send_verse_face_uint8(struct uint8_item *item, short type);
+
+void send_verse_vert_vec_real32(struct vec_real32_item *item, short type);
+void send_verse_vert_real32(struct real32_item *item, short type);
+void send_verse_vert_uint32(struct uint32_item *item, short type);
+
+void send_verse_vertex_delete(struct VerseVert *vvert);
+void send_verse_vertex(struct VerseVert *vvert);
+void send_verse_face_delete(struct VerseFace *vface);
+
+void destroy_geometry(struct VNode *vnode);
+
+struct VLayer* find_verse_layer_type(struct VGeomData *geom, short content);
+void add_item_to_send_queue(struct ListBase *lb, void *item, short type);
+void free_geom_data(struct VNode *vnode);
+void set_geometry_callbacks(void);
+
+/* functions prototypes from verse_bitmap.c */
+void set_bitmap_callbacks(void);
+void free_bitmap_layer_data(struct VBitmapLayer *vblayer);
+struct VBitmapLayer *create_bitmap_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNBLayerType type);
+void free_bitmap_node_data(struct VNode *vnode);
+struct VBitmapData *create_bitmap_data(void);
+
+#endif
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index dbc990d0613..ae522b029cb 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
+incs += ' ../bmesh'
incs += ' ' + env['BF_OPENGL_INC']
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c
index 177bb4a136b..0f372790a9d 100644
--- a/source/blender/blenkernel/intern/BME_conversions.c
+++ b/source/blender/blenkernel/intern/BME_conversions.c
@@ -268,7 +268,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
/*copy face corner data*/
- CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
+ CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0);
/*initialize memory pools*/
CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
@@ -463,7 +463,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
/*copy face corner data*/
- CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
+ CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata, 0, 0);
/*initialize memory pools*/
CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
@@ -475,10 +475,10 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
mvert = dm->getVertArray(dm);
medge = dm->getEdgeArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
@@ -574,7 +574,8 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
}
/*convert back to mesh*/
- result = CDDM_from_template(dm,totvert,totedge,totface);
+ /*BMESH_TODO this should add in mloops and mpolys as well*/
+ result = CDDM_from_template(dm,totvert,totedge,totface, 0, 0);
CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
@@ -613,7 +614,7 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
}
}
if(totface){
- mface = CDDM_get_faces(result);
+ mface = CDDM_get_tessfaces(result);
/*make faces*/
for(i=0,f=bm->polys.first;f;f=f->next){
mf = &mface[i];
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index cee032f364e..c2fc626b8e1 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -2035,7 +2035,7 @@ int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
return ss->eMap->numEntries;
}
-int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
+int ccgSubSurf_getNumTessFaces(CCGSubSurf *ss) {
return ss->fMap->numEntries;
}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index fbd0aecc0a5..c7716314899 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -73,7 +73,7 @@ CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, i
int ccgSubSurf_getNumVerts (CCGSubSurf *ss);
int ccgSubSurf_getNumEdges (CCGSubSurf *ss);
-int ccgSubSurf_getNumFaces (CCGSubSurf *ss);
+int ccgSubSurf_getNumTessFaces (CCGSubSurf *ss);
int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss);
int ccgSubSurf_getEdgeSize (CCGSubSurf *ss);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 090f256ab9f..a1068080927 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -76,6 +76,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
#include "BKE_bvhutils.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -124,9 +125,9 @@ static MFace *dm_getFaceArray(DerivedMesh *dm)
if (!mface) {
mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL,
- dm->getNumFaces(dm));
+ dm->getNumTessFaces(dm));
CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
- dm->copyFaceArray(dm, mface);
+ dm->copyTessFaceArray(dm, mface);
}
return mface;
@@ -154,40 +155,73 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
static MFace *dm_dupFaceArray(DerivedMesh *dm)
{
- MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
+ MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
"dm_dupFaceArray tmp");
- if(tmp) dm->copyFaceArray(dm, tmp);
+ if(tmp) dm->copyTessFaceArray(dm, tmp);
return tmp;
}
+CustomData *dm_getVertCData(DerivedMesh *dm)
+{
+ return &dm->vertData;
+}
+
+CustomData *dm_getEdgeCData(DerivedMesh *dm)
+{
+ return &dm->edgeData;
+}
+
+CustomData *dm_getFaceCData(DerivedMesh *dm)
+{
+ return &dm->faceData;
+}
+
+CustomData *dm_getLoopCData(DerivedMesh *dm)
+{
+ return &dm->loopData;
+}
+
+CustomData *dm_getPolyCData(DerivedMesh *dm)
+{
+ return &dm->polyData;
+}
+
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
dm->getVertArray = dm_getVertArray;
dm->getEdgeArray = dm_getEdgeArray;
- dm->getFaceArray = dm_getFaceArray;
+ dm->getTessFaceArray = dm_getFaceArray;
dm->dupVertArray = dm_dupVertArray;
dm->dupEdgeArray = dm_dupEdgeArray;
- dm->dupFaceArray = dm_dupFaceArray;
+ dm->dupTessFaceArray = dm_dupFaceArray;
+
+ dm->getVertDataLayout = dm_getVertCData;
+ dm->getEdgeDataLayout = dm_getEdgeCData;
+ dm->getTessFaceDataLayout = dm_getFaceCData;
+ dm->getLoopDataLayout = dm_getLoopCData;
+ dm->getFaceDataLayout = dm_getPolyCData;
dm->getVertData = DM_get_vert_data;
dm->getEdgeData = DM_get_edge_data;
- dm->getFaceData = DM_get_face_data;
+ dm->getTessFaceData = DM_get_face_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getFaceDataArray = DM_get_face_data_layer;
+ dm->getTessFaceDataArray = DM_get_face_data_layer;
bvhcache_init(&dm->bvhCache);
}
-void DM_init(DerivedMesh *dm,
- int numVerts, int numEdges, int numFaces)
+void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPoly)
{
dm->numVertData = numVerts;
dm->numEdgeData = numEdges;
dm->numFaceData = numFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPoly;
DM_init_funcs(dm);
@@ -195,7 +229,8 @@ void DM_init(DerivedMesh *dm,
}
void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
- int numVerts, int numEdges, int numFaces)
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys)
{
CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
CD_CALLOC, numVerts);
@@ -203,10 +238,16 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
CD_CALLOC, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_CALLOC, numFaces);
+ CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, numLoops);
+ CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, numPolys);
dm->numVertData = numVerts;
dm->numEdgeData = numEdges;
dm->numFaceData = numFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPolys;
DM_init_funcs(dm);
@@ -221,6 +262,8 @@ int DM_release(DerivedMesh *dm)
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numFaceData);
+ CustomData_free(&dm->loopData, dm->numLoopData);
+ CustomData_free(&dm->polyData, dm->numPolyData);
return 1;
}
@@ -228,28 +271,105 @@ int DM_release(DerivedMesh *dm)
CustomData_free_temporary(&dm->vertData, dm->numVertData);
CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
CustomData_free_temporary(&dm->faceData, dm->numFaceData);
+ CustomData_free_temporary(&dm->loopData, dm->numLoopData);
+ CustomData_free_temporary(&dm->polyData, dm->numPolyData);
return 0;
}
}
+void dm_add_polys_from_iter(CustomData *ldata, CustomData *pdata, DerivedMesh *dm, int totloop)
+{
+ DMFaceIter *iter = dm->newFaceIter(dm);
+ DMLoopIter *liter;
+ MPoly *mpoly;
+ MLoop *mloop;
+ int i;
+
+ mloop = MEM_callocN(sizeof(MLoop)*totloop, "MLoop from dm_add_polys_from_iter");
+ mpoly = MEM_callocN(sizeof(MPoly)*dm->getNumFaces(dm), "MPoly from dm_add_polys_from_iter");
+
+ CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
+ CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, dm->getNumFaces(dm));
+
+ i = 0;
+ for (; !iter->done; iter->step(iter), mpoly++) {
+ mpoly->flag = iter->flags;
+ mpoly->loopstart = i;
+ mpoly->totloop = iter->len;
+ mpoly->mat_nr = iter->mat_nr;
+
+ liter = iter->getLoopsIter(iter);
+ for (; !liter->done; liter->step(liter), mloop++, i++) {
+ mloop->v = liter->vindex;
+ mloop->e = liter->eindex;
+ }
+ }
+ iter->free(iter);
+}
+
+void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
+{
+ DMFaceIter *iter = source->newFaceIter(source);
+ DMLoopIter *liter;
+ MPoly *mpoly;
+ MLoop *mloop;
+ int i;
+
+ mloop = MEM_callocN(sizeof(MLoop)*source->numLoopData, "MLoop from dm_add_polys_from_iter");
+ mpoly = MEM_callocN(sizeof(MPoly)*source->getNumFaces(source), "MPoly from dm_add_polys_from_iter");
+
+ CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData);
+ CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->getNumFaces(source));
+
+ target->numLoopData = source->numLoopData;
+ target->numPolyData = source->numPolyData;
+
+ i = 0;
+ for (; !iter->done; iter->step(iter), mpoly++) {
+ mpoly->flag = iter->flags;
+ mpoly->loopstart = i;
+ mpoly->totloop = iter->len;
+ mpoly->mat_nr = iter->mat_nr;
+
+ liter = iter->getLoopsIter(iter);
+ for (; !liter->done; liter->step(liter), mloop++, i++) {
+ mloop->v = liter->vindex;
+ mloop->e = liter->eindex;
+ }
+ }
+ iter->free(iter);
+}
+
void DM_to_mesh(DerivedMesh *dm, Mesh *me)
{
/* dm might depend on me, so we need to do everything with a local copy */
Mesh tmp = *me;
- int totvert, totedge, totface;
+ DMFaceIter *iter;
+ int totvert, totedge, totface, totloop, totpoly;
memset(&tmp.vdata, 0, sizeof(tmp.vdata));
memset(&tmp.edata, 0, sizeof(tmp.edata));
memset(&tmp.fdata, 0, sizeof(tmp.fdata));
+ memset(&tmp.ldata, 0, sizeof(tmp.ldata));
+ memset(&tmp.pdata, 0, sizeof(tmp.pdata));
totvert = tmp.totvert = dm->getNumVerts(dm);
totedge = tmp.totedge = dm->getNumEdges(dm);
- totface = tmp.totface = dm->getNumFaces(dm);
+ totface = tmp.totface = dm->getNumTessFaces(dm);
+ totpoly = tmp.totpoly = dm->getNumFaces(dm);
+
+ totloop = 0;
+ for (iter=dm->newFaceIter(dm); !iter->done; iter->step(iter)) {
+ totloop += iter->len;
+ }
+ iter->free(iter);
CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
+ CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop);
+ CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly);
/* not all DerivedMeshes store their verts/edges/faces in CustomData, so
we set them here in case they are missing */
@@ -258,13 +378,18 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
if(!CustomData_has_layer(&tmp.edata, CD_MEDGE))
CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
if(!CustomData_has_layer(&tmp.fdata, CD_MFACE))
- CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface);
+ CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupTessFaceArray(dm), totface);
+
+ if(!CustomData_has_layer(&tmp.fdata, CD_MPOLY))
+ dm_add_polys_from_iter(&tmp.ldata, &tmp.pdata, dm, totloop);
mesh_update_customdata_pointers(&tmp);
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
/* if the number of verts has changed, remove invalid data */
if(tmp.totvert != me->totvert) {
@@ -356,13 +481,27 @@ void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest,
source_index, dest_index, count);
}
-void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_copy_tessface_data(DerivedMesh *source, DerivedMesh *dest,
int source_index, int dest_index, int count)
{
CustomData_copy_data(&source->faceData, &dest->faceData,
source_index, dest_index, count);
}
+void DM_copy_loop_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->loopData, &dest->loopData,
+ source_index, dest_index, count);
+}
+
+void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->polyData, &dest->polyData,
+ source_index, dest_index, count);
+}
+
void DM_free_vert_data(struct DerivedMesh *dm, int index, int count)
{
CustomData_free_elem(&dm->vertData, index, count);
@@ -373,11 +512,21 @@ void DM_free_edge_data(struct DerivedMesh *dm, int index, int count)
CustomData_free_elem(&dm->edgeData, index, count);
}
-void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count)
{
CustomData_free_elem(&dm->faceData, index, count);
}
+void DM_free_loop_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->loopData, index, count);
+}
+
+void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->polyData, index, count);
+}
+
void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
int *src_indices, float *weights,
int count, int dest_index)
@@ -395,7 +544,7 @@ void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
weights, (float*)vert_weights, count, dest_index);
}
-void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_interp_tessface_data(DerivedMesh *source, DerivedMesh *dest,
int *src_indices,
float *weights, FaceVertWeight *vert_weights,
int count, int dest_index)
@@ -404,11 +553,28 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
weights, (float*)vert_weights, count, dest_index);
}
-void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
+
+void DM_swap_tessface_data(DerivedMesh *dm, int index, int *corner_indices)
{
CustomData_swap(&dm->faceData, index, corner_indices);
}
+void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
+{
+ CustomData_interp(&source->loopData, &dest->loopData, src_indices,
+ weights, NULL, count, dest_index);
+}
+
+void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
+{
+ CustomData_interp(&source->polyData, &dest->polyData, src_indices,
+ weights, NULL, count, dest_index);
+}
+
///
static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
@@ -437,9 +603,9 @@ typedef struct {
float (*faceNos)[3];
} EditMeshDerivedMesh;
-static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
+static void emDM_foreachMappedVert(void *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditVert *eve;
int i;
@@ -451,9 +617,9 @@ static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData,
}
}
}
-static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
+static void emDM_foreachMappedEdge(void *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditEdge *eed;
int i;
@@ -469,9 +635,9 @@ static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData,
func(userData, i, eed->v1->co, eed->v2->co);
}
}
-static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+static void emDM_drawMappedEdges(void *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditEdge *eed;
int i;
@@ -500,13 +666,13 @@ static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us
glEnd();
}
}
-static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
+static void emDM_drawEdges(void *dm, int drawLooseEdges)
{
emDM_drawMappedEdges(dm, NULL, NULL);
}
-static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData)
+static void emDM_drawMappedEdgesInterp(void *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditEdge *eed;
int i;
@@ -540,9 +706,9 @@ static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(vo
}
}
-static void emDM_drawUVEdges(DerivedMesh *dm)
+static void emDM_drawUVEdges(void *dm)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditFace *efa;
MTFace *tf;
@@ -591,9 +757,9 @@ static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[
VecMulf(cent, 0.33333333333f);
}
}
-static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
+static void emDM_foreachMappedFaceCenter(void *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditVert *eve;
EditFace *efa;
float cent[3];
@@ -609,9 +775,9 @@ static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
}
}
-static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
+static void emDM_drawMappedFaces(void *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditFace *efa;
int i, draw;
@@ -696,12 +862,12 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
}
}
-static void emDM_drawFacesTex_common(DerivedMesh *dm,
+static void emDM_drawFacesTex_common(void *dm,
int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
int (*drawParamsMapped)(void *userData, int index),
void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditMesh *em= emdm->em;
float (*vertexCos)[3]= emdm->vertexCos;
float (*vertexNos)[3]= emdm->vertexNos;
@@ -864,21 +1030,21 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
}
}
-static void emDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
+static void emDM_drawFacesTex(void *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
}
-static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+static void emDM_drawMappedFacesTex(void *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
-static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
+static void emDM_drawMappedFacesGLSL(void *dm,
int (*setMaterial)(int, void *attribs),
int (*setDrawOptions)(void *userData, int index), void *userData)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditMesh *em= emdm->em;
float (*vertexCos)[3]= emdm->vertexCos;
float (*vertexNos)[3]= emdm->vertexNos;
@@ -1024,15 +1190,15 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
}
}
-static void emDM_drawFacesGLSL(DerivedMesh *dm,
+static void emDM_drawFacesGLSL(void *dm,
int (*setMaterial)(int, void *attribs))
{
- dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+ ((DerivedMesh*)dm)->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
-static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+static void emDM_getMinMax(void *dm, float min_r[3], float max_r[3])
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditVert *eve;
int i;
@@ -1048,28 +1214,28 @@ static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
}
}
-static int emDM_getNumVerts(DerivedMesh *dm)
+static int emDM_getNumVerts(void *dm)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
return BLI_countlist(&emdm->em->verts);
}
-static int emDM_getNumEdges(DerivedMesh *dm)
+static int emDM_getNumEdges(void *dm)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
return BLI_countlist(&emdm->em->edges);
}
-static int emDM_getNumFaces(DerivedMesh *dm)
+static int emDM_getNumTessFaces(void *dm)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
return BLI_countlist(&emdm->em->faces);
}
-static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+static void emDM_getVert(void *dm, int index, MVert *vert_r)
{
EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
int i;
@@ -1087,7 +1253,7 @@ static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
}
-static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+static void emDM_getEdge(void *dm, int index, MEdge *edge_r)
{
EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
EditEdge *ee = em->edges.first;
@@ -1122,7 +1288,7 @@ static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
}
}
-static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+static void emDM_getFace(void *dm, int index, MFace *face_r)
{
EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
EditFace *ef = em->faces.first;
@@ -1164,7 +1330,7 @@ static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
test_index_face(face_r, NULL, 0, ef->v4?4:3);
}
-static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
+static void emDM_copyVertArray(void *dm, MVert *vert_r)
{
EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
@@ -1182,7 +1348,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
}
}
-static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+static void emDM_copyEdgeArray(void *dm, MEdge *edge_r)
{
EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
EditEdge *ee = em->edges.first;
@@ -1210,7 +1376,7 @@ static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
}
}
-static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+static void emDM_copyFaceArray(void *dm, MFace *face_r)
{
EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
EditFace *ef = em->faces.first;
@@ -1235,9 +1401,9 @@ static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
}
}
-static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+static void *emDM_getFaceDataArray(void *dm, int type)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
EditMesh *em= emdm->em;
EditFace *efa;
char *data, *emdata;
@@ -1258,8 +1424,8 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
size = CustomData_sizeof(type);
DM_add_face_layer(dm, type, CD_CALLOC, NULL);
- index = CustomData_get_layer_index(&dm->faceData, type);
- dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+ index = CustomData_get_layer_index(&emdm->dm.faceData, type);
+ emdm->dm.faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
data = datalayer = DM_get_face_data_layer(dm, type);
for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
@@ -1272,9 +1438,9 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
return datalayer;
}
-static void emDM_release(DerivedMesh *dm)
+static void emDM_release(void *dm)
{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ EditMeshDerivedMesh *emdm= dm;
if (DM_release(dm)) {
if (emdm->vertexCos) {
@@ -1293,21 +1459,22 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
DM_init(&emdm->dm, BLI_countlist(&em->verts),
- BLI_countlist(&em->edges), BLI_countlist(&em->faces));
+ BLI_countlist(&em->edges), BLI_countlist(&em->faces),
+ 0, 0);
emdm->dm.getMinMax = emDM_getMinMax;
emdm->dm.getNumVerts = emDM_getNumVerts;
emdm->dm.getNumEdges = emDM_getNumEdges;
- emdm->dm.getNumFaces = emDM_getNumFaces;
+ emdm->dm.getNumTessFaces = emDM_getNumTessFaces;
emdm->dm.getVert = emDM_getVert;
emdm->dm.getEdge = emDM_getEdge;
- emdm->dm.getFace = emDM_getFace;
+ emdm->dm.getTessFace = emDM_getFace;
emdm->dm.copyVertArray = emDM_copyVertArray;
emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
- emdm->dm.copyFaceArray = emDM_copyFaceArray;
- emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
+ emdm->dm.copyTessFaceArray = emDM_copyFaceArray;
+ emdm->dm.getTessFaceDataArray = emDM_getFaceDataArray;
emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
@@ -1417,37 +1584,36 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
return dm;
}
-static float *get_editmesh_orco_verts(EditMesh *em)
+static float *get_editbmesh_orco_verts(BMEditMesh *em)
{
- EditVert *eve;
+ BMIter iter;
+ BMVert *eve;
float *orco;
int a, totvert;
/* these may not really be the orco's, but it's only for preview.
* could be solver better once, but isn't simple */
- totvert= 0;
- for(eve=em->verts.first; eve; eve=eve->next)
- totvert++;
+ totvert= em->bm->totvert;
orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
- for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (a=0; eve; eve=BMIter_Step(&iter), a+=3)
VECCOPY(orco+a, eve->co);
return orco;
}
/* orco custom data layer */
-
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em)
{
DerivedMesh *dm;
float (*orco)[3];
if(em) {
- dm= CDDM_from_editmesh(em, me);
- orco= (float(*)[3])get_editmesh_orco_verts(em);
+ dm= CDDM_from_BMEditMesh(em, me);
+ orco= (float(*)[3])get_editbmesh_orco_verts(em);
}
else {
dm= CDDM_from_mesh(me, ob);
@@ -1461,7 +1627,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
return dm;
}
-static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_orco_dm(Object *ob, BMEditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
{
float (*orco)[3], (*layerorco)[3];
int totvert;
@@ -1477,7 +1643,7 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *
dm->getVertCos(dm, orco);
}
else {
- if(em) orco= (float(*)[3])get_editmesh_orco_verts(em);
+ if(em) orco= (float(*)[3])get_editbmesh_orco_verts(em);
else orco= (float(*)[3])get_mesh_orco_verts(ob);
}
@@ -1839,21 +2005,24 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
BLI_linklist_free(datamasks, NULL);
}
-static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
+static float (*editbmesh_getVertexCos(BMEditMesh *em, int *numVerts_r))[3]
{
- int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
+ int i, numVerts = *numVerts_r = em->bm->totvert;
float (*cos)[3];
- EditVert *eve;
+ BMIter iter;
+ BMVert *eve;
cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
- for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
+
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
VECCOPY(cos[i], eve->co);
}
return cos;
}
-static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
+static int editbmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -1867,7 +2036,7 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
return 1;
}
-static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r,
+static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r,
DerivedMesh **final_r,
CustomDataMask dataMask)
{
@@ -1882,7 +2051,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
modifiers_clearErrors(ob);
if(cage_r && cageIndex == -1) {
- *cage_r = getEditMeshDerivedMesh(em, ob, NULL);
+ *cage_r = getEditDerivedBMesh(em, ob, NULL);
}
dm = NULL;
@@ -1899,7 +2068,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
md->scene= scene;
- if(!editmesh_modifier_is_enabled(md, dm))
+ if(!editbmesh_modifier_is_enabled(md, dm))
continue;
/* add an orco layer if needed by this modifier */
@@ -1927,7 +2096,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
dm->getVertCos(dm, deformedVerts);
} else {
- deformedVerts = editmesh_getVertexCos(em, &numVerts);
+ deformedVerts = editbmesh_getVertexCos(em, &numVerts);
}
}
@@ -1951,7 +2120,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
}
} else {
- dm = CDDM_from_editmesh(em, ob->data);
+ dm = CDDM_from_BMEditMesh(em, ob->data);
if(deformedVerts) {
CDDM_apply_vert_coords(dm, deformedVerts);
@@ -2006,7 +2175,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
*cage_r = dm;
} else {
*cage_r =
- getEditMeshDerivedMesh(em, ob,
+ getEditDerivedBMesh(em, ob,
deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
@@ -2030,7 +2199,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
} else if (!deformedVerts && cage_r && *cage_r) {
*final_r = *cage_r;
} else {
- *final_r = getEditMeshDerivedMesh(em, ob, deformedVerts);
+ *final_r = getEditDerivedBMesh(em, ob, deformedVerts);
deformedVerts = NULL;
}
@@ -2100,7 +2269,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
}
-static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
+static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
float min[3], max[3];
@@ -2119,7 +2288,7 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust
em->derivedCage = NULL;
}
- editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
+ editbmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
em->lastDataMask = dataMask;
INIT_MINMAX(min, max);
@@ -2134,10 +2303,10 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust
em->derivedCage->needsFree = 0;
}
-void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask)
+void makeDerivedMesh(Scene *scene, Object *ob, BMEditMesh *em, CustomDataMask dataMask)
{
if (em) {
- editmesh_build_data(scene, ob, em, dataMask);
+ editbmesh_build_data(scene, ob, em, dataMask);
} else {
mesh_build_data(scene, ob, dataMask);
}
@@ -2227,7 +2396,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
/***/
-DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r,
+DerivedMesh *editbmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, BMEditMesh *em, DerivedMesh **final_r,
CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
@@ -2235,27 +2404,27 @@ DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, E
*/
if(!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
- editmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(scene, obedit, em, dataMask);
*final_r = em->derivedFinal;
return em->derivedCage;
}
-DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
+DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
if(!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
- editmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(scene, obedit, em, dataMask);
return em->derivedCage;
}
-DerivedMesh *editmesh_get_derived_base(Object *obedit, EditMesh *em)
+DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
{
- return getEditMeshDerivedMesh(em, obedit, NULL);
+ return getEditDerivedBMesh(em, obedit, NULL);
}
@@ -2317,7 +2486,7 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
/* ********* crazyspace *************** */
-int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
+int editbmesh_get_first_deform_matrices(Object *ob, BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -2336,13 +2505,13 @@ int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deform
for(i = 0; md && i <= cageIndex; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if(!editmesh_modifier_is_enabled(md, dm))
+ if(!editbmesh_modifier_is_enabled(md, dm))
continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
if(!defmats) {
- dm= getEditMeshDerivedMesh(em, ob, NULL);
- deformedVerts= editmesh_getVertexCos(em, &numVerts);
+ dm= getEditDerivedBMesh(em, ob, NULL);
+ deformedVerts= editbmesh_getVertexCos(em, &numVerts);
defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
for(a=0; a<numVerts; a++)
@@ -2357,7 +2526,7 @@ int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deform
}
for(; md && i <= cageIndex; md = md->next, i++)
- if(editmesh_modifier_is_enabled(md, dm) && modifier_isDeformer(md))
+ if(editbmesh_modifier_is_enabled(md, dm) && modifier_isDeformer(md))
numleft++;
if(dm)
@@ -2389,11 +2558,11 @@ void DM_add_tangent_layer(DerivedMesh *dm)
/* check we have all the needed layers */
totvert= dm->getNumVerts(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
mvert= dm->getVertArray(dm);
- mface= dm->getFaceArray(dm);
- mtface= dm->getFaceDataArray(dm, CD_MTFACE);
+ mface= dm->getTessFaceArray(dm);
+ mtface= dm->getTessFaceDataArray(dm, CD_MTFACE);
if(!mtface) {
orco= dm->getVertDataArray(dm, CD_ORCO);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 6c1b8eb9000..7d9d261f306 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -68,6 +68,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -450,7 +451,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
Scene *sce = NULL;
Group *group = NULL;
GroupObject * go = NULL;
- EditMesh *em;
+ BMEditMesh *em;
float vec[3], no[3], pmat[4][4];
int lay, totvert, a, oblay;
@@ -459,11 +460,10 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
- em = BKE_mesh_get_editmesh(me);
+ em = me->edit_btmesh;
if(em) {
- dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
- BKE_mesh_end_editmesh(me, em);
+ dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
} else
dm= mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
@@ -566,34 +566,31 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
Scene *sce = NULL;
Group *group = NULL;
GroupObject *go = NULL;
- EditMesh *em;
+ BMEditMesh *em;
float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
Mat4CpyMat4(pmat, par->obmat);
-
- em = BKE_mesh_get_editmesh(me);
+ em = me->edit_btmesh;
+
if(em) {
int totvert;
+ dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
- dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
-
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
- dm->copyFaceArray(dm, mface);
+ dm->copyTessFaceArray(dm, mface);
totvert= dm->getNumVerts(dm);
mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
dm->copyVertArray(dm, mvert);
-
- BKE_mesh_end_editmesh(me, em);
}
else {
dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
- totface= dm->getNumFaces(dm);
- mface= dm->getFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
+ mface= dm->getTessFaceArray(dm);
mvert= dm->getVertArray(dm);
}
diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c
index eb3aefe7ee6..b6d1f7612b0 100644
--- a/source/blender/blenkernel/intern/booleanops.c
+++ b/source/blender/blenkernel/intern/booleanops.c
@@ -178,14 +178,14 @@ static int FaceIt_Done(CSG_IteratorPtr it)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt * iterator = (FaceIt *)it;
- return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
+ return(iterator->pos >= iterator->dm->getNumTessFaces(iterator->dm));
}
static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt *face_it = (FaceIt *)it;
- MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
+ MFace *mfaces = face_it->dm->getTessFaceArray(face_it->dm);
MFace *mface = &mfaces[face_it->pos];
/* reverse face vertices if necessary */
@@ -259,7 +259,7 @@ static void FaceIt_Construct(
output->Fill = FaceIt_Fill;
output->Done = FaceIt_Done;
output->Reset = FaceIt_Reset;
- output->num_elements = it->dm->getNumFaces(it->dm);
+ output->num_elements = it->dm->getNumTessFaces(it->dm);
output->it = it;
}
@@ -309,8 +309,8 @@ static void InterpCSGFace(
MFace *mface, *orig_mface;
int j;
- mface = CDDM_get_face(dm, index);
- orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
+ mface = CDDM_get_tessface(dm, index);
+ orig_mface = orig_dm->getTessFaceArray(orig_dm) + orig_index;
// get the vertex coordinates from the original mesh
orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
@@ -358,7 +358,7 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
int i;
// create a new DerivedMesh
- result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements, 0, 0);
CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
CD_DEFAULT, face_it->num_elements);
CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
@@ -398,16 +398,16 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
face_it->Step(face_it->it);
// find the original mesh and data
- orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
- orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
+ orig_ob = (csgface.orig_face < dm1->getNumTessFaces(dm1))? ob1: ob2;
+ orig_dm = (csgface.orig_face < dm1->getNumTessFaces(dm1))? dm1: dm2;
orig_me = (orig_ob == ob1)? me1: me2;
- orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
+ orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumTessFaces(dm1);
// copy all face layers, including mface
CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
// set mface
- mface = CDDM_get_face(result, i);
+ mface = CDDM_get_tessface(result, i);
mface->v1 = csgface.vertex_index[0];
mface->v2 = csgface.vertex_index[1];
mface->v3 = csgface.vertex_index[2];
@@ -440,6 +440,8 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
CDDM_calc_edges(result);
CDDM_calc_normals(result);
+ CDDM_tessfaces_to_faces(result);
+
return result;
}
@@ -473,7 +475,7 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
DerivedMesh *result = NULL;
if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
+ if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) return 0;
// we map the final object back into ob's local coordinate space. For this
// we need to compute the inverse transform from global to ob (inv_mat),
@@ -505,7 +507,7 @@ DerivedMesh *NewBooleanDerivedMesh_intern(
}
BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
- BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
+ BuildMeshDescriptors(dm, ob, dm_select->getNumTessFaces(dm_select) , &fd_2, &vd_2);
bool_op = CSG_NewBooleanFunction();
@@ -559,7 +561,7 @@ int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
/* put some checks in for nice user feedback */
if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
+ if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select))
{
MEM_freeN(mat);
return -1;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index d9e005811d0..08bcd9c2820 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -532,7 +532,7 @@ BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float
data->mesh = mesh;
data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
- data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
data->sphere_radius = epsilon;
}
@@ -549,9 +549,9 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
if(tree == NULL)
{
int i;
- int numFaces= mesh->getNumFaces(mesh);
+ int numFaces= mesh->getNumTessFaces(mesh);
MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
- MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ MFace *face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
if(vert != NULL && face != NULL)
{
@@ -597,7 +597,7 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
data->mesh = mesh;
data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
- data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
data->sphere_radius = epsilon;
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 706eece108c..120e1360d48 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -44,6 +44,7 @@
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@@ -76,8 +77,12 @@ typedef struct {
MVert *mvert;
MEdge *medge;
MFace *mface;
+ MLoop *mloop;
+ MPoly *mpoly;
} CDDerivedMesh;
+DMFaceIter *cdDM_newFaceIter(DerivedMesh *source);
+
/**************** DerivedMesh interface functions ****************/
static int cdDM_getNumVerts(DerivedMesh *dm)
{
@@ -89,11 +94,16 @@ static int cdDM_getNumEdges(DerivedMesh *dm)
return dm->numEdgeData;
}
-static int cdDM_getNumFaces(DerivedMesh *dm)
+static int cdDM_getNumTessFaces(DerivedMesh *dm)
{
return dm->numFaceData;
}
+static int cdDM_getNumFaces(DerivedMesh *dm)
+{
+ return dm->numPolyData;
+}
+
static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -255,7 +265,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mvert = cddm->mvert;
MFace *mface = cddm->mface;
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
#define PASSVERT(index) { \
@@ -391,8 +401,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mv = cddm->mvert;
MFace *mf = cddm->mface;
- MCol *mcol = dm->getFaceDataArray(dm, CD_MCOL);
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
@@ -483,7 +493,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
MVert *mv = cddm->mvert;
MFace *mf = cddm->mface;
MCol *mc;
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
@@ -574,11 +584,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
DMVertexAttribs attribs;
MVert *mvert = cddm->mvert;
MFace *mface = cddm->mface;
- MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
- float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
+ MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
+ float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
int a, b, dodraw, smoothnormal, matnr, new_matnr;
int transp, new_transp, orig_transp;
- int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
matnr = -1;
smoothnormal = 0;
@@ -769,37 +779,45 @@ static void cdDM_foreachMappedFaceCenter(
{
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
MVert *mv = cddm->mvert;
- MFace *mf = cddm->mface;
- int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
-
- for(i = 0; i < dm->numFaceData; i++, mf++) {
+ MPoly *mf = cddm->mpoly;
+ MLoop *ml = cddm->mloop;
+ float (*cents)[3];
+ float (*nors)[3];
+ int *flens;
+ int i, j, orig, *index;
+ int maxf=0;
+
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ mf = cddm->mpoly;
+ for(i = 0; i < dm->numPolyData; i++, mf++) {
float cent[3];
float no[3];
if (index) {
orig = *index++;
if(orig == ORIGINDEX_NONE) continue;
- }
- else
+ } else
orig = i;
+
+ ml = &cddm->mloop[mf->loopstart];
+ cent[0] = cent[1] = cent[2] = 0.0f;
+ for (j=0; j<mf->totloop; j++, ml++) {
+ VecAddf(cent, cent, mv[ml->v].co);
+ }
+ VecMulf(cent, 1.0f / (float)j);
- VECCOPY(cent, mv[mf->v1].co);
- VecAddf(cent, cent, mv[mf->v2].co);
- VecAddf(cent, cent, mv[mf->v3].co);
-
- if (mf->v4) {
- CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
- mv[mf->v3].co, mv[mf->v4].co, no);
- VecAddf(cent, cent, mv[mf->v4].co);
- VecMulf(cent, 0.25f);
+ ml = &cddm->mloop[mf->loopstart];
+ if (j > 3) {
+ CalcNormFloat4(mv[ml->v].co, mv[(ml+1)->v].co,
+ mv[(ml+2)->v].co, mv[(ml+3)->v].co, no);
} else {
- CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
- mv[mf->v3].co, no);
- VecMulf(cent, 0.33333333333f);
+ CalcNormFloat(mv[ml->v].co, mv[(ml+1)->v].co,
+ mv[(ml+2)->v].co, no);
}
func(userData, orig, cent, no);
}
+
}
static void cdDM_release(DerivedMesh *dm)
@@ -822,21 +840,24 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getMinMax = cdDM_getMinMax;
dm->getNumVerts = cdDM_getNumVerts;
- dm->getNumFaces = cdDM_getNumFaces;
dm->getNumEdges = cdDM_getNumEdges;
+ dm->getNumTessFaces = cdDM_getNumTessFaces;
+ dm->getNumFaces = cdDM_getNumFaces;
+
+ dm->newFaceIter = cdDM_newFaceIter;
dm->getVert = cdDM_getVert;
dm->getEdge = cdDM_getEdge;
- dm->getFace = cdDM_getFace;
+ dm->getTessFace = cdDM_getFace;
dm->copyVertArray = cdDM_copyVertArray;
dm->copyEdgeArray = cdDM_copyEdgeArray;
- dm->copyFaceArray = cdDM_copyFaceArray;
+ dm->copyTessFaceArray = cdDM_copyFaceArray;
dm->getVertData = DM_get_vert_data;
dm->getEdgeData = DM_get_edge_data;
- dm->getFaceData = DM_get_face_data;
+ dm->getTessFaceData = DM_get_face_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getFaceDataArray = DM_get_face_data_layer;
+ dm->getTessFaceDataArray = DM_get_face_data_layer;
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
@@ -866,24 +887,29 @@ static CDDerivedMesh *cdDM_create(const char *desc)
return cddm;
}
-DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
+DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
DerivedMesh *dm = &cddm->dm;
- DM_init(dm, numVerts, numEdges, numFaces);
+ DM_init(dm, numVerts, numEdges, numFaces, numLoops, numPolys);
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
+ CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
return dm;
}
@@ -898,11 +924,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
/* this does a referenced copy, the only new layers being ORIGINDEX,
* with an exception for fluidsim */
- DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface);
+ DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface,
+ mesh->totloop, mesh->totpoly);
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert);
CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge);
CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
+ CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totpoly);
dm->deformedOnly = 1;
@@ -914,10 +942,16 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
mesh->totedge);
CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
mesh->totface);
+ CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
+ mesh->totloop);
+ CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
+ mesh->totpoly);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX);
for(i = 0; i < mesh->totvert; ++i, ++index)
@@ -931,6 +965,10 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
for(i = 0; i < mesh->totface; ++i, ++index)
*index = i;
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ for(i = 0; i < mesh->totpoly; ++i, ++index)
+ *index = i;
+
return dm;
}
@@ -938,7 +976,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
{
DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
BLI_countlist(&em->edges),
- BLI_countlist(&em->faces));
+ BLI_countlist(&em->faces), 0, 0);
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
EditVert *eve;
EditEdge *eed;
@@ -956,6 +994,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
CD_CALLOC, dm->numEdgeData); */
CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_CALLOC, dm->numFaceData);
+ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numFaceData);
/* set eve->hash to vert index */
for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
@@ -1012,7 +1052,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
/* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
}
- index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
for(i = 0, efa = em->faces.first; i < dm->numFaceData;
i++, efa = efa->next, index++) {
MFace *mf = &mface[i];
@@ -1033,6 +1073,321 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
return dm;
}
+
+static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
+ int cdindex, BMLoop *l3[3],
+ int numCol, int numTex)
+{
+ int i, j;
+ BMLoop *l;
+ BMFace *f = l3[0]->f;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ for (j=0; j<3; i++) {
+ l = l3[j];
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
+
+ for (j=0; j<3; j++) {
+ l = l3[j];
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *me)
+{
+ DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge,
+ em->tottri, em->bm->totloop, em->bm->totface);
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ BMesh *bm = em->bm;
+ BMIter iter, liter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ MVert *mvert = cddm->mvert;
+ MEdge *medge = cddm->medge;
+ MFace *mface = cddm->mface;
+ MLoop *mloop = cddm->mloop;
+ MPoly *mpoly = cddm->mpoly;
+ int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
+ int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
+ int i, j, *index, add_orig;
+
+ dm->deformedOnly = 1;
+
+ /*don't add origindex layer if one already exists*/
+ add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
+
+ CustomData_merge(&em->bm->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numVertData);
+ CustomData_merge(&em->bm->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numEdgeData);
+ CustomData_merge(&em->bm->pdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numFaceData);
+ CustomData_merge(&em->bm->ldata, &dm->loopData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numLoopData);
+ CustomData_merge(&em->bm->pdata, &dm->polyData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numPolyData);
+
+ /*add tesselation mface and mcol layers as necassary*/
+ for (i=0; i<numTex; i++) {
+ CustomData_add_layer(&dm->faceData, CD_MTFACE, CD_CALLOC, NULL, em->tottri);
+ }
+
+ for (i=0; i<numCol; i++) {
+ CustomData_add_layer(&dm->faceData, CD_MCOL, CD_CALLOC, NULL, em->tottri);
+ }
+
+ /* set vert index */
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BMINDEX_SET(eve, i);
+
+ index = dm->getVertDataArray(dm, CD_ORIGINDEX);
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
+ MVert *mv = &mvert[i];
+
+ VECCOPY(mv->co, eve->co);
+
+ BMINDEX_SET(eve, i);
+
+ mv->no[0] = eve->no[0] * 32767.0;
+ mv->no[1] = eve->no[1] * 32767.0;
+ mv->no[2] = eve->no[2] * 32767.0;
+ mv->bweight = (unsigned char) (eve->bweight * 255.0f);
+
+ mv->mat_nr = 0;
+ mv->flag = BMFlags_To_MEFlags(eve);
+
+ if (add_orig) *index = i;
+
+ CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
+ }
+
+ index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
+ eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
+ MEdge *med = &medge[i];
+
+ BMINDEX_SET(eed, i);
+
+ med->v1 = BMINDEX_GET(eed->v1);
+ med->v2 = BMINDEX_GET(eed->v2);
+ med->crease = (unsigned char) (eed->crease * 255.0f);
+ med->bweight = (unsigned char) (eed->bweight * 255.0f);
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+
+ med->flag = BMFlags_To_MEFlags(eed);
+
+ CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
+ if (add_orig) *index = i;
+ }
+
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
+ BMINDEX_SET(efa, i);
+ }
+
+ index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ for(i = 0; i < dm->numFaceData; i++, index++) {
+ MFace *mf = &mface[i];
+ BMLoop **l = em->looptris[i];
+ efa = l[0]->f;
+
+ mf->v1 = BMINDEX_GET(l[0]->v);
+ mf->v2 = BMINDEX_GET(l[1]->v);
+ mf->v3 = BMINDEX_GET(l[2]->v);
+ mf->v4 = 0;
+ mf->mat_nr = efa->mat_nr;
+ mf->flag = BMFlags_To_MEFlags(efa);
+
+ *index = add_orig ? BMINDEX_GET(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
+
+ loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
+ test_index_face(mf, &dm->faceData, i, 3);
+ }
+
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ j = 0;
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
+ BMLoop *l;
+ MPoly *mp = &mpoly[i];
+
+ mp->totloop = efa->len;
+ mp->flag = BMFlags_To_MEFlags(efa);
+ mp->loopstart = j;
+ mp->mat_nr = efa->mat_nr;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+ mloop->v = BMINDEX_GET(l->v);
+ mloop->e = BMINDEX_GET(l->e);
+ CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
+
+ j++;
+ mloop++;
+ }
+
+ CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
+
+ if (add_orig) *index = i;
+ }
+
+ return dm;
+}
+
+typedef struct CDDM_LoopIter {
+ DMLoopIter head;
+ CDDerivedMesh *cddm;
+ int len, i;
+} CDDM_LoopIter;
+
+typedef struct CDDM_FaceIter {
+ DMFaceIter head;
+ CDDerivedMesh *cddm;
+ CDDM_LoopIter liter;
+} CDDM_FaceIter;
+
+void cddm_freeiter(void *self)
+{
+ MEM_freeN(self);
+}
+
+void cddm_stepiter(void *self)
+{
+ CDDM_FaceIter *iter = self;
+ MPoly *mp;
+
+ iter->head.index++;
+ if (iter->head.index >= iter->cddm->dm.numPolyData) {
+ iter->head.done = 1;
+ return;
+ }
+
+ mp = iter->cddm->mpoly + iter->head.index;
+
+ iter->head.flags = mp->flag;
+ iter->head.mat_nr = mp->mat_nr;
+ iter->head.len = mp->totloop;
+}
+
+void *cddm_faceiter_getcddata(void *self, int type, int layer)
+{
+ CDDM_FaceIter *iter = self;
+
+ if (layer == -1) return CustomData_get(&iter->cddm->dm.polyData,
+ iter->head.index, type);
+ else return CustomData_get_n(&iter->cddm->dm.polyData, type,
+ iter->head.index, layer);
+}
+
+void *cddm_loopiter_getcddata(void *self, int type, int layer)
+{
+ CDDM_FaceIter *iter = self;
+
+ if (layer == -1) return CustomData_get(&iter->cddm->dm.loopData,
+ iter->head.index, type);
+ else return CustomData_get_n(&iter->cddm->dm.loopData, type,
+ iter->head.index, layer);
+}
+
+void *cddm_loopiter_getvertcddata(void *self, int type, int layer)
+{
+ CDDM_FaceIter *iter = self;
+
+ if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData,
+ iter->cddm->mloop[iter->head.index].v,
+ type);
+ else return CustomData_get_n(&iter->cddm->dm.vertData, type,
+ iter->cddm->mloop[iter->head.index].v, layer);
+}
+
+DMLoopIter *cddmiter_get_loopiter(void *self)
+{
+ CDDM_FaceIter *iter = self;
+ CDDM_LoopIter *liter = &iter->liter;
+ MPoly *mp = iter->cddm->mpoly + iter->head.index;
+
+ liter->i = -1;
+ liter->len = iter->head.len;
+ liter->head.index = mp->loopstart-1;
+ liter->head.done = 0;
+
+ liter->head.step(liter);
+
+ return (DMLoopIter*) liter;
+}
+
+void cddm_loopiter_step(void *self)
+{
+ CDDM_LoopIter *liter = self;
+ MLoop *ml;
+
+ liter->i++;
+ liter->head.index++;
+
+ if (liter->i == liter->len) {
+ liter->head.done = 1;
+ return;
+ }
+
+ ml = liter->cddm->mloop + liter->head.index;
+
+ liter->head.eindex = ml->e;
+ liter->head.v = liter->cddm->mvert[ml->v];
+ liter->head.vindex = ml->v;
+}
+
+DMFaceIter *cdDM_newFaceIter(DerivedMesh *source)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*) source;
+ CDDM_FaceIter *iter = MEM_callocN(sizeof(CDDM_FaceIter), "DMFaceIter from cddm");
+
+ iter->head.free = cddm_freeiter;
+ iter->head.step = cddm_stepiter;
+ iter->head.getCDData = cddm_faceiter_getcddata;
+ iter->head.getLoopsIter = cddmiter_get_loopiter;
+
+ iter->liter.head.step = cddm_loopiter_step;
+ iter->liter.head.getLoopCDData = cddm_loopiter_getcddata;
+ iter->liter.head.getVertCDData = cddm_loopiter_getvertcddata;
+ iter->liter.cddm = cddm;
+
+ iter->cddm = cddm;
+ iter->head.index = -1;
+ iter->head.step(iter);
+
+ return (DMFaceIter*) iter;
+}
+
DerivedMesh *CDDM_copy(DerivedMesh *source)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
@@ -1040,44 +1395,59 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
int numVerts = source->numVertData;
int numEdges = source->numEdgeData;
int numFaces = source->numFaceData;
+ int numLoops = source->numLoopData;
+ int numPolys = source->numPolyData;
/* this initializes dm, and copies all non mvert/medge/mface layers */
- DM_from_template(dm, source, numVerts, numEdges, numFaces);
+ DM_from_template(dm, source, numVerts, numEdges, numFaces,
+ numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
+ CustomData_copy_data(&source->loopData, &dm->loopData, 0, 0, numLoops);
+ CustomData_copy_data(&source->polyData, &dm->polyData, 0, 0, numPolys);
/* now add mvert/medge/mface layers */
cddm->mvert = source->dupVertArray(source);
cddm->medge = source->dupEdgeArray(source);
- cddm->mface = source->dupFaceArray(source);
+ cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
+
+ DM_DupPolys(source, dm);
+
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
return dm;
}
DerivedMesh *CDDM_from_template(DerivedMesh *source,
- int numVerts, int numEdges, int numFaces)
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
DerivedMesh *dm = &cddm->dm;
/* this does a copy of all non mvert/medge/mface layers */
- DM_from_template(dm, source, numVerts, numEdges, numFaces);
+ DM_from_template(dm, source, numVerts, numEdges, numFaces, numLoops, numPolys);
/* now add mvert/medge/mface layers */
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
+ CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
return dm;
}
@@ -1138,7 +1508,7 @@ void CDDM_calc_normals(DerivedMesh *dm)
NULL, dm->numFaceData);
/* calculate face normals and add to vertex normals */
- mf = CDDM_get_faces(dm);
+ mf = CDDM_get_tessfaces(dm);
for(i = 0; i < numFaces; i++, mf++) {
float *f_no = face_nors[i];
@@ -1263,7 +1633,7 @@ MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
return &((CDDerivedMesh*)dm)->medge[index];
}
-MFace *CDDM_get_face(DerivedMesh *dm, int index)
+MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
{
return &((CDDerivedMesh*)dm)->mface[index];
}
@@ -1278,11 +1648,85 @@ MEdge *CDDM_get_edges(DerivedMesh *dm)
return ((CDDerivedMesh*)dm)->medge;
}
-MFace *CDDM_get_faces(DerivedMesh *dm)
+MFace *CDDM_get_tessfaces(DerivedMesh *dm)
{
return ((CDDerivedMesh*)dm)->mface;
}
+void CDDM_tessfaces_to_faces(DerivedMesh *dm)
+{
+ /*converts mfaces to mpolys/mloops*/
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ MFace *mf;
+ MEdge *me;
+ MLoop *ml;
+ MPoly *mp;
+ EdgeHash *eh = BLI_edgehash_new();
+ int i, l, totloop, *index1, *index2;
+
+ me = cddm->medge;
+ for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
+
+ mf = cddm->mface;
+ totloop = 0;
+ for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
+ CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
+
+ cddm->dm.numLoopData = totloop;
+ cddm->dm.numPolyData = cddm->dm.numFaceData;
+
+ if (!totloop) return;
+
+ cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
+ cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
+
+ CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
+ CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
+ CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData,
+ CD_MASK_DERIVEDMESH, CD_DUPLICATE, cddm->dm.numFaceData);
+
+ index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
+ index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
+
+ mf = cddm->mface;
+ mp = cddm->mpoly;
+ ml = cddm->mloop;
+ l = 0;
+ for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
+ mp->flag = mf->flag;
+ mp->loopstart = l;
+ mp->mat_nr = mf->mat_nr;
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ ml->v = mf->v1;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
+ ml++, l++;
+
+ ml->v = mf->v2;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
+ ml++, l++;
+
+ ml->v = mf->v3;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
+ ml++, l++;
+
+ if (mf->v4) {
+ ml->v = mf->v4;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
+ ml++, l++;
+ }
+
+ }
+
+ BLI_edgehash_free(eh, NULL);
+}
+
/* Multires DerivedMesh, extends CDDM */
typedef struct MultiresDM {
CDDerivedMesh cddm;
@@ -1337,7 +1781,9 @@ static void MultiresDM_release(DerivedMesh *dm)
}
}
-DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces)
+DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys)
{
MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM");
CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM");
@@ -1355,7 +1801,8 @@ DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts
MVert *mvert;
int i;
- DM_from_template(dm, orig, numVerts, numEdges, numFaces);
+ DM_from_template(dm, orig, numVerts, numEdges, numFaces,
+ numLoops, numPolys);
CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces);
disps = CustomData_get_layer(&orig->faceData, CD_MDISPS);
@@ -1369,7 +1816,7 @@ DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts
VecCopyf(mrdm->orco[i], mvert[i].co);
}
else
- DM_init(dm, numVerts, numEdges, numFaces);
+ DM_init(dm, numVerts, numEdges, numFaces, numLoops, numPolys);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
@@ -1472,3 +1919,4 @@ void MultiresDM_mark_as_modified(DerivedMesh *dm)
{
((MultiresDM*)dm)->modified = 1;
}
+
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 089dafeb8c7..b16a046cd58 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -1017,8 +1017,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int numverts = dm->getNumVerts ( dm );
- unsigned int numfaces = dm->getNumFaces ( dm );
- MFace *mface = CDDM_get_faces(dm);
+ unsigned int numfaces = dm->getNumTessFaces ( dm );
+ MFace *mface = CDDM_get_tessfaces(dm);
unsigned int i = 0;
/* Allocate our vertices. */
@@ -1130,9 +1130,9 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
int i = 0;
int numverts = dm->getNumVerts ( dm );
int numedges = dm->getNumEdges ( dm );
- int numfaces = dm->getNumFaces ( dm );
+ int numfaces = dm->getNumTessFaces ( dm );
MEdge *medge = CDDM_get_edges ( dm );
- MFace *mface = CDDM_get_faces ( dm );
+ MFace *mface = CDDM_get_tessfaces ( dm );
int index2 = 0; // our second vertex index
LinkNode **edgelist = NULL;
EdgeHash *edgehash = NULL;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 88e73a00ba7..f1420db706f 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -66,6 +66,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "BKE_mesh.h"
#include "BKE_shrinkwrap.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 705d0b66d7f..0173e660e18 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -45,6 +45,8 @@
#include "MEM_guardedalloc.h"
+#include "bmesh.h"
+
#include <math.h>
#include <string.h>
@@ -257,6 +259,7 @@ static void layerInterp_tface(void **sources, float *weights,
}
*tf = *(MTFace *)sources[0];
+
for(j = 0; j < 4; ++j) {
tf->uv[j][0] = uv[j][0];
tf->uv[j][1] = uv[j][1];
@@ -726,6 +729,8 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL},
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
+ {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL},
};
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
@@ -735,19 +740,22 @@ const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol"};
const CustomDataMask CD_MASK_BAREMESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
+ CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MPOLY;
const CustomDataMask CD_MASK_MESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
- CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
+ CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP;
const CustomDataMask CD_MASK_EDITMESH =
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
+ CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
+ CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL;
-const CustomDataMask CD_MASK_BMESH =
+const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
@@ -800,7 +808,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
if(layer->flag & CD_FLAG_NOCOPY) continue;
else if(!((int)mask & (int)(1 << (int)type))) continue;
- else if(number < CustomData_number_of_layers(dest, type)) continue;
+ else if(number+1 < CustomData_number_of_layers(dest, type)) continue;
if((alloctype == CD_ASSIGN) && (layer->flag & CD_FLAG_NOFREE))
newlayer = customData_add_layer__internal(dest, type, CD_REFERENCE,
@@ -1480,6 +1488,19 @@ void *CustomData_get(const CustomData *data, int index, int type)
return (char *)data->layers[layer_index].data + offset;
}
+void *CustomData_get_n(const CustomData *data, int type, int index, int n)
+{
+ int layer_index;
+ int offset;
+
+ /* get the layer index of the first layer of type */
+ layer_index = CustomData_get_layer_index(data, type);
+ if(layer_index < 0) return NULL;
+
+ offset = layerType_getInfo(type)->size * index;
+ return (char *)data->layers[layer_index].data + offset;
+}
+
void *CustomData_get_layer(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
@@ -1814,16 +1835,17 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest,
/*Bmesh functions*/
/*needed to convert to/from different face reps*/
-void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata,
+ int totloop, int totpoly)
{
int i;
for(i=0; i < fdata->totlayer; i++){
if(fdata->layers[i].type == CD_MTFACE){
- CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0);
- CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0);
+ CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), totpoly);
+ CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), totloop);
}
else if(fdata->layers[i].type == CD_MCOL)
- CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0);
+ CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), totloop);
}
}
void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){
@@ -1843,6 +1865,54 @@ void CustomData_bmesh_init_pool(CustomData *data, int allocsize){
if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize);
}
+void CustomData_bmesh_merge(CustomData *source, CustomData *dest,
+ int mask, int alloctype, BMesh *bm, int type)
+{
+ BMHeader *h;
+ BMIter iter;
+ CustomData destold = *dest;
+ void *tmp;
+ int i, t;
+
+ CustomData_merge(source, dest, mask, alloctype, 0);
+ CustomData_bmesh_init_pool(dest, 512);
+
+ switch (type) {
+ case BM_VERT:
+ t = BM_VERTS_OF_MESH; break;
+ case BM_EDGE:
+ t = BM_EDGES_OF_MESH; break;
+ case BM_LOOP:
+ t = BM_LOOPS_OF_FACE; break;
+ case BM_FACE:
+ t = BM_FACES_OF_MESH; break;
+ }
+
+ if (t != BM_LOOPS_OF_FACE) {
+ /*ensure all current elements follow new customdata layout*/
+ BM_ITER(h, &iter, bm, t, NULL) {
+ CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
+ CustomData_bmesh_free_block(&destold, &h->data);
+ h->data = tmp;
+ }
+ } else {
+ BMFace *f;
+ BMLoop *l;
+ BMIter liter;
+
+ /*ensure all current elements follow new customdata layout*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
+ CustomData_bmesh_free_block(&destold, &h->data);
+ h->data = tmp;
+ }
+ }
+ }
+
+ if (destold.pool) BLI_mempool_destroy(destold.pool);
+}
+
void CustomData_bmesh_free_block(CustomData *data, void **block)
{
const LayerTypeInfo *typeInfo;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cdf4b90cee1..3136630ce93 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -526,10 +526,10 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
dm = mesh_get_derived_final(RE_GetScene(re), ob, dataMask);
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
- nors = dm->getFaceDataArray(dm, CD_NORMAL);
+ mface = dm->getTessFaceArray(dm);
+ nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
orco= dm->getVertDataArray(dm, CD_ORCO);
if (onlyForMesh) {
diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c
new file mode 100644
index 00000000000..fa9747ec54f
--- /dev/null
+++ b/source/blender/blenkernel/intern/editderivedbmesh.c
@@ -0,0 +1,1526 @@
+/**
+ * $Id: editderivedbmesh.c 18571 2009-01-19 06:04:57Z joeedh $
+ *
+ * ***** 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 Tbmple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "PIL_time.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_effect_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h" // N_T
+#include "DNA_scene_types.h" // N_T
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_particle_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+#include "BLI_scanfill.h"
+#include "BLI_ghash.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
+#include "bmesh.h"
+
+BMEditMesh *BMEdit_Create(BMesh *bm)
+{
+ BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), "tm");
+
+ tm->bm = bm;
+
+ BMEdit_RecalcTesselation(tm);
+
+ return tm;
+}
+
+BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
+{
+ BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), "tm2");
+ *tm2 = *tm;
+
+ tm2->derivedCage = tm2->derivedFinal = NULL;
+
+ tm2->looptris = NULL;
+ tm2->bm = BM_Copy_Mesh(tm->bm);
+ BMEdit_RecalcTesselation(tm2);
+
+ tm2->vert_index = NULL;
+ tm2->edge_index = NULL;
+ tm2->face_index = NULL;
+
+ return tm2;
+}
+
+static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
+{
+ BMesh *bm = tm->bm;
+ BMLoop **looptris = NULL;
+ V_DYNDECLARE(looptris);
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l;
+ int i = 0, j;
+
+ if (tm->looptris) MEM_freeN(tm->looptris);
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for ( ; f; f=BMIter_Step(&iter)) {
+ /*don't consider two-edged faces*/
+ if (f->len < 3) continue;
+
+ if (f->len <= 4) {
+ /*triangle fan for quads. should be recoded to
+ just add one tri for tris, and two for quads,
+ but this code works for now too.*/
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (l == f->loopbase) continue;
+ if ((BMLoop*)l->head.next == f->loopbase) continue;
+
+ V_GROW(looptris);
+ V_GROW(looptris);
+ V_GROW(looptris);
+
+ looptris[i*3] = l;
+ looptris[i*3+1] = (BMLoop*)l->head.next;
+ looptris[i*3+2] = f->loopbase;
+
+ i += 1;
+ }
+ } else {
+ /*scanfill time*/
+ EditVert *v, *lastv=NULL, *firstv=NULL;
+ EditEdge *e;
+ EditFace *efa;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (j=0; l; l=BMIter_Step(&liter), j++) {
+ /*mark order*/
+ l->head.eflag2 = j;
+
+ v = BLI_addfillvert(l->v->co);
+ v->tmp.p = l;
+
+ if (lastv) {
+ e = BLI_addfilledge(lastv, v);
+ }
+
+ lastv = v;
+ if (firstv==NULL) firstv = v;
+ }
+
+ /*complete the loop*/
+ BLI_addfilledge(firstv, v);
+
+ BLI_edgefill(0, 0);
+
+ for (efa = fillfacebase.first; efa; efa=efa->next) {
+ V_GROW(looptris);
+ V_GROW(looptris);
+ V_GROW(looptris);
+
+ looptris[i*3] = efa->v1->tmp.p;
+ looptris[i*3+1] = efa->v2->tmp.p;
+ looptris[i*3+2] = efa->v3->tmp.p;
+
+ if (looptris[i*3]->head.eflag2 > looptris[i*3+1]->head.eflag2);
+ SWAP(BMLoop*, looptris[i*3], looptris[i*3+1]);
+ if (looptris[i*3+1]->head.eflag2 > looptris[i*3+2]->head.eflag2);
+ SWAP(BMLoop*, looptris[i*3+1], looptris[i*3+2]);
+ if (looptris[i*3]->head.eflag2 > looptris[i*3+1]->head.eflag2);
+ SWAP(BMLoop*, looptris[i*3], looptris[i*3+1]);
+
+ i += 1;
+ }
+ BLI_end_edgefill();
+ }
+ }
+
+ tm->tottri = i;
+ tm->looptris = looptris;
+}
+
+void BMEdit_RecalcTesselation(BMEditMesh *tm)
+{
+ BMEdit_RecalcTesselation_intern(tm);
+
+ if (tm->derivedFinal && tm->derivedFinal == tm->derivedCage) {
+ if (tm->derivedFinal->recalcTesselation)
+ tm->derivedFinal->recalcTesselation(tm->derivedFinal);
+ } else if (tm->derivedFinal) {
+ if (tm->derivedCage->recalcTesselation)
+ tm->derivedCage->recalcTesselation(tm->derivedCage);
+ if (tm->derivedFinal->recalcTesselation)
+ tm->derivedFinal->recalcTesselation(tm->derivedFinal);
+ }
+}
+
+/*does not free the BMEditMesh struct itself*/
+void BMEdit_Free(BMEditMesh *em)
+{
+ if(em->derivedFinal) {
+ if (em->derivedFinal!=em->derivedCage) {
+ em->derivedFinal->needsFree= 1;
+ em->derivedFinal->release(em->derivedFinal);
+ }
+ em->derivedFinal= NULL;
+ }
+ if(em->derivedCage) {
+ em->derivedCage->needsFree= 1;
+ em->derivedCage->release(em->derivedCage);
+ em->derivedCage= NULL;
+ }
+
+ em->retopo_paint_data= NULL;
+
+ if (em->looptris) MEM_freeN(em->looptris);
+
+ if (em->vert_index) MEM_freeN(em->vert_index);
+ if (em->edge_index) MEM_freeN(em->edge_index);
+ if (em->face_index) MEM_freeN(em->face_index);
+
+ BM_Free_Mesh(em->bm);
+}
+
+
+/*
+ok, basic design:
+
+the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
+to three loops per triangle. the derivedmesh stores a cache of tesselations
+for each face. this cache will smartly update as needed (though at first
+it'll simply be more brute force). keeping track of face/edge counts may
+be a small problbm.
+
+this won't be the most efficient thing, considering that internal edges and
+faces of tesselations are exposed. looking up an edge by index in particular
+is likely to be a little slow.
+*/
+
+typedef struct EditDerivedBMesh {
+ DerivedMesh dm;
+
+ Object *ob;
+ BMEditMesh *tc;
+
+ float (*vertexCos)[3];
+ float (*vertexNos)[3];
+ float (*faceNos)[3];
+
+ /*lookup caches; these are rebuilt on dm->RecalcTesselation()
+ (or when the derivedmesh is created, of course)*/
+ GHash *vhash, *ehash, *fhash;
+ BMVert **vtable;
+ BMEdge **etable;
+ BMFace **ftable;
+
+ /*private variables, for number of verts/edges/faces
+ within the above hash/table members*/
+ int tv, te, tf;
+} EditDerivedBMesh;
+
+static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
+{
+ BMIter iter;
+ BMHeader *h;
+ int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ bmdm->tv = bmdm->tc->bm->totvert;
+ bmdm->te = bmdm->tc->bm->totedge;
+ bmdm->tf = bmdm->tc->bm->totface;
+
+ if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
+ if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+ if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+
+ bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+ if (bmdm->etable) MEM_freeN(bmdm->etable);
+ if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+
+ if (bmdm->tc->bm->totvert)
+ bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
+ else bmdm->vtable = NULL;
+
+ if (bmdm->tc->bm->totedge)
+ bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
+ else bmdm->etable = NULL;
+
+ if (bmdm->tc->bm->totface)
+ bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
+ else bmdm->ftable = NULL;
+
+ for (a=0; a<3; a++) {
+ h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
+ for (i=0; h; h=BMIter_Step(&iter), i++) {
+ switch (a) {
+ case 0:
+ bmdm->vtable[i] = (BMVert*) h;
+ BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
+ break;
+ case 1:
+ bmdm->etable[i] = (BMEdge*) h;
+ BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
+ break;
+ case 2:
+ bmdm->ftable[i] = (BMFace*) h;
+ BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
+ break;
+
+ }
+ }
+ }
+}
+
+static void bmDM_recalcTesselation(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ bmdm_recalc_lookups(bmdm);
+}
+
+static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
+ if (bmdm->vertexCos) {
+ func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
+ } else {
+ func(userData, i, eve->co, eve->no, NULL);
+ }
+ }
+}
+static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+ BMIter viter;
+
+ eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&viter), i++) {
+ BMINDEX_SET(eve, i);
+ }
+
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter))
+ func(userData, i,
+ bmdm->vertexCos[BMINDEX_GET(eve)],
+ bmdm->vertexCos[BMINDEX_GET(eve)]);
+ } else {
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter))
+ func(userData, i, eed->v1->co, eed->v2->co);
+ }
+
+}
+
+static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+ BMIter viter;
+
+ eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&viter)) {
+ BMINDEX_SET(eve, i);
+ }
+
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v1)]);
+ glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v2)]);
+ }
+ }
+ glEnd();
+
+ } else {
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ glVertex3fv(eed->v1->co);
+ glVertex3fv(eed->v2->co);
+ }
+ }
+ glEnd();
+ }
+}
+
+static void bmDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
+{
+ bmDM_drawMappedEdges(dm, NULL, NULL);
+}
+
+static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BMINDEX_SET(eve, i);
+
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ setDrawInterpOptions(userData, i, 0.0);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v1)]);
+ setDrawInterpOptions(userData, i, 1.0);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v2)]);
+ }
+ }
+ glEnd();
+ } else {
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ setDrawInterpOptions(userData, i, 0.0);
+ glVertex3fv(eed->v1->co);
+ setDrawInterpOptions(userData, i, 1.0);
+ glVertex3fv(eed->v2->co);
+ }
+ }
+ glEnd();
+ }
+}
+
+static void bmDM_drawUVEdges(DerivedMesh *dm)
+{
+#if 0
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMFace *efa;
+ MTFace *tf;
+
+ glBegin(GL_LINES);
+ for(efa= bmdm->tc->bm->faces.first; efa; efa= efa->next) {
+ tf = CustomData_bm_get(&bmdm->tc->bm->pdata, efa->data, CD_MTFACE);
+
+ if(tf && !(efa->h)) {
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+
+ if (!efa->v4) {
+ glVertex2fv(tf->uv[2]);
+ glVertex2fv(tf->uv[0]);
+ } else {
+ glVertex2fv(tf->uv[2]);
+ glVertex2fv(tf->uv[3]);
+ glVertex2fv(tf->uv[3]);
+ glVertex2fv(tf->uv[0]);
+ }
+ }
+ }
+ glEnd();
+#endif
+}
+
+static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
+ float (*vertexCos)[3])
+{
+ BMIter iter;
+ BMLoop *l;
+ int tot = 0;
+
+ cent[0] = cent[1] = cent[2] = 0.0f;
+
+ /*simple (and stupid) median (average) based method :/ */
+
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, l->v->co);
+ tot++;
+ }
+
+ if (tot==0) return;
+ VECMUL(cent, 1.0f/(float)tot);
+}
+
+static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMFace *efa;
+ BMIter iter;
+ float cent[3];
+ int i;
+
+ if (bmdm->vertexCos) {
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter));
+ BMINDEX_SET(eve, i);
+ }
+
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++) {
+ bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
+ func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
+ }
+}
+
+static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMFace *efa;
+ BMIter iter;
+ int i, draw;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter))
+ BMINDEX_SET(eve, i);
+
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++)
+ BMINDEX_SET(efa, i);
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ int drawSmooth;
+
+ drawSmooth = (efa->head.flag & BM_SMOOTH);
+ efa = l[0]->f;
+
+ draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
+ if(draw) {
+ if (draw==2) { /* enabled with stipple */
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+
+ glBegin(GL_TRIANGLES);
+
+ if (!drawSmooth) {
+ glNormal3fv(efa->no);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]);
+ } else {
+ glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[0]->v)]);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]);
+ glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[1]->v)]);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]);
+ glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[2]->v)]);
+ glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]);
+ }
+ glEnd();
+
+ if (draw==2)
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+ }
+ } else {
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++)
+ BMINDEX_SET(efa, i);
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ int drawSmooth;
+
+ efa = l[0]->f;
+
+ drawSmooth = (efa->head.flag & BM_SMOOTH);
+
+ draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
+ if(draw) {
+ if (draw==2) { /* enabled with stipple */
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+
+ glBegin(GL_TRIANGLES);
+ if (!drawSmooth) {
+ glNormal3fv(efa->no);
+ glVertex3fv(l[0]->v->co);
+ glVertex3fv(l[1]->v->co);
+ glVertex3fv(l[2]->v->co);
+ } else {
+ glNormal3fv(l[0]->v->no);
+ glVertex3fv(l[0]->v->co);
+ glNormal3fv(l[1]->v->no);
+ glVertex3fv(l[1]->v->co);
+ glNormal3fv(l[2]->v->no);
+ glVertex3fv(l[2]->v->co);
+ }
+ glEnd();
+
+ if (draw==2)
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+ }
+ }
+}
+
+static void bmDM_drawFacesTex_common(DerivedMesh *dm,
+ int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
+ int (*drawParamsMapped)(void *userData, int index),
+ void *userData)
+{
+#if 0
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMesh *bm= bmdm->tc->bm;
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ BMFace *efa;
+ BMIter iter;
+ int i;
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+
+ if (vertexCos) {
+ BMVert *eve;
+
+ for (i=0,eve=bm->verts.first; eve; eve= eve->next)
+ BMINDEX_SET(eve, i++);
+
+ for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
+ MTFace *tf= CustomData_bm_get(&bm->pdata, efa->data, CD_MTFACE);
+ MCol *mcol= CustomData_bm_get(&bm->pdata, efa->data, CD_MCOL);
+ unsigned char *cp= NULL;
+ int drawSmooth= (efa->flag & ME_SMOOTH);
+ int flag;
+
+ if(drawParams)
+ flag= drawParams(tf, mcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, i);
+ else
+ flag= 1;
+
+ if(flag != 0) { /* flag 0 == the face is hidden or invisible */
+
+ /* we always want smooth here since otherwise vertex colors dont interpolate */
+ if (mcol) {
+ if (flag==1) {
+ cp= (unsigned char*)mcol;
+ }
+ } else {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ if (!drawSmooth) {
+ glNormal3fv(bmdm->faceNos[i]);
+
+ if(tf) glTexCoord2fv(tf->uv[0]);
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+
+ if(tf) glTexCoord2fv(tf->uv[1]);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+
+ if(tf) glTexCoord2fv(tf->uv[2]);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+
+ if(efa->v4) {
+ if(tf) glTexCoord2fv(tf->uv[3]);
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ }
+ } else {
+ if(tf) glTexCoord2fv(tf->uv[0]);
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+
+ if(tf) glTexCoord2fv(tf->uv[1]);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+
+ if(tf) glTexCoord2fv(tf->uv[2]);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+
+ if(efa->v4) {
+ if(tf) glTexCoord2fv(tf->uv[3]);
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ }
+ }
+ glEnd();
+ }
+ }
+ } else {
+ for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
+ MTFace *tf= CustomData_bm_get(&bm->pdata, efa->data, CD_MTFACE);
+ MCol *mcol= CustomData_bm_get(&bm->pdata, efa->data, CD_MCOL);
+ unsigned char *cp= NULL;
+ int drawSmooth= (efa->flag & ME_SMOOTH);
+ int flag;
+
+ if(drawParams)
+ flag= drawParams(tf, mcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, i);
+ else
+ flag= 1;
+
+ if(flag != 0) { /* flag 0 == the face is hidden or invisible */
+ /* we always want smooth here since otherwise vertex colors dont interpolate */
+ if (mcol) {
+ if (flag==1) {
+ cp= (unsigned char*)mcol;
+ }
+ } else {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ if (!drawSmooth) {
+ glNormal3fv(efa->n);
+
+ if(tf) glTexCoord2fv(tf->uv[0]);
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(efa->v1->co);
+
+ if(tf) glTexCoord2fv(tf->uv[1]);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glVertex3fv(efa->v2->co);
+
+ if(tf) glTexCoord2fv(tf->uv[2]);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glVertex3fv(efa->v3->co);
+
+ if(efa->v4) {
+ if(tf) glTexCoord2fv(tf->uv[3]);
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glVertex3fv(efa->v4->co);
+ }
+ } else {
+ if(tf) glTexCoord2fv(tf->uv[0]);
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glNormal3fv(efa->v1->no);
+ glVertex3fv(efa->v1->co);
+
+ if(tf) glTexCoord2fv(tf->uv[1]);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glNormal3fv(efa->v2->no);
+ glVertex3fv(efa->v2->co);
+
+ if(tf) glTexCoord2fv(tf->uv[2]);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glNormal3fv(efa->v3->no);
+ glVertex3fv(efa->v3->co);
+
+ if(efa->v4) {
+ if(tf) glTexCoord2fv(tf->uv[3]);
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glNormal3fv(efa->v4->no);
+ glVertex3fv(efa->v4->co);
+ }
+ }
+ glEnd();
+ }
+ }
+ }
+#endif
+}
+
+static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
+{
+ bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
+}
+
+static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
+}
+
+static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs),
+ int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+#if 0
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMesh *bm= bmdm->tc->bm;
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ BMVert *eve;
+ BMFace *efa;
+ DMVertexAttribs attribs;
+ GPUVertexAttribs gattribs;
+ MTFace *tf;
+ int transp, new_transp, orig_transp, tfoffset;
+ int i, b, matnr, new_matnr, dodraw, layer;
+
+ dodraw = 0;
+ matnr = -1;
+
+ transp = GPU_get_material_blend_mode();
+ orig_transp = transp;
+ layer = CustomData_get_layer_index(&bm->pdata, CD_MTFACE);
+ tfoffset = (layer == -1)? -1: bm->pdata.layers[layer].offset;
+
+ memset(&attribs, 0, sizeof(attribs));
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+
+ for (i=0,eve=bm->verts.first; eve; eve= eve->next)
+ BMINDEX_SET(eve, i++);
+
+#define PASSATTRIB(efa, eve, vert) { \
+ if(attribs.totorco) { \
+ float *orco = attribs.orco.array[BMINDEX_GET(eve)]; \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
+ } \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].bmOffset); \
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].bmOffset); \
+ GLubyte col[4]; \
+ col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[i*4 + vert]; \
+ glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ } \
+}
+
+ for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
+ int drawSmooth= (efa->flag & ME_SMOOTH);
+
+ if(setDrawOptions && !setDrawOptions(userData, i))
+ continue;
+
+ new_matnr = efa->mat_nr + 1;
+ if(new_matnr != matnr) {
+ dodraw = setMaterial(matnr = new_matnr, &gattribs);
+ if(dodraw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ }
+
+ if(tfoffset != -1) {
+ tf = (MTFace*)((char*)efa->data)+tfoffset;
+ new_transp = tf->transp;
+
+ if(new_transp != transp) {
+ if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+ GPU_set_material_blend_mode(orig_transp);
+ else
+ GPU_set_material_blend_mode(new_transp);
+ transp = new_transp;
+ }
+ }
+
+ if(dodraw) {
+ glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+ if (!drawSmooth) {
+ if(vertexCos) glNormal3fv(bmdm->faceNos[i]);
+ else glNormal3fv(efa->n);
+
+ PASSATTRIB(efa, efa->v1, 0);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+ else glVertex3fv(efa->v1->co);
+
+ PASSATTRIB(efa, efa->v2, 1);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+ else glVertex3fv(efa->v2->co);
+
+ PASSATTRIB(efa, efa->v3, 2);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+ else glVertex3fv(efa->v3->co);
+
+ if(efa->v4) {
+ PASSATTRIB(efa, efa->v4, 3);
+ if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ else glVertex3fv(efa->v4->co);
+ }
+ } else {
+ PASSATTRIB(efa, efa->v1, 0);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v1->no);
+ glVertex3fv(efa->v1->co);
+ }
+
+ PASSATTRIB(efa, efa->v2, 1);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v2->no);
+ glVertex3fv(efa->v2->co);
+ }
+
+ PASSATTRIB(efa, efa->v3, 2);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v3->no);
+ glVertex3fv(efa->v3->co);
+ }
+
+ if(efa->v4) {
+ PASSATTRIB(efa, efa->v4, 3);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+ glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+ }
+ else {
+ glNormal3fv(efa->v4->no);
+ glVertex3fv(efa->v4->co);
+ }
+ }
+ }
+ glEnd();
+ }
+ }
+#endif
+}
+
+static void bmDM_drawFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs))
+{
+ dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
+static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ if (bmdm->tc->bm->verts.first) {
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ if (bmdm->vertexCos) {
+ DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
+ } else {
+ DO_MINMAX(eve->co, min_r, max_r);
+ }
+ }
+ } else {
+ min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
+ }
+}
+static int bmDM_getNumVerts(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totvert;
+}
+
+static int bmDM_getNumEdges(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totedge;
+}
+
+static int bmDM_getNumTessFaces(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->tottri;
+}
+
+static int bmDM_getNumFaces(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totface;
+}
+
+static int bmvert_to_mvert(BMVert *ev, MVert *vert_r)
+{
+ VECCOPY(vert_r->co, ev->co);
+
+ vert_r->no[0] = (short)(ev->no[0] * 32767.0f);
+ vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
+ vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
+
+ /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+ vert_r->flag = BMFlags_To_MEFlags(ev);
+ vert_r->mat_nr = 0;
+ vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
+}
+
+static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ BMVert *ev;
+ BMIter iter;
+ int i;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
+ printf("error in bmDM_getVert.\n");
+ return;
+ }
+
+ ev = ((EditDerivedBMesh *)dm)->vtable[index];
+ bmvert_to_mvert(ev, vert_r);
+}
+
+static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMEdge *e;
+ BMVert *ev, *v1, *v2;
+ BMIter iter;
+ int i;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
+ printf("error in bmDM_getEdge.\n");
+ return;
+ }
+
+ e = bmdm->etable[index];
+
+ edge_r->crease = (unsigned char) (e->crease*255.0f);
+ edge_r->bweight = (unsigned char) (e->bweight*255.0f);
+ /* TODO what to do with edge_r->flag? */
+ edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ edge_r->flag |= BMFlags_To_MEFlags(e);
+#if 0
+ /* this needs setup of f2 field */
+ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+ edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
+ edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
+}
+
+static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMesh *bm = bmdm->tc->bm;
+ BMFace *ef;
+ BMIter iter;
+ BMLoop **l;
+ int i;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
+ printf("error in bmDM_getTessFace.\n");
+ return;
+ }
+
+ l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
+
+ ef = l[0]->f;
+
+ face_r->mat_nr = (unsigned char) ef->mat_nr;
+ face_r->flag = BMFlags_To_MEFlags(ef);
+
+ face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
+ face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
+ face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
+ face_r->v4 = 0;
+
+ test_index_face(face_r, NULL, 0, 3);
+}
+
+static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMVert *ev;
+ BMIter iter;
+
+ ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
+ VECCOPY(vert_r->co, ev->co);
+
+ vert_r->no[0] = (short) (ev->no[0] * 32767.0);
+ vert_r->no[1] = (short) (ev->no[1] * 32767.0);
+ vert_r->no[2] = (short) (ev->no[2] * 32767.0);
+
+ /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+ vert_r->mat_nr = 0;
+ vert_r->flag = BMFlags_To_MEFlags(ev);
+ vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
+ }
+}
+
+static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMEdge *ee;
+ BMIter iter;
+ BMVert *ev;
+ int i;
+
+ /* store vertex indices in tmp union */
+ ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; ev; ev=BMIter_Step(&iter), i++)
+ BMINDEX_SET(ev, i);
+
+ ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for( ; ee; ee=BMIter_Step(&iter)) {
+ edge_r->crease = (unsigned char) (ee->crease*255.0f);
+ edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
+ /* TODO what to do with edge_r->flag? */
+ edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ if (ee->head.flag & BM_SEAM) edge_r->flag |= ME_SEAM;
+ if (ee->head.flag & BM_SHARP) edge_r->flag |= ME_SHARP;
+#if 0
+ /* this needs setup of f2 field */
+ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+ edge_r->v1 = (int)BMINDEX_GET(ee->v1);
+ edge_r->v2 = (int)BMINDEX_GET(ee->v2);
+ }
+}
+
+static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMFace *ef;
+ BMVert *ev;
+ BMIter iter;
+ BMLoop **l;
+ int i;
+
+ /* store vertexes indices in tmp union */
+ ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; ev; ev=BMIter_Step(&iter), i++)
+ BMINDEX_SET(ev, i);
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ l = bmdm->tc->looptris[i];
+ ef = l[0]->f;
+
+ face_r->mat_nr = (unsigned char) ef->mat_nr;
+
+ /*HACK/TODO: need to convert this*/
+ face_r->flag = ef->head.flag;
+
+ face_r->v1 = BMINDEX_GET(l[0]->v);
+ face_r->v2 = BMINDEX_GET(l[1]->v);
+ face_r->v3 = BMINDEX_GET(l[2]->v);
+ face_r->v4 = 0;
+
+ test_index_face(face_r, NULL, 0, 3);
+ }
+}
+
+static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMesh *bm= bmdm->tc->bm;
+ BMFace *efa;
+ char *data, *bmdata;
+ void *datalayer;
+ int index, offset, size, i;
+
+ datalayer = DM_get_face_data_layer(dm, type);
+ if(datalayer)
+ return datalayer;
+
+ /* layers are store per face for editmesh, we convert to a tbmporary
+ * data layer array in the derivedmesh when these are requested */
+ if(type == CD_MTFACE || type == CD_MCOL) {
+ index = CustomData_get_layer_index(&bm->pdata, type);
+
+ if(index != -1) {
+ offset = bm->pdata.layers[index].offset;
+ size = CustomData_sizeof(type);
+
+ DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+ index = CustomData_get_layer_index(&dm->faceData, type);
+ dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+ data = datalayer = DM_get_face_data_layer(dm, type);
+ for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
+ efa = bmdm->tc->looptris[i][0]->f;
+ /*BMESH_TODO: need to still add tface data,
+ derived from the loops.*/
+ bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
+ memcpy(data, bmdata, size);
+ }
+ }
+ }
+
+ return datalayer;
+}
+
+typedef struct bmDM_loopIter {
+ DMLoopIter head;
+
+ BMFace *f;
+ BMLoop *l, *nextl;
+ BMIter iter;
+ BMesh *bm;
+} bmDM_loopIter;
+
+typedef struct bmDM_faceIter {
+ DMFaceIter head;
+
+ BMFace *f, *nextf;
+ BMIter iter;
+ BMesh *bm;
+
+ bmDM_loopIter loopiter;
+} bmDM_faceIter;
+
+void bmDM_faceIterStep(void *self)
+{
+ bmDM_faceIter *iter = self;
+
+ iter->f = iter->nextf;
+
+ iter->head.mat_nr = iter->f->mat_nr;
+ iter->head.flags = BMFlags_To_MEFlags(iter->f);
+ iter->head.index++;
+
+ iter->nextf = BMIter_Step(&iter->iter);
+
+ if (!iter->nextf) iter->head.done = 1;
+}
+
+void *bmDM_getFaceCDData(void *self, int type, int layer)
+{
+ bmDM_faceIter *iter = self;
+
+ if (layer == -1)
+ return CustomData_bmesh_get(&iter->bm->pdata, iter->f->head.data, type);
+ else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->head.data, type, layer);
+}
+
+void bmDM_loopIterStep(void *self)
+{
+ bmDM_loopIter *iter = self;
+
+ iter->l = iter->nextl;
+
+ bmvert_to_mvert(iter->l->v, &iter->head.v);
+ iter->head.index++;
+ iter->head.vindex = BMINDEX_GET(iter->l->v);
+ iter->head.eindex = BMINDEX_GET(iter->l->e);
+
+ iter->nextl = BMIter_Step(&iter->iter);
+
+ if (!iter->nextl) iter->head.done = 1;
+}
+
+void *bmDM_getLoopCDData(void *self, int type, int layer)
+{
+ bmDM_loopIter *iter = self;
+
+ if (layer == -1)
+ return CustomData_bmesh_get(&iter->bm->ldata, iter->l->head.data, type);
+ else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->head.data, type, layer);
+}
+
+void *bmDM_getVertCDData(void *self, int type, int layer)
+{
+ bmDM_loopIter *iter = self;
+
+ if (layer == -1)
+ return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->head.data, type);
+ else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->head.data, type, layer);
+}
+
+void bmDM_iterFree(void *self)
+{
+ MEM_freeN(self);
+}
+
+void bmDM_nulliterFree(void *self)
+{
+}
+
+DMLoopIter *bmDM_newLoopsIter(void *faceiter)
+{
+ bmDM_faceIter *fiter = faceiter;
+ bmDM_loopIter *iter = &fiter->loopiter;
+
+ memset(&fiter->loopiter, 0, sizeof(bmDM_loopIter));
+
+ iter->bm = fiter->bm;
+ iter->f = fiter->f;
+ iter->nextl = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f);
+
+ iter->head.step = bmDM_loopIterStep;
+ iter->head.getLoopCDData = bmDM_getLoopCDData;
+ iter->head.getVertCDData = bmDM_getVertCDData;
+
+ bmvert_to_mvert(iter->nextl->v, &iter->head.v);
+ iter->head.vindex = BMINDEX_GET(iter->nextl->v);
+ iter->head.eindex = BMINDEX_GET(iter->nextl->e);
+
+ return (DMLoopIter*) iter;
+}
+
+static DMFaceIter *bmDM_getFaceIter(void *dm)
+{
+ EditDerivedBMesh *bmdm= dm;
+ bmDM_faceIter *iter = MEM_callocN(sizeof(bmDM_faceIter), "bmDM_faceIter");
+ BMIter biter;
+ BMVert *v;
+ BMEdge *e;
+ int i;
+
+ iter->bm = bmdm->tc->bm;
+ iter->f = iter->nextf = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL);
+
+ iter->head.step = bmDM_faceIterStep;
+ iter->head.free = bmDM_iterFree;
+ iter->head.getCDData = bmDM_getFaceCDData;
+ iter->head.getLoopsIter = bmDM_newLoopsIter;
+
+ iter->head.mat_nr = iter->f->mat_nr;
+ iter->head.flags = BMFlags_To_MEFlags(iter->f);
+
+ /*set up vert/edge indices*/
+ i = 0;
+ BM_ITER(v, &biter, iter->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(v, i);
+ i++;
+ }
+
+ i = 0;
+ BM_ITER(e, &biter, iter->bm, BM_EDGES_OF_MESH, NULL) {
+ BMINDEX_SET(e, i);
+ i++;
+ }
+
+ return (DMFaceIter*) iter;
+}
+
+static void bmDM_release(void *dm)
+{
+ EditDerivedBMesh *bmdm= dm;
+
+ if (DM_release(dm)) {
+ if (bmdm->vertexCos) {
+ MEM_freeN(bmdm->vertexCos);
+ MEM_freeN(bmdm->vertexNos);
+ MEM_freeN(bmdm->faceNos);
+ }
+
+ BLI_ghash_free(bmdm->fhash, NULL, NULL);
+ BLI_ghash_free(bmdm->ehash, NULL, NULL);
+ BLI_ghash_free(bmdm->vhash, NULL, NULL);
+
+ if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+ if (bmdm->etable) MEM_freeN(bmdm->etable);
+ if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+
+ MEM_freeN(bmdm);
+ }
+}
+
+DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
+ float (*vertexCos)[3])
+{
+ EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
+ BMesh *bm = em->bm;
+
+ bmdm->tc = em;
+
+ DM_init((DerivedMesh*)bmdm, em->bm->totvert, em->bm->totedge, em->tottri,
+ em->bm->totloop, em->bm->totface);
+
+ bmdm->dm.getMinMax = bmDM_getMinMax;
+
+ bmdm->dm.getNumVerts = bmDM_getNumVerts;
+ bmdm->dm.getNumEdges = bmDM_getNumEdges;
+ bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
+ bmdm->dm.getNumFaces = bmDM_getNumFaces;
+
+ bmdm->dm.getVert = bmDM_getVert;
+ bmdm->dm.getEdge = bmDM_getEdge;
+ bmdm->dm.getTessFace = bmDM_getTessFace;
+ bmdm->dm.copyVertArray = bmDM_copyVertArray;
+ bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
+ bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
+ bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
+
+ bmdm->dm.newFaceIter = bmDM_getFaceIter;
+ bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
+
+ bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
+ bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
+ bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
+
+ bmdm->dm.drawEdges = bmDM_drawEdges;
+ bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
+ bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
+ bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
+ bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
+ bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
+ bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
+ bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
+ bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
+
+ bmdm->dm.release = bmDM_release;
+
+ bmdm->vertexCos = vertexCos;
+
+ if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
+ BMIter iter;
+ BMVert *eve;
+ int i;
+
+ DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
+ CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
+ }
+
+ if(vertexCos) {
+ BMVert *eve;
+ BMIter iter;
+ int totface = bm->totface;
+ int i;
+
+ eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BMINDEX_SET(eve, i);
+
+ bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno");
+ bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ float *v1 = vertexCos[(int) BMINDEX_GET(l[0]->v)];
+ float *v2 = vertexCos[(int) BMINDEX_GET(l[1]->v)];
+ float *v3 = vertexCos[(int) BMINDEX_GET(l[2]->v)];
+ float *no = bmdm->faceNos[i];
+
+ CalcNormFloat(v1, v2, v3, no);
+ VecAddf(bmdm->vertexNos[BMINDEX_GET(l[0]->v)], bmdm->vertexNos[BMINDEX_GET(l[0]->v)], no);
+ VecAddf(bmdm->vertexNos[BMINDEX_GET(l[1]->v)], bmdm->vertexNos[BMINDEX_GET(l[1]->v)], no);
+ VecAddf(bmdm->vertexNos[BMINDEX_GET(l[2]->v)], bmdm->vertexNos[BMINDEX_GET(l[2]->v)], no);
+ }
+
+ eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ float *no = bmdm->vertexNos[i];
+ /* following Mesh convention; we use vertex coordinate itself
+ * for normal in this case */
+ if (Normalize(no)==0.0) {
+ VECCOPY(no, vertexCos[i]);
+ Normalize(no);
+ }
+ }
+ }
+
+ bmdm_recalc_lookups(bmdm);
+
+ return (DerivedMesh*) bmdm;
+}
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index c7a8b150d3a..5566851db43 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -1851,8 +1851,8 @@ static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL)
static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm)
{
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
- int i, numfacets = 0, totface = dm->getNumFaces(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
+ int i, numfacets = 0, totface = dm->getNumTessFaces(dm);
float zero[3] = {0.0f, 0.0f, 0.0f};
for (i=0; i<totface; i++, mface++) {
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 2b4032af503..6c684994e30 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -298,7 +298,7 @@ static DerivedMesh *fluidsim_read_obj(char *filename)
return NULL;
}
- dm = CDDM_new(numverts, 0, numfaces);
+ dm = CDDM_new(numverts, 0, numfaces, 0, 0);
if(!dm)
{
@@ -355,7 +355,7 @@ static DerivedMesh *fluidsim_read_obj(char *filename)
printf("Fluidsim: error in reading data from file.\n");
// read triangles from file
- mface = CDDM_get_faces(dm);
+ mface = CDDM_get_tessfaces(dm);
for(i=0; i<numfaces; i++)
{
int face[4];
@@ -391,6 +391,7 @@ static DerivedMesh *fluidsim_read_obj(char *filename)
CDDM_apply_vert_normals(dm, (short (*)[3])normals);
MEM_freeN(normals);
+ CDDM_tessfaces_to_faces(dm);
// CDDM_calc_normals(result);
return dm;
@@ -458,12 +459,12 @@ DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifie
}
// assign material + flags to new dm
- mface = orgdm->getFaceArray(orgdm);
+ mface = orgdm->getTessFaceArray(orgdm);
mat_nr = mface[0].mat_nr;
flag = mface[0].flag;
- mface = dm->getFaceArray(dm);
- numfaces = dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ numfaces = dm->getNumTessFaces(dm);
for(i=0; i<numfaces; i++)
{
mface[i].mat_nr = mat_nr;
@@ -617,9 +618,9 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
*numVertices = totvert;
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
deleted file mode 100644
index 64558d0b456..00000000000
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ /dev/null
@@ -1,1197 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
- * All rights reserved.
- *
- * Contributor(s): Joshua Leung (full recode)
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-
-#include <math.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-#include <float.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_anim_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_arithb.h"
-#include "BLI_noise.h"
-
-#include "BKE_fcurve.h"
-#include "BKE_curve.h"
-#include "BKE_global.h"
-#include "BKE_idprop.h"
-#include "BKE_utildefines.h"
-
-#include "RNA_access.h"
-#include "RNA_types.h"
-
-#ifndef DISABLE_PYTHON
-#include "BPY_extern.h" /* for BPY_pydriver_eval() */
-#endif
-
-#define SMALL -1.0e-10
-#define SELECT 1
-
-/* ******************************** F-Modifiers ********************************* */
-
-/* Info ------------------------------- */
-
-/* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined
- * on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip.
- */
-
-/* Template --------------------------- */
-
-/* Each modifier defines a set of functions, which will be called at the appropriate
- * times. In addition to this, each modifier should have a type-info struct, where
- * its functions are attached for use.
- */
-
-/* Template for type-info data:
- * - make a copy of this when creating new modifiers, and just change the functions
- * pointed to as necessary
- * - although the naming of functions doesn't matter, it would help for code
- * readability, to follow the same naming convention as is presented here
- * - any functions that a constraint doesn't need to define, don't define
- * for such cases, just use NULL
- * - these should be defined after all the functions have been defined, so that
- * forward-definitions/prototypes don't need to be used!
- * - keep this copy #if-def'd so that future constraints can get based off this
- */
-#if 0
-static FModifierTypeInfo FMI_MODNAME = {
- FMODIFIER_TYPE_MODNAME, /* type */
- sizeof(FMod_ModName), /* size */
- FMI_TYPE_SOME_ACTION, /* action type */
- FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
- "Modifier Name", /* name */
- "FMod_ModName", /* struct name */
- fcm_modname_free, /* free data */
- fcm_modname_relink, /* relink data */
- fcm_modname_copy, /* copy data */
- fcm_modname_new_data, /* new data */
- fcm_modname_verify, /* verify */
- fcm_modname_time, /* evaluate time */
- fcm_modname_evaluate /* evaluate */
-};
-#endif
-
-/* Generator F-Curve Modifier --------------------------- */
-
-/* Generators available:
- * 1) simple polynomial generator:
- * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
- * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
- */
-
-static void fcm_generator_free (FModifier *fcm)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* free polynomial coefficients array */
- if (data->coefficients)
- MEM_freeN(data->coefficients);
-}
-
-static void fcm_generator_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Generator *gen= (FMod_Generator *)fcm->data;
- FMod_Generator *ogen= (FMod_Generator *)src->data;
-
- /* copy coefficients array? */
- if (ogen->coefficients)
- gen->coefficients= MEM_dupallocN(ogen->coefficients);
-}
-
-static void fcm_generator_new_data (void *mdata)
-{
- FMod_Generator *data= (FMod_Generator *)mdata;
- float *cp;
-
- /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
- data->poly_order= 1;
- data->arraysize= 2;
- cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
- cp[0] = 0; // y-offset
- cp[1] = 1; // gradient
-}
-
-static void fcm_generator_verify (FModifier *fcm)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* requirements depend on mode */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
- {
- /* arraysize needs to be order+1, so resize if not */
- if (data->arraysize != (data->poly_order+1)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
-
- if (data->coefficients) {
- if (data->arraysize > (data->poly_order+1))
- memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
- else
- memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
- }
-
- /* set the new data */
- data->coefficients= nc;
- data->arraysize= data->poly_order+1;
- }
- }
- break;
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
- {
- /* arraysize needs to be 2*order, so resize if not */
- if (data->arraysize != (data->poly_order * 2)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
-
- if (data->coefficients) {
- if (data->arraysize > (data->poly_order * 2))
- memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
- else
- memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
- }
-
- /* set the new data */
- data->coefficients= nc;
- data->arraysize= data->poly_order * 2;
- }
- }
- break;
- }
-}
-
-static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* behaviour depends on mode
- * NOTE: the data in its default state is fine too
- */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
- {
- /* we overwrite cvalue with the sum of the polynomial */
- float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
- float value= 0.0f;
- unsigned int i;
-
- /* for each x^n, precalculate value based on previous one first... this should be
- * faster that calling pow() for each entry
- */
- for (i=0; i < data->arraysize; i++) {
- /* first entry is x^0 = 1, otherwise, calculate based on previous */
- if (i)
- powers[i]= powers[i-1] * evaltime;
- else
- powers[0]= 1;
- }
-
- /* for each coefficient, add to value, which we'll write to *cvalue in one go */
- for (i=0; i < data->arraysize; i++)
- value += data->coefficients[i] * powers[i];
-
- /* only if something changed, write *cvalue in one go */
- if (data->poly_order) {
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
-
- /* cleanup */
- if (powers)
- MEM_freeN(powers);
- }
- break;
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
- {
- float value= 1.0f, *cp=NULL;
- unsigned int i;
-
- /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
- for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
- value *= (cp[0]*evaltime + cp[1]);
-
- /* only if something changed, write *cvalue in one go */
- if (data->poly_order) {
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
- }
- break;
- }
-}
-
-static FModifierTypeInfo FMI_GENERATOR = {
- FMODIFIER_TYPE_GENERATOR, /* type */
- sizeof(FMod_Generator), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_NOTHING, /* requirements */
- "Generator", /* name */
- "FMod_Generator", /* struct name */
- fcm_generator_free, /* free data */
- fcm_generator_copy, /* copy data */
- fcm_generator_new_data, /* new data */
- fcm_generator_verify, /* verify */
- NULL, /* evaluate time */
- fcm_generator_evaluate /* evaluate */
-};
-
-/* Built-In Function Generator F-Curve Modifier --------------------------- */
-
-/* This uses the general equation for equations:
- * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset
- *
- * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients,
- * x is the evaluation 'time', and 'y' is the resultant value
- *
- * Functions available are
- * sin, cos, tan, sinc (normalised sin), natural log, square root
- */
-
-static void fcm_fn_generator_new_data (void *mdata)
-{
- FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata;
-
- /* set amplitude and phase multiplier to 1.0f so that something is generated */
- data->amplitude= 1.0f;
- data->phase_multiplier= 1.0f;
-}
-
-/* Unary 'normalised sine' function
- * y = sin(PI + x) / (PI * x),
- * except for x = 0 when y = 1.
- */
-static double sinc (double x)
-{
- if (fabs(x) < 0.0001)
- return 1.0;
- else
- return sin(M_PI * x) / (M_PI * x);
-}
-
-static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data;
- double arg= data->phase_multiplier*evaltime + data->phase_offset;
- double (*fn)(double v) = NULL;
-
- /* get function pointer to the func to use:
- * WARNING: must perform special argument validation hereto guard against crashes
- */
- switch (data->type)
- {
- /* simple ones */
- case FCM_GENERATOR_FN_SIN: /* sine wave */
- fn= sin;
- break;
- case FCM_GENERATOR_FN_COS: /* cosine wave */
- fn= cos;
- break;
- case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
- fn= sinc;
- break;
-
- /* validation required */
- case FCM_GENERATOR_FN_TAN: /* tangent wave */
- {
- /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */
- if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) {
- if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- *cvalue = 0.0f; /* no value possible here */
- }
- else
- fn= tan;
- }
- break;
- case FCM_GENERATOR_FN_LN: /* natural log */
- {
- /* check that value is greater than 1? */
- if (arg > 1.0f) {
- fn= log;
- }
- else {
- if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- *cvalue = 0.0f; /* no value possible here */
- }
- }
- break;
- case FCM_GENERATOR_FN_SQRT: /* square root */
- {
- /* no negative numbers */
- if (arg > 0.0f) {
- fn= sqrt;
- }
- else {
- if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- *cvalue = 0.0f; /* no value possible here */
- }
- }
- break;
-
- default:
- printf("Invalid Function-Generator for F-Modifier - %d \n", data->type);
- }
-
- /* execute function callback to set value if appropriate */
- if (fn) {
- float value= (float)(data->amplitude*fn(arg) + data->value_offset);
-
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
-}
-
-static FModifierTypeInfo FMI_FN_GENERATOR = {
- FMODIFIER_TYPE_FN_GENERATOR, /* type */
- sizeof(FMod_FunctionGenerator), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_NOTHING, /* requirements */
- "Built-In Function", /* name */
- "FMod_FunctionGenerator", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_fn_generator_new_data, /* new data */
- NULL, /* verify */
- NULL, /* evaluate time */
- fcm_fn_generator_evaluate /* evaluate */
-};
-
-/* Envelope F-Curve Modifier --------------------------- */
-
-static void fcm_envelope_free (FModifier *fcm)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
-
- /* free envelope data array */
- if (env->data)
- MEM_freeN(env->data);
-}
-
-static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
- FMod_Envelope *oenv= (FMod_Envelope *)src->data;
-
- /* copy envelope data array */
- if (oenv->data)
- env->data= MEM_dupallocN(oenv->data);
-}
-
-static void fcm_envelope_new_data (void *mdata)
-{
- FMod_Envelope *env= (FMod_Envelope *)mdata;
-
- /* set default min/max ranges */
- env->min= -1.0f;
- env->max= 1.0f;
-}
-
-static void fcm_envelope_verify (FModifier *fcm)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
-
- /* if the are points, perform bubble-sort on them, as user may have changed the order */
- if (env->data) {
- // XXX todo...
- }
-}
-
-static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed, *prevfed, *lastfed;
- float min=0.0f, max=0.0f, fac=0.0f;
- int a;
-
- /* get pointers */
- if (env->data == NULL) return;
- prevfed= env->data;
- fed= prevfed + 1;
- lastfed= prevfed + (env->totvert-1);
-
- /* get min/max values for envelope at evaluation time (relative to mid-value) */
- if (prevfed->time >= evaltime) {
- /* before or on first sample, so just extend value */
- min= prevfed->min;
- max= prevfed->max;
- }
- else if (lastfed->time <= evaltime) {
- /* after or on last sample, so just extend value */
- min= lastfed->min;
- max= lastfed->max;
- }
- else {
- /* evaltime occurs somewhere between segments */
- // TODO: implement binary search for this to make it faster?
- for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {
- /* evaltime occurs within the interval defined by these two envelope points */
- if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {
- float afac, bfac, diff;
-
- diff= fed->time - prevfed->time;
- afac= (evaltime - prevfed->time) / diff;
- bfac= (fed->time - evaltime) / diff;
-
- min= bfac*prevfed->min + afac*fed->min;
- max= bfac*prevfed->max + afac*fed->max;
-
- break;
- }
- }
- }
-
- /* adjust *cvalue
- * - fac is the ratio of how the current y-value corresponds to the reference range
- * - thus, the new value is found by mapping the old range to the new!
- */
- fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
- *cvalue= min + fac*(max - min);
-}
-
-static FModifierTypeInfo FMI_ENVELOPE = {
- FMODIFIER_TYPE_ENVELOPE, /* type */
- sizeof(FMod_Envelope), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Envelope", /* name */
- "FMod_Envelope", /* struct name */
- fcm_envelope_free, /* free data */
- fcm_envelope_copy, /* copy data */
- fcm_envelope_new_data, /* new data */
- fcm_envelope_verify, /* verify */
- NULL, /* evaluate time */
- fcm_envelope_evaluate /* evaluate */
-};
-
-/* Cycles F-Curve Modifier --------------------------- */
-
-/* This modifier changes evaltime to something that exists within the curve's frame-range,
- * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
- * is very likely to be more time-consuming than the original approach... (which was tighly integrated into
- * the calculation code...).
- *
- * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
- * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
- * as appropriate
- */
-
-/* temp data used during evaluation */
-typedef struct tFCMED_Cycles {
- float cycyofs; /* y-offset to apply */
-} tFCMED_Cycles;
-
-static void fcm_cycles_new_data (void *mdata)
-{
- FMod_Cycles *data= (FMod_Cycles *)mdata;
-
- /* turn on cycles by default */
- data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
-}
-
-static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
-{
- FMod_Cycles *data= (FMod_Cycles *)fcm->data;
- float prevkey[2], lastkey[2], cycyofs=0.0f;
- short side=0, mode=0;
- int cycles=0;
-
- /* check if modifier is first in stack, otherwise disable ourself... */
- // FIXME...
- if (fcm->prev) {
- fcm->flag |= FMODIFIER_FLAG_DISABLED;
- return evaltime;
- }
-
- /* calculate new evaltime due to cyclic interpolation */
- if (fcu && fcu->bezt) {
- BezTriple *prevbezt= fcu->bezt;
- BezTriple *lastbezt= prevbezt + fcu->totvert-1;
-
- prevkey[0]= prevbezt->vec[1][0];
- prevkey[1]= prevbezt->vec[1][1];
-
- lastkey[0]= lastbezt->vec[1][0];
- lastkey[1]= lastbezt->vec[1][1];
- }
- else if (fcu && fcu->fpt) {
- FPoint *prevfpt= fcu->fpt;
- FPoint *lastfpt= prevfpt + fcu->totvert-1;
-
- prevkey[0]= prevfpt->vec[0];
- prevkey[1]= prevfpt->vec[1];
-
- lastkey[0]= lastfpt->vec[0];
- lastkey[1]= lastfpt->vec[1];
- }
- else
- return evaltime;
-
- /* check if modifier will do anything
- * 1) if in data range, definitely don't do anything
- * 2) if before first frame or after last frame, make sure some cycling is in use
- */
- if (evaltime < prevkey[0]) {
- if (data->before_mode) {
- side= -1;
- mode= data->before_mode;
- cycles= data->before_cycles;
- }
- }
- else if (evaltime > lastkey[0]) {
- if (data->after_mode) {
- side= 1;
- mode= data->after_mode;
- cycles= data->after_cycles;
- }
- }
- if ELEM(0, side, mode)
- return evaltime;
-
- /* find relative place within a cycle */
- {
- float cycdx=0, cycdy=0, ofs=0;
- float cycle= 0;
-
- /* ofs is start frame of cycle */
- ofs= prevkey[0];
-
- /* calculate period and amplitude (total height) of a cycle */
- cycdx= lastkey[0] - prevkey[0];
- cycdy= lastkey[1] - prevkey[1];
-
- /* check if cycle is infinitely small, to be point of being impossible to use */
- if (cycdx == 0)
- return evaltime;
-
- /* calculate the 'number' of the cycle */
- cycle= ((float)side * (evaltime - ofs) / cycdx);
-
- /* check that cyclic is still enabled for the specified time */
- if (cycles == 0) {
- /* catch this case so that we don't exit when we have cycles=0
- * as this indicates infinite cycles...
- */
- }
- else if (cycle > (cycles+1)) {
- /* we are too far away from range to evaluate
- * TODO: but we should still hold last value...
- */
- return evaltime;
- }
-
- /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
- if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- cycyofs = (float)floor((evaltime - ofs) / cycdx);
- cycyofs *= cycdy;
- }
-
- /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
- if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
- /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
- * - for 'before' extrapolation, we need to flip in a different way, otherwise values past
- * then end of the curve get referenced (result of fmod will be negative, and with different phase)
- */
- if (side < 0)
- evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
- else
- evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
- }
- else {
- /* the cycle is played normally... */
- evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
- }
- if (evaltime < ofs) evaltime += cycdx;
- }
-
- /* store temp data if needed */
- if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- tFCMED_Cycles *edata;
-
- /* for now, this is just a float, but we could get more stuff... */
- fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
- edata->cycyofs= cycyofs;
- }
-
- /* return the new frame to evaluate */
- return evaltime;
-}
-
-static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
-
- /* use temp data */
- if (edata) {
- /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
- *cvalue += edata->cycyofs;
-
- /* free temp data */
- MEM_freeN(edata);
- fcm->edata= NULL;
- }
-}
-
-static FModifierTypeInfo FMI_CYCLES = {
- FMODIFIER_TYPE_CYCLES, /* type */
- sizeof(FMod_Cycles), /* size */
- FMI_TYPE_EXTRAPOLATION, /* action type */
- FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
- "Cycles", /* name */
- "FMod_Cycles", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_cycles_new_data, /* new data */
- NULL /*fcm_cycles_verify*/, /* verify */
- fcm_cycles_time, /* evaluate time */
- fcm_cycles_evaluate /* evaluate */
-};
-
-/* Noise F-Curve Modifier --------------------------- */
-
-static void fcm_noise_new_data (void *mdata)
-{
- FMod_Noise *data= (FMod_Noise *)mdata;
-
- /* defaults */
- data->size= 1.0f;
- data->strength= 1.0f;
- data->phase= 1.0f;
- data->depth = 0;
- data->modification = FCM_NOISE_MODIF_REPLACE;
-}
-
-static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Noise *data= (FMod_Noise *)fcm->data;
- float noise;
-
- noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
-
- switch (data->modification) {
- case FCM_NOISE_MODIF_ADD:
- *cvalue= *cvalue + noise * data->strength;
- break;
- case FCM_NOISE_MODIF_SUBTRACT:
- *cvalue= *cvalue - noise * data->strength;
- break;
- case FCM_NOISE_MODIF_MULTIPLY:
- *cvalue= *cvalue * noise * data->strength;
- break;
- case FCM_NOISE_MODIF_REPLACE:
- default:
- *cvalue= *cvalue + (noise - 0.5f) * data->strength;
- break;
- }
-}
-
-static FModifierTypeInfo FMI_NOISE = {
- FMODIFIER_TYPE_NOISE, /* type */
- sizeof(FMod_Noise), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Noise", /* name */
- "FMod_Noise", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_noise_new_data, /* new data */
- NULL /*fcm_noise_verify*/, /* verify */
- NULL, /* evaluate time */
- fcm_noise_evaluate /* evaluate */
-};
-
-/* Filter F-Curve Modifier --------------------------- */
-
-#if 0 // XXX not yet implemented
-static FModifierTypeInfo FMI_FILTER = {
- FMODIFIER_TYPE_FILTER, /* type */
- sizeof(FMod_Filter), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Filter", /* name */
- "FMod_Filter", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- NULL, /* new data */
- NULL /*fcm_filter_verify*/, /* verify */
- NULL, /* evlauate time */
- fcm_filter_evaluate /* evaluate */
-};
-#endif // XXX not yet implemented
-
-
-/* Python F-Curve Modifier --------------------------- */
-
-static void fcm_python_free (FModifier *fcm)
-{
- FMod_Python *data= (FMod_Python *)fcm->data;
-
- /* id-properties */
- IDP_FreeProperty(data->prop);
- MEM_freeN(data->prop);
-}
-
-static void fcm_python_new_data (void *mdata)
-{
- FMod_Python *data= (FMod_Python *)mdata;
-
- /* everything should be set correctly by calloc, except for the prop->type constant.*/
- data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
- data->prop->type = IDP_GROUP;
-}
-
-static void fcm_python_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Python *pymod = (FMod_Python *)fcm->data;
- FMod_Python *opymod = (FMod_Python *)src->data;
-
- pymod->prop = IDP_CopyProperty(opymod->prop);
-}
-
-static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
-#ifndef DISABLE_PYTHON
- //FMod_Python *data= (FMod_Python *)fcm->data;
-
- /* FIXME... need to implement this modifier...
- * It will need it execute a script using the custom properties
- */
-#endif /* DISABLE_PYTHON */
-}
-
-static FModifierTypeInfo FMI_PYTHON = {
- FMODIFIER_TYPE_PYTHON, /* type */
- sizeof(FMod_Python), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
- "Python", /* name */
- "FMod_Python", /* struct name */
- fcm_python_free, /* free data */
- fcm_python_copy, /* copy data */
- fcm_python_new_data, /* new data */
- NULL /*fcm_python_verify*/, /* verify */
- NULL /*fcm_python_time*/, /* evaluate time */
- fcm_python_evaluate /* evaluate */
-};
-
-
-/* Limits F-Curve Modifier --------------------------- */
-
-static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
-{
- FMod_Limits *data= (FMod_Limits *)fcm->data;
-
- /* check for the time limits */
- if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
- return data->rect.xmin;
- if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
- return data->rect.xmax;
-
- /* modifier doesn't change time */
- return evaltime;
-}
-
-static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Limits *data= (FMod_Limits *)fcm->data;
-
- /* value limits now */
- if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
- *cvalue= data->rect.ymin;
- if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
- *cvalue= data->rect.ymax;
-}
-
-static FModifierTypeInfo FMI_LIMITS = {
- FMODIFIER_TYPE_LIMITS, /* type */
- sizeof(FMod_Limits), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
- FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
- "Limits", /* name */
- "FMod_Limits", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- NULL, /* new data */
- NULL, /* verify */
- fcm_limits_time, /* evaluate time */
- fcm_limits_evaluate /* evaluate */
-};
-
-/* F-Curve Modifier API --------------------------- */
-/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
- * and operations that involve F-Curve modifier specific code.
- */
-
-/* These globals only ever get directly accessed in this file */
-static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
-static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
-
-/* This function only gets called when FMI_INIT is non-zero */
-static void fmods_init_typeinfo ()
-{
- fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
- fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
- fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */
- fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
- fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
- fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */
- fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
- fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
- fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */
-}
-
-/* This function should be used for getting the appropriate type-info when only
- * a F-Curve modifier type is known
- */
-FModifierTypeInfo *get_fmodifier_typeinfo (int type)
-{
- /* initialise the type-info list? */
- if (FMI_INIT) {
- fmods_init_typeinfo();
- FMI_INIT = 0;
- }
-
- /* only return for valid types */
- if ( (type >= FMODIFIER_TYPE_NULL) &&
- (type <= FMODIFIER_NUM_TYPES ) )
- {
- /* there shouldn't be any segfaults here... */
- return fmodifiersTypeInfo[type];
- }
- else {
- printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
- }
-
- return NULL;
-}
-
-/* This function should always be used to get the appropriate type-info, as it
- * has checks which prevent segfaults in some weird cases.
- */
-FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
-{
- /* only return typeinfo for valid modifiers */
- if (fcm)
- return get_fmodifier_typeinfo(fcm->type);
- else
- return NULL;
-}
-
-/* API --------------------------- */
-
-/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
-FModifier *add_fmodifier (ListBase *modifiers, int type)
-{
- FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, fmi)
- return NULL;
-
- /* special checks for whether modifier can be added */
- if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) {
- /* cycles modifier must be first in stack, so for now, don't add if it can't be */
- // TODO: perhaps there is some better way, but for now,
- printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
- return NULL;
- }
-
- /* add modifier itself */
- fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
- fcm->type = type;
- fcm->flag = FMODIFIER_FLAG_EXPANDED;
- BLI_addtail(modifiers, fcm);
-
- /* add modifier's data */
- fcm->data= MEM_callocN(fmi->size, fmi->structName);
-
- /* init custom settings if necessary */
- if (fmi->new_data)
- fmi->new_data(fcm->data);
-
- /* return modifier for further editing */
- return fcm;
-}
-
-/* Duplicate all of the F-Modifiers in the Modifier stacks */
-void copy_fmodifiers (ListBase *dst, ListBase *src)
-{
- FModifier *fcm, *srcfcm;
-
- if ELEM(NULL, dst, src)
- return;
-
- dst->first= dst->last= NULL;
- BLI_duplicatelist(dst, src);
-
- for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* make a new copy of the F-Modifier's data */
- fcm->data = MEM_dupallocN(fcm->data);
-
- /* only do specific constraints if required */
- if (fmi && fmi->copy_data)
- fmi->copy_data(fcm, srcfcm);
- }
-}
-
-/* Remove and free the given F-Modifier from the given stack */
-void remove_fmodifier (ListBase *modifiers, FModifier *fcm)
-{
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* sanity check */
- if (fcm == NULL)
- return;
-
- /* free modifier's special data (stored inside fcm->data) */
- if (fcm->data) {
- if (fmi && fmi->free_data)
- fmi->free_data(fcm);
-
- /* free modifier's data (fcm->data) */
- MEM_freeN(fcm->data);
- }
-
- /* remove modifier from stack */
- if (modifiers)
- BLI_freelinkN(modifiers, fcm);
- else {
- // XXX this case can probably be removed some day, as it shouldn't happen...
- printf("remove_fmodifier() - no modifier stack given \n");
- MEM_freeN(fcm);
- }
-}
-
-/* Remove all of a given F-Curve's modifiers */
-void free_fmodifiers (ListBase *modifiers)
-{
- FModifier *fcm, *fmn;
-
- /* sanity check */
- if (modifiers == NULL)
- return;
-
- /* free each modifier in order - modifier is unlinked from list and freed */
- for (fcm= modifiers->first; fcm; fcm= fmn) {
- fmn= fcm->next;
- remove_fmodifier(modifiers, fcm);
- }
-}
-
-/* Find the active F-Modifier */
-FModifier *find_active_fmodifier (ListBase *modifiers)
-{
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return NULL;
-
- /* loop over modifiers until 'active' one is found */
- for (fcm= modifiers->first; fcm; fcm= fcm->next) {
- if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
- return fcm;
- }
-
- /* no modifier is active */
- return NULL;
-}
-
-/* Set the active F-Modifier */
-void set_active_fmodifier (ListBase *modifiers, FModifier *fcm)
-{
- FModifier *fm;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return;
-
- /* deactivate all, and set current one active */
- for (fm= modifiers->first; fm; fm= fm->next)
- fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
-
- /* make given modifier active */
- if (fcm)
- fcm->flag |= FMODIFIER_FLAG_ACTIVE;
-}
-
-/* Do we have any modifiers which match certain criteria
- * - mtype - type of modifier (if 0, doesn't matter)
- * - acttype - type of action to perform (if -1, doesn't matter)
- */
-short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype)
-{
- FModifier *fcm;
-
- /* if there are no specific filtering criteria, just skip */
- if ((mtype == 0) && (acttype == 0))
- return (modifiers && modifiers->first);
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return 0;
-
- /* find the first mdifier fitting these criteria */
- for (fcm= modifiers->first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
-
- /* check if applicable ones are fullfilled */
- if (mtype)
- mOk= (fcm->type == mtype);
- if (acttype > -1)
- aOk= (fmi->acttype == acttype);
-
- /* if both are ok, we've found a hit */
- if (mOk && aOk)
- return 1;
- }
-
- /* no matches */
- return 0;
-}
-
-/* Evaluation API --------------------------- */
-
-/* evaluate time modifications imposed by some F-Curve Modifiers
- * - this step acts as an optimisation to prevent the F-Curve stack being evaluated
- * several times by modifiers requesting the time be modified, as the final result
- * would have required using the modified time
- * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
- * working on the 'global' result of the modified curve, not some localised segment,
- * so nevaltime gets set to whatever the last time-modifying modifier likes...
- * - we start from the end of the stack, as only the last one matters for now
- */
-float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
-{
- FModifier *fcm;
- float m_evaltime= evaltime;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->last)
- return evaltime;
-
- /* find the first modifier from end of stack that modifies time, and calculate the time the modifier
- * would calculate time at
- */
- for (fcm= modifiers->last; fcm; fcm= fcm->prev) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier_time) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
- break;
- }
- }
-
- /* return the modified evaltime */
- return m_evaltime;
-}
-
-/* Evalautes the given set of F-Curve Modifiers using the given data
- * Should only be called after evaluate_time_fmodifiers() has been called...
- */
-void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
-{
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return;
-
- /* evaluate modifiers */
- for (fcm= modifiers->first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
- }
- }
-}
-
-/* ---------- */
-
-/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
- * by start and end (inclusive).
- */
-void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
-{
- ChannelDriver *driver;
-
- /* sanity checks */
- // TODO: make these tests report errors using reports not printf's
- if ELEM(NULL, fcu, fcu->modifiers.first) {
- printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
- return;
- }
-
- /* temporarily, disable driver while we sample, so that they don't influence the outcome */
- driver= fcu->driver;
- fcu->driver= NULL;
-
- /* bake the modifiers, by sampling the curve at each frame */
- fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
-
- /* free the modifiers now */
- free_fmodifiers(&fcu->modifiers);
-
- /* restore driver */
- fcu->driver= driver;
-}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3facf975992..8f67fdc74d2 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -66,19 +66,24 @@
/* -- */
#include "BKE_object.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_arithb.h"
+#include "bmesh.h"
EditMesh *BKE_mesh_get_editmesh(Mesh *me)
{
- return me->edit_mesh;
+ return bmesh_to_editmesh(me->edit_btmesh->bm);
}
void BKE_mesh_end_editmesh(Mesh *me, EditMesh *em)
{
+ BM_Free_Mesh(me->edit_btmesh->bm);
+ me->edit_btmesh->bm = editmesh_to_bmesh(em);
+ BMEdit_RecalcTesselation(me->edit_btmesh);
}
@@ -93,6 +98,13 @@ void mesh_update_customdata_pointers(Mesh *me)
me->mface = CustomData_get_layer(&me->fdata, CD_MFACE);
me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL);
me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
+
+ me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
+ me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+
+ me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
+ me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+ me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
/* Note: unlinking is called when me->id.us is 0, question remains how
@@ -141,12 +153,14 @@ void free_mesh(Mesh *me)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
if(me->mat) MEM_freeN(me->mat);
if(me->bb) MEM_freeN(me->bb);
if(me->mselect) MEM_freeN(me->mselect);
- if(me->edit_mesh) MEM_freeN(me->edit_mesh);
+ if(me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
@@ -205,6 +219,7 @@ Mesh *copy_mesh(Mesh *me)
{
Mesh *men;
MTFace *tface;
+ MTexPoly *txface;
int a, i;
men= copy_libblock(me);
@@ -218,6 +233,8 @@ Mesh *copy_mesh(Mesh *me)
CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
+ CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop);
+ CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly);
mesh_update_customdata_pointers(men);
/* ensure indirect linked data becomes lib-extern */
@@ -230,7 +247,17 @@ Mesh *copy_mesh(Mesh *me)
id_lib_extern((ID*)tface->tpage);
}
}
-
+
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->pdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++)
+ if(txface->tpage)
+ id_lib_extern((ID*)txface->tpage);
+ }
+ }
+
men->mselect= NULL;
men->bb= MEM_dupallocN(men->bb);
@@ -241,12 +268,43 @@ Mesh *copy_mesh(Mesh *me)
return men;
}
+BMesh *BKE_mesh_to_bmesh(Mesh *me)
+{
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512};
+
+ bm = BM_Make_Mesh(allocsize);
+
+ BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p", me);
+
+ return bm;
+}
+
void make_local_tface(Mesh *me)
{
MTFace *tface;
+ MTexPoly *txface;
Image *ima;
int a, i;
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->fdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++) {
+ /* special case: ima always local immediately */
+ if(txface->tpage) {
+ ima= txface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= 0;
+ ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ima, 0);
+ }
+ }
+ }
+ }
+ }
+
for(i=0; i<me->fdata.totlayer; i++) {
if(me->fdata.layers[i].type == CD_MTFACE) {
tface= (MTFace*)me->fdata.layers[i].data;
@@ -264,6 +322,7 @@ void make_local_tface(Mesh *me)
}
}
}
+
}
void make_local_mesh(Mesh *me)
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 046dfcc9f87..fc4788d9ff3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -24,7 +24,8 @@
* Ton Roosendaal,
* Ben Batt,
* Brecht Van Lommel,
-* Campbell Barton
+* Campbell Barton,
+* Joseph Eagar
*
* ***** END GPL LICENSE BLOCK *****
*
@@ -100,6 +101,7 @@
#include "BKE_subsurf.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "depsgraph_private.h"
#include "BKE_deform.h"
@@ -263,12 +265,12 @@ static void curveModifier_deformVerts(
}
static void curveModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
@@ -355,12 +357,12 @@ static void latticeModifier_deformVerts(
}
static void latticeModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
@@ -416,7 +418,7 @@ static DerivedMesh *subsurfModifier_applyModifier(
}
static DerivedMesh *subsurfModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
SubsurfModifierData *smd = (SubsurfModifierData*) md;
@@ -484,7 +486,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
"build modifier edgeMap");
for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
- maxFaces = dm->getNumFaces(dm);
+ maxFaces = dm->getNumTessFaces(dm);
faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
"build modifier faceMap");
for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
@@ -497,7 +499,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
}
CLAMP(frac, 0.0, 1.0);
- numFaces = dm->getNumFaces(dm) * frac;
+ numFaces = dm->getNumTessFaces(dm) * frac;
numEdges = dm->getNumEdges(dm) * frac;
/* if there's at least one face, build based on faces */
@@ -513,7 +515,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
*/
for(i = 0; i < numFaces; ++i) {
MFace mf;
- dm->getFace(dm, faceMap[i], &mf);
+ dm->getTessFace(dm, faceMap[i], &mf);
if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
@@ -589,7 +591,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
* the mesh
*/
result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
- BLI_ghash_size(edgeHash), numFaces);
+ BLI_ghash_size(edgeHash), numFaces, 0, 0);
/* copy the vertices across */
for(hashIter = BLI_ghashIterator_new(vertHash);
@@ -630,8 +632,8 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
MFace *dest;
int orig_v4;
- dm->getFace(dm, faceMap[i], &source);
- dest = CDDM_get_face(result, i);
+ dm->getTessFace(dm, faceMap[i], &source);
+ dest = CDDM_get_tessface(result, i);
orig_v4 = source.v4;
@@ -641,13 +643,14 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
if(source.v4)
source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
- DM_copy_face_data(dm, result, faceMap[i], i, 1);
+ DM_copy_tessface_data(dm, result, faceMap[i], i, 1);
*dest = source;
test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
}
CDDM_calc_normals(result);
+ CDDM_tessfaces_to_faces(result);
BLI_ghash_free(vertHash, NULL, NULL);
BLI_ghash_free(edgeHash, NULL, NULL);
@@ -655,7 +658,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
MEM_freeN(vertMap);
MEM_freeN(edgeMap);
MEM_freeN(faceMap);
-
+
return result;
}
@@ -719,7 +722,7 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
/* get original number of verts, edges, and faces */
maxVerts= dm->getNumVerts(dm);
maxEdges= dm->getNumEdges(dm);
- maxFaces= dm->getNumFaces(dm);
+ maxFaces= dm->getNumTessFaces(dm);
/* check if we can just return the original mesh
* - must have verts and therefore verts assigned to vgroups to do anything useful
@@ -913,7 +916,7 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
for (i = 0; i < maxFaces; i++)
{
MFace mf;
- dm->getFace(dm, i, &mf);
+ dm->getTessFace(dm, i, &mf);
/* all verts must be available */
if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
@@ -930,7 +933,7 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
/* now we know the number of verts, edges and faces,
* we can create the new (reduced) mesh
*/
- result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
+ result = CDDM_from_template(dm, numVerts, numEdges, numFaces, 0, 0);
/* using ghash-iterators, map data into new mesh */
@@ -984,8 +987,8 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
int orig_v4;
- dm->getFace(dm, oldIndex, &source);
- dest = CDDM_get_face(result, newIndex);
+ dm->getTessFace(dm, oldIndex, &source);
+ dest = CDDM_get_tessface(result, newIndex);
orig_v4 = source.v4;
@@ -995,7 +998,7 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
if (source.v4)
source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
- DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
+ DM_copy_tessface_data(dm, result, oldIndex, newIndex, 1);
*dest = source;
test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
@@ -1010,6 +1013,8 @@ static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
BLI_ghash_free(edgeHash, NULL, NULL);
BLI_ghash_free(faceHash, NULL, NULL);
+ CDDM_tessfaces_to_faces(result);
+
/* return the new mesh */
return result;
}
@@ -1157,6 +1162,7 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
}
}
+#if 0
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
Scene *scene, Object *ob, DerivedMesh *dm,
int initFlags)
@@ -1259,18 +1265,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
*/
finalVerts = dm->getNumVerts(dm) * count;
finalEdges = dm->getNumEdges(dm) * count;
- finalFaces = dm->getNumFaces(dm) * count;
+ finalFaces = dm->getNumTessFaces(dm) * count;
if(start_cap) {
finalVerts += start_cap->getNumVerts(start_cap);
finalEdges += start_cap->getNumEdges(start_cap);
- finalFaces += start_cap->getNumFaces(start_cap);
+ finalFaces += start_cap->getNumTessFaces(start_cap);
}
if(end_cap) {
finalVerts += end_cap->getNumVerts(end_cap);
finalEdges += end_cap->getNumEdges(end_cap);
- finalFaces += end_cap->getNumFaces(end_cap);
+ finalFaces += end_cap->getNumTessFaces(end_cap);
}
- result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
+ result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces, 0, 0);
/* calculate the offset matrix of the final copy (for merging) */
MTC_Mat4One(final_offset);
@@ -1421,15 +1427,15 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
}
}
- maxFaces = dm->getNumFaces(dm);
- mface = CDDM_get_faces(result);
+ maxFaces = dm->getNumTessFaces(dm);
+ mface = CDDM_get_tessfaces(result);
for (i=0; i < maxFaces; i++) {
MFace inMF;
MFace *mf = &mface[numFaces];
- dm->getFace(dm, i, &inMF);
+ dm->getTessFace(dm, i, &inMF);
- DM_copy_face_data(dm, result, i, numFaces, 1);
+ DM_copy_tessface_data(dm, result, i, numFaces, 1);
*mf = inMF;
mf->v1 = indexMap[inMF.v1].new;
@@ -1465,7 +1471,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
{
MFace *mf2 = &mface[numFaces];
- DM_copy_face_data(dm, result, i, numFaces, 1);
+ DM_copy_tessface_data(dm, result, i, numFaces, 1);
*mf2 = *mf;
mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
@@ -1498,10 +1504,10 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
capVerts = start_cap->getNumVerts(start_cap);
capEdges = start_cap->getNumEdges(start_cap);
- capFaces = start_cap->getNumFaces(start_cap);
+ capFaces = start_cap->getNumTessFaces(start_cap);
cap_mvert = start_cap->getVertArray(start_cap);
cap_medge = start_cap->getEdgeArray(start_cap);
- cap_mface = start_cap->getFaceArray(start_cap);
+ cap_mface = start_cap->getTessFaceArray(start_cap);
Mat4Invert(startoffset, offset);
@@ -1560,9 +1566,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
numEdges++;
}
}
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
+ origindex = result->getTessFaceDataArray(result, CD_ORIGINDEX);
for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(start_cap, result, i, numFaces, 1);
+ DM_copy_tessface_data(start_cap, result, i, numFaces, 1);
mface[numFaces] = cap_mface[i];
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
@@ -1599,10 +1605,10 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
capVerts = end_cap->getNumVerts(end_cap);
capEdges = end_cap->getNumEdges(end_cap);
- capFaces = end_cap->getNumFaces(end_cap);
+ capFaces = end_cap->getNumTessFaces(end_cap);
cap_mvert = end_cap->getVertArray(end_cap);
cap_medge = end_cap->getEdgeArray(end_cap);
- cap_mface = end_cap->getFaceArray(end_cap);
+ cap_mface = end_cap->getTessFaceArray(end_cap);
Mat4MulMat4(endoffset, final_offset, offset);
@@ -1661,9 +1667,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
numEdges++;
}
}
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
+ origindex = result->getTessFaceDataArray(result, CD_ORIGINDEX);
for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(end_cap, result, i, numFaces, 1);
+ DM_copy_tessface_data(end_cap, result, i, numFaces, 1);
mface[numFaces] = cap_mface[i];
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
@@ -1694,6 +1700,8 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
CDDM_lower_num_verts(result, numVerts);
CDDM_lower_num_edges(result, numEdges);
CDDM_lower_num_faces(result, numFaces);
+
+ CDDM_tessfaces_to_faces(result);
return result;
}
@@ -1714,11 +1722,19 @@ static DerivedMesh *arrayModifier_applyModifier(
}
static DerivedMesh *arrayModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
}
+#endif
+
+DerivedMesh *arrayModifier_applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc);
+DerivedMesh *arrayModifier_applyModifierEM(ModifierData *md, Object *ob,
+ BMEditMesh *editData,
+ DerivedMesh *derivedData);
/* Mirror */
@@ -1877,6 +1893,7 @@ void vertgroup_flip_name (char *name, int strip_number)
sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
}
+#if 0
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
Object *ob,
DerivedMesh *dm,
@@ -1889,7 +1906,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
int numVerts, numEdges, numFaces;
int maxVerts = dm->getNumVerts(dm);
int maxEdges = dm->getNumEdges(dm);
- int maxFaces = dm->getNumFaces(dm);
+ int maxFaces = dm->getNumTessFaces(dm);
int vector_size=0, j, a, b;
bDeformGroup *def, *defb;
bDeformGroup **vector_def = NULL;
@@ -1900,7 +1917,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
- result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
+ result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2, 0, 0);
if (mmd->flag & MOD_MIR_VGROUP) {
@@ -2035,11 +2052,11 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
for(i = 0; i < maxFaces; i++) {
MFace inMF;
- MFace *mf = CDDM_get_face(result, numFaces);
+ MFace *mf = CDDM_get_tessface(result, numFaces);
- dm->getFace(dm, i, &inMF);
+ dm->getTessFace(dm, i, &inMF);
- DM_copy_face_data(dm, result, i, numFaces, 1);
+ DM_copy_tessface_data(dm, result, i, numFaces, 1);
*mf = inMF;
numFaces++;
@@ -2052,10 +2069,10 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|| indexMap[inMF.v2][1]
|| indexMap[inMF.v3][1]
|| (mf->v4 && indexMap[inMF.v4][1])) {
- MFace *mf2 = CDDM_get_face(result, numFaces);
+ MFace *mf2 = CDDM_get_tessface(result, numFaces);
static int corner_indices[4] = {2, 1, 0, 3};
- DM_copy_face_data(dm, result, i, numFaces, 1);
+ DM_copy_tessface_data(dm, result, i, numFaces, 1);
*mf2 = *mf;
mf2->v1 += indexMap[inMF.v1][1];
@@ -2065,7 +2082,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
/* mirror UVs if enabled */
if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
- MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
+ MTFace *tf = result->getTessFaceData(result, numFaces, CD_MTFACE);
if(tf) {
int j;
for(j = 0; j < 4; ++j) {
@@ -2079,7 +2096,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
/* Flip face normal */
SWAP(int, mf2->v1, mf2->v3);
- DM_swap_face_data(result, numFaces, corner_indices);
+ DM_swap_tessface_data(result, numFaces, corner_indices);
test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
numFaces++;
@@ -2094,8 +2111,11 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
CDDM_lower_num_edges(result, numEdges);
CDDM_lower_num_faces(result, numFaces);
+ CDDM_tessfaces_to_faces(result);
+
return result;
}
+#endif
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
Object *ob, DerivedMesh *dm,
@@ -2137,7 +2157,7 @@ static DerivedMesh *mirrorModifier_applyModifier(
}
static DerivedMesh *mirrorModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
@@ -2428,7 +2448,7 @@ static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
mesh = smoothmesh_new(totvert, totedge, totface,
totvert, totedge, totface);
@@ -2460,7 +2480,7 @@ static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
MVert v1, v2, v3;
int j;
- dm->getFace(dm, i, &mf);
+ dm->getTessFace(dm, i, &mf);
dm->getVert(dm, mf.v1, &v1);
dm->getVert(dm, mf.v2, &v2);
@@ -2502,11 +2522,12 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
{
DerivedMesh *result = CDDM_from_template(mesh->dm,
mesh->num_verts,
- mesh->num_edges,
- mesh->num_faces);
+ mesh->num_edges,
+ mesh->num_faces,
+ 0, 0);
MVert *new_verts = CDDM_get_verts(result);
MEdge *new_edges = CDDM_get_edges(result);
- MFace *new_faces = CDDM_get_faces(result);
+ MFace *new_faces = CDDM_get_tessfaces(result);
int i;
for(i = 0; i < mesh->num_verts; ++i) {
@@ -2533,9 +2554,9 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
SmoothFace *face = &mesh->faces[i];
MFace *newMF = &new_faces[face->newIndex];
- DM_copy_face_data(mesh->dm, result,
+ DM_copy_tessface_data(mesh->dm, result,
face->oldIndex, face->newIndex, 1);
- mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
+ mesh->dm->getTessFace(mesh->dm, face->oldIndex, newMF);
newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
@@ -2548,6 +2569,8 @@ static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
}
}
+ CDDM_tessfaces_to_faces(result);
+
return result;
}
@@ -3360,7 +3383,7 @@ static DerivedMesh *edgesplitModifier_applyModifier(
}
static DerivedMesh *edgesplitModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
@@ -3444,7 +3467,7 @@ static DerivedMesh *bevelModifier_applyModifier(
}
static DerivedMesh *bevelModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return bevelModifier_applyModifier(md, ob, derivedData, 0, 1);
@@ -3580,12 +3603,12 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
/* UVs need special handling, since they come from faces */
if(texmapping == MOD_DISP_MAP_UV) {
- if(dm->getFaceDataArray(dm, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
+ if(dm->getTessFaceDataArray(dm, CD_MTFACE)) {
+ MFace *mface = dm->getTessFaceArray(dm);
MFace *mf;
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
+ int numFaces = dm->getNumTessFaces(dm);
char uvname[32];
MTFace *tf;
@@ -3772,13 +3795,13 @@ static void displaceModifier_deformVerts(
}
static void displaceModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm;
if(derivedData) dm = CDDM_copy(derivedData);
- else dm = CDDM_from_editmesh(editData, ob->data);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
CDDM_apply_vert_coords(dm, vertexCos);
CDDM_calc_normals(dm);
@@ -3898,7 +3921,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
if(num_projectors == 0) return dm;
/* make sure there are UV layers available */
- if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
+ if(!dm->getTessFaceDataArray(dm, CD_MTFACE)) return dm;
/* make sure we're using an existing layer */
validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
@@ -4004,8 +4027,8 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
for(i = 0, co = coords; i < numVerts; ++i, ++co)
Mat4MulVec3Project(projectors[0].projmat, *co);
- mface = dm->getFaceArray(dm);
- numFaces = dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ numFaces = dm->getNumTessFaces(dm);
/* apply coords as UVs, and apply image if tfaces are new */
for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
@@ -4103,7 +4126,7 @@ static DerivedMesh *uvprojectModifier_applyModifier(
}
static DerivedMesh *uvprojectModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
@@ -4139,9 +4162,9 @@ static DerivedMesh *decimateModifier_applyModifier(
int a, numTris;
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
numTris = 0;
for (a=0; a<totface; a++) {
@@ -4217,7 +4240,7 @@ static DerivedMesh *decimateModifier_applyModifier(
}
if(lod.vertex_num>2) {
- mface = CDDM_get_faces(result);
+ mface = CDDM_get_tessfaces(result);
for(a=0; a<lod.face_num; a++) {
MFace *mf = &mface[a];
int *tri = &lod.triangle_index_buffer[a*3];
@@ -4456,13 +4479,13 @@ static void smoothModifier_deformVerts(
}
static void smoothModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm;
if(derivedData) dm = CDDM_copy(derivedData);
- else dm = CDDM_from_editmesh(editData, ob->data);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
CDDM_apply_vert_coords(dm, vertexCos);
CDDM_calc_normals(dm);
@@ -5037,14 +5060,14 @@ static void castModifier_deformVerts(
}
static void castModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
CastModifierData *cmd = (CastModifierData *)md;
if (!dm && ob->type == OB_MESH)
- dm = CDDM_from_editmesh(editData, ob->data);
+ dm = CDDM_from_BMEditMesh(editData, ob->data);
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
@@ -5181,12 +5204,12 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
/* UVs need special handling, since they come from faces */
if(texmapping == MOD_WAV_MAP_UV) {
- if(dm->getFaceDataArray(dm, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
+ if(dm->getTessFaceDataArray(dm, CD_MTFACE)) {
+ MFace *mface = dm->getTessFaceArray(dm);
MFace *mf;
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
+ int numFaces = dm->getNumTessFaces(dm);
char uvname[32];
MTFace *tf;
@@ -5443,7 +5466,7 @@ static void waveModifier_deformVerts(
}
static void waveModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm;
@@ -5452,7 +5475,7 @@ static void waveModifier_deformVertsEM(
if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
dm = derivedData;
else if(derivedData) dm = CDDM_copy(derivedData);
- else dm = CDDM_from_editmesh(editData, ob->data);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
if(wmd->flag & MOD_WAVE_NORM) {
CDDM_apply_vert_coords(dm, vertexCos);
@@ -5543,13 +5566,13 @@ static void armatureModifier_deformVerts(
}
static void armatureModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
amd->deformflag, NULL, amd->defgrp_name);
@@ -5558,14 +5581,14 @@ static void armatureModifier_deformVertsEM(
}
static void armatureModifier_deformMatricesEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3],
float (*defMats)[3][3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
amd->deformflag, NULL, amd->defgrp_name);
@@ -5761,12 +5784,12 @@ static void hookModifier_deformVerts(
}
static void hookModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
@@ -6018,8 +6041,8 @@ static void collisionModifier_deformVerts(
collmd->numverts = numverts;
- collmd->mfaces = dm->dupFaceArray(dm);
- collmd->numfaces = dm->getNumFaces(dm);
+ collmd->mfaces = dm->dupTessFaceArray(dm);
+ collmd->numfaces = dm->getNumTessFaces(dm);
// create bounding box hierarchy
collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
@@ -6218,8 +6241,8 @@ static DerivedMesh *booleanModifier_applyModifier(
DerivedMesh *dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_BAREMESH);
/* we do a quick sanity check */
- if(dm && (derivedData->getNumFaces(derivedData) > 3)
- && bmd->object && dm->getNumFaces(dm) > 3) {
+ if(dm && (derivedData->getNumTessFaces(derivedData) > 3)
+ && bmd->object && dm->getNumTessFaces(dm) > 3) {
DerivedMesh *result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
1 + bmd->operation);
@@ -6378,7 +6401,7 @@ static void particleSystemModifier_deformVerts(
/* report change in mesh structure */
if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
- psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
+ psmd->dm->getNumTessFaces(psmd->dm)!=psmd->totdmface){
/* in file read dm hasn't really changed but just wasn't saved in file */
psys->recalc |= PSYS_RECALC_RESET;
@@ -6386,7 +6409,7 @@ static void particleSystemModifier_deformVerts(
psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
- psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
+ psmd->totdmface= psmd->dm->getNumTessFaces(psmd->dm);
}
if(psys){
@@ -6401,12 +6424,12 @@ static void particleSystemModifier_deformVerts(
* updates is coded */
#if 0
static void particleSystemModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data);
particleSystemModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
@@ -6526,7 +6549,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
pars=psys->particles;
totvert=dm->getNumVerts(dm);
- totface=dm->getNumFaces(dm);
+ totface=dm->getNumTessFaces(dm);
maxvert=totvert*totpart;
maxface=totface*totpart;
@@ -6542,7 +6565,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
max_co=max_r[track];
}
- result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
+ result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface, 0, 0);
mvert=result->getVertArray(result);
orig_mvert=dm->getVertArray(dm);
@@ -6614,8 +6637,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
VECADD(mv->co,mv->co,state.co);
}
- mface=result->getFaceArray(result);
- orig_mface=dm->getFaceArray(dm);
+ mface=result->getTessFaceArray(result);
+ orig_mface=dm->getTessFaceArray(dm);
for(i=0; i<maxface; i++){
MFace *inMF;
@@ -6645,7 +6668,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
}
inMF = orig_mface + i%totface;
- DM_copy_face_data(dm, result, i%totface, i, 1);
+ DM_copy_tessface_data(dm, result, i%totface, i, 1);
*mf = *inMF;
mf->v1+=(i/totface)*totvert;
@@ -6662,14 +6685,15 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
end_latt_deform(psys->lattice);
psys->lattice= NULL;
}
-
+
+ CDDM_tessfaces_to_faces(result);
if(size)
MEM_freeN(size);
return result;
}
static DerivedMesh *particleInstanceModifier_applyModifierEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData)
{
return particleInstanceModifier_applyModifier(md, ob, derivedData, 0, 1);
@@ -6728,8 +6752,8 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd,
int i,p,v1,v2,v3,v4=0;
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
totvert= dm->getNumVerts(dm);
totpart= psmd->psys->totpart;
@@ -6811,12 +6835,12 @@ static int edgesplit_get(EdgeHash *edgehash, int v1, int v2)
static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){
DerivedMesh *splitdm;
MFace *mf=0,*df1=0,*df2=0,*df3=0;
- MFace *mface=CDDM_get_faces(dm);
+ MFace *mface=CDDM_get_tessfaces(dm);
MVert *dupve, *mv;
EdgeHash *edgehash;
EdgeHashIterator *ehi;
int totvert=dm->getNumVerts(dm);
- int totface=dm->getNumFaces(dm);
+ int totface=dm->getNumTessFaces(dm);
int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit");
int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
@@ -6902,14 +6926,14 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
else if(*fs==4){
totfsplit+=3;
- mf=dm->getFaceData(dm,i,CD_MFACE);//CDDM_get_face(dm,i);
+ mf=dm->getTessFaceData(dm,i,CD_MFACE);//CDDM_get_tessface(dm,i);
if(vertpa[mf->v1]!=vertpa[mf->v2] && vertpa[mf->v2]!=vertpa[mf->v3])
totin++;
}
}
- splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit);
+ splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit, 0, 0);
/* copy new faces & verts (is it really this painful with custom data??) */
for(i=0; i<totvert; i++){
@@ -6924,10 +6948,10 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
for(i=0; i<totface; i++){
MFace source;
MFace *dest;
- dm->getFace(dm, i, &source);
- dest = CDDM_get_face(splitdm, i);
+ dm->getTessFace(dm, i, &source);
+ dest = CDDM_get_tessface(splitdm, i);
- DM_copy_face_data(dm, splitdm, i, i, 1);
+ DM_copy_tessface_data(dm, splitdm, i, i, 1);
*dest = source;
}
@@ -6961,7 +6985,7 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
curdupin=totesplit;
for(i=0,fs=facesplit; i<totface; i++,fs++){
if(*fs){
- mf=CDDM_get_face(splitdm,i);
+ mf=CDDM_get_tessface(splitdm,i);
v1=vertpa[mf->v1];
v2=vertpa[mf->v2];
@@ -6969,8 +6993,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
v4=vertpa[mf->v4];
/* ouch! creating new faces & remapping them to new verts is no fun */
if(*fs==1){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df1=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df1=*mf;
curdupface++;
@@ -6993,13 +7017,13 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
test_index_face(df1, &splitdm->faceData, curdupface, (df1->v4 ? 4 : 3));
}
if(*fs==2){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df1=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df1=*mf;
curdupface++;
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df2=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df2=*mf;
curdupface++;
@@ -7070,18 +7094,18 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
}
else if(*fs==3){
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df1=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df1=*mf;
curdupface++;
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df2=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df2=*mf;
curdupface++;
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df3=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df3=*mf;
curdupface++;
@@ -7171,18 +7195,18 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
VecMulf(dupve->co,0.25);
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df1=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df1=*mf;
curdupface++;
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df2=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df2=*mf;
curdupface++;
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df3=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df3=*mf;
curdupface++;
@@ -7211,18 +7235,18 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3));
}
else{
- df1=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df1=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df1=*mf;
curdupface++;
- df2=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df2=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df2=*mf;
curdupface++;
- df3=CDDM_get_face(splitdm,curdupface);
- DM_copy_face_data(splitdm,splitdm,i,curdupface,1);
+ df3=CDDM_get_tessface(splitdm,curdupface);
+ DM_copy_tessface_data(splitdm,splitdm,i,curdupface,1);
*df3=*mf;
curdupface++;
@@ -7276,7 +7300,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive
BLI_edgehash_free(edgehash, NULL);
MEM_freeN(facesplit);
MEM_freeN(vertpa);
-
+
+ CDDM_tessfaces_to_faces(splitdm);
return splitdm;
}
@@ -7298,7 +7323,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
int totdup=0,totvert=0,totface=0,totpart=0;
int i, j, v, mindex=0;
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
totvert= dm->getNumVerts(dm);
totpart= psmd->psys->totpart;
@@ -7320,7 +7345,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
else
mindex = totvert+facepa[i];
- mf=CDDM_get_face(dm,i);
+ mf=CDDM_get_tessface(dm,i);
/* set face vertices to exist in particle group */
BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL);
@@ -7339,7 +7364,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
BLI_edgehashIterator_free(ehi);
/* the final duplicated vertices */
- explode= CDDM_from_template(dm, totdup, 0,totface);
+ explode= CDDM_from_template(dm, totdup, 0,totface, 0, 0);
/*dupvert= CDDM_get_verts(explode);*/
/* getting back to object space */
@@ -7405,8 +7430,8 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue;
}
- dm->getFace(dm,i,&source);
- mf=CDDM_get_face(explode,i);
+ dm->getTessFace(dm,i,&source);
+ mf=CDDM_get_tessface(explode,i);
orig_v4 = source.v4;
@@ -7421,7 +7446,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
if(source.v4)
source.v4 = edgesplit_get(vertpahash, source.v4, mindex);
- DM_copy_face_data(dm,explode,i,i,1);
+ DM_copy_tessface_data(dm,explode,i,i,1);
*mf = source;
@@ -7442,6 +7467,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
psmd->psys->lattice= NULL;
}
+ CDDM_tessfaces_to_faces(explode);
return explode;
}
@@ -7475,7 +7501,7 @@ static DerivedMesh * explodeModifier_applyModifier(
if(emd->facepa==0
|| psmd->flag&eParticleSystemFlag_Pars
|| emd->flag&eExplodeFlag_CalcFaces
- || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){
+ || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumTessFaces(dm)){
if(psmd->flag & eParticleSystemFlag_Pars)
psmd->flag &= ~eParticleSystemFlag_Pars;
@@ -7718,10 +7744,10 @@ static void meshdeformModifier_do(
{
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
Mesh *me= ob->data;
+ BMEditMesh *bem = me->edit_btmesh;
DerivedMesh *tmpdm, *cagedm;
MDeformVert *dvert = NULL;
MDeformWeight *dw;
- EditMesh *em = BKE_mesh_get_editmesh(me);
MVert *cagemvert;
float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3];
@@ -7731,11 +7757,10 @@ static void meshdeformModifier_do(
return;
/* get cage derivedmesh */
- if(em) {
- tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0);
+ if(bem) {
+ tmpdm= editbmesh_get_derived_cage_and_final(md->scene, ob, bem, &cagedm, 0);
if(tmpdm)
tmpdm->release(tmpdm);
- BKE_mesh_end_editmesh(me, em);
}
else
cagedm= mmd->object->derivedFinal;
@@ -7897,13 +7922,13 @@ static void meshdeformModifier_deformVerts(
}
static void meshdeformModifier_deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
+ ModifierData *md, Object *ob, BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm;
if(!derivedData && ob->type == OB_MESH)
- dm = CDDM_from_editmesh(editData, ob->data);
+ dm = CDDM_from_BMEditMesh(editData, ob->data);
else
dm = derivedData;
@@ -8055,7 +8080,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived
dm->release(dm);
}
-static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = NULL;
CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md);
@@ -8063,7 +8088,7 @@ static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditM
if(dataMask)
{
if(derivedData) dm = CDDM_copy(derivedData);
- else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data);
+ else if(ob->type==OB_MESH) dm = CDDM_from_BMEditMesh(editData, ob->data);
else if(ob->type==OB_LATTICE) dm = NULL;
else return;
@@ -8170,7 +8195,7 @@ static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, Deriv
}
-static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = NULL;
CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md);
@@ -8179,7 +8204,7 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, Edi
if(dataMask)
{
if(derivedData) dm = CDDM_copy(derivedData);
- else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data);
+ else if(ob->type==OB_MESH) dm = CDDM_from_BMEditMesh(editData, ob->data);
else if(ob->type==OB_LATTICE) dm = NULL;
else return;
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
new file mode 100644
index 00000000000..b3ce91855b2
--- /dev/null
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -0,0 +1,568 @@
+/*
+* $Id: modifier_bmesh.c 20831 2009-06-12 14:02:37Z joeedh $
+*
+* ***** 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.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Joseph Eagar
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+* Modifier stack implementation.
+*
+* BKE_modifier.h contains the function prototypes for this file.
+*
+*/
+
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+#include "ctype.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_kdtree.h"
+#include "BLI_linklist.h"
+#include "BLI_rand.h"
+#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_editVert.h"
+
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+
+#include "BKE_main.h"
+#include "BKE_anim.h"
+#include "BKE_bmesh.h"
+// XXX #include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+#include "BKE_simple_deform.h"
+
+#include "CCGSubSurf.h"
+#include "RE_shader_ext.h"
+#include "LOD_decimation.h"
+
+/*converts a cddm to a BMEditMesh. if existing is non-NULL, the
+ new geometry will be put in there.*/
+BMEditMesh *CDDM_To_BMesh(DerivedMesh *dm, BMEditMesh *existing)
+{
+ int allocsize[4] = {512, 512, 2048, 512};
+ BMesh *bm, bmold; /*bmold is for storing old customdata layout*/
+ BMEditMesh *em = existing;
+ MVert *mv;
+ MEdge *me;
+ DMFaceIter *dfiter;
+ DMLoopIter *dliter;
+ BMVert *v, **vtable, **verts=NULL;
+ BMEdge *e, **etable, **edges=NULL;
+ BMFace *f;
+ BMIter liter, iter;
+ V_DECLARE(verts);
+ V_DECLARE(edges);
+ void *tmp;
+ int numTex, numCol;
+ int i, j, k, tot, totvert, totedge, totface;
+
+ if (em) bm = em->bm;
+ else bm = BM_Make_Mesh(allocsize);
+
+ bmold = *bm;
+
+ /*merge custom data layout*/
+ CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_BMESH|CD_MASK_ORIGINDEX, CD_CALLOC, bm, BM_VERT);
+ CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_BMESH|CD_MASK_ORIGINDEX, CD_CALLOC, bm, BM_EDGE);
+ CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_BMESH|CD_MASK_ORIGINDEX, CD_CALLOC, bm, BM_LOOP);
+ CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_BMESH|CD_MASK_ORIGINDEX, CD_CALLOC, bm, BM_FACE);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+
+ vtable = MEM_callocN(sizeof(void**)*totvert, "vert table in BMDM_Copy");
+ etable = MEM_callocN(sizeof(void**)*totedge, "edge table in BMDM_Copy");
+
+ /*do verts*/
+ mv = dm->dupVertArray(dm);
+ for (i=0; i<totvert; i++, mv++) {
+ v = BM_Make_Vert(bm, mv->co, NULL);
+
+ v->bweight = mv->bweight;
+ VECCOPY(v->no, mv->no);
+ v->head.flag = MEFlags_To_BMFlags(mv->flag, BM_VERT);
+
+ CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
+ vtable[i] = v;
+ }
+
+ /*do edges*/
+ me = dm->dupEdgeArray(dm);
+ for (i=0; i<totedge; i++, me++) {
+ e = BM_Make_Edge(bm, vtable[me->v1], vtable[me->v2], NULL, 0);
+
+ e->bweight = me->bweight;
+ e->crease = me->crease;
+ e->head.flag = MEFlags_To_BMFlags(me->flag, BM_EDGE);
+
+ CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data);
+ etable[i] = e;
+ }
+
+ k = 0;
+ dfiter = dm->newFaceIter(dm);
+ for (; !dfiter->done; dfiter->step(dfiter)) {
+ BMLoop *l;
+
+ V_RESET(verts);
+ V_RESET(edges);
+
+ dliter = dfiter->getLoopsIter(dfiter);
+ for (j=0; !dliter->done; dliter->step(dliter), j++) {
+ V_GROW(verts);
+ V_GROW(edges);
+
+ verts[j] = vtable[dliter->vindex];
+ edges[j] = etable[dliter->eindex];
+ }
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, dfiter->len, 0);
+ f->head.flag = MEFlags_To_BMFlags(dfiter->flags, BM_FACE);
+
+ if (!f)
+ continue;
+
+ dliter = dfiter->getLoopsIter(dfiter);
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (j=0; l; l=BMIter_Step(&liter)) {
+ CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data);
+ k += 1;
+ }
+
+ CustomData_to_bmesh_block(&dm->polyData, &bm->pdata,
+ dfiter->index, &f->head.data);
+ }
+
+ MEM_freeN(vtable);
+ MEM_freeN(etable);
+
+ if (!em) em = BMEdit_Create(bm);
+ else BMEdit_RecalcTesselation(em);
+
+ return em;
+}
+
+float vertarray_size(MVert *mvert, int numVerts, int axis);
+
+
+typedef struct IndexMapEntry {
+ /* the new vert index that this old vert index maps to */
+ int new;
+ /* -1 if this vert isn't merged, otherwise the old vert index it
+ * should be replaced with
+ */
+ int merge;
+ /* 1 if this vert's first copy is merged with the last copy of its
+ * merge target, otherwise 0
+ */
+ short merge_final;
+} IndexMapEntry;
+
+/* indexMap - an array of IndexMap entries
+ * oldIndex - the old index to map
+ * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
+ */
+static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
+{
+ if(indexMap[oldIndex].merge < 0) {
+ /* vert wasn't merged, so use copy of this vert */
+ return indexMap[oldIndex].new + copyNum;
+ } else if(indexMap[oldIndex].merge == oldIndex) {
+ /* vert was merged with itself */
+ return indexMap[oldIndex].new;
+ } else {
+ /* vert was merged with another vert */
+ /* follow the chain of merges to the end, or until we've passed
+ * a number of vertices equal to the copy number
+ */
+ if(copyNum <= 0)
+ return indexMap[oldIndex].new;
+ else
+ return calc_mapping(indexMap, indexMap[oldIndex].merge,
+ copyNum - 1);
+ }
+}
+
+static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
+ Scene *scene, Object *ob, DerivedMesh *dm,
+ int initFlags)
+{
+ DerivedMesh *cddm = CDDM_copy(dm);
+ BMEditMesh *em = CDDM_To_BMesh(cddm, NULL);
+ BMOperator op, oldop, weldop;
+ int i, j, indexLen;
+ /* offset matrix */
+ float offset[4][4];
+ float final_offset[4][4];
+ float tmp_mat[4][4];
+ float length = amd->length;
+ int count = amd->count;
+ int numVerts, numEdges, numFaces;
+ int maxVerts, maxEdges, maxFaces;
+ int finalVerts, finalEdges, finalFaces;
+ int *indexMap;
+ DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
+ MVert *src_mvert;
+
+ /* need to avoid infinite recursion here */
+ if(amd->start_cap && amd->start_cap != ob)
+ start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
+ if(amd->end_cap && amd->end_cap != ob)
+ end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
+
+ MTC_Mat4One(offset);
+
+ src_mvert = cddm->getVertArray(dm);
+ maxVerts = cddm->getNumVerts(dm);
+
+ if(amd->offset_type & MOD_ARR_OFF_CONST)
+ VecAddf(offset[3], offset[3], amd->offset);
+ if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
+ for(j = 0; j < 3; j++)
+ offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
+ maxVerts, j);
+ }
+
+ if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
+ float obinv[4][4];
+ float result_mat[4][4];
+
+ if(ob)
+ MTC_Mat4Invert(obinv, ob->obmat);
+ else
+ MTC_Mat4One(obinv);
+
+ MTC_Mat4MulSerie(result_mat, offset,
+ obinv, amd->offset_ob->obmat,
+ NULL, NULL, NULL, NULL, NULL);
+ MTC_Mat4CpyMat4(offset, result_mat);
+ }
+
+ if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
+ Curve *cu = amd->curve_ob->data;
+ if(cu) {
+ float tmp_mat[3][3];
+ float scale;
+
+ object_to_mat3(amd->curve_ob, tmp_mat);
+ scale = Mat3ToScalef(tmp_mat);
+
+ if(!cu->path) {
+ cu->flag |= CU_PATH; // needed for path & bevlist
+ makeDispListCurveTypes(scene, amd->curve_ob, 0);
+ }
+ if(cu->path)
+ length = scale*cu->path->totdist;
+ }
+ }
+
+ /* calculate the maximum number of copies which will fit within the
+ prescribed length */
+ if(amd->fit_type == MOD_ARR_FITLENGTH
+ || amd->fit_type == MOD_ARR_FITCURVE)
+ {
+ float dist = sqrt(MTC_dot3Float(offset[3], offset[3]));
+
+ if(dist > 1e-6f)
+ /* this gives length = first copy start to last copy end
+ add a tiny offset for floating point rounding errors */
+ count = (length + 1e-6f) / dist;
+ else
+ /* if the offset has no translation, just make one copy */
+ count = 1;
+ }
+
+ if(count < 1)
+ count = 1;
+
+ /* allocate memory for count duplicates (including original) plus
+ * start and end caps
+ */
+ finalVerts = dm->getNumVerts(dm) * count;
+ finalEdges = dm->getNumEdges(dm) * count;
+ finalFaces = dm->getNumFaces(dm) * count;
+ if(start_cap) {
+ finalVerts += start_cap->getNumVerts(start_cap);
+ finalEdges += start_cap->getNumEdges(start_cap);
+ finalFaces += start_cap->getNumFaces(start_cap);
+ }
+ if(end_cap) {
+ finalVerts += end_cap->getNumVerts(end_cap);
+ finalEdges += end_cap->getNumEdges(end_cap);
+ finalFaces += end_cap->getNumFaces(end_cap);
+ }
+
+ /* calculate the offset matrix of the final copy (for merging) */
+ MTC_Mat4One(final_offset);
+
+ for(j=0; j < count - 1; j++) {
+ MTC_Mat4MulMat4(tmp_mat, final_offset, offset);
+ MTC_Mat4CpyMat4(final_offset, tmp_mat);
+ }
+
+ cddm->needsFree = 1;
+ cddm->release(cddm);
+
+ BMO_Init_Op(&weldop, "weldverts");
+ BMO_InitOpf(em->bm, &op, "dupe geom=%avef");
+ oldop = op;
+ for (j=0; j < count; j++) {
+ BMVert *v, *v2;
+ BMOpSlot *s1;
+ BMOpSlot *s2;
+
+ BMO_InitOpf(em->bm, &op, "dupe geom=%s", &oldop, j==0 ? "geom" : "newout");
+ BMO_Exec_Op(em->bm, &op);
+
+ s1 = BMO_GetSlot(&op, "geom");
+ s2 = BMO_GetSlot(&op, "newout");
+
+ BMO_CallOpf(em->bm, "transform mat=%m4 verts=%s", offset, &op, "newout");
+
+ #define _E(s, i) ((BMVert**)(s)->data.buf)[i]
+
+ /*calculate merge mapping*/
+ if (j == 0) {
+ BMOperator findop;
+ BMOIter oiter;
+ BMIter iter;
+ BMVert *v, *v2;
+ BMHeader *h;
+
+ BMO_InitOpf(em->bm, &findop,
+ "finddoubles verts=%av dist=%f keepverts=%s",
+ amd->merge_dist, &op, "geom");
+
+ i = 0;
+ BMO_ITER(h, &oiter, em->bm, &op, "geom", BM_ALL) {
+ BMINDEX_SET(h, i);
+ i++;
+ }
+
+ BMO_ITER(h, &oiter, em->bm, &op, "newout", BM_ALL) {
+ BMINDEX_SET(h, i);
+ i++;
+ }
+
+ BMO_Exec_Op(em->bm, &findop);
+
+ indexLen = i;
+ indexMap = MEM_callocN(sizeof(int)*indexLen, "indexMap");
+
+ /*element type argument doesn't do anything here*/
+ BMO_ITER(v, &oiter, em->bm, &findop, "targetmapout", 0) {
+ v2 = BMO_IterMapValp(&oiter);
+
+ /*make sure merge pairs are duplicate-to-duplicate*/
+ /*if (BMINDEX_GET(v) >= s1->len && BMINDEX_GET(v2) >= s1->len)
+ continue;
+ else if (BMINDEX_GET(v) < s1->len && BMINDEX_GET(v2) < s1->len)
+ continue;*/
+
+ indexMap[BMINDEX_GET(v)] = BMINDEX_GET(v2)+1;
+ }
+
+ BMO_Finish_Op(em->bm, &findop);
+ }
+
+ /*generate merge mappping using index map. we do this by using the
+ operator slots as lookup arrays.*/
+ #define E(i) (i) < s1->len ? _E(s1, i) : _E(s2, (i)-s1->len)
+
+ for (i=0; i<indexLen; i++) {
+ if (!indexMap[i]) continue;
+
+ v = E(i);
+ v2 = E(indexMap[i]-1);
+
+ BMO_Insert_MapPointer(em->bm, &weldop, "targetmap", v, v2);
+ }
+
+ #undef E
+ #undef _E
+
+ BMO_Finish_Op(em->bm, &oldop);
+ oldop = op;
+ }
+
+ if (j > 0) BMO_Finish_Op(em->bm, &op);
+
+ BMO_Exec_Op(em->bm, &weldop);
+ BMO_Finish_Op(em->bm, &weldop);
+
+ //BMO_CallOpf(em->bm, "removedoubles verts=%av dist=%f", amd->merge_dist);
+
+ BMEdit_RecalcTesselation(em);
+ cddm = CDDM_from_BMEditMesh(em, NULL);
+
+ BMEdit_Free(em);
+ MEM_freeN(indexMap);
+
+ return cddm;
+}
+
+DerivedMesh *arrayModifier_applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ ArrayModifierData *amd = (ArrayModifierData*) md;
+
+ result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
+
+ //if(result != derivedData)
+ // CDDM_calc_normals(result);
+
+ return result;
+}
+
+DerivedMesh *arrayModifier_applyModifierEM(ModifierData *md, Object *ob,
+ BMEditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
+}
+
+/* Mirror */
+
+DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+ Object *ob,
+ DerivedMesh *dm,
+ int initFlags,
+ int axis)
+{
+ int i;
+ float tolerance = mmd->tolerance;
+ DerivedMesh *result, *cddm;
+ BMEditMesh *em;
+ BMesh *bm;
+ int numVerts, numEdges, numFaces;
+ int maxVerts = dm->getNumVerts(dm);
+ int maxEdges = dm->getNumEdges(dm);
+ int maxFaces = dm->getNumTessFaces(dm);
+ int vector_size=0, j, a, b;
+ bDeformGroup *def, *defb;
+ bDeformGroup **vector_def = NULL;
+ int (*indexMap)[2];
+ float mtx[4][4], imtx[4][4];
+
+ cddm = CDDM_copy(dm);
+ em = CDDM_To_BMesh(dm, NULL);
+
+ cddm->needsFree = 1;
+ cddm->release(cddm);
+
+ /*convienence variable*/
+ bm = em->bm;
+
+ numVerts = numEdges = numFaces = 0;
+ indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
+ result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2, 0, 0);
+
+ if (mmd->flag & MOD_MIR_VGROUP) {
+ /* calculate the number of deformedGroups */
+ for(vector_size = 0, def = ob->defbase.first; def;
+ def = def->next, vector_size++);
+
+ /* load the deformedGroups for fast access */
+ vector_def =
+ (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
+ "group_index");
+ for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+ vector_def[a] = def;
+ }
+ }
+
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
+
+ Mat4Invert(obinv, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, ob->obmat, obinv);
+ Mat4Invert(imtx, mtx);
+ }
+
+
+
+ BMEdit_RecalcTesselation(em);
+ result = CDDM_from_BMEditMesh(em, NULL);
+
+ BMEdit_Free(em);
+
+ return result;
+}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 5def910ddef..03838e3c258 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -469,7 +469,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista
mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0);
totsubvert = mrdm->getNumVerts(mrdm);
totsubedge = mrdm->getNumEdges(mrdm);
- totsubface = mrdm->getNumFaces(mrdm);
+ totsubface = mrdm->getNumTessFaces(mrdm);
orig->needsFree = 1;
orig->release(orig);
@@ -1198,7 +1198,7 @@ static void multiresModifier_update(DerivedMesh *dm)
final = multires_subdisp_pre(dm, totlvl - lvl, 0);
multires_subdisp(orig, me, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm),
- dm->getNumFaces(dm), 1);
+ dm->getNumTessFaces(dm), 1);
subco_dm->release(subco_dm);
orig->release(orig);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 02c0d46a73f..82eca760a60 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -96,6 +96,7 @@
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -862,7 +863,7 @@ void free_lamp(Lamp *la)
BKE_free_animdata((ID *)la);
- curvemapping_free(la->curfalloff);
+ curvemapping_free(la->curfalloff);
BKE_previewimg_free(&la->preview);
BKE_icon_delete(&la->id);
@@ -2314,12 +2315,11 @@ void object_handle_update(Scene *scene, Object *ob)
/* includes all keys and modifiers */
if(ob->type==OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(ob->data);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
- // here was vieweditdatamask? XXX
+ // here was vieweditdatamask? XXX
if(ob==scene->obedit) {
makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH);
- BKE_mesh_end_editmesh(ob->data, em);
} else
makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index cefeafcdd50..8e0e948f0a4 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -697,9 +697,9 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
return tot;
mvert= dm->getVertArray(dm);
- mface= dm->getFaceArray(dm);
- origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
- totface= dm->getNumFaces(dm);
+ mface= dm->getTessFaceArray(dm);
+ origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ totface= dm->getNumTessFaces(dm);
totorigface= me->totface;
if(totface == 0 || totorigface == 0 || origindex == NULL)
@@ -1347,7 +1347,7 @@ float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index,
case PART_FROM_FACE:
case PART_FROM_VOLUME:
{
- MFace *mf=dm->getFaceData(dm,index,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,index,CD_MFACE);
return interpolate_particle_value(values[mf->v1],values[mf->v2],values[mf->v3],values[mf->v4],fw,mf->v4);
}
@@ -1395,11 +1395,11 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float *
int quad, findex, totface;
float uv[2], (*faceuv)[2];
- mface = dm->getFaceDataArray(dm, CD_MFACE);
- origindex = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- osface = dm->getFaceDataArray(dm, CD_ORIGSPACE);
+ mface = dm->getTessFaceDataArray(dm, CD_MFACE);
+ origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
if(osface==NULL || origindex==NULL) {
/* Assume we dont need osface data */
@@ -1468,7 +1468,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
*mapindex = index;
}
else { /* FROM_FACE/FROM_VOLUME */
- if(index >= dm->getNumFaces(dm))
+ if(index >= dm->getNumTessFaces(dm))
return 0;
*mapindex = index;
@@ -1492,15 +1492,15 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
i = index_dmcache;
- if(i== DMCACHE_NOTFOUND || i >= dm->getNumFaces(dm))
+ if(i== DMCACHE_NOTFOUND || i >= dm->getNumTessFaces(dm))
return 0;
*mapindex = i;
/* modify the original weights to become
* weights for the derived mesh face */
- osface= dm->getFaceDataArray(dm, CD_ORIGSPACE);
- mface= dm->getFaceData(dm, i, CD_MFACE);
+ osface= dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
+ mface= dm->getTessFaceData(dm, i, CD_MFACE);
if(osface == NULL)
mapfw[0]= mapfw[1]= mapfw[2]= mapfw[3]= 0.0f;
@@ -1558,7 +1558,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
MTFace *mtface;
MVert *mvert;
- mface=dm->getFaceData(dm,mapindex,CD_MFACE);
+ mface=dm->getTessFaceData(dm,mapindex,CD_MFACE);
mvert=dm->getVertDataArray(dm,CD_MVERT);
mtface=CustomData_get_layer(&dm->faceData,CD_MTFACE);
@@ -2946,10 +2946,10 @@ static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float m
int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache;
- if (i==-1 || i >= dm->getNumFaces(dm)) { Mat4One(mat); return; }
+ if (i==-1 || i >= dm->getNumTessFaces(dm)) { Mat4One(mat); return; }
- mface=dm->getFaceData(dm,i,CD_MFACE);
- osface=dm->getFaceData(dm,i,CD_ORIGSPACE);
+ mface=dm->getTessFaceData(dm,i,CD_MFACE);
+ osface=dm->getTessFaceData(dm,i,CD_ORIGSPACE);
if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) {
VECCOPY(v[0], orcodata[mface->v1]);
@@ -3309,7 +3309,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl
if(pa) {
i= (pa->num_dmcache==DMCACHE_NOTFOUND)? pa->num: pa->num_dmcache;
- if(i >= dm->getNumFaces(dm))
+ if(i >= dm->getNumTessFaces(dm))
i = -1;
}
else
@@ -3321,7 +3321,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl
texco[2]= 0.0f;
}
else {
- mf= dm->getFaceData(dm, i, CD_MFACE);
+ mf= dm->getTessFaceData(dm, i, CD_MFACE);
psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
@@ -3962,7 +3962,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo
if(part->childtype == PART_CHILD_FACES) {
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
if(mtface) {
- mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE);
+ mface= psmd->dm->getTessFaceData(psmd->dm, cpa->num, CD_MFACE);
mtface += cpa->num;
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
}
@@ -3982,11 +3982,11 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo
num= pa->num_dmcache;
if(num == DMCACHE_NOTFOUND)
- if(pa->num < psmd->dm->getNumFaces(psmd->dm))
+ if(pa->num < psmd->dm->getNumTessFaces(psmd->dm))
num= pa->num;
if(mtface && num != DMCACHE_NOTFOUND) {
- mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
+ mface= psmd->dm->getTessFaceData(psmd->dm, num, CD_MFACE);
mtface += num;
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 56ca3e8e22b..9004f4b9973 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -410,7 +410,7 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
int amax= from==PART_FROM_FACE ? 3 : 1;
totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
for(a=0; a<amax; a++){
if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@ -419,7 +419,7 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
for(a1=0; a1<size[(a+1)%3]; a1++){
for(a2=0; a2<size[(a+2)%3]; a2++){
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
pa=psys->particles + a1*a1mul + a2*a2mul;
VECCOPY(co1,pa->fuv);
@@ -633,7 +633,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C
MFace *mface;
pa->num = i = ctx->index[p];
- mface = dm->getFaceData(dm,i,CD_MFACE);
+ mface = dm->getTessFaceData(dm,i,CD_MFACE);
switch(distr){
case PART_DISTR_JIT:
@@ -672,7 +672,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C
min_d=2.0;
intersect=0;
- for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
+ for(i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
if(i==pa->num) continue;
v1=mvert[mface->v1].co;
@@ -734,7 +734,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C
return;
}
- mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
+ mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
//switch(distr){
// case PART_DISTR_JIT:
@@ -1165,7 +1165,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive
orcodata= dm->getVertDataArray(dm, CD_ORCO);
for(i=0; i<tot; i++){
- MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
if(orcodata) {
VECCOPY(co1, orcodata[mf->v1]);
@@ -1234,7 +1234,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive
}
else { /* PART_FROM_FACE / PART_FROM_VOLUME */
for(i=0;i<tot; i++){
- MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
if(mf->v4) {
@@ -1309,7 +1309,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive
}
else {
if(dm->numFaceData)
- COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
}
if(COMPARE_ORIG_INDEX) {
@@ -3031,7 +3031,7 @@ int psys_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos
}
totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
mvert=dm->getVertDataArray(dm,CD_MVERT);
/* lets intersect the faces */
@@ -3472,7 +3472,7 @@ static int boid_see_mesh(ListBase *lb, Scene *scene, Object *pob, ParticleSystem
psys_enable_all(ob);
}
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
mface+=min_face;
mvert=dm->getVertDataArray(dm,CD_MVERT);
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 27357d92aae..577156ef453 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -50,6 +50,8 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_subsurf.h"
+#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_kdtree.h"
@@ -98,14 +100,13 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c
DerivedMesh *object_get_derived_final(struct Scene *scene, Object *ob, CustomDataMask dataMask)
{
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
if (em)
{
DerivedMesh *final = NULL;
- editmesh_get_derived_cage_and_final(scene, ob, em, &final, dataMask);
-
- BKE_mesh_end_editmesh(me, em);
+ editbmesh_get_derived_cage_and_final(scene, ob, em, &final, dataMask);
+
return final;
}
else
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index bc6b487080c..3e6f30cde36 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -247,11 +247,11 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
/* first some paranoia checks */
if (!dm) return NULL;
- if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return NULL;
+ if (!dm->getNumVerts(dm) || !dm->getNumTessFaces(dm)) return NULL;
pccd_M = MEM_mallocN(sizeof(ccd_Mesh),"ccd_Mesh");
pccd_M->totvert = dm->getNumVerts(dm);
- pccd_M->totface = dm->getNumFaces(dm);
+ pccd_M->totface = dm->getNumTessFaces(dm);
pccd_M->savety = CCD_SAVETY;
pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
@@ -280,7 +280,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
}
/* alloc and copy faces*/
- pccd_M->mface = dm->dupFaceArray(dm);
+ pccd_M->mface = dm->dupTessFaceArray(dm);
/* OBBs for idea1 */
pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface,"ccd_Mesh_Faces_mima");
@@ -343,10 +343,10 @@ static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M, DerivedMesh *dm)
/* first some paranoia checks */
if (!dm) return ;
- if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return ;
+ if (!dm->getNumVerts(dm) || !dm->getNumTessFaces(dm)) return ;
if ((pccd_M->totvert != dm->getNumVerts(dm)) ||
- (pccd_M->totface != dm->getNumFaces(dm))) return;
+ (pccd_M->totface != dm->getNumTessFaces(dm))) return;
pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 6e95fe7ebc7..61f10239148 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -231,10 +231,11 @@ static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGV
}
static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
- MFace *mface = dm->getFaceArray(dm);
+#if 0
+ MFace *mface = dm->getTessFaceArray(dm);
MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
int i, j, seam;
UvMapVert *v;
UvVertMap *vmap;
@@ -324,6 +325,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
free_uv_vert_map(vmap);
ccgSubSurf_processSync(ss);
+#endif
return 1;
}
@@ -349,7 +351,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
}
/* get some info from CCGSubsurf */
- totface = ccgSubSurf_getNumFaces(uvss);
+ totface = ccgSubSurf_getNumTessFaces(uvss);
edgeSize = ccgSubSurf_getEdgeSize(uvss);
gridSize = ccgSubSurf_getGridSize(uvss);
gridFaces = gridSize - 1;
@@ -427,7 +429,7 @@ static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditme
}
#endif
-/* face weighting */
+
static void calc_ss_weights(int gridFaces,
FaceVertWeight **qweight, FaceVertWeight **tweight)
{
@@ -471,6 +473,61 @@ static void calc_ss_weights(int gridFaces,
}
}
+/* face weighting */
+typedef struct FaceVertWeightEntry {
+ FaceVertWeight *weight;
+ int valid;
+} FaceVertWeightEntry;
+
+typedef struct WeightTable {
+ FaceVertWeightEntry *weight_table;
+ int len;
+} WeightTable;
+
+static FaceVertWeight *get_ss_weights(WeightTable *wtable, int gridFaces, int faceLen)
+{
+ int i;
+
+ /*ensure we have at least the triangle and quad weights*/
+ if (wtable->len < 4) {
+ wtable->weight_table = MEM_callocN(sizeof(FaceVertWeightEntry)*5, "weight table alloc");
+ wtable->len = 5;
+
+ calc_ss_weights(gridFaces, &wtable->weight_table[4].weight, &wtable->weight_table[3].weight);
+ wtable->weight_table[4].valid = wtable->weight_table[3].valid = 1;
+ }
+
+ if (wtable->len <= faceLen) {
+ void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2");
+
+ memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry)*wtable->len);
+ MEM_freeN(wtable->weight_table);
+
+ wtable->weight_table = tmp;
+ wtable->len = faceLen+1;
+ }
+
+ if (!wtable->weight_table[faceLen].valid) {
+ /*ok, need to calculate weights here*/
+ wtable->weight_table[faceLen].weight =
+ MEM_callocN(sizeof(FaceVertWeight)*gridFaces*gridFaces,
+ "vert face weight");
+ wtable->weight_table[faceLen].valid = 1;
+ }
+
+ return wtable->weight_table[faceLen].weight;
+}
+
+void free_ss_weights(WeightTable *wtable)
+{
+ int i;
+
+ for (i=0; i<wtable->len; i++) {
+ if (wtable->weight_table[i].valid)
+ MEM_freeN(wtable->weight_table[i].weight);
+ }
+}
+
static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
int drawInteriorEdges, int useSubsurfUv,
DerivedMesh *dm, MultiresSubsurf *ms)
@@ -481,6 +538,8 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
int gridFaces = gridSize - 1;
int edgeBase, faceBase;
int i, j, k, S, x, y, index;
+ int *vertIdx = NULL;
+ V_DECLARE(vertIdx);
CCGVertIterator *vi;
CCGEdgeIterator *ei;
CCGFaceIterator *fi;
@@ -490,11 +549,13 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
int totvert, totedge, totface;
MVert *mvert;
MEdge *med;
+ float *w = NULL;
+ WeightTable wtable;
+ V_DECLARE(w);
MFace *mf;
int *origIndex;
- FaceVertWeight *qweight, *tweight;
- calc_ss_weights(gridFaces, &qweight, &tweight);
+ memset(&wtable, 0, sizeof(wtable));
/* vert map */
totvert = ccgSubSurf_getNumVerts(ss);
@@ -516,7 +577,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
fi = ccgSubSurf_getFaceIterator(ss);
for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
@@ -529,17 +590,17 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
if(ms) {
result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss),
ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ ccgSubSurf_getNumFinalFaces(ss), 0, 0);
}
else {
if(dm) {
result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ ccgSubSurf_getNumFinalFaces(ss), 0, 0);
} else {
result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ ccgSubSurf_getNumFinalFaces(ss), 0, 0);
}
}
@@ -551,11 +612,13 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
for(index = 0; index < totface; index++) {
CCGFace *f = faceMap2[index];
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
- FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
- int vertIdx[4];
+ FaceVertWeight *weight = get_ss_weights(&wtable, gridFaces, numVerts);
+
+ V_RESET(vertIdx);
for(S = 0; S < numVerts; S++) {
CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ V_GROW(vertIdx);
vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
}
@@ -567,17 +630,22 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
++origIndex;
i++;
+ V_RESET(w);
+ for (x=0; x<numVerts; x++) {
+ V_GROW(w);
+ }
+
for(S = 0; S < numVerts; S++) {
int prevS = (S - 1 + numVerts) % numVerts;
int nextS = (S + 1) % numVerts;
- int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ int otherS = (numVerts >= 4) ? (S + 2) % numVerts : 3;
for(x = 1; x < gridFaces; x++) {
- float w[4];
w[prevS] = weight[x][0][0];
w[S] = weight[x][0][1];
w[nextS] = weight[x][0][2];
w[otherS] = weight[x][0][3];
+
DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
VecCopyf(mvert->co,
ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
@@ -588,20 +656,25 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
i++;
}
}
+
+ V_RESET(w);
+ for (x=0; x<numVerts; x++) {
+ V_GROW(w);
+ }
for(S = 0; S < numVerts; S++) {
int prevS = (S - 1 + numVerts) % numVerts;
int nextS = (S + 1) % numVerts;
int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
-
+
for(y = 1; y < gridFaces; y++) {
for(x = 1; x < gridFaces; x++) {
- float w[4];
w[prevS] = weight[y * gridFaces + x][0][0];
w[S] = weight[y * gridFaces + x][0][1];
w[nextS] = weight[y * gridFaces + x][0][2];
w[otherS] = weight[y * gridFaces + x][0][3];
DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
+
VecCopyf(mvert->co,
ccgSubSurf_getFaceGridData(ss, f, S, x, y));
*origIndex = ORIGINDEX_NONE;
@@ -611,7 +684,6 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
}
}
-
*((int*)ccgSubSurf_getFaceUserData(ss, f)) = faceBase;
faceBase += 1 + numVerts * ((gridSize-2) + (gridSize-2) * (gridSize-2));
}
@@ -627,12 +699,14 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
v = ccgSubSurf_getEdgeVert1(e);
vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
-
+
for(x = 1; x < edgeSize - 1; x++) {
- float w[2];
- w[1] = (float) x / (edgeSize - 1);
- w[0] = 1 - w[1];
- DM_interp_vert_data(dm, result, vertIdx, w, 2, i);
+ float w2[2];
+
+ w2[1] = (float) x / (edgeSize - 1);
+ w2[0] = 1 - w2[1];
+ DM_interp_vert_data(dm, result, vertIdx, w2, 2, i);
+
VecCopyf(mvert->co, ccgSubSurf_getEdgeData(ss, e, x));
*origIndex = ORIGINDEX_NONE;
++mvert;
@@ -737,8 +811,8 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
// load faces
i = 0;
- mf = CDDM_get_faces(result);
- origIndex = result->getFaceData(result, 0, CD_ORIGINDEX);
+ mf = CDDM_get_tessfaces(result);
+ origIndex = result->getTessFaceData(result, 0, CD_ORIGINDEX);
for(index = 0; index < totface; index++) {
CCGFace *f = faceMap2[index];
@@ -750,7 +824,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
if(!ssFromEditmesh) {
MFace origMFace;
- dm->getFace(dm, faceIdx, &origMFace);
+ dm->getTessFace(dm, faceIdx, &origMFace);
mat_nr = origMFace.mat_nr;
flag = origMFace.flag;
@@ -761,8 +835,8 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
for(S = 0; S < numVerts; S++) {
- FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
-
+ FaceVertWeight *weight = get_ss_weights(&wtable, gridFaces, numVerts);
+
for(y = 0; y < gridFaces; y++) {
for(x = 0; x < gridFaces; x++) {
mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
@@ -775,7 +849,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
edgeSize, gridSize);
mf->mat_nr = mat_nr;
mf->flag = flag;
-
+#if 0 //BMESH_TODO
if(dm) {
int prevS = (S - 1 + numVerts) % numVerts;
int nextS = (S + 1) % numVerts;
@@ -789,10 +863,11 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
w[j][otherS] = (*weight)[j][3];
}
- DM_interp_face_data(dm, result, &faceIdx, NULL,
+ DM_interp_tessface_data(dm, result, &faceIdx, NULL,
&w, 1, i);
weight++;
}
+#endif
*origIndex = mapIndex;
++mf;
@@ -807,8 +882,9 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
MEM_freeN(edgeMap2);
MEM_freeN(vertMap2);
- MEM_freeN(tweight);
- MEM_freeN(qweight);
+ free_ss_weights(&wtable);
+
+ V_FREE(vertIdx);
if(useSubsurfUv) {
CustomData *fdata = &result->faceData;
@@ -821,7 +897,9 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
CDDM_calc_normals(result);
-
+ CDDM_tessfaces_to_faces(result);
+
+ V_FREE(w);
return result;
}
@@ -829,18 +907,22 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
float (*vertexCos)[3], int useFlatSubdiv)
{
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
- CCGVertHDL fVerts[4];
+ CCGVertHDL *fVerts = NULL;
+ V_DECLARE(fVerts);
int totvert = dm->getNumVerts(dm);
int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
+ int totpoly = dm->getNumFaces(dm);
int i;
int *index;
MVert *mvert = dm->getVertArray(dm);
MEdge *medge = dm->getEdgeArray(dm);
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
MVert *mv;
MEdge *me;
MFace *mf;
+ DMFaceIter *fiter;
+ DMLoopIter *liter;
ccgSubSurf_initFullSync(ss);
@@ -872,28 +954,31 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = *index;
}
-
- mf = mface;
- index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
- for (i = 0; i < totface; i++, mf++, index++) {
+
+ fiter = dm->newFaceIter(dm);
+ for (i=0; !fiter->done; fiter->step(fiter), i++) {
CCGFace *f;
+ V_RESET(fVerts);
- fVerts[0] = SET_INT_IN_POINTER(mf->v1);
- fVerts[1] = SET_INT_IN_POINTER(mf->v2);
- fVerts[2] = SET_INT_IN_POINTER(mf->v3);
- fVerts[3] = SET_INT_IN_POINTER(mf->v4);
+ index = (int*) fiter->getCDData(fiter, CD_ORIGINDEX, -1);
+ liter = fiter->getLoopsIter(fiter);
+
+ for (; !liter->done; liter->step(liter)) {
+ V_GROW(fVerts);
+ fVerts[V_COUNT(fVerts)-1] = SET_INT_IN_POINTER(liter->vindex);
+ }
- // this is very bad, means mesh is internally consistent.
- // it is not really possible to continue without modifying
- // other parts of code significantly to handle missing faces.
- // since this really shouldn't even be possible we just bail.
- if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
+ /* this is very bad, means mesh is internally inconsistent.
+ * it is not really possible to continue without modifying
+ * other parts of code significantly to handle missing faces.
+ * since this really shouldn't even be possible we just bail.*/
+ if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fiter->len,
fVerts, &f) == eCCGError_InvalidValue) {
static int hasGivenError = 0;
if(!hasGivenError) {
- //XXX error("Unrecoverable error in SubSurf calculation,"
- // " mesh is inconsistent.");
+ printf("Unrecoverable error in SubSurf calculation,"
+ " mesh is inconsistent.\n");
hasGivenError = 1;
}
@@ -975,7 +1060,7 @@ static int ccgDM_getNumEdges(DerivedMesh *dm) {
return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
}
-static int ccgDM_getNumFaces(DerivedMesh *dm) {
+static int ccgDM_getNumTessFaces(DerivedMesh *dm) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
@@ -989,9 +1074,9 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
memset(mv, 0, sizeof(*mv));
- if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
+ if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumTessFaces(ss) > 0)) {
/* this vert comes from face data */
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+ int lastface = ccgSubSurf_getNumTessFaces(ss) - 1;
CCGFace *f;
int x, y, grid, numVerts;
int offset;
@@ -1064,7 +1149,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
if(edgeNum < ccgdm->edgeMap[0].startEdge) {
/* this edge comes from face data */
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+ int lastface = ccgSubSurf_getNumTessFaces(ss) - 1;
CCGFace *f;
int x, y, grid, numVerts;
int offset;
@@ -1146,8 +1231,8 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
int offset;
int grid;
int x, y;
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
+ int lastface = ccgSubSurf_getNumTessFaces(ss) - 1;
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
memset(mf, 0, sizeof(*mf));
@@ -1183,7 +1268,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int i = 0;
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
for(index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -1238,7 +1323,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
int i = 0;
int *edgeFlags = dm->getEdgeDataArray(dm, CD_FLAGS);
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
for(index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -1308,6 +1393,138 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
}
}
+struct ccgDM_faceIter;
+
+typedef struct ccgDM_loopIter {
+ DMLoopIter head;
+ int curloop;
+ CCGDerivedMesh *ccgdm;
+ struct ccgDM_faceIter *fiter;
+} ccgDM_loopIter;
+
+typedef struct ccgDM_faceIter {
+ DMFaceIter head;
+ CCGDerivedMesh *ccgdm;
+ MFace mface;
+
+ ccgDM_loopIter liter;
+} ccgDM_faceIter;
+
+void ccgDM_faceIterStep(void *self)
+{
+ ccgDM_faceIter *fiter = self;
+
+ if (!fiter->ccgdm || !fiter->ccgdm->ss) {
+ fiter->head.done = 1;
+ return;
+ }
+
+ if (fiter->head.index >= ccgSubSurf_getNumTessFaces(fiter->ccgdm->ss)) {
+ fiter->head.done = 1;
+ return;
+ };
+
+ fiter->head.index++;
+
+ ccgDM_getFinalFace((DerivedMesh*)fiter->ccgdm, fiter->head.index, &fiter->mface);
+
+ fiter->head.flags = fiter->mface.flag;
+ fiter->head.mat_nr = fiter->mface.mat_nr;
+ fiter->head.len = fiter->mface.v4 ? 4 : 3;
+}
+
+void *ccgDM_faceIterCData(void *self, int type, int layer)
+{
+ ccgDM_faceIter *fiter = self;
+
+ if (layer == -1)
+ return CustomData_get(&fiter->ccgdm->dm.faceData, fiter->head.index, type);
+ else
+ return CustomData_get_n(&fiter->ccgdm->dm.faceData, type, fiter->head.index, layer);
+}
+
+void ccgDM_loopIterStep(void *self)
+{
+ ccgDM_loopIter *liter = self;
+ MFace *mf = &liter->fiter->mface;
+ int i, in;
+
+ if (liter->head.index >= liter->fiter->head.len) {
+ liter->head.done = 1;
+ return;
+ }
+
+ liter->head.index++;
+ i = liter->head.index;
+
+ switch (i) {
+ case 0:
+ in = liter->fiter->mface.v1;
+ break;
+ case 1:
+ in = liter->fiter->mface.v2;
+ break;
+ case 2:
+ in = liter->fiter->mface.v3;
+ break;
+ case 3:
+ in = liter->fiter->mface.v4;
+ break;
+ }
+
+ liter->head.vindex = in;
+
+ /*we don't set .eindex*/
+ ccgDM_getFinalVert((DerivedMesh*)liter->ccgdm, in, &liter->head.v);
+}
+
+void *ccgDM_loopIterGetVCData(void *self, int type, int layer)
+{
+ ccgDM_loopIter *liter = self;
+
+ if (layer == -1)
+ return CustomData_get(&liter->ccgdm->dm.vertData, liter->head.vindex, type);
+ else return CustomData_get_n(&liter->ccgdm->dm.vertData, type, liter->head.vindex, layer);
+}
+
+void *ccgDM_loopIterGetCData(void *self, int type, int layer)
+{
+ ccgDM_loopIter *liter = self;
+
+ /*BMESH_TODO
+ yeek, this has to convert mface-style uv/mcols to loop-style*/
+ return NULL;
+}
+
+DMLoopIter *ccgDM_faceIterGetLIter(void *self)
+{
+ ccgDM_faceIter *fiter = self;
+
+ fiter->liter.head.index = -1;
+ fiter->liter.head.done = 0;
+ fiter->liter.head.step(&fiter->liter);
+
+ return (DMLoopIter*) &fiter->liter;
+}
+
+DMFaceIter *ccgDM_newFaceIter(DerivedMesh *dm)
+{
+ ccgDM_faceIter *fiter = MEM_callocN(sizeof(ccgDM_faceIter), "ccgDM_faceIter");
+
+ fiter->head.free = MEM_freeN;
+ fiter->head.step = ccgDM_faceIterStep;
+ fiter->head.index = -1;
+ fiter->head.getCDData = ccgDM_faceIterCData;
+ fiter->head.getLoopsIter = ccgDM_faceIterGetLIter;
+
+ fiter->liter.fiter = fiter;
+ fiter->liter.head.getLoopCDData = ccgDM_loopIterGetCData;
+ fiter->liter.head.getVertCDData = ccgDM_loopIterGetVCData;
+ fiter->liter.head.step = ccgDM_loopIterStep;
+
+ fiter->head.step(fiter);
+}
+
static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
@@ -1317,9 +1534,9 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int i = 0;
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
for(index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -1382,7 +1599,7 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
fi = ccgSubSurf_getFaceIterator(ss);
for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
@@ -1690,7 +1907,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
GPUVertexAttribs gattribs;
DMVertexAttribs attribs;
- MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+ MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1727,7 +1944,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
} \
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
for(a = 0, i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, drawSmooth;
@@ -1922,7 +2139,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
for(i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2054,7 +2271,7 @@ static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
static void ccgDM_drawUVEdges(DerivedMesh *dm)
{
- MFace *mf = dm->getFaceArray(dm);
+ MFace *mf = dm->getTessFaceArray(dm);
MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
int i;
@@ -2089,7 +2306,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
CCGSubSurf *ss = ccgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
int i, gridSize = ccgSubSurf_getGridSize(ss);
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) {
CCGFace *f = ccgFaceIterator_getCurrent(fi);
@@ -2274,6 +2491,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int edgeSize;
int gridSize;
int gridFaces;
+ int *vertIdx = NULL;
+ V_DECLARE(vertIdx);
int gridSideVerts;
/*int gridInternalVerts; - as yet unused */
int gridSideEdges;
@@ -2285,7 +2504,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss),
ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ ccgSubSurf_getNumFinalFaces(ss),
+ 0, 0);
DM_add_face_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
DM_add_edge_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
@@ -2294,21 +2514,24 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getMinMax = ccgDM_getMinMax;
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
- ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
+ ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
+ ccgdm->dm.getNumFaces = ccgDM_getNumTessFaces;
+
+ ccgdm->dm.newFaceIter = ccgDM_newFaceIter;
ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
- ccgdm->dm.getFace = ccgDM_getFinalFace;
+ ccgdm->dm.getTessFace = ccgDM_getFinalFace;
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
+ ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
ccgdm->dm.getVertData = DM_get_vert_data;
ccgdm->dm.getEdgeData = DM_get_edge_data;
- ccgdm->dm.getFaceData = DM_get_face_data;
+ ccgdm->dm.getTessFaceData = DM_get_face_data;
ccgdm->dm.getVertDataArray = DM_get_vert_data_layer;
ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
- ccgdm->dm.getFaceDataArray = DM_get_face_data_layer;
+ ccgdm->dm.getTessFaceDataArray = DM_get_face_data_layer;
ccgdm->dm.getVertCos = ccgdm_getVertCos;
ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
@@ -2355,7 +2578,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = ccgSubSurf_getNumTessFaces(ss);
ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
fi = ccgSubSurf_getFaceIterator(ss);
for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
@@ -2381,7 +2604,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/* mvert = dm->getVertArray(dm); - as yet unused */
medge = dm->getEdgeArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
/*edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);*/
@@ -2397,7 +2620,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
int S, x, y;
- int vertIdx[4];
ccgdm->faceMap[index].startVert = vertNum;
ccgdm->faceMap[index].startEdge = edgeNum;
@@ -2405,9 +2627,11 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/* set the face base vert */
*((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
-
+
+ V_RESET(vertIdx);
for(S = 0; S < numVerts; S++) {
CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ V_GROW(vertIdx);
vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
}
@@ -2418,18 +2642,22 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
++vertOrigIndex;
++vertNum;
+
for(S = 0; S < numVerts; S++) {
int prevS = (S - 1 + numVerts) % numVerts;
int nextS = (S + 1) % numVerts;
int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+
for(x = 1; x < gridFaces; x++) {
float w[4];
+#if 0 //BMESH_TODO
w[prevS] = weight[x][0][0];
w[S] = weight[x][0][1];
w[nextS] = weight[x][0][2];
w[otherS] = weight[x][0][3];
DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
numVerts, vertNum);
+#endif
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
++vertNum;
@@ -2443,12 +2671,14 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
for(y = 1; y < gridFaces; y++) {
for(x = 1; x < gridFaces; x++) {
float w[4];
+#if 0 //BMESH_TODO
w[prevS] = weight[y * gridFaces + x][0][0];
w[S] = weight[y * gridFaces + x][0][1];
w[nextS] = weight[y * gridFaces + x][0][2];
w[otherS] = weight[y * gridFaces + x][0][3];
DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
numVerts, vertNum);
+#endif
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
++vertNum;
@@ -2472,6 +2702,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
FaceVertWeight w;
int j;
+#if 0 //BMESH_TODO
for(j = 0; j < 4; ++j) {
w[j][prevS] = (*weight)[j][0];
w[j][S] = (*weight)[j][1];
@@ -2479,9 +2710,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
w[j][otherS] = (*weight)[j][3];
}
- DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
+ DM_interp_tessface_data(dm, &ccgdm->dm, &origIndex, NULL,
&w, 1, faceNum);
weight++;
+#endif
*faceOrigIndex = mapIndex;
@@ -2572,6 +2804,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
MEM_freeN(qweight);
MEM_freeN(tweight);
+ V_FREE(vertIdx);
return ccgdm;
}
diff --git a/source/blender/blenkernel/intern/verse_bitmap_node.c b/source/blender/blenkernel/intern/verse_bitmap_node.c
new file mode 100644
index 00000000000..d27f7a13f02
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_bitmap_node.c
@@ -0,0 +1,451 @@
+/**
+ * $Id: verse_bitmap_node.c 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth);
+static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type);
+static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
+static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile);
+
+static void change_layer_dimension(
+ VBitmapLayer *vblayer,
+ unsigned int old_width,
+ unsigned int old_height,
+ unsigned int t_old_width,
+ unsigned int t_old_height);
+static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer);
+
+/*
+ * resize/crop verse bitmap layer
+ */
+static void change_layer_dimension(
+ VBitmapLayer *vblayer,
+ unsigned int old_width,
+ unsigned int old_height,
+ unsigned int t_old_width,
+ unsigned int t_old_height)
+{
+ struct VNode *vnode = vblayer->vnode;
+ unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
+ unsigned int width = ((VBitmapData*)(vnode->data))->width;
+ unsigned int height = ((VBitmapData*)(vnode->data))->height;
+ unsigned int x, y, i, j;
+
+ i = j = 0;
+
+ /* "copy" old data to new data */
+ if(vblayer->type==VN_B_LAYER_UINT8) {
+ unsigned char *data = (unsigned char*)vblayer->data;
+ /* allocate new verse bitmap layer data */
+ unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer);
+ for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) {
+ for(x=0; x<old_width && y<width; x++, i++, j++) {
+ new_data[i] = data[j];
+ }
+ }
+ MEM_freeN(vblayer->data);
+ vblayer->data = new_data;
+ }
+}
+
+/*
+ * free data stored in verse bitmap layer
+ */
+void free_bitmap_layer_data(VBitmapLayer *vblayer)
+{
+ struct VerseSession *session = vblayer->vnode->session;
+
+ /* free name of bitmap layer */
+ MEM_freeN(vblayer->name);
+
+ /* unsubscribe from verse bitmap layer */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id);
+
+ /* free image data of bitmap layer */
+ if(vblayer->data) MEM_freeN(vblayer->data);
+}
+
+/*
+ * allocate data of verse bitmap layer
+ */
+static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer)
+{
+ struct VNode *vnode = vblayer->vnode;
+ unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
+ unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height;
+ unsigned int size;
+ void *data;
+
+ size = t_width*t_height;
+
+ /* allocation of own data stored in verse bitmap layer */
+ switch (vblayer->type) {
+ case VN_B_LAYER_UINT1:
+ data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1");
+ break;
+ case VN_B_LAYER_UINT8:
+ data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8");
+ break;
+ case VN_B_LAYER_UINT16:
+ data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16");
+ break;
+ case VN_B_LAYER_REAL32:
+ data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16");
+ break;
+ case VN_B_LAYER_REAL64:
+ data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32");
+ break;
+ default:
+ data = NULL;
+ break;
+ }
+
+ return data;
+}
+
+/*
+ * create verse bitmap layer
+ */
+VBitmapLayer *create_bitmap_layer(
+ VNode *vnode,
+ VLayerID layer_id,
+ const char *name,
+ VNBLayerType type)
+{
+ struct VBitmapLayer *vblayer;
+ unsigned int width = ((VBitmapData*)(vnode->data))->width;
+ unsigned int height = ((VBitmapData*)(vnode->data))->height;
+
+ /* allocate memory for own verse bitmap layer */
+ vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer");
+
+ /* verse bitmap layer will include pointer at parent verse node and own id */
+ vblayer->vnode = vnode;
+ vblayer->id = layer_id;
+
+ /* name of verse layer */
+ vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name");
+ vblayer->name[0] = '\0';
+ strcpy(vblayer->name, name);
+
+ /* type of data stored in verse bitmap layer */
+ vblayer->type = type;
+
+ /* we can allocate memory for layer data, when we know dimmension of layers; when
+ * we don't know it, then we will allocate this data when we will receive dimmension */
+ if(width==0 || height==0)
+ vblayer->data = NULL;
+ else
+ vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
+
+ vblayer->flag = 0;
+
+ return vblayer;
+}
+
+/*
+ * free data of bitmap node
+ */
+void free_bitmap_node_data(VNode *vnode)
+{
+ if(vnode->data) {
+ struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first;
+
+ /* free all VerseLayer data */
+ while(vblayer) {
+ free_bitmap_layer_data(vblayer);
+ vblayer = vblayer->next;
+ }
+
+ /* free all VerseLayers */
+ BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
+ }
+}
+
+/*
+ * create data of bitmap node
+ */
+VBitmapData *create_bitmap_data()
+{
+ struct VBitmapData *vbitmap;
+
+ vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data");
+
+ BLI_dlist_init(&(vbitmap->layers));
+ vbitmap->queue.first = vbitmap->queue.last = NULL;
+
+ vbitmap->width = 0;
+ vbitmap->height = 0;
+ vbitmap->depth = 0;
+
+ vbitmap->image = NULL;
+
+ vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set;
+ vbitmap->post_bitmap_layer_create = post_bitmap_layer_create;
+ vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy;
+ vbitmap->post_bitmap_tile_set = post_bitmap_tile_set;
+
+ return vbitmap;
+}
+
+/*
+ * callback function, dimension of image was changed, it is neccessary to
+ * crop all layers
+ */
+static void cb_b_dimension_set(
+ void *user_data,
+ VNodeID node_id,
+ uint16 width,
+ uint16 height,
+ uint16 depth)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VBitmapLayer *vblayer;
+ unsigned int old_width, old_height, t_old_width, t_old_height;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf("\t cb_b_dimension_set()\n");
+#endif
+
+ /* backup old width and height */
+ old_width = ((VBitmapData*)(vnode->data))->width;
+ old_height = ((VBitmapData*)(vnode->data))->height;
+ t_old_width = ((VBitmapData*)(vnode->data))->t_width;
+ t_old_height = ((VBitmapData*)(vnode->data))->t_height;
+
+ /* set up new dimension of layers */
+ ((VBitmapData*)(vnode->data))->width = width;
+ ((VBitmapData*)(vnode->data))->height = height;
+ ((VBitmapData*)(vnode->data))->depth = depth;
+
+ /* we cache t_width because tiles aren't one pixel width */
+ if((width % VN_B_TILE_SIZE)!=0)
+ ((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
+ else
+ ((VBitmapData*)(vnode->data))->t_width = width;
+
+ /* we cache t_height because tiles aren't one pixel height */
+ if((height % VN_B_TILE_SIZE)!=0)
+ ((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
+ else
+ ((VBitmapData*)(vnode->data))->t_height = height;
+
+ /* crop resize all layers */
+ vblayer = ((VBitmapData*)vnode->data)->layers.lb.first;
+
+ while(vblayer) {
+ /* when this callback function received after cb_b_layer_create,
+ * then we have to allocate memory for verse bitmap layer data */
+ if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
+ /* crop/resize all verse bitmap layers */
+ else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height);
+
+ vblayer = vblayer->next;
+ }
+
+ /* post callback function */
+ ((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode);
+}
+
+/*
+ * callback function, new layer channel of image was created
+ */
+static void cb_b_layer_create(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id,
+ const char *name,
+ VNBLayerType type)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VBitmapLayer *vblayer;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf("\t cb_b_layer_create()\n");
+#endif
+
+ /* when no layer exists, then new layer will be created */
+ vblayer = create_bitmap_layer(vnode, layer_id, name, type);
+
+ /* add verse bitmap layer to list of layers */
+ BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id);
+
+ /* post callback function */
+ ((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer);
+
+}
+
+/*
+ * callback function, existing layer of image was destroyed
+ */
+static void cb_b_layer_destroy(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VBitmapLayer *vblayer;
+
+ if(!session) return;
+
+ /* find node of this layer*/
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
+ if(!vblayer) return;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf("\t cb_b_layer_destroy()\n");
+#endif
+
+ /* remove verse bitmap layer from list of layers */
+ BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id);
+
+ /* post callback function */
+ ((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer);
+
+ /* free data of verse bitmap layer */
+ free_bitmap_layer_data(vblayer);
+
+ /* free verse bitmap layer */
+ MEM_freeN(vblayer);
+}
+
+/*
+ * callback function, small part (8x8 pixels) was changed
+ */
+static void cb_b_tile_set(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint16 tile_x,
+ uint16 tile_y,
+ uint16 z,
+ VNBLayerType type,
+ const VNBTile *tile)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VBitmapLayer *vblayer;
+ unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j;
+
+ if(!session) return;
+
+ /* try to find verse node in dynamic list nodes */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find verse bitmap layer in list of layers */
+ vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
+ if(!vblayer) return;
+
+ /* we have to have allocated memory for bitmap layer */
+ if(!vblayer->data) return;
+
+ width = ((VBitmapData*)vnode->data)->width;
+ height = ((VBitmapData*)vnode->data)->height;
+
+ /* width of verse image including all tiles */
+ t_height = ((VBitmapData*)vnode->data)->t_height;
+ /* height of verse image including all tiles */
+ t_width = ((VBitmapData*)vnode->data)->t_width;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf("\t cb_b_tile_set()\n");
+#endif
+
+ xs = tile_x*VN_B_TILE_SIZE;
+ ys = tile_y*VN_B_TILE_SIZE;
+
+ /* initial position in one dimension vblayer->data (y_start*width + x_start) */
+ i = ys*t_width + xs;
+ /* intial position in one dimension tile array */
+ j = 0;
+
+ if(type==VN_B_LAYER_UINT8) {
+ unsigned char *data = (unsigned char*)vblayer->data;
+ for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs)
+ for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++)
+ data[i] = (unsigned char)tile->vuint8[j];
+ }
+
+ /* post callback function */
+ ((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys);
+}
+
+/*
+ * set up all callbacks functions for image nodes
+ */
+void set_bitmap_callbacks(void)
+{
+ /* dimension (size) of bitmap was set up or changes (image will be croped) */
+ verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL);
+
+ /* new layer (chanell) of image was added or created */
+ verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL);
+
+ /* existing layer was destroyed */
+ verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL);
+
+ /* some tile (small part 8x8 pixels of image was changed) */
+ verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL);
+}
+
+#endif
+
diff --git a/source/blender/blenkernel/intern/verse_geometry_node.c b/source/blender/blenkernel/intern/verse_geometry_node.c
new file mode 100644
index 00000000000..a53ad2cb627
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_geometry_node.c
@@ -0,0 +1,2101 @@
+/**
+ * $Id: verse_geometry_node.c 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_verse.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+
+/* test functions for callback functions */
+static char test_polygon_set_corner_uint32(uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+
+/* callback functions */
+static void cb_g_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real);
+static void cb_g_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
+static void cb_g_vertex_set_xyz_real32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 vertex_id, real32 x, real32 y, real32 z);
+static void cb_g_polygon_set_corner_uint32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+static void cb_g_vertex_delete_real32(void *user_data, VNodeID node_id, uint32 vertex_id);
+static void cb_g_polygon_delete(void *user_data, VNodeID node_id, uint32 polygon_id);
+static void cb_g_crease_set_edge(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
+static void cb_g_crease_set_vertex(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
+
+/* other static functions */
+
+static void free_unneeded_verseverts_of_verseface(struct VNode *vnode, struct VerseFace *vface);
+static void free_verse_vertex(struct VLayer *vlayer, struct VerseVert *vvert);
+static void free_verse_face(struct VLayer *vlayer, struct VerseFace *vface);
+static void free_verse_layer_data(struct VNode *vnode, struct VLayer *vlayer);
+
+static void send_verse_face(struct VerseFace *vface);
+
+static VerseVert* find_verse_vert_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 vertex_id, real32 x, real32 y, real32 z);
+static VerseFace* find_verse_face_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+
+static unsigned short test_incoming_verseface(struct VGeomData *geom, struct VerseFace *vface);
+static void find_unsent_faces(struct VNode *vnode, struct VerseVert *vvert);
+static void find_vlayer_orphans(struct VNode *vnode, struct VerseVert *vvert);
+static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer, struct VerseFace *vface);
+static void increase_verse_verts_references(struct VerseFace *vface);
+static void recalculate_verseface_normals(struct VNode *vnode);
+
+/* verse edge functions */
+static VerseEdge* find_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
+static void insert_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge);
+static void remove_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge);
+static void remove_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
+static void add_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1);
+static void update_edgehash_of_deleted_verseface(struct VNode *vnode, struct VerseFace *vface);
+static void update_edgehash_of_changed_verseface(struct VNode *vnode, struct VerseFace *vface, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+static void update_edgehash_of_new_verseface(struct VNode *vnode, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+
+/*
+ * recalcute normals of all VerseFaces
+ */
+static void recalculate_verseface_normals(VNode *vnode)
+{
+ struct VLayer *vert_layer, *face_layer;
+ struct VerseFace *vface;
+ struct VerseVert *vvert;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ vert_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ face_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ vvert = vert_layer->dl.lb.first;
+ while(vvert) {
+ vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
+ vvert = vvert->next;
+ }
+
+ vface = face_layer->dl.lb.first;
+ while(vface) {
+ /* calculate face normals */
+ if(vface->vvert3) {
+ CalcNormFloat4(vface->vvert0->co, vface->vvert1->co,
+ vface->vvert2->co, vface->vvert3->co, vface->no);
+ VecAddf(vface->vvert3->no, vface->vvert3->no, vface->no);
+ }
+ else
+ CalcNormFloat(vface->vvert0->co, vface->vvert1->co,
+ vface->vvert2->co, vface->no);
+
+ /* calculate vertex normals ... it is averadge of all face normals using the vertex */
+ VecAddf(vface->vvert0->no, vface->vvert0->no, vface->no);
+ VecAddf(vface->vvert1->no, vface->vvert1->no, vface->no);
+ VecAddf(vface->vvert2->no, vface->vvert2->no, vface->no);
+
+ vface = vface->next;
+ }
+
+ /* we have to normalize all vertex normals */
+ vvert = vert_layer->dl.lb.first;
+ while(vvert) {
+ Normalize(vvert->no);
+ vvert = vvert->next;
+ }
+}
+
+/*
+ * add created item to the queue and send it if possible
+ */
+void add_item_to_send_queue(ListBase *lb, void *item, short type)
+{
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct VerseVert *vvert;
+ struct VerseFace *vface;
+
+ /* this prevent from adding duplicated faces */
+ if(type==VERSE_FACE) {
+ struct Link *link = (Link*)lb->first;
+ while(link) {
+ if(link==item) {
+ if(((VerseFace*)item)->flag & FACE_SENT) {
+/* printf("\tverse face %d marked as OBSOLETE\n", ((VerseFace*)item)->id);*/
+ ((VerseFace*)item)->flag |= FACE_OBSOLETE;
+ }
+ return;
+ }
+ link = link->next;
+ }
+ }
+
+ /* add item to sending queue (two way dynamic list) */
+ BLI_addtail(lb, item);
+
+ /* send item, when it is possible */
+ switch (type) {
+ case VERSE_NODE: /* only first node in queue can be sent */
+ if(lb->first==lb->last)
+ send_verse_node((VNode*)item);
+ break;
+ case VERSE_LINK: /* both object between have to exist */
+ if(((VLink*)item)->flag & LINK_SEND_READY)
+ send_verse_link((VLink*)item);
+ break;
+ case VERSE_LAYER:
+ if(((VLayer*)item)->vnode->flag & NODE_RECEIVED)
+ send_verse_layer((VLayer*)item);
+ break;
+ case VERSE_VERT:
+ if(((VerseVert*)item)->vlayer->flag & LAYER_RECEIVED)
+ send_verse_vertex((VerseVert*)item);
+ break;
+ case VERSE_FACE: /* all vertexes of face have to be received */
+ if(((VerseFace*)item)->flag & FACE_SEND_READY)
+ send_verse_face((VerseFace*)item);
+ break;
+ case VERSE_TAG:
+ send_verse_tag((VTag*)item);
+ break;
+ case VERSE_TAG_GROUP:
+ send_verse_taggroup((VTagGroup*)item);
+ break;
+ case VERSE_VERT_UINT32: /* parent item has to exist */
+ vnode = (((uint32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
+ vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id );
+ if(vvert != NULL)
+ send_verse_vert_uint32((uint32_item*)item, type);
+ break;
+ case VERSE_VERT_REAL32: /* parent item has to exist */
+ vnode = (((real32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
+ vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id );
+ if( vvert != NULL)
+ send_verse_vert_real32((real32_item*)item, type);
+ break;
+ case VERSE_VERT_VEC_REAL32: /* parent item has to exist */
+ vnode = (((vec_real32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 );
+ vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((vec_real32_item*)item)->id );
+ if(vvert != NULL)
+ send_verse_vert_vec_real32((vec_real32_item*)item, type);
+ break;
+ case VERSE_FACE_UINT8: /* parent item has to exist */
+ vnode = (((uint8_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint8_item*)item)->id );
+ if(vface != NULL)
+ send_verse_face_uint8((uint8_item*)item, type);
+ break;
+ case VERSE_FACE_UINT32: /* parent item has to exist */
+ vnode = (((uint32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id );
+ if(vface != NULL)
+ send_verse_face_uint32((uint32_item*)item, type);
+ break;
+ case VERSE_FACE_REAL32: /* parent item has to exist */
+ vnode = (((real32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id );
+ if(vface != NULL)
+ send_verse_face_real32((real32_item*)item, type);
+ break;
+ case VERSE_FACE_QUAT_UINT32: /* parent item has to exist */
+ vnode = (((quat_uint32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_uint32_item*)item)->id );
+ if(vface != NULL)
+ send_verse_face_corner_quat_uint32((quat_uint32_item*)item, type);
+ break;
+ case VERSE_FACE_QUAT_REAL32: /* parent item has to exist */
+ vnode = (((quat_real32_item*)item)->vlayer)->vnode;
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 );
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_real32_item*)item)->id );
+ if(vface != NULL)
+ send_verse_face_corner_quat_real32((quat_real32_item*)item, type);
+ break;
+ }
+}
+
+/*
+ * return VerseLayer with certain content (vertexes, polygons, in the
+ * future: weight, red color, etc.)
+ */
+VLayer* find_verse_layer_type(VGeomData *geom, short content)
+{
+ struct VLayer *vlayer = NULL;
+
+ switch(content) {
+ case VERTEX_LAYER:
+ /* VERTEX_LAYER equals 0 and vertex layer is
+ * always in 1st layer */
+ vlayer = geom->layers.da.items[VERTEX_LAYER];
+ break;
+ case POLYGON_LAYER:
+ /* POLYGON_LAYER equals 1 and vertex layer is
+ * always in 2nd layer */
+ vlayer = geom->layers.da.items[POLYGON_LAYER];
+ break;
+ }
+
+ return vlayer;
+}
+
+/*
+ * increase references of VerseVerts of new VerseFace
+ */
+static void increase_verse_verts_references(VerseFace *vface)
+{
+ if(vface->vvert0) vface->vvert0->counter++;
+ if(vface->vvert1) vface->vvert1->counter++;
+ if(vface->vvert2) vface->vvert2->counter++;
+ if(vface->vvert3) vface->vvert3->counter++;
+}
+
+/*
+ * move VerseFace from list of orphans to dlist of VerseFaces (if VerseFace was only changed
+ * then this VerseFace is only removed from list of orphans)
+ */
+static void move_face_orphan_to_dlist(VNode *vnode, VLayer *vlayer, VerseFace *vface)
+{
+ /* remove vface from list of orphans */
+ BLI_remlink(&(vlayer->orphans), vface);
+ /* increase references of all vertexes beying part of this face*/
+ increase_verse_verts_references(vface);
+
+ if(vface->flag & FACE_RECEIVED) {
+ /* set up vface flag */
+ vface->flag &= ~FACE_RECEIVED;
+ /* move vface to dynamic list of faces */
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
+ /* recalculate all vertex and faces normals */
+ recalculate_verseface_normals(vnode);
+ /* post create action (change local data) */
+ ((VGeomData*)vnode->data)->post_polygon_create(vface);
+ }
+ else if(vface->flag & FACE_CHANGED) {
+ /* set up vface flag */
+ vface->flag &= ~FACE_CHANGED;
+ /* move vface to dynamic list of faces */
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
+ /* recalculate all vertex and faces normals */
+ recalculate_verseface_normals(vnode);
+ /* post create action (change local data) */
+ ((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
+ }
+}
+
+/*
+ * find all VerseFaces waiting in queue, which needs id of new VerseVert
+ */
+static void find_unsent_faces(VNode *vnode, VerseVert *vvert)
+{
+ VLayer *vlayer;
+ VerseFace *vface, *next_vface;
+
+ vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ if(vlayer) {
+ vface = vlayer->queue.first;
+ while(vface) {
+ next_vface = vface->next;
+ if(vface->vvert0==vvert) {
+ vface->v0 = vvert->id;
+ vface->counter--;
+ }
+ else if(vface->vvert1==vvert) {
+ vface->v1 = vvert->id;
+ vface->counter--;
+ }
+ else if(vface->vvert2==vvert) {
+ vface->v2 = vvert->id;
+ vface->counter--;
+ }
+ else if(vface->vvert3==vvert){
+ vface->v3 = vvert->id;
+ vface->counter--;
+ }
+
+ if(vface->counter<1 && !(vface->flag & FACE_SENT))
+ send_verse_face(vface);
+
+ vface = next_vface;
+ }
+ }
+}
+
+/*
+ * find all VerseFace orphans, which needs incoming VerseVert
+ */
+static void find_vlayer_orphans(VNode *vnode, VerseVert *vvert)
+{
+ VLayer *vlayer;
+ VerseFace *vface, *next_vface;
+ unsigned int vertex_id = vvert->id;
+
+ vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ if(vlayer) {
+ vface = vlayer->orphans.first;
+ while(vface){
+ next_vface = vface->next;
+ if(vface->v0 == vertex_id) {
+ vface->vvert0 = vvert;
+ vface->counter--;
+ }
+ else if(vface->v1 == vertex_id) {
+ vface->vvert1 = vvert;
+ vface->counter--;
+ }
+ else if(vface->v2 == vertex_id) {
+ vface->vvert2 = vvert;
+ vface->counter--;
+ }
+ else if(vface->v3 == vertex_id) {
+ vface->vvert3 = vvert;
+ vface->counter--;
+ }
+ if(vface->counter<1) {
+ /* moving VerseFace orphan to dlist */
+ move_face_orphan_to_dlist(vnode, vlayer, vface);
+ }
+ vface = next_vface;
+ }
+ }
+}
+
+/*
+ * return number of VerseVerts missing to incoming VerseFace, set up pointers
+ * at VerseVerts
+ */
+static unsigned short test_incoming_verseface(VGeomData *geom, VerseFace *vface)
+{
+ struct VLayer *vert_layer;
+ struct VerseVert *vvert;
+ int counter=0;
+
+ vert_layer = find_verse_layer_type(geom, VERTEX_LAYER);
+
+ if(vface->v0 != -1){
+ vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v0);
+ if(vvert==NULL) counter++;
+ else vface->vvert0 = vvert;
+ }
+ if(vface->v1 != -1){
+ vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v1);
+ if(vvert==NULL) counter++;
+ else vface->vvert1 = vvert;
+ }
+ if(vface->v2 != -1){
+ vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v2);
+ if(vvert==NULL) counter++;
+ else vface->vvert2 = vvert;
+ }
+ if(vface->v3 != -1){
+ vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v3);
+ if(vvert==NULL) counter++;
+ else vface->vvert3 = vvert;
+ }
+
+ return counter;
+}
+
+/*
+ * try to find changed VerseFace in sending queue
+ */
+static VerseFace* find_changed_verse_face_in_queue(VLayer *vlayer, uint32 polygon_id)
+{
+ struct VerseFace *vface = vlayer->queue.first;
+
+ while(vface){
+ if(vface->id == polygon_id && vface->flag & FACE_CHANGED) {
+ return vface;
+ }
+ vface = vface->next;
+ }
+ return NULL;
+}
+
+/*
+ * try to find VerseFace in queue
+ */
+static VerseFace* find_verse_face_in_queue(
+ VLayer *vlayer,
+ VNodeID node_id,
+ uint32 polygon_id,
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ struct VerseFace *vface = vlayer->queue.first;
+
+ while(vface){
+ if((vface->v0==v0) && (vface->v1==v1) && (vface->v2==v2) && (vface->v3==v3)){
+ vface->id = polygon_id;
+ vface->vlayer = vlayer;
+ return vface;
+ }
+ vface = vface->next;
+ }
+ return NULL;
+}
+
+/*
+ * try to find VerseVert in queue
+ */
+static VerseVert* find_verse_vert_in_queue(
+ VLayer *vlayer,
+ VNodeID node_id,
+ uint32 vertex_id,
+ real32 x,
+ real32 y,
+ real32 z)
+{
+ struct VerseVert *vvert = vlayer->queue.first;
+
+ while(vvert){
+ if((vvert->vlayer->vnode->id == node_id) && (vvert->co[0] == x) && (vvert->co[1] == y) && (vvert->co[2] == z))
+ {
+ vvert->id = vertex_id;
+ vvert->vlayer = vlayer;
+
+ return vvert;
+ }
+ vvert = vvert->next;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * send quat of float values to verse server (4x32 bits)
+ */
+void send_verse_face_corner_quat_real32(quat_real32_item *item, short type)
+{
+ verse_send_g_polygon_set_corner_real32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value[0],
+ item->value[1],
+ item->value[2],
+ item->value[3]);
+}
+
+/*
+ * send quat of unsigned int values to verse server (4x32 bits)
+ */
+void send_verse_face_corner_quat_uint32(quat_uint32_item *item, short type)
+{
+ verse_send_g_polygon_set_corner_uint32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value[0],
+ item->value[1],
+ item->value[2],
+ item->value[3]);
+}
+
+/*
+ * send float value (32 bits) to verse server
+ */
+void send_verse_face_real32(real32_item *item, short type)
+{
+ verse_send_g_polygon_set_face_real32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value);
+}
+
+/*
+ * send unsigned integer (32 bits) to verse server
+ */
+void send_verse_face_uint32(uint32_item *item, short type)
+{
+ verse_send_g_polygon_set_face_uint32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value);
+}
+
+/*
+ * send unsigned char (8 bits) to verse server
+ */
+void send_verse_face_uint8(uint8_item *item, short type)
+{
+ verse_send_g_polygon_set_face_uint8(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value);
+}
+
+/*
+ * send vector of float values to verse server (3x32 bits)
+ */
+void send_verse_vert_vec_real32(vec_real32_item *item, short type)
+{
+ verse_send_g_vertex_set_xyz_real32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value[0],
+ item->value[1],
+ item->value[2]);
+}
+
+/*
+ * send float value (32 bits) to verse server
+ */
+void send_verse_vert_real32(real32_item *item, short type)
+{
+ verse_send_g_vertex_set_real32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value);
+}
+
+/*
+ * send unsigned integer (32 bits) to verse server
+ */
+void send_verse_vert_uint32(uint32_item *item, short type)
+{
+ verse_send_g_vertex_set_uint32(
+ item->vlayer->vnode->id,
+ item->vlayer->id,
+ item->id,
+ item->value);
+}
+
+/*
+ * send delete command to verse server
+ */
+void send_verse_vertex_delete(VerseVert *vvert)
+{
+ verse_session_set(vvert->vlayer->vnode->session->vsession);
+
+ vvert->flag |= VERT_OBSOLETE;
+
+ verse_send_g_vertex_delete_real32(vvert->vlayer->vnode->id, vvert->id);
+}
+
+/*
+ * send VerseLayer to verse server
+ */
+void send_verse_layer(VLayer *vlayer)
+{
+ verse_session_set(vlayer->vnode->session->vsession);
+
+ verse_send_g_layer_create(
+ vlayer->vnode->id,
+ vlayer->id,
+ vlayer->name,
+ vlayer->type,
+ vlayer->def_int,
+ vlayer->def_real);
+}
+
+/*
+ * send VerseVert to verse server
+ */
+void send_verse_vertex(VerseVert *vvert)
+{
+ /* new vertex position will not be sent, when vertex was deleted */
+ if(vvert->flag & VERT_OBSOLETE) return;
+
+ verse_session_set(vvert->vlayer->vnode->session->vsession);
+
+ verse_send_g_vertex_set_xyz_real32(
+ vvert->vlayer->vnode->id,
+ vvert->vlayer->id,
+ vvert->id,
+ vvert->co[0],
+ vvert->co[2],
+ -vvert->co[1]);
+}
+
+/*
+ * send delete command to verse server
+ */
+void send_verse_face_delete(VerseFace *vface)
+{
+ verse_session_set(vface->vlayer->vnode->session->vsession);
+
+ vface->flag |= FACE_DELETED;
+
+ verse_send_g_polygon_delete(vface->vlayer->vnode->id, vface->id);
+}
+
+/*
+ * send VerseFace to verse server
+ */
+static void send_verse_face(VerseFace *vface)
+{
+ verse_session_set(vface->vlayer->vnode->session->vsession);
+
+ vface->flag |= FACE_SENT;
+
+ if(vface->v3 != -1) {
+ verse_send_g_polygon_set_corner_uint32(
+ vface->vlayer->vnode->id,
+ vface->vlayer->id,
+ vface->id,
+ vface->v0,
+ vface->v3, /* verse use clock-wise winding */
+ vface->v2,
+ vface->v1); /* verse use clock-wise winding */
+ }
+ else {
+ verse_send_g_polygon_set_corner_uint32(
+ vface->vlayer->vnode->id,
+ vface->vlayer->id,
+ vface->id,
+ vface->v0,
+ vface->v2, /* verse use clock-wise winding */
+ vface->v1, /* verse use clock-wise winding */
+ vface->v3);
+ }
+}
+
+/*
+ * free VerseVert
+ */
+static void free_verse_vertex(VLayer *vlayer, VerseVert *vvert)
+{
+ /* free VerseVert */
+ BLI_freelinkN(&(vlayer->orphans), vvert);
+}
+
+/*
+ * free VerseFace (and blender face)
+ */
+static void free_verse_face(VLayer *vlayer, VerseFace *vface)
+{
+ /* free VerseFace */
+ BLI_dlist_free_item(&(vlayer->dl), (unsigned int)vface->id);
+}
+
+/*
+ * free VerseLayer data
+ */
+static void free_verse_layer_data(VNode *vnode, VLayer *vlayer)
+{
+ struct VerseFace *vface;
+ struct VerseVert *vvert;
+
+ /* set up EditVert->vvert and EditFace->vface pointers to NULL */
+ switch(vlayer->content) {
+ case VERTEX_LAYER:
+ vvert = (VerseVert*)vlayer->dl.lb.first;
+ while(vvert) {
+ ((VGeomData*)vnode->data)->post_vertex_free_constraint(vvert);
+ vvert = vvert->next;
+ }
+ break;
+ case POLYGON_LAYER:
+ vface = (VerseFace*)vlayer->dl.lb.first;
+ while(vface) {
+ ((VGeomData*)vnode->data)->post_polygon_free_constraint(vface);
+ vface = vface->next;
+ }
+ break;
+ default:
+ break;
+ }
+ /* free Verse Layer name */
+ MEM_freeN(vlayer->name);
+ /* destroy VerseLayer data (vertexes, polygons, etc.) */
+ BLI_dlist_destroy(&(vlayer->dl));
+ /* free unsent data */
+ BLI_freelistN(&(vlayer->queue));
+ /* free orphans */
+ BLI_freelistN(&(vlayer->orphans));
+}
+
+/*
+ * free all unneeded VerseVerts waiting for deleting
+ */
+static void free_unneeded_verseverts_of_verseface(VNode *vnode, VerseFace *vface)
+{
+ struct VLayer *vert_vlayer;
+
+ /* find layer containing vertexes */
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+
+ /* free all "deleted" VerseVert waiting for deleting this VerseFace */
+
+ if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
+ free_verse_vertex(vert_vlayer, vface->vvert0);
+ vface->vvert0 = NULL;
+ }
+ if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
+ free_verse_vertex(vert_vlayer, vface->vvert1);
+ vface->vvert1 = NULL;
+ }
+ if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
+ free_verse_vertex(vert_vlayer, vface->vvert2);
+ vface->vvert2 = NULL;
+ }
+ if((vface->vvert3) && (vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
+ free_verse_vertex(vert_vlayer, vface->vvert3);
+ vface->vvert3 = NULL;
+ }
+}
+
+/*
+ * This function create VerseVert and returns pointer on this vertex
+ */
+VerseVert* create_verse_vertex(
+ VLayer *vlayer,
+ uint32 vertex_id,
+ real32 x,
+ real32 y,
+ real32 z)
+{
+ struct VerseVert *vvert;
+
+ vvert = (VerseVert*)MEM_mallocN(sizeof(VerseVert), "VerseVert");
+
+ /* set up pointer on parent node */
+ vvert->vlayer = vlayer;
+ vvert->id = vertex_id;
+ /* position */
+ vvert->co[0] = x;
+ vvert->co[1] = y;
+ vvert->co[2] = z;
+ /* normal */
+ vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
+ /* blender internals */
+ vvert->flag = 0;
+ vvert->counter = 0;
+ vvert->vertex = NULL;
+
+ /* increase layer counter of vertexes */
+ vlayer->counter++;
+
+ return vvert;
+}
+
+/*
+ * this function creates fake VerseEdge and returns pointer at this edge
+ */
+VerseEdge *create_verse_edge(uint32 v0, uint32 v1)
+{
+ struct VerseEdge *vedge;
+
+ vedge = (VerseEdge*)MEM_mallocN(sizeof(VerseEdge), "VerseEdge");
+
+ vedge->v0 = v0;
+ vedge->v1 = v1;
+ vedge->counter = 0;
+
+ return vedge;
+}
+
+/*
+ * this function will create new VerseFace and will return pointer on such Face
+ */
+VerseFace* create_verse_face(
+ VLayer *vlayer,
+ uint32 polygon_id,
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ struct VerseFace *vface;
+
+ vface = (VerseFace*)MEM_mallocN(sizeof(VerseFace), "VerseFace");
+
+ /* verse data */
+ vface->vlayer = vlayer;
+ vface->id = polygon_id;
+
+ vface->vvert0 = NULL;
+ vface->vvert1 = NULL;
+ vface->vvert2 = NULL;
+ vface->vvert3 = NULL;
+
+ vface->v0 = v0;
+ vface->v1 = v1;
+ vface->v2 = v2;
+ vface->v3 = v3;
+
+ /* blender data */
+ vface->face = NULL;
+ vface->flag = 0;
+ vface->counter = 4;
+
+ /* increase layer counter of faces */
+ vlayer->counter++;
+
+ return vface;
+}
+
+/*
+ * create and return VerseLayer
+ */
+VLayer *create_verse_layer(
+ VNode *vnode,
+ VLayerID layer_id,
+ const char *name,
+ VNGLayerType type,
+ uint32 def_integer,
+ real64 def_real)
+{
+ struct VLayer *vlayer;
+
+ /* add layer to the DynamicList */
+ vlayer = (VLayer*)MEM_mallocN(sizeof(VLayer), "VerseLayer");
+
+ /* store all relevant info to the vlayer and set up vlayer */
+ vlayer->vnode = vnode;
+ vlayer->id = layer_id;
+ vlayer->name = (char*)MEM_mallocN(sizeof(char)*(sizeof(name)+1),"Verse Layer name");
+ strcpy(vlayer->name, name);
+ vlayer->type = type;
+ vlayer->def_int = def_integer;
+ vlayer->def_real = def_real;
+
+ if((type == VN_G_LAYER_VERTEX_XYZ) && (layer_id == 0))
+ vlayer->content = VERTEX_LAYER;
+ else if((type == VN_G_LAYER_POLYGON_CORNER_UINT32) && (layer_id == 1))
+ vlayer->content = POLYGON_LAYER;
+ else
+ vlayer->content = -1;
+
+ /* initialize DynamicList in the vlayer (vertexes, polygons, etc.)*/
+ BLI_dlist_init(&(vlayer->dl));
+ /* initialization of queue of layer */
+ vlayer->queue.first = vlayer->queue.last = NULL;
+ /* initialization of list of orphans */
+ vlayer->orphans.first = vlayer->orphans.last = NULL;
+ /* initialize number of sent items (vertexes, faces, etc) */
+ vlayer->counter = 0;
+ /* initialize flag */
+ vlayer->flag = 0;
+
+ /* set up methods */
+ vlayer->post_layer_create = post_layer_create;
+ vlayer->post_layer_destroy = post_layer_destroy;
+
+ return vlayer;
+}
+
+/*
+ * create geometry data
+ */
+VGeomData *create_geometry_data(void)
+{
+ struct VGeomData *geom;
+
+ geom = (VGeomData*)MEM_mallocN(sizeof(VGeomData), "VerseGeometryData");
+ BLI_dlist_init(&(geom->layers));
+ geom->vlink = NULL;
+ geom->queue.first = geom->queue.last = NULL;
+ geom->mesh = NULL;
+ geom->editmesh = NULL;
+
+ /* initialize list of fake verse edges and initialize verse edge hash */
+ geom->edges.first = geom->edges.last = NULL;
+ geom->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
+
+ /* set up methods */
+ geom->post_vertex_create = post_vertex_create;
+ geom->post_vertex_set_xyz = post_vertex_set_xyz;
+ geom->post_vertex_delete = post_vertex_delete;
+ geom->post_vertex_free_constraint = post_vertex_free_constraint;
+ geom->post_polygon_create = post_polygon_create;
+ geom->post_polygon_set_corner = post_polygon_set_corner;
+ geom->post_polygon_delete = post_polygon_delete;
+ geom->post_polygon_free_constraint = post_polygon_free_constraint;
+ geom->post_geometry_free_constraint = post_geometry_free_constraint;
+ geom->post_polygon_set_uint8 = post_polygon_set_uint8;
+
+ return geom;
+}
+
+/* Create item containing 4 floats */
+static quat_real32_item *create_quat_real32_item(
+ VLayer *vlayer,
+ uint32 item_id,
+ real32 v0,
+ real32 v1,
+ real32 v2,
+ real32 v3)
+{
+ struct quat_real32_item *item;
+
+ item = (quat_real32_item*)MEM_mallocN(sizeof(quat_real32_item), "quat_real32_item");
+
+ item->vlayer = vlayer;
+ item->id = item_id;
+ item->value[0] = v0;
+ item->value[1] = v1;
+ item->value[2] = v2;
+ item->value[3] = v3;
+
+ return item;
+}
+
+/* Create item containing 1 float */
+static real32_item *create_real32_item(VLayer *vlayer, uint32 item_id, real32 value)
+{
+ struct real32_item *item;
+
+ item = (real32_item*)MEM_mallocN(sizeof(real32_item), "real32_item");
+
+ item->vlayer = vlayer;
+ item->id = item_id;
+ item->value = value;
+
+ return item;
+}
+
+/* Create item containing 1 integer */
+static uint32_item *create_uint32_item(VLayer *vlayer, uint32 item_id, uint32 value)
+{
+ struct uint32_item *item;
+
+ item = (uint32_item*)MEM_mallocN(sizeof(uint32_item), "uint32_item");
+
+ item->vlayer = vlayer;
+ item->id = item_id;
+ item->value = value;
+
+ return item;
+}
+
+/* Create item containing 1 byte */
+static uint8_item *create_uint8_item(VLayer *vlayer, uint32 item_id, uint8 value)
+{
+ struct uint8_item *item;
+
+ item = (uint8_item*)MEM_mallocN(sizeof(uint8_item), "uint8_item");
+
+ item->vlayer = vlayer;
+ item->id = item_id;
+ item->value = value;
+
+ return item;
+}
+
+/*
+ * callback function: vertex crease was set
+ */
+static void cb_g_crease_set_vertex(
+ void *user_data,
+ VNodeID node_id,
+ const char *layer,
+ uint32 def_crease)
+{
+}
+
+/*
+ * we have to test corretness of incoming data from verse server
+ * no two vertexes can have the same index
+ */
+static char test_polygon_set_corner_uint32(
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ if((v0==v1) || (v0==v2) || (v0==v3) || (v1==v2) || (v1==v3) || (v2==v3))
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * try to find verse layer in sending queue of verse geometry node
+ */
+static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id)
+{
+ struct VLayer *vlayer;
+
+ /* try to find verse layyer in sending queue */
+ vlayer = ((VGeomData*)vnode->data)->queue.first;
+ while(vlayer) {
+ if(vlayer->id==layer_id) return vlayer;
+ vlayer = vlayer->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * this function will find edge in hash table, hash function isn't too optimal (it needs
+ * lot of memory for every verse node), but it works without any bug
+ */
+static VerseEdge* find_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
+{
+ struct HashVerseEdge *hve;
+
+ if(((VGeomData*)vnode->data)->hash==NULL)
+ ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
+
+ hve = ((VGeomData*)vnode->data)->hash + VEDHASH(v0, v1);;
+ while(hve) {
+ /* edge v0---v1 is the same edge as v1---v0 */
+ if(hve->vedge && ((hve->vedge->v0==v0 && hve->vedge->v1==v1) || (hve->vedge->v0==v1 && hve->vedge->v1==v0))) return hve->vedge;
+ hve = hve->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * insert hash of verse edge to hash table
+ */
+static void insert_verse_edgehash(VNode *vnode, VerseEdge *vedge)
+{
+ struct HashVerseEdge *first, *hve;
+
+ if(((VGeomData*)vnode->data)->hash==NULL)
+ ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab");
+
+ first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1);
+
+ if(first->vedge==NULL) {
+ first->vedge = vedge;
+ }
+ else {
+ hve = &(vedge->hash);
+ hve->vedge = vedge;
+ hve->next = first->next;
+ first->next = hve;
+ }
+}
+
+/*
+ * remove hash of verse edge from hash table
+ */
+static void remove_verse_edgehash(VNode *vnode, VerseEdge *vedge)
+{
+ struct HashVerseEdge *first, *hve, *prev;
+
+ hve = first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1);
+
+ while(hve) {
+ if(hve->vedge == vedge) {
+ if(hve==first) {
+ if(first->next) {
+ hve = first->next;
+ first->vedge = hve->vedge;
+ first->next = hve->next;
+ }
+ else {
+ hve->vedge = NULL;
+ }
+ }
+ else {
+ prev->next = hve->next;
+ }
+ return;
+ }
+ prev = hve;
+ hve = hve->next;
+ }
+}
+
+/*
+ * this function will try to remove existing fake verse edge, when this verse
+ * edge is still used by some faces, then counter will be only decremented
+ */
+static void remove_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
+{
+ struct VerseEdge *vedge;
+
+ vedge = find_verse_edge(vnode, v0, v1);
+ if(vedge) {
+ vedge->counter--;
+ if(vedge->counter==0) {
+ remove_verse_edgehash(vnode, vedge);
+ BLI_freelinkN(&(((VGeomData*)vnode->data)->edges), vedge);
+ }
+ }
+ else {
+ printf("error: remove_verse_edge %d, %d\n", v0, v1);
+ }
+}
+
+/*
+ * this function will try to add new fake verse edge, when no such edge exist,
+ * when such edge exist, then only counter of edge will be incremented
+ */
+static void add_verse_edge(VNode *vnode, uint32 v0, uint32 v1)
+{
+ struct VerseEdge *vedge;
+
+ vedge = find_verse_edge(vnode, v0, v1);
+ if(!vedge) {
+ if(v0!=v1) {
+ vedge = create_verse_edge(v0, v1);
+ BLI_addtail(&(((VGeomData*)vnode->data)->edges), vedge);
+ insert_verse_edgehash(vnode, vedge);
+ }
+ else {
+ printf("error:add_verse_edge: %d, %d\n", v0, v1);
+ return;
+ }
+ }
+ vedge->counter++;
+}
+
+/*
+ * verse face was deleted ... update edge hash
+ */
+static void update_edgehash_of_deleted_verseface(VNode *vnode, VerseFace *vface)
+{
+ uint32 v0, v1, v2, v3; /* verse vertex indexes of deleted verse face */
+
+ v0 = vface->vvert0->id;
+ v1 = vface->vvert1->id;
+ v2 = vface->vvert2->id;
+ v3 = vface->vvert3 ? vface->vvert3->id : -1;
+
+ remove_verse_edge(vnode, v0, v1);
+ remove_verse_edge(vnode, v1, v2);
+ if(v3!=-1) {
+ remove_verse_edge(vnode, v2, v3);
+ remove_verse_edge(vnode, v3, v0);
+ }
+ else {
+ remove_verse_edge(vnode, v2, v0);
+ }
+}
+
+/*
+ * existing verse face was changed ... update edge hash
+ */
+static void update_edgehash_of_changed_verseface(
+ VNode *vnode,
+ VerseFace *vface,
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ uint32 ov0, ov1, ov2, ov3; /* old indexes at verse vertexes*/
+
+ ov0 = vface->vvert0->id;
+ ov1 = vface->vvert1->id;
+ ov2 = vface->vvert2->id;
+ ov3 = vface->vvert3 ? vface->vvert3->id : -1;
+
+ /* 1st edge */
+ if(v0!=ov0 || v1!=ov1) {
+ remove_verse_edge(vnode, ov0, ov1);
+ add_verse_edge(vnode, v0, v1);
+ }
+
+ /* 2nd edge */
+ if(v1!=ov1 || v2!=ov2) {
+ remove_verse_edge(vnode, ov1, ov2);
+ add_verse_edge(vnode, v1, v2);
+ }
+
+ /* 3rd edge */
+ if(v2!=ov2 || v3!=ov3 || v0!=ov0) {
+ if(ov3!=-1) {
+ remove_verse_edge(vnode, ov2, ov3);
+ if(v3!=-1) {
+ add_verse_edge(vnode, v2, v3); /* new 3rd edge (quat->quat) */
+ }
+ else {
+ remove_verse_edge(vnode, ov3, ov0); /* old edge v3,v0 of quat have to be removed */
+ add_verse_edge(vnode, v2, v0); /* new 3rd edge (quat->triangle) */
+ }
+ }
+ else {
+ remove_verse_edge(vnode, ov2, ov0);
+ if(v3!=-1) {
+ add_verse_edge(vnode, v2, v3); /* new 3rd edge (triangle->quat) */
+ }
+ else {
+ add_verse_edge(vnode, v2, v0); /* new 3rd edge (triangle->triangle) */
+ }
+ }
+ }
+
+ /* 4th edge */
+ if(v3!=-1 && (v3!=ov3 || v0!=ov0)) {
+ remove_verse_edge(vnode, ov3, ov0);
+ add_verse_edge(vnode, v3, v0);
+ }
+}
+
+/*
+ * new verse face was created ... update list of edges and edge has
+ */
+static void update_edgehash_of_new_verseface(
+ VNode *vnode,
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ /* when edge already exists, then only its counter is incremented,
+ * look at commentary of add_verse_edge() function */
+ add_verse_edge(vnode, v0, v1);
+ add_verse_edge(vnode, v1, v2);
+ if(v3!=-1) {
+ add_verse_edge(vnode, v2, v3);
+ add_verse_edge(vnode, v3, v0);
+ }
+ else {
+ add_verse_edge(vnode, v2, v0);
+ }
+}
+
+/*
+ * callback function: edge crease was set
+ */
+static void cb_g_crease_set_edge(
+ void *user_data,
+ VNodeID node_id,
+ const char *layer,
+ uint32 def_crease)
+{
+}
+
+/*
+ * callback function: float value for polygon was set up
+ */
+static void cb_g_polygon_set_face_real32(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 polygon_id,
+ real32 value)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct real32_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+ if(item) {
+ item->value = value;
+ }
+ else {
+ item = create_real32_item(vlayer, polygon_id, value);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: int values for polygon was set up
+ */
+static void cb_g_polygon_set_face_uint32(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 polygon_id,
+ uint32 value)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct uint32_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+ if(item) {
+ item->value = value;
+ }
+ else {
+ item = create_uint32_item(vlayer, polygon_id, value);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: uint8 value for polygon was set up
+ */
+static void cb_g_polygon_set_face_uint8(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 polygon_id,
+ uint8 value)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct uint8_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+ if(item) {
+ item->value = value;
+ }
+ else {
+ item = create_uint8_item(vlayer, polygon_id, value);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: float value for polygon corner was set up
+ */
+static void cb_g_polygon_set_corner_real32(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 polygon_id,
+ real32 v0,
+ real32 v1,
+ real32 v2,
+ real32 v3)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct quat_real32_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+ if(item) {
+ item->value[0] = v0;
+ item->value[1] = v1;
+ item->value[2] = v2;
+ item->value[3] = v3;
+ }
+ else {
+ item = create_quat_real32_item(vlayer, polygon_id, v0, v1, v2, v3);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: polygon is deleted
+ */
+static void cb_g_polygon_delete(
+ void *user_data,
+ VNodeID node_id,
+ uint32 polygon_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ VNode *vnode;
+ VLayer *vlayer;
+ VerseFace *vface;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+
+ /* find layer containing faces */
+ vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ /* find wanted VerseFace */
+ vface = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+ if(!vface) return;
+
+ /* update edge hash */
+ update_edgehash_of_deleted_verseface(vnode, vface);
+
+ ((VGeomData*)vnode->data)->post_polygon_delete(vface);
+
+ /* decrease references at coresponding VerseVertexes */
+ vface->vvert0->counter--;
+ vface->vvert1->counter--;
+ vface->vvert2->counter--;
+ if(vface->vvert3) vface->vvert3->counter--;
+
+ /* delete unneeded VerseVertexes */
+ free_unneeded_verseverts_of_verseface(vnode, vface);
+
+ free_verse_face(vlayer, vface);
+}
+
+/*
+ * callback function: new polygon (face) created or existing polygon was changed
+ */
+static void cb_g_polygon_set_corner_uint32(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 polygon_id,
+ uint32 v0,
+ uint32 v1,
+ uint32 v2,
+ uint32 v3)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct VerseFace *vface=NULL;
+
+ if(!session) return;
+
+ /* try to find VerseNode */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find VerseLayer */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+ if(!vlayer) return;
+
+ /* we have to test coretness of incoming data */
+ if(!test_polygon_set_corner_uint32(v0, v1, v2, v3)) return;
+
+ /* Blender uses different order of vertexes */
+ if(v3!=-1) { /* quat swap */
+ unsigned int v; v = v1; v1 = v3; v3 = v;
+ }
+ else { /* triangle swap */
+ unsigned int v; v = v1; v1 = v2; v2 = v;
+ }
+
+ /* try to find VerseFace */
+ vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)polygon_id);
+
+ /* try to find modified VerseFace */
+ if(!vface) {
+ vface = find_changed_verse_face_in_queue(vlayer, polygon_id);
+ if(vface) {
+ BLI_remlink(&(vlayer->queue), (void*)vface);
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
+ }
+ }
+
+ if(!vface) {
+ /* try to find VerseFace in list of VerseVaces created by me and set up polygon and
+ * layer ids */
+ vface = find_verse_face_in_queue(vlayer, node_id, polygon_id, v0, v1, v2, v3);
+
+ /* update edge hash */
+ update_edgehash_of_new_verseface(vnode, v0, v1, v2, v3);
+
+ if(vface){
+ /* I creeated this face ... remove VerseFace from queue */
+ BLI_remlink(&(vlayer->queue), (void*)vface);
+ }
+ else {
+ /* some other client created this face*/
+ vface = create_verse_face(vlayer, polygon_id, v0, v1, v2, v3);
+ }
+
+ vface->flag &= ~FACE_SENT;
+
+ /* return number of missing verse vertexes */
+ vface->counter = test_incoming_verseface((VGeomData*)vnode->data, vface);
+
+ if(vface->counter < 1) {
+ /* when VerseFace received all needed VerseFaces, then it is moved
+ * to list of VerseFaces */
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
+ increase_verse_verts_references(vface);
+ recalculate_verseface_normals(vnode);
+ ((VGeomData*)vnode->data)->post_polygon_create(vface);
+ }
+ else {
+ /* when all needed VerseVertexes weren't received, then VerseFace is moved to
+ * the list of orphans waiting on needed vertexes */
+ vface->flag |= FACE_RECEIVED;
+ BLI_addtail(&(vlayer->orphans), (void*)vface);
+ }
+ }
+ else {
+ VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ /* VerseVertexes of existing VerseFace were changed (VerseFace will use some different
+ * VerseVertexes or it will use them in different order) */
+
+ /* update fake verse edges */
+ update_edgehash_of_changed_verseface(vnode, vface, v0, v1, v2, v3);
+
+ /* initialize count of unreceived vertexes needed for this face */
+ vface->counter = 4;
+
+ /* 1st corner */
+ if(vface->vvert0->id != v0) {
+ /* decrease references of obsolete vertexes*/
+ vface->vvert0->counter--;
+ /* delete this vertex, when it isn't used by any face and it was marked as deleted */
+ if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
+ free_verse_vertex(vert_vlayer, vface->vvert0);
+ }
+ /* try to set up new pointer at verse vertex */
+ vface->v0 = v0;
+ vface->vvert0 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v0);
+ if(vface->vvert0) {
+ /* increase references at new vertex */
+ vface->vvert0->counter++;
+ /* decrease count of needed vertex to receive */
+ vface->counter--;
+ }
+
+ }
+ else
+ /* this corner wasn't changed */
+ vface->counter--;
+
+ /* 2nd corner */
+ if(vface->vvert1->id != v1) {
+ vface->vvert1->counter--;
+ if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
+ free_verse_vertex(vert_vlayer, vface->vvert1);
+ }
+ vface->v1 = v1;
+ vface->vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v1);
+ if(vface->vvert1) {
+ vface->vvert1->counter++;
+ vface->counter--;
+ }
+ }
+ else
+ vface->counter--;
+
+ /* 3rd corner */
+ if(vface->vvert2->id != v2) {
+ vface->vvert2->counter--;
+ if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
+ free_verse_vertex(vert_vlayer, vface->vvert2);
+ }
+ vface->v2 = v2;
+ vface->vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v2);
+ if(vface->vvert2) {
+ vface->vvert2->counter++;
+ vface->counter--;
+ }
+ }
+ else
+ vface->counter--;
+
+ /* 4th corner */
+ if(vface->vvert3) {
+ if(vface->vvert3->id != v3) {
+ vface->vvert3->counter--;
+ if((vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
+ free_verse_vertex(vert_vlayer, vface->vvert3);
+ }
+ vface->v3 = v3;
+ if(v3 != -1) {
+ vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
+ if(vface->vvert3) {
+ vface->vvert3->counter++;
+ vface->counter--;
+ }
+ }
+ else {
+ /* this is some special case, this face hase now only 3 corners
+ * quat -> triangle */
+ vface->vvert3 = NULL;
+ vface->counter--;
+ }
+ }
+ }
+ else if(v3 != -1)
+ /* this is some special case, 4th corner of this polygon was created
+ * triangle -> quat */
+ vface->v3 = v3;
+ vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
+ if(vface->vvert3) {
+ vface->vvert3->counter++;
+ vface->counter--;
+ }
+ else {
+ vface->v3 = -1;
+ vface->counter--;
+ }
+
+ vface->flag &= ~FACE_SENT;
+ vface->flag |= FACE_CHANGED;
+
+ if(vface->counter<1) {
+ vface->flag &= ~FACE_CHANGED;
+ recalculate_verseface_normals(vnode);
+ ((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
+ }
+ else {
+ /* when all needed VerseVertexes weren't received, then VerseFace is added to
+ * the list of orphans waiting on needed vertexes */
+ BLI_dlist_rem_item(&(vlayer->dl), vface->id);
+ BLI_addtail(&(vlayer->orphans), (void*)vface);
+ }
+ }
+}
+
+/*
+ * callback function: float value was set up for VerseVert with vertex_id
+ */
+static void cb_g_vertex_set_real32(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 vertex_id,
+ real32 value)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct real32_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), vertex_id);
+
+ if(item) {
+ item->value = value;
+ }
+ else {
+ item = create_real32_item(vlayer, vertex_id, value);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: int value was set up for VerseVert with vertex_id
+ */
+static void cb_g_vertex_set_uint32(
+ void *user_def,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 vertex_id,
+ uint32 value)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+ struct uint32_item *item;
+
+ if(!session) return;
+
+ /* find needed node (we can be sure, that it is geometry node) */
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ /* find layer containing uint_8 data */
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+ /* try to find item*/
+ item = BLI_dlist_find_link(&(vlayer->dl), vertex_id);
+
+ if(item) {
+ item->value = value;
+ }
+ else {
+ item = create_uint32_item(vlayer, vertex_id, value);
+ BLI_dlist_add_item_index(&(vlayer->dl), item, item->id);
+ }
+}
+
+/*
+ * callback function: polygon was deleted
+ */
+static void cb_g_vertex_delete_real32(
+ void *user_data,
+ VNodeID node_id,
+ uint32 vertex_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ VNode *vnode=NULL;
+ VLayer *vert_vlayer=NULL;
+ VerseVert *vvert=NULL;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+
+ vvert = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vertex_id);
+
+ if(!vvert) return;
+
+ if(vvert->counter < 1) {
+ ((VGeomData*)vnode->data)->post_vertex_delete(vvert);
+ BLI_dlist_free_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
+ }
+ else {
+ /* some VerseFace(s) still need VerseVert, remove verse vert from
+ * list verse vertexes and put it to list of orphans */
+ vvert->flag |= VERT_DELETED;
+ BLI_dlist_rem_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
+ BLI_addtail(&(vert_vlayer->orphans), vvert);
+ }
+}
+
+/*
+ * callback function: position of one vertex was changed or new vertex was created
+ */
+static void cb_g_vertex_set_xyz_real32(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id,
+ uint32 vertex_id,
+ real32 x,
+ real32 y,
+ real32 z)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode = NULL;
+ struct VLayer *vlayer = NULL;
+ struct VerseVert *vvert = NULL;
+ real32 tmp;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode)return;
+
+ vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+ if(!vlayer) return;
+
+ /* switch axis orientation */
+ tmp = y;
+ y = -z;
+ z = tmp;
+
+ if(vlayer->id == 0) {
+ /* try to pick up verse vert from DynamicList */
+ vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)vertex_id);
+
+ if(vvert) {
+ if(vvert->flag & VERT_OBSOLETE) return;
+
+ if (vvert->flag & VERT_LOCKED) {
+ /* this application changed position of this vertex */
+ if((vvert->co[0]==x) && (vvert->co[1]==y) && (vvert->co[2]==z)) {
+ /* unlock vertex position */
+ vvert->flag &= ~VERT_LOCKED;
+ /* call post_vertex_set_xyz only, when position of vertex is
+ * obsolete ... the new vertex position will be sent to
+ * verse server */
+ if (vvert->flag & VERT_POS_OBSOLETE) {
+ ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
+ }
+ }
+ }
+ else {
+ /* somebody else changed position of this vertex*/
+ if((vvert->co[0]!=x) || (vvert->co[1]!=y) || (vvert->co[2]!=z)) {
+ vvert->co[0] = x;
+ vvert->co[1] = y;
+ vvert->co[2] = z;
+ recalculate_verseface_normals(vnode);
+ ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
+ }
+ }
+ }
+ else {
+ /* create new verse vert */
+
+ /* test if we are authors of this vertex :-) */
+ vvert = find_verse_vert_in_queue(vlayer, node_id, vertex_id, x, y, z);
+
+ if(vvert) {
+ /* remove vert from queue */
+ BLI_remlink(&(vlayer->queue), (void*)vvert);
+ /* add vvert to the dynamic list */
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
+ /* set VerseVert flags */
+ vvert->flag |= VERT_RECEIVED;
+ if(!(vvert->flag & VERT_POS_OBSOLETE))
+ vvert->flag &= ~VERT_LOCKED;
+ /* find VerseFaces orphans */
+ find_vlayer_orphans(vnode, vvert);
+ /* find unsent VerseFaces */
+ find_unsent_faces(vnode, vvert);
+ }
+ else {
+ /* create new VerseVert */
+ vvert = create_verse_vertex(vlayer, vertex_id, x, y, z);
+ /* add VerseVert to list of VerseVerts */
+ BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
+ /* set VerseVert flags */
+ vvert->flag |= VERT_RECEIVED;
+ /* find VerseFaces orphans */
+ find_vlayer_orphans(vnode, vvert);
+ }
+
+ ((VGeomData*)vnode->data)->post_vertex_create(vvert);
+ }
+ }
+}
+
+/*
+ * callback function for destroyng of verse layer
+ */
+static void cb_g_layer_destroy(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLayer *vlayer;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), node_id);
+ if(!vnode) return;
+
+ vlayer = (VLayer*) BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), layer_id);
+
+ if(vlayer){
+ /* free VerseLayer data */
+ free_verse_layer_data(vnode, vlayer);
+ /* remove VerseLayer from list of verse layers */
+ BLI_dlist_rem_item(&(((VGeomData*)vnode->data)->layers), layer_id);
+ /* do client dependent actions */
+ vlayer->post_layer_destroy(vlayer);
+ /* free vlayer itself */
+ MEM_freeN(vlayer);
+ }
+
+}
+
+/*
+ * callback function: new layer was created
+ */
+static void cb_g_layer_create(
+ void *user_data,
+ VNodeID node_id,
+ VLayerID layer_id,
+ const char *name,
+ VNGLayerType type,
+ uint32 def_integer,
+ real64 def_real)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode=NULL;
+ struct VLayer *vlayer=NULL;
+
+ if(!session) return;
+
+ /* find node of this layer*/
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ if(!vnode) return;
+
+ /* when we created this layer, then subscribe to this layer */
+ if(vnode->owner_id == VN_OWNER_MINE || session->flag & VERSE_AUTOSUBSCRIBE)
+ verse_send_g_layer_subscribe(node_id, layer_id, 0);
+
+ /* try to find */
+ if(vnode->owner_id == VN_OWNER_MINE)
+ vlayer = find_vlayer_in_sending_queue(vnode, layer_id);
+
+ if(vlayer) {
+ /* remove vlayer form sending queue add verse layer to list of verse layers */
+ BLI_remlink(&((VGeomData*)vnode->data)->queue, vlayer);
+ BLI_dlist_add_item_index(&((VGeomData*)vnode->data)->layers, (void*)vlayer, (unsigned int)vlayer->id);
+ /* send all not sent vertexes to verse server
+ * other items waiting in sending queue will be automaticaly sent to verse server,
+ * when verse vertexes will be received from verse server */
+ if((vlayer->type == VN_G_LAYER_VERTEX_XYZ) && (layer_id==0)) {
+ struct VerseVert *vvert = (VerseVert*)vlayer->queue.first;
+ while(vvert) {
+ send_verse_vertex(vvert);
+ vvert = vvert->next;
+ }
+ }
+ }
+ else {
+ /* create new VerseLayer */
+ vlayer = create_verse_layer(vnode, layer_id, name, type, def_integer, def_real);
+ /* add layer to the list of VerseLayers */
+ BLI_dlist_add_item_index(&(((VGeomData*)vnode->data)->layers), (void*)vlayer, (unsigned int)layer_id);
+ }
+
+ vlayer->flag |= LAYER_RECEIVED;
+
+ /* post callback function */
+ vlayer->post_layer_create(vlayer);
+}
+
+/*
+ * this function will send destroy commands for all VerseVertexes and
+ * VerseFaces to verse server, but it will not send destroy commands
+ * for VerseLayers or geometry node, it can be used in other functions
+ * (undo, destroy geom node, some edit mesh commands, ... ), parameter of
+ * this function has to be geometry verse node
+ */
+void destroy_geometry(VNode *vnode)
+{
+ struct VLayer *vert_vlayer, *face_vlayer;
+ struct VerseFace *vface;
+ struct VerseVert *vvert;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+ vface = face_vlayer->dl.lb.first;
+
+ while(vface) {
+ send_verse_face_delete(vface);
+ vface = vface->next;
+ }
+
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ vvert = vert_vlayer->dl.lb.first;
+
+ while(vvert) {
+ send_verse_vertex_delete(vvert);
+ vvert = vvert->next;
+ }
+
+ /* own destruction of local verse date will be executed, when client will
+ * receive apropriate callback commands from verse server */
+}
+
+/*
+ * free VGeomData
+ */
+void free_geom_data(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VLayer *vlayer;
+
+ if(vnode->data){
+ vlayer = (VLayer*)((VGeomData*)vnode->data)->layers.lb.first;
+ while(vlayer){
+ /* unsubscribe from layer */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_g_layer_unsubscribe(vnode->id, vlayer->id);
+ /* free VerseLayer data */
+ free_verse_layer_data(vnode, vlayer);
+ /* next layer */
+ vlayer = vlayer->next;
+ }
+ /* free constraint between vnode and mesh */
+ ((VGeomData*)vnode->data)->post_geometry_free_constraint(vnode);
+ /* free all VerseLayers */
+ BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
+ /* free fake verse edges */
+ BLI_freelistN(&((VGeomData*)vnode->data)->edges);
+ /* free edge hash */
+ MEM_freeN(((VGeomData*)vnode->data)->hash);
+ }
+}
+
+void set_geometry_callbacks(void)
+{
+ /* new layer created */
+ verse_callback_set(verse_send_g_layer_create, cb_g_layer_create, NULL);
+ /* layer was destroyed */
+ verse_callback_set(verse_send_g_layer_destroy, cb_g_layer_destroy, NULL);
+
+ /* position of vertex was changed */
+ verse_callback_set(verse_send_g_vertex_set_xyz_real32, cb_g_vertex_set_xyz_real32, NULL);
+ /* vertex was deleted */
+ verse_callback_set(verse_send_g_vertex_delete_real32, cb_g_vertex_delete_real32, NULL);
+
+ /* callback functions for values being associated with vertexes */
+ verse_callback_set(verse_send_g_vertex_set_uint32, cb_g_vertex_set_uint32, NULL);
+ verse_callback_set(verse_send_g_vertex_set_real32, cb_g_vertex_set_real32, NULL);
+
+ /* new polygon was created / vertex(es) of polygon was set */
+ verse_callback_set(verse_send_g_polygon_set_corner_uint32, cb_g_polygon_set_corner_uint32, NULL);
+ /* polygon was deleted */
+ verse_callback_set(verse_send_g_polygon_delete, cb_g_polygon_delete, NULL);
+
+ /* callback functions for values being associated with polygon corners */
+ verse_callback_set(verse_send_g_polygon_set_corner_real32, cb_g_polygon_set_corner_real32, NULL);
+ /* callback functions for values being associated with faces */
+ verse_callback_set(verse_send_g_polygon_set_face_uint8, cb_g_polygon_set_face_uint8, NULL);
+ verse_callback_set(verse_send_g_polygon_set_face_uint32, cb_g_polygon_set_face_uint32, NULL);
+ verse_callback_set(verse_send_g_polygon_set_face_real32, cb_g_polygon_set_face_real32, NULL);
+
+ /* crease of vertex was set */
+ verse_callback_set(verse_send_g_crease_set_vertex, cb_g_crease_set_vertex, NULL);
+ /* crease of edge was set */
+ verse_callback_set(verse_send_g_crease_set_edge, cb_g_crease_set_edge, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_method.c b/source/blender/blenkernel/intern/verse_method.c
new file mode 100644
index 00000000000..89b5282acfd
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_method.c
@@ -0,0 +1,523 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Nathan Letwory.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+#include "DNA_text_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_bad_level_calls.h"
+#include "BKE_library.h"
+#include "BKE_text.h"
+#include "BKE_verse.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+#include "verse.h"
+
+/* helper struct for creating method descriptions */
+typedef struct VMethodInfo {
+ const char *name;
+ uint8 param_count;
+ const VNOParamType param_type[4];
+ const char *param_name[4];
+ uint16 id;
+} VMethodInfo;
+
+#ifdef VERSECHAT
+/* array with methods for verse chat */
+static VMethodInfo vmethod_info[] = {
+ { "join", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}},
+ { "leave", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}},
+ { "hear", 3, { VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING }, { "channel", "from", "msg"}}
+};
+#endif
+
+/* lookup a method group based on its name */
+struct VMethodGroup *lookup_vmethodgroup_name(ListBase *lb, const char *name) {
+ struct VMethodGroup *vmg;
+
+ for(vmg= lb->first; vmg; vmg= vmg->next)
+ if(strcmp(vmg->name,name)==0) break;
+
+ return vmg;
+}
+
+/* lookup a method group based on its group_id */
+struct VMethodGroup *lookup_vmethodgroup(ListBase *lb, uint16 group_id) {
+ struct VMethodGroup *vmg;
+
+ for(vmg= lb->first; vmg; vmg= vmg->next)
+ if(vmg->group_id==group_id) break;
+
+ return vmg;
+}
+
+/* lookup a method based on its name */
+struct VMethod *lookup_vmethod_name(ListBase *lb, const char *name) {
+ struct VMethod *vm;
+ for(vm= lb->first; vm; vm= vm->next)
+ if(strcmp(vm->name,name)==0) break;
+
+ return vm;
+}
+
+/* lookup a method based on its method_id */
+struct VMethod *lookup_vmethod(ListBase *lb, uint8 method_id) {
+ struct VMethod *vm;
+ for(vm= lb->first; vm; vm= vm->next)
+ if(vm->id==method_id) break;
+
+ return vm;
+}
+
+#ifdef VERSECHAT
+/*
+ * send say command
+ */
+void send_say(const char *chan, const char *utter)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ VNOPackedParams *utterpack;
+ VNOParam args[2];
+
+ vnode= (VNode *)(session->nodes.lb.first);
+
+ for( ; vnode; vnode= vnode->next) {
+ if(strcmp(vnode->name, "tawksrv")==0) {
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
+ if(!vmg) break;
+ vm= lookup_vmethod_name(&(vmg->methods), "say");
+ if(!vm) break;
+ args[0].vstring= (char *)chan;
+ args[1].vstring= (char *)utter;
+ if((utterpack= verse_method_call_pack(vm->param_count, vm->param_type, args))!=NULL) {
+ verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, utterpack);
+ }
+ break;
+ }
+
+ }
+}
+
+/*
+ * send logout command
+ */
+void send_logout(VNode *vnode)
+{
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ VNOPackedParams *pack;
+
+ vnode->chat_flag = CHAT_LOGGED;
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
+ if(!vmg) return;
+ vm= lookup_vmethod_name(&(vmg->methods), "logout");
+ if(!vm) return;
+
+ if((pack= verse_method_call_pack(vm->param_count, vm->param_type, NULL))!=NULL) {
+ verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, pack);
+ }
+ vnode->chat_flag = CHAT_NOTLOGGED;
+}
+
+/*
+ * send join command
+ */
+void send_join(VNode *vnode, const char *chan)
+{
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ VNOPackedParams *join;
+ VNOParam channel[1];
+
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
+ if(!vmg) return;
+ vm= lookup_vmethod_name(&(vmg->methods), "join");
+ if(!vm) return;
+
+ channel[0].vstring= (char *)chan;
+ if((join= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) {
+ verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, join);
+ }
+}
+
+/*
+ * send leave command
+ */
+void send_leave(VNode *vnode, const char *chan)
+{
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ VNOPackedParams *leave;
+ VNOParam channel[1];
+
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
+ if(!vmg) return;
+ vm= lookup_vmethod_name(&(vmg->methods), "leave");
+ if(!vm) return;
+
+ channel[0].vstring= (char *)chan;
+ if((leave= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) {
+ verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, leave);
+ }
+}
+
+/*
+ * send login command
+ */
+void send_login(VNode *vnode)
+{
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ VNOPackedParams *login;
+ VNOParam param[1];
+
+ vnode->chat_flag = CHAT_LOGGED;
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
+ if(!vmg) return;
+ vm= lookup_vmethod_name(&(vmg->methods), "login");
+ if(!vm) return;
+
+ param[0].vstring= U.verseuser;
+
+ if((login= verse_method_call_pack(vm->param_count, vm->param_type, param))!=NULL) {
+ verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, login);
+ }
+ vnode->chat_flag = CHAT_LOGGED;
+
+ vnode= lookup_vnode(vnode->session, vnode->session->avatar);
+ vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk-client");
+ if(!vmg)
+ verse_send_o_method_group_create(vnode->session->avatar, ~0, "tawk-client");
+}
+#endif
+
+/*
+ * Free a VMethod
+ */
+void free_verse_method(VMethod *vm) {
+ if(!vm) return;
+
+ MEM_freeN(vm->param_type);
+}
+
+/*
+ * Free methods for VMethodGroup
+ */
+void free_verse_methodgroup(VMethodGroup *vmg)
+{
+ struct VMethod *vm, *tmpvm;
+
+ if(!vmg) return;
+
+ vm= vmg->methods.first;
+ while(vm) {
+ tmpvm=vm->next;
+ free_verse_method(vm);
+ vm= tmpvm;
+ }
+ BLI_freelistN(&(vmg->methods));
+}
+
+/* callback for method group creation */
+static void cb_o_method_group_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ vmg = lookup_vmethodgroup(&(vnode->methodgroups), group_id);
+
+ /* create method group holder in node node_id */
+ if(!vmg) {
+ vmg= MEM_mallocN(sizeof(VMethodGroup), "VMethodGroup");
+ vmg->group_id = group_id;
+ vmg->methods.first = vmg->methods.last = NULL;
+ BLI_addtail(&(vnode->methodgroups), vmg);
+ printf("new method group with name %s (group_id %d) for node %u created\n", name, group_id, node_id);
+ }
+
+ /* this ensures name of an existing group gets updated, in case it is changed */
+ BLI_strncpy(vmg->name, (char *)name, 16);
+
+ /* subscribe to method group */
+ verse_send_o_method_group_subscribe(node_id, group_id);
+
+#ifdef VERSECHAT
+ /* if this is our own method group, register our methods */
+ if(node_id==session->avatar) {
+ verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[0].name,
+ vmethod_info[0].param_count,
+ (VNOParamType *)vmethod_info[0].param_type,
+ (const char **)vmethod_info[0].param_name);
+ b_verse_update();
+ verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[1].name,
+ vmethod_info[1].param_count,
+ (VNOParamType *)vmethod_info[1].param_type,
+ (const char **)vmethod_info[1].param_name);
+ b_verse_update();
+ verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[2].name,
+ vmethod_info[2].param_count,
+ (VNOParamType *)vmethod_info[2].param_type,
+ (const char **)vmethod_info[2].param_name);
+ b_verse_update();
+ }
+#endif
+}
+
+/* callback for method group destruction */
+static void cb_o_method_group_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+
+ printf("method group %d destroyed\n", group_id);
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next)
+ if(vmg->group_id==group_id) break;
+
+ if(!vmg) return; /* method group doesn't exist? */
+
+ vmg->group_id = 0;
+ vmg->name[0] = '\0';
+ vm= vmg->methods.first;
+ while(vm) {
+ /* free vm */
+
+ }
+
+ /* TODO: unsubscribe from method group */
+ BLI_remlink(&(vnode->methodgroups),vmg);
+ MEM_freeN(vmg);
+}
+
+/* callback for method creation */
+static void cb_o_method_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 method_id,
+ const char *name,
+ uint8 param_count,
+ const VNOParamType *param_type,
+ const char *param_name[])
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ unsigned int size;
+ unsigned int i;
+ char *put;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ vmg= lookup_vmethodgroup((&vnode->methodgroups), group_id);
+
+ if(!vmg) return;
+
+ vm= lookup_vmethod((&vmg->methods), method_id);
+
+ if(!vm) {
+ vm= MEM_mallocN(sizeof(VMethod), "VMethod");
+ vm->id= method_id;
+ vm->param_count= param_count;
+ size= param_count* (sizeof(*vm->param_type) + sizeof(*vm->param_name));
+ for(i= 0; i <param_count; i++) {
+ size+=strlen(param_name[i])+1;
+ }
+ vm->param_type= MEM_mallocN(size, "param_type and param_name");
+ memcpy(vm->param_type, param_type, sizeof(VNOParamType)*param_count);
+ vm->param_name= (char **)(vm->param_type + param_count);
+ put= (char *)(vm->param_name + param_count);
+ for(i= 0; i < param_count; i++) {
+ vm->param_name[i]= put;
+ strcpy(put, param_name[i]);
+ put += strlen(param_name[i]) + 1;
+ }
+
+ BLI_addtail(&(vmg->methods), vm);
+#ifdef VERSECHAT
+ if(strcmp(vmethod_info[0].name, name)==0) {
+ vmethod_info[0].id = method_id;
+ }
+#endif
+ printf("method %s in group %d of node %u created\n", name, group_id, node_id);
+ }
+
+ BLI_strncpy(vm->name, (char *)name, 500);
+}
+
+/* callback for method destruction */
+static void cb_o_method_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 method_id,
+ const char *name,
+ uint8 param_count,
+ const VNOParamType *param_type,
+ const char *param_name[])
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next)
+ if(vmg->group_id==group_id) break;
+
+ if(!vmg) return; /* method group doesn't exist? */
+
+ for(vm= vmg->methods.first; vm; vm= vm->next)
+ if(vm->id==method_id) break;
+
+ if(!vm) return;
+
+ BLI_remlink(&(vmg->methods), vm);
+ MEM_freeN(vm->param_type);
+ MEM_freeN(vm);
+}
+
+/* callback for method calls */
+static void cb_o_method_call(void *user_data, VNodeID node_id, uint8 group_id, uint8 method_id, VNodeID sender, VNOPackedParams *params)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VMethodGroup *vmg;
+ struct VMethod *vm;
+ Text *text;
+ int method_idx= -1;
+
+ VNOParam arg[3];
+
+ if(!session) return;
+
+ if(session->avatar!=node_id) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ vmg= lookup_vmethodgroup(&(vnode->methodgroups), group_id);
+ if(!vmg) return;
+
+ vm= lookup_vmethod(&(vmg->methods), method_id);
+ if(!vm) return;
+#ifdef VERSECHAT
+ if(strcmp(vm->name, "join")==0) method_idx=0;
+ if(strcmp(vm->name, "leave")==0) method_idx=1;
+ if(strcmp(vm->name, "hear")==0) method_idx=2;
+ if(method_idx>-1)
+ verse_method_call_unpack(params, vmethod_info[method_idx].param_count, vmethod_info[method_idx].param_type, arg);
+
+ switch(method_idx) {
+ case 0:
+ printf("Joining channel %s\n",arg[0].vstring);
+ text=add_empty_text();
+ text->flags |= TXT_ISCHAT;
+ rename_id(&(text->id), arg[0].vstring);
+ break;
+ case 1:
+ printf("Leaving channel %s\n",arg[0].vstring);
+ break;
+ case 2:
+ {
+ ListBase lb = G.main->text;
+ ID *id= (ID *)lb.first;
+ char showstr[1024];
+ showstr[0]='\0';
+ text = NULL;
+ sprintf(showstr, "%s: %s\n", arg[1].vstring, arg[2].vstring);
+ for(; id; id= id->next) {
+ if(strcmp(id->name+2, arg[0].vstring)==0 && strcmp(arg[0].vstring, "#server")!=0) {
+ text = (Text *)id;
+ break;
+ }
+ }
+ if(text) {
+ txt_insert_buf(text, showstr);
+ txt_move_eof(text, 0);
+ allqueue(REDRAWCHAT, 0);
+ } else {
+ printf("%s> %s: %s\n",arg[0].vstring, arg[1].vstring, arg[2].vstring);
+ }
+ }
+ break;
+ }
+#endif
+}
+
+void set_method_callbacks(void)
+{
+ /* create and destroy method groups */
+ verse_callback_set(verse_send_o_method_group_create, cb_o_method_group_create, NULL);
+ verse_callback_set(verse_send_o_method_group_destroy, cb_o_method_group_destroy, NULL);
+
+ /* create and destroy methods */
+ verse_callback_set(verse_send_o_method_create, cb_o_method_create, NULL);
+ verse_callback_set(verse_send_o_method_destroy, cb_o_method_destroy, NULL);
+
+ /* call methods */
+ verse_callback_set(verse_send_o_method_call, cb_o_method_call, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_node.c b/source/blender/blenkernel/intern/verse_node.c
new file mode 100644
index 00000000000..682ae773da5
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_node.c
@@ -0,0 +1,750 @@
+/**
+ * $Id: verse_node.c 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+ /* for tags */
+static void free_verse_tag_data(struct VTag *vtag);
+static struct VTag *find_tag_in_queue(struct VTagGroup *vtaggroup, const char *name);
+static struct VTag *create_verse_tag(struct VTagGroup *vtaggroup, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag);
+ /* for verse tag groups */
+static void free_verse_taggroup_data(struct VTagGroup *taggroup);
+static struct VTagGroup *find_taggroup_in_queue(struct VNode *vnode, const char *name);
+static struct VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name);
+ /* for verse nodes */
+static void move_verse_node_to_dlist(struct VerseSession *session, VNodeID vnode_id);
+ /* function prototypes of node callback functions */
+static void cb_tag_destroy(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id);
+static void cb_tag_create(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag);
+static void cb_tag_group_destroy(void *user_data, VNodeID node_id, uint16 group_id);
+static void cb_tag_group_create(void *user_data, VNodeID node_id, uint16 group_id, const char *name);
+static void cb_node_name_set(void *user_data, VNodeID node_id, const char *name);
+static void cb_node_destroy(void *user_data, VNodeID node_id);
+static void cb_node_create(void *user_data, VNodeID node_id, uint8 type, VNodeID owner_id);
+
+/*
+ * send new tag to verse server
+ */
+void send_verse_tag(VTag *vtag)
+{
+ verse_send_tag_create(vtag->vtaggroup->vnode->id,
+ vtag->vtaggroup->id,
+ vtag->id,
+ vtag->name,
+ vtag->type,
+ vtag->tag);
+}
+
+/*
+ * free tag data
+ */
+static void free_verse_tag_data(VTag *vtag)
+{
+ /* free name of verse tag */
+ MEM_freeN(vtag->name);
+ /* free value of tag */
+ MEM_freeN(vtag->tag);
+}
+
+/*
+ * try to find tag in sending queue ... if tag will be found, then
+ * this function will removed tag from queue and will return pointer
+ * at this tag
+ */
+static VTag *find_tag_in_queue(VTagGroup *vtaggroup, const char *name)
+{
+ struct VTag *vtag;
+
+ vtag = vtaggroup->queue.first;
+
+ while(vtag) {
+ if(strcmp(vtag->name, name)==0) {
+ BLI_remlink(&(vtaggroup->queue), vtag);
+ break;
+ }
+ vtag = vtag->next;
+ }
+
+ return vtag;
+}
+
+/*
+ * create new verse tag
+ */
+static VTag *create_verse_tag(
+ VTagGroup *vtaggroup,
+ uint16 tag_id,
+ const char *name,
+ VNTagType type,
+ const VNTag *tag)
+{
+ struct VTag *vtag;
+
+ vtag = (VTag*)MEM_mallocN(sizeof(VTag), "VTag");
+
+ vtag->vtaggroup = vtaggroup;
+ vtag->id = tag_id;
+ vtag->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTag name");
+ strcpy(vtag->name, name);
+ vtag->type = type;
+
+ vtag->tag = (VNTag*)MEM_mallocN(sizeof(VNTag), "VNTag");
+ *vtag->tag = *tag;
+
+ vtag->value = NULL;
+
+ return vtag;
+}
+
+/*
+ * send taggroup to verse server
+ */
+void send_verse_taggroup(VTagGroup *vtaggroup)
+{
+ verse_send_tag_group_create(
+ vtaggroup->vnode->id,
+ vtaggroup->id,
+ vtaggroup->name);
+}
+
+/*
+ * free taggroup data
+ */
+static void free_verse_taggroup_data(VTagGroup *taggroup)
+{
+ struct VerseSession *session = taggroup->vnode->session;
+ struct VTag *vtag;
+
+ vtag = taggroup->tags.lb.first;
+
+ while(vtag) {
+ free_verse_tag_data(vtag);
+ vtag = vtag->next;
+ }
+
+ /* unsubscribe from taggroup */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_tag_group_unsubscribe(taggroup->vnode->id, taggroup->id);
+
+ BLI_dlist_destroy(&(taggroup->tags));
+ MEM_freeN(taggroup->name);
+}
+
+/*
+ * move taggroup from queue to dynamic list with access array,
+ * set up taggroup id and return pointer at this taggroup
+ */
+static VTagGroup *find_taggroup_in_queue(VNode *vnode, const char *name)
+{
+ struct VTagGroup *vtaggroup;
+
+ vtaggroup = vnode->queue.first;
+
+ while(vtaggroup) {
+ if(strcmp(vtaggroup->name, name)==0) {
+ BLI_remlink(&(vnode->queue), vtaggroup);
+ break;
+ }
+ vtaggroup = vtaggroup->next;
+ }
+
+ return vtaggroup;
+}
+
+/*
+ * create new verse group of tags
+ */
+static VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name)
+{
+ struct VTagGroup *taggroup;
+
+ taggroup = (VTagGroup*)MEM_mallocN(sizeof(VTagGroup), "VTagGroup");
+
+ taggroup->vnode = vnode;
+ taggroup->id = group_id;
+ taggroup->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTagGroup name");
+ strcpy(taggroup->name, name);
+
+ BLI_dlist_init(&(taggroup->tags));
+ taggroup->queue.first = taggroup->queue.last = NULL;
+
+ taggroup->post_tag_change = post_tag_change;
+ taggroup->post_taggroup_create = post_taggroup_create;
+
+ return taggroup;
+}
+
+/*
+ * move first VerseNode waiting in sending queue to dynamic list of VerseNodes
+ * (it usually happens, when "our" VerseNode was received from verse server)
+ */
+static void move_verse_node_to_dlist(VerseSession *session, VNodeID vnode_id)
+{
+ VNode *vnode;
+
+ vnode = session->queue.first;
+
+ if(vnode) {
+ BLI_remlink(&(session->queue), vnode);
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, vnode_id);
+ }
+}
+
+/*
+ * send VerseNode to verse server
+ */
+void send_verse_node(VNode *vnode)
+{
+ verse_send_node_create(
+ vnode->id,
+ vnode->type,
+ vnode->session->avatar);
+}
+
+/*
+ * free Verse Node data
+ */
+void free_verse_node_data(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VTagGroup *vtaggroup;
+
+ /* free node data (object, geometry, etc.) */
+ switch(vnode->type){
+ case V_NT_OBJECT:
+ free_object_data(vnode);
+ break;
+ case V_NT_GEOMETRY:
+ free_geom_data(vnode);
+ break;
+ case V_NT_BITMAP:
+ free_bitmap_node_data(vnode);
+ break;
+ default:
+ break;
+ }
+
+ /* free all tag groups in dynamic list with access array */
+ vtaggroup = vnode->taggroups.lb.first;
+ while(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ vtaggroup = vtaggroup->next;
+ }
+ BLI_dlist_destroy(&(vnode->taggroups));
+
+ /* free all tag groups still waiting in queue */
+ vtaggroup = vnode->queue.first;
+ while(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ vtaggroup = vtaggroup->next;
+ }
+ BLI_freelistN(&(vnode->queue));
+
+ /* unsubscribe from node */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_node_unsubscribe(vnode->id);
+
+ /* free node name */
+ MEM_freeN(vnode->name);
+ vnode->name = NULL;
+
+ /* free node data */
+ MEM_freeN(vnode->data);
+ vnode->data = NULL;
+
+}
+
+/*
+ * free VerseNode
+ */
+void free_verse_node(VNode *vnode)
+{
+ free_verse_node_data(vnode);
+
+ BLI_dlist_free_item(&(vnode->session->nodes), vnode->id);
+}
+
+/*
+ * Find a Verse Node from session
+ */
+VNode* lookup_vnode(VerseSession *session, VNodeID node_id)
+{
+ struct VNode *vnode;
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ return vnode;
+}
+
+/*
+ * create new Verse Node
+ */
+VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id)
+{
+ struct VNode *vnode;
+
+ vnode = (VNode*)MEM_mallocN(sizeof(VNode), "VerseNode");
+
+ vnode->session = session;
+ vnode->id = node_id;
+ vnode->owner_id = owner_id;
+ vnode->name = NULL;
+ vnode->type = type;
+
+ BLI_dlist_init(&(vnode->taggroups));
+ vnode->queue.first = vnode->queue.last = NULL;
+ vnode->methodgroups.first = vnode->methodgroups.last = NULL;
+
+ vnode->data = NULL;
+
+ vnode->counter = 0;
+
+ vnode->flag = 0;
+#ifdef VERSECHAT
+ vnode->chat_flag = CHAT_NOTLOGGED;
+#endif
+
+ vnode->post_node_create = post_node_create;
+ vnode->post_node_destroy = post_node_destroy;
+ vnode->post_node_name_set = post_node_name_set;
+
+ return vnode;
+}
+
+/*
+ * callback function: tag was destroyed
+ */
+static void cb_tag_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 tag_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+ struct VTag *vtag;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) return;
+
+ /* try to find verse tag in dynamic list of tags in tag group */
+ vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id);
+
+ if(vtag) {
+ free_verse_tag_data(vtag);
+ BLI_dlist_free_item(&(vtaggroup->tags), vtag->id);
+ }
+}
+
+/*
+ * callback function: new tag was created
+ */
+static void cb_tag_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 tag_id,
+ const char *name,
+ VNTagType type,
+ const VNTag *tag)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+ struct VTag *vtag;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) return;
+
+ /* try to find verse tag in dynamic list of tags in tag group */
+ vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id);
+
+ if(!vtag) {
+ /* we will try to find vtag in sending queue */
+ vtag = find_tag_in_queue(vtaggroup, name);
+
+ /* when we didn't create this tag, then we will have to create one */
+ if(!vtag) vtag = create_verse_tag(vtaggroup, tag_id, name, type, tag);
+ else vtag->id = tag_id;
+
+ /* add tag to the list of tags in tag group */
+ BLI_dlist_add_item_index(&(vtaggroup->tags), vtag, tag_id);
+
+ /* post change/create method */
+ vtaggroup->post_tag_change(vtag);
+ }
+ else {
+ /* this tag exists, then we will propably change value of this tag */
+ if((vtag->type != type) || (strcmp(vtag->name, name)!=0)) {
+ /* changes of type or name are not allowed and such
+ * stupid changes will be returned back */
+ send_verse_tag(vtag);
+ }
+ else {
+ /* post change/create method */
+ vtaggroup->post_tag_change(vtag);
+ }
+ }
+}
+
+/*
+ * callback function: tag group was destroyed
+ */
+static void cb_tag_group_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ BLI_dlist_free_item(&(vnode->taggroups), vtaggroup->id);
+ }
+}
+
+/*
+ * callback function: new tag group was created
+ */
+static void cb_tag_group_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* name of taggroup has to begin with string "blender:" */
+ if(strncmp("blender:", name, 8)) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) {
+ /* subscribe to tag group (when new tag will be created, then blender will
+ * receive command about it) */
+ verse_send_tag_group_subscribe(vnode->id, group_id);
+ verse_callback_update(0);
+
+ /* try to find taggroup in waiting queue */
+ vtaggroup = find_taggroup_in_queue(vnode, name);
+
+ /* if no taggroup exist, then new has to be created */
+ if(!vtaggroup) vtaggroup = create_verse_taggroup(vnode, group_id, name);
+ else vtaggroup->id = group_id;
+
+ /* add tag group to dynamic list with access array */
+ BLI_dlist_add_item_index(&(vnode->taggroups), (void*)vtaggroup, (unsigned int)group_id);
+
+ /* post create method */
+ vtaggroup->post_taggroup_create(vtaggroup);
+ }
+ else {
+ /* this taggroup exist and somebody try to change its name */
+ if(strcmp(vtaggroup->name, name)!=0) {
+ /* blender doesn't allow such stupid and dangerous things */
+ send_verse_taggroup(vtaggroup);
+ }
+ }
+}
+
+/*
+ * callback function: change name of node
+ */
+static void cb_node_name_set(
+ void *user_data,
+ VNodeID node_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(vnode && name) {
+ if(!vnode->name) {
+ vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name");
+ }
+ else if(strlen(name) > strlen(vnode->name)) {
+ MEM_freeN(vnode->name);
+ vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name");
+ }
+ strcpy(vnode->name, name);
+
+ vnode->post_node_name_set(vnode);
+ }
+}
+
+/*
+ * callback function for deleting node
+ */
+static void cb_node_destroy(
+ void *user_data,
+ VNodeID node_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ if(vnode) {
+ /* remove VerseNode from dynamic list */
+ BLI_dlist_rem_item(&(session->nodes), (unsigned int)node_id);
+ /* do post destroy operations */
+ vnode->post_node_destroy(vnode);
+ /* free verse data */
+ free_verse_node_data(vnode);
+ /* free VerseNode */
+ MEM_freeN(vnode);
+ };
+}
+
+
+/*
+ * callback function for new created node
+ */
+static void cb_node_create(
+ void *user_data,
+ VNodeID node_id,
+ uint8 type,
+ VNodeID owner_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode = NULL;
+
+ if(!session) return;
+
+ /* subscribe to node */
+ if((type==V_NT_OBJECT) || (type==V_NT_GEOMETRY) || (type==V_NT_BITMAP))
+ verse_send_node_subscribe(node_id);
+ else
+ return;
+
+ switch(type){
+ case V_NT_OBJECT :
+ if(owner_id==VN_OWNER_MINE) {
+ struct VLink *vlink;
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* find unsent link pointing at this VerseNode */
+ vlink = find_unsent_child_vlink(session, vnode);
+ /* send VerseLink */
+ if(vlink) send_verse_link(vlink);
+ /* send name of object node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* subscribe to changes of object node transformations */
+ verse_send_o_transform_subscribe(node_id, 0);
+ /* send object transformation matrix */
+ send_verse_object_position(vnode);
+ send_verse_object_rotation(vnode);
+ send_verse_object_scale(vnode);
+ }
+ else {
+ /* create new VerseNode */
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to list of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create object data */
+ vnode->data = create_object_data();
+ /* set up avatar's name */
+ if(node_id == session->avatar) {
+ verse_send_node_name_set(node_id, U.verseuser);
+ }
+ else if(session->flag & VERSE_AUTOSUBSCRIBE) {
+ /* subscribe to changes of object node transformations */
+ verse_send_o_transform_subscribe(node_id, 0);
+ }
+ }
+ break;
+ case V_NT_GEOMETRY :
+ if(owner_id==VN_OWNER_MINE){
+ struct VLink *vlink;
+ struct VLayer *vlayer;
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* find unsent link pointing at this VerseNode */
+ vlink = find_unsent_parent_vlink(session, vnode);
+ /* send VerseLink */
+ if(vlink) send_verse_link(vlink);
+ /* send name of geometry node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* send all not sent layer to verse server */
+ vlayer = (VLayer*)((VGeomData*)vnode->data)->queue.first;
+ if(vlayer) {
+ while(vlayer) {
+ send_verse_layer(vlayer);
+ vlayer = vlayer->next;
+ }
+ }
+ else {
+ /* send two verse layers to verse server */
+/* verse_send_g_layer_create(node_id, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0);
+ verse_send_g_layer_create(node_id, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);*/
+ }
+ }
+ else {
+ /* create new VerseNode*/
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to dlist of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create geometry data */
+ vnode->data = (void*)create_geometry_data();
+ }
+ break;
+ case V_NT_BITMAP :
+ if(owner_id==VN_OWNER_MINE) {
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* send name of object node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* send dimension of image to verse server */
+ verse_send_b_dimensions_set(node_id,
+ ((VBitmapData*)vnode->data)->width,
+ ((VBitmapData*)vnode->data)->height,
+ ((VBitmapData*)vnode->data)->depth);
+ }
+ else {
+ /* create new VerseNode*/
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to dlist of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create bitmap data */
+ vnode->data = (void*)create_bitmap_data();
+ }
+ break;
+ default:
+ vnode = NULL;
+ break;
+ }
+
+ if(vnode) vnode->post_node_create(vnode);
+}
+
+/*
+ * set up all callbacks for verse nodes
+ */
+void set_node_callbacks(void)
+{
+ /* new node created */
+ verse_callback_set(verse_send_node_create, cb_node_create, NULL);
+ /* node was deleted */
+ verse_callback_set(verse_send_node_destroy, cb_node_destroy, NULL);
+ /* name of node was set */
+ verse_callback_set(verse_send_node_name_set, cb_node_name_set, NULL);
+
+ /* new tag group was created */
+ verse_callback_set(verse_send_tag_group_create, cb_tag_group_create, NULL);
+ /* tag group was destroy */
+ verse_callback_set(verse_send_tag_group_destroy, cb_tag_group_destroy, NULL);
+
+ /* new tag was created */
+ verse_callback_set(verse_send_tag_create, cb_tag_create, NULL);
+ /* tag was destroy */
+ verse_callback_set(verse_send_tag_destroy, cb_tag_destroy, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c
new file mode 100644
index 00000000000..9f4dcc72237
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_object_node.c
@@ -0,0 +1,620 @@
+/**
+ * $Id: verse_object_node.c 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_verse.h"
+#include "BKE_utildefines.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+
+/* callback functions */
+static void cb_o_transform_pos_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const real32 *pos, const real32 *speed, const real32 *accelerate, const real32 *drag_normal, real32 drag);
+static void cb_o_transform_rot_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const VNQuat32 *temp, const VNQuat32 *speed, const VNQuat32 *accelerate, const VNQuat32 *drag_normal, real32 drag);
+static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z);
+static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id);
+static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id);
+
+/* other functions */
+static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink);
+static void free_verse_link_data(struct VLink *vlink);
+
+/*
+ * find noy sent VerseLink in queue
+ */
+VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode)
+{
+ struct VLink *vlink;
+
+ if(vnode->type!=V_NT_OBJECT) return NULL;
+
+ vlink = ((VObjectData*)vnode->data)->queue.first;
+ while(vlink) {
+ if(vlink->target->id != -1) {
+ printf("\t vlink found, vnode target id %d\n", vlink->target->id);
+ return vlink;
+ }
+ vlink = vlink->next;
+ }
+ return NULL;
+}
+
+/*
+ * find unsent VerseLink "pointing at this VerseNode"
+ */
+VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode)
+{
+ struct VNode *tmp;
+ struct VLink *vlink;
+
+ tmp = session->nodes.lb.first;
+
+ while(tmp) {
+ if(tmp->type==V_NT_OBJECT) {
+ vlink = ((VObjectData*)tmp->data)->queue.first;
+ while(vlink) {
+ if(vlink->target == vnode)
+ return vlink;
+ vlink = vlink->next;
+ }
+ }
+ tmp = tmp->next;
+ }
+ return NULL;
+}
+
+/*
+ * send object position to verse server
+ */
+void send_verse_object_position(VNode *vnode)
+{
+ float tmp;
+
+ ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY;
+
+ /* we have to do rotation around x axis (+pi/2) to be
+ compatible with other verse applications */
+ tmp = -((VObjectData*)vnode->data)->pos[1];
+ ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2];
+ ((VObjectData*)vnode->data)->pos[2] = tmp;
+
+ verse_send_o_transform_pos_real32(
+ vnode->id, /* node id */
+ 0, /* time_s ... no interpolation */
+ 0, /* time_f ... no interpolation */
+ ((VObjectData*)vnode->data)->pos,
+ NULL, /* speed ... no interpolation */
+ NULL, /* accelerate ... no interpolation */
+ NULL, /* drag normal ... no interpolation */
+ 0.0); /* drag ... no interpolation */
+}
+
+/*
+ * send object rotation to verse server
+ */
+void send_verse_object_rotation(VNode *vnode)
+{
+ VNQuat32 quat;
+ float q[4] = {cos(-M_PI/4), -sin(-M_PI/4), 0, 0}, v[4], tmp[4];
+
+ /* inverse transformation to transformation in function cb_o_transform_rot_real32 */
+ QuatMul(v, ((VObjectData*)vnode->data)->quat, q);
+ q[1]= sin(-M_PI/4);
+ QuatMul(tmp, q, v);
+
+ quat.x = tmp[1];
+ quat.y = tmp[2];
+ quat.z = tmp[3];
+ quat.w = tmp[0];
+
+ ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY;
+
+ verse_send_o_transform_rot_real32(
+ vnode->id, /* node id */
+ 0, /* time_s ... no interpolation */
+ 0, /* time_f ... no interpolation */
+ &quat,
+ NULL, /* speed ... no interpolation */
+ NULL, /* accelerate ... no interpolation */
+ NULL, /* drag normal ... no interpolation */
+ 0.0); /* drag ... no interpolation */
+}
+
+/*
+ * send object rotation to verse server
+ */
+void send_verse_object_scale(VNode *vnode)
+{
+ float tmp;
+
+ ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY;
+
+ /* we have to do rotation around x axis (+pi/2) to be
+ compatible with other verse applications */
+ tmp = ((VObjectData*)vnode->data)->scale[1];
+ ((VObjectData*)vnode->data)->scale[1] = ((VObjectData*)vnode->data)->scale[2];
+ ((VObjectData*)vnode->data)->scale[2] = tmp;
+
+ verse_send_o_transform_scale_real32(
+ vnode->id,
+ ((VObjectData*)vnode->data)->scale[0],
+ ((VObjectData*)vnode->data)->scale[1],
+ ((VObjectData*)vnode->data)->scale[2]);
+}
+
+/*
+ * send VerseLink to verse server
+ */
+void send_verse_link(VLink *vlink)
+{
+ verse_session_set(vlink->session->vsession);
+
+ verse_send_o_link_set(
+ vlink->source->id,
+ vlink->id,
+ vlink->target->id,
+ vlink->label,
+ vlink->target_id);
+}
+
+/*
+ * set up pointer at VerseLink of target node (geometry node, material node, etc.)
+ */
+static void set_target_node_link_pointer(VNode *vnode, VLink *vlink)
+{
+ switch (vnode->type) {
+ case V_NT_GEOMETRY:
+ ((VGeomData*)vnode->data)->vlink = vlink;
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * free VerseLink and it's label
+ */
+static void free_verse_link_data(VLink *vlink)
+{
+ MEM_freeN(vlink->label);
+}
+
+/*
+ * create new VerseLink
+ */
+VLink *create_verse_link(
+ VerseSession *session,
+ VNode *source,
+ VNode *target,
+ uint16 link_id,
+ uint32 target_id,
+ const char *label)
+{
+ struct VLink *vlink;
+
+ vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink");
+ vlink->session = session;
+ vlink->source = source;
+ vlink->target = target;
+ vlink->id = link_id;
+ vlink->target_id = target_id;
+
+ set_target_node_link_pointer(target, vlink);
+
+ vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label");
+ vlink->label[0] = '\0';
+ strcat(vlink->label, label);
+
+ vlink->flag = 0;
+
+ vlink->post_link_set = post_link_set;
+ vlink->post_link_destroy = post_link_destroy;
+
+ return vlink;
+}
+
+/*
+ * free ObjectData (links, links in queue and lables of links)
+ */
+void free_object_data(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VObjectData *obj = (VObjectData*)vnode->data;
+ struct VLink *vlink;
+ struct VMethodGroup *vmg;
+
+ if(!obj) return;
+
+ /* free all labels of links in dlist */
+ vlink = obj->links.lb.first;
+ while(vlink){
+ free_verse_link_data(vlink);
+ vlink = vlink->next;
+ }
+
+ /* free all labels of links waiting in queue */
+ vlink = obj->queue.first;
+ while(vlink){
+ free_verse_link_data(vlink);
+ vlink = vlink->next;
+ }
+ /* free dynamic list and sendig queue of links */
+ BLI_dlist_destroy(&(obj->links));
+ BLI_freelistN(&(obj->queue));
+
+ /* free method groups and their methods */
+ for(vmg = vnode->methodgroups.first; vmg; vmg= vmg->next) {
+ free_verse_methodgroup(vmg);
+ }
+ BLI_freelistN(&(vnode->methodgroups));
+
+ /* free constraint between VerseNode and Object */
+ obj->post_object_free_constraint(vnode);
+
+ /* unsubscribe from receiving changes of transformation matrix */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_o_transform_unsubscribe(vnode->id, 0);
+}
+
+/*
+ * create new object data
+ */
+VObjectData *create_object_data(void)
+{
+ VObjectData *obj;
+
+ obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData");
+ obj->object = NULL;
+ BLI_dlist_init(&(obj->links));
+ obj->queue.first = obj->queue.last = NULL;
+ obj->flag = 0;
+
+ /* transformation matrix */
+ obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0;
+ obj->quat[0] = obj->quat[1] = obj->quat[2] = 0.0; obj->quat[3] = 1;
+ obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0;
+
+ /* transformation flags */
+ obj->flag |= POS_SEND_READY;
+ obj->flag |= ROT_SEND_READY;
+ obj->flag |= SCALE_SEND_READY;
+
+ /* set up pointers at post callback functions */
+/* obj->post_transform = post_transform;*/
+ obj->post_transform_pos = post_transform_pos;
+ obj->post_transform_rot = post_transform_rot;
+ obj->post_transform_scale = post_transform_scale;
+ obj->post_object_free_constraint = post_object_free_constraint;
+
+ return obj;
+}
+
+/*
+ * callback function:
+ */
+static void cb_o_transform_pos_real32(
+ void *user_data,
+ VNodeID node_id,
+ uint32 time_s,
+ uint32 time_f,
+ const real32 *pos,
+ const real32 *speed,
+ const real32 *accelerate,
+ const real32 *drag_normal,
+ real32 drag)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ float vec[3], dt, tmp;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
+
+ /* verse server sends automaticaly some stupid default values ...
+ * we have to ignore these values, when we created this object node */
+ if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) {
+ ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY;
+ return;
+ }
+
+ dt = time_s + time_f/(0xffff);
+
+ if(pos) {
+ vec[0] = pos[0];
+ vec[1] = pos[1];
+ vec[2] = pos[2];
+ }
+ else {
+ vec[0] = 0.0f;
+ vec[1] = 0.0f;
+ vec[2] = 0.0f;
+ }
+
+ if(speed) {
+ vec[0] += speed[0]*dt;
+ vec[1] += speed[1]*dt;
+ vec[2] += speed[2]*dt;
+ }
+
+ if(accelerate) {
+ vec[0] += accelerate[0]*dt*dt/2;
+ vec[1] += accelerate[1]*dt*dt/2;
+ vec[2] += accelerate[2]*dt*dt/2;
+ }
+
+ /* we have to do rotation around x axis (+pi/2) to be
+ compatible with other verse applications */
+ tmp = vec[1];
+ vec[1] = -vec[2];
+ vec[2] = tmp;
+
+ if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) ||
+ (((VObjectData*)vnode->data)->pos[1] != vec[1]) ||
+ (((VObjectData*)vnode->data)->pos[2] != vec[2]))
+ {
+ ((VObjectData*)vnode->data)->pos[0] = vec[0];
+ ((VObjectData*)vnode->data)->pos[1] = vec[1];
+ ((VObjectData*)vnode->data)->pos[2] = vec[2];
+
+ ((VObjectData*)vnode->data)->post_transform_pos(vnode);
+ }
+}
+
+/*
+ * callback function:
+ */
+static void cb_o_transform_rot_real32(
+ void *user_data,
+ VNodeID node_id,
+ uint32 time_s,
+ uint32 time_f,
+ const VNQuat32 *quat,
+ const VNQuat32 *speed,
+ const VNQuat32 *accelerate,
+ const VNQuat32 *drag_normal,
+ real32 drag)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ float temp[4]={0, 0, 0, 0}, v[4], dt; /* temporary quaternions */
+ float q[4]={cos(M_PI/4), -sin(M_PI/4), 0, 0}; /* conjugate quaternion (represents rotation
+ around x-axis +90 degrees) */
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
+
+ /* verse server sends automaticaly some stupid default values ...
+ * we have to ignore these values, when we created this object node */
+ if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) {
+ ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY;
+ return;
+ }
+
+ dt = time_s + time_f/(0xffff);
+
+ if(quat) {
+ temp[1] = quat->x;
+ temp[2] = quat->y;
+ temp[3] = quat->z;
+ temp[0] = quat->w;
+ }
+
+ if(speed) {
+ temp[1] += speed->x*dt;
+ temp[2] += speed->y*dt;
+ temp[3] += speed->z*dt;
+ temp[0] += speed->w*dt;
+ }
+
+ if(accelerate) {
+ temp[1] += accelerate->x*dt*dt/2;
+ temp[2] += accelerate->y*dt*dt/2;
+ temp[3] += accelerate->z*dt*dt/2;
+ temp[0] += accelerate->w*dt*dt/2;
+ }
+
+ /* following matematical operation transform rotation:
+ *
+ * v' = quaternion * v * conjugate_quaternion
+ *
+ *, where v is original representation of rotation */
+
+ QuatMul(v, temp, q);
+ q[1]= sin(M_PI/4); /* normal quaternion */
+ QuatMul(temp, q, v);
+
+ if( (((VObjectData*)vnode->data)->quat[0] != temp[0]) ||
+ (((VObjectData*)vnode->data)->quat[1] != temp[1]) ||
+ (((VObjectData*)vnode->data)->quat[2] != temp[2]) ||
+ (((VObjectData*)vnode->data)->quat[3] != temp[3]))
+ {
+ QUATCOPY(((VObjectData*)vnode->data)->quat, temp);
+
+ ((VObjectData*)vnode->data)->post_transform_rot(vnode);
+ }
+}
+
+/*
+ * callback function:
+ */
+static void cb_o_transform_scale_real32(
+ void *user_data,
+ VNodeID node_id,
+ real32 scale_x,
+ real32 scale_y,
+ real32 scale_z)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ real32 tmp;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
+
+ /* verse server sends automaticaly some stupid default values ...
+ * we have to ignore these values, when we created this object node */
+ if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) {
+ ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY;
+ return;
+ }
+
+ /* flip axis (verse spec) */
+ tmp = scale_y;
+ scale_y = scale_z;
+ scale_z = tmp;
+
+ /* z and y axis are flipped here too */
+ if( (((VObjectData*)vnode->data)->scale[0] != scale_x) ||
+ (((VObjectData*)vnode->data)->scale[1] != scale_y) ||
+ (((VObjectData*)vnode->data)->scale[2] != scale_z))
+ {
+ ((VObjectData*)vnode->data)->scale[0] = scale_x;
+ ((VObjectData*)vnode->data)->scale[1] = scale_y;
+ ((VObjectData*)vnode->data)->scale[2] = scale_z;
+
+ ((VObjectData*)vnode->data)->post_transform_scale(vnode);
+ }
+}
+
+/*
+ * callback function: link between object node and some other node was created
+ */
+static void cb_o_link_set(
+ void *user_data,
+ VNodeID node_id,
+ uint16 link_id,
+ VNodeID link,
+ const char *label,
+ uint32 target_id)
+{
+ struct VLink *vlink;
+ struct VNode *source;
+ struct VNode *target;
+
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+
+ if(!session) return;
+
+ source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link);
+
+ if(!(source && target)) return;
+
+ vlink = ((VObjectData*)source->data)->queue.first;
+
+ if(vlink && (vlink->source==source) && (vlink->target==target)) {
+ /* remove VerseLink from sending queue */
+ BLI_remlink(&(((VObjectData*)source->data)->queue), vlink);
+ /* add VerseLink to dynamic list of VerseLinks */
+ BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
+ /* send next link from sending queue */
+ if(((VObjectData*)source->data)->queue.first)
+ send_verse_link(((VObjectData*)source->data)->queue.first);
+ /* set up VerseLink variables */
+ vlink->flag = 0;
+ vlink->id = link_id;
+ vlink->target_id = target_id;
+ }
+ else {
+ /* create new VerseLink */
+ vlink = create_verse_link(session, source, target, link_id, target_id, label);
+ /* add VerseLink to dynamic list of VerseLinks */
+ BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
+ }
+
+ target->counter++;
+
+ vlink->post_link_set(vlink);
+}
+
+/*
+ * callback function: destroy link between two VerseNodes
+ */
+static void cb_o_link_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 link_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VLink *vlink;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id);
+
+ if(vlink) {
+ vlink->target->counter--;
+ free_verse_link_data(vlink);
+ BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id);
+ }
+
+ vlink->post_link_destroy(vlink);
+}
+
+void set_object_callbacks(void)
+{
+ /* position of object was changed */
+ verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL);
+ /* rotation of object was changed */
+ verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL);
+ /* size of object was changed */
+ verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL);
+ /* new link between nodes was created */
+ verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL);
+ /* link between nodes was destroyed */
+ verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_session.c b/source/blender/blenkernel/intern/verse_session.c
new file mode 100644
index 00000000000..64d6b9885fe
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_session.c
@@ -0,0 +1,480 @@
+/**
+ * $Id: verse_session.c 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h" /* temp */
+#include "DNA_listBase.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_screen.h"
+#include "BIF_verse.h"
+
+#include "BKE_global.h"
+#include "BKE_verse.h"
+
+struct ListBase session_list={NULL, NULL};
+struct ListBase server_list={NULL, NULL};
+
+static int cb_ping_registered = 0;
+
+/* list of static function prototypes */
+static void cb_connect_terminate(const char *address, const char *bye);
+static void cb_connect_accept(void *user_data, uint32 avatar, void *address, void *connection, const uint8 *host_id);
+static void set_all_callbacks(void);
+static void free_verse_session_data(struct VerseSession *session);
+static void add_verse_server(VMSServer *server);
+static void check_connection_state(struct VerseServer *server);
+
+static void check_connection_state(struct VerseServer *server)
+{
+ struct VerseSession *session;
+ session = session_list.first;
+ while(session) {
+ if(strcmp(server->ip,session->address)==0) {
+ server->flag = session->flag;
+ return;
+ }
+ session = session->next;
+ }
+}
+/*
+ * add verse server to server_list. Prevents duplicate
+ * entries
+ */
+static void add_verse_server(VMSServer *server)
+{
+ struct VerseServer *iter, *niter;
+ VerseServer *newserver;
+ const char *name = verse_ms_field_value(server, "DE");
+ iter = server_list.first;
+
+ while(iter) {
+ niter = iter->next;
+ if(strcmp(iter->ip, server->ip)==0) {
+ return;
+ }
+ iter = niter;
+ }
+
+ newserver = (VerseServer *)MEM_mallocN(sizeof(VerseServer), "VerseServer");
+ newserver->ip = (char *)MEM_mallocN(sizeof(char)*(strlen(server->ip)+1), "VerseServer ip");
+ strcpy(newserver->ip, server->ip);
+
+ if(name) {
+ newserver->name = (char *)MEM_mallocN(sizeof(char)*(strlen(name)+strlen(newserver->ip)+4), "VerseServer name");
+ strcpy(newserver->name, name);
+ strcat(newserver->name, " (");
+ strcat(newserver->name, newserver->ip);
+ strcat(newserver->name, ")");
+ }
+
+ newserver->flag = 0;
+ check_connection_state(newserver);
+
+ printf("Adding new verse server: %s at %s\n", newserver->name, newserver->ip);
+
+ BLI_addtail(&server_list, newserver);
+ post_server_add();
+}
+
+/*
+ * callback function for ping
+ */
+static void cb_ping(void *user, const char *address, const char *message)
+{
+ VMSServer **servers = verse_ms_list_parse(message);
+ if(servers != NULL)
+ {
+ int i;
+
+ for(i = 0; servers[i] != NULL; i++)
+ add_verse_server(servers[i]);
+
+ free(servers);
+ }
+}
+
+/*
+ * callback function for connection terminated
+ */
+static void cb_connect_terminate(const char *address, const char *bye)
+{
+ VerseSession *session = (VerseSession*)current_verse_session();
+
+ if(!session) return;
+
+ /* remove session from list of session */
+ BLI_remlink(&session_list, session);
+ /* do post connect operations */
+ session->post_connect_terminated(session);
+ /* free session data */
+ free_verse_session_data(session);
+ /* free session */
+ MEM_freeN(session);
+}
+
+/*
+ * callback function for accepted connection to verse server
+ */
+static void cb_connect_accept(
+ void *user_data,
+ uint32 avatar,
+ void *address,
+ void *connection,
+ const uint8 *host_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VerseServer *server = server_list.first;
+ uint32 i, mask=0;
+
+ if(!session) return;
+
+ session->flag |= VERSE_CONNECTED;
+ session->flag &= ~VERSE_CONNECTING;
+
+ while(server) {
+ if(strcmp(session->address, server->ip)==0) {
+ server->flag |= VERSE_CONNECTED;
+ server->flag &= ~VERSE_CONNECTING;
+ server->session = session;
+ break;
+ }
+ server = server->next;
+ }
+
+ printf("\tBlender is connected to verse server: %s\n", (char*)address);
+ printf("\tVerseSession->counter: %d\n", session->counter);
+
+ session->avatar = avatar;
+
+ session->post_connect_accept(session);
+
+ for(i = 0; i < V_NT_NUM_TYPES; i++)
+ mask = mask | (1 << i);
+ verse_send_node_index_subscribe(mask);
+ verse_send_node_subscribe(session->avatar); /* subscribe to avatar node, as well */
+
+ /* create our own method group and method */
+ /*verse_send_o_method_group_create(session->avatar, ~0, "tawk-client");*/
+}
+
+/*
+ * set up all callbacks for sessions
+ */
+void set_verse_session_callbacks(void)
+{
+ /* connection */
+ verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL);
+ /* connection was terminated */
+ verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL);
+
+}
+
+/*
+ * set all callbacks used in Blender
+ */
+static void set_all_callbacks(void)
+{
+ /* set up all callbacks for sessions */
+ set_verse_session_callbacks();
+
+ /* set up callbacks for nodes */
+ set_node_callbacks();
+
+ /* set up all callbacks for object nodes */
+ set_object_callbacks();
+
+ /* set up all callbacks for geometry nodes */
+ set_geometry_callbacks();
+
+ /* set up all callbacks for bitmap nodes */
+ set_bitmap_callbacks();
+
+ /* set up all callbacks for method groups and methods */
+ set_method_callbacks();
+}
+
+/*
+ * this function sends and receive all packets for all sessions
+ */
+void b_verse_update(void)
+{
+ VerseSession *session, *next_session;
+
+ session = session_list.first;
+ while(session){
+ next_session = session->next;
+ verse_session_set(session->vsession);
+ if((session->flag & VERSE_CONNECTED) || (session->flag & VERSE_CONNECTING)) {
+ verse_callback_update(10);
+ session->post_connect_update(session);
+ }
+ session = next_session;
+ }
+ if(cb_ping_registered>0) {
+ verse_callback_update(10);
+ }
+}
+
+/*
+ * returns VerseSession coresponding to vsession pointer
+ */
+VerseSession *versesession_from_vsession(VSession *vsession)
+{
+ struct VerseSession *session;
+
+ session = session_list.first;
+
+ while(session) {
+ if(session->vsession==vsession) return session;
+ session = session->next;
+ }
+
+ return session;
+}
+
+/*
+ * returns pointer at current VerseSession
+ */
+VerseSession *current_verse_session(void)
+{
+ struct VerseSession *session;
+ VSession vsession = verse_session_get();
+
+ session = session_list.first;
+
+ while(session){
+ if(session->vsession == vsession)
+ return session;
+ session = session->next;
+ }
+
+ printf("error: non-existing SESSION occured!\n");
+ return NULL;
+}
+
+/*
+ * free VerseSession
+ */
+static void free_verse_session_data(VerseSession *session)
+{
+ struct VNode *vnode;
+
+ /* free data of all nodes */
+ vnode = session->nodes.lb.first;
+ while(vnode){
+ free_verse_node_data(vnode);
+ vnode = vnode->next;
+ }
+
+ /* free data of nodes waiting in queue */
+ vnode = session->queue.first;
+ while(vnode){
+ free_verse_node_data(vnode);
+ vnode = vnode->next;
+ }
+
+ /* free all VerseNodes */
+ BLI_dlist_destroy(&(session->nodes));
+ /* free all VerseNodes waiting in queque */
+ BLI_freelistN(&(session->queue));
+
+ /* free name of verse host for this session */
+ MEM_freeN(session->address);
+}
+
+/*
+ * free VerseSession
+ */
+void free_verse_session(VerseSession *session)
+{
+ /* remove session from session list*/
+ BLI_remlink(&session_list, session);
+ /* do post terminated operations */
+ session->post_connect_terminated(session);
+ /* free session data (nodes, layers) */
+ free_verse_session_data(session);
+ /* free session */
+ MEM_freeN(session);
+}
+
+/*
+ * create new verse session and return coresponding data structure
+ */
+VerseSession *create_verse_session(
+ const char *name,
+ const char *pass,
+ const char *address,
+ uint8 *expected_key)
+{
+ struct VerseSession *session;
+ VSession *vsession;
+
+ vsession = verse_send_connect(name, pass, address, expected_key);
+
+ if(!vsession) return NULL;
+
+ session = (VerseSession*)MEM_mallocN(sizeof(VerseSession), "VerseSession");
+
+ session->flag = VERSE_CONNECTING;
+
+ session->vsession = vsession;
+ session->avatar = -1;
+
+ session->address = (char*)MEM_mallocN(sizeof(char)*(strlen(address)+1),"session adress name");
+ strcpy(session->address, address);
+
+ session->connection = NULL;
+ session->host_id = NULL;
+ session->counter = 0;
+
+ /* initialize dynamic list of nodes and node queue */
+ BLI_dlist_init(&(session->nodes));
+ session->queue.first = session->queue.last = NULL;
+
+ /* set up all client dependent functions */
+ session->post_connect_accept = post_connect_accept;
+ session->post_connect_terminated = post_connect_terminated;
+ session->post_connect_update = post_connect_update;
+
+ post_server_add();
+
+ return session;
+}
+
+/*
+ * end verse session and free all session data
+ */
+void end_verse_session(VerseSession *session)
+{
+ /* send terminate command to verse server */
+ verse_send_connect_terminate(session->address, "blender: bye bye");
+ /* update callbacks */
+ verse_callback_update(1000);
+ /* send destroy session command to verse server */
+ verse_session_destroy(session->vsession);
+ /* set up flag of verse session */
+ session->flag &= ~VERSE_CONNECTED;
+ /* do post connect operations */
+ session->post_connect_terminated(session);
+ /* free structure of verse session */
+ free_verse_session(session);
+}
+
+void free_all_servers(void)
+{
+ VerseServer *server, *nextserver;
+
+ server = server_list.first;
+
+ while(server) {
+ nextserver = server->next;
+ BLI_remlink(&server_list, server);
+ MEM_freeN(server->name);
+ MEM_freeN(server->ip);
+ MEM_freeN(server);
+ server = nextserver;
+ }
+
+ BLI_freelistN(&server_list);
+}
+
+/*
+ * end connection to all verse hosts (servers) ... free all VerseSessions
+ * free all VerseServers
+ */
+void end_all_verse_sessions(void)
+{
+ VerseSession *session,*nextsession;
+
+ session = session_list.first;
+
+ while(session) {
+ nextsession= session->next;
+ end_verse_session(session);
+ /* end next session */
+ session = nextsession;
+ }
+
+ BLI_freelistN(&session_list);
+
+ free_all_servers();
+}
+
+/*
+ * do a get from ms
+ */
+void b_verse_ms_get(void)
+{
+ if(cb_ping_registered==0) {
+ /* handle ping messages (for master server) */
+ verse_callback_set(verse_send_ping, cb_ping, NULL);
+ add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1);
+ cb_ping_registered++;
+ }
+ free_all_servers();
+
+ verse_ms_get_send(U.versemaster, VERSE_MS_FIELD_DESCRIPTION, NULL);
+ verse_callback_update(10);
+}
+
+/*
+ * connect to verse host, set up all callbacks, create session
+ */
+void b_verse_connect(char *address)
+{
+ VerseSession *session = NULL;
+
+ /* if no session was created before, then set up all callbacks */
+ if((session_list.first==NULL) && (session_list.last==NULL))
+ set_all_callbacks();
+
+ /* create new session */
+ if(address)
+ session = create_verse_session("Blender", "pass", address, NULL);
+
+ if(session) {
+ /* add new session to the list of sessions */
+ BLI_addtail(&session_list, session);
+
+ /* add verse handler if this is first session */
+ if(session_list.first == session_list.last)
+ add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1);
+
+ }
+}
+
+#endif
diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h
deleted file mode 100644
index 325798f325f..00000000000
--- a/source/blender/blenkernel/nla_private.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Joshua Leung (full recode)
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef NLA_PRIVATE
-#define NLA_PRIVATE
-
-/* --------------- NLA Evaluation DataTypes ----------------------- */
-
-/* used for list of strips to accumulate at current time */
-typedef struct NlaEvalStrip {
- struct NlaEvalStrip *next, *prev;
-
- NlaTrack *track; /* track that this strip belongs to */
- NlaStrip *strip; /* strip that's being used */
-
- short track_index; /* the index of the track within the list */
- short strip_mode; /* which end of the strip are we looking at */
-
- float strip_time; /* time at which which strip is being evaluated */
-} NlaEvalStrip;
-
-/* NlaEvalStrip->strip_mode */
-enum {
- /* standard evaluation */
- NES_TIME_BEFORE = -1,
- NES_TIME_WITHIN,
- NES_TIME_AFTER,
-
- /* transition-strip evaluations */
- NES_TIME_TRANSITION_START,
- NES_TIME_TRANSITION_END,
-} eNlaEvalStrip_StripMode;
-
-
-/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
-// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
-typedef struct NlaEvalChannel {
- struct NlaEvalChannel *next, *prev;
-
- PointerRNA ptr; /* pointer to struct containing property to use */
- PropertyRNA *prop; /* RNA-property type to use (should be in the struct given) */
- int index; /* array index (where applicable) */
-
- float value; /* value of this channel */
-} NlaEvalChannel;
-
-/* --------------- NLA Functions (not to be used as a proper API) ----------------------- */
-
-/* convert from strip time <-> global time */
-float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode);
-
-/* --------------- NLA Evaluation (very-private stuff) ----------------------- */
-/* these functions are only defined here to avoid problems with the order in which they get defined... */
-
-NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short index, float ctime);
-void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes);
-void nladata_flush_channels(ListBase *channels);
-
-#endif // NLA_PRIVATE
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index 787579250ed..bcc2ac3deec 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -75,6 +75,7 @@ void CalcCent3f(float *cent, float *v1, float *v2, float *v3);
void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4);
void Crossf(float *c, float *a, float *b);
+void Crossd(double *c, double *a, double *b);
void Projf(float *c, float *v1, float *v2);
float Inpf(float *v1, float *v2);
@@ -82,6 +83,7 @@ float Inp2f(float *v1, float *v2);
float Normalize(float *n);
float Normalize2(float *n);
+double Normalize_d(double *n);
float Sqrt3f(float f);
double Sqrt3d(double d);
@@ -267,6 +269,7 @@ void Vec2Subf(float *v, float *v1, float *v2);
void Vec2Copyf(float *v1, float *v2);
void Vec2Lerpf(float *target, float *a, float *b, float t);
+void AxisAngleToQuatd(float *q, float *axis, double angle);
void AxisAngleToQuat(float *q, float *axis, float angle);
void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3]);
void vectoquat(float *vec, short axis, short upflag, float *q);
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index 56a20d8462a..60b7f74954d 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -42,6 +42,7 @@
struct DerivedMesh;
struct RetopoPaintData;
+struct BLI_mempool;
/* note; changing this also might affect the undo copy in editmesh.c */
typedef struct EditVert
@@ -154,6 +155,8 @@ typedef struct EditMesh
HashEdge *hashedgetab;
/* this is for the editmesh_fastmalloc */
+ struct BLI_mempool *vertpool, *edgepool, *facepool;
+
EditVert *allverts, *curvert;
EditEdge *alledges, *curedge;
EditFace *allfaces, *curface;
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 80cd507520c..d835ed18476 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
+#include "BLI_mempool.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -63,6 +64,7 @@ struct GHash {
GHashCmpFP cmpfp;
Entry **buckets;
+ struct BLI_mempool *entrypool;
int nbuckets, nentries, cursize;
};
@@ -72,7 +74,8 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) {
GHash *gh= MEM_mallocN(sizeof(*gh), "GHash");
gh->hashfp= hashfp;
gh->cmpfp= cmpfp;
-
+ gh->entrypool = BLI_mempool_create(sizeof(Entry), 1, 32);
+
gh->cursize= 0;
gh->nentries= 0;
gh->nbuckets= hashsizes[gh->cursize];
@@ -85,7 +88,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) {
void BLI_ghash_insert(GHash *gh, void *key, void *val) {
unsigned int hash= gh->hashfp(key)%gh->nbuckets;
- Entry *e= malloc(sizeof(*e));
+ Entry *e= BLI_mempool_alloc(gh->entrypool);
e->key= key;
e->val= val;
@@ -141,7 +144,7 @@ int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
- free(e);
+ BLI_mempool_free(gh->entrypool, e);
e= n;
@@ -185,13 +188,13 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef
if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
- free(e);
-
+
e= n;
}
}
free(gh->buckets);
+ BLI_mempool_destroy(gh->entrypool);
gh->buckets = 0;
gh->nentries = 0;
gh->nbuckets = 0;
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 7ac7b8b1791..493bbba3567 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -65,7 +65,8 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk)
pool->chunks.first = pool->chunks.last = NULL;
maxchunks = tote / pchunk;
-
+ if (maxchunks==0) maxchunks = 1;
+
/*allocate the actual chunks*/
for(i=0; i < maxchunks; i++){
BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
@@ -85,6 +86,7 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk)
/*set the end of this chunks memoryy to the new tail for next iteration*/
lasttail = curnode;
}
+
/*terminate the list*/
curnode->next = NULL;
return pool;
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index f111e94a141..0c7db0331e1 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -111,6 +111,26 @@ float Normalize(float *n)
return d;
}
+/*original function from shadeoutput.c*/
+double Normalize_d(double *n)
+{
+ double d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+
+ if(d>0.00000000000000001) {
+ d= sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
void Crossf(float *c, float *a, float *b)
{
c[0] = a[1] * b[2] - a[2] * b[1];
@@ -118,6 +138,13 @@ void Crossf(float *c, float *a, float *b)
c[2] = a[0] * b[1] - a[1] * b[0];
}
+void Crossd(double *c, double *a, double *b)
+{
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
/* Inpf returns the dot product, also called the scalar product and inner product */
float Inpf( float *v1, float *v2)
{
@@ -845,7 +872,7 @@ void Mat4MulVec( float mat[][4], int *vec)
vec[2]=(int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]);
}
-void Mat4MulVecfl( float mat[][4], float *vec)
+void Mat4MulVecfl(float mat[][4], float *vec)
{
float x,y;
@@ -1404,6 +1431,28 @@ void AxisAngleToQuat(float *q, float *axis, float angle)
q[3] = nor[2] * si;
}
+void AxisAngleToQuatd(float *q, float *axis, double angle)
+{
+ double nor[3];
+ double si, l;
+
+ nor[0] = axis[0];
+ nor[1] = axis[1];
+ nor[2] = axis[2];
+
+ l = sqrt(nor[0]*nor[0] + nor[1]*nor[1] + nor[2]*nor[2]);
+ nor[0] /= l;
+ nor[1] /= l;
+ nor[2] /= l;
+
+ angle /= 2;
+ si = sin(angle);
+ q[0] = cos(angle);
+ q[1] = nor[0] * si;
+ q[2] = nor[1] * si;
+ q[3] = nor[2] * si;
+}
+
void vectoquat(float *vec, short axis, short upflag, float *q)
{
float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 603c85655d7..8976059d153 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -62,20 +62,19 @@ struct EdgeHash {
/***/
EdgeHash *BLI_edgehash_new(void) {
- EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash");
+ EdgeHash *eh= MEM_callocN(sizeof(*eh), "EdgeHash");
eh->cursize= 0;
eh->nentries= 0;
eh->nbuckets= hashsizes[eh->cursize];
- eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+ eh->buckets= MEM_callocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets 2");
return eh;
}
void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
unsigned int hash;
- Entry *e= malloc(sizeof(*e));
+ Entry *e= MEM_callocN(sizeof(*e), "edgehash e");
if (v1<v0) {
v0 ^= v1;
@@ -95,7 +94,7 @@ void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
int i, nold= eh->nbuckets;
eh->nbuckets= hashsizes[++eh->cursize];
- eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
+ eh->buckets= MEM_mallocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets");
memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
for (i=0; i<nold; i++) {
@@ -110,7 +109,7 @@ void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
}
}
- free(old);
+ MEM_freeN(old);
}
}
@@ -155,7 +154,7 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
Entry *n= e->next;
if (valfreefp) valfreefp(e->val);
- free(e);
+ MEM_freeN(e);
e= n;
}
@@ -168,7 +167,7 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
BLI_edgehash_clear(eh, valfreefp);
- free(eh->buckets);
+ MEM_freeN(eh->buckets);
MEM_freeN(eh);
}
@@ -182,7 +181,7 @@ struct EdgeHashIterator {
};
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) {
- EdgeHashIterator *ehi= malloc(sizeof(*ehi));
+ EdgeHashIterator *ehi= MEM_mallocN(sizeof(*ehi), "eh iter");
ehi->eh= eh;
ehi->curEntry= NULL;
ehi->curBucket= -1;
@@ -195,7 +194,7 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) {
return ehi;
}
void BLI_edgehashIterator_free(EdgeHashIterator *ehi) {
- free(ehi);
+ MEM_freeN(ehi);
}
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 06092cc97d4..5cc9698f79a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3118,6 +3118,26 @@ static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata
}
+static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata, int totface)
+{
+ int i;
+
+ for(i=0; i<pdata->totlayer; i++) {
+ CustomDataLayer *layer = &pdata->layers[i];
+
+ if(layer->type == CD_MTEXPOLY) {
+ MTexPoly *tf= layer->data;
+ int i;
+
+ for (i=0; i<totface; i++, tf++) {
+ tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
+ if(tf->tpage && tf->tpage->id.us==0)
+ tf->tpage->id.us= 1;
+ }
+ }
+ }
+}
+
static void lib_link_mesh(FileData *fd, Main *main)
{
Mesh *me;
@@ -3144,6 +3164,7 @@ static void lib_link_mesh(FileData *fd, Main *main)
me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
+ lib_link_customdata_mtpoly(fd, me, &me->pdata, me->totpoly);
if(me->mr && me->mr->levels.first)
lib_link_customdata_mtface(fd, me, &me->mr->fdata,
((MultiresLevel*)me->mr->levels.first)->totface);
@@ -3199,6 +3220,124 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
}
}
+
+void bmesh_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ MFace *mf;
+ int i;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i);
+ mf = me->mface + findex;
+
+ texpoly->tpage = texface->tpage;
+ texpoly->flag = texface->flag;
+ texpoly->transp = texface->transp;
+ texpoly->mode = texface->mode;
+ texpoly->tile = texface->tile;
+ texpoly->unwrap = texface->unwrap;
+
+ mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i);
+ mloopuv->uv[0] = texface->uv[0][0]; mloopuv->uv[1] = texface->uv[0][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[1][0]; mloopuv->uv[1] = texface->uv[1][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[2][0]; mloopuv->uv[1] = texface->uv[2][1]; mloopuv++;
+
+ if (mf->v4) {
+ mloopuv->uv[0] = texface->uv[3][0]; mloopuv->uv[1] = texface->uv[3][1]; mloopuv++;
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mf = me->mface + findex;
+ mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ mloopcol->r = mcol[0].r; mloopcol->g = mcol[0].g; mloopcol->b = mcol[0].b; mloopcol->a = mcol[0].a; mloopcol++;
+ mloopcol->r = mcol[1].r; mloopcol->g = mcol[1].g; mloopcol->b = mcol[1].b; mloopcol->a = mcol[1].a; mloopcol++;
+ mloopcol->r = mcol[2].r; mloopcol->g = mcol[2].g; mloopcol->b = mcol[2].b; mloopcol->a = mcol[2].a; mloopcol++;
+ if (mf->v4) {
+ mloopcol->r = mcol[3].r; mloopcol->g = mcol[3].g; mloopcol->b = mcol[3].b; mloopcol->a = mcol[3].a; mloopcol++;
+ }
+ }
+}
+
+static void convert_mfaces_to_mpolys(Mesh *mesh)
+{
+ MFace *mf;
+ MLoop *ml;
+ MPoly *mp;
+ MEdge *me;
+ EdgeHash *eh;
+ int numTex, numCol;
+ int i, j, totloop;
+
+ mesh->totpoly = mesh->totface;
+ mesh->mpoly = MEM_callocN(sizeof(MPoly)*mesh->totpoly, "mpoly converted");
+ CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly);
+
+ numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE);
+ numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL);
+
+ totloop = 0;
+ mf = mesh->mface;
+ for (i=0; i<mesh->totface; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ mesh->totloop = totloop;
+ mesh->mloop = MEM_callocN(sizeof(MLoop)*mesh->totloop, "mloop converted");
+
+ CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop);
+ CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata,
+ mesh->totloop, mesh->totpoly);
+
+ eh = BLI_edgehash_new();
+
+ /*build edge hash*/
+ me = mesh->medge;
+ for (i=0; i<mesh->totedge; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
+
+ j = 0; /*current loop index*/
+ ml = mesh->mloop;
+ mf = mesh->mface;
+ mp = mesh->mpoly;
+ for (i=0; i<mesh->totface; i++, mf++, mp++) {
+ mp->loopstart = j;
+
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ mp->mat_nr = mf->mat_nr;
+ mp->flag = mf->flag;
+
+ #define ML(v1, v2) {ml->v = mf->##v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->##v1, mf->##v2)); ml++; j++;}
+
+ ML(v1, v2);
+ ML(v2, v3);
+ if (mf->v4) {
+ ML(v3, v4);
+ ML(v4, v1);
+ } else {
+ ML(v3, v1);
+ }
+
+ #undef ML
+
+ bmesh_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol);
+ }
+
+ /*BMESH_TODO now to deal with fgons*/
+
+ BLI_edgehash_free(eh, NULL);
+}
+
static void direct_link_mesh(FileData *fd, Mesh *mesh)
{
mesh->mat= newdataadr(fd, mesh->mat);
@@ -3207,12 +3346,17 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->mvert= newdataadr(fd, mesh->mvert);
mesh->medge= newdataadr(fd, mesh->medge);
mesh->mface= newdataadr(fd, mesh->mface);
+ mesh->mloop= newdataadr(fd, mesh->mloop);
+ mesh->mpoly= newdataadr(fd, mesh->mpoly);
mesh->tface= newdataadr(fd, mesh->tface);
mesh->mtface= newdataadr(fd, mesh->mtface);
mesh->mcol= newdataadr(fd, mesh->mcol);
mesh->msticky= newdataadr(fd, mesh->msticky);
mesh->dvert= newdataadr(fd, mesh->dvert);
-
+ mesh->mloopcol= newdataadr(fd, mesh->mloopcol);
+ mesh->mloopuv= newdataadr(fd, mesh->mloopuv);
+ mesh->mtpoly= newdataadr(fd, mesh->mtpoly);
+
/* Partial-mesh visibility (do this before using totvert, totface, or totedge!) */
mesh->pv= newdataadr(fd, mesh->pv);
if(mesh->pv) {
@@ -3229,10 +3373,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_customdata(fd, &mesh->vdata, mesh->pv ? mesh->pv->totvert : mesh->totvert);
direct_link_customdata(fd, &mesh->edata, mesh->pv ? mesh->pv->totedge : mesh->totedge);
direct_link_customdata(fd, &mesh->fdata, mesh->pv ? mesh->pv->totface : mesh->totface);
-
+ direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
+ direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
+
mesh->bb= NULL;
mesh->mselect = NULL;
- mesh->edit_mesh= NULL;
+ mesh->edit_btmesh= NULL;
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
@@ -3282,6 +3428,11 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
SWITCH_INT(tf->col[3]);
}
}
+
+ /*check if we need to convert mfaces to mpolys*/
+ if (mesh->totface && !mesh->totpoly) {
+ convert_mfaces_to_mpolys(mesh);
+ }
}
/* ************ READ LATTICE ***************** */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ebec409ddf4..c7cc1aacb18 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1404,6 +1404,8 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
write_customdata(wd, mesh->totvert, &mesh->vdata, -1, 0);
write_customdata(wd, mesh->totedge, &mesh->edata, -1, 0);
write_customdata(wd, mesh->totface, &mesh->fdata, -1, 0);
+ write_customdata(wd, mesh->totloop, &mesh->ldata, -1, 0);
+ write_customdata(wd, mesh->totpoly, &mesh->pdata, -1, 0);
}
/* PMV data */
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
new file mode 100644
index 00000000000..d7cfa9ca942
--- /dev/null
+++ b/source/blender/bmesh/SConscript
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+Import ('env')
+
+cflags=''
+"""
+sources = ['intern/bmesh_eulers.c']
+sources.append('intern/bmesh_mesh.c')
+sources.append('intern/bmesh_polygon.c')
+sources.append('intern/bmesh_structure.c')
+sources.append('intern/bmesh_marking.c')
+
+sources.append('intern/bmesh_construct.c')
+sources.append('intern/bmesh_interp.c')
+sources.append('intern/bmesh_filters.c')
+sources.append('intern/bmesh_iterators.c')
+sources.append('intern/bmesh_mods.c')
+sources.append('intern/bmesh_queries.c')
+sources.append('intern/bmesh_operators.c')
+"""
+#sources.append('api/BME_walkers.c')
+
+
+sources = env.Glob('intern/*.c')
+sources += env.Glob('operators/*.c')
+
+#sources += env.Glob('tools/*.c')
+
+incs = ['#/intern/guardedalloc']
+incs.append('../blenlib')
+incs.append('../makesdna')
+incs.append('../blenkernel')
+incs.append('./')
+incs.append('./intern')
+incs.append('../editors/mesh')
+incs.append('../editors/include')
+
+defs = []
+env.BlenderLib ( libname = 'bf_bmesh', sources = sources, includes = Split(incs), libtype = 'core', defines=defs, priority=100, compileflags=cflags )
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
new file mode 100644
index 00000000000..443e04c8711
--- /dev/null
+++ b/source/blender/bmesh/bmesh.h
@@ -0,0 +1,355 @@
+/**
+ * bmesh.h jan 2007
+ *
+ * BMesh API.
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BMESH_H
+#define BMESH_H
+
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_scene_types.h"
+#include "BLI_mempool.h"
+#include "BKE_customdata.h"
+
+/*
+short introduction:
+
+the bmesh structure is a boundary representation, supporting non-manifold
+locally modifiable topology. the API is designed to allow clean, maintainable
+code, that never (or almost never) directly inspects the underlying structure.
+
+The API includes iterators, including many useful topological iterators;
+walkers, which walk over a mesh, without the risk of hitting the recursion
+limit; operators, which are logical, reusable mesh modules; topological
+modification functions (like split face, join faces, etc), which are used for
+topological manipulations; and some (not yet finished) geometric utility
+functions.
+
+some definitions:
+
+tool flags: private flags for tools. each operator has it's own private
+ tool flag "layer", which it can use to flag elements.
+ tool flags are also used by various other parts of the api.
+header flags: stores persistent flags, such as selection state, hide state,
+ etc. be careful of touching these.
+*/
+
+/*forward declarations*/
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+struct BMLoop;
+struct BMOperator;
+struct Mesh;
+struct EditMesh;
+
+/*
+ * BMHeader
+ *
+ * All mesh elements begin with a BMHeader. This structure
+ * hold several types of data
+ *
+ * 1: The type of the element (vert, edge, loop or face)
+ * 2: Persistant flags/markings (sharp, seam, select, hidden, ect)
+ * 3: Unique ID in the bmesh.
+ * 4: some elements for internal record keeping.
+ *
+*/
+
+/*BMHeader->type*/
+#define BM_VERT 1
+#define BM_EDGE 2
+#define BM_FACE 4
+#define BM_LOOP 8
+#define BM_ALL (BM_VERT | BM_EDGE | BM_FACE | BM_LOOP)
+
+/*BMHeader->flag*/
+#define BM_SELECT (1<<0)
+
+#define BM_SEAM (1<<1)
+#define BM_FGON (1<<2)
+#define BM_HIDDEN (1<<3)
+#define BM_SHARP (1<<4)
+#define BM_SMOOTH (1<<5)
+#define BM_ACTIVE (1<<6)
+#define BM_NONORMCALC (1<<7)
+
+typedef struct BMHeader {
+ struct BMHeader *next, *prev;
+ int EID; /*Consider removing this/making it ifdeffed for debugging*/
+
+ /*don't confuse this with tool flags. this flag
+ member is what "header flag" means.*/
+ int flag;
+ int type;
+ int eflag1, eflag2; /*Flags used by eulers. Try and get rid of/minimize some of these*/
+
+ //this can only be used to store a temporary index. don't use it for anything else.
+ //use the BMINDEX_GET and BMINDEX_SET macros!!
+ int index;
+ struct BMFlagLayer *flags; /*Dynamically allocated block of flag layers for operators to use*/
+ void *data; /*customdata*/
+} BMHeader;
+
+typedef struct BMFlagLayer {
+ int f1;
+ short mask, pflag;
+} BMFlagLayer;
+
+#define BM_OVERLAP (1<<14) /*used by bmesh_verts_in_face*/
+#define BM_EDGEVERT (1<<15) /*used by bmesh_make_ngon*/
+
+/*
+ * BMNode
+ *
+ * Used for circular/linked list functions that form basis of
+ * adjacency system in BMesh. This should probably be hidden
+ * somewhere since tool authors never need to know about it.
+ *
+*/
+
+typedef struct BMNode {
+ struct BMNode *next, *prev;
+ void *data;
+} BMNode;
+
+typedef struct BMesh {
+ ListBase verts, edges, polys;
+ struct BLI_mempool *vpool;
+ struct BLI_mempool *epool;
+ struct BLI_mempool *lpool;
+ struct BLI_mempool *ppool;
+ struct BMVert **vtar;
+ struct BMEdge **edar;
+ struct BMLoop **lpar;
+ struct BMFace **plar;
+ int vtarlen, edarlen, lparlen, plarlen;
+ int totvert, totedge, totface, totloop;
+ int totvertsel, totedgesel, totfacesel;
+ int nextv, nexte, nextp, nextl;
+ struct CustomData vdata, edata, pdata, ldata;
+ int selectmode; /*now uses defines in DNA_scene_types.h*/
+ struct BLI_mempool *flagpool; /*memory pool for dynamically allocated flag layers*/
+ int stackdepth; /*current depth of operator stack*/
+ int totflags, walkers; /*total number of tool flag layers*/
+ ListBase errorstack;
+
+ /*active face pointer*/
+ struct BMFace *act_face;
+} BMesh;
+
+typedef struct BMVert {
+ struct BMHeader head;
+ float co[3];
+ float no[3];
+ struct BMEdge *edge;
+ void *tmp; /*what?*/
+ float bweight; /*please, someone just get rid of me...*/
+} BMVert;
+
+typedef struct BMEdge {
+ struct BMHeader head;
+ struct BMVert *v1, *v2;
+ struct BMNode d1, d2;
+ struct BMLoop *loop;
+ float crease, bweight; /*make these custom data.... no really, please....*/
+} BMEdge;
+
+typedef struct BMLoop {
+ struct BMHeader head;
+ struct BMNode radial;
+ struct BMVert *v;
+ struct BMEdge *e;
+ struct BMFace *f;
+} BMLoop;
+
+typedef struct BMFace {
+ struct BMHeader head;
+ struct BMLoop *loopbase;
+ int len;
+ float no[3];
+
+ /*custom data again*/
+ short mat_nr;
+} BMFace;
+
+/*stub */
+void bmesh_error(void);
+
+/*Mesh Level Ops */
+struct BMesh *BM_Make_Mesh(int allocsize[4]);
+BMesh *BM_Copy_Mesh(BMesh *bmold);
+void BM_Free_Mesh(struct BMesh *bm);
+
+/*frees mesh, but not actual BMesh struct*/
+void BM_Free_Mesh_Data(BMesh *bm);
+void BM_Compute_Normals(struct BMesh *bm);
+
+/*Construction*/
+struct BMVert *BM_Make_Vert(struct BMesh *bm, float co[3], struct BMVert *example);
+struct BMEdge *BM_Make_Edge(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge *example, int nodouble);
+struct BMFace *BM_Make_Quadtriangle(struct BMesh *bm, struct BMVert **verts, BMEdge **edges, int len, struct BMFace *example, int nodouble);
+
+/*more easier to use version of BM_Make_Quadtriangle.
+ creates edges if necassary.*/
+BMFace *BM_Make_QuadTri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3,
+ BMVert *v4, BMFace *example, int nodouble);
+
+/*makes an ngon from an unordered list of edges. v1 and v2 must be the verts
+defining edges[0], and define the winding of the new face.*/
+struct BMFace *BM_Make_Ngon(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge **edges, int len, int nodouble);
+
+/*stuff for dealing with header flags*/
+#define BM_TestHFlag(ele, f) (((BMHeader*)ele)->flag & (f))
+#define BM_SetHFlag(ele, f) (((BMHeader*)ele)->flag = ((BMHeader*)ele)->flag | (f))
+#define BM_ClearHFlag(ele, f) (((BMHeader*)ele)->flag = ((BMHeader*)ele)->flag & ~(f))
+
+/*stuff for setting indices in elements.*/
+#define BMINDEX_SET(ele, i) (((BMHeader*)ele)->index = i)
+#define BMINDEX_GET(ele) ((BMHeader*)ele)->index
+
+/*copies loop data from adjacent faces*/
+void BM_Face_CopyShared(BMesh *bm, BMFace *f);
+
+/*copies attributes, e.g. customdata, header flags, etc, from one element
+ to another of the same type.*/
+void BM_Copy_Attributes(struct BMesh *source_mesh, struct BMesh *target_mesh, void *source, void *target);
+
+/*remove tool flagged elements*/
+void BM_remove_tagged_faces(struct BMesh *bm, int flag);
+void BM_remove_tagged_edges(struct BMesh *bm, int flag);
+void BM_remove_tagged_verts(struct BMesh *bm, int flag);
+
+
+/*Modification*/
+/*join two adjacent faces together along an edge. note that
+ the faces must only be joined by on edge. e is the edge you
+ wish to dissolve.*/
+struct BMFace *BM_Join_Faces(struct BMesh *bm, struct BMFace *f1,
+ struct BMFace *f2, struct BMEdge *e);
+
+/*split a face along two vertices. returns the newly made face, and sets
+ the nl member to a loop in the newly created edge.*/
+struct BMFace *BM_Split_Face(struct BMesh *bm, struct BMFace *f,
+ struct BMVert *v1, struct BMVert *v2,
+ struct BMLoop **nl, struct BMEdge *example);
+
+/*dissolves a vert shared only by two edges*/
+void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
+ float fac);
+
+/*splits an edge. ne is set to the new edge created.*/
+struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v,
+ struct BMEdge *e, struct BMEdge **ne,
+ float percent);
+
+/*split an edge multiple times evenly*/
+struct BMVert *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e,
+ int numcuts);
+
+/*connect two verts together, through a face they share. this function may
+ be removed in the future.*/
+BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf);
+
+
+/*updates a face normal*/
+void BM_Face_UpdateNormal(BMesh *bm, BMFace *f);
+
+/*updates face and vertex normals incident on an edge*/
+void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e);
+
+/*update a vert normal (but not the faces incident on it)*/
+void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v);
+
+
+/*dissolves all faces around a vert, and removes it.*/
+int BM_Dissolve_Disk(BMesh *bm, BMVert *v);
+
+/*dissolves vert, in more situations then BM_Dissolve_Disk
+ (e.g. if the vert is part of a wire edge, etc).*/
+int BM_Dissolve_Vert(BMesh *bm, BMVert *v);
+
+
+/*Interpolation*/
+void BM_Data_Interp_From_Verts(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac);
+void BM_Data_Facevert_Edgeinterp(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac);
+//void bmesh_data_interp_from_face(struct BMesh *bm, struct BMFace *source, struct BMFace *target);
+void BM_add_data_layer(BMesh *em, CustomData *data, int type);
+void BM_free_data_layer(BMesh *em, CustomData *data, int type);
+
+
+/*computes the centroid of a face, using the center of the bounding box*/
+int BM_Compute_Face_Center(BMesh *bm, BMFace *f, float center[3]);
+void BM_SelectMode_Flush(BMesh *bm);
+
+/*convert an editmesh to a bmesh*/
+BMesh *editmesh_to_bmesh(struct EditMesh *em);
+
+/*initializes editmesh to bmesh operator, but doesn't execute.
+ this is used in situations where you need to get access to the
+ conversion operator's editmesh->bmesh mapping slot (e.g. if you
+ need to find the bmesh edge that corrusponds to a specific editmesh
+ edge).*/
+BMesh *init_editmesh_to_bmesh(struct EditMesh *em, struct BMOperator *op);
+
+/*converts a bmesh to an editmesh*/
+struct EditMesh *bmesh_to_editmesh(BMesh *bm);
+
+/*convert between bmesh and Mesh flags*/
+int BMFlags_To_MEFlags(void *element);
+
+/*convert between Mesh and bmesh flags
+ type must be BM_VERT/BM_EDGE/BM_FACE,
+ and represents the type of the element
+ parameter (the three defines map to
+ MVert, MEdge, and MPoly, respectively).*/
+int MEFlags_To_BMFlags(int flag, int type);
+
+/*convert MLoop*** in a bmface to mtface and mcol in
+ an MFace*/
+void BM_loops_to_corners(BMesh *bm, struct Mesh *me, int findex,
+ BMFace *f, int numTex, int numCol);
+
+/*include the rest of the API*/
+#include "bmesh_filters.h"
+#include "bmesh_iterators.h"
+#include "bmesh_marking.h"
+#include "bmesh_operator_api.h"
+#include "bmesh_operators.h"
+#include "bmesh_error.h"
+#include "bmesh_queries.h"
+#include "bmesh_walkers.h"
+
+#endif /* BMESH_H */
diff --git a/source/blender/bmesh/bmesh_error.h b/source/blender/bmesh/bmesh_error.h
new file mode 100644
index 00000000000..77204f57e0d
--- /dev/null
+++ b/source/blender/bmesh/bmesh_error.h
@@ -0,0 +1,53 @@
+#ifndef _BMESH_ERROR_H
+#define _BMESH_ERROR_H
+
+/*----------- bmop error system ----------*/
+
+/*pushes an error onto the bmesh error stack.
+ if msg is null, then the default message for the errorcode is used.*/
+void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg);
+
+/*gets the topmost error from the stack.
+ returns error code or 0 if no error.*/
+int BMO_GetError(BMesh *bm, char **msg, BMOperator **op);
+int BMO_HasError(BMesh *bm);
+
+/*same as geterror, only pops the error off the stack as well*/
+int BMO_PopError(BMesh *bm, char **msg, BMOperator **op);
+void BMO_ClearStack(BMesh *bm);
+
+#if 0
+//this is meant for handling errors, like self-intersection test failures.
+//it's dangerous to handle errors in general though, so disabled for now.
+
+/*catches an error raised by the op pointed to by catchop.
+ errorcode is either the errorcode, or BMERR_ALL for any
+ error.*/
+int BMO_CatchOpError(BMesh *bm, BMOperator *catchop, int errorcode, char **msg);
+#endif
+
+/*------ error code defines -------*/
+
+/*error messages*/
+#define BMERR_SELF_INTERSECTING 1
+#define BMERR_DISSOLVEDISK_FAILED 2
+#define BMERR_CONNECTVERT_FAILED 3
+#define BMERR_WALKER_FAILED 4
+#define BMERR_DISSOLVEFACES_FAILED 5
+#define BMERR_DISSOLVEVERTS_FAILED 6
+#define BMERR_TESSELATION 7
+#define BMERR_NONMANIFOLD 8
+
+static char *bmop_error_messages[] = {
+ 0,
+ "Self intersection error",
+ "Could not dissolve vert",
+ "Could not connect vertices",
+ "Could not traverse mesh",
+ "Could not dissolve faces",
+ "Could not dissolve vertices",
+ "Tesselation error",
+ "Can not deal with non-manifold geometry"
+};
+
+#endif /* _BMESH_ERROR_H */ \ No newline at end of file
diff --git a/source/blender/bmesh/bmesh_filters.h b/source/blender/bmesh/bmesh_filters.h
new file mode 100644
index 00000000000..9eed4e509fa
--- /dev/null
+++ b/source/blender/bmesh/bmesh_filters.h
@@ -0,0 +1,4 @@
+#ifndef BM_FILTER_H
+#define BM_FILTER_H
+
+#endif
diff --git a/source/blender/bmesh/bmesh_iterators.h b/source/blender/bmesh/bmesh_iterators.h
new file mode 100644
index 00000000000..7c3f91f2334
--- /dev/null
+++ b/source/blender/bmesh/bmesh_iterators.h
@@ -0,0 +1,70 @@
+/*
+ * BMESH ITERATORS
+ *
+ * The functions and structures in this file
+ * provide a unified method for iterating over
+ * the elements of a mesh and answering simple
+ * adjacency queries. Tool authors should use
+ * the iterators provided in this file instead
+ * of inspecting the structure directly.
+ *
+*/
+
+#ifndef BM_ITERATORS_H
+#define BM_ITERATORS_H
+
+/*Defines for passing to BMIter_New.
+
+ "OF" can be substituted for "around"
+ so BM_VERTS_OF_MESH_OF_FACE means "vertices
+ around a face."
+ */
+
+/*these iterator over all elements of a specific
+ type in the mesh.*/
+#define BM_VERTS_OF_MESH 1
+#define BM_EDGES_OF_MESH 2
+#define BM_FACES_OF_MESH 3
+
+#define BM_ITER(ele, iter, bm, type, data) \
+ ele = BMIter_New(iter, bm, type, data); \
+ for ( ; ele; ele=BMIter_Step(iter))
+
+/*these are topological iterators.*/
+#define BM_EDGES_OF_VERT 4
+#define BM_FACES_OF_VERT 5
+#define BM_FACES_OF_EDGE 6
+#define BM_VERTS_OF_FACE 7
+#define BM_FACEVERTS_OF_FACE 8
+#define BM_EDGES_OF_FACE 9
+#define BM_LOOPS_OF_FACE 10
+
+/*iterate through loops around this loop, which are fetched
+ from the other faces in the radial cycle surrounding the
+ input loop's edge.*/
+#define BM_LOOPS_OF_LOOP 11
+
+
+/*Iterator Structure*/
+typedef struct BMIter{
+ struct BMVert *firstvert, *nextvert, *vdata;
+ struct BMEdge *firstedge, *nextedge, *edata;
+ struct BMLoop *firstloop, *nextloop, *ldata, *l;
+ struct BMFace *firstpoly, *nextpoly, *pdata;
+ struct BMesh *bm;
+ void (*begin)(struct BMIter *iter);
+ void *(*step)(struct BMIter *iter);
+ union{
+ void *p;
+ int i;
+ long l;
+ float f;
+ }filter;
+ int type, count;
+}BMIter;
+
+void *BMIter_New(struct BMIter *iter, struct BMesh *bm, int type, void *data);
+void *BMIter_Step(struct BMIter *iter);
+void *BMIter_AtIndex(struct BMesh *bm, int type, void *data, int index);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_marking.h b/source/blender/bmesh/bmesh_marking.h
new file mode 100644
index 00000000000..1074b057eba
--- /dev/null
+++ b/source/blender/bmesh/bmesh_marking.h
@@ -0,0 +1,16 @@
+#ifndef BM_MARKING_H
+#define BM_MARKING_H
+
+/*Selection code*/
+void BM_Select_Vert(struct BMesh *bm, struct BMVert *v, int select);
+void BM_Select_Edge(struct BMesh *bm, struct BMEdge *e, int select);
+void BM_Select_Face(struct BMesh *bm, struct BMFace *f, int select);
+void BM_Selectmode_Set(struct BMesh *bm, int selectmode);
+
+/*counts number of elements with flag set*/
+int BM_CountFlag(struct BMesh *bm, int type, int flag);
+
+void BM_Select(struct BMesh *bm, void *element, int select);
+int BM_Is_Selected(BMesh *bm, void *element);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_operator_api.h b/source/blender/bmesh/bmesh_operator_api.h
new file mode 100644
index 00000000000..0c0e0db0e6e
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operator_api.h
@@ -0,0 +1,338 @@
+#ifndef _BMESH_OPERATOR_H
+#define _BMESH_OPERATOR_H
+
+#include "BLI_memarena.h"
+#include "BLI_ghash.h"
+
+#include <stdarg.h>
+
+/*
+operators represent logical, executable mesh modules. all topological
+operations involving a bmesh has to go through them.
+
+operators are nested, as are tool flags, which are private to an operator
+when it's executed. tool flags are allocated in layers, one per operator
+execution, and are used for all internal flagging a tool needs to do.
+
+each operator has a series of "slots," which can be of the following types:
+* simple numerical types
+* arrays of elements (e.g. arrays of faces).
+* hash mappings.
+
+each slot is identified by a slot code, as are each operator.
+operators, and their slots, are defined in bmesh_opdefines.c (with their
+execution functions prototyped in bmesh_operators_private.h), with all their
+operator code and slot codes defined in bmesh_operators.h. see
+bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
+
+in general, operators are fed arrays of elements, created using either
+BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
+specifyers in BMO_CallOpf or BMO_InitOpf). Note that multiple element
+types (e.g. faces and edges) can be fed to the same slot array. Operators
+act on this data, and possibly spit out data into output slots.
+
+some notes:
+* operators should never read from header flags (e.g. element->head.flag). for
+ example, if you want an operator to only operate on selected faces, you
+ should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
+* when you read from an element slot array or mapping, you can either tool-flag
+ all the elements in it, or read them using an iterator APi (which is
+ semantically similar to the iterator api in bmesh_iterators.h).
+*/
+
+struct GHashIterator;
+
+/*slot type arrays are terminated by the last member
+ having a slot type of 0.*/
+#define BMOP_OPSLOT_SENTINEL 0
+#define BMOP_OPSLOT_INT 1
+#define BMOP_OPSLOT_FLT 2
+#define BMOP_OPSLOT_PNT 3
+#define BMOP_OPSLOT_MAT 4
+#define BMOP_OPSLOT_VEC 7
+
+/*after BMOP_OPSLOT_VEC, everything is
+
+ dynamically allocated arrays. we
+ leave a space in the identifiers
+ for future growth.
+
+ */
+//it's very important this remain a power of two
+#define BMOP_OPSLOT_ELEMENT_BUF 8
+#define BMOP_OPSLOT_MAPPING 9
+#define BMOP_OPSLOT_TYPES 10
+
+/*please ignore all these structures, don't touch them in tool code, except
+ for when your defining an operator with BMOpDefine.*/
+
+typedef struct BMOpSlot{
+ int slottype;
+ int len;
+ int flag;
+ int index; /*index within slot array*/
+ union {
+ int i;
+ float f;
+ void *p;
+ float vec[3];
+ void *buf;
+ GHash *ghash;
+ } data;
+}BMOpSlot;
+
+#define BMOP_MAX_SLOTS 16 /*way more than probably needed*/
+
+typedef struct BMOperator {
+ int type;
+ int slottype;
+ int needflag;
+ struct BMOpSlot slots[BMOP_MAX_SLOTS];
+ void (*exec)(struct BMesh *bm, struct BMOperator *op);
+ MemArena *arena;
+} BMOperator;
+
+#define MAX_SLOTNAME 32
+
+typedef struct slottype {
+ int type;
+ char name[MAX_SLOTNAME];
+} slottype;
+
+typedef struct BMOpDefine {
+ char *name;
+ slottype slottypes[BMOP_MAX_SLOTS];
+ void (*exec)(BMesh *bm, BMOperator *op);
+ int flag; /*doesn't do anything right now*/
+} BMOpDefine;
+
+/*------------- Operator API --------------*/
+
+/*data types that use pointers (arrays, etc) should never
+ have it set directly. and never use BMO_Set_Pnt to
+ pass in a list of edges or any arrays, really.*/
+
+void BMO_Init_Op(struct BMOperator *op, char *opname);
+
+/*executes an operator, pushing and popping a new tool flag
+ layer as appropriate.*/
+void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
+
+/*finishes an operator (though note the operator's tool flag is removed
+ after it finishes executing in BMO_Exec_Op).*/
+void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
+
+
+/*tool flag API. never, ever ever should tool code put junk in
+ header flags (element->head.flag), nor should they use
+ element->head.eflag1/eflag2. instead, use this api to set
+ flags.
+
+ if you need to store a value per element, use a
+ ghash or a mapping slot to do it.*/
+/*flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use*/
+void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
+void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
+int BMO_TestFlag(struct BMesh *bm, void *element, int flag);
+
+/*count the number of elements with a specific flag. type
+ can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE.*/
+int BMO_CountFlag(struct BMesh *bm, int flag, int type);
+
+/*---------formatted operator initialization/execution-----------*/
+/*
+ this system is used to execute or initialize an operator,
+ using a formatted-string system.
+
+ for example, BMO_CallOpf(bm, "del geom=%hf context=%d", BM_SELECT, DEL_FACES);
+ . . .will execute the delete operator, feeding in selected faces, deleting them.
+
+ the basic format for the format string is:
+ [operatorname] [slotname]=%[code] [slotname]=%[code]
+
+ as in printf, you pass in one additional argument to the function
+ for every code.
+
+ the formatting codes are:
+ %d - put int in slot
+ %f - put float in slot
+ %p - put pointer in slot
+ %h[f/e/v] - put elements with a header flag in slot.
+ the letters after %h define which element types to use,
+ so e.g. %hf will do faces, %hfe will do faces and edges,
+ %hv will do verts, etc. must pass in at least one
+ element type letter.
+ %f[f/e/v] - same as %h, except it deals with tool flags instead of
+ header flags.
+ %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
+ slot.
+ %v - pointer to a float vector of length 3.
+ %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the
+ corrusponding argument must be a pointer to
+ a float matrix.
+ %s - copy a slot from another op, instead of mapping to one
+ argument, it maps to two, a pointer to an operator and
+ a slot name.
+*/
+/*executes an operator*/
+int BMO_CallOpf(BMesh *bm, char *fmt, ...);
+
+/*initializes, but doesn't execute an operator. this is so you can
+ gain access to the outputs of the operator. note that you have
+ to execute/finitsh (BMO_Exec_Op and BMO_Finish_Op) yourself.*/
+int BMO_InitOpf(BMesh *bm, BMOperator *op, char *fmt, ...);
+
+/*va_list version, used to implement the above two functions,
+ plus EDBM_CallOpf in bmeshutils.c.*/
+int BMO_VInitOpf(BMesh *bm, BMOperator *op, char *fmt, va_list vlist);
+
+/*get a point to a slot. this may be removed layer on from the public API.*/
+BMOpSlot *BMO_GetSlot(struct BMOperator *op, char *slotname);
+
+/*copies the data of a slot from one operator to another. src and dst are the
+ source/destination slot codes, respectively.*/
+void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op,
+ char *src, char *dst);
+
+
+void BMO_Set_Float(struct BMOperator *op, char *slotname, float f);
+float BMO_Get_Float(BMOperator *op, char *slotname);
+void BMO_Set_Int(struct BMOperator *op, char *slotname, int i);
+int BMO_Get_Int(BMOperator *op, char *slotname);
+
+/*don't pass in arrays that are supposed to map to elements this way.
+
+ so, e.g. passing in list of floats per element in another slot is bad.
+ passing in, e.g. pointer to an editmesh for the conversion operator is fine
+ though.*/
+void BMO_Set_Pnt(struct BMOperator *op, char *slotname, void *p);
+void *BMO_Get_Pnt(BMOperator *op, char *slotname);
+void BMO_Set_Vec(struct BMOperator *op, char *slotname, float *vec);
+void BMO_Get_Vec(BMOperator *op, char *slotname, float *vec_out);
+
+/*only supports square mats*/
+/*size must be 3 or 4; this api is meant only for transformation matrices.
+ note that internally the matrix is stored in 4x4 form, and it's safe to
+ call whichever BMO_Get_Mat* function you want.*/
+void BMO_Set_Mat(struct BMOperator *op, char *slotname, float *mat, int size);
+void BMO_Get_Mat4(struct BMOperator *op, char *slotname, float mat[4][4]);
+void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3]);
+
+/*puts every element of type type (which is a bitmask) with tool flag flag,
+ into a slot.*/
+void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
+
+/*tool-flags all elements inside an element slot array with flag flag.*/
+void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
+/*clears tool-flag flag from all elements inside a slot array.*/
+void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
+
+/*tool-flags all elements inside an element slot array with flag flag.*/
+void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
+/*clears tool-flag flag from all elements inside a slot array.*/
+void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag);
+
+/*puts every element of type type (which is a bitmask) with header flag
+ flag, into a slot.*/
+void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
+
+/*counts number of elements inside a slot array.*/
+int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, char *slotname);
+
+
+/*inserts a key/value mapping into a mapping slot. note that it copies the
+ value, it doesn't store a reference to it.*/
+void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, void *data, int len);
+
+/*inserts a key/float mapping pair into a mapping slot.*/
+void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, float val);
+
+//returns 1 if the specified pointer is in the map.
+int BMO_InMap(BMesh *bm, BMOperator *op, char *slotname, void *element);
+
+/*returns a point to the value of a specific key.*/
+void *BMO_Get_MapData(BMesh *bm, BMOperator *op, char *slotname, void *element);
+
+/*returns the float part of a key/float pair.*/
+float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, char *slotname, void *element);
+
+/*flags all elements in a mapping. note that the mapping must only have
+ bmesh elements in it.*/
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
+ char *slotname, int flag);
+
+/*pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
+
+ do NOT use these for non-operator-api-allocated memory! instead
+ use BMO_Get_MapData and BMO_Insert_Mapping, which copies the data.*/
+void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ void *key, void *val);
+void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ void *key);
+
+/*this part of the API is used to iterate over element buffer or
+ mapping slots.
+
+ for example, iterating over the faces in a slot is:
+
+ BMOIter oiter;
+ BMFace *f;
+
+ f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
+ for (; f; f=BMO_IterStep(&oiter)) {
+ /do something with the face
+ }
+
+ another example, iterating over a mapping:
+ BMOIter oiter;
+ void *key;
+ void *val;
+
+ key = BMO_IterNew(&oiter, bm, some_operator, "slotname", 0);
+ for (; key; key=BMO_IterStep(&oiter)) {
+ val = BMO_IterMapVal(&oiter);
+ //do something with the key/val pair
+ //note that val is a pointer to the val data,
+ //whether it's a float, pointer, whatever.
+ //
+ // so to get a pointer, for example, use:
+ // *((void**)BMO_IterMapVal(&oiter));
+ //or something like that.
+ }
+
+ */
+
+/*contents of this structure are private,
+ don't directly access.*/
+typedef struct BMOIter {
+ BMOpSlot *slot;
+ int cur; //for arrays
+ struct GHashIterator giter;
+ void *val;
+ int restrict;
+} BMOIter;
+
+/*restrictmask restricts the iteration to certain element types
+ (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
+ over an element buffer (not a mapping).*/
+void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op,
+ char *slotname, int restrictmask);
+void *BMO_IterStep(BMOIter *iter);
+
+/*returns a pointer to the key value when iterating over mappings.
+ remember for pointer maps this will be a pointer to a pointer.*/
+void *BMO_IterMapVal(BMOIter *iter);
+
+/*use this for pointer mappings*/
+void *BMO_IterMapValp(BMOIter *iter);
+
+/*use this for float mappings*/
+float BMO_IterMapValf(BMOIter *iter);
+
+#define BMO_ITER(ele, iter, bm, op, slotname, restrict) \
+ ele = BMO_IterNew(iter, bm, op, slotname, restrict); \
+ for ( ; ele; ele=BMO_IterStep(iter))
+
+#endif /* _BMESH_OPERATOR_H */ \ No newline at end of file
diff --git a/source/blender/bmesh/bmesh_operators.h b/source/blender/bmesh/bmesh_operators.h
new file mode 100644
index 00000000000..3ef229f00c6
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operators.h
@@ -0,0 +1,40 @@
+#ifndef BM_OPERATORS_H
+#define BM_OPERATORS_H
+
+/*--------defines/enumerations for specific operators-------*/
+
+/*del operator "context" slot values*/
+enum {
+ DEL_VERTS = 1,
+ DEL_EDGES,
+ DEL_ONLYFACES,
+ DEL_EDGESFACES,
+ DEL_FACES,
+ DEL_ALL ,
+ DEL_ONLYTAGGED,
+};
+
+extern BMOpDefine *opdefines[];
+extern int bmesh_total_ops;
+
+/*------specific operator helper functions-------*/
+
+/*executes the duplicate operation, feeding elements of
+ type flag etypeflag and header flag flag to it. note,
+ to get more useful information (such as the mapping from
+ original to new elements) you should run the dupe op manually.*/
+struct Object;
+struct EditMesh;
+
+void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
+void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth,
+ float fractal, int beauty, int numcuts, int seltype);
+void BM_extrudefaceflag(BMesh *bm, int flag);
+
+/*this next one return 1 if they did anything, or zero otherwise.
+ they're kindof a hackish way to integrate with fkey, until
+ such time as fkey is completely bmeshafied.*/
+/*this doesn't display errors to the user, btw*/
+int BM_ConnectVerts(struct EditMesh *em, int flag);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_queries.h b/source/blender/bmesh/bmesh_queries.h
new file mode 100644
index 00000000000..ee2b8605a17
--- /dev/null
+++ b/source/blender/bmesh/bmesh_queries.h
@@ -0,0 +1,86 @@
+#ifndef BMESH_QUERIES_H
+#define BMESH_QUERIES_H
+#include <stdio.h>
+
+/*Queries*/
+/*counts number of elements of type type are in the mesh.*/
+int BM_Count_Element(struct BMesh *bm, int type);
+
+/*returns true if v is in f*/
+int BM_Vert_In_Face(struct BMFace *f, struct BMVert *v);
+
+// int BM_VERTS_OF_MESH_In_Face(struct BMFace *f, struct BMVert **varr, int len);
+int BM_Verts_In_Face(struct BMesh *bm, struct BMFace *f, struct BMVert **varr, int len);
+
+int BM_Edge_In_Face(struct BMFace *f, struct BMEdge *e);
+
+int BM_Vert_In_Edge(struct BMVert *v1, struct BMVert *v2, BMEdge *e);
+
+
+/*get opposing vert from v in edge e.*/
+struct BMVert *BM_OtherEdgeVert(struct BMEdge *e, struct BMVert *v);
+
+/*finds other loop that shares v with e's loop in f.*/
+struct BMLoop *BM_OtherFaceLoop(BMEdge *e, BMFace *f, BMVert *v);
+
+//#define BM_OtherEdgeVert(e, v) (v==e->v1?e->v2:e->v1)
+
+/*returns the edge existing between v1 and v2, or NULL if there isn't one.*/
+struct BMEdge *BM_Edge_Exist(struct BMVert *v1, struct BMVert *v2);
+
+
+/*returns number of edges aroudn a vert*/
+int BM_Vert_EdgeCount(struct BMVert *v);
+
+/*returns number of faces around an edge*/
+int BM_Edge_FaceCount(struct BMEdge *e);
+
+/*returns number of faces around a vert.*/
+int BM_Vert_FaceCount(struct BMVert *v);
+
+
+/*returns true if v is a wire vert*/
+int BM_Wire_Vert(struct BMesh *bm, struct BMVert *v);
+
+/*returns true if e is a wire edge*/
+int BM_Wire_Edge(struct BMesh *bm, struct BMEdge *e);
+
+/*returns true if v is part of a non-manifold edge in the mesh,
+ I believe this includes if it's part of both a wire edge and
+ a face.*/
+int BM_Nonmanifold_Vert(struct BMesh *bm, struct BMVert *v);
+
+/*returns true if e is shared by more then two faces.*/
+int BM_Nonmanifold_Edge(struct BMesh *bm, struct BMEdge *e);
+
+/*returns true if e is a boundary edge, e.g. has only 1 face bordering it.*/
+int BM_Boundary_Edge(struct BMEdge *e);
+
+
+/*returns angle of two faces surrounding an edge. note there must be
+ exactly two faces sharing the edge.*/
+float BM_Face_Angle(struct BMesh *bm, struct BMEdge *e);
+
+/*checks overlapping of existing faces with the verts in varr.*/
+int BM_Exist_Face_Overlaps(struct BMesh *bm, struct BMVert **varr, int len, struct BMFace **existface);
+
+/*checks if a face defined by varr already exists.*/
+int BM_Face_Exists(BMesh *bm, BMVert **varr, int len, BMFace **existface);
+
+
+/*returns number of edges f1 and f2 share.*/
+int BM_Face_Sharededges(struct BMFace *f1, struct BMFace *f2);
+
+/*returns number of faces e1 and e2 share.*/
+int BM_Edge_Share_Faces(struct BMEdge *e1, struct BMEdge *e2);
+
+/*checks if a face is valid in the data structure*/
+int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err);
+
+/*each pair of loops defines a new edge, a split. this function goes
+ through and sets pairs that are geometrically invalid to null. a
+ split is invalid, if it forms a concave angle or it intersects other
+ edges in the face.*/
+void BM_LegalSplits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_walkers.h b/source/blender/bmesh/bmesh_walkers.h
new file mode 100644
index 00000000000..2fdb9e18a3a
--- /dev/null
+++ b/source/blender/bmesh/bmesh_walkers.h
@@ -0,0 +1,64 @@
+#ifndef BM_WALKERS_H
+#define BM_WALKERS_H
+
+#include "BLI_ghash.h"
+
+/*
+ NOTE: do NOT modify topology while walking a mesh!
+*/
+
+/*Walkers*/
+typedef struct BMWalker {
+ BLI_mempool *stack;
+ BMesh *bm;
+ void *currentstate;
+ void (*begin) (struct BMWalker *walker, void *start);
+ void *(*yield)(struct BMWalker *walker);
+ void *(*step) (struct BMWalker *walker);
+ int restrictflag;
+ GHash *visithash;
+} BMWalker;
+
+/*initialize a walker. searchmask restricts some (not all) walkers to
+ elements with a specific tool flag set.*/
+void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask);
+void *BMW_Begin(BMWalker *walker, void *start);
+void *BMW_Step(struct BMWalker *walker);
+void BMW_End(struct BMWalker *walker);
+
+/*
+example of usage, walking over an island of tool flagged faces:
+
+BMWalker walker;
+BMFace *f;
+
+BMW_Init(&walker, bm, BMW_ISLAND, SOME_OP_FLAG);
+f = BMW_Begin(&walker, some_start_face);
+for (; f; f=BMW_Step(&walker)) {
+ //do something with f
+}
+BMW_End(&walker);
+*/
+
+enum {
+ /*walk over connected geometry. can restrict to a search flag,
+ or not, it's optional.*/
+ BMW_SHELL,
+ /*walk over an edge loop. search flag doesn't do anything.*/
+ BMW_LOOP,
+ BMW_FACELOOP,
+ BMW_EDGERING,
+ /*#define BMW_RING 2
+ #define BMW_UVISLANDS 3*/
+ /*walk over an island of flagged faces. note, that this doesn't work on
+ non-manifold geometry. it might be better to rewrite this to extract
+ boundary info from the island walker, rather then directly walking
+ over the boundary. raises an error if it encouters nonmanifold
+ geometry.*/
+ BMW_ISLANDBOUND,
+ /*walk over all faces in an island of tool flagged faces.*/
+ BMW_ISLAND,
+ BMW_MAXWALKERS,
+};
+
+#endif \ No newline at end of file
diff --git a/source/blender/bmesh/editmesh_tools.c b/source/blender/bmesh/editmesh_tools.c
new file mode 100644
index 00000000000..e2b83c6e111
--- /dev/null
+++ b/source/blender/bmesh/editmesh_tools.c
@@ -0,0 +1,7244 @@
+/**
+ * $Id:
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Johnny Matthews, Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
+#include "BIF_cursors.h"
+#include "BIF_editmesh.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_resources.h"
+#include "BIF_toolbox.h"
+#include "BIF_transform.h"
+#include "transform.h"
+
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+
+#include "blendef.h"
+#include "multires.h"
+#include "mydevice.h"
+
+#include "editmesh.h"
+
+#include "MTC_vectorops.h"
+
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* local prototypes ---------------*/
+void bevel_menu(void);
+static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa);
+
+/********* qsort routines *********/
+
+
+typedef struct xvertsort {
+ float x;
+ EditVert *v1;
+} xvertsort;
+
+static int vergxco(const void *v1, const void *v2)
+{
+ const xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct facesort {
+ uintptr_t x;
+ struct EditFace *efa;
+};
+
+
+static int vergface(const void *v1, const void *v2)
+{
+ const struct facesort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+
+/* *********************************** */
+
+void convert_to_triface(int direction)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa, *efan, *next;
+ float fac;
+
+ if(multires_test()) return;
+
+ efa= em->faces.last;
+ while(efa) {
+ next= efa->prev;
+ if(efa->v4) {
+ if(efa->f & SELECT) {
+ /* choose shortest diagonal for split */
+ fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
+ /* this makes sure exact squares get split different in both cases */
+ if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
+ efan= EM_face_from_faces(efa, NULL, 0, 1, 2, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ efan= EM_face_from_faces(efa, NULL, 0, 2, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ }
+ else {
+ efan= EM_face_from_faces(efa, NULL, 0, 1, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ efan= EM_face_from_faces(efa, NULL, 1, 2, 3, -1);
+ if(efa->f & SELECT) EM_select_face(efan, 1);
+ }
+
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ }
+ efa= next;
+ }
+
+ EM_fgon_flags(); // redo flags and indices for fgons
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Convert Quads to Triangles");
+
+}
+
+int removedoublesflag(short flag, short automerge, float limit) /* return amount */
+{
+ /*
+ flag - Test with vert->flags
+ automerge - Alternative operation, merge unselected into selected.
+ Used for "Auto Weld" mode. warning.
+ limit - Quick manhattan distance between verts.
+ */
+
+ EditMesh *em = G.editMesh;
+ /* all verts with (flag & 'flag') are being evaluated */
+ EditVert *eve, *v1, *nextve;
+ EditEdge *eed, *e1, *nexted;
+ EditFace *efa, *nextvl;
+ xvertsort *sortblock, *sb, *sb1;
+ struct facesort *vlsortblock, *vsb, *vsb1;
+ int a, b, test, amount;
+
+ if(multires_test()) return 0;
+
+
+ /* flag 128 is cleared, count */
+
+ /* Normal non weld operation */
+ eve= em->verts.first;
+ amount= 0;
+ while(eve) {
+ eve->f &= ~128;
+ if(eve->h==0 && (automerge || (eve->f & flag))) amount++;
+ eve= eve->next;
+ }
+ if(amount==0) return 0;
+
+ /* allocate memory and qsort */
+ sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->h==0 && (automerge || (eve->f & flag))) {
+ sb->x= eve->co[0]+eve->co[1]+eve->co[2];
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+
+ /* test for doubles */
+ sb= sortblock;
+ if (automerge) {
+ for(a=0; a<amount; a++, sb++) {
+ eve= sb->v1;
+ if( (eve->f & 128)==0 ) {
+ sb1= sb+1;
+ for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
+ if(sb1->x - sb->x > limit) break;
+
+ /* when automarge, only allow unselected->selected */
+ v1= sb1->v1;
+ if( (v1->f & 128)==0 ) {
+ if ((eve->f & flag)==0 && (v1->f & flag)==1) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ { /* unique bit */
+ eve->f|= 128;
+ eve->tmp.v = v1;
+ }
+ } else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ { /* unique bit */
+ v1->f|= 128;
+ v1->tmp.v = eve;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ for(a=0; a<amount; a++, sb++) {
+ eve= sb->v1;
+ if( (eve->f & 128)==0 ) {
+ sb1= sb+1;
+ for(b=a+1; b<amount; b++, sb1++) {
+ /* first test: simpel dist */
+ if(sb1->x - sb->x > limit) break;
+ v1= sb1->v1;
+
+ /* second test: is vertex allowed */
+ if( (v1->f & 128)==0 ) {
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ (float)fabs(v1->co[1]-eve->co[1])<=limit &&
+ (float)fabs(v1->co[2]-eve->co[2])<=limit)
+ {
+ v1->f|= 128;
+ v1->tmp.v = eve;
+ }
+ }
+ }
+ }
+ }
+ }
+ MEM_freeN(sortblock);
+
+ if (!automerge)
+ for(eve = em->verts.first; eve; eve=eve->next)
+ if((eve->f & flag) && (eve->f & 128))
+ EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
+
+ /* test edges and insert again */
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= 0;
+ eed= eed->next;
+ }
+ eed= em->edges.last;
+ while(eed) {
+ nexted= eed->prev;
+
+ if(eed->f2==0) {
+ if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
+ remedge(eed);
+
+ if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
+ if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
+ e1= addedgelist(eed->v1, eed->v2, eed);
+
+ if(e1) {
+ e1->f2= 1;
+ if(eed->f & SELECT)
+ e1->f |= SELECT;
+ }
+ if(e1!=eed) free_editedge(eed);
+ }
+ }
+ eed= nexted;
+ }
+
+ /* first count amount of test faces */
+ efa= (struct EditFace *)em->faces.first;
+ amount= 0;
+ while(efa) {
+ efa->f1= 0;
+ if(efa->v1->f & 128) efa->f1= 1;
+ else if(efa->v2->f & 128) efa->f1= 1;
+ else if(efa->v3->f & 128) efa->f1= 1;
+ else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
+
+ if(efa->f1==1) amount++;
+ efa= efa->next;
+ }
+
+ /* test faces for double vertices, and if needed remove them */
+ efa= (struct EditFace *)em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1==1) {
+
+ if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
+ if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
+ if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
+ if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
+
+ test= 0;
+ if(efa->v1==efa->v2) test+=1;
+ if(efa->v2==efa->v3) test+=2;
+ if(efa->v3==efa->v1) test+=4;
+ if(efa->v4==efa->v1) test+=8;
+ if(efa->v3==efa->v4) test+=16;
+ if(efa->v2==efa->v4) test+=32;
+
+ if(test) {
+ if(efa->v4) {
+ if(test==1 || test==2) {
+ efa->v2= efa->v3;
+ efa->v3= efa->v4;
+ efa->v4= 0;
+
+ EM_data_interp_from_faces(efa, NULL, efa, 0, 2, 3, 3);
+
+ test= 0;
+ }
+ else if(test==8 || test==16) {
+ efa->v4= 0;
+ test= 0;
+ }
+ else {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ amount--;
+ }
+ }
+ else {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ amount--;
+ }
+ }
+
+ if(test==0) {
+ /* set edge pointers */
+ efa->e1= findedgelist(efa->v1, efa->v2);
+ efa->e2= findedgelist(efa->v2, efa->v3);
+ if(efa->v4==0) {
+ efa->e3= findedgelist(efa->v3, efa->v1);
+ efa->e4= 0;
+ }
+ else {
+ efa->e3= findedgelist(efa->v3, efa->v4);
+ efa->e4= findedgelist(efa->v4, efa->v1);
+ }
+ }
+ }
+ efa= nextvl;
+ }
+
+ /* double faces: sort block */
+ /* count again, now all selected faces */
+ amount= 0;
+ efa= em->faces.first;
+ while(efa) {
+ efa->f1= 0;
+ if(faceselectedOR(efa, 1)) {
+ efa->f1= 1;
+ amount++;
+ }
+ efa= efa->next;
+ }
+
+ if(amount) {
+ /* double faces: sort block */
+ vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub");
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f1 & 1) {
+ if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4);
+ else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3);
+
+ vsb->efa= efa;
+ vsb++;
+ }
+ efa= efa->next;
+ }
+
+ qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
+
+ vsb= vlsortblock;
+ for(a=0; a<amount; a++) {
+ efa= vsb->efa;
+ if( (efa->f1 & 128)==0 ) {
+ vsb1= vsb+1;
+
+ for(b=a+1; b<amount; b++) {
+
+ /* first test: same pointer? */
+ if(vsb->x != vsb1->x) break;
+
+ /* second test: is test permitted? */
+ efa= vsb1->efa;
+ if( (efa->f1 & 128)==0 ) {
+ if( compareface(efa, vsb->efa)) efa->f1 |= 128;
+
+ }
+ vsb1++;
+ }
+ }
+ vsb++;
+ }
+
+ MEM_freeN(vlsortblock);
+
+ /* remove double faces */
+ efa= (struct EditFace *)em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1 & 128) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ efa= nextvl;
+ }
+ }
+
+ /* remove double vertices */
+ a= 0;
+ eve= (struct EditVert *)em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(automerge || eve->f & flag) {
+ if(eve->f & 128) {
+ a++;
+ BLI_remlink(&em->verts, eve);
+ free_editvert(eve);
+ }
+ }
+ eve= nextve;
+ }
+
+#ifdef WITH_VERSE
+ if((a>0) && (G.editMesh->vnode)) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ }
+#endif
+
+ return a; /* amount */
+}
+
+/* called from buttons */
+static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
+{
+ xvertsort *sortblock = userData;
+
+ sortblock[index].x = x;
+}
+void xsortvert_flag(int flag)
+{
+ EditMesh *em = G.editMesh;
+ /* all verts with (flag & 'flag') are sorted */
+ EditVert *eve;
+ xvertsort *sortblock;
+ ListBase tbase;
+ int i, amount = BLI_countlist(&em->verts);
+
+ if(multires_test()) return;
+
+ sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
+ for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
+ if(eve->f & flag)
+ sortblock[i].v1 = eve;
+ mesh_foreachScreenVert(xsortvert_flag__doSetX, sortblock, 0);
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ for (i=0; i<amount; i++) {
+ eve = sortblock[i].v1;
+
+ if (eve) {
+ BLI_remlink(&em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ }
+ }
+
+ addlisttolist(&em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
+ BIF_undo_push("Xsort");
+
+}
+
+/* called from buttons */
+void hashvert_flag(int flag)
+{
+ /* switch vertex order using hash table */
+ EditMesh *em = G.editMesh;
+ EditVert *eve;
+ struct xvertsort *sortblock, *sb, onth, *newsort;
+ ListBase tbase;
+ int amount, a, b;
+
+ if(multires_test()) return;
+
+ /* count */
+ eve= em->verts.first;
+ amount= 0;
+ while(eve) {
+ if(eve->f & flag) amount++;
+ eve= eve->next;
+ }
+ if(amount==0) return;
+
+ /* allocate memory */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+
+ BLI_srand(1);
+
+ sb= sortblock;
+ for(a=0; a<amount; a++, sb++) {
+ b= (int)(amount*BLI_drand());
+ if(b>=0 && b<amount) {
+ newsort= sortblock+b;
+ onth= *sb;
+ *sb= *newsort;
+ *newsort= onth;
+ }
+ }
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ sb= sortblock;
+ while(amount--) {
+ eve= sb->v1;
+ BLI_remlink(&em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ sb++;
+ }
+
+ addlisttolist(&em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Hash");
+
+}
+
+/* generic extern called extruder */
+void extrude_mesh(void)
+{
+ float nor[3]= {0.0, 0.0, 0.0};
+ short nr, transmode= 0;
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+ if(G.totvertsel==0) nr= 0;
+ else if(G.totvertsel==1) nr= 4;
+ else if(G.totedgesel==0) nr= 4;
+ else if(G.totfacesel==0)
+ nr= pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ else if(G.totfacesel==1)
+ nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ }
+ else if(G.scene->selectmode & SCE_SELECT_EDGE) {
+ if (G.totedgesel==0) nr = 0;
+ else if (G.totedgesel==1) nr = 3;
+ else if(G.totfacesel==0) nr = 3;
+ else if(G.totfacesel==1)
+ nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ }
+ else {
+ if (G.totfacesel == 0) nr = 0;
+ else if (G.totfacesel == 1) nr = 1;
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ }
+
+ if(nr<1) return;
+
+ if(nr==1) transmode= extrudeflag(SELECT, nor);
+ else if(nr==4) transmode= extrudeflag_verts_indiv(SELECT, nor);
+ else if(nr==3) transmode= extrudeflag_edges_indiv(SELECT, nor);
+ else transmode= extrudeflag_face_indiv(SELECT, nor);
+
+ if(transmode==0) {
+ error("No valid selection");
+ }
+ else {
+ EM_fgon_flags();
+ countall();
+
+ /* We need to force immediate calculation here because
+ * transform may use derived objects (which are now stale).
+ *
+ * This shouldn't be necessary, derived queries should be
+ * automatically building this data if invalid. Or something.
+ */
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ object_handle_update(G.obedit);
+
+ /* individual faces? */
+ BIF_TransformSetUndo("Extrude");
+ if(nr==2) {
+ initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
+ Transform();
+ }
+ else {
+ initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
+ if(transmode=='n') {
+ Mat4MulVecfl(G.obedit->obmat, nor);
+ VecSubf(nor, nor, G.obedit->obmat[3]);
+ BIF_setSingleAxisConstraint(nor, "along normal");
+ }
+ Transform();
+ }
+ }
+
+}
+
+void split_mesh(void)
+{
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ if(okee(" Split ")==0) return;
+
+ waitcursor(1);
+
+ /* make duplicate first */
+ adduplicateflag(SELECT);
+ /* old faces have flag 128 set, delete them */
+ delfaceflag(128);
+ recalc_editnormals();
+
+ waitcursor(0);
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
+ BIF_undo_push("Split");
+
+}
+
+void extrude_repeat_mesh(int steps, float offs)
+{
+ float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
+ short a;
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ /* dvec */
+ dvec[0]= G.vd->persinv[2][0];
+ dvec[1]= G.vd->persinv[2][1];
+ dvec[2]= G.vd->persinv[2][2];
+ Normalize(dvec);
+ dvec[0]*= offs;
+ dvec[1]*= offs;
+ dvec[2]*= offs;
+
+ /* base correction */
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(tmat, bmat);
+ Mat3MulVecfl(tmat, dvec);
+
+ for(a=0; a<steps; a++) {
+ extrudeflag(SELECT, nor);
+ translateflag(SELECT, dvec);
+ }
+
+ recalc_editnormals();
+
+ EM_fgon_flags();
+ countall();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+ BIF_undo_push("Extrude Repeat");
+}
+
+void spin_mesh(int steps, float degr, float *dvec, int mode)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *eve,*nextve;
+ float nor[3]= {0.0, 0.0, 0.0};
+ float *curs, si,n[3],q[4],cmat[3][3],imat[3][3], tmat[3][3];
+ float cent[3],bmat[3][3];
+ float phi;
+ short a,ok;
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ /* imat and center and size */
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(imat,bmat);
+
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
+ Mat3MulVecfl(imat, cent);
+
+ phi= degr*M_PI/360.0;
+ phi/= steps;
+ if(G.scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
+
+ if(dvec) {
+ n[0]= G.vd->viewinv[1][0];
+ n[1]= G.vd->viewinv[1][1];
+ n[2]= G.vd->viewinv[1][2];
+ } else {
+ n[0]= G.vd->viewinv[2][0];
+ n[1]= G.vd->viewinv[2][1];
+ n[2]= G.vd->viewinv[2][2];
+ }
+ Normalize(n);
+
+ q[0]= (float)cos(phi);
+ si= (float)sin(phi);
+ q[1]= n[0]*si;
+ q[2]= n[1]*si;
+ q[3]= n[2]*si;
+ QuatToMat3(q, cmat);
+
+ Mat3MulMat3(tmat,cmat,bmat);
+ Mat3MulMat3(bmat,imat,tmat);
+
+ if(mode==0) if(G.scene->toolsettings->editbutflag & B_KEEPORIG) adduplicateflag(1);
+ ok= 1;
+
+ for(a=0;a<steps;a++) {
+ if(mode==0) ok= extrudeflag(SELECT, nor);
+ else adduplicateflag(SELECT);
+ if(ok==0) {
+ error("No valid vertices are selected");
+ break;
+ }
+ rotateflag(SELECT, cent, bmat);
+ if(dvec) {
+ Mat3MulVecfl(bmat,dvec);
+ translateflag(SELECT, dvec);
+ }
+ }
+
+ if(ok==0) {
+ /* no vertices or only loose ones selected, remove duplicates */
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & SELECT) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(eve);
+ }
+ eve= nextve;
+ }
+ }
+ recalc_editnormals();
+
+ EM_fgon_flags();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+
+ if(dvec==NULL) BIF_undo_push("Spin");
+}
+
+void screw_mesh(int steps, int turns)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *eve,*v1=0,*v2=0;
+ EditEdge *eed;
+ float dvec[3], nor[3];
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ /* clear flags */
+ eve= em->verts.first;
+ while(eve) {
+ eve->f1= 0;
+ eve= eve->next;
+ }
+ /* edges set flags in verts */
+ eed= em->edges.first;
+ while(eed) {
+ if(eed->v1->f & SELECT) {
+ if(eed->v2->f & SELECT) {
+ /* watch: f1 is a byte */
+ if(eed->v1->f1<2) eed->v1->f1++;
+ if(eed->v2->f1<2) eed->v2->f1++;
+ }
+ }
+ eed= eed->next;
+ }
+ /* find two vertices with eve->f1==1, more or less is wrong */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f1==1) {
+ if(v1==0) v1= eve;
+ else if(v2==0) v2= eve;
+ else {
+ v1=0;
+ break;
+ }
+ }
+ eve= eve->next;
+ }
+ if(v1==0 || v2==0) {
+ error("You have to select a string of connected vertices too");
+ return;
+ }
+
+ /* calculate dvec */
+ dvec[0]= ( (v1->co[0]- v2->co[0]) )/(steps);
+ dvec[1]= ( (v1->co[1]- v2->co[1]) )/(steps);
+ dvec[2]= ( (v1->co[2]- v2->co[2]) )/(steps);
+
+ VECCOPY(nor, G.obedit->obmat[2]);
+
+ if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
+ dvec[0]= -dvec[0];
+ dvec[1]= -dvec[1];
+ dvec[2]= -dvec[2];
+ }
+
+ spin_mesh(turns*steps, turns*360, dvec, 0);
+
+ BIF_undo_push("Spin");
+}
+
+
+static void erase_edges(ListBase *l)
+{
+ EditEdge *ed, *nexted;
+
+ ed = (EditEdge *) l->first;
+ while(ed) {
+ nexted= ed->next;
+ if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
+ remedge(ed);
+ free_editedge(ed);
+ }
+ ed= nexted;
+ }
+}
+
+static void erase_faces(ListBase *l)
+{
+ EditFace *f, *nextf;
+
+ f = (EditFace *) l->first;
+
+ while(f) {
+ nextf= f->next;
+ if( faceselectedOR(f, SELECT) ) {
+ BLI_remlink(l, f);
+ free_editface(f);
+ }
+ f = nextf;
+ }
+}
+
+static void erase_vertices(ListBase *l)
+{
+ EditVert *v, *nextv;
+
+ v = (EditVert *) l->first;
+ while(v) {
+ nextv= v->next;
+ if(v->f & 1) {
+ BLI_remlink(l, v);
+ free_editvert(v);
+ }
+ v = nextv;
+ }
+}
+
+void delete_mesh(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa, *nextvl;
+ EditVert *eve,*nextve;
+ EditEdge *eed,*nexted;
+ short event;
+ int count;
+ char *str="Erase";
+
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ event= pupmenu("Erase %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5|Edge Loop%x6");
+ if(event<1) return;
+
+ if(event==10 ) {
+ str= "Erase Vertices";
+ erase_edges(&em->edges);
+ erase_faces(&em->faces);
+ erase_vertices(&em->verts);
+ }
+ else if(event==6) {
+ if(!EdgeLoopDelete())
+ return;
+
+ str= "Erase Edge Loop";
+ }
+ else if(event==4) {
+ str= "Erase Edges & Faces";
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ /* delete only faces with 1 or more edges selected */
+ count= 0;
+ if(efa->e1->f & SELECT) count++;
+ if(efa->e2->f & SELECT) count++;
+ if(efa->e3->f & SELECT) count++;
+ if(efa->e4 && (efa->e4->f & SELECT)) count++;
+ if(count) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ efa= nextvl;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f & SELECT) {
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed= nexted;
+ }
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ event=0;
+ if( efa->v1->f & SELECT) event++;
+ if( efa->v2->f & SELECT) event++;
+ if( efa->v3->f & SELECT) event++;
+ if(efa->v4 && (efa->v4->f & SELECT)) event++;
+
+ if(event>1) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ efa= nextvl;
+ }
+ }
+ else if(event==1) {
+ str= "Erase Edges";
+ // faces first
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ event=0;
+ if( efa->e1->f & SELECT) event++;
+ if( efa->e2->f & SELECT) event++;
+ if( efa->e3->f & SELECT) event++;
+ if(efa->e4 && (efa->e4->f & SELECT)) event++;
+
+ if(event) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ efa= nextvl;
+ }
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f & SELECT) {
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed= nexted;
+ }
+ /* to remove loose vertices: */
+ eed= em->edges.first;
+ while(eed) {
+ if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
+ if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
+ eed= eed->next;
+ }
+ eve= em->verts.first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->f & SELECT) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(eve);
+ }
+ eve= nextve;
+ }
+
+ }
+ else if(event==2) {
+ str="Erase Faces";
+ delfaceflag(SELECT);
+ }
+ else if(event==3) {
+ str= "Erase All";
+ if(em->verts.first) free_vertlist(&em->verts);
+ if(em->edges.first) free_edgelist(&em->edges);
+ if(em->faces.first) free_facelist(&em->faces);
+ if(em->selected.first) BLI_freelistN(&(em->selected));
+ }
+ else if(event==5) {
+ str= "Erase Only Faces";
+ efa= em->faces.first;
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ efa= nextvl;
+ }
+ }
+
+ EM_fgon_flags(); // redo flags and indices for fgons
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ BIF_undo_push(str);
+}
+
+
+/* Got this from scanfill.c. You will need to juggle around the
+ * callbacks for the scanfill.c code a bit for this to work. */
+void fill_mesh(void)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *eve,*v1;
+ EditEdge *eed,*e1,*nexted;
+ EditFace *efa,*nextvl, *efan;
+ short ok;
+
+ if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
+ if(multires_test()) return;
+
+ waitcursor(1);
+
+ /* copy all selected vertices */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ v1= BLI_addfillvert(eve->co);
+ eve->tmp.v= v1;
+ v1->tmp.v= eve;
+ v1->xs= 0; // used for counting edges
+ }
+ eve= eve->next;
+ }
+ /* copy all selected edges */
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) {
+ e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v);
+ e1->v1->xs++;
+ e1->v2->xs++;
+ }
+ eed= eed->next;
+ }
+ /* from all selected faces: remove vertices and edges to prevent doubles */
+ /* all edges add values, faces subtract,
+ then remove edges with vertices ->xs<2 */
+ efa= em->faces.first;
+ ok= 0;
+ while(efa) {
+ nextvl= efa->next;
+ if( faceselectedAND(efa, 1) ) {
+ efa->v1->tmp.v->xs--;
+ efa->v2->tmp.v->xs--;
+ efa->v3->tmp.v->xs--;
+ if(efa->v4) efa->v4->tmp.v->xs--;
+ ok= 1;
+
+ }
+ efa= nextvl;
+ }
+ if(ok) { /* there are faces selected */
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->v1->xs<2 || eed->v2->xs<2) {
+ BLI_remlink(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+ }
+
+ if(BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) {
+ efa= fillfacebase.first;
+ while(efa) {
+ /* normals default pointing up */
+ efan= addfacelist(efa->v3->tmp.v, efa->v2->tmp.v,
+ efa->v1->tmp.v, 0, NULL, NULL);
+ if(efan) EM_select_face(efan, 1);
+ efa= efa->next;
+ }
+ }
+
+ BLI_end_edgefill();
+
+ waitcursor(0);
+ EM_select_flush();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
+ BIF_undo_push("Fill");
+}
+/*GB*/
+/*-------------------------------------------------------------------------------*/
+/*--------------------------- Edge Based Subdivide ------------------------------*/
+
+#define EDGENEW 2
+#define FACENEW 2
+#define EDGEINNER 4
+#define EDGEOLD 8
+
+/*used by faceloop cut to select only edges valid for edge slide*/
+#define DOUBLEOPFILL 16
+
+/* calculates offset for co, based on fractal, sphere or smooth settings */
+static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc)
+{
+ float vec1[3], fac;
+
+ if(beauty & B_SMOOTH) {
+ /* we calculate an offset vector vec1[], to be added to *co */
+ float len, fac, nor[3], nor1[3], nor2[3];
+
+ VecSubf(nor, edge->v1->co, edge->v2->co);
+ len= 0.5f*Normalize(nor);
+
+ VECCOPY(nor1, edge->v1->no);
+ VECCOPY(nor2, edge->v2->no);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec1[0]= fac*nor1[0];
+ vec1[1]= fac*nor1[1];
+ vec1[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec1[0]+= fac*nor2[0];
+ vec1[1]+= fac*nor2[1];
+ vec1[2]+= fac*nor2[2];
+
+ vec1[0]*= rad*len;
+ vec1[1]*= rad*len;
+ vec1[2]*= rad*len;
+
+ co[0] += vec1[0];
+ co[1] += vec1[1];
+ co[2] += vec1[2];
+ }
+ else {
+ if(rad > 0.0) { /* subdivide sphere */
+ Normalize(co);
+ co[0]*= rad;
+ co[1]*= rad;
+ co[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fractal subdivide */
+ fac= rad* VecLenf(edge->v1->co, edge->v2->co);
+ vec1[0]= fac*(float)(0.5-BLI_drand());
+ vec1[1]= fac*(float)(0.5-BLI_drand());
+ vec1[2]= fac*(float)(0.5-BLI_drand());
+ VecAddf(co, co, vec1);
+ }
+
+ }
+}
+
+/* assumes in the edge is the correct interpolated vertices already */
+/* percent defines the interpolation, rad and beauty are for special options */
+/* results in new vertex with correct coordinate, vertex normal and weight group info */
+static EditVert *subdivide_edge_addvert(EditEdge *edge, float rad, int beauty, float percent)
+{
+ EditVert *ev;
+ float co[3];
+
+ co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
+ co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
+ co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
+
+ /* offset for smooth or sphere or fractal */
+ alter_co(co, edge, rad, beauty, percent);
+
+ /* clip if needed by mirror modifier */
+ if (edge->v1->f2) {
+ if ( edge->v1->f2 & edge->v2->f2 & 1) {
+ co[0]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 2) {
+ co[1]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 4) {
+ co[2]= 0.0f;
+ }
+ }
+
+ ev = addvertlist(co, NULL);
+
+ /* vert data (vgroups, ..) */
+ EM_data_interp_from_verts(edge->v1, edge->v2, ev, percent);
+
+ /* normal */
+ ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
+ ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
+ ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
+ Normalize(ev->no);
+
+ return ev;
+}
+
+static void flipvertarray(EditVert** arr, short size)
+{
+ EditVert *hold;
+ int i;
+
+ for(i=0; i<size/2; i++) {
+ hold = arr[i];
+ arr[i] = arr[size-i-1];
+ arr[size-i-1] = hold;
+ }
+}
+
+static void facecopy(EditFace *source, EditFace *target)
+{
+ EditMesh *em= G.editMesh;
+ float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
+ float *v4 = source->v4? source->v4->co: NULL;
+ float w[4][4];
+
+ CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
+
+ target->mat_nr = source->mat_nr;
+ target->flag = source->flag;
+ target->h = source->h;
+
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
+ if (target->v4)
+ InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
+
+ CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
+}
+
+static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[4], **verts;
+ EditFace *hold;
+ short start=0, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ -------------
+ left right
+
+ where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---| |---*---|
+ | / \ | | / \ |
+ | / \ | | / \ |
+ |/ \| |/ \|
+ ------------- ---------
+ */
+
+ // Make center face
+ if(vertsize % 2 == 0) {
+ hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e4->f2 |= EDGEINNER;
+ }else{
+ hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ }
+ facecopy(efa,hold);
+
+ // Make side faces
+ for(i=0;i<(vertsize-1)/2;i++) {
+ hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ if(i+1 != (vertsize-1)/2) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
+ }
+ hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ if(i+1 != (vertsize-1)/2) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e3->f2 |= EDGEINNER;
+ }
+ }
+ }
+}
+
+static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[3], **verts;
+ EditFace *hold;
+ short start=0, end, op, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
+ end = (start+1)%3;
+ op = (start+2)%3;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ |op
+
+ where start,end,op are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ 3 2 1 0
+ |---*---*---|
+ \ \ \ |
+ \ \ \ |
+ \ \ \ |
+ \ \ \|
+ \ \\|
+ \ |
+ |op
+ */
+
+ // Make side faces
+ for(i=0;i<(vertsize-1);i++) {
+ hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL);
+ if(i+1 != vertsize-1) {
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
+ }
+ facecopy(efa,hold);
+ }
+}
+
+static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start=0, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+ if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ |---*---*---|
+ 0 1 2 3
+ left right
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---|
+ | | | |
+ | | | |
+ | | | |
+ |---*---*---|
+ */
+
+ // Make side faces
+ for(i=0;i<vertsize-1;i++) {
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
+ if(i < vertsize-2) {
+ hold->e2->f2 |= EDGEINNER;
+ hold->e2->f2 |= DOUBLEOPFILL;
+ }
+ facecopy(efa,hold);
+ }
+}
+
+static void fill_quad_double_adj_path(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / / |
+ * / / |
+ | / / |
+ * / |
+ | / |
+ |-----------|
+ */
+
+ // Make outside tris
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ /* when ctrl is depressed, only want verts on the cutline selected */
+ if (G.qual != LR_CTRLKEY)
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
+ /* when ctrl is depressed, only want verts on the cutline selected */
+ if (G.qual != LR_CTRLKEY)
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ // Make side faces
+
+ for(i=0;i<numcuts;i++) {
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ }
+ //EM_fgon_flags();
+
+}
+
+static void fill_quad_double_adj_fan(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], *op=NULL, **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
+
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|op
+
+ We will fill this case like this or this (warning horrible ascii art follows)
+ |---*---*---|
+ | \ \ \ |
+ *---\ \ \ |
+ | \ \ \ \|
+ *---- \ \ \ |
+ | --- \\\|
+ |-----------|
+ */
+
+ for(i=0;i<=numcuts;i++) {
+ hold = addfacelist(op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+
+ hold = addfacelist(op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ }
+}
+
+static void fill_quad_double_adj_inner(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[4], *op=NULL, **verts[2],**inner;
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+ float co[3];
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
+
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|op
+
+ We will fill this case like this or this (warning horrible ascii art follows)
+ |---*-----*---|
+ | * / |
+ * \ / |
+ | * |
+ | / \ |
+ * \ |
+ | \ |
+ |-------------|
+ */
+
+ // Add Inner Vert(s)
+ inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
+
+ for(i=0;i<numcuts;i++) {
+ co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
+ co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
+ co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
+ inner[i] = addvertlist(co, NULL);
+ inner[i]->f2 |= EDGEINNER;
+
+ EM_data_interp_from_verts(verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
+ }
+
+ // Add Corner Quad
+ hold = addfacelist(verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ // Add Bottom Quads
+ hold = addfacelist(verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+
+ hold = addfacelist(op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ // Add Fill Quads (if # cuts > 1)
+
+ for(i=0;i<numcuts-1;i++) {
+ hold = addfacelist(inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
+ hold->e1->f2 |= EDGEINNER;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+
+ hold = addfacelist(inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e1->h |= EM_FGON;
+ //}
+ }
+
+ //EM_fgon_flags();
+
+ MEM_freeN(inner);
+}
+
+static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[2]={NULL, NULL};
+ EditVert *v[3], **verts[2];
+ EditFace *hold;
+ short start=0, start2=0, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | /
+ 1* /
+ | /
+ 2* /
+ | /
+ end2 3|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / /
+ * / /
+ | / /
+ * /
+ | /
+ |
+ */
+
+ // Make outside tri
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ // Make side faces
+
+ for(i=0;i<numcuts;i++) {
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ }
+}
+
+static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts)
+{
+ EditEdge *cedge[3]={0};
+ EditVert *v[4], **verts[3];
+ EditFace *hold;
+ short start=0, start2=0, start3=0, vertsize, i, repeats;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(!(efa->e1->f & SELECT)) {
+ cedge[0] = efa->e2;
+ cedge[1] = efa->e3;
+ cedge[2] = efa->e4;
+ start = 1;start2 = 2;start3 = 3;
+ }
+ if(!(efa->e2->f & SELECT)) {
+ cedge[0] = efa->e3;
+ cedge[1] = efa->e4;
+ cedge[2] = efa->e1;
+ start = 2;start2 = 3;start3 = 0;
+ }
+ if(!(efa->e3->f & SELECT)) {
+ cedge[0] = efa->e4;
+ cedge[1] = efa->e1;
+ cedge[2] = efa->e2;
+ start = 3;start2 = 0;start3 = 1;
+ }
+ if(!(efa->e4->f & SELECT)) {
+ cedge[0] = efa->e1;
+ cedge[1] = efa->e2;
+ cedge[2] = efa->e3;
+ start = 0;start2 = 1;start3 = 2;
+ }
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ verts[2] = BLI_ghash_lookup(gh, cedge[2]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+
+ start2
+ 3 2 1 0
+ start3 0|---*---*---|3
+ | |
+ 1* *2
+ | |
+ 2* *1
+ | |
+ 3|-----------|0 start
+
+ We will fill this case like this or this depending on even or odd cuts
+ there are a couple of differences. For odd cuts, there is a tri in the
+ middle as well as 1 quad at the bottom (not including the extra quads
+ for odd cuts > 1
+
+ For even cuts, there is a quad in the middle and 2 quads on the bottom
+
+ they are numbered here for clarity
+
+ 1 outer tris and bottom quads
+ 2 inner tri or quad
+ 3 repeating quads
+
+ |---*---*---*---|
+ |1/ / \ \ 1|
+ |/ 3 / \ 3 \|
+ * / 2 \ *
+ | / \ |
+ |/ \ |
+ *---------------*
+ | 3 |
+ | |
+ *---------------*
+ | |
+ | 1 |
+ | |
+ |---------------|
+
+ |---*---*---*---*---|
+ | 1/ / \ \ 1|
+ | / / \ \ |
+ |/ 3 / \ 3 \|
+ * / \ *
+ | / \ |
+ | / 2 \ |
+ |/ \|
+ *-------------------*
+ | |
+ | 3 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ |-------------------|
+
+ */
+
+ // Make outside tris
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ // Make bottom quad
+ hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ //If it is even cuts, add the 2nd lower quad
+ if(numcuts % 2 == 0) {
+ hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ // Also Make inner quad
+ hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
+ hold->e3->f2 |= EDGEINNER;
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e3->h |= EM_FGON;
+ //}
+ facecopy(efa,hold);
+ repeats = (numcuts / 2) -1;
+ } else {
+ // Make inner tri
+ hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
+ // hold->e2->h |= EM_FGON;
+ //}
+ facecopy(efa,hold);
+ repeats = ((numcuts+1) / 2)-1;
+ }
+
+ // cuts for 1 and 2 do not have the repeating quads
+ if(numcuts < 3) {repeats = 0;}
+ for(i=0;i<repeats;i++) {
+ //Make side repeating Quads
+ hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ }
+ // Do repeating bottom quads
+ for(i=0;i<repeats;i++) {
+ if(numcuts % 2 == 1) {
+ hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
+ } else {
+ hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
+ }
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ }
+ //EM_fgon_flags();
+}
+
+static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
+{
+ EditVert **verts[4], ***innerverts;
+ EditFace *hold;
+ EditEdge temp;
+ short vertsize, i, j;
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+ verts[3] = BLI_ghash_lookup(gh, efa->e4);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
+ /*
+ We should have something like this now
+ 1
+
+ 3 2 1 0
+ 0|---*---*---|0
+ | |
+ 1* *1
+ 2 | | 4
+ 2* *2
+ | |
+ 3|---*---*---|3
+ 3 2 1 0
+
+ 3
+ // we will fill a 2 dim array of editvert*s to make filling easier
+ // the innervert order is shown
+
+ 0 0---1---2---3
+ | | | |
+ 1 0---1---2---3
+ | | | |
+ 2 0---1---2---3
+ | | | |
+ 3 0---1---2---3
+
+ */
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
+ }
+
+ // first row is e1 last row is e3
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[0][i] = verts[0][(numcuts+1)-i];
+ innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
+ }
+
+ for(i=1;i<=numcuts;i++) {
+ /* we create a fake edge for the next loop */
+ temp.v2 = innerverts[i][0] = verts[1][i];
+ temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
+
+ for(j=1;j<=numcuts;j++) {
+ float percent= (float)j/(float)(numcuts+1);
+
+ innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(&temp, rad, beauty, percent);
+ }
+ }
+ // Fill with faces
+ for(i=0;i<numcuts+1;i++) {
+ for(j=0;j<numcuts+1;j++) {
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ hold->e4->f2 = EDGENEW;
+
+ if(i != 0) { hold->e1->f2 |= EDGEINNER; }
+ if(j != 0) { hold->e2->f2 |= EDGEINNER; }
+ if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
+ if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
+
+ facecopy(efa,hold);
+ }
+ }
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++) {
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
+}
+
+static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
+{
+ EditVert **verts[3], ***innerverts;
+ short vertsize, i, j;
+ EditFace *hold;
+ EditEdge temp;
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+ 3
+
+ 3 2 1 0
+ 0|---*---*---|3
+ | /
+ 1 1* *2
+ | /
+ 2* *1 2
+ | /
+ 3|/
+ 0
+
+ we will fill a 2 dim array of editvert*s to make filling easier
+
+ 3
+
+ 0 0---1---2---3---4
+ | / | / |/ | /
+ 1 0---1----2---3
+ 1 | / | / | /
+ 2 0----1---2 2
+ | / | /
+ |/ |/
+ 3 0---1
+ | /
+ |/
+ 4 0
+
+ */
+
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
+ }
+ //top row is e3 backwards
+ for(i=0;i<numcuts+2;i++) {
+ innerverts[0][i] = verts[2][(numcuts+1)-i];
+ }
+
+ for(i=1;i<=numcuts+1;i++) {
+ //fake edge, first vert is from e1, last is from e2
+ temp.v1= innerverts[i][0] = verts[0][i];
+ temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
+
+ for(j=1;j<(numcuts+1)-i;j++) {
+ float percent= (float)j/(float)((numcuts+1)-i);
+
+ innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(&temp, rad, beauty, 1-percent);
+ }
+ }
+
+ // Now fill the verts with happy little tris :)
+ for(i=0;i<=numcuts+1;i++) {
+ for(j=0;j<(numcuts+1)-i;j++) {
+ //We always do the first tri
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ if(i != 0) { hold->e1->f2 |= EDGEINNER; }
+ if(j != 0) { hold->e2->f2 |= EDGEINNER; }
+ if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
+
+ facecopy(efa,hold);
+ //if there are more to come, we do the 2nd
+ if(j+1 <= numcuts-i) {
+ hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ }
+ }
+ }
+
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++) {
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
+}
+
+//Next two fill types are for knife exact only and are provided to allow for knifing through vertices
+//This means there is no multicut!
+static void fill_quad_doublevert(EditFace *efa, int v1, int v2){
+ EditFace *hold;
+ /*
+ Depending on which two vertices have been knifed through (v1 and v2), we
+ triangulate like the patterns below.
+ X-------| |-------X
+ | \ | | / |
+ | \ | | / |
+ | \ | | / |
+ --------X X--------
+ */
+
+ if(v1 == 1 && v2 == 3){
+ hold= addfacelist(efa->v1, efa->v2, efa->v3, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+
+ hold= addfacelist(efa->v1, efa->v3, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+ }
+ else{
+ hold= addfacelist(efa->v1, efa->v2, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+
+ hold= addfacelist(efa->v2, efa->v3, efa->v4, 0, efa, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+ }
+}
+
+static void fill_quad_singlevert(EditFace *efa, struct GHash *gh)
+{
+ EditEdge *cedge=NULL;
+ EditVert *v[4], **verts;
+ EditFace *hold;
+ short start=0, end, left, right, vertsize;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = 3;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]) {flipvertarray(verts,3);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+
+/*
+ We should have something like this now
+
+ end start
+ 2 1 0
+ |-----*-----|
+ | |
+ | |
+ | |
+ -------------
+ left right
+
+ where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2 are the indexes of the new verts stored in verts. We fill like
+ this, depending on whether its vertex 'left' or vertex 'right' thats
+ been knifed through...
+
+ |---*---| |---*---|
+ | / | | \ |
+ | / | | \ |
+ |/ | | \|
+ X-------- --------X
+*/
+
+ if(v[left]->f1){
+ //triangle is composed of cutvert, end and left
+ hold = addfacelist(verts[1],v[end],v[left],NULL, NULL,NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+
+ //quad is composed of cutvert, left, right and start
+ hold = addfacelist(verts[1],v[left],v[right],v[start], NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+ }
+ else if(v[right]->f1){
+ //triangle is composed of cutvert, right and start
+ hold = addfacelist(verts[1],v[right],v[start], NULL, NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+ //quad is composed of cutvert, end, left, right
+ hold = addfacelist(verts[1],v[end], v[left], v[right], NULL, NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGENEW;
+ hold->e4->f2 |= EDGEINNER;
+ facecopy(efa, hold);
+ }
+
+}
+
+// This function takes an example edge, the current point to create and
+// the total # of points to create, then creates the point and return the
+// editvert pointer to it.
+static EditVert *subdivideedgenum(EditEdge *edge, int curpoint, int totpoint, float rad, int beauty)
+{
+ EditVert *ev;
+ float percent;
+
+ if (beauty & (B_PERCENTSUBD) && totpoint == 1)
+ //percent=(float)(edge->tmp.l)/32768.0f;
+ percent= edge->tmp.fp;
+ else
+ percent= (float)curpoint/(float)(totpoint+1);
+
+ ev= subdivide_edge_addvert(edge, rad, beauty, percent);
+ ev->f = edge->v1->f;
+
+ return ev;
+}
+
+#if 1
+#include "bmesh.h"
+
+void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
+{
+ BMesh *bm;
+ BMOperator subdop, conv;
+ EditMesh *em = G.editMesh;
+ BMEdge **list, *bed;
+ BMIter iter;
+ int tot;
+
+ /*convert from editmesh*/
+ bm = editmesh_to_bmesh(G.editMesh);
+
+ BMO_Init_Op(&subdop, BMOP_ESUBDIVIDE);
+ for (tot=0, bed=BMIter_New(&iter, bm, BM_EDGES, NULL); bed; bed=BMIter_Step(&iter)) {
+ if (BM_Is_Selected(bm, bed)) tot++;
+ }
+
+ list = MEM_callocN(sizeof(void*)*tot, "vert ptr list");
+
+ for (tot=0, bed=BMIter_New(&iter, bm, BM_EDGES, NULL); bed; bed=BMIter_Step(&iter)) {
+ if (BM_Is_Selected(bm, bed)) list[tot++] = bed;
+ }
+
+ BMO_Set_PntBuf(&subdop, BMOP_ESUBDIVIDE_EDGES, list, tot);
+ BMO_Exec_Op(bm, &subdop);
+ BMO_Finish_Op(bm, &subdop);
+
+ free_editMesh(G.editMesh);
+ bmesh_to_editmesh(bm);
+ BM_Free_Mesh(bm);
+
+ if (list) MEM_freeN(list);
+}
+#else
+void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *ef;
+ EditEdge *eed, *cedge, *sort[4];
+ EditVert *eve, **templist;
+ struct GHash *gh;
+ float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
+ int i, j, edgecount, touchcount, facetype,hold;
+ ModifierData *md= G.obedit->modifiers.first;
+
+ if(multires_test()) return;
+
+ //Set faces f1 to 0 cause we need it later
+ for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
+ for(eve=em->verts.first; eve; eve=eve->next) {
+ if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */
+ eve->f1 = 0;
+ eve->f2 = 0;
+ }
+
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ for (eve= em->verts.first; eve; eve= eve->next) {
+ eve->f2= 0;
+ switch(mmd->axis){
+ case 0:
+ if (fabs(eve->co[0]) < mmd->tolerance)
+ eve->f2 |= 1;
+ break;
+ case 1:
+ if (fabs(eve->co[1]) < mmd->tolerance)
+ eve->f2 |= 2;
+ break;
+ case 2:
+ if (fabs(eve->co[2]) < mmd->tolerance)
+ eve->f2 |= 4;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //Flush vertex flags upward to the edges
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ //if(eed->f & flag && eed->v1->f == eed->v2->f) {
+ // eed->f |= eed->v1->f;
+ // }
+ eed->f2 = 0;
+ if(eed->f & flag) {
+ eed->f2 |= EDGEOLD;
+ }
+ }
+
+ // We store an array of verts for each edge that is subdivided,
+ // we put this array as a value in a ghash which is keyed by the EditEdge*
+
+ // Now for beauty subdivide deselect edges based on length
+ if(beauty & B_BEAUTY) {
+ for(ef = em->faces.first;ef;ef = ef->next) {
+ if(!ef->v4) {
+ continue;
+ }
+ if(ef->f & SELECT) {
+ VECCOPY(v1mat, ef->v1->co);
+ VECCOPY(v2mat, ef->v2->co);
+ VECCOPY(v3mat, ef->v3->co);
+ VECCOPY(v4mat, ef->v4->co);
+ Mat4Mul3Vecfl(G.obedit->obmat, v1mat);
+ Mat4Mul3Vecfl(G.obedit->obmat, v2mat);
+ Mat4Mul3Vecfl(G.obedit->obmat, v3mat);
+ Mat4Mul3Vecfl(G.obedit->obmat, v4mat);
+
+ length[0] = VecLenf(v1mat, v2mat);
+ length[1] = VecLenf(v2mat, v3mat);
+ length[2] = VecLenf(v3mat, v4mat);
+ length[3] = VecLenf(v4mat, v1mat);
+ sort[0] = ef->e1;
+ sort[1] = ef->e2;
+ sort[2] = ef->e3;
+ sort[3] = ef->e4;
+
+
+ // Beauty Short Edges
+ if(beauty & B_BEAUTY_SHORT) {
+ for(j=0;j<2;j++) {
+ hold = -1;
+ for(i=0;i<4;i++) {
+ if(length[i] < 0) {
+ continue;
+ } else if(hold == -1) {
+ hold = i;
+ } else {
+ if(length[hold] < length[i]) {
+ hold = i;
+ }
+ }
+ }
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
+
+ // Beauty Long Edges
+ else {
+ for(j=0;j<2;j++) {
+ hold = -1;
+ for(i=0;i<4;i++) {
+ if(length[i] < 0) {
+ continue;
+ } else if(hold == -1) {
+ hold = i;
+ } else {
+ if(length[hold] > length[i]) {
+ hold = i;
+ }
+ }
+ }
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
+ }
+ }
+ }
+
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
+ if(beauty & B_KNIFE) {
+ for(eed= em->edges.first;eed;eed=eed->next) {
+ if( eed->tmp.fp == 0 ) {
+ EM_select_edge(eed,0);
+ }
+ }
+ }
+ // So for each edge, if it is selected, we allocate an array of size cuts+2
+ // so we can have a place for the v1, the new verts and v2
+ for(eed=em->edges.first;eed;eed = eed->next) {
+ if(eed->f & flag) {
+ templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
+ templist[0] = eed->v1;
+ for(i=0;i<numcuts;i++) {
+ // This function creates the new vert and returns it back
+ // to the array
+ templist[i+1] = subdivideedgenum(eed, i+1, numcuts, rad, beauty);
+ //while we are here, we can copy edge info from the original edge
+ cedge = addedgelist(templist[i],templist[i+1],eed);
+ // Also set the edge f2 to EDGENEW so that we can use this info later
+ cedge->f2 = EDGENEW;
+ }
+ templist[i+1] = eed->v2;
+ //Do the last edge too
+ cedge = addedgelist(templist[i],templist[i+1],eed);
+ cedge->f2 = EDGENEW;
+ // Now that the edge is subdivided, we can put its verts in the ghash
+ BLI_ghash_insert(gh, eed, templist);
+ }
+ }
+
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ // Now for each face in the mesh we need to figure out How many edges were cut
+ // and which filling method to use for that face
+ for(ef = em->faces.first;ef;ef = ef->next) {
+ edgecount = 0;
+ facetype = 3;
+ if(ef->e1->f & flag) {edgecount++;}
+ if(ef->e2->f & flag) {edgecount++;}
+ if(ef->e3->f & flag) {edgecount++;}
+ if(ef->v4) {
+ facetype = 4;
+ if(ef->e4->f & flag) {edgecount++;}
+ }
+ if(facetype == 4) {
+ switch(edgecount) {
+ case 0:
+ if(beauty & B_KNIFE && numcuts == 1){
+ /*Test for when knifing through two opposite verts but no edges*/
+ touchcount = 0;
+ if(ef->v1->f1) touchcount++;
+ if(ef->v2->f1) touchcount++;
+ if(ef->v3->f1) touchcount++;
+ if(ef->v4->f1) touchcount++;
+ if(touchcount == 2){
+ if(ef->v1->f1 && ef->v3->f1){
+ ef->f1 = SELECT;
+ fill_quad_doublevert(ef, 1, 3);
+ }
+ else if(ef->v2->f1 && ef->v4->f1){
+ ef->f1 = SELECT;
+ fill_quad_doublevert(ef, 2, 4);
+ }
+ }
+ }
+ break;
+
+ case 1:
+ if(beauty & B_KNIFE && numcuts == 1){
+ /*Test for when knifing through an edge and one vert*/
+ touchcount = 0;
+ if(ef->v1->f1) touchcount++;
+ if(ef->v2->f1) touchcount++;
+ if(ef->v3->f1) touchcount++;
+ if(ef->v4->f1) touchcount++;
+
+ if(touchcount == 1){
+ if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
+ (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
+ (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
+ (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
+
+ ef->f1 = SELECT;
+ fill_quad_singlevert(ef, gh);
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(ef, gh, numcuts, seltype);
+ }
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(ef, gh, numcuts, seltype);
+ }
+ }
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(ef, gh, numcuts, seltype);
+ }
+ break;
+ case 2: ef->f1 = SELECT;
+ // if there are 2, we check if edge 1 and 3 are either both on or off that way
+ // we can tell if the selected pair is Adjacent or Opposite of each other
+ if((ef->e1->f & flag && ef->e3->f & flag) ||
+ (ef->e2->f & flag && ef->e4->f & flag)) {
+ fill_quad_double_op(ef, gh, numcuts);
+ }else{
+ switch(G.scene->toolsettings->cornertype) {
+ case 0: fill_quad_double_adj_path(ef, gh, numcuts); break;
+ case 1: fill_quad_double_adj_inner(ef, gh, numcuts); break;
+ case 2: fill_quad_double_adj_fan(ef, gh, numcuts); break;
+ }
+
+ }
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_quad_triple(ef, gh, numcuts);
+ break;
+ case 4: ef->f1 = SELECT;
+ fill_quad_quadruple(ef, gh, numcuts, rad, beauty);
+ break;
+ }
+ } else {
+ switch(edgecount) {
+ case 0: break;
+ case 1: ef->f1 = SELECT;
+ fill_tri_single(ef, gh, numcuts, seltype);
+ break;
+ case 2: ef->f1 = SELECT;
+ fill_tri_double(ef, gh, numcuts);
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_tri_triple(ef, gh, numcuts, rad, beauty);
+ break;
+ }
+ }
+ }
+
+ // Delete Old Edges and Faces
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(BLI_ghash_haskey(gh,eed)) {
+ eed->f1 = SELECT;
+ } else {
+ eed->f1 = 0;
+ }
+ }
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
+ if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) {
+ /* bugfix: vertex could get flagged as "not-selected"
+ // solution: clear flags before, not at the same time as setting SELECT flag -dg
+ */
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }
+ }
+ } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) {
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & EDGEINNER) {
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
+ if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ } else if(seltype == SUBDIV_SELECT_LOOPCUT){
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f2 & DOUBLEOPFILL){
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ }
+ if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+ for(eed = em->edges.first;eed;eed = eed->next) {
+ if(eed->f & SELECT) {
+ eed->v1->f |= SELECT;
+ eed->v2->f |= SELECT;
+ }
+ }
+ }
+
+ //fix hide flags for edges. First pass, hide edges of hidden faces
+ for(ef=em->faces.first; ef; ef=ef->next){
+ if(ef->h){
+ ef->e1->h |= 1;
+ ef->e2->h |= 1;
+ ef->e3->h |= 1;
+ if(ef->e4) ef->e4->h |= 1;
+ }
+ }
+ //second pass: unhide edges of visible faces adjacent to hidden faces
+ for(ef=em->faces.first; ef; ef=ef->next){
+ if(ef->h == 0){
+ ef->e1->h &= ~1;
+ ef->e2->h &= ~1;
+ ef->e3->h &= ~1;
+ if(ef->e4) ef->e4->h &= ~1;
+ }
+ }
+
+ // Free the ghash and call MEM_freeN on all the value entries to return
+ // that memory
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+ EM_selectmode_flush();
+ for(ef=em->faces.first;ef;ef = ef->next) {
+ if(ef->e4) {
+ if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
+ (ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
+ ef->f |= SELECT;
+ }
+ } else {
+ if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
+ ef->f |= SELECT;
+ }
+ }
+ }
+
+ recalc_editnormals();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+}
+#endif
+
+static int count_selected_edges(EditEdge *ed)
+{
+ int totedge = 0;
+ while(ed) {
+ ed->tmp.p = 0;
+ if( ed->f & SELECT ) totedge++;
+ ed= ed->next;
+ }
+ return totedge;
+}
+
+/* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
+typedef EditFace *EVPtr;
+typedef EVPtr EVPTuple[2];
+
+/** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
+ sharing one edge.
+ arguments: selected edge list, face list.
+ Edges will also be tagged accordingly (see eed->f2) */
+
+static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
+{
+ EditEdge *e1, *e2, *e3;
+ EVPtr *evp;
+ int i = 0;
+
+ /* run through edges, if selected, set pointer edge-> facearray */
+ while(eed) {
+ eed->f2= 0;
+ eed->f1= 0;
+ if( eed->f & SELECT ) {
+ eed->tmp.p = (EditVert *) (&efaa[i]);
+ i++;
+ }
+ else eed->tmp.p = NULL;
+
+ eed= eed->next;
+ }
+
+
+ /* find edges pointing to 2 faces by procedure:
+
+ - run through faces and their edges, increase
+ face counter e->f1 for each face
+ */
+
+ while(efa) {
+ efa->f1= 0;
+ if(efa->v4==0 && (efa->f & SELECT)) { /* if selected triangle */
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ if(e1->f2<3 && e1->tmp.p) {
+ if(e1->f2<2) {
+ evp= (EVPtr *) e1->tmp.p;
+ evp[(int)e1->f2] = efa;
+ }
+ e1->f2+= 1;
+ }
+ if(e2->f2<3 && e2->tmp.p) {
+ if(e2->f2<2) {
+ evp= (EVPtr *) e2->tmp.p;
+ evp[(int)e2->f2]= efa;
+ }
+ e2->f2+= 1;
+ }
+ if(e3->f2<3 && e3->tmp.p) {
+ if(e3->f2<2) {
+ evp= (EVPtr *) e3->tmp.p;
+ evp[(int)e3->f2]= efa;
+ }
+ e3->f2+= 1;
+ }
+ }
+ else {
+ /* set to 3 to make sure these are not flipped or joined */
+ efa->e1->f2= 3;
+ efa->e2->f2= 3;
+ efa->e3->f2= 3;
+ if (efa->e4) efa->e4->f2= 3;
+ }
+
+ efa= efa->next;
+ }
+ return i;
+}
+
+
+/* returns vertices of two adjacent triangles forming a quad
+ - can be righthand or lefthand
+
+ 4-----3
+ |\ |
+ | \ 2 | <- efa1
+ | \ |
+ efa-> | 1 \ |
+ | \|
+ 1-----2
+
+*/
+#define VTEST(face, num, other) \
+ (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
+
+static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex)
+{
+ if VTEST(efa, 1, efa1) {
+ *v1= efa->v1;
+ *v2= efa->v2;
+ vindex[0]= 0;
+ vindex[1]= 1;
+ }
+ else if VTEST(efa, 2, efa1) {
+ *v1= efa->v2;
+ *v2= efa->v3;
+ vindex[0]= 1;
+ vindex[1]= 2;
+ }
+ else if VTEST(efa, 3, efa1) {
+ *v1= efa->v3;
+ *v2= efa->v1;
+ vindex[0]= 2;
+ vindex[1]= 0;
+ }
+
+ if VTEST(efa1, 1, efa) {
+ *v3= efa1->v1;
+ *v4= efa1->v2;
+ vindex[2]= 0;
+ vindex[3]= 1;
+ }
+ else if VTEST(efa1, 2, efa) {
+ *v3= efa1->v2;
+ *v4= efa1->v3;
+ vindex[2]= 1;
+ vindex[3]= 2;
+ }
+ else if VTEST(efa1, 3, efa) {
+ *v3= efa1->v3;
+ *v4= efa1->v1;
+ vindex[2]= 2;
+ vindex[3]= 0;
+ }
+ else
+ *v3= *v4= NULL;
+}
+
+/* Helper functions for edge/quad edit features*/
+static void untag_edges(EditFace *f)
+{
+ f->e1->f1 = 0;
+ f->e2->f1 = 0;
+ f->e3->f1 = 0;
+ if (f->e4) f->e4->f1 = 0;
+}
+
+/** remove and free list of tagged edges and faces */
+static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa)
+{
+ EditMesh *em= G.editMesh;
+ EditEdge *nexted;
+ EditFace *nextvl;
+
+ while(efa) {
+ nextvl= efa->next;
+ if(efa->f1) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ }
+ else
+ /* avoid deleting edges that are still in use */
+ untag_edges(efa);
+ efa= nextvl;
+ }
+
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f1) {
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed= nexted;
+ }
+}
+
+/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
+ edge/face flags, with very mixed results.... */
+void beauty_fill(void)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditEdge dia1, dia2;
+ EditFace *efa, *w;
+ // void **efaar, **efaa;
+ EVPTuple *efaar;
+ EVPtr *efaa;
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ int totedge, ok, notbeauty=8, onedone, vindex[4];
+
+ if(multires_test()) return;
+
+ /* - all selected edges with two faces
+ * - find the faces: store them in edges (using datablock)
+ * - per edge: - test convex
+ * - test edge: flip?
+ * - if true: remedge, addedge, all edges at the edge get new face pointers
+ */
+
+ EM_selectmode_set(); // makes sure in selectmode 'face' the edges of selected faces are selected too
+
+ totedge = count_selected_edges(em->edges.first);
+ if(totedge==0) return;
+
+ /* temp block with face pointers */
+ efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
+
+ while (notbeauty) {
+ notbeauty--;
+
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+
+ /* there we go */
+ onedone= 0;
+
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ /* f2 is set in collect_quadedges() */
+ if(eed->f2==2 && eed->h==0) {
+
+ efaa = (EVPtr *) eed->tmp.p;
+
+ /* none of the faces should be treated before, nor be part of fgon */
+ ok= 1;
+ efa= efaa[0];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+ efa= efaa[1];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if(v1 && v2 && v3 && v4) {
+ if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+
+ /* test edges */
+ if( (v1) > (v3) ) {
+ dia1.v1= v3;
+ dia1.v2= v1;
+ }
+ else {
+ dia1.v1= v1;
+ dia1.v2= v3;
+ }
+
+ if( (v2) > (v4) ) {
+ dia2.v1= v4;
+ dia2.v2= v2;
+ }
+ else {
+ dia2.v1= v2;
+ dia2.v2= v4;
+ }
+
+ /* testing rule:
+ * the area divided by the total edge lengths
+ */
+
+ len1= VecLenf(v1->co, v2->co);
+ len2= VecLenf(v2->co, v3->co);
+ len3= VecLenf(v3->co, v4->co);
+ len4= VecLenf(v4->co, v1->co);
+ len5= VecLenf(v1->co, v3->co);
+ len6= VecLenf(v2->co, v4->co);
+
+ opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
+ opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
+
+ fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+ opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
+ opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
+
+ fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+ ok= 0;
+ if(fac1 > fac2) {
+ if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], vindex[1], 4+vindex[2], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ else if(fac1 < fac2) {
+ if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[1], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], 4+vindex[1], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ eed= nexted;
+ }
+
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
+ if(onedone==0) break;
+
+ EM_selectmode_set(); // new edges/faces were added
+ }
+
+ MEM_freeN(efaar);
+
+ EM_select_flush();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Beauty Fill");
+}
+
+
+/* ******************** BEGIN TRIANGLE TO QUAD ************************************* */
+static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit){
+
+ /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/
+ /*Note: this is more complicated than it needs to be and should be cleaned up...*/
+ float measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff,
+ edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff,
+ minarea, maxarea, areaA, areaB;
+
+ /*First Test: Normal difference*/
+ CalcNormFloat(v1->co, v2->co, v3->co, noA1);
+ CalcNormFloat(v1->co, v3->co, v4->co, noA2);
+
+ if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0;
+ else normalADiff = VecAngle2(noA1, noA2);
+ //if(!normalADiff) normalADiff = 179;
+ CalcNormFloat(v2->co, v3->co, v4->co, noB1);
+ CalcNormFloat(v4->co, v1->co, v2->co, noB2);
+
+ if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0;
+ else normalBDiff = VecAngle2(noB1, noB2);
+ //if(!normalBDiff) normalBDiff = 179;
+
+ measure += (normalADiff/360) + (normalBDiff/360);
+ if(measure > limit) return measure;
+
+ /*Second test: Colinearity*/
+ VecSubf(edgeVec1, v1->co, v2->co);
+ VecSubf(edgeVec2, v2->co, v3->co);
+ VecSubf(edgeVec3, v3->co, v4->co);
+ VecSubf(edgeVec4, v4->co, v1->co);
+
+ diff = 0.0;
+
+ diff = (
+ fabs(VecAngle2(edgeVec1, edgeVec2) - 90) +
+ fabs(VecAngle2(edgeVec2, edgeVec3) - 90) +
+ fabs(VecAngle2(edgeVec3, edgeVec4) - 90) +
+ fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360;
+ if(!diff) return 0.0;
+
+ measure += diff;
+ if(measure > limit) return measure;
+
+ /*Third test: Concavity*/
+ areaA = AreaT3Dfl(v1->co, v2->co, v3->co) + AreaT3Dfl(v1->co, v3->co, v4->co);
+ areaB = AreaT3Dfl(v2->co, v3->co, v4->co) + AreaT3Dfl(v4->co, v1->co, v2->co);
+
+ if(areaA <= areaB) minarea = areaA;
+ else minarea = areaB;
+
+ if(areaA >= areaB) maxarea = areaA;
+ else maxarea = areaB;
+
+ if(!maxarea) measure += 1;
+ else measure += (1 - (minarea / maxarea));
+
+ return measure;
+}
+
+#define T2QUV_LIMIT 0.005
+#define T2QCOL_LIMIT 3
+static int compareFaceAttribs(EditFace *f1, EditFace *f2, EditEdge *eed)
+{
+ /*Test to see if the per-face attributes for the joining edge match within limit*/
+ MTFace *tf1, *tf2;
+ unsigned int *col1, *col2;
+ short i,attrok=0, flag = G.scene->toolsettings->editbutflag, fe1[2], fe2[2];
+
+ tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MTFACE);
+ tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MTFACE);
+
+ col1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MCOL);
+ col2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MCOL);
+
+ /*store indices for faceedges*/
+ f1->v1->f1 = 0;
+ f1->v2->f1 = 1;
+ f1->v3->f1 = 2;
+
+ fe1[0] = eed->v1->f1;
+ fe1[1] = eed->v2->f1;
+
+ f2->v1->f1 = 0;
+ f2->v2->f1 = 1;
+ f2->v3->f1 = 2;
+
+ fe2[0] = eed->v1->f1;
+ fe2[1] = eed->v2->f1;
+
+ /*compare faceedges for each face attribute. Additional per face attributes can be added later*/
+ /*do UVs*/
+ if(flag & B_JOINTRIA_UV){
+
+ if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV;
+ else if(tf1->tpage != tf2->tpage); /*do nothing*/
+ else{
+ for(i = 0; i < 2; i++){
+ if(tf1->uv[fe1[i]][0] + T2QUV_LIMIT > tf2->uv[fe2[i]][0] && tf1->uv[fe1[i]][0] - T2QUV_LIMIT < tf2->uv[fe2[i]][0] &&
+ tf1->uv[fe1[i]][1] + T2QUV_LIMIT > tf2->uv[fe2[i]][1] && tf1->uv[fe1[i]][1] - T2QUV_LIMIT < tf2->uv[fe2[i]][1]) attrok |= B_JOINTRIA_UV;
+ }
+ }
+ }
+
+ /*do VCOLs*/
+ if(flag & B_JOINTRIA_VCOL){
+ if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL;
+ else{
+ char *f1vcol, *f2vcol;
+ for(i = 0; i < 2; i++){
+ f1vcol = (char *)&(col1[fe1[i]]);
+ f2vcol = (char *)&(col2[fe2[i]]);
+
+ /*compare f1vcol with f2vcol*/
+ if( f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] &&
+ f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] &&
+ f1vcol[3] + T2QCOL_LIMIT > f2vcol[3] && f1vcol[3] - T2QCOL_LIMIT < f2vcol[3]) attrok |= B_JOINTRIA_VCOL;
+ }
+ }
+ }
+
+ if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1;
+ return 0;
+}
+
+static int fplcmp(const void *v1, const void *v2)
+{
+ const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2);
+
+ if( e1->crease > e2->crease) return 1;
+ else if( e1->crease < e2->crease) return -1;
+
+ return 0;
+}
+
+/*Bitflags for edges.*/
+#define T2QDELETE 1
+#define T2QCOMPLEX 2
+#define T2QJOIN 4
+void join_triangles(void)
+{
+ EditMesh *em=G.editMesh;
+ EditVert *v1, *v2, *v3, *v4, *eve;
+ EditEdge *eed, **edsortblock = NULL, **edb = NULL;
+ EditFace *efa;
+ EVPTuple *efaar = NULL;
+ EVPtr *efaa = NULL;
+ float *creases = NULL;
+ float measure; /*Used to set tolerance*/
+ float limit = G.scene->toolsettings->jointrilimit;
+ int i, ok, totedge=0, totseledge=0, complexedges, vindex[4];
+
+ /*test for multi-resolution data*/
+ if(multires_test()) return;
+
+ /*if we take a long time on very dense meshes we want waitcursor to display*/
+ waitcursor(1);
+
+ totseledge = count_selected_edges(em->edges.first);
+ if(totseledge==0) return;
+
+ /*abusing crease value to store weights for edge pairs. Nasty*/
+ for(eed=em->edges.first; eed; eed=eed->next) totedge++;
+ if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");
+ for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){
+ creases[i] = eed->crease;
+ eed->crease = 0.0;
+ }
+
+ /*clear temp flags*/
+ for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0;
+ for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0;
+ for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = efa->tmp.l = 0;
+
+ /*For every selected 2 manifold edge, create pointers to its two faces.*/
+ efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad");
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+ complexedges = 0;
+
+ if(ok){
+
+
+ /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/
+ for(eed=em->edges.first; eed; eed=eed->next){
+ /* eed->f2 is 2 only if this edge is part of exactly two
+ triangles, and both are selected, and it has EVPTuple assigned */
+ if(eed->f2 == 2){
+ efaa= (EVPtr *) eed->tmp.p;
+ efaa[0]->tmp.l++;
+ efaa[1]->tmp.l++;
+ }
+ }
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f2 == 2){
+ efaa= (EVPtr *) eed->tmp.p;
+ v1 = v2 = v3 = v4 = NULL;
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if(v1 && v2 && v3 && v4){
+ /*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/
+ if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){
+ if( convex(v1->co, v2->co, v3->co, v4->co) ){
+ eed->f1 |= T2QJOIN;
+ efaa[0]->f1 = 1; //mark for join
+ efaa[1]->f1 = 1; //mark for join
+ }
+ }
+ else{
+
+ /* The face pair is part of a 'complex' island, so the rules for dealing with it are more involved.
+ Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria:
+
+ 1: the two faces do not share the same material
+ 2: the edge joining the two faces is marked as sharp.
+ 3: the two faces UV's do not make a good match
+ 4: the two faces Vertex colors do not make a good match
+
+ If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function.
+ This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user
+ the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the
+ same faces in the current pair later.
+
+ This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of
+ the python scripts bundled with Blender releases.
+ */
+
+ if(G.scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
+ else if(G.scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
+ else if(((G.scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (G.scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
+ compareFaceAttribs(efaa[0], efaa[1], eed) == 0); /*do nothing*/
+ else{
+ measure = measure_facepair(v1, v2, v3, v4, limit);
+ if(measure < limit){
+ complexedges++;
+ eed->f1 |= T2QCOMPLEX;
+ eed->crease = measure; /*we dont mark edges for join yet*/
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*Quicksort the complex edges according to their weighting*/
+ if(complexedges){
+ edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array");
+ for(eed = em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QCOMPLEX){
+ *edb = eed;
+ edb++;
+ }
+ }
+ qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp);
+ /*now go through and mark the edges who get the highest weighting*/
+ for(edb=edsortblock, i=0; i < complexedges; edb++, i++){
+ efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/
+ if( !efaa[0]->f1 && !efaa[1]->f1){
+ efaa[0]->f1 = 1; //mark for join
+ efaa[1]->f1 = 1; //mark for join
+ (*edb)->f1 |= T2QJOIN;
+ }
+ }
+ }
+
+ /*finally go through all edges marked for join (simple and complex) and create new faces*/
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QJOIN){
+ efaa= (EVPtr *)eed->tmp.p;
+ v1 = v2 = v3 = v4 = NULL;
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if((v1 && v2 && v3 && v4) && (exist_face(v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/
+ /*flag for delete*/
+ eed->f1 |= T2QDELETE;
+ /*create new quad and select*/
+ efa = EM_face_from_faces(efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]);
+ EM_select_face(efa,1);
+ }
+ else{
+ efaa[0]->f1 = 0;
+ efaa[1]->f1 = 0;
+ }
+ }
+ }
+ }
+
+ /*free data and cleanup*/
+ if(creases){
+ for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];
+ MEM_freeN(creases);
+ }
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f1 & T2QDELETE) eed->f1 = 1;
+ else eed->f1 = 0;
+ }
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+ if(efaar) MEM_freeN(efaar);
+ if(edsortblock) MEM_freeN(edsortblock);
+
+ EM_selectmode_flush();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ #ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ #endif
+ waitcursor(0);
+ BIF_undo_push("Convert Triangles to Quads");
+}
+/* ******************** END TRIANGLE TO QUAD ************************************* */
+
+#define FACE_MARKCLEAR(f) (f->f1 = 1)
+
+/* quick hack, basically a copy of beauty_fill */
+void edge_flip(void)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditFace *efa, *w;
+ //void **efaar, **efaa;
+ EVPTuple *efaar;
+ EVPtr *efaa;
+ int totedge, ok, vindex[4];
+
+ /* - all selected edges with two faces
+ * - find the faces: store them in edges (using datablock)
+ * - per edge: - test convex
+ * - test edge: flip?
+ - if true: remedge, addedge, all edges at the edge get new face pointers
+ */
+
+ EM_selectmode_flush(); // makes sure in selectmode 'face' the edges of selected faces are selected too
+
+ totedge = count_selected_edges(em->edges.first);
+ if(totedge==0) return;
+
+ /* temporary array for : edge -> face[1], face[2] */
+ efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
+
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ if(eed->f2==2) { /* points to 2 faces */
+
+ efaa= (EVPtr *) eed->tmp.p;
+
+ /* don't do it if flagged */
+
+ ok= 1;
+ efa= efaa[0];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ efa= efaa[1];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+
+/*
+ 4-----3 4-----3
+ |\ | | /|
+ | \ 1 | | 1 / |
+ | \ | -> | / |
+ | 0 \ | | / 0 |
+ | \| |/ |
+ 1-----2 1-----2
+*/
+ /* make new faces */
+ if (v1 && v2 && v3) {
+ if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+ if(exist_face(v1, v2, v3, v4)==0) {
+ /* outch this may break seams */
+ w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
+ vindex[1], 4+vindex[2], -1);
+
+ EM_select_face(w, 1);
+
+ /* outch this may break seams */
+ w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
+ 4+vindex[2], 4+vindex[3], -1);
+
+ EM_select_face(w, 1);
+ }
+ /* tag as to-be-removed */
+ FACE_MARKCLEAR(efaa[1]);
+ FACE_MARKCLEAR(efaa[0]);
+ eed->f1 = 1;
+
+ } /* endif test convex */
+ }
+ }
+ }
+ eed= nexted;
+ }
+
+ /* clear tagged edges and faces: */
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
+ MEM_freeN(efaar);
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Flip Triangle Edges");
+
+}
+
+static void edge_rotate(EditEdge *eed,int dir)
+{
+ EditMesh *em = G.editMesh;
+ EditVert **verts[2];
+ EditFace *face[2], *efa, *newFace[2];
+ EditEdge **edges[2], **hiddenedges, *srchedge;
+ int facecount, p1, p2, p3, p4, fac1, fac2, i, j;
+ int numhidden, numshared, p[2][4];
+
+ /* check to make sure that the edge is only part of 2 faces */
+ facecount = 0;
+ for(efa = em->faces.first;efa;efa = efa->next) {
+ if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) {
+ if(facecount >= 2) {
+ /* more than two faces with this edge */
+ return;
+ }
+ else {
+ face[facecount] = efa;
+ facecount++;
+ }
+ }
+ }
+
+ if(facecount < 2)
+ return;
+
+ /* how many edges does each face have */
+ if(face[0]->e4) fac1= 4;
+ else fac1= 3;
+
+ if(face[1]->e4) fac2= 4;
+ else fac2= 3;
+
+ /* make a handy array for verts and edges */
+ verts[0]= &face[0]->v1;
+ edges[0]= &face[0]->e1;
+ verts[1]= &face[1]->v1;
+ edges[1]= &face[1]->e1;
+
+ /* we don't want to rotate edges between faces that share more than one edge */
+ numshared= 0;
+ for(i=0; i<fac1; i++)
+ for(j=0; j<fac2; j++)
+ if (edges[0][i] == edges[1][j])
+ numshared++;
+
+ if(numshared > 1)
+ return;
+
+ /* coplaner faces only please */
+ if(Inpf(face[0]->n,face[1]->n) <= 0.000001)
+ return;
+
+ /* we want to construct an array of vertex indicis in both faces, starting at
+ the last vertex of the edge being rotated.
+ - first we find the two vertices that lie on the rotating edge
+ - then we make sure they are ordered according to the face vertex order
+ - and then we construct the array */
+ p1= p2= p3= p4= 0;
+
+ for(i=0; i<4; i++) {
+ if(eed->v1 == verts[0][i]) p1 = i;
+ if(eed->v2 == verts[0][i]) p2 = i;
+ if(eed->v1 == verts[1][i]) p3 = i;
+ if(eed->v2 == verts[1][i]) p4 = i;
+ }
+
+ if((p1+1)%fac1 == p2)
+ SWAP(int, p1, p2);
+ if((p3+1)%fac2 == p4)
+ SWAP(int, p3, p4);
+
+ for (i = 0; i < 4; i++) {
+ p[0][i]= (p1 + i)%fac1;
+ p[1][i]= (p3 + i)%fac2;
+ }
+
+ /* create an Array of the Edges who have h set prior to rotate */
+ numhidden = 0;
+ for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next)
+ if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT)))
+ numhidden++;
+
+ hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts");
+ if(!hiddenedges) {
+ error("Malloc Was not happy!");
+ return;
+ }
+
+ numhidden = 0;
+ for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+ if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT))
+ hiddenedges[numhidden++] = srchedge;
+
+ /* create the 2 new faces */
+ if(fac1 == 3 && fac2 == 3) {
+ /* no need of reverse setup */
+
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ }
+ else if(fac1 == 4 && fac2 == 3) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
+
+ verts[0][p[0][2]]->f |= SELECT;
+ verts[1][p[1][1]]->f |= SELECT;
+ }
+ }
+ else if(fac1 == 3 && fac2 == 4) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
+
+ verts[0][p[0][1]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
+ }
+
+ }
+ else if(fac1 == 4 && fac2 == 4) {
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
+
+ verts[0][p[0][2]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
+ }
+ }
+ else
+ return; /* This should never happen */
+
+ if(dir == 1 || (fac1 == 3 && fac2 == 3)) {
+ verts[0][p[0][1]]->f |= SELECT;
+ verts[1][p[1][1]]->f |= SELECT;
+ }
+
+ /* copy old edge's flags to new center edge*/
+ for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) {
+ if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) {
+ srchedge->f = eed->f;
+ srchedge->h = eed->h;
+ srchedge->dir = eed->dir;
+ srchedge->seam = eed->seam;
+ srchedge->crease = eed->crease;
+ srchedge->bweight = eed->bweight;
+ }
+ }
+
+ /* resetting hidden flag */
+ for(numhidden--; numhidden>=0; numhidden--)
+ hiddenedges[numhidden]->h= 1;
+
+ /* check for orhphan edges */
+ for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
+ srchedge->f1= -1;
+
+ /* cleanup */
+ MEM_freeN(hiddenedges);
+
+ /* get rid of the old edge and faces*/
+ remedge(eed);
+ free_editedge(eed);
+ BLI_remlink(&em->faces, face[0]);
+ free_editface(face[0]);
+ BLI_remlink(&em->faces, face[1]);
+ free_editface(face[1]);
+}
+
+/* only accepts 1 selected edge, or 2 selected faces */
+void edge_rotate_selected(int dir)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ short edgeCount = 0;
+
+ /*clear new flag for new edges, count selected edges */
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2 &= ~2;
+ if(eed->f & SELECT) edgeCount++;
+ }
+
+ if(edgeCount>1) {
+ /* more selected edges, check faces */
+ for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+ edgeCount= 0;
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2) edgeCount++;
+ }
+ if(edgeCount==1) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2) {
+ edge_rotate(eed,dir);
+ break;
+ }
+ }
+ }
+ else error("Select one edge or two adjacent faces");
+ }
+ else if(edgeCount==1) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
+ if(eed->f & SELECT) {
+ EM_select_edge(eed, 0);
+ edge_rotate(eed,dir);
+ break;
+ }
+ }
+ }
+ else error("Select one edge or two adjacent faces");
+
+
+ /* flush selected vertices (again) to edges/faces */
+ EM_select_flush();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
+ BIF_undo_push("Rotate Edge");
+}
+
+/******************* BEVEL CODE STARTS HERE ********************/
+
+static void bevel_displace_vec(float *midvec, float *v1, float *v2, float *v3, float d, float no[3])
+{
+ float a[3], c[3], n_a[3], n_c[3], mid[3], ac, ac2, fac;
+
+ VecSubf(a, v1, v2);
+ VecSubf(c, v3, v2);
+
+ Crossf(n_a, a, no);
+ Normalize(n_a);
+ Crossf(n_c, no, c);
+ Normalize(n_c);
+
+ Normalize(a);
+ Normalize(c);
+ ac = Inpf(a, c);
+
+ if (ac == 1 || ac == -1) {
+ midvec[0] = midvec[1] = midvec[2] = 0;
+ return;
+ }
+ ac2 = ac * ac;
+ fac = (float)sqrt((ac2 + 2*ac + 1)/(1 - ac2) + 1);
+ VecAddf(mid, n_c, n_a);
+ Normalize(mid);
+ VecMulf(mid, d * fac);
+ VecAddf(mid, mid, v2);
+ VecCopyf(midvec, mid);
+}
+
+/* Finds the new point using the sinus law to extrapolate a triangle
+ Lots of sqrts which would not be good for a real time algo
+ Using the mid point of the extrapolation of both sides
+ Useless for coplanar quads, but that doesn't happen too often */
+static void fix_bevel_wrap(float *midvec, float *v1, float *v2, float *v3, float *v4, float d, float no[3])
+{
+ float a[3], b[3], c[3], l_a, l_b, l_c, s_a, s_b, s_c, Pos1[3], Pos2[3], Dir[3];
+
+ VecSubf(a, v3, v2);
+ l_a = Normalize(a);
+ VecSubf(b, v4, v3);
+ Normalize(b);
+ VecSubf(c, v1, v2);
+ Normalize(c);
+
+ s_b = Inpf(a, c);
+ s_b = (float)sqrt(1 - (s_b * s_b));
+ s_a = Inpf(b, c);
+ s_a = (float)sqrt(1 - (s_a * s_a));
+ VecMulf(a, -1);
+ s_c = Inpf(a, b);
+ s_c = (float)sqrt(1 - (s_c * s_c));
+
+ l_b = s_b * l_a / s_a;
+ l_c = s_c * l_a / s_a;
+
+ VecMulf(b, l_b);
+ VecMulf(c, l_c);
+
+ VecAddf(Pos1, v2, c);
+ VecAddf(Pos2, v3, b);
+
+ VecAddf(Dir, Pos1, Pos2);
+ VecMulf(Dir, 0.5);
+
+ bevel_displace_vec(midvec, v3, Dir, v2, d, no);
+
+}
+
+
+static char detect_wrap(float *o_v1, float *o_v2, float *v1, float *v2, float *no)
+{
+ float o_a[3], a[3], o_c[3], c[3];
+
+ VecSubf(o_a, o_v1, o_v2);
+ VecSubf(a, v1, v2);
+
+ Crossf(o_c, o_a, no);
+ Crossf(c, a, no);
+
+ if (Inpf(c, o_c) <= 0)
+ return 1;
+ else
+ return 0;
+}
+
+// Detects and fix a quad wrapping after the resize
+// Arguments are the orginal verts followed by the final verts and then the bevel size and the normal
+static void fix_bevel_quad_wrap(float *o_v1, float *o_v2, float *o_v3, float *o_v4, float *v1, float *v2, float *v3, float *v4, float d, float *no)
+{
+ float vec[3];
+ char wrap[4];
+
+ // Quads can wrap partially. Watch out
+ wrap[0] = detect_wrap(o_v1, o_v2, v1, v2, no); // Edge 1-2
+ wrap[1] = detect_wrap(o_v2, o_v3, v2, v3, no); // Edge 2-3
+ wrap[2] = detect_wrap(o_v3, o_v4, v3, v4, no); // Edge 3-4
+ wrap[3] = detect_wrap(o_v4, o_v1, v4, v1, no); // Edge 4-1
+
+ // Edge 1 inverted
+ if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v2, o_v3, o_v4, o_v1, d, no);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ }
+ // Edge 2 inverted
+ else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v3, o_v4, o_v1, o_v2, d, no);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ }
+ // Edge 3 inverted
+ else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v4, o_v1, o_v2, o_v3, d, no);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+ // Edge 4 inverted
+ else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 1) {
+ fix_bevel_wrap(vec, o_v1, o_v2, o_v3, o_v4, d, no);
+ VECCOPY(v4, vec);
+ VECCOPY(v1, vec);
+ }
+ // Edge 2 and 4 inverted
+ else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 1) {
+ VecAddf(vec, v2, v3);
+ VecMulf(vec, 0.5);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ VecAddf(vec, v1, v4);
+ VecMulf(vec, 0.5);
+ VECCOPY(v1, vec);
+ VECCOPY(v4, vec);
+ }
+ // Edge 1 and 3 inverted
+ else if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
+ VecAddf(vec, v1, v2);
+ VecMulf(vec, 0.5);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ VecAddf(vec, v3, v4);
+ VecMulf(vec, 0.5);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+ // Totally inverted
+ else if (wrap[0] == 1 && wrap[1] == 1 && wrap[2] == 1 && wrap[3] == 1) {
+ VecAddf(vec, v1, v2);
+ VecAddf(vec, vec, v3);
+ VecAddf(vec, vec, v4);
+ VecMulf(vec, 0.25);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+
+}
+
+// Detects and fix a tri wrapping after the resize
+// Arguments are the orginal verts followed by the final verts and the normal
+// Triangles cannot wrap partially (not in this situation
+static void fix_bevel_tri_wrap(float *o_v1, float *o_v2, float *o_v3, float *v1, float *v2, float *v3, float *no)
+{
+ if (detect_wrap(o_v1, o_v2, v1, v2, no)) {
+ float vec[3];
+ VecAddf(vec, o_v1, o_v2);
+ VecAddf(vec, vec, o_v3);
+ VecMulf(vec, 1.0f/3.0f);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ }
+}
+
+static void bevel_shrink_faces(float d, int flag)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ float vec[3], no[3], v1[3], v2[3], v3[3], v4[3];
+
+ /* move edges of all faces with efa->f1 & flag closer towards their centers */
+ efa= em->faces.first;
+ while (efa) {
+ if (efa->f1 & flag) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ VECCOPY(no, efa->n);
+ if (efa->v4 == NULL) {
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(efa->v2->co, vec);
+ bevel_displace_vec(vec, v2, v3, v1, d, no);
+ VECCOPY(efa->v3->co, vec);
+ bevel_displace_vec(vec, v3, v1, v2, d, no);
+ VECCOPY(efa->v1->co, vec);
+
+ fix_bevel_tri_wrap(v1, v2, v3, efa->v1->co, efa->v2->co, efa->v3->co, no);
+ } else {
+ VECCOPY(v4, efa->v4->co);
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(efa->v2->co, vec);
+ bevel_displace_vec(vec, v2, v3, v4, d, no);
+ VECCOPY(efa->v3->co, vec);
+ bevel_displace_vec(vec, v3, v4, v1, d, no);
+ VECCOPY(efa->v4->co, vec);
+ bevel_displace_vec(vec, v4, v1, v2, d, no);
+ VECCOPY(efa->v1->co, vec);
+
+ fix_bevel_quad_wrap(v1, v2, v3, v4, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, d, no);
+ }
+ }
+ efa= efa->next;
+ }
+}
+
+static void bevel_shrink_draw(float d, int flag)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ float vec[3], no[3], v1[3], v2[3], v3[3], v4[3], fv1[3], fv2[3], fv3[3], fv4[3];
+
+ /* move edges of all faces with efa->f1 & flag closer towards their centers */
+ efa= em->faces.first;
+ while (efa) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ VECCOPY(no, efa->n);
+ if (efa->v4 == NULL) {
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(fv2, vec);
+ bevel_displace_vec(vec, v2, v3, v1, d, no);
+ VECCOPY(fv3, vec);
+ bevel_displace_vec(vec, v3, v1, v2, d, no);
+ VECCOPY(fv1, vec);
+
+ fix_bevel_tri_wrap(v1, v2, v3, fv1, fv2, fv3, no);
+
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv2);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv2);
+ glVertex3fv(fv3);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv3);
+ glEnd();
+ } else {
+ VECCOPY(v4, efa->v4->co);
+ bevel_displace_vec(vec, v4, v1, v2, d, no);
+ VECCOPY(fv1, vec);
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(fv2, vec);
+ bevel_displace_vec(vec, v2, v3, v4, d, no);
+ VECCOPY(fv3, vec);
+ bevel_displace_vec(vec, v3, v4, v1, d, no);
+ VECCOPY(fv4, vec);
+
+ fix_bevel_quad_wrap(v1, v2, v3, v4, fv1, fv2, fv3, fv4, d, no);
+
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv2);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv2);
+ glVertex3fv(fv3);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv3);
+ glVertex3fv(fv4);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv4);
+ glEnd();
+ }
+ efa= efa->next;
+ }
+}
+
+static void bevel_mesh(float bsize, int allfaces)
+{
+ EditMesh *em = G.editMesh;
+//#define BEV_DEBUG
+/* Enables debug printfs and assigns material indices: */
+/* 2 = edge quad */
+/* 3 = fill polygon (vertex clusters) */
+
+ EditFace *efa, *example; //, *nextvl;
+ EditEdge *eed, *eed2;
+ EditVert *neweve[1024], *eve, *eve2, *eve3, *v1, *v2, *v3, *v4; //, *eve4;
+ //short found4, search;
+ //float f1, f2, f3, f4;
+ float cent[3], min[3], max[3];
+ int a, b, c;
+ float limit= 0.001f;
+
+ if(multires_test()) return;
+
+ waitcursor(1);
+
+ removedoublesflag(1, 0, limit);
+
+ /* tag all original faces */
+ efa= em->faces.first;
+ while (efa) {
+ efa->f1= 0;
+ if (faceselectedAND(efa, 1)||allfaces) {
+ efa->f1= 1;
+ efa->v1->f |= 128;
+ efa->v2->f |= 128;
+ efa->v3->f |= 128;
+ if (efa->v4) efa->v4->f |= 128;
+ }
+ efa->v1->f &= ~64;
+ efa->v2->f &= ~64;
+ efa->v3->f &= ~64;
+ if (efa->v4) efa->v4->f &= ~64;
+
+ efa= efa->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: split\n");
+#endif
+
+ efa= em->faces.first;
+ while (efa) {
+ if (efa->f1 & 1) {
+ efa->f1-= 1;
+ v1= addvertlist(efa->v1->co, efa->v1);
+ v1->f= efa->v1->f & ~128;
+ efa->v1->tmp.v = v1;
+
+ v1= addvertlist(efa->v2->co, efa->v2);
+ v1->f= efa->v2->f & ~128;
+ efa->v2->tmp.v = v1;
+
+ v1= addvertlist(efa->v3->co, efa->v3);
+ v1->f= efa->v3->f & ~128;
+ efa->v3->tmp.v = v1;
+
+ if (efa->v4) {
+ v1= addvertlist(efa->v4->co, efa->v4);
+ v1->f= efa->v4->f & ~128;
+ efa->v4->tmp.v = v1;
+ }
+
+ /* Needs better adaption of creases? */
+ addedgelist(efa->e1->v1->tmp.v,
+ efa->e1->v2->tmp.v,
+ efa->e1);
+ addedgelist(efa->e2->v1->tmp.v,
+ efa->e2->v2->tmp.v,
+ efa->e2);
+ addedgelist(efa->e3->v1->tmp.v,
+ efa->e3->v2->tmp.v,
+ efa->e3);
+ if (efa->e4) addedgelist(efa->e4->v1->tmp.v,
+ efa->e4->v2->tmp.v,
+ efa->e4);
+
+ if(efa->v4) {
+ v1 = efa->v1->tmp.v;
+ v2 = efa->v2->tmp.v;
+ v3 = efa->v3->tmp.v;
+ v4 = efa->v4->tmp.v;
+ addfacelist(v1, v2, v3, v4, efa,NULL);
+ } else {
+ v1= efa->v1->tmp.v;
+ v2= efa->v2->tmp.v;
+ v3= efa->v3->tmp.v;
+ addfacelist(v1, v2, v3, 0, efa,NULL);
+ }
+
+ efa= efa-> next;
+ } else {
+ efa= efa->next;
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if( (efa->v1->f & 128) && (efa->v2->f & 128) && (efa->v3->f & 128) ) {
+ if(efa->v4==NULL || (efa->v4->f & 128)) efa->f |= 128;
+ }
+ }
+
+ delfaceflag(128); // works with face flag now
+
+ /* tag all faces for shrink*/
+ efa= em->faces.first;
+ while (efa) {
+ if (faceselectedAND(efa, 1)||allfaces) {
+ efa->f1= 2;
+ }
+ efa= efa->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: make edge quads\n");
+#endif
+
+ /* find edges that are on each other and make quads between them */
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= eed->f1= 0;
+ if ( ((eed->v1->f & eed->v2->f) & 1) || allfaces)
+ eed->f1 |= 4; /* original edges */
+ eed->tmp.v = 0;
+ eed= eed->next;
+ }
+
+ eed= em->edges.first;
+ while (eed) {
+ if ( ((eed->f1 & 2)==0) && (eed->f1 & 4) ) {
+ eed2= em->edges.first;
+ while (eed2) {
+ if ( (eed2 != eed) && ((eed2->f1 & 2)==0) && (eed->f1 & 4) ) {
+ if (
+ (eed->v1 != eed2->v1) &&
+ (eed->v1 != eed2->v2) &&
+ (eed->v2 != eed2->v1) &&
+ (eed->v2 != eed2->v2) && (
+ ( VecCompare(eed->v1->co, eed2->v1->co, limit) &&
+ VecCompare(eed->v2->co, eed2->v2->co, limit) ) ||
+ ( VecCompare(eed->v1->co, eed2->v2->co, limit) &&
+ VecCompare(eed->v2->co, eed2->v1->co, limit) ) ) )
+ {
+
+#ifdef BEV_DEBUG
+ fprintf(stderr, "bevel_mesh: edge quad\n");
+#endif
+
+ eed->f1 |= 2; /* these edges are finished */
+ eed2->f1 |= 2;
+
+ example= NULL;
+ efa= em->faces.first; /* search example face (for mat_nr, ME_SMOOTH, ...) */
+ while (efa) {
+ if ( (efa->e1 == eed) ||
+ (efa->e2 == eed) ||
+ (efa->e3 == eed) ||
+ (efa->e4 && (efa->e4 == eed)) ) {
+ example= efa;
+ efa= NULL;
+ }
+ if (efa) efa= efa->next;
+ }
+
+ neweve[0]= eed->v1; neweve[1]= eed->v2;
+ neweve[2]= eed2->v1; neweve[3]= eed2->v2;
+
+ if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ efa= NULL;
+
+ if (VecCompare(eed->v1->co, eed2->v2->co, limit)) {
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], example,NULL);
+ } else {
+ efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], example,NULL);
+ }
+
+ if(efa) {
+ float inp;
+ CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
+ inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
+ if(inp < 0.0) flipface(efa);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 1;
+#endif
+ } else fprintf(stderr,"bevel_mesh: error creating face\n");
+ }
+ eed2= NULL;
+ }
+ }
+ if (eed2) eed2= eed2->next;
+ }
+ }
+ eed= eed->next;
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= eed->f1= 0;
+ eed->f1= 0;
+ eed->v1->f1 &= ~1;
+ eed->v2->f1 &= ~1;
+ eed->tmp.v = 0;
+ eed= eed->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: find clusters\n");
+#endif
+
+ /* Look for vertex clusters */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f &= ~(64|128);
+ eve->tmp.v = NULL;
+ eve= eve->next;
+ }
+
+ /* eve->f: 128: first vertex in a list (->tmp.v) */
+ /* 64: vertex is in a list */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve2= em->verts.first;
+ eve3= NULL;
+ while (eve2) {
+ if ((eve2 != eve) && ((eve2->f & (64|128))==0)) {
+ if (VecCompare(eve->co, eve2->co, limit)) {
+ if ((eve->f & (128|64)) == 0) {
+ /* fprintf(stderr,"Found vertex cluster:\n *\n *\n"); */
+ eve->f |= 128;
+ eve->tmp.v = eve2;
+ eve3= eve2;
+ } else if ((eve->f & 64) == 0) {
+ /* fprintf(stderr," *\n"); */
+ if (eve3) eve3->tmp.v = eve2;
+ eve2->f |= 64;
+ eve3= eve2;
+ }
+ }
+ }
+ eve2= eve2->next;
+ if (!eve2) {
+ if (eve3) eve3->tmp.v = NULL;
+ }
+ }
+ eve= eve->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: shrink faces\n");
+#endif
+
+ bevel_shrink_faces(bsize, 2);
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: fill clusters\n");
+#endif
+
+ /* Make former vertex clusters faces */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f &= ~64;
+ eve= eve->next;
+ }
+
+ eve= em->verts.first;
+ while (eve) {
+ if (eve->f & 128) {
+ eve->f &= ~128;
+ a= 0;
+ neweve[a]= eve;
+ eve2 = eve->tmp.v;
+ while (eve2) {
+ a++;
+ neweve[a]= eve2;
+ eve2 = eve2->tmp.v;
+ }
+ a++;
+ efa= NULL;
+ if (a>=3) {
+ example= NULL;
+ efa= em->faces.first; /* search example face */
+ while (efa) {
+ if ( (efa->v1 == neweve[0]) ||
+ (efa->v2 == neweve[0]) ||
+ (efa->v3 == neweve[0]) ||
+ (efa->v4 && (efa->v4 == neweve[0])) ) {
+ example= efa;
+ efa= NULL;
+ }
+ if (efa) efa= efa->next;
+ }
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: Making %d-gon\n", a);
+#endif
+ if (a>4) {
+ cent[0]= cent[1]= cent[2]= 0.0;
+ INIT_MINMAX(min, max);
+ for (b=0; b<a; b++) {
+ VecAddf(cent, cent, neweve[b]->co);
+ DO_MINMAX(neweve[b]->co, min, max);
+ }
+ cent[0]= (min[0]+max[0])/2;
+ cent[1]= (min[1]+max[1])/2;
+ cent[2]= (min[2]+max[2])/2;
+ eve2= addvertlist(cent, NULL);
+ eve2->f |= 1;
+ eed= em->edges.first;
+ while (eed) {
+ c= 0;
+ for (b=0; b<a; b++)
+ if ((neweve[b]==eed->v1) || (neweve[b]==eed->v2)) c++;
+ if (c==2) {
+ if(exist_face(eed->v1, eed->v2, eve2, 0)==0) {
+ efa= addfacelist(eed->v1, eed->v2, eve2, 0, example,NULL);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 2;
+#endif
+ }
+ }
+ eed= eed->next;
+ }
+ } else if (a==4) {
+ if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ /* the order of vertices can be anything, three cases to check */
+ if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
+ efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
+ efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
+ }
+ }
+ }
+ else if (a==3) {
+ if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0)
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, example, NULL);
+ }
+ if(efa) {
+ float inp;
+ CalcNormFloat(neweve[0]->co, neweve[1]->co, neweve[2]->co, efa->n);
+ inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
+ if(inp < 0.0) flipface(efa);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 2;
+#endif
+ }
+ }
+ }
+ eve= eve->next;
+ }
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f1= 0;
+ eve->f &= ~(128|64);
+ eve->tmp.v= NULL;
+ eve= eve->next;
+ }
+
+ recalc_editnormals();
+ waitcursor(0);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+ removedoublesflag(1, 0, limit);
+
+ /* flush selected vertices to edges/faces */
+ EM_select_flush();
+
+#undef BEV_DEBUG
+}
+
+static void bevel_mesh_recurs(float bsize, short recurs, int allfaces)
+{
+ float d;
+ short nr;
+
+ d= bsize;
+ for (nr=0; nr<recurs; nr++) {
+ bevel_mesh(d, allfaces);
+ if (nr==0) d /= 3; else d /= 2;
+ }
+}
+
+void bevel_menu(void) {
+ BME_Mesh *bm;
+ BME_TransData_Head *td;
+ TransInfo *t;
+ int options, res, gbm_free = 0;
+
+ t = BIF_GetTransInfo();
+ if (!G.editBMesh) {
+ G.editBMesh = MEM_callocN(sizeof(*(G.editBMesh)),"bevel_menu() G.editBMesh");
+ gbm_free = 1;
+ }
+
+ G.editBMesh->options = BME_BEVEL_RUNNING | BME_BEVEL_SELECT;
+ G.editBMesh->res = 1;
+
+ while(G.editBMesh->options & BME_BEVEL_RUNNING) {
+ options = G.editBMesh->options;
+ res = G.editBMesh->res;
+ bm = BME_editmesh_to_bmesh(G.editMesh);
+ BIF_undo_push("Pre-Bevel");
+ free_editMesh(G.editMesh);
+ BME_bevel(bm,0.1f,res,options,0,0,&td);
+ BME_bmesh_to_editmesh(bm, td);
+ EM_selectmode_flush();
+ G.editBMesh->bm = bm;
+ G.editBMesh->td = td;
+ initTransform(TFM_BEVEL,CTX_BMESH);
+ Transform();
+ BME_free_transdata(td);
+ BME_free_mesh(bm);
+ if (t->state != TRANS_CONFIRM) {
+ BIF_undo();
+ }
+ if (options == G.editBMesh->options) {
+ G.editBMesh->options &= ~BME_BEVEL_RUNNING;
+ }
+ }
+
+ if (gbm_free) {
+ MEM_freeN(G.editBMesh);
+ G.editBMesh = NULL;
+ }
+}
+
+
+void bevel_menu_old()
+{
+ char Finished = 0, Canceled = 0, str[100], Recalc = 0;
+ short mval[2], oval[2], curval[2], event = 0, recurs = 1, nr;
+ float vec[3], d, drawd=0.0, center[3], fac = 1;
+
+ getmouseco_areawin(mval);
+ oval[0] = mval[0]; oval[1] = mval[1];
+
+ // Silly hackish code to initialise the variable (warning if not done)
+ // while still drawing in the first iteration (and without using another variable)
+ curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
+
+ // Init grabz for window to vec conversions
+ initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]);
+ window_to_3d(center, mval[0], mval[1]);
+
+ if(button(&recurs, 1, 4, "Recursion:")==0) return;
+
+ for (nr=0; nr<recurs-1; nr++) {
+ if (nr==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * nr * 2.0f);
+ }
+
+ EM_set_flag_all(SELECT);
+
+ SetBlenderCursor(SYSCURSOR);
+
+ while (Finished == 0)
+ {
+ getmouseco_areawin(mval);
+ if (mval[0] != curval[0] || mval[1] != curval[1] || (Recalc == 1))
+ {
+ Recalc = 0;
+ curval[0] = mval[0];
+ curval[1] = mval[1];
+
+ window_to_3d(vec, mval[0]-oval[0], mval[1]-oval[1]);
+ d = Normalize(vec) / 10;
+
+
+ drawd = d * fac;
+ if (G.qual & LR_CTRLKEY)
+ drawd = (float) floor(drawd * 10.0f)/10.0f;
+ if (G.qual & LR_SHIFTKEY)
+ drawd /= 10;
+
+ /*------------- Preview lines--------------- */
+
+ /* uses callback mechanism to draw it all in current area */
+ scrarea_do_windraw(curarea);
+
+ /* set window matrix to perspective, default an area returns with buttons transform */
+ persp(PERSP_VIEW);
+ /* make a copy, for safety */
+ glPushMatrix();
+ /* multiply with the object transformation */
+ mymultmatrix(G.obedit->obmat);
+
+ glColor3ub(255, 255, 0);
+
+ // PREVIEW CODE GOES HERE
+ bevel_shrink_draw(drawd, 2);
+
+ /* restore matrix transform */
+ glPopMatrix();
+
+ sprintf(str, "Bevel Size: %.4f LMB to confirm, RMB to cancel, SPACE to input directly.", drawd);
+ headerprint(str);
+
+ /* this also verifies other area/windows for clean swap */
+ screen_swapbuffers();
+
+ persp(PERSP_WIN);
+
+ glDrawBuffer(GL_FRONT);
+
+ BIF_ThemeColor(TH_WIRE);
+
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2sv(mval);
+ glVertex2sv(oval);
+ glEnd();
+ setlinestyle(0);
+
+ persp(PERSP_VIEW);
+ bglFlush(); // flush display for frontbuffer
+ glDrawBuffer(GL_BACK);
+ }
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
+ /* val==0 on key-release event */
+ if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event==ESCKEY)) {
+ if (event==RIGHTMOUSE || event==ESCKEY)
+ Canceled = 1;
+ Finished = 1;
+ }
+ else if (val && event==SPACEKEY) {
+ if (fbutton(&d, 0.000, 10.000, 10, 0, "Width:")!=0) {
+ drawd = d * fac;
+ Finished = 1;
+ }
+ }
+ else if (val) {
+ /* On any other keyboard event, recalc */
+ Recalc = 1;
+ }
+
+ }
+ }
+ if (Canceled==0) {
+ SetBlenderCursor(BC_WAITCURSOR);
+ bevel_mesh_recurs(drawd/fac, recurs, 1);
+ righthandfaces(1);
+ SetBlenderCursor(SYSCURSOR);
+ BIF_undo_push("Bevel");
+ }
+}
+
+/* *********** END BEVEL *********/
+typedef struct SlideUv {
+ float origuv[2];
+ float *uv_up, *uv_down;
+ //float *fuv[4];
+ LinkNode *fuv_list;
+} SlideUv;
+
+typedef struct SlideVert {
+ EditEdge *up,*down;
+ EditVert origvert;
+} SlideVert;
+
+int EdgeLoopDelete(void) {
+
+ /* temporal flag setting so we keep UVs when deleting edge loops,
+ * this is a bit of a hack but it works how you would want in almost all cases */
+ short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag;
+ G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+
+ if(!EdgeSlide(1, 1)) {
+ return 0;
+ }
+
+ /* restore uvcalc flag */
+ G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
+
+ EM_select_more();
+ removedoublesflag(1,0, 0.001);
+ EM_select_flush();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ return 1;
+}
+
+int EdgeSlide(short immediate, float imperc)
+{
+ NumInput num;
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
+ EditVert *ev, *nearest;
+ LinkNode *edgelist = NULL, *vertlist=NULL, *look;
+ GHash *vertgh;
+
+ SlideVert *tempsv;
+ float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4];
+ float shiftlabda= 0.0f,len = 0.0f;
+ int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0;
+ int wasshift = 0;
+
+ /* UV correction vars */
+ GHash **uvarray= NULL;
+ int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE);
+ int uvlay_idx;
+ SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
+ float uv_tmp[2];
+ LinkNode *fuv_link;
+
+ short event, draw=1;
+ short mval[2], mvalo[2];
+ char str[128];
+ float labda = 0.0f;
+
+ initNumInput(&num);
+
+ view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
+
+ mvalo[0] = -1; mvalo[1] = -1;
+ numsel =0;
+
+ // Get number of selected edges and clear some flags
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ eed->f1 = 0;
+ eed->f2 = 0;
+ if(eed->f & SELECT) numsel++;
+ }
+
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ ev->f1 = 0;
+ }
+
+ //Make sure each edge only has 2 faces
+ // make sure loop doesn't cross face
+ for(efa=em->faces.first;efa;efa=efa->next) {
+ int ct = 0;
+ if(efa->e1->f & SELECT) {
+ ct++;
+ efa->e1->f1++;
+ if(efa->e1->f1 > 2) {
+ error("3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e2->f & SELECT) {
+ ct++;
+ efa->e2->f1++;
+ if(efa->e2->f1 > 2) {
+ error("3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e3->f & SELECT) {
+ ct++;
+ efa->e3->f1++;
+ if(efa->e3->f1 > 2) {
+ error("3+ face edge");
+ return 0;
+ }
+ }
+ if(efa->e4 && efa->e4->f & SELECT) {
+ ct++;
+ efa->e4->f1++;
+ if(efa->e4->f1 > 2) {
+ error("3+ face edge");
+ return 0;
+ }
+ }
+ // Make sure loop is not 2 edges of same face
+ if(ct > 1) {
+ error("loop crosses itself");
+ return 0;
+ }
+ }
+ // Get # of selected verts
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ if(ev->f & SELECT) vertsel++;
+ }
+
+ // Test for multiple segments
+ if(vertsel > numsel+1) {
+ error("Was not a single edge loop");
+ return 0;
+ }
+
+ // Get the edgeloop in order - mark f1 with SELECT once added
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
+ // If this is the first edge added, just put it in
+ if(!edgelist) {
+ BLI_linklist_prepend(&edgelist,eed);
+ numadded++;
+ first = eed;
+ last = eed;
+ eed->f1 = SELECT;
+ } else {
+ if(editedge_getSharedVert(eed, last)) {
+ BLI_linklist_append(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ last = eed;
+ } else if(editedge_getSharedVert(eed, first)) {
+ BLI_linklist_prepend(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ first = eed;
+ }
+ }
+ }
+ if(eed->next == NULL && numadded != numsel) {
+ eed=em->edges.first;
+ timesthrough++;
+ }
+
+ // It looks like there was an unexpected case - Hopefully should not happen
+ if(timesthrough >= numsel*2) {
+ BLI_linklist_free(edgelist,NULL);
+ error("could not order loop");
+ return 0;
+ }
+ }
+
+ // Put the verts in order in a linklist
+ look = edgelist;
+ while(look) {
+ eed = look->link;
+ if(!vertlist) {
+ if(look->next) {
+ temp = look->next->link;
+
+ //This is the first entry takes care of extra vert
+ if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else {
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ } else {
+ //This is the case that we only have 1 edge
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ }
+ }
+ // for all the entries
+ if(eed->v1->f1 != 1) {
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else if(eed->v2->f1 != 1) {
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ look = look->next;
+ }
+
+ // populate the SlideVerts
+
+ vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ look = vertlist;
+ while(look) {
+ i=0;
+ j=0;
+ ev = look->link;
+ tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert");
+ tempsv->up = NULL;
+ tempsv->down = NULL;
+ tempsv->origvert.co[0] = ev->co[0];
+ tempsv->origvert.co[1] = ev->co[1];
+ tempsv->origvert.co[2] = ev->co[2];
+ tempsv->origvert.no[0] = ev->no[0];
+ tempsv->origvert.no[1] = ev->no[1];
+ tempsv->origvert.no[2] = ev->no[2];
+ // i is total edges that vert is on
+ // j is total selected edges that vert is on
+
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(eed->v1 == ev || eed->v2 == ev) {
+ i++;
+ if(eed->f & SELECT) {
+ j++;
+ }
+ }
+ }
+ // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
+ if(i == 4 && j == 2) {
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(editedge_containsVert(eed, ev)) {
+ if(!(eed->f & SELECT)) {
+ if(!tempsv->up) {
+ tempsv->up = eed;
+ } else if (!(tempsv->down)) {
+ tempsv->down = eed;
+ }
+ }
+ }
+ }
+ }
+ // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
+ if(i >= 3 && j == 1) {
+ for(eed=em->edges.first;eed;eed=eed->next) {
+ if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
+ for(efa = em->faces.first;efa;efa=efa->next) {
+ if(editface_containsEdge(efa, eed)) {
+ if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e1;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e1;
+ }
+ }
+ if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e2;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e2;
+ }
+ }
+ if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e3;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e3;
+ }
+ }
+ if(efa->e4) {
+ if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
+ if(!tempsv->up) {
+ tempsv->up = efa->e4;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e4;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if(i > 4 && j == 2) {
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return 0;
+ }
+ BLI_ghash_insert(vertgh,ev,tempsv);
+
+ look = look->next;
+ }
+
+ // make sure the UPs nad DOWNs are 'faceloops'
+ // Also find the nearest slidevert to the cursor
+ getmouseco_areawin(mval);
+ look = vertlist;
+ nearest = NULL;
+ vertdist = -1;
+ while(look) {
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+
+ if(!tempsv->up || !tempsv->down) {
+ error("Missing rails");
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return 0;
+ }
+
+ if(G.f & G_DRAW_EDGELEN) {
+ if(!(tempsv->up->f & SELECT)) {
+ tempsv->up->f |= SELECT;
+ tempsv->up->f2 |= 16;
+ } else {
+ tempsv->up->f2 |= ~16;
+ }
+ if(!(tempsv->down->f & SELECT)) {
+ tempsv->down->f |= SELECT;
+ tempsv->down->f2 |= 16;
+ } else {
+ tempsv->down->f2 |= ~16;
+ }
+ }
+
+ if(look->next != NULL) {
+ SlideVert *sv;
+
+ sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link);
+
+ if(sv) {
+ float tempdist, co[2];
+
+ if(!sharesFace(tempsv->up,sv->up)) {
+ EditEdge *swap;
+ swap = sv->up;
+ sv->up = sv->down;
+ sv->down = swap;
+ }
+
+ view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
+
+ tempdist = sqrt(pow(co[0] - mval[0],2)+pow(co[1] - mval[1],2));
+
+ if(vertdist < 0) {
+ vertdist = tempdist;
+ nearest = (EditVert*)look->link;
+ } else if ( tempdist < vertdist ) {
+ vertdist = tempdist;
+ nearest = (EditVert*)look->link;
+ }
+ }
+ }
+
+
+
+ look = look->next;
+ }
+
+
+ if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ int maxnum = 0;
+ uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
+ suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */
+ suv = NULL;
+
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+
+ uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ for(ev=em->verts.first;ev;ev=ev->next) {
+ ev->tmp.l = 0;
+ }
+ look = vertlist;
+ while(look) {
+ float *uv_new;
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+
+ ev = look->link;
+ suv = NULL;
+ for(efa = em->faces.first;efa;efa=efa->next) {
+ if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
+ int k=-1; /* face corner */
+
+ /* Is this vert in the faces corner? */
+ if (efa->v1==ev) k=0;
+ else if (efa->v2==ev) k=1;
+ else if (efa->v3==ev) k=2;
+ else if (efa->v4 && efa->v4==ev) k=3;
+
+ if (k != -1) {
+ MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
+ EditVert *ev_up, *ev_down;
+
+ uv_new = tf->uv[k];
+
+ if (ev->tmp.l) {
+ if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) {
+ ev->tmp.l = -1; /* Tag as invalid */
+ BLI_linklist_free(suv->fuv_list,NULL);
+ suv->fuv_list = NULL;
+ BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
+ suv = NULL;
+ break;
+ }
+ } else {
+ ev->tmp.l = 1;
+ suv = suv_last;
+
+ suv->fuv_list = NULL;
+ suv->uv_up = suv->uv_down = NULL;
+ suv->origuv[0] = uv_new[0];
+ suv->origuv[1] = uv_new[1];
+
+ BLI_linklist_prepend(&suv->fuv_list, uv_new);
+ BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
+
+ suv_last++; /* advance to next slide UV */
+ maxnum++;
+ }
+
+ /* Now get the uvs along the up or down edge if we can */
+ if (suv) {
+ if (!suv->uv_up) {
+ ev_up = editedge_getOtherVert(tempsv->up,ev);
+ if (efa->v1==ev_up) suv->uv_up = tf->uv[0];
+ else if (efa->v2==ev_up) suv->uv_up = tf->uv[1];
+ else if (efa->v3==ev_up) suv->uv_up = tf->uv[2];
+ else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3];
+ }
+ if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
+ ev_down = editedge_getOtherVert(tempsv->down,ev);
+ if (efa->v1==ev_down) suv->uv_down = tf->uv[0];
+ else if (efa->v2==ev_down) suv->uv_down = tf->uv[1];
+ else if (efa->v3==ev_down) suv->uv_down = tf->uv[2];
+ else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3];
+ }
+
+ /* Copy the pointers to the face UV's */
+ BLI_linklist_prepend(&suv->fuv_list, uv_new);
+ }
+ }
+ }
+ }
+ look = look->next;
+ }
+ } /* end uv layer loop */
+ } /* end uvlay_tot */
+
+
+
+ // we should have enough info now to slide
+
+ len = 0.0f;
+
+ percp = -1;
+ while(draw) {
+ /* For the % calculation */
+ short mval[2];
+ float rc[2];
+ float v2[2], v3[2];
+ EditVert *centerVert, *upVert, *downVert;
+
+ getmouseco_areawin(mval);
+
+ if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) {
+ PIL_sleep_ms(10);
+ } else {
+ char *p = str;;
+
+ mvalo[0] = mval[0];
+ mvalo[1] = mval[1];
+
+
+ tempsv = BLI_ghash_lookup(vertgh,nearest);
+
+ centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
+ upVert = editedge_getOtherVert(tempsv->up, centerVert);
+ downVert = editedge_getOtherVert(tempsv->down, centerVert);
+
+ view3d_project_float(curarea, upVert->co, v2, projectMat);
+ view3d_project_float(curarea, downVert->co, v3, projectMat);
+
+ /* Determine the % on which the loop should be cut */
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if (len==0) {len = 0.0001;}
+
+ if ((G.qual & LR_SHIFTKEY)==0) {
+ wasshift = 0;
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;
+ }
+ else {
+ if (wasshift==0) {
+ wasshift = 1;
+ shiftlabda = labda;
+ }
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;
+ }
+
+
+ if(labda<=0.0) labda=0.0;
+ else if(labda>=1.0)labda=1.0;
+
+ perc=((1-labda)*2)-1;
+
+ if(G.qual == 0) {
+ perc *= 100;
+ perc = floor(perc);
+ perc /= 100;
+ } else if (G.qual == LR_CTRLKEY) {
+ perc *= 10;
+ perc = floor(perc);
+ perc /= 10;
+ }
+
+ if(prop == 0) {
+ len = VecLenf(upVert->co,downVert->co)*((perc+1)/2);
+ if(flip == 1) {
+ len = VecLenf(upVert->co,downVert->co) - len;
+ }
+ }
+
+ if (hasNumInput(&num))
+ {
+ applyNumInput(&num, &perc);
+
+ if (prop)
+ {
+ perc = MIN2(perc, 1);
+ perc = MAX2(perc, -1);
+ }
+ else
+ {
+ len = MIN2(perc, VecLenf(upVert->co,downVert->co));
+ len = MAX2(len, 0);
+ }
+ }
+
+ //Adjust Edgeloop
+ if(immediate) {
+ perc = imperc;
+ }
+ percp = perc;
+ if(prop) {
+ look = vertlist;
+ while(look) {
+ EditVert *tempev;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+
+ tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
+ VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
+
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+
+ look = look->next;
+ }
+ }
+ else {
+ //Non prop code
+ look = vertlist;
+ while(look) {
+ float newlen;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+ newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co));
+ if(newlen > 1.0) {newlen = 1.0;}
+ if(newlen < 0.0) {newlen = 0.0;}
+ if(flip == 0) {
+ VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ /* dont do anything if no UVs */
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+ } else{
+ VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
+
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ /* dont do anything if no UVs */
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
+ if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
+ Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
+ fuv_link = suv->fuv_list;
+ while (fuv_link) {
+ VECCOPY2D(((float *)fuv_link->link), uv_tmp);
+ fuv_link = fuv_link->next;
+ }
+ }
+ }
+ }
+ }
+ look = look->next;
+ }
+
+ }
+
+ // Highlight the Control Edges
+ scrarea_do_windraw(curarea);
+ persp(PERSP_VIEW);
+ glPushMatrix();
+ mymultmatrix(G.obedit->obmat);
+
+ glColor3ub(0, 255, 0);
+ glBegin(GL_LINES);
+ glVertex3fv(upVert->co);
+ glVertex3fv(downVert->co);
+ glEnd();
+
+ if(prop == 0) {
+ // draw start edge for non-prop
+ glPointSize(5);
+ glBegin(GL_POINTS);
+ glColor3ub(255,0,255);
+ if(flip) {
+ glVertex3fv(upVert->co);
+ } else {
+ glVertex3fv(downVert->co);
+ }
+ glEnd();
+ }
+
+
+ glPopMatrix();
+
+ if(prop) {
+ p += sprintf(str, "(P)ercentage: ");
+ } else {
+ p += sprintf(str, "Non (P)rop Length: ");
+ }
+
+ if (hasNumInput(&num))
+ {
+ char num_str[20];
+
+ outputNumInput(&num, num_str);
+ p += sprintf(p, "%s", num_str);
+ }
+ else
+ {
+ if (prop)
+ {
+ p += sprintf(p, "%f", perc);
+ }
+ else
+ {
+ p += sprintf(p, "%f", len);
+ }
+ }
+
+
+ if (prop == 0) {
+ p += sprintf(p, ", Press (F) to flip control side");
+ }
+
+ headerprint(str);
+ screen_swapbuffers();
+ }
+ if(!immediate) {
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
+ /* val==0 on key-release event */
+ if (val) {
+ if(ELEM(event, ESCKEY, RIGHTMOUSE)) {
+ prop = 1; // Go back to prop mode
+ imperc = 0; // This is the % that gets set for immediate
+ immediate = 1; //Run through eval code 1 more time
+ cancel = 1; // Return -1
+ mvalo[0] = -1;
+ } else if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)) {
+ draw = 0; // End looping now
+ } else if(event==MIDDLEMOUSE) {
+ perc = 0;
+ immediate = 1;
+ } else if(event==PKEY) {
+ initNumInput(&num); /* reset num input */
+ if (prop) {
+ prop = 0;
+ num.flag |= NUM_NO_NEGATIVE;
+ }
+ else {
+ prop = 1;
+ }
+ mvalo[0] = -1;
+ } else if(event==FKEY) {
+ (flip == 1) ? (flip = 0):(flip = 1);
+ mvalo[0] = -1;
+ } else if(ELEM(event, RIGHTARROWKEY, WHEELUPMOUSE)) { // Scroll through Control Edges
+ look = vertlist;
+ while(look) {
+ if(nearest == (EditVert*)look->link) {
+ if(look->next == NULL) {
+ nearest = (EditVert*)vertlist->link;
+ } else {
+ nearest = (EditVert*)look->next->link;
+ }
+ mvalo[0] = -1;
+ break;
+ }
+ look = look->next;
+ }
+ } else if(ELEM(event, LEFTARROWKEY, WHEELDOWNMOUSE)) { // Scroll through Control Edges
+ look = vertlist;
+ while(look) {
+ if(look->next) {
+ if(look->next->link == nearest) {
+ nearest = (EditVert*)look->link;
+ mvalo[0] = -1;
+ break;
+ }
+ } else {
+ if((EditVert*)vertlist->link == nearest) {
+ nearest = look->link;
+ mvalo[0] = -1;
+ break;
+ }
+ }
+ look = look->next;
+ }
+ }
+
+ if (handleNumInput(&num, event))
+ {
+ mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */
+ }
+ }
+
+ }
+ } else {
+ draw = 0;
+ }
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ }
+
+
+ if(G.f & G_DRAW_EDGELEN) {
+ look = vertlist;
+ while(look) {
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+ if(tempsv != NULL) {
+ tempsv->up->f &= !SELECT;
+ tempsv->down->f &= !SELECT;
+ }
+ look = look->next;
+ }
+ }
+
+ force_draw(0);
+
+ if(!immediate)
+ EM_automerge(0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ scrarea_queue_winredraw(curarea);
+
+ //BLI_ghash_free(edgesgh, freeGHash, NULL);
+ BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+
+ if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+ BLI_ghash_free(uvarray[uvlay_idx], NULL, NULL);
+ }
+ MEM_freeN(uvarray);
+ MEM_freeN(slideuvs);
+
+ suv = suv_last-1;
+ while (suv >= slideuvs) {
+ if (suv->fuv_list) {
+ BLI_linklist_free(suv->fuv_list,NULL);
+ }
+ suv--;
+ }
+
+ allqueue(REDRAWIMAGE, 0);
+ }
+
+ if(cancel == 1) {
+ return -1;
+ }
+ else {
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ }
+#endif
+ }
+ return 1;
+}
+
+/* -------------------- More tools ------------------ */
+
+void mesh_set_face_flags(short mode)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ MTFace *tface;
+ short m_tex=0, m_tiles=0, m_shared=0,
+ m_light=0, m_invis=0, m_collision=0,
+ m_twoside=0, m_obcolor=0, m_halo=0,
+ m_billboard=0, m_shadow=0, m_text=0,
+ m_sort=0;
+ short flag = 0, change = 0;
+
+ if (!EM_texFaceCheck()) {
+ error("not a mesh with uv/image layers");
+ return;
+ }
+
+ add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL);
+ add_numbut(1, TOG|SHO, "Tiles", 0, 0, &m_tiles, NULL);
+ add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL);
+ add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL);
+ add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL);
+ add_numbut(5, TOG|SHO, "Shared", 0, 0, &m_shared, NULL);
+ add_numbut(6, TOG|SHO, "Twoside", 0, 0, &m_twoside, NULL);
+ add_numbut(7, TOG|SHO, "ObColor", 0, 0, &m_obcolor, NULL);
+ add_numbut(8, TOG|SHO, "Halo", 0, 0, &m_halo, NULL);
+ add_numbut(9, TOG|SHO, "Billboard", 0, 0, &m_billboard, NULL);
+ add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL);
+ add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL);
+ add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL);
+
+ if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW))
+ return;
+
+ /* these 2 cant both be on */
+ if (mode) /* are we seeting*/
+ if (m_halo)
+ m_billboard = 0;
+
+ if (m_tex) flag |= TF_TEX;
+ if (m_tiles) flag |= TF_TILES;
+ if (m_shared) flag |= TF_SHAREDCOL;
+ if (m_light) flag |= TF_LIGHT;
+ if (m_invis) flag |= TF_INVISIBLE;
+ if (m_collision) flag |= TF_DYNAMIC;
+ if (m_twoside) flag |= TF_TWOSIDE;
+ if (m_obcolor) flag |= TF_OBCOL;
+ if (m_halo) flag |= TF_BILLBOARD;
+ if (m_billboard) flag |= TF_BILLBOARD2;
+ if (m_shadow) flag |= TF_SHADOW;
+ if (m_text) flag |= TF_BMFONT;
+ if (m_sort) flag |= TF_ALPHASORT;
+
+ if (flag==0)
+ return;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f & SELECT) {
+ tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (mode) tface->mode |= flag;
+ else tface->mode &= ~flag;
+ change = 1;
+ }
+ efa= efa->next;
+ }
+
+ if (change) {
+ BIF_undo_push((mode ? "Set Flags" : "Clear Flags"));
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+void mesh_set_smooth_faces(short event)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+
+ if(G.obedit==0) return;
+
+ if(G.obedit->type != OB_MESH) return;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f & SELECT) {
+ if(event==1) efa->flag |= ME_SMOOTH;
+ else if(event==0) efa->flag &= ~ME_SMOOTH;
+ }
+ efa= efa->next;
+ }
+
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+
+ if(event==1) BIF_undo_push("Set Smooth");
+ else if(event==0) BIF_undo_push("Set Solid");
+}
+
+/* helper to find edge for edge_rip */
+static float mesh_rip_edgedist(float mat[][4], float *co1, float *co2, short *mval)
+{
+ float vec1[3], vec2[3], mvalf[2];
+
+ view3d_project_float(curarea, co1, vec1, mat);
+ view3d_project_float(curarea, co2, vec2, mat);
+ mvalf[0]= (float)mval[0];
+ mvalf[1]= (float)mval[1];
+
+ return PdistVL2Dfl(mvalf, vec1, vec2);
+}
+
+/* helper for below */
+static void mesh_rip_setface(EditFace *sefa)
+{
+ /* put new vertices & edges in best face */
+ if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v;
+ if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v;
+ if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v;
+ if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v;
+
+ sefa->e1= addedgelist(sefa->v1, sefa->v2, sefa->e1);
+ sefa->e2= addedgelist(sefa->v2, sefa->v3, sefa->e2);
+ if(sefa->v4) {
+ sefa->e3= addedgelist(sefa->v3, sefa->v4, sefa->e3);
+ sefa->e4= addedgelist(sefa->v4, sefa->v1, sefa->e4);
+ }
+ else
+ sefa->e3= addedgelist(sefa->v3, sefa->v1, sefa->e3);
+
+}
+
+/* based on mouse cursor position, it defines how is being ripped */
+void mesh_rip(void)
+{
+ extern void faceloop_select(EditEdge *startedge, int select);
+ EditMesh *em = G.editMesh;
+ EditVert *eve, *nextve;
+ EditEdge *eed, *seed= NULL;
+ EditFace *efa, *sefa= NULL;
+ float projectMat[4][4], viewMat[4][4], vec[3], dist, mindist;
+ short doit= 1, mval[2],propmode,prop;
+
+ propmode = G.scene->prop_mode;
+ G.scene->prop_mode = 0;
+ prop = G.scene->proportional;
+ G.scene->proportional = 0;
+
+ /* select flush... vertices are important */
+ EM_selectmode_set();
+
+ getmouseco_areawin(mval);
+ view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
+
+ /* find best face, exclude triangles and break on face select or faces with 2 edges select */
+ mindist= 1000000.0f;
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ if( efa->f & 1)
+ break;
+ if(efa->v4 && faceselectedOR(efa, SELECT) ) {
+ int totsel=0;
+
+ if(efa->e1->f & SELECT) totsel++;
+ if(efa->e2->f & SELECT) totsel++;
+ if(efa->e3->f & SELECT) totsel++;
+ if(efa->e4->f & SELECT) totsel++;
+
+ if(totsel>1)
+ break;
+ view3d_project_float(curarea, efa->cent, vec, projectMat);
+ dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) );
+ if(dist<mindist) {
+ mindist= dist;
+ sefa= efa;
+ }
+ }
+ }
+
+ if(efa) {
+ error("Can't perform ripping with faces selected this way");
+ return;
+ }
+ if(sefa==NULL) {
+ error("No proper selection or faces included");
+ return;
+ }
+
+
+ /* duplicate vertices, new vertices get selected */
+ for(eve = em->verts.last; eve; eve= eve->prev) {
+ eve->tmp.v = NULL;
+ if(eve->f & SELECT) {
+ eve->tmp.v = addvertlist(eve->co, eve);
+ eve->f &= ~SELECT;
+ eve->tmp.v->f |= SELECT;
+ }
+ }
+
+ /* find the best candidate edge */
+ /* or one of sefa edges is selected... */
+ if(sefa->e1->f & SELECT) seed= sefa->e2;
+ if(sefa->e2->f & SELECT) seed= sefa->e1;
+ if(sefa->e3->f & SELECT) seed= sefa->e2;
+ if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3;
+
+ /* or we do the distance trick */
+ if(seed==NULL) {
+ mindist= 1000000.0f;
+ if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) {
+ dist = mesh_rip_edgedist(projectMat,
+ sefa->e1->v1->co,
+ sefa->e1->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e1;
+ mindist= dist;
+ }
+ }
+ if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) {
+ dist = mesh_rip_edgedist(projectMat,
+ sefa->e2->v1->co,
+ sefa->e2->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e2;
+ mindist= dist;
+ }
+ }
+ if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) {
+ dist= mesh_rip_edgedist(projectMat,
+ sefa->e3->v1->co,
+ sefa->e3->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e3;
+ mindist= dist;
+ }
+ }
+ if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) {
+ dist= mesh_rip_edgedist(projectMat,
+ sefa->e4->v1->co,
+ sefa->e4->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e4;
+ mindist= dist;
+ }
+ }
+ }
+
+ if(seed==NULL) { // never happens?
+ error("No proper edge found to start");
+ return;
+ }
+
+ faceloop_select(seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1
+
+ /* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */
+ for(eed = em->edges.last; eed; eed= eed->prev) {
+ eed->tmp.v = NULL;
+ if((eed->v1->tmp.v) || (eed->v2->tmp.v)) {
+ EditEdge *newed;
+
+ newed= addedgelist(eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,
+ eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed);
+ if(eed->f & SELECT) {
+ eed->f &= ~SELECT;
+ newed->f |= SELECT;
+ }
+ eed->tmp.v = (EditVert *)newed;
+ }
+ }
+
+ /* first clear edges to help finding neighbours */
+ for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
+
+ /* put new vertices & edges && flag in best face */
+ mesh_rip_setface(sefa);
+
+ /* starting with neighbours of best face, we loop over the seam */
+ sefa->f1= 2;
+ doit= 1;
+ while(doit) {
+ doit= 0;
+
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ /* new vert in face */
+ if (efa->v1->tmp.v || efa->v2->tmp.v ||
+ efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) {
+ /* face is tagged with loop */
+ if(efa->f1==1) {
+ mesh_rip_setface(efa);
+ efa->f1= 2;
+ doit= 1;
+ }
+ }
+ }
+ }
+
+ /* remove loose edges, that were part of a ripped face */
+ for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
+ for(efa= em->faces.first; efa; efa=efa->next) {
+ efa->e1->f1= 1;
+ efa->e2->f1= 1;
+ efa->e3->f1= 1;
+ if(efa->e4) efa->e4->f1= 1;
+ }
+
+ for(eed = em->edges.last; eed; eed= seed) {
+ seed= eed->prev;
+ if(eed->f1==0) {
+ if(eed->v1->tmp.v || eed->v2->tmp.v ||
+ (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) {
+ remedge(eed);
+ free_editedge(eed);
+ eed= NULL;
+ }
+ }
+ if(eed) {
+ eed->v1->f1= 1;
+ eed->v2->f1= 1;
+ }
+ }
+
+ /* and remove loose selected vertices, that got duplicated accidentally */
+ for(eve = em->verts.first; eve; eve= nextve) {
+ nextve= eve->next;
+ if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) {
+ BLI_remlink(&em->verts,eve);
+ free_editvert(eve);
+ }
+ }
+
+ countall(); // apparently always needed when adding stuff, derived mesh
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ }
+#endif
+
+ BIF_TransformSetUndo("Rip");
+ initTransform(TFM_TRANSLATION, 0);
+ Transform();
+
+ G.scene->prop_mode = propmode;
+ G.scene->proportional = prop;
+}
+
+void shape_propagate(){
+ EditMesh *em = G.editMesh;
+ EditVert *ev = NULL;
+ Mesh* me = (Mesh*)G.obedit->data;
+ Key* ky = NULL;
+ KeyBlock* kb = NULL;
+ Base* base=NULL;
+
+
+ if(me->key){
+ ky = me->key;
+ } else {
+ error("Object Has No Key");
+ return;
+ }
+
+ if(ky->block.first){
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ for(kb=ky->block.first;kb;kb = kb->next){
+ float *data;
+ data = kb->data;
+ VECCOPY(data+(ev->keyindex*3),ev->co);
+ }
+ }
+ }
+ } else {
+ error("Object Has No Blendshapes");
+ return;
+ }
+
+ //TAG Mesh Objects that share this data
+ for(base = G.scene->base.first; base; base = base->next){
+ if(base->object && base->object->data == me){
+ base->object->recalc = OB_RECALC_DATA;
+ }
+ }
+
+ BIF_undo_push("Propagate Blendshape Verts");
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+}
+
+void shape_copy_from_lerp(KeyBlock* thisBlock, KeyBlock* fromBlock)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *ev = NULL;
+ short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ;
+ float perc = 0;
+ char str[64];
+ float *data, *odata;
+
+ data = fromBlock->data;
+ odata = thisBlock->data;
+
+ getmouseco_areawin(mval);
+ curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
+
+ while (finished == 0)
+ {
+ getmouseco_areawin(mval);
+ if (mval[0] != curval[0] || mval[1] != curval[1])
+ {
+
+ if(mval[0] > curval[0])
+ perc += 0.1;
+ else if(mval[0] < curval[0])
+ perc -= 0.1;
+
+ if(perc < 0) perc = 0;
+ if(perc > 1) perc = 1;
+
+ curval[0] = mval[0];
+ curval[1] = mval[1];
+
+ if(fullcopy == 1){
+ perc = 1;
+ }
+
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ VecLerpf(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc);
+ }
+ }
+ sprintf(str,"Blending at %d%c MMB to Copy at 100%c",(int)(perc*100),'%','%');
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ headerprint(str);
+ force_draw(0);
+
+ if(fullcopy == 1){
+ break;
+ }
+
+ } else {
+ PIL_sleep_ms(10);
+ }
+
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val);
+ if(val){
+ if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){
+ finished = 1;
+ }
+ else if (event == MIDDLEMOUSE){
+ fullcopy = 1;
+ }
+ else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){
+ canceled = 1;
+ finished = 1;
+ }
+ }
+ }
+ }
+ if(!canceled)
+ BIF_undo_push("Copy Blendshape Verts");
+ else
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ VECCOPY(ev->co, odata+(ev->keyindex*3));
+ }
+ }
+ return;
+}
+
+
+
+void shape_copy_select_from()
+{
+ Mesh* me = (Mesh*)G.obedit->data;
+ EditMesh *em = G.editMesh;
+ EditVert *ev = NULL;
+ int totverts = 0,curshape = G.obedit->shapenr;
+
+ Key* ky = NULL;
+ KeyBlock *kb = NULL,*thisBlock = NULL;
+ int maxlen=32, nr=0, a=0;
+ char *menu;
+
+ if(me->key){
+ ky = me->key;
+ } else {
+ error("Object Has No Key");
+ return;
+ }
+
+ if(ky->block.first){
+ for(kb=ky->block.first;kb;kb = kb->next){
+ maxlen += 40; // Size of a block name
+ if(a == curshape-1){
+ thisBlock = kb;
+ }
+
+ a++;
+ }
+ a=0;
+ menu = MEM_callocN(maxlen, "Copy Shape Menu Text");
+ strcpy(menu, "Copy Vert Positions from Shape %t|");
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a != curshape-1){
+ sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a);
+ }
+ a++;
+ }
+ nr = pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+ } else {
+ error("Object Has No Blendshapes");
+ return;
+ }
+
+ a = 0;
+
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a == nr){
+
+ for(ev = em->verts.first;ev;ev = ev->next){
+ totverts++;
+ }
+
+ if(me->totvert != totverts){
+ error("Shape Has had Verts Added/Removed, please cycle editmode before copying");
+ return;
+ }
+ shape_copy_from_lerp(thisBlock,kb);
+
+ return;
+ }
+ a++;
+ }
+ return;
+}
+
+/* Collection Routines|Currently used by the improved merge code*/
+/* buildEdge_collection() creates a list of lists*/
+/* these lists are filled with edges that are topologically connected.*/
+/* This whole tool needs to be redone, its rather poorly implemented...*/
+
+typedef struct Collection{
+ struct Collection *next, *prev;
+ int index;
+ ListBase collectionbase;
+} Collection;
+
+typedef struct CollectedEdge{
+ struct CollectedEdge *next, *prev;
+ EditEdge *eed;
+} CollectedEdge;
+
+#define MERGELIMIT 0.000001
+
+static void build_edgecollection(ListBase *allcollections)
+{
+ EditEdge *eed;
+ Collection *edgecollection, *newcollection;
+ CollectedEdge *newedge;
+
+ int currtag = 1;
+ short ebalanced = 0;
+ short collectionfound = 0;
+
+ for (eed=G.editMesh->edges.first; eed; eed = eed->next){
+ eed->tmp.l = 0;
+ eed->v1->tmp.l = 0;
+ eed->v2->tmp.l = 0;
+ }
+
+ /*1st pass*/
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ eed->v1->tmp.l = currtag;
+ eed->v2->tmp.l = currtag;
+ currtag +=1;
+ }
+ }
+
+ /*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */
+ while(ebalanced == 0){
+ ebalanced = 1;
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next){
+ if(eed->f&SELECT){
+ if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{
+ if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
+ else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
+ ebalanced = 0;
+ }
+ }
+ }
+ }
+
+ /*3rd pass, set all the edge flags (unnessecary?)*/
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next){
+ if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l;
+ }
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ if(allcollections->first){
+ for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){
+ if(edgecollection->index == eed->tmp.l){
+ newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
+ newedge->eed = eed;
+ BLI_addtail(&(edgecollection->collectionbase), newedge);
+ collectionfound = 1;
+ break;
+ }
+ else collectionfound = 0;
+ }
+ }
+ if(allcollections->first == NULL || collectionfound == 0){
+ newcollection = MEM_mallocN(sizeof(Collection), "element collection");
+ newcollection->index = eed->tmp.l;
+ newcollection->collectionbase.first = 0;
+ newcollection->collectionbase.last = 0;
+
+ newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
+ newedge->eed = eed;
+
+ BLI_addtail(&(newcollection->collectionbase), newedge);
+ BLI_addtail(allcollections, newcollection);
+ }
+ }
+
+ }
+}
+
+static void freecollections(ListBase *allcollections)
+{
+ struct Collection *curcollection;
+
+ for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next)
+ BLI_freelistN(&(curcollection->collectionbase));
+ BLI_freelistN(allcollections);
+}
+
+/*Begin UV Edge Collapse Code
+ Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail
+ in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it.
+ The welded UV edges can then be sorted and collapsed.
+*/
+typedef struct wUV{
+ struct wUV *next, *prev;
+ ListBase nodes;
+ float u, v; /*cached copy of UV coordinates pointed to by nodes*/
+ EditVert *eve;
+ int f;
+} wUV;
+
+typedef struct wUVNode{
+ struct wUVNode *next, *prev;
+ float *u; /*pointer to original tface data*/
+ float *v; /*pointer to original tface data*/
+} wUVNode;
+
+typedef struct wUVEdge{
+ struct wUVEdge *next, *prev;
+ float v1uv[2], v2uv[2]; /*nasty.*/
+ struct wUV *v1, *v2; /*oriented same as editedge*/
+ EditEdge *eed;
+ int f;
+} wUVEdge;
+
+typedef struct wUVEdgeCollect{ /*used for grouping*/
+ struct wUVEdgeCollect *next, *prev;
+ wUVEdge *uved;
+ int id;
+} wUVEdgeCollect;
+
+static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts)
+{
+ wUV *curwvert, *newwvert;
+ wUVNode *newnode;
+ int found;
+ MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
+ found = 0;
+
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){
+ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
+ newnode->u = &(tf->uv[tfindex][0]);
+ newnode->v = &(tf->uv[tfindex][1]);
+ BLI_addtail(&(curwvert->nodes), newnode);
+ found = 1;
+ break;
+ }
+ }
+
+ if(!found){
+ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
+ newnode->u = &(tf->uv[tfindex][0]);
+ newnode->v = &(tf->uv[tfindex][1]);
+
+ newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert");
+ newwvert->u = *(newnode->u);
+ newwvert->v = *(newnode->v);
+ newwvert->eve = eve;
+
+ BLI_addtail(&(newwvert->nodes), newnode);
+ BLI_addtail(uvverts, newwvert);
+
+ }
+}
+
+static void build_weldedUVs(ListBase *uvverts)
+{
+ EditFace *efa;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->v1->f1) append_weldedUV(efa, efa->v1, 0, uvverts);
+ if(efa->v2->f1) append_weldedUV(efa, efa->v2, 1, uvverts);
+ if(efa->v3->f1) append_weldedUV(efa, efa->v3, 2, uvverts);
+ if(efa->v4 && efa->v4->f1) append_weldedUV(efa, efa->v4, 3, uvverts);
+ }
+}
+
+static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
+{
+ wUVEdge *curwedge, *newwedge;
+ int v1tfindex, v2tfindex, found;
+ MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
+ found = 0;
+
+ if(eed->v1 == efa->v1) v1tfindex = 0;
+ else if(eed->v1 == efa->v2) v1tfindex = 1;
+ else if(eed->v1 == efa->v3) v1tfindex = 2;
+ else /* if(eed->v1 == efa->v4) */ v1tfindex = 3;
+
+ if(eed->v2 == efa->v1) v2tfindex = 0;
+ else if(eed->v2 == efa->v2) v2tfindex = 1;
+ else if(eed->v2 == efa->v3) v2tfindex = 2;
+ else /* if(eed->v2 == efa->v4) */ v2tfindex = 3;
+
+ for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
+ if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){
+ found = 1;
+ break; //do nothing, we don't need another welded uv edge
+ }
+ }
+
+ if(!found){
+ newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge");
+ newwedge->v1uv[0] = tf->uv[v1tfindex][0];
+ newwedge->v1uv[1] = tf->uv[v1tfindex][1];
+ newwedge->v2uv[0] = tf->uv[v2tfindex][0];
+ newwedge->v2uv[1] = tf->uv[v2tfindex][1];
+ newwedge->eed = eed;
+
+ BLI_addtail(uvedges, newwedge);
+ }
+}
+
+static void build_weldedUVEdges(ListBase *uvedges, ListBase *uvverts)
+{
+ wUV *curwvert;
+ wUVEdge *curwedge;
+ EditFace *efa;
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->e1->f1) append_weldedUVEdge(efa, efa->e1, uvedges);
+ if(efa->e2->f1) append_weldedUVEdge(efa, efa->e2, uvedges);
+ if(efa->e3->f1) append_weldedUVEdge(efa, efa->e3, uvedges);
+ if(efa->e4 && efa->e4->f1) append_weldedUVEdge(efa, efa->e4, uvedges);
+ }
+
+
+ //link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers
+ for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwedge->eed->v1 == curwvert->eve && curwedge->v1uv[0] == curwvert->u && curwedge->v1uv[1] == curwvert->v){
+ curwedge->v1 = curwvert;
+ break;
+ }
+ }
+ for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
+ if(curwedge->eed->v2 == curwvert->eve && curwedge->v2uv[0] == curwvert->u && curwedge->v2uv[1] == curwvert->v){
+ curwedge->v2 = curwvert;
+ break;
+ }
+ }
+ }
+}
+
+static void free_weldedUVs(ListBase *uvverts)
+{
+ wUV *curwvert;
+ for(curwvert = uvverts->first; curwvert; curwvert=curwvert->next) BLI_freelistN(&(curwvert->nodes));
+ BLI_freelistN(uvverts);
+}
+
+static void collapse_edgeuvs(void)
+{
+ ListBase uvedges, uvverts, allcollections;
+ wUVEdge *curwedge;
+ wUVNode *curwnode;
+ wUVEdgeCollect *collectedwuve, *newcollectedwuve;
+ Collection *wuvecollection, *newcollection;
+ int curtag, balanced, collectionfound= 0, vcount;
+ float avg[2];
+
+ if (!EM_texFaceCheck())
+ return;
+
+ uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL;
+
+ build_weldedUVs(&uvverts);
+ build_weldedUVEdges(&uvedges, &uvverts);
+
+ curtag = 0;
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ curwedge->v1->f = curtag;
+ curwedge->v2->f = curtag;
+ curtag +=1;
+ }
+
+ balanced = 0;
+ while(!balanced){
+ balanced = 1;
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ if(curwedge->v1->f != curwedge->v2->f){
+ if(curwedge->v1->f > curwedge->v2->f) curwedge->v1->f = curwedge->v2->f;
+ else curwedge->v2->f = curwedge->v1->f;
+ balanced = 0;
+ }
+ }
+ }
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f;
+
+
+ for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
+ if(allcollections.first){
+ for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
+ if(wuvecollection->index == curwedge->f){
+ newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
+ newcollectedwuve->uved = curwedge;
+ BLI_addtail(&(wuvecollection->collectionbase), newcollectedwuve);
+ collectionfound = 1;
+ break;
+ }
+
+ else collectionfound = 0;
+ }
+ }
+ if(allcollections.first == NULL || collectionfound == 0){
+ newcollection = MEM_callocN(sizeof(Collection), "element collection");
+ newcollection->index = curwedge->f;
+ newcollection->collectionbase.first = 0;
+ newcollection->collectionbase.last = 0;
+
+ newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
+ newcollectedwuve->uved = curwedge;
+
+ BLI_addtail(&(newcollection->collectionbase), newcollectedwuve);
+ BLI_addtail(&allcollections, newcollection);
+ }
+ }
+
+ for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
+
+ vcount = avg[0] = avg[1] = 0;
+
+ for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
+ avg[0] += collectedwuve->uved->v1uv[0];
+ avg[1] += collectedwuve->uved->v1uv[1];
+
+ avg[0] += collectedwuve->uved->v2uv[0];
+ avg[1] += collectedwuve->uved->v2uv[1];
+
+ vcount +=2;
+
+ }
+
+ avg[0] /= vcount; avg[1] /= vcount;
+
+ for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
+ for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){
+ *(curwnode->u) = avg[0];
+ *(curwnode->v) = avg[1];
+ }
+ for(curwnode=collectedwuve->uved->v2->nodes.first; curwnode; curwnode=curwnode->next){
+ *(curwnode->u) = avg[0];
+ *(curwnode->v) = avg[1];
+ }
+ }
+ }
+
+ free_weldedUVs(&uvverts);
+ BLI_freelistN(&uvedges);
+ freecollections(&allcollections);
+}
+
+/*End UV Edge collapse code*/
+
+static void collapseuvs(EditVert *mergevert)
+{
+ EditFace *efa;
+ MTFace *tf;
+ int uvcount;
+ float uvav[2];
+
+ if (!EM_texFaceCheck())
+ return;
+
+ uvcount = 0;
+ uvav[0] = 0;
+ uvav[1] = 0;
+
+ for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
+ if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) {
+ uvav[0] += tf->uv[0][0];
+ uvav[1] += tf->uv[0][1];
+ uvcount += 1;
+ }
+ if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){
+ uvav[0] += tf->uv[1][0];
+ uvav[1] += tf->uv[1][1];
+ uvcount += 1;
+ }
+ if(efa->v3->f1 && ELEM(mergevert, NULL, efa->v3)){
+ uvav[0] += tf->uv[2][0];
+ uvav[1] += tf->uv[2][1];
+ uvcount += 1;
+ }
+ if(efa->v4 && efa->v4->f1 && ELEM(mergevert, NULL, efa->v4)){
+ uvav[0] += tf->uv[3][0];
+ uvav[1] += tf->uv[3][1];
+ uvcount += 1;
+ }
+ }
+
+ if(uvcount > 0) {
+ uvav[0] /= uvcount;
+ uvav[1] /= uvcount;
+
+ for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
+ if(efa->v1->f1){
+ tf->uv[0][0] = uvav[0];
+ tf->uv[0][1] = uvav[1];
+ }
+ if(efa->v2->f1){
+ tf->uv[1][0] = uvav[0];
+ tf->uv[1][1] = uvav[1];
+ }
+ if(efa->v3->f1){
+ tf->uv[2][0] = uvav[0];
+ tf->uv[2][1] = uvav[1];
+ }
+ if(efa->v4 && efa->v4->f1){
+ tf->uv[3][0] = uvav[0];
+ tf->uv[3][1] = uvav[1];
+ }
+ }
+ }
+}
+
+int collapseEdges(void)
+{
+ EditVert *eve;
+ EditEdge *eed;
+
+ ListBase allcollections;
+ CollectedEdge *curredge;
+ Collection *edgecollection;
+
+ int totedges, groupcount, mergecount,vcount;
+ float avgcount[3];
+
+ allcollections.first = 0;
+ allcollections.last = 0;
+
+ mergecount = 0;
+
+ if(multires_test()) return 0;
+
+ build_edgecollection(&allcollections);
+ groupcount = BLI_countlist(&allcollections);
+
+
+ for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){
+ totedges = BLI_countlist(&(edgecollection->collectionbase));
+ mergecount += totedges;
+ avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0;
+
+ vcount = 0;
+
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0];
+ avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1];
+ avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2];
+
+ avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0];
+ avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1];
+ avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2];
+
+ vcount +=2;
+ }
+
+ avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount;
+
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount);
+ VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount);
+ }
+
+ if (EM_texFaceCheck()) {
+ /*uv collapse*/
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
+ curredge->eed->v1->f1 = 1;
+ curredge->eed->v2->f1 = 1;
+ curredge->eed->f1 = 1;
+ }
+ collapse_edgeuvs();
+ }
+
+ }
+ freecollections(&allcollections);
+ removedoublesflag(1, 0, MERGELIMIT);
+ /*get rid of this!*/
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ return mergecount;
+}
+
+int merge_firstlast(int first, int uvmerge)
+{
+ EditVert *eve,*mergevert;
+ EditSelection *ese;
+
+ if(multires_test()) return 0;
+
+ /* do sanity check in mergemenu in edit.c ?*/
+ if(first == 0){
+ ese = G.editMesh->selected.last;
+ mergevert= (EditVert*)ese->data;
+ }
+ else{
+ ese = G.editMesh->selected.first;
+ mergevert = (EditVert*)ese->data;
+ }
+
+ if(mergevert->f&SELECT){
+ for (eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if (eve->f&SELECT)
+ VECCOPY(eve->co,mergevert->co);
+ }
+ }
+
+ if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
+
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if(eve->f&SELECT) eve->f1 = 1;
+ }
+ collapseuvs(mergevert);
+ }
+
+ countall();
+ return removedoublesflag(1, 0, MERGELIMIT);
+}
+
+int merge_target(int target, int uvmerge)
+{
+ EditVert *eve;
+
+ if(multires_test()) return 0;
+
+ if(target) snap_sel_to_curs();
+ else snap_to_center();
+
+ if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if(eve->f&SELECT) eve->f1 = 1;
+ }
+ collapseuvs(NULL);
+ }
+
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ return removedoublesflag(1, 0, MERGELIMIT);
+
+}
+#undef MERGELIMIT
+
+typedef struct PathNode{
+ int u;
+ int visited;
+ ListBase edges;
+} PathNode;
+
+typedef struct PathEdge{
+ struct PathEdge *next, *prev;
+ int v;
+ float w;
+} PathEdge;
+
+void pathselect(void)
+{
+ EditVert *eve, *s, *t;
+ EditEdge *eed;
+ EditSelection *ese;
+ PathEdge *newpe, *currpe;
+ PathNode *currpn;
+ PathNode *Q;
+ int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
+ int unbalanced, totnodes;
+ short physical;
+ float *cost;
+ Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
+
+ s = t = NULL;
+
+ countall(); /*paranoid?*/
+
+ ese = ((EditSelection*)G.editMesh->selected.last);
+ if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
+ physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
+
+ t = (EditVert*)ese->data;
+ s = (EditVert*)ese->prev->data;
+
+ /*need to find out if t is actually reachable by s....*/
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ eve->f1 = 0;
+ }
+
+ s->f1 = 1;
+
+ unbalanced = 1;
+ totnodes = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(!eed->h){
+ if(eed->v1->f1 && !eed->v2->f1){
+ eed->v2->f1 = 1;
+ totnodes++;
+ unbalanced = 1;
+ }
+ else if(eed->v2->f1 && !eed->v1->f1){
+ eed->v1->f1 = 1;
+ totnodes++;
+ unbalanced = 1;
+ }
+ }
+ }
+ }
+
+
+
+ if(s->f1 && t->f1){ /*t can be reached by s*/
+ Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
+ totnodes = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if(eve->f1){
+ Q[totnodes].u = totnodes;
+ Q[totnodes].edges.first = 0;
+ Q[totnodes].edges.last = 0;
+ Q[totnodes].visited = 0;
+ eve->tmp.p = &(Q[totnodes]);
+ totnodes++;
+ }
+ else eve->tmp.p = NULL;
+ }
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(!eed->h){
+ if(eed->v1->f1){
+ currpn = ((PathNode*)eed->v1->tmp.p);
+
+ newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
+ newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
+ if(physical){
+ newpe->w = VecLenf(eed->v1->co, eed->v2->co);
+ }
+ else newpe->w = 1;
+ newpe->next = 0;
+ newpe->prev = 0;
+ BLI_addtail(&(currpn->edges), newpe);
+ }
+ if(eed->v2->f1){
+ currpn = ((PathNode*)eed->v2->tmp.p);
+ newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
+ newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
+ if(physical){
+ newpe->w = VecLenf(eed->v1->co, eed->v2->co);
+ }
+ else newpe->w = 1;
+ newpe->next = 0;
+ newpe->prev = 0;
+ BLI_addtail(&(currpn->edges), newpe);
+ }
+ }
+ }
+
+ heap = BLI_heap_new();
+ cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
+ previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
+
+ for(v=0; v < totnodes; v++){
+ cost[v] = 1000000;
+ previous[v] = -1; /*array of indices*/
+ }
+
+ pnindex = ((PathNode*)s->tmp.p)->u;
+ cost[pnindex] = 0;
+ BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex));
+
+ while( !BLI_heap_empty(heap) ){
+
+ pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
+ currpn = &(Q[pnindex]);
+
+ if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
+ break;
+
+ for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
+ if(!Q[currpe->v].visited){
+ if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
+ cost[currpe->v] = cost[currpn->u] + currpe->w;
+ previous[currpe->v] = currpn->u;
+ Q[currpe->v].visited = 1;
+ BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v));
+ }
+ }
+ }
+ }
+
+ pathvert = ((PathNode*)t->tmp.p)->u;
+ while(pathvert != -1){
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if(eve->f1){
+ if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
+ }
+ }
+ pathvert = previous[pathvert];
+ }
+
+ for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
+ MEM_freeN(Q);
+ MEM_freeN(cost);
+ MEM_freeN(previous);
+ BLI_heap_free(heap, NULL);
+ EM_select_flush();
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ }
+ }
+ else{
+ error("Path Selection requires that exactly two vertices be selected");
+ return;
+ }
+}
+
+void region_to_loop(void)
+{
+ EditEdge *eed;
+ EditFace *efa;
+
+ if(G.totfacesel){
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->f&SELECT){
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4)
+ efa->e4->f1++;
+ }
+ }
+
+ EM_clear_flag_all(SELECT);
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(eed->f1 == 1) EM_select_edge(eed, 1);
+ }
+
+ G.scene->selectmode = SCE_SELECT_EDGE;
+ EM_selectmode_set();
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ BIF_undo_push("Face Region to Edge Loop");
+
+ }
+}
+
+static int validate_loop(Collection *edgecollection)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ CollectedEdge *curredge;
+
+ /*1st test*/
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ curredge->eed->v1->f1 = 0;
+ curredge->eed->v2->f1 = 0;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ curredge->eed->v1->f1++;
+ curredge->eed->v2->f1++;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ if(curredge->eed->v1->f1 > 2) return(0); else
+ if(curredge->eed->v2->f1 > 2) return(0);
+ }
+
+ /*2nd test*/
+ for(eed = G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
+ if(curredge->eed->f1 > 2) return(0);
+ }
+ return(1);
+}
+
+static int loop_bisect(Collection *edgecollection){
+
+ EditFace *efa, *sf1, *sf2;
+ EditEdge *eed, *sed;
+ CollectedEdge *curredge;
+ int totsf1, totsf2, unbalanced,balancededges;
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next) efa->f1 = 0;
+
+ for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1;
+
+ sf1 = sf2 = NULL;
+ sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed;
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(sf2) break;
+ else if(sf1){
+ if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa;
+ }
+ else{
+ if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa;
+ }
+ }
+
+ if(sf1==NULL || sf2==NULL)
+ return(-1);
+
+ if(!(sf1->e1->f1)) sf1->e1->f2 = 1;
+ if(!(sf1->e2->f1)) sf1->e2->f2 = 1;
+ if(!(sf1->e3->f1)) sf1->e3->f2 = 1;
+ if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1;
+ sf1->f1 = 1;
+ totsf1 = 1;
+
+ if(!(sf2->e1->f1)) sf2->e1->f2 = 2;
+ if(!(sf2->e2->f1)) sf2->e2->f2 = 2;
+ if(!(sf2->e3->f1)) sf2->e3->f2 = 2;
+ if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2;
+ sf2->f1 = 2;
+ totsf2 = 1;
+
+ /*do sf1*/
+ unbalanced = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ balancededges = 0;
+ if(efa->f1 == 0){
+ if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){
+ balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1;
+ balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1;
+ balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1;
+ if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1;
+ if(balancededges){
+ unbalanced = 1;
+ efa->f1 = 1;
+ totsf1++;
+ }
+ }
+ }
+ }
+ }
+
+ /*do sf2*/
+ unbalanced = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ balancededges = 0;
+ if(efa->f1 == 0){
+ if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){
+ balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2;
+ balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2;
+ balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2;
+ if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2;
+ if(balancededges){
+ unbalanced = 1;
+ efa->f1 = 2;
+ totsf2++;
+ }
+ }
+ }
+ }
+ }
+
+ if(totsf1 < totsf2) return(1);
+ else return(2);
+}
+
+void loop_to_region(void)
+{
+ EditFace *efa;
+ ListBase allcollections={NULL,NULL};
+ Collection *edgecollection;
+ int testflag;
+
+ build_edgecollection(&allcollections);
+
+ for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){
+ if(validate_loop(edgecollection)){
+ testflag = loop_bisect(edgecollection);
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->f1 == testflag){
+ if(efa->f&SELECT) EM_select_face(efa, 0);
+ else EM_select_face(efa,1);
+ }
+ }
+ }
+ }
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){ /*fix this*/
+ if(efa->f&SELECT) EM_select_face(efa,1);
+ }
+
+ countall();
+ freecollections(&allcollections);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ BIF_undo_push("Edge Loop to Face Region");
+}
+
+
+/* texface and vertex color editmode tools for the face menu */
+
+void mesh_rotate_uvs(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ short change = 0, ccw;
+ MTFace *tf;
+ float u1, v1;
+
+ if (!EM_texFaceCheck()) {
+ error("mesh has no uv/image layers");
+ return;
+ }
+
+ ccw = (G.qual == LR_SHIFTKEY);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ u1= tf->uv[0][0];
+ v1= tf->uv[0][1];
+
+ if (ccw) {
+ if(efa->v4) {
+ tf->uv[0][0]= tf->uv[3][0];
+ tf->uv[0][1]= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[2][0];
+ tf->uv[3][1]= tf->uv[2][1];
+ } else {
+ tf->uv[0][0]= tf->uv[2][0];
+ tf->uv[0][1]= tf->uv[2][1];
+ }
+
+ tf->uv[2][0]= tf->uv[1][0];
+ tf->uv[2][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+ } else {
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+
+ if(efa->v4) {
+ tf->uv[2][0]= tf->uv[3][0];
+ tf->uv[2][1]= tf->uv[3][1];
+
+ tf->uv[3][0]= u1;
+ tf->uv[3][1]= v1;
+ }
+ else {
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Rotate UV face");
+ }
+}
+
+void mesh_mirror_uvs(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ short change = 0, altaxis;
+ MTFace *tf;
+ float u1, v1;
+
+ if (!EM_texFaceCheck()) {
+ error("mesh has no uv/image layers");
+ return;
+ }
+
+ altaxis = (G.qual == LR_SHIFTKEY);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if (altaxis) {
+ u1= tf->uv[1][0];
+ v1= tf->uv[1][1];
+ if(efa->v4) {
+
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+
+ u1= tf->uv[3][0];
+ v1= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[0][0];
+ tf->uv[3][1]= tf->uv[0][1];
+
+ tf->uv[0][0]= u1;
+ tf->uv[0][1]= v1;
+ }
+ else {
+ tf->uv[1][0]= tf->uv[2][0];
+ tf->uv[1][1]= tf->uv[2][1];
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+
+ } else {
+ u1= tf->uv[0][0];
+ v1= tf->uv[0][1];
+ if(efa->v4) {
+
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+
+ u1= tf->uv[3][0];
+ v1= tf->uv[3][1];
+
+ tf->uv[3][0]= tf->uv[2][0];
+ tf->uv[3][1]= tf->uv[2][1];
+
+ tf->uv[2][0]= u1;
+ tf->uv[2][1]= v1;
+ }
+ else {
+ tf->uv[0][0]= tf->uv[1][0];
+ tf->uv[0][1]= tf->uv[1][1];
+ tf->uv[1][0]= u1;
+ tf->uv[1][1]= v1;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Mirror UV face");
+ }
+}
+
+void mesh_rotate_colors(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ short change = 0, ccw;
+ MCol tmpcol, *mcol;
+ if (!EM_vertColorCheck()) {
+ error("mesh has no color layers");
+ return;
+ }
+
+ ccw = (G.qual == LR_SHIFTKEY);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ tmpcol= mcol[0];
+
+ if (ccw) {
+ if(efa->v4) {
+ mcol[0]= mcol[3];
+ mcol[3]= mcol[2];
+ } else {
+ mcol[0]= mcol[2];
+ }
+ mcol[2]= mcol[1];
+ mcol[1]= tmpcol;
+ } else {
+ mcol[0]= mcol[1];
+ mcol[1]= mcol[2];
+
+ if(efa->v4) {
+ mcol[2]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ else
+ mcol[2]= tmpcol;
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Rotate Color face");
+ }
+}
+
+void mesh_mirror_colors(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ short change = 0, altaxis;
+ MCol tmpcol, *mcol;
+ if (!EM_vertColorCheck()) {
+ error("mesh has no color layers");
+ return;
+ }
+
+ altaxis = (G.qual == LR_SHIFTKEY);
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ if (altaxis) {
+ tmpcol= mcol[1];
+ mcol[1]= mcol[2];
+ mcol[2]= tmpcol;
+
+ if(efa->v4) {
+ tmpcol= mcol[0];
+ mcol[0]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ } else {
+ tmpcol= mcol[0];
+ mcol[0]= mcol[1];
+ mcol[1]= tmpcol;
+
+ if(efa->v4) {
+ tmpcol= mcol[2];
+ mcol[2]= mcol[3];
+ mcol[3]= tmpcol;
+ }
+ }
+ change = 1;
+ }
+ }
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Mirror Color face");
+ }
+}
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
new file mode 100644
index 00000000000..58025fd33cc
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -0,0 +1,566 @@
+/**
+ * bmesh_construct.c August 2008
+ *
+ * BM construction functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "math.h"
+#include "stdio.h"
+#include "string.h"
+
+#define SELECT 1
+
+/*prototypes*/
+static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
+ BMLoop *source_loop, BMLoop *target_loop);
+
+/*
+ * BM_CONSTRUCT.C
+ *
+ * This file contains functions for making and destroying
+ * individual elements like verts, edges and faces.
+ *
+*/
+
+/*
+ * BMESH MAKE VERT
+ *
+ * Creates a new vertex and returns a pointer
+ * to it. If a pointer to an example vertex is
+ * passed in, it's custom data and properties
+ * will be copied to the new vertex.
+ *
+*/
+
+BMVert *BM_Make_Vert(BMesh *bm, float co[3], BMVert *example)
+{
+ BMVert *v = NULL;
+ v = bmesh_mv(bm, co);
+ if(example)
+ CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->head.data, &v->head.data);
+ return v;
+}
+
+/*
+ * BMESH MAKE EDGE
+ *
+ * Creates a new edge betweeen two vertices and returns a
+ * pointer to it. If 'nodouble' equals 1, then a check is
+ * is done to make sure that an edge between those two vertices
+ * does not already exist. If it does, that edge is returned instead
+ * of creating a new one.
+ *
+ * If a new edge is created, and a pointer to an example edge is
+ * provided, it's custom data and properties will be copied to the
+ * new edge.
+ *
+*/
+
+BMEdge *BM_Make_Edge(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example, int nodouble)
+{
+ BMEdge *e = NULL;
+
+ if(nodouble) /*test if edge already exists.*/
+ e = bmesh_disk_existedge(v1, v2);
+
+ if(!e){
+ e = bmesh_me(bm, v1, v2);
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->head.data, &e->head.data);
+ }
+
+ return e;
+
+}
+
+/*
+ * BMESH MAKE QUADTRIANGLE
+ *
+ * Creates a new quad or triangle from
+ * a list of 3 or 4 vertices. If nodouble
+ * equals 1, then a check is done to see
+ * if a face with these vertices already
+ * exists and returns it instead. If a pointer
+ * to an example face is provided, it's custom
+ * data and properties will be copied to the new
+ * face.
+ *
+ * Note that the winding of the face is determined
+ * by the order of the vertices in the vertex array
+ *
+*/
+
+BMFace *BM_Make_QuadTri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3,
+ BMVert *v4, BMFace *example, int nodouble)
+{
+ BMEdge *edar[4];
+ BMVert *vtar[4];
+
+ edar[0] = bmesh_disk_existedge(v1, v2);
+ edar[1] = bmesh_disk_existedge(v2, v3);
+ edar[2] = bmesh_disk_existedge(v3, v4? v4 : v1);
+ if (v4) edar[3] = bmesh_disk_existedge(v4, v1);
+ else edar[3] = NULL;
+
+ if (!edar[0]) edar[0] = BM_Make_Edge(bm, v1, v2, NULL, 0);
+ if (!edar[1]) edar[1] = BM_Make_Edge(bm, v2, v3, NULL, 0);
+ if (!edar[2]) edar[2] = BM_Make_Edge(bm, v3, v4?v4:v1, NULL, 0);
+ if (!edar[0] && v4) edar[0] = BM_Make_Edge(bm, v4, v1, NULL, 0);
+
+ vtar[0] = v1;
+ vtar[1] = v2;
+ vtar[2] = v3;
+ vtar[3] = v4;
+
+ return BM_Make_Quadtriangle(bm, vtar, edar, v4?4:3, example, nodouble);
+}
+
+/*remove the edge array bits from this. Its not really needed?*/
+BMFace *BM_Make_Quadtriangle(BMesh *bm, BMVert **verts, BMEdge **edges, int len, BMFace *example, int nodouble)
+{
+ BMEdge *edar[4];
+ BMFace *f = NULL;
+ int overlap = 0;
+
+ edar[0] = edar[1] = edar[2] = edar[3] = NULL;
+
+ if(edges){
+ edar[0] = edges[0];
+ edar[1] = edges[1];
+ edar[2] = edges[2];
+ if(len == 4) edar[3] = edges[3];
+ }else{
+ edar[0] = bmesh_disk_existedge(verts[0],verts[1]);
+ edar[1] = bmesh_disk_existedge(verts[1],verts[2]);
+ if(len == 4){
+ edar[2] = bmesh_disk_existedge(verts[2],verts[3]);
+ edar[3] = bmesh_disk_existedge(verts[3],verts[0]);
+
+ }else{
+ edar[2] = bmesh_disk_existedge(verts[2],verts[0]);
+ }
+ }
+
+ if(nodouble){
+ /*check if face exists or overlaps*/
+ if(len == 4){
+ overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
+ }else{
+ overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
+ }
+ }
+
+ /*make new face*/
+ if((!f) && (!overlap)){
+ if(!edar[0]) edar[0] = bmesh_me(bm, verts[0], verts[1]);
+ if(!edar[1]) edar[1] = bmesh_me(bm, verts[1], verts[2]);
+ if(len == 4){
+ if(!edar[2]) edar[2] = bmesh_me(bm, verts[2], verts[3]);
+ if(!edar[3]) edar[3] = bmesh_me(bm, verts[3], verts[0]);
+ } else {
+ if(!edar[2]) edar[2] = bmesh_me(bm, verts[2], verts[0]);
+ }
+
+ if(len == 4) f = bmesh_mf(bm, verts[0], verts[1], edar, 4);
+ else f = bmesh_mf(bm, verts[0], verts[1], edar, 3);
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->head.data, &f->head.data);
+
+ }
+
+ return f;
+}
+
+
+/*copies face data from shared adjacent faces*/
+void BM_Face_CopyShared(BMesh *bm, BMFace *f) {
+ BMIter iter;
+ BMLoop *l, *l2;
+
+ if (!f) return;
+
+ l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ l2 = l->radial.next->data;
+
+ if (l2 && l2 != l) {
+ if (l2->v == l->v) {
+ bm_copy_loop_attributes(bm, bm, l2, l);
+ } else {
+ l2 = (BMLoop*) l2->head.next;
+ bm_copy_loop_attributes(bm, bm, l2, l);
+ }
+ }
+ }
+}
+
+/*
+ * BMESH MAKE NGON
+ *
+ * Attempts to make a new Ngon from a list of edges.
+ * If nodouble equals one, a check for overlaps or existing
+ *
+ *
+ *
+*/
+#define VERT_BUF_SIZE 100
+BMFace *BM_Make_Ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
+{
+ BMVert *vert_buf[VERT_BUF_SIZE];
+ BMVert **verts = vert_buf, *lastv;
+ BMFace *f = NULL;
+ int overlap = 0, i, j;
+
+ /*note: need to make sure this is correct*/
+ if(bmesh_verts_in_edge(v1,v2,edges[0]) == 0) {
+ if (v1 == edges[0]->v1)
+ v2 = edges[0]->v2;
+ else {
+ v1 = edges[0]->v2;
+ v2 = edges[0]->v1;
+ }
+ }
+
+ if(nodouble) {
+ if(len > VERT_BUF_SIZE)
+ verts = MEM_callocN(sizeof(BMVert *) * len, "bmesh make ngon vertex array");
+
+ /*if ((edges[i]->v1 == edges[i]->v1) ||
+ (edges[i]->v1 == edges[i]->v2))
+ {
+ lastv = edges[i]->v2;
+ } else lastv = edges[i]->v1;
+ verts[0] = lastv;
+
+ for (i=1; i<len; i++) {
+ if (!BMO_TestFlag
+ }*/
+
+ for(i = 0, j=0; i < len; i++){
+ if(!BMO_TestFlag(bm, edges[i]->v1, BM_EDGEVERT)){
+ BMO_SetFlag(bm, edges[i]->v1, BM_EDGEVERT);
+ verts[j++] = edges[i]->v1;
+ }
+ if(!BMO_TestFlag(bm, edges[i]->v2, BM_EDGEVERT)) {
+ BMO_SetFlag(bm, edges[i]->v2, BM_EDGEVERT);
+ verts[j++] = edges[i]->v2;
+ }
+ }
+
+ if (j != len) {
+ /*sanity check*/
+ return NULL;
+ }
+
+ overlap = BM_Face_Exists(bm, verts, len, &f);
+
+ /*clear flags*/
+ for(i = 0; i < len; i++){
+ BMO_ClearFlag(bm, edges[i]->v1, BM_EDGEVERT);
+ BMO_ClearFlag(bm, edges[i]->v2, BM_EDGEVERT);
+ }
+
+ if(len > VERT_BUF_SIZE)
+ MEM_freeN(verts);
+ }
+
+ if((!f) && (!overlap)) {
+ f = bmesh_mf(bm, v1, v2, edges, len);
+ }
+
+ return f;
+}
+
+
+/*bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
+
+
+/*
+ * REMOVE TAGGED XXX
+ *
+ * Called by operators to remove elements that they have marked for
+ * removal.
+ *
+*/
+
+void BM_remove_tagged_faces(BMesh *bm, int flag)
+{
+ BMHeader *current, *next;
+
+ current = bm->polys.first;
+ while(current){
+ next = current->next;
+ if(BMO_TestFlag(bm, current, flag)) bmesh_kf(bm, (BMFace*)current);
+ current = next;
+ }
+}
+void BM_remove_tagged_edges(BMesh *bm, int flag)
+{
+ BMHeader *current, *next;
+
+ current = bm->edges.first;
+
+ while(current){
+ next = current->next;
+ if(BMO_TestFlag(bm, current, flag)) bmesh_ke(bm, (BMEdge*)current);
+ current = next;
+ }
+}
+
+void BM_remove_tagged_verts(BMesh *bm, int flag)
+{
+ BMHeader *current, *next;
+
+ current = bm->verts.first;
+
+ while(current){
+ next = current->next;
+ if(BMO_TestFlag(bm, current, flag)) bmesh_kv(bm,(BMVert*)current);
+ current = next;
+ }
+}
+
+static void bm_copy_vert_attributes(BMesh *source_mesh, BMesh *target_mesh, BMVert *source_vertex, BMVert *target_vertex)
+{
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->head.data, &target_vertex->head.data);
+ target_vertex->bweight = source_vertex->bweight;
+}
+
+static void bm_copy_edge_attributes(BMesh *source_mesh, BMesh *target_mesh, BMEdge *source_edge, BMEdge *target_edge)
+{
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data);
+ target_edge->crease = source_edge->crease;
+ target_edge->bweight = source_edge->bweight;
+}
+
+static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh, BMLoop *source_loop, BMLoop *target_loop)
+{
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data);
+}
+
+static void bm_copy_face_attributes(BMesh *source_mesh, BMesh *target_mesh, BMFace *source_face, BMFace *target_face)
+{
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data);
+ target_face->mat_nr = source_face->mat_nr;
+}
+
+/*Todo: Special handling for hide flags?*/
+
+void BM_Copy_Attributes(BMesh *source_mesh, BMesh *target_mesh, void *source, void *target)
+{
+ BMHeader *sheader = source, *theader = target;
+
+ if(sheader->type != theader->type)
+ return;
+
+ /*First we copy select*/
+ if(BM_Is_Selected(source_mesh, source)) BM_Select(target_mesh, target, 1);
+
+ /*Now we copy flags*/
+ theader->flag = sheader->flag;
+
+ /*Copy specific attributes*/
+ if(theader->type == BM_VERT)
+ bm_copy_vert_attributes(source_mesh, target_mesh, (BMVert*)source, (BMVert*)target);
+ else if(theader->type == BM_EDGE)
+ bm_copy_edge_attributes(source_mesh, target_mesh, (BMEdge*)source, (BMEdge*)target);
+ else if(theader->type == BM_LOOP)
+ bm_copy_loop_attributes(source_mesh, target_mesh, (BMLoop*)source, (BMLoop*)target);
+ else if(theader->type == BM_FACE)
+ bm_copy_face_attributes(source_mesh, target_mesh, (BMFace*)source, (BMFace*)target);
+}
+
+BMesh *BM_Copy_Mesh(BMesh *bmold)
+{
+ BMesh *bm;
+ BMVert *v, *v2, **vtable = NULL;
+ V_DECLARE(vtable);
+ BMEdge *e, *e2, **edges = NULL, **etable = NULL;
+ V_DECLARE(edges);
+ V_DECLARE(etable);
+ BMLoop *l, *l2, **loops = NULL;
+ V_DECLARE(loops);
+ BMFace *f, *f2;
+
+ BMIter iter, liter;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+ int i;
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(allocsize);
+
+ CustomData_copy(&bmold->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ v = BMIter_New(&iter, bmold, BM_VERTS_OF_MESH, NULL);
+ for (i=0; v; v=BMIter_Step(&iter), i++) {
+ v2 = BM_Make_Vert(bm, v->co, NULL);
+ BM_Copy_Attributes(bmold, bm, v, v2);
+ V_GROW(vtable);
+ VECCOPY(v2->no, v->no);
+
+ vtable[V_COUNT(vtable)-1] = v2;
+
+ BMINDEX_SET(v, i);
+ BMINDEX_SET(v2, i);
+ }
+
+ e = BMIter_New(&iter, bmold, BM_EDGES_OF_MESH, NULL);
+ for (i=0; e; e=BMIter_Step(&iter), i++) {
+ e2 = BM_Make_Edge(bm, vtable[BMINDEX_GET(e->v1)],
+ vtable[BMINDEX_GET(e->v2)], e, 0);
+
+ BM_Copy_Attributes(bmold, bm, e, e2);
+ V_GROW(etable);
+ etable[V_COUNT(etable)-1] = e2;
+
+ BMINDEX_SET(e, i);
+ BMINDEX_SET(e2, i);
+ }
+
+ f = BMIter_New(&iter, bmold, BM_FACES_OF_MESH, NULL);
+ for (; f; f=BMIter_Step(&iter)) {
+ V_RESET(loops);
+ V_RESET(edges);
+ l = BMIter_New(&liter, bmold, BM_LOOPS_OF_FACE, f);
+ for (i=0; i<f->len; i++, l = BMIter_Step(&liter)) {
+ V_GROW(loops);
+ V_GROW(edges);
+ loops[i] = l;
+ edges[i] = etable[BMINDEX_GET(l->e)];
+ }
+
+ v = vtable[BMINDEX_GET(loops[0]->v)];
+ v2 = vtable[BMINDEX_GET(loops[1]->v)];
+
+ if (!bmesh_verts_in_edge(v, v2, edges[0])) {
+ v = vtable[BMINDEX_GET(loops[V_COUNT(loops)-1]->v)];
+ v2 = vtable[BMINDEX_GET(loops[0]->v)];
+ }
+
+ f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
+ BM_Copy_Attributes(bmold, bm, f, f2);
+ VECCOPY(f2->no, f->no);
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f2);
+ for (i=0; i<f->len; i++, l = BMIter_Step(&liter)) {
+ BM_Copy_Attributes(bmold, bm, loops[i], l);
+ }
+
+ if (f == bmold->act_face) bm->act_face = f2;
+ }
+
+ V_FREE(etable);
+ V_FREE(vtable);
+ V_FREE(loops);
+ V_FREE(edges);
+
+ return bm;
+}
+
+/*
+ BM FLAGS TO ME FLAGS
+
+ Returns the flags stored in element,
+ which much be either a BMVert, BMEdge,
+ or BMFace, converted to mesh flags.
+*/
+int BMFlags_To_MEFlags(void *element) {
+ BMHeader *h = element;
+ int f = 0;
+
+ if (h->flag & BM_HIDDEN) f |= ME_HIDE;
+
+ if (h->type == BM_FACE) {
+ if (h->flag & BM_SELECT) f |= ME_FACE_SEL;
+ if (h->flag & BM_SMOOTH) f |= ME_SMOOTH;
+ } else if (h->type == BM_EDGE) {
+ if (h->flag & BM_SELECT) f |= BM_SELECT;
+ if (h->flag & BM_SEAM) f |= ME_SEAM;
+ if (h->flag & BM_SHARP) f |= ME_SHARP;
+ if (BM_Wire_Edge(NULL, element)) f |= ME_LOOSEEDGE;
+ } else if (h->type == BM_VERT) {
+ if (h->flag & BM_SELECT) f |= BM_SELECT;
+ if (h->flag & BM_HIDDEN) f |= ME_HIDE;
+ }
+
+ return f;
+}
+
+/*
+ BM FLAGS TO ME FLAGS
+
+ Returns the flags stored in element,
+ which much be either a MVert, MEdge,
+ or MPoly, converted to mesh flags.
+ type must be either BM_VERT, BM_EDGE,
+ or BM_FACE.
+*/
+int MEFlags_To_BMFlags(int flag, int type) {
+ int f = 0;
+
+ if (type == BM_FACE) {
+ if (flag & ME_FACE_SEL) f |= BM_SELECT;
+ if (flag & ME_SMOOTH) f |= BM_SMOOTH;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ } else if (type == BM_EDGE) {
+ if (flag & SELECT) f |= BM_SELECT;
+ if (flag & ME_SEAM) f |= BM_SEAM;
+ if (flag & ME_SHARP) f |= BM_SHARP;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ } else if (type == BM_VERT) {
+ if (flag & SELECT) f |= BM_SELECT;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ }
+
+ return f;
+} \ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_eulers.c b/source/blender/bmesh/intern/bmesh_eulers.c
new file mode 100644
index 00000000000..6a68989a42a
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_eulers.c
@@ -0,0 +1,1186 @@
+/**
+ * bmesh_eulers.c jan 2007
+ *
+ * BM Euler construction API.
+ *
+ * $Id: bmesh_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+/*********************************************************
+ * "Euler API" *
+ * *
+ * *
+ * Primitive construction operators for mesh tools. *
+ * *
+ **********************************************************/
+
+
+/*
+ The functions in this file represent the 'primitive' or 'atomic' operators that
+ mesh tools use to manipulate the topology of the structure.* The purpose of these
+ functions is to provide a trusted set of operators to manipulate the mesh topology
+ and which can also be combined together like building blocks to create more
+ sophisticated tools. It needs to be stressed that NO manipulation of an existing
+ mesh structure should be done outside of these functions.
+
+ In the BM system, each euler is named by an ancronym which describes what it actually does.
+ Furthermore each Euler has a logical inverse. An important design criteria of all Eulers is that
+ through a Euler's logical inverse you can 'undo' an operation. (Special note should
+ be taken of bmesh_loop_reverse, which is its own inverse).
+
+ bmesh_MF/KF: Make Face and Kill Face
+ bmesh_ME/KE: Make Edge and Kill Edge
+ bmesh_MV/KV: Make Vert and Kill Vert
+ bmesh_SEMV/JEKV: Split Edge, Make Vert and Join Edge, Kill Vert
+ bmesh_SFME/JFKE: Split Face, Make Edge and Join Face, Kill Edge
+ bmesh_loop_reverse: Reverse a Polygon's loop cycle. (used for flip normals for one)
+
+ Using a combination of these eleven eulers any non-manifold modelling operation can be achieved.
+ Each Euler operator has a detailed explanation of what is does in the comments preceding its
+ code.
+
+ *The term "Euler Operator" is actually a misnomer when referring to a non-manifold
+ data structure. Its use is in keeping with the convention established by others.
+
+ TODO:
+ -Make seperate 'debug levels' of validation
+ -Add in the UnglueFaceRegionMakeVert and GlueFaceRegionKillVert eulers.
+
+ NOTE:
+ -The functions in this file are notoriously difficult to debug and even understand sometimes.
+ better code comments would be nice....
+
+*/
+
+
+/*MAKE Eulers*/
+
+/**
+ * bmesh_MV
+ *
+ * MAKE VERT EULER:
+ *
+ * Makes a single loose vertex.
+ *
+ * Returns -
+ * A BMVert pointer.
+ */
+
+BMVert *bmesh_mv(BMesh *bm, float *vec){
+ BMVert *v = bmesh_addvertlist(bm, NULL);
+ VECCOPY(v->co,vec);
+ return v;
+}
+
+/**
+ * bmesh_ME
+ *
+ * MAKE EDGE EULER:
+ *
+ * Makes a single wire edge between two vertices.
+ * If the caller does not want there to be duplicate
+ * edges between the vertices, it is up to them to check
+ * for this condition beforehand.
+ *
+ * Returns -
+ * A BMEdge pointer.
+ */
+
+BMEdge *bmesh_me(BMesh *bm, BMVert *v1, BMVert *v2){
+ BMEdge *e=NULL;
+ BMNode *d1=NULL, *d2=NULL;
+ int valance1=0, valance2=0, edok;
+
+ /*edge must be between two distinct vertices...*/
+ if(v1 == v2) return NULL;
+
+ #ifndef bmesh_FASTEULER
+ /*count valance of v1*/
+ if(v1->edge){
+ d1 = bmesh_disk_getpointer(v1->edge,v1);
+ if(d1) valance1 = bmesh_cycle_length(d1);
+ else bmesh_error();
+ }
+ if(v2->edge){
+ d2 = bmesh_disk_getpointer(v2->edge,v2);
+ if(d2) valance2 = bmesh_cycle_length(d2);
+ else bmesh_error();
+ }
+ #endif
+
+ /*go ahead and add*/
+ e = bmesh_addedgelist(bm, v1, v2, NULL);
+ bmesh_disk_append_edge(e, e->v1);
+ bmesh_disk_append_edge(e, e->v2);
+
+ #ifndef bmesh_FASTEULER
+ /*verify disk cycle lengths*/
+ d1 = bmesh_disk_getpointer(e, e->v1);
+ edok = bmesh_cycle_validate(valance1+1, d1);
+ if(!edok) bmesh_error();
+ d2 = bmesh_disk_getpointer(e, e->v2);
+ edok = bmesh_cycle_validate(valance2+1, d2);
+ if(!edok) bmesh_error();
+
+ /*verify that edge actually made it into the cycle*/
+ edok = bmesh_disk_hasedge(v1, e);
+ if(!edok) bmesh_error();
+ edok = bmesh_disk_hasedge(v2, e);
+ if(!edok) bmesh_error();
+ #endif
+ return e;
+}
+
+
+
+/**
+ * bmesh_MF
+ *
+ * MAKE FACE EULER:
+ * Takes a list of edge pointers which form a closed loop and makes a face
+ * from them. The first edge in elist is considered to be the start of the
+ * polygon, and v1 and v2 are its vertices and determine the winding of the face
+ * Other than the first edge, no other assumptions are made about the order of edges
+ * in the elist array. To verify that it is a single closed loop and derive the correct
+ * order a simple series of verifications is done and all elements are visited.
+ *
+ * Returns -
+ * A BMFace pointer
+ */
+
+#define MF_CANDIDATE 1
+#define MF_VISITED 2
+#define MF_TAKEN 4
+
+BMFace *bmesh_mf(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **elist, int len)
+{
+ BMFace *f = NULL;
+ BMEdge *curedge;
+ BMVert *curvert, *tv, **vlist;
+ int i, j, done, cont, edok;
+
+ if(len < 2) return NULL;
+
+ /*make sure that v1 and v2 are in elist[0]*/
+ if(bmesh_verts_in_edge(v1,v2,elist[0]) == 0)
+ return NULL;
+
+ /*clear euler flags*/
+ for(i=0;i<len;i++) elist[i]->head.eflag1=elist[i]->head.eflag2 = 0;
+ for(i=0;i<len;i++){
+ elist[i]->head.eflag1 |= MF_CANDIDATE;
+
+ /*if elist[i] has a loop, count its radial length*/
+ if(elist[i]->loop) elist[i]->head.eflag2 = bmesh_cycle_length(&(elist[i]->loop->radial));
+ else elist[i]->head.eflag2 = 0;
+ }
+
+ /* For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it
+ Note that this does not gauruntee that face is a single closed loop. At best it gauruntees
+ that elist contains a finite number of seperate closed loops.
+ */
+ for(i=0; i<len; i++){
+ edok = bmesh_disk_count_edgeflag(elist[i]->v1, MF_CANDIDATE, 0);
+ if(edok != 2) return NULL;
+ edok = bmesh_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0);
+ if(edok != 2) return NULL;
+ }
+
+ /*set start edge, start vert and target vert for our loop traversal*/
+ curedge = elist[0];
+ tv = v1;
+ curvert = v2;
+
+ if(bm->vtarlen < len){
+ if (bm->vtar) MEM_freeN(bm->vtar);
+ bm->vtar = MEM_callocN(sizeof(BMVert *)* len, "BM Vert pointer array");
+ bm->vtarlen = len;
+ }
+ /*insert tv into vlist since its the first vertex in face*/
+
+ i=0;
+ vlist=bm->vtar;
+ vlist[i] = tv;
+
+ /* Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't
+ been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE
+ edge, loop until we find TV. We know TV is reachable because of test we did earlier.
+ */
+ done=0;
+ while(!done){
+ /*add curvert to vlist*/
+ /*insert some error cheking here for overflows*/
+ i++;
+ vlist[i] = curvert;
+
+ /*mark curedge as visited*/
+ curedge->head.eflag1 |= MF_VISITED;
+
+ /*find next edge and vert*/
+ curedge = bmesh_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0);
+ curvert = bmesh_edge_getothervert(curedge, curvert);
+ if(curvert == tv){
+ curedge->head.eflag1 |= MF_VISITED;
+ done=1;
+ }
+ }
+
+ /* Verify that all edges have been visited It's possible that we did reach tv
+ from sv, but that several unconnected loops were passed in via elist.
+ */
+ cont=1;
+ for(i=0; i<len; i++){
+ if((elist[i]->head.eflag1 & MF_VISITED) == 0) cont = 0;
+ }
+
+ /*if we get this far, its ok to allocate the face and add the loops*/
+ if(cont){
+ BMLoop *l;
+ BMEdge *e;
+ f = bmesh_addpolylist(bm, NULL);
+ f->len = len;
+ for(i=0;i<len;i++){
+ curvert = vlist[i];
+ l = bmesh_create_loop(bm,curvert,NULL,f,NULL);
+ if(!(f->loopbase)) f->loopbase = l;
+ bmesh_cycle_append(f->loopbase, l);
+ }
+
+ /*take care of edge pointers and radial cycle*/
+ for(i=0, l = f->loopbase; i<len; i++, l=((BMLoop*)(l->head.next))){
+ e = NULL;
+ if(l == f->loopbase) e = elist[0]; /*first edge*/
+
+ else{/*search elist for others*/
+ for(j=1; j<len; j++){
+ edok = bmesh_verts_in_edge(l->v, ((BMLoop*)(l->head.next))->v, elist[j]);
+ if(edok){
+ e = elist[j];
+ break;
+ }
+ }
+ }
+ l->e = e; /*set pointer*/
+ bmesh_radial_append(e, l); /*append into radial*/
+ }
+
+ f->len = len;
+
+ /*Validation Loop cycle*/
+ edok = bmesh_cycle_validate(len, f->loopbase);
+ if(!edok) bmesh_error();
+ for(i=0, l = f->loopbase; i<len; i++, l=((BMLoop*)(l->head.next))){
+ /*validate loop vert pointers*/
+ edok = bmesh_verts_in_edge(l->v, ((BMLoop*)(l->head.next))->v, l->e);
+ if(!edok) bmesh_error();
+ /*validate the radial cycle of each edge*/
+ edok = bmesh_cycle_length(&(l->radial));
+ if(edok != (l->e->head.eflag2 + 1)) bmesh_error();
+ }
+ }
+
+ for(i=0;i<len;i++) elist[i]->head.eflag1=elist[i]->head.eflag2 = 0;
+ return f;
+}
+
+/* KILL Eulers */
+
+/**
+ * bmesh_KV
+ *
+ * KILL VERT EULER:
+ *
+ * Kills a single loose vertex.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_kv(BMesh *bm, BMVert *v){
+ if(v->edge == NULL){
+ if (BM_TestHFlag(v, BM_SELECT)) bm->totvertsel--;
+
+ BLI_remlink(&(bm->verts), &(v->head));
+ bmesh_free_vert(bm,v);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * bmesh_KE
+ *
+ * KILL EDGE EULER:
+ *
+ * Kills a wire edge.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_ke(BMesh *bm, BMEdge *e){
+ int edok;
+
+ /*Make sure that no faces!*/
+ if(e->loop == NULL){
+ bmesh_disk_remove_edge(e, e->v1);
+ bmesh_disk_remove_edge(e, e->v2);
+
+ /*verify that edge out of disk*/
+ edok = bmesh_disk_hasedge(e->v1, e);
+ if(edok) bmesh_error();
+ edok = bmesh_disk_hasedge(e->v2, e);
+ if(edok) bmesh_error();
+
+ /*remove and deallocate*/
+ if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel--;
+ BLI_remlink(&(bm->edges), &(e->head));
+ bmesh_free_edge(bm, e);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * bmesh_KF
+ *
+ * KILL FACE EULER:
+ *
+ * The logical inverse of bmesh_MF.
+ * Kills a face and removes each of its loops from the radial that it belongs to.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+*/
+
+int bmesh_kf(BMesh *bm, BMFace *bply){
+ BMLoop *newbase,*oldbase, *curloop;
+ int i,len=0;
+
+ /*add validation to make sure that radial cycle is cleaned up ok*/
+ /*deal with radial cycle first*/
+ len = bmesh_cycle_length(bply->loopbase);
+ for(i=0, curloop=bply->loopbase; i < len; i++, curloop = ((BMLoop*)(curloop->head.next)))
+ bmesh_radial_remove_loop(curloop, curloop->e);
+
+ /*now deallocate the editloops*/
+ for(i=0; i < len; i++){
+ newbase = ((BMLoop*)(bply->loopbase->head.next));
+ oldbase = bply->loopbase;
+ bmesh_cycle_remove(oldbase, oldbase);
+ bmesh_free_loop(bm, oldbase);
+ bply->loopbase = newbase;
+ }
+
+ if (BM_TestHFlag(bply, BM_SELECT)) bm->totfacesel--;
+ BLI_remlink(&(bm->polys), &(bply->head));
+ bmesh_free_poly(bm, bply);
+ return 1;
+}
+
+/*SPLIT Eulers*/
+
+/**
+ * bmesh_SEMV
+ *
+ * SPLIT EDGE MAKE VERT:
+ * Takes a given edge and splits it into two, creating a new vert.
+ *
+ *
+ * Before: OV---------TV
+ * After: OV----NV---TV
+ *
+ * Returns -
+ * BMVert pointer.
+ *
+*/
+
+BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **re){
+ BMVert *nv, *ov;
+ BMNode *diskbase;
+ BMEdge *ne;
+ int i, edok, valance1=0, valance2=0;
+
+ if(bmesh_vert_in_edge(e,tv) == 0) return NULL;
+ ov = bmesh_edge_getothervert(e,tv);
+ //v2 = tv;
+
+ /*count valance of v1*/
+ diskbase = bmesh_disk_getpointer(e, ov);
+ valance1 = bmesh_cycle_length(diskbase);
+ /*count valance of v2*/
+ diskbase = bmesh_disk_getpointer(e, tv);
+ valance2 = bmesh_cycle_length(diskbase);
+
+ nv = bmesh_addvertlist(bm, tv);
+ ne = bmesh_addedgelist(bm, nv, tv, e);
+
+ //e->v2 = nv;
+ /*remove e from v2's disk cycle*/
+ bmesh_disk_remove_edge(e, tv);
+ /*swap out tv for nv in e*/
+ bmesh_edge_swapverts(e, tv, nv);
+ /*add e to nv's disk cycle*/
+ bmesh_disk_append_edge(e, nv);
+ /*add ne to nv's disk cycle*/
+ bmesh_disk_append_edge(ne, nv);
+ /*add ne to tv's disk cycle*/
+ bmesh_disk_append_edge(ne, tv);
+ /*verify disk cycles*/
+ diskbase = bmesh_disk_getpointer(ov->edge,ov);
+ edok = bmesh_cycle_validate(valance1, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(tv->edge,tv);
+ edok = bmesh_cycle_validate(valance2, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(nv->edge,nv);
+ edok = bmesh_cycle_validate(2, diskbase);
+ if(!edok) bmesh_error();
+
+ /*Split the radial cycle if present*/
+ if(e->loop){
+ BMLoop *nl,*l;
+ BMNode *radEBase=NULL, *radNEBase=NULL;
+ int radlen = bmesh_cycle_length(&(e->loop->radial));
+ /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/
+ while(e->loop){
+ l=e->loop;
+ l->f->len++;
+ bmesh_radial_remove_loop(l,e);
+
+ nl = bmesh_create_loop(bm,NULL,NULL,l->f,l);
+ nl->head.prev = (BMHeader*)l;
+ nl->head.next = (BMHeader*)(l->head.next);
+ nl->head.prev->next = (BMHeader*)nl;
+ nl->head.next->prev = (BMHeader*)nl;
+ nl->v = nv;
+
+ /*assign the correct edge to the correct loop*/
+ if(bmesh_verts_in_edge(nl->v, ((BMLoop*)(nl->head.next))->v, e)){
+ nl->e = e;
+ l->e = ne;
+
+ /*append l into ne's rad cycle*/
+ if(!radNEBase){
+ radNEBase = &(l->radial);
+ radNEBase->next = NULL;
+ radNEBase->prev = NULL;
+ }
+
+ if(!radEBase){
+ radEBase = &(nl->radial);
+ radEBase->next = NULL;
+ radEBase->prev = NULL;
+ }
+
+ bmesh_cycle_append(radEBase,&(nl->radial));
+ bmesh_cycle_append(radNEBase,&(l->radial));
+
+ }
+ else if(bmesh_verts_in_edge(nl->v,((BMLoop*)(nl->head.next))->v,ne)){
+ nl->e = ne;
+ l->e = e;
+
+ if(!radNEBase){
+ radNEBase = &(nl->radial);
+ radNEBase->next = NULL;
+ radNEBase->prev = NULL;
+ }
+ if(!radEBase){
+ radEBase = &(l->radial);
+ radEBase->next = NULL;
+ radEBase->prev = NULL;
+ }
+ bmesh_cycle_append(radEBase,&(l->radial));
+ bmesh_cycle_append(radNEBase,&(nl->radial));
+ }
+
+ }
+
+ e->loop = radEBase->data;
+ ne->loop = radNEBase->data;
+
+ /*verify length of radial cycle*/
+ edok = bmesh_cycle_validate(radlen,&(e->loop->radial));
+ if(!edok) bmesh_error();
+ edok = bmesh_cycle_validate(radlen,&(ne->loop->radial));
+ if(!edok) bmesh_error();
+
+ /*verify loop->v and loop->next->v pointers for e*/
+ for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){
+ if(!(l->e == e)) bmesh_error();
+ if(!(l->radial.data == l)) bmesh_error();
+ if( ((BMLoop*)(l->head.prev))->e != ne && ((BMLoop*)(l->head.next))->e != ne) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, ((BMLoop*)(l->head.next))->v, e);
+ if(!edok) bmesh_error();
+ if(l->v == ((BMLoop*)(l->head.next))->v) bmesh_error();
+ if(l->e == ((BMLoop*)(l->head.next))->e) bmesh_error();
+ /*verify loop cycle for kloop->f*/
+ edok = bmesh_cycle_validate(l->f->len, l->f->loopbase);
+ if(!edok) bmesh_error();
+ }
+ /*verify loop->v and loop->next->v pointers for ne*/
+ for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){
+ if(!(l->e == ne)) bmesh_error();
+ if(!(l->radial.data == l)) bmesh_error();
+ if( ((BMLoop*)(l->head.prev))->e != e && ((BMLoop*)(l->head.next))->e != e) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, ((BMLoop*)(l->head.next))->v, ne);
+ if(!edok) bmesh_error();
+ if(l->v == ((BMLoop*)(l->head.next))->v) bmesh_error();
+ if(l->e == ((BMLoop*)(l->head.next))->e) bmesh_error();
+ /*verify loop cycle for kloop->f. Redundant*/
+ edok = bmesh_cycle_validate(l->f->len, l->f->loopbase);
+ if(!edok) bmesh_error();
+ }
+ }
+
+ if(re) *re = ne;
+ return nv;
+}
+
+/**
+ * bmesh_SFME
+ *
+ * SPLIT FACE MAKE EDGE:
+ *
+ * Takes as input two vertices in a single face. An edge is created which divides the original face
+ * into two distinct regions. One of the regions is assigned to the original face and it is closed off.
+ * The second region has a new face assigned to it.
+ *
+ * Examples:
+ *
+ * Before: After:
+ * ---------- ----------
+ * | | | |
+ * | | | f1 |
+ * v1 f1 v2 v1======v2
+ * | | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * Note that the input vertices can be part of the same edge. This will result in a two edged face.
+ * This is desirable for advanced construction tools and particularly essential for edge bevel. Because
+ * of this it is up to the caller to decide what to do with the extra edge.
+ *
+ * Note that the tesselator abuses eflag2 while using this euler! (don't ever ever do this....)
+ *
+ * Returns -
+ * A BMFace pointer
+ */
+BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **rl){
+
+ BMFace *f2;
+ BMLoop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL;
+ BMEdge *e;
+ int i, len, f1len, f2len;
+
+
+ /*verify that v1 and v2 are in face.*/
+ len = bmesh_cycle_length(f->loopbase);
+ for(i = 0, curloop = f->loopbase; i < len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop->v == v1) v1loop = curloop;
+ else if(curloop->v == v2) v2loop = curloop;
+ }
+
+ if(!v1loop || !v2loop) return NULL;
+
+ /*allocate new edge between v1 and v2*/
+ e = bmesh_addedgelist(bm, v1, v2,NULL);
+ bmesh_disk_append_edge(e, v1);
+ bmesh_disk_append_edge(e, v2);
+
+ f2 = bmesh_addpolylist(bm,f);
+ f1loop = bmesh_create_loop(bm,v2,e,f,v2loop);
+ f2loop = bmesh_create_loop(bm,v1,e,f2,v1loop);
+
+ f1loop->head.prev = v2loop->head.prev;
+ f2loop->head.prev = v1loop->head.prev;
+ v2loop->head.prev->next = (BMHeader*)f1loop;
+ v1loop->head.prev->next = (BMHeader*)f2loop;
+
+ f1loop->head.next = (BMHeader*)v1loop;
+ f2loop->head.next = (BMHeader*)v2loop;
+ v1loop->head.prev = (BMHeader*)f1loop;
+ v2loop->head.prev = (BMHeader*)f2loop;
+
+ f2->loopbase = f2loop;
+ f->loopbase = f1loop;
+
+ /*validate both loops*/
+ /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/
+
+ /*go through all of f2's loops and make sure they point to it properly.*/
+ f2len = bmesh_cycle_length(f2->loopbase);
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((BMLoop*)(curloop->head.next)) ) curloop->f = f2;
+
+ /*link up the new loops into the new edges radial*/
+ bmesh_radial_append(e, f1loop);
+ bmesh_radial_append(e, f2loop);
+
+
+ f2->len = f2len;
+
+ f1len = bmesh_cycle_length(f->loopbase);
+ f->len = f1len;
+
+ if(rl) *rl = f2loop;
+ return f2;
+}
+
+
+/**
+ * bmesh_JEKV
+ *
+ * JOIN EDGE KILL VERT:
+ * Takes a an edge and pointer to one of its vertices and collapses
+ * the edge on that vertex.
+ *
+ * Before: OE KE
+ * ------- -------
+ * | || |
+ * OV KV TV
+ *
+ *
+ * After: OE
+ * ---------------
+ * | |
+ * OV TV
+ *
+ *
+ * Restrictions:
+ * KV is a vertex that must have a valance of exactly two. Furthermore
+ * both edges in KV's disk cycle (OE and KE) must be unique (no double
+ * edges).
+ *
+ * It should also be noted that this euler has the possibility of creating
+ * faces with just 2 edges. It is up to the caller to decide what to do with
+ * these faces.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
+{
+ BMEdge *oe;
+ BMVert *ov, *tv;
+ BMNode *diskbase;
+ BMLoop *killoop,*nextl;
+ int len,radlen=0, halt = 0, i, valance1, valance2,edok;
+
+ if(bmesh_vert_in_edge(ke,kv) == 0) return 0;
+ diskbase = bmesh_disk_getpointer(kv->edge, kv);
+ len = bmesh_cycle_length(diskbase);
+
+ if(len == 2){
+ oe = bmesh_disk_nextedge(ke, kv);
+ tv = bmesh_edge_getothervert(ke, kv);
+ ov = bmesh_edge_getothervert(oe, kv);
+ halt = bmesh_verts_in_edge(kv, tv, oe); //check for double edges
+
+ if(halt) return 0;
+ else{
+
+ /*For verification later, count valance of ov and tv*/
+ diskbase = bmesh_disk_getpointer(ov->edge, ov);
+ valance1 = bmesh_cycle_length(diskbase);
+ diskbase = bmesh_disk_getpointer(tv->edge, tv);
+ valance2 = bmesh_cycle_length(diskbase);
+
+ /*remove oe from kv's disk cycle*/
+ bmesh_disk_remove_edge(oe,kv);
+ /*relink oe->kv to be oe->tv*/
+ bmesh_edge_swapverts(oe, kv, tv);
+ /*append oe to tv's disk cycle*/
+ bmesh_disk_append_edge(oe, tv);
+ /*remove ke from tv's disk cycle*/
+ bmesh_disk_remove_edge(ke, tv);
+
+
+
+ /*deal with radial cycle of ke*/
+ if(ke->loop){
+ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/
+ radlen = bmesh_cycle_length(&(ke->loop->radial));
+ for(i=0,killoop = ke->loop; i<radlen; i++, killoop = bmesh_radial_nextloop(killoop)){
+ /*relink loops and fix vertex pointer*/
+ killoop->head.next->prev = killoop->head.prev;
+ killoop->head.prev->next = killoop->head.next;
+ if( ((BMLoop*)(killoop->head.next))->v == kv) ((BMLoop*)(killoop->head.next))->v = tv;
+
+ /*fix len attribute of face*/
+ killoop->f->len--;
+ if(killoop->f->loopbase == killoop) killoop->f->loopbase = ((BMLoop*)(killoop->head.next));
+ }
+ /*second step, remove all the hanging loops attached to ke*/
+ killoop = ke->loop;
+ radlen = bmesh_cycle_length(&(ke->loop->radial));
+ /*make sure we have enough room in bm->lpar*/
+ if(bm->lparlen < radlen){
+ MEM_freeN(bm->lpar);
+ bm->lpar = MEM_callocN(sizeof(BMLoop *)* radlen, "BM Loop pointer array");
+ bm->lparlen = bm->lparlen * radlen;
+ }
+ /*this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well...*/
+ i=0;
+ while(i<radlen){
+ bm->lpar[i] = killoop;
+ killoop = killoop->radial.next->data;
+ i++;
+ }
+ i=0;
+ while(i<radlen){
+ bmesh_free_loop(bm,bm->lpar[i]);
+ i++;
+ }
+ /*Validate radial cycle of oe*/
+ edok = bmesh_cycle_validate(radlen,&(oe->loop->radial));
+
+ }
+
+
+ /*Validate disk cycles*/
+ diskbase = bmesh_disk_getpointer(ov->edge,ov);
+ edok = bmesh_cycle_validate(valance1, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(tv->edge,tv);
+ edok = bmesh_cycle_validate(valance2, diskbase);
+ if(!edok) bmesh_error();
+
+ /*Validate loop cycle of all faces attached to oe*/
+ for(i=0,nextl = oe->loop; i<radlen; i++, nextl = bmesh_radial_nextloop(nextl)){
+ edok = bmesh_cycle_validate(nextl->f->len,nextl->f->loopbase);
+ if(!edok) bmesh_error();
+ }
+ /*deallocate edge*/
+ BLI_remlink(&(bm->edges), &(ke->head));
+ bmesh_free_edge(bm, ke);
+ /*deallocate vertex*/
+ BLI_remlink(&(bm->verts), &(kv->head));
+ bmesh_free_vert(bm, kv);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * bmesh_loop_reverse
+ *
+ * FLIP FACE EULER
+ *
+ * Changes the winding order of a face from CW to CCW or vice versa.
+ * This euler is a bit peculiar in compairson to others as it is its
+ * own inverse.
+ *
+ * TODO: reinsert validation code.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_loop_reverse(BMesh *bm, BMFace *f){
+ BMLoop *l = f->loopbase, *curloop, *oldprev, *oldnext;
+ int i, j, edok, len = 0;
+
+ len = bmesh_cycle_length(l);
+ if(bm->edarlen < len){
+ MEM_freeN(bm->edar);
+ bm->edar = MEM_callocN(sizeof(BMEdge *)* len, "BM Edge pointer array");
+ bm->edarlen = len;
+ }
+
+ for(i=0, curloop = l; i< len; i++, curloop= ((BMLoop*)(curloop->head.next)) ){
+ curloop->e->head.eflag1 = 0;
+ curloop->e->head.eflag2 = bmesh_cycle_length(&curloop->radial);
+ bmesh_radial_remove_loop(curloop, curloop->e);
+ /*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/
+ curloop->radial.next = curloop->radial.prev = NULL;
+ bm->edar[i] = curloop->e;
+ }
+
+ /*actually reverse the loop. This belongs in bmesh_cycle_reverse!*/
+ for(i=0, curloop = l; i < len; i++){
+ oldnext = ((BMLoop*)(curloop->head.next));
+ oldprev = ((BMLoop*)(curloop->head.prev));
+ curloop->head.next = (BMHeader*)oldprev;
+ curloop->head.prev = (BMHeader*)oldnext;
+ curloop = oldnext;
+ }
+
+ if(len == 2){ //two edged face
+ //do some verification here!
+ l->e = bm->edar[1];
+ ((BMLoop*)(l->head.next))->e = bm->edar[0];
+ }
+ else{
+ for(i=0, curloop = l; i < len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ edok = 0;
+ for(j=0; j < len; j++){
+ edok = bmesh_verts_in_edge(curloop->v, ((BMLoop*)(curloop->head.next))->v, bm->edar[j]);
+ if(edok){
+ curloop->e = bm->edar[j];
+ break;
+ }
+ }
+ }
+ }
+ /*rebuild radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = ((BMLoop*)(curloop->head.next)) ) bmesh_radial_append(curloop->e, curloop);
+
+ /*validate radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ edok = bmesh_cycle_validate(curloop->e->head.eflag2, &(curloop->radial));
+ if(!edok){
+ bmesh_error();
+ }
+ }
+ return 1;
+}
+
+/**
+ * bmesh_JFKE
+ *
+ * JOIN FACE KILL EDGE:
+ *
+ * Takes two faces joined by a single 2-manifold edge and fuses them togather.
+ * The edge shared by the faces must not be connected to any other edges which have
+ * Both faces in its radial cycle
+ *
+ * Examples:
+ *
+ * A B
+ * ---------- ----------
+ * | | | |
+ * | f1 | | f1 |
+ * v1========v2 = Ok! v1==V2==v3 == Wrong!
+ * | f2 | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
+ * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
+ * in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
+ *
+ * Also note that the order of arguments decides whether or not certain per-face attributes are present
+ * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
+ * from f1, not f2.
+ *
+ * Returns -
+ * A BMFace pointer
+*/
+
+//disregarding f1loop and f2loop, if a vertex appears in a joined face more than once, we cancel
+
+BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
+
+ BMLoop *curloop, *f1loop=NULL, *f2loop=NULL;
+ int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok, shared;
+
+ if(f1 == f2) return NULL; //can't join a face to itself
+ /*verify that e is in both f1 and f2*/
+ f1len = bmesh_cycle_length(f1->loopbase);
+ f2len = bmesh_cycle_length(f2->loopbase);
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop->e == e){
+ f1loop = curloop;
+ break;
+ }
+ }
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop->e==e){
+ f2loop = curloop;
+ break;
+ }
+ }
+ if(!(f1loop && f2loop)) return NULL;
+
+ /*validate that edge is 2-manifold edge*/
+ radlen = bmesh_cycle_length(&(f1loop->radial));
+ if(radlen != 2) return NULL;
+
+ /*validate direction of f2's loop cycle is compatible.*/
+ if(f1loop->v == f2loop->v) return NULL;
+
+ /*
+ validate that for each face, each vertex has another edge in its disk cycle that is
+ not e, and not shared.
+ */
+ if(bmesh_radial_find_face( ((BMLoop*)(f1loop->head.next))->e,f2)) return NULL;
+ if(bmesh_radial_find_face( ((BMLoop*)(f1loop->head.prev))->e,f2)) return NULL;
+ if(bmesh_radial_find_face( ((BMLoop*)(f2loop->head.next))->e,f1)) return NULL;
+ if(bmesh_radial_find_face( ((BMLoop*)(f2loop->head.prev))->e,f1)) return NULL;
+
+ /*validate only one shared edge*/
+ shared = BM_Face_Sharededges(f1,f2);
+ if(shared > 1) return NULL;
+
+ /*validate no internal joins*/
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((BMLoop*)(curloop->head.next)) ) curloop->v->head.eflag1 = 0;
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((BMLoop*)(curloop->head.next)) ) curloop->v->head.eflag1 = 0;
+
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop != f1loop)
+ curloop->v->head.eflag1++;
+ }
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop != f2loop)
+ curloop->v->head.eflag1++;
+ }
+
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop->v->head.eflag1 > 1)
+ return NULL;
+ }
+
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((BMLoop*)(curloop->head.next)) ){
+ if(curloop->v->head.eflag1 > 1)
+ return NULL;
+ }
+
+ /*join the two loops*/
+ f1loop->head.prev->next = f2loop->head.next;
+ f2loop->head.next->prev = f1loop->head.prev;
+
+ f1loop->head.next->prev = f2loop->head.prev;
+ f2loop->head.prev->next = f1loop->head.next;
+
+ /*if f1loop was baseloop, give f1loop->next the base.*/
+ if(f1->loopbase == f1loop) f1->loopbase = ((BMLoop*)(f1loop->head.next));
+
+ /*validate the new loop*/
+ loopok = bmesh_cycle_validate((f1len+f2len)-2, f1->loopbase);
+ if(!loopok) bmesh_error();
+
+ /*make sure each loop points to the proper face*/
+ newlen = bmesh_cycle_length(f1->loopbase);
+ for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = ((BMLoop*)(curloop->head.next)) ) curloop->f = f1;
+
+ f1->len = newlen;
+
+ edok = bmesh_cycle_validate(f1->len, f1->loopbase);
+ if(!edok) bmesh_error();
+
+ /*remove edge from the disk cycle of its two vertices.*/
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1);
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2);
+
+ /*deallocate edge and its two loops as well as f2*/
+ BLI_remlink(&(bm->edges), &(f1loop->e->head));
+ BLI_remlink(&(bm->polys), &(f2->head));
+ bmesh_free_edge(bm, f1loop->e);
+ bmesh_free_loop(bm, f1loop);
+ bmesh_free_loop(bm, f2loop);
+ bmesh_free_poly(bm, f2);
+ return f1;
+}
+
+/**
+* bmesh_URMV
+*
+* UNGLUE REGION MAKE VERT:
+*
+* Takes a locally manifold disk of face corners and 'unglues' it
+* creating a new vertex
+*
+**/
+
+#define URMV_VISIT 1
+#define URMV_VISIT2 2
+
+BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+{
+ BMVert *nv = NULL;
+ BMLoop *l = NULL, *sl = NULL;
+ BMEdge *curedge = NULL;
+ int numloops = 0, numedges = 0, i, maxedges, maxloops;
+
+
+ /*Todo: Validation*/
+ /*validate radial cycle of all collected loops*/
+ /*validate the disk cycle of sv, and nv*/
+ /*validate the face length of all faces? overkill?*/
+ /*validate the l->e pointers of all affected faces, ie: l->v and l->next->v should be equivalent to l->e*/
+
+ /*verify that sv has edges*/
+ if(sv->edge == NULL)
+ return NULL;
+
+ /*first verify no wire edges on sv*/
+ curedge = sv->edge;
+ do{
+ if(curedge->loop == NULL)
+ return NULL;
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->edge);
+
+ /*next verify that sv is in sf*/
+ l = sf->loopbase;
+ do{
+ if(l->v == sv){
+ sl = l;
+ break;
+ }
+ l = (BMLoop*)(l->head.next);
+ }while(l != sf->loopbase);
+
+ if(sl == NULL)
+ return NULL;
+
+ /*clear euler flags*/
+ sv->head.eflag1 = 0;
+
+ curedge = sv->edge;
+ do{
+ curedge->head.eflag1 = 0;
+ l = curedge->loop;
+ do{
+ l->head.eflag1 = 0;
+ l->f->head.eflag1 = 0;
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->loop);
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->edge);
+
+ /*search through face disk and flag elements as we go.*/
+ /*Note, test this to make sure that it works correct on
+ non-manifold faces!
+ */
+ l = sl;
+ l->e->head.eflag1 |= URMV_VISIT;
+ l->f->head.eflag1 |= URMV_VISIT;
+ do{
+ if(l->v == sv)
+ l = bmesh_radial_nextloop((BMLoop*)(l->head.prev));
+ else
+ l = bmesh_radial_nextloop((BMLoop*)(l->head.next));
+ l->e->head.eflag1 |= URMV_VISIT;
+ l->f->head.eflag1 |= URMV_VISIT;
+ }while(l != sl && (bmesh_cycle_length(&(l->radial)) > 1) );
+
+ /*Verify that all visited edges are at least 1 or 2 manifold*/
+ curedge = sv->edge;
+ do{
+ if(curedge->head.eflag1 && (bmesh_cycle_length(&(curedge->loop->radial)) > 2) )
+ return NULL;
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->edge);
+
+ /*allocate temp storage - we overallocate here instead of trying to be clever*/
+ maxedges = 0;
+ maxloops = 0;
+ curedge = sv->edge;
+ do{
+ if(curedge->loop){
+ l = curedge->loop;
+ do{
+ maxloops += l->f->len;
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->loop);
+ }
+ maxedges+= 1;
+ curedge = bmesh_disk_nextedge(curedge,sv);
+ }while(curedge != sv->edge);
+
+ if(bm->edarlen < maxedges){
+ MEM_freeN(bm->edar);
+ bm->edar = MEM_callocN(sizeof(BMEdge *) * maxedges, "BM Edge pointer array");
+ bm->edarlen = maxedges;
+ }
+ if(bm->lparlen < maxloops){
+ MEM_freeN(bm->lpar);
+ bm->lpar = MEM_callocN(sizeof(BMLoop *) * maxloops, "BM Loop pointer array");
+ bm->lparlen = maxloops;
+ }
+
+ /*first get loops by looping around edges and loops around that edges faces*/
+ curedge = sv->edge;
+ do{
+ if(curedge->loop){
+ l = curedge->loop;
+ do{
+ if( (l->head.eflag1 & URMV_VISIT) && (!(l->head.eflag1 & URMV_VISIT2)) ){
+ bm->lpar[numloops] = l;
+ l->head.eflag1 |= URMV_VISIT2;
+ numloops++;
+ }
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->loop);
+ }
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->edge);
+
+ /*now collect edges by looping around edges and looking at visited flags*/
+ curedge = sv->edge;
+ do{
+ if(curedge->head.eflag1 & URMV_VISIT){
+ bm->edar[numedges] = curedge;
+ numedges++;
+ }
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->edge);
+
+ /*make new vertex*/
+ nv = bmesh_addvertlist(bm, sv);
+
+ /*go through and relink edges*/
+ for(i = 0; i < numedges; i++){
+ curedge = bm->edar[i];
+ /*remove curedge from sv*/
+ bmesh_disk_remove_edge(curedge, sv);
+ /*swap out sv for nv in curedge*/
+ bmesh_edge_swapverts(curedge, sv, nv);
+ /*add curedge to nv's disk cycle*/
+ bmesh_disk_append_edge(curedge, nv);
+ }
+
+ /*go through and relink loops*/
+ for(i = 0; i < numloops; i ++){
+ l = bm->lpar[i];
+ if(l->v == sv)
+ l->v = nv;
+ }
+ return nv;
+}
diff --git a/source/blender/bmesh/intern/bmesh_filters.c b/source/blender/bmesh/intern/bmesh_filters.c
new file mode 100644
index 00000000000..c31139a8f93
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_filters.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
new file mode 100644
index 00000000000..ae0904a75df
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -0,0 +1,246 @@
+/**
+ * BME_interp.c August 2008
+ *
+ * BM interpolation functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+/*
+ * BME_INTERP.C
+ *
+ * Functions for interpolating data across the surface of a mesh.
+ *
+*/
+
+/**
+ * bmesh_data_interp_from_verts
+ *
+ * Interpolates per-vertex data from two sources to a target.
+ *
+ * Returns -
+ * Nothing
+ */
+void BM_Data_Interp_From_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, float fac)
+{
+ void *src[2];
+ float w[2];
+ if (v1->head.data && v2->head.data) {
+ src[0]= v1->head.data;
+ src[1]= v2->head.data;
+ w[0] = 1.0f-fac;
+ w[1] = fac;
+ CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->head.data);
+ }
+}
+
+/**
+ * bmesh_data_facevert_edgeinterp
+ *
+ * Walks around the faces of an edge and interpolates the per-face-edge
+ * data between two sources to a target.
+ *
+ * Returns -
+ * Nothing
+*/
+
+void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, float fac){
+ void *src[2];
+ float w[2];
+ BMLoop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
+
+ w[1] = 1.0f - fac;
+ w[0] = fac;
+
+ if(!e1->loop) return;
+ l = e1->loop;
+ do{
+ if(l->v == v1){
+ v1loop = l;
+ vloop = (BMLoop*)(v1loop->head.next);
+ v2loop = (BMLoop*)(vloop->head.next);
+ }else if(l->v == v){
+ v1loop = (BMLoop*)(l->head.next);
+ vloop = l;
+ v2loop = (BMLoop*)(l->head.prev);
+
+ }
+
+ src[0] = v1loop->head.data;
+ src[1] = v2loop->head.data;
+
+ CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);
+ l = l->radial.next->data;
+ }while(l!=e1->loop);
+}
+
+void BM_loops_to_corners(BMesh *bm, Mesh *me, int findex,
+ BMFace *f, int numTex, int numCol)
+{
+ BMLoop *l;
+ BMIter iter;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ j = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+
+ j++;
+ }
+
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ j = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+
+ j++;
+ }
+ }
+}
+
+//static void bmesh_data_interp_from_face(BME_Mesh *bm, BMFace *source, BMFace *target)
+//{
+//
+//}
+/*insert BM_data_interp_from_face here for mean value coordinates...*/
+
+
+static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
+{
+ BMIter iter;
+ void *block;
+
+ if (data == &bm->vdata) {
+ BMVert *eve;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eve->head.data);
+ eve->head.data= block;
+ }
+ }
+ else if (data == &bm->edata) {
+ BMEdge *eed;
+
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eed->head.data);
+ eed->head.data= block;
+ }
+ }
+ else if (data == &bm->pdata || data == &bm->ldata) {
+ BMIter liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (data == &bm->pdata) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &efa->head.data);
+ efa->head.data= block;
+ }
+
+ if (data == &bm->ldata) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &l->head.data);
+ l->head.data= block;
+ }
+ }
+ }
+ }
+}
+
+
+void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_add_layer(data, type, CD_CALLOC, NULL, 0);
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_free_layer_active(data, type, 0);
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
new file mode 100644
index 00000000000..73c76817254
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -0,0 +1,393 @@
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+
+void *BMIter_AtIndex(struct BMesh *bm, int type, void *data, int index)
+{
+ BMIter iter;
+ void *val;
+ int i;
+
+ /*sanity check*/
+ if (index < 0) return NULL;
+
+ val=BMIter_New(&iter, bm, type, data);
+
+ i = 0;
+ while (i < index) {
+ val=BMIter_Step(&iter);
+ i++;
+ }
+
+ return val;
+}
+
+/*
+ * BMESH ITERATOR STEP
+ *
+ * Calls an iterators step fucntion to return
+ * the next element.
+*/
+
+void *BMIter_Step(BMIter *iter)
+{
+ return iter->step(iter);
+}
+
+/*
+ * INIT ITERATOR
+ *
+ * Clears the internal state of an iterator
+ * For begin() callbacks.
+ *
+*/
+
+static void init_iterator(BMIter *iter)
+{
+ iter->firstvert = iter->nextvert = NULL;
+ iter->firstedge = iter->nextedge = NULL;
+ iter->firstloop = iter->nextloop = NULL;
+ iter->firstpoly = iter->nextpoly = NULL;
+ iter->ldata = NULL;
+}
+
+/*
+ * Notes on iterator implementation:
+ *
+ * Iterators keep track of the next element
+ * in a sequence. When a step() callback is
+ * invoked the current value of 'next' is stored
+ * to be returned later and the next variable is
+ * incremented.
+ *
+ * When the end of a sequence is
+ * reached, next should always equal NULL
+ *
+*/
+
+/*
+ * VERT OF MESH CALLBACKS
+ *
+*/
+
+static void vert_of_mesh_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ if(iter->bm->verts.first){
+ iter->firstvert = iter->bm->verts.first;
+ iter->nextvert = iter->bm->verts.first;
+ }
+}
+
+static void *vert_of_mesh_step(BMIter *iter)
+{
+ BMVert *current = iter->nextvert;
+
+ if(iter->nextvert)
+ iter->nextvert = (BMVert*)(iter->nextvert->head.next);
+
+ return current;
+}
+
+/*
+ * EDGE OF MESH CALLBACKS
+ *
+*/
+
+static void edge_of_mesh_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ if(iter->bm->edges.first){
+ iter->firstedge = iter->bm->edges.first;
+ iter->nextedge = iter->bm->edges.first;
+ }
+}
+
+static void *edge_of_mesh_step(BMIter *iter)
+{
+ BMEdge *current = iter->nextedge;
+
+ if(iter->nextedge)
+ iter->nextedge = (BMEdge*)(iter->nextedge->head.next);
+
+ return current;
+}
+
+/*
+ * FACE OF MESH CALLBACKS
+ *
+*/
+
+static void face_of_mesh_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ if(iter->bm->polys.first){
+ iter->firstpoly = iter->bm->polys.first;
+ iter->nextpoly = iter->bm->polys.first;
+ }
+}
+
+static void *face_of_mesh_step(BMIter *iter)
+{
+ BMFace *current = iter->nextpoly;
+
+ if(iter->nextpoly)
+ iter->nextpoly = (BMFace*)(iter->nextpoly->head.next);
+ return current;
+}
+
+/*
+ * EDGE OF VERT CALLBACKS
+ *
+*/
+
+static void edge_of_vert_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ if(iter->vdata->edge){
+ iter->firstedge = iter->vdata->edge;
+ iter->nextedge = iter->vdata->edge;
+ }
+}
+
+static void *edge_of_vert_step(BMIter *iter)
+{
+ BMEdge *current = iter->nextedge;
+
+ if(iter->nextedge)
+ iter->nextedge = bmesh_disk_nextedge(iter->nextedge, iter->vdata);
+
+ if(iter->nextedge == iter->firstedge) iter->nextedge = NULL;
+
+ return current;
+}
+
+/*
+ * FACE OF VERT CALLBACKS
+ *
+*/
+
+static void face_of_vert_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->count = 0;
+ if(iter->vdata->edge)
+ iter->count = bmesh_disk_count_facevert(iter->vdata);
+ if(iter->count){
+ iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->edge, iter->vdata);
+ iter->nextedge = iter->firstedge;
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->loop, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+}
+static void *face_of_vert_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->count){
+ iter->count--;
+ iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
+ if(iter->nextloop == iter->firstloop){
+ iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->loop, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+ }
+
+ if(!iter->count) iter->nextloop = NULL;
+
+
+ if(current) return current->f;
+ return NULL;
+}
+
+static void loops_of_loop_begin(BMIter *iter)
+{
+ BMLoop *l;
+
+ l = iter->ldata;
+
+ /*note sure why this sets ldata. . .*/
+ init_iterator(iter);
+
+ iter->firstloop = l;
+ iter->nextloop = bmesh_radial_nextloop(iter->firstloop);
+}
+
+static void *loops_of_loop_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+ if(current) return current;
+ return NULL;
+}
+
+/*
+ * FACE OF EDGE CALLBACKS
+ *
+*/
+
+static void face_of_edge_begin(BMIter *iter)
+{
+ init_iterator(iter);
+
+ if(iter->edata->loop){
+ iter->firstloop = iter->edata->loop;
+ iter->nextloop = iter->edata->loop;
+ }
+}
+
+static void *face_of_edge_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+ if(current) return current->f;
+ return NULL;
+}
+
+/*
+ * VERT OF FACE CALLBACKS
+ *
+*/
+
+static void vert_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = iter->pdata->loopbase;
+}
+
+static void *vert_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = ((BMLoop*)(iter->nextloop->head.next));
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ if(current) return current->v;
+ return NULL;
+}
+
+/*
+ * EDGE OF FACE CALLBACKS
+ *
+*/
+
+static void edge_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = iter->pdata->loopbase;
+}
+
+static void *edge_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = ((BMLoop*)(iter->nextloop->head.next));
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ if(current) return current->e;
+ return NULL;
+}
+
+/*
+ * LOOP OF FACE CALLBACKS
+ *
+*/
+
+static void loop_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = iter->pdata->loopbase;
+}
+
+static void *loop_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = ((BMLoop*)(iter->nextloop->head.next));
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ return current;
+}
+
+/*
+ * BMESH ITERATOR INIT
+ *
+ * Takes a bmesh iterator structure and fills
+ * it with the appropriate function pointers based
+ * upon its type and then calls BMeshIter_step()
+ * to return the first element of the iterator.
+ *
+*/
+void *BMIter_New(BMIter *iter, BMesh *bm, int type, void *data)
+{
+ int argtype;
+ iter->type = type;
+ iter->bm = bm;
+
+ switch(type){
+ case BM_VERTS_OF_MESH:
+ iter->begin = vert_of_mesh_begin;
+ iter->step = vert_of_mesh_step;
+ iter->bm = bm;
+ break;
+ case BM_EDGES_OF_MESH:
+ iter->begin = edge_of_mesh_begin;
+ iter->step = edge_of_mesh_step;
+ iter->bm = bm;
+ break;
+ case BM_FACES_OF_MESH:
+ iter->begin = face_of_mesh_begin;
+ iter->step = face_of_mesh_step;
+ iter->bm = bm;
+ break;
+ case BM_EDGES_OF_VERT:
+ iter->begin = edge_of_vert_begin;
+ iter->step = edge_of_vert_step;
+ iter->vdata = data;
+ break;
+ case BM_FACES_OF_VERT:
+ iter->begin = face_of_vert_begin;
+ iter->step = face_of_vert_step;
+ iter->vdata = data;
+ break;
+ case BM_FACES_OF_EDGE:
+ iter->begin = face_of_edge_begin;
+ iter->step = face_of_edge_step;
+ iter->edata = data;
+ break;
+ case BM_VERTS_OF_FACE:
+ iter->begin = vert_of_face_begin;
+ iter->step = vert_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_EDGES_OF_FACE:
+ iter->begin = edge_of_face_begin;
+ iter->step = edge_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_LOOPS_OF_FACE:
+ iter->begin = loop_of_face_begin;
+ iter->step = loop_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_LOOPS_OF_LOOP:
+ iter->begin = loops_of_loop_begin;
+ iter->step = loops_of_loop_step;
+ iter->ldata = data;
+ break;
+ default:
+ break;
+ }
+
+ iter->begin(iter);
+ return BMIter_Step(iter);
+}
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
new file mode 100644
index 00000000000..5923add3025
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -0,0 +1,307 @@
+#include <string.h>
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+
+/*
+ * BM_MARK.C
+ *
+ * Selection routines for bmesh structures.
+ * This is actually all old code ripped from
+ * editmesh_lib.c and slightly modified to work
+ * for bmesh's. This also means that it has some
+ * of the same problems.... something that
+ * that should be addressed eventually.
+ *
+*/
+
+
+/*
+ * BMESH SELECTMODE FLUSH
+ *
+ * Makes sure to flush selections
+ * 'upwards' (ie: all verts of an edge
+ * selects the edge and so on). This
+ * should only be called by system and not
+ * tool authors.
+ *
+*/
+
+static void recount_totsels(BMesh *bm)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ /*recount tot*sel variables*/
+ bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
+ tots[0] = &bm->totvertsel;
+ tots[1] = &bm->totedgesel;
+ tots[2] = &bm->totfacesel;
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
+ }
+ }
+}
+
+void BM_SelectMode_Flush(BMesh *bm)
+{
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter edges;
+ BMIter faces;
+
+ int totsel;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
+ if(BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT)) BM_SetHFlag(e, BM_SELECT);
+ else BM_ClearHFlag(e, BM_SELECT);
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l=f->loopbase;
+ do{
+ if(BM_TestHFlag(l->v, BM_SELECT))
+ totsel++;
+ l = ((BMLoop*)(l->head.next));
+ } while(l != f->loopbase);
+
+ if(totsel == f->len)
+ BM_SetHFlag(f, BM_SELECT);
+ else
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l=f->loopbase;
+ do{
+ if(bmesh_test_sysflag(&(l->e->head), BM_SELECT))
+ totsel++;
+ l = ((BMLoop*)(l->head.next));
+ }while(l!=f->loopbase);
+
+ if(totsel == f->len)
+ BM_SetHFlag(f, BM_SELECT);
+ else
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+
+ recount_totsels(bm);
+}
+
+/*
+ * BMESH SELECT VERT
+ *
+ * Changes selection state of a single vertex
+ * in a mesh
+ *
+*/
+
+void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
+{
+ if(select) {
+ if (!BM_TestHFlag(v, BM_SELECT)) bm->totvertsel += 1;
+ BM_SetHFlag(v, BM_SELECT);
+ } else {
+ if (BM_TestHFlag(v, BM_SELECT)) bm->totvertsel -= 1;
+ BM_ClearHFlag(v, BM_SELECT);
+ }
+}
+
+/*
+ * BMESH SELECT EDGE
+ *
+ * Changes selection state of a single edge
+ * in a mesh. Note that this is actually not
+ * 100 percent reliable. Deselecting an edge
+ * will also deselect both its vertices
+ * regardless of the selection state of
+ * other edges incident upon it. Fixing this
+ * issue breaks multi-select mode though...
+ *
+*/
+
+void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
+{
+ int candesel;
+ int testiso = 1;
+
+ /*I might move this logic to bmeshutils_mods.c, where it'd be invoked
+ by the selection tools. in that case, we'd still retain the checks
+ for if an edge's verts can be deselected.*/
+
+ /*ensure vert selections are valid, only if not in a multiselect
+ mode that shares SCE_SELECT_VERT*/
+ if (bm->selectmode & (SCE_SELECT_VERTEX|SCE_SELECT_EDGE)) testiso = 1;
+ else if (bm->selectmode & (SCE_SELECT_VERTEX|SCE_SELECT_FACE)) testiso = 1;
+
+ if (testiso && !select) {
+ BMIter eiter;
+ BMEdge *e2;
+ int i;
+
+ for (i=0; i<2; i++) {
+ candesel = 1;
+ e2 = BMIter_New(&eiter, bm, BM_EDGES_OF_VERT, !i?e->v1:e->v2);
+ for (; e2; e2=BMIter_Step(&eiter)) {
+ if (e2 == e) continue;
+ if (BM_TestHFlag(e2, BM_SELECT)) {
+ candesel = 0;
+ break;
+ }
+ }
+
+ if (candesel) BM_Select_Vert(bm, !i?e->v1:e->v2, 0);
+ }
+ }
+
+ if(select) {
+ if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
+
+ BM_SetHFlag(&(e->head), BM_SELECT);
+ BM_SetHFlag(e->v1, BM_SELECT);
+ BM_SetHFlag(e->v2, BM_SELECT);
+ }
+ else{
+ if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
+
+ BM_ClearHFlag(&(e->head), BM_SELECT);
+ }
+}
+
+/*
+ *
+ * BMESH SELECT FACE
+ *
+ * Changes selection state of a single
+ * face in a mesh. This (might) suffer
+ * from same problems as edge select
+ * code...
+ *
+*/
+
+void BM_Select_Face(BMesh *bm, BMFace *f, int select)
+{
+ BMLoop *l;
+
+ if(select){
+ if (!BM_TestHFlag(f, BM_SELECT)) bm->totfacesel += 1;
+
+ BM_SetHFlag(&(f->head), BM_SELECT);
+ l = f->loopbase;
+ do{
+ BM_SetHFlag(&(l->v->head), BM_SELECT);
+ BM_SetHFlag(&(l->e->head), BM_SELECT);
+ l = ((BMLoop*)(l->head.next));
+ }while(l != f->loopbase);
+ }
+ else{
+ if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
+
+ BM_ClearHFlag(&(f->head), BM_SELECT);
+ l = f->loopbase;
+ do {
+ BM_ClearHFlag(&(l->v->head), BM_SELECT);
+ BM_ClearHFlag(&(l->e->head), BM_SELECT);
+ l = ((BMLoop*)(l->head.next));
+ } while(l != f->loopbase);
+ }
+}
+
+/*
+ * BMESH SELECTMODE SET
+ *
+ * Sets the selection mode for the bmesh
+ *
+*/
+
+void BM_Selectmode_Set(BMesh *bm, int selectmode)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ bm->selectmode = selectmode;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces))
+ BM_ClearHFlag(f, 0);
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(v= BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts))
+ BM_ClearHFlag(v, 0);
+ for(e= BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)){
+ if(BM_TestHFlag(&(e->head), BM_SELECT))
+ BM_Select_Edge(bm, e, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_FACE) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)){
+ if(BM_TestHFlag(&(f->head), BM_SELECT))
+ BM_Select_Face(bm, f, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+}
+
+
+int BM_CountFlag(struct BMesh *bm, int type, int flag)
+{
+ BMHeader *head;
+ BMIter iter;
+ int tot = 0;
+
+ if (type & BM_VERT) {
+ for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (head->flag & flag) tot++;
+ }
+ }
+ if (type & BM_EDGE) {
+ for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (head->flag & flag) tot++;
+ }
+ }
+ if (type & BM_FACE) {
+ for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (head->flag & flag) tot++;
+ }
+ }
+
+ return tot;
+}
+
+void BM_Select(struct BMesh *bm, void *element, int select)
+{
+ BMHeader *head = element;
+
+ if(head->type == BM_VERT) BM_Select_Vert(bm, (BMVert*)element, select);
+ else if(head->type == BM_EDGE) BM_Select_Edge(bm, (BMEdge*)element, select);
+ else if(head->type == BM_FACE) BM_Select_Face(bm, (BMFace*)element, select);
+}
+
+int BM_Is_Selected(BMesh *bm, void *element)
+{
+ BMHeader *head = element;
+ return BM_TestHFlag(head, BM_SELECT);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
new file mode 100644
index 00000000000..48b0d117843
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -0,0 +1,277 @@
+/**
+ * BME_mesh.c jan 2007
+ *
+ * BM mesh level functions.
+ *
+ * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+#include "DNA_listBase.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+void BME_error(void);
+
+/*bmesh_error stub*/
+void bmesh_error(void)
+{
+ printf("BM modelling error!");
+}
+
+/*
+ * BMESH SET SYSFLAG
+ *
+ * Sets a bitflag for a given element.
+ *
+*/
+
+void bmesh_set_sysflag(BMHeader *head, int flag)
+{
+ head->flag |= flag;
+}
+
+/*
+ * BMESH CLEAR SYSFLAG
+ *
+ * Clears a bitflag for a given element.
+ *
+*/
+
+void bmesh_clear_sysflag(BMHeader *head, int flag)
+{
+ head->flag &= ~flag;
+}
+
+
+/*
+ * BMESH TEST SYSFLAG
+ *
+ * Tests whether a bitflag is set for a given element.
+ *
+*/
+
+int bmesh_test_sysflag(BMHeader *head, int flag)
+{
+ if(head->flag & flag)
+ return 1;
+ return 0;
+}
+
+/*
+ * BMESH MAKE MESH
+ *
+ * Allocates a new BMesh structure.
+ * Returns -
+ * Pointer to a BM
+ *
+*/
+
+BMesh *BM_Make_Mesh(int allocsize[4])
+{
+ /*allocate the structure*/
+ BMesh *bm = MEM_callocN(sizeof(BMesh),"BM");
+ /*allocate the memory pools for the mesh elements*/
+ bm->vpool = BLI_mempool_create(sizeof(BMVert), allocsize[0], allocsize[0]);
+ bm->epool = BLI_mempool_create(sizeof(BMEdge), allocsize[1], allocsize[1]);
+ bm->lpool = BLI_mempool_create(sizeof(BMLoop), allocsize[2], allocsize[2]);
+ bm->ppool = BLI_mempool_create(sizeof(BMFace), allocsize[3], allocsize[3]);
+
+ /*allocate one flag pool that we dont get rid of.*/
+ bm->flagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512);
+ bm->totflags = 1;
+
+ return bm;
+}
+/*
+ * BMESH FREE MESH
+ *
+ * Frees a BMesh structure.
+*/
+
+void BM_Free_Mesh_Data(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v = BMIter_Step(&verts)) CustomData_bmesh_free_block( &(bm->vdata), &(v->head.data) );
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e = BMIter_Step(&edges)) CustomData_bmesh_free_block( &(bm->edata), &(e->head.data) );
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){
+ CustomData_bmesh_free_block( &(bm->pdata), &(f->head.data) );
+ for(l = BMIter_New(&loops, bm, BM_LOOPS_OF_FACE, f ); l; l = BMIter_Step(&loops)) CustomData_bmesh_free_block( &(bm->ldata), &(l->head.data) );
+ }
+
+ /*Free custom data pools, This should probably go in CustomData_free?*/
+ if(bm->vdata.totlayer) BLI_mempool_destroy(bm->vdata.pool);
+ if(bm->edata.totlayer) BLI_mempool_destroy(bm->edata.pool);
+ if(bm->ldata.totlayer) BLI_mempool_destroy(bm->ldata.pool);
+ if(bm->pdata.totlayer) BLI_mempool_destroy(bm->pdata.pool);
+
+ /*free custom data*/
+ CustomData_free(&bm->vdata,0);
+ CustomData_free(&bm->edata,0);
+ CustomData_free(&bm->ldata,0);
+ CustomData_free(&bm->pdata,0);
+
+ /*destroy element pools*/
+ BLI_mempool_destroy(bm->vpool);
+ BLI_mempool_destroy(bm->epool);
+ BLI_mempool_destroy(bm->ppool);
+ BLI_mempool_destroy(bm->lpool);
+
+ /*destroy flag pool*/
+ BLI_mempool_destroy(bm->flagpool);
+
+ BMO_ClearStack(bm);
+}
+
+void BM_Free_Mesh(BMesh *bm)
+{
+ BM_Free_Mesh_Data(bm);
+ MEM_freeN(bm);
+}
+
+/*
+ * BMESH COMPUTE NORMALS
+ *
+ * Updates the normals of a mesh.
+ * Note that this can only be called
+ *
+*/
+
+void BM_Compute_Normals(BMesh *bm)
+{
+ BMVert *v;
+ BMFace *f;
+ BMLoop *l;
+
+ BMIter verts;
+ BMIter faces;
+ BMIter loops;
+
+ unsigned int maxlength = 0;
+ float (*projectverts)[3];
+
+ /*first, find out the largest face in mesh*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+
+ /*make sure we actually have something to do*/
+ if(maxlength < 3) return;
+
+ /*allocate projectverts array*/
+ projectverts = MEM_callocN(sizeof(float) * maxlength * 3, "BM normal computation array");
+
+ /*calculate all face normals*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){
+ if (f->head.flag & BM_NONORMCALC) continue;
+ bmesh_update_face_normal(bm, f, projectverts);
+ }
+
+ /*Zero out vertex normals*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v = BMIter_Step(&verts)) v->no[0] = v->no[1] = v->no[2] = 0.0;
+
+ /*add face normals to vertices*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){
+ for(l = BMIter_New(&loops, bm, BM_LOOPS_OF_FACE, f ); l; l = BMIter_Step(&loops)) VecAddf(l->v->no, l->v->no, f->no);
+ }
+
+ /*average the vertex normals*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts)){
+ if (Normalize(v->no)==0.0) {
+ VECCOPY(v->no, v->co);
+ Normalize(v->no);
+ }
+ }
+
+ MEM_freeN(projectverts);
+}
+
+/*
+ * BMESH BEGIN/END EDIT
+ *
+ * Functions for setting up a mesh for editing and cleaning up after
+ * the editing operations are done. These are called by the tools/operator
+ * API for each time a tool is executed.
+ *
+ * Returns -
+ * Nothing
+ *
+*/
+
+void bmesh_begin_edit(BMesh *bm){
+
+ /*Initialize some scratch pointer arrays used by eulers*/
+ bm->vtar = MEM_callocN(sizeof(BMVert *) * 1024, "BM scratch vert array");
+ bm->edar = MEM_callocN(sizeof(BMEdge *) * 1024, "BM scratch edge array");
+ bm->lpar = MEM_callocN(sizeof(BMLoop *) * 1024, "BM scratch loop array");
+ bm->plar = MEM_callocN(sizeof(BMFace *) * 1024, "BM scratch poly array");
+
+ bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 1024;
+}
+
+void bmesh_end_edit(BMesh *bm, int flag){
+ int totvert, totedge, totface;
+ /*verify element counts*/
+ totvert = BLI_countlist(&(bm->verts));
+ totedge = BLI_countlist(&(bm->edges));
+ totface = BLI_countlist(&(bm->polys));
+
+ if(bm->totvert!=totvert || bm->totedge!=totedge || bm->totface!=totface) BME_error();
+
+ /*free temp storage*/
+ if(bm->vtar) MEM_freeN(bm->vtar);
+ if(bm->edar) MEM_freeN(bm->edar);
+ if(bm->lpar) MEM_freeN(bm->lpar);
+ if(bm->plar) MEM_freeN(bm->plar);
+
+ /*zero out pointers*/
+ bm->vtar = NULL;
+ bm->edar = NULL;
+ bm->lpar = NULL;
+ bm->plar = NULL;
+ bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 0;
+
+ /*compute normals, clear temp flags and flush selections*/
+ BM_Compute_Normals(bm);
+ BM_SelectMode_Flush(bm);
+}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
new file mode 100644
index 00000000000..433b8a74387
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -0,0 +1,417 @@
+#include <limits.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_ghash.h"
+#include "BLI_arithb.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * BME_MODS.C
+ *
+ * This file contains functions for locally modifying
+ * the topology of existing mesh data. (split, join, flip ect).
+ *
+*/
+
+/**
+ * bmesh_dissolve_disk
+ *
+ * Turns the face region surrounding a manifold vertex into
+ * A single polygon.
+ *
+ *
+ * Example:
+ *
+ * |=========| |=========|
+ * | \ / | | |
+ * Before: | V | After: | |
+ * | / \ | | |
+ * |=========| |=========|
+ *
+ *
+ */
+#if 1
+int BM_Dissolve_Vert(BMesh *bm, BMVert *v) {
+ BMIter iter;
+ BMEdge *e;
+ int len=0;
+
+ if (!v) return 0;
+
+ e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v);
+ for (; e; e=BMIter_Step(&iter)) {
+ len++;
+ }
+
+ if (len == 1) {
+ bmesh_ke(bm, v->edge);
+ bmesh_kv(bm, v);
+ return 1;
+ }
+
+ if(BM_Nonmanifold_Vert(bm, v)) {
+ if (!v->edge) bmesh_kv(bm, v);
+ else if (!v->edge->loop) {
+ bmesh_ke(bm, v->edge);
+ bmesh_kv(bm, v);
+ } else return 0;
+
+ return 1;
+ }
+
+ return BM_Dissolve_Disk(bm, v);
+}
+
+int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
+ BMFace *f, *f2;
+ BMEdge *e, *keepedge=NULL, *baseedge=NULL;
+ BMLoop *loop;
+ int done, len;
+
+ if(BM_Nonmanifold_Vert(bm, v)) {
+ return 0;
+ }
+
+ if(v->edge){
+ /*v->edge we keep, what else?*/
+ e = v->edge;
+ len = 0;
+ do{
+ e = bmesh_disk_nextedge(e,v);
+ if(!(BM_Edge_Share_Faces(e, v->edge))){
+ keepedge = e;
+ baseedge = v->edge;
+ break;
+ }
+ len++;
+ }while(e != v->edge);
+ }
+
+ /*this code for handling 2 and 3-valence verts
+ may be totally bad.*/
+ if (keepedge == NULL && len == 3) {
+ /*handle specific case for three-valence. solve it by
+ increasing valence to four. this may be hackish. . .*/
+ loop = e->loop;
+ if (loop->v == v) loop = (BMLoop*) loop->head.next;
+ if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
+ return 0;
+
+ BM_Dissolve_Disk(bm, v);
+ return 1;
+ } else if (keepedge == NULL && len == 2) {
+ /*handle two-valence*/
+ f = v->edge->loop->f;
+ f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
+ /*collapse the vertex*/
+ BM_Collapse_Vert(bm, v->edge, v, 1.0);
+ BM_Join_Faces(bm, f, f2, NULL);
+
+ return 1;
+ }
+
+ if(keepedge){
+ done = 0;
+ while(!done){
+ done = 1;
+ e = v->edge;
+ do{
+ f = NULL;
+ len = bmesh_cycle_length(&(e->loop->radial));
+ if(len == 2 && (e!=baseedge) && (e!=keepedge)) {
+ f = BM_Join_Faces(bm, e->loop->f, ((BMLoop*)(e->loop->radial.next->data))->f, e);
+ /*return if couldn't join faces in manifold
+ conditions.*/
+ //!disabled for testing why bad things happen
+ if (!f) return 0;
+ }
+
+ if(f){
+ done = 0;
+ break;
+ }
+ e = bmesh_disk_nextedge(e, v);
+ }while(e != v->edge);
+ }
+
+ /*get remaining two faces*/
+ f = v->edge->loop->f;
+ f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
+
+ /*collapse the vertex*/
+ BM_Collapse_Vert(bm, baseedge, v, 1.0);
+
+ if (f != f2) {
+ /*join two remaining faces*/
+ if (!BM_Join_Faces(bm, f, f2, NULL)) return 0;
+ }
+ }
+
+ return 1;
+}
+#else
+void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
+ BMFace *f;
+ BMEdge *e;
+ BMIter iter;
+ int done, len;
+
+ if(v->edge){
+ done = 0;
+ while(!done){
+ done = 1;
+
+ /*loop the edges looking for an edge to dissolve*/
+ for (e=BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); e;
+ e = BMIter_Step(&iter)) {
+ f = NULL;
+ len = bmesh_cycle_length(&(e->loop->radial));
+ if(len == 2){
+ f = BM_Join_Faces(bm,e->loop->f,((BMLoop*)
+ (e->loop->radial.next->data))->f,
+ e);
+ }
+ if(f){
+ done = 0;
+ break;
+ }
+ };
+ }
+ BM_Collapse_Vert(bm, v->edge, v, 1.0);
+ }
+}
+#endif
+
+/**
+ * bmesh_join_faces
+ *
+ * joins two adjacenct faces togather.
+ *
+ * Returns -
+ * BMFace pointer
+ */
+
+BMFace *BM_Join_Faces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) {
+
+ BMLoop *l1, *l2;
+ BMEdge *jed=NULL;
+
+ jed = e;
+ if(!jed){
+ /*search for an edge that has both these faces in its radial cycle*/
+ l1 = f1->loopbase;
+ do{
+ if( ((BMLoop*)l1->radial.next->data)->f == f2 ){
+ jed = l1->e;
+ break;
+ }
+ l1 = ((BMLoop*)(l1->head.next));
+ }while(l1!=f1->loopbase);
+ }
+
+ l1 = jed->loop;
+ l2 = l1->radial.next->data;
+ if (l1->v == l2->v) {
+ bmesh_loop_reverse(bm, f2);
+ }
+
+ f1 = bmesh_jfke(bm, f1, f2, jed);
+
+ return f1;
+}
+
+/*connects two verts together, automatically (if very naively) finding the
+ face they both share (if there is one) and splittling it. use this at your
+ own risk, as it doesn't handle the many complex cases it should (like zero-area faces,
+ multiple faces, etc).
+
+ this is really only meant for cases where you don't know before hand the face
+ the two verts belong to for splitting (e.g. the subdivision operator).
+*/
+
+BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
+ BMIter iter, iter2;
+ BMVert *v;
+ BMLoop *nl;
+ BMFace *face;
+
+ /*this isn't the best thing in the world. it doesn't handle cases where there's
+ multiple faces yet. that might require a convexity test to figure out which
+ face is "best," and who knows what for non-manifold conditions.*/
+ for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
+ for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
+ if (v == v2) {
+ face = BM_Split_Face(bm, face, v1, v2, &nl, NULL);
+
+ if (nf) *nf = face;
+ return nl->e;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * BM_split_face
+ *
+ * Splits a single face into two.
+ *
+ * Returns -
+ * BMFace pointer
+ */
+
+BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *example)
+{
+ BMFace *nf;
+ nf = bmesh_sfme(bm,f,v1,v2,nl);
+
+ if (nf) {
+ BM_Copy_Attributes(bm, bm, f, nf);
+ VECCOPY(nf->no, f->no);
+ }
+
+ return nf;
+}
+
+/**
+ * bmesh_collapse_vert
+ *
+ * Collapses a vertex that has only two manifold edges
+ * onto a vertex it shares an edge with. Fac defines
+ * the amount of interpolation for Custom Data.
+ *
+ * Note that this is not a general edge collapse function. For
+ * that see BM_manifold_edge_collapse
+ *
+ * TODO:
+ * Insert error checking for KV valance.
+ *
+ * Returns -
+ * Nothing
+ */
+
+void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
+ void *src[2];
+ float w[2];
+ BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
+ BMVert *tv = bmesh_edge_getothervert(ke,kv);
+
+ w[0] = 1.0f - fac;
+ w[1] = fac;
+
+ if(ke->loop){
+ l = ke->loop;
+ do{
+ if(l->v == tv && ((BMLoop*)(l->head.next))->v == kv){
+ tvloop = l;
+ kvloop = ((BMLoop*)(l->head.next));
+
+ src[0] = kvloop->head.data;
+ src[1] = tvloop->head.data;
+ CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->head.data);
+ }
+ l=l->radial.next->data;
+ }while(l!=ke->loop);
+ }
+ BM_Data_Interp_From_Verts(bm, kv, tv, kv, fac);
+ bmesh_jekv(bm,ke,kv);
+}
+
+/**
+ * BM_split_edge
+ *
+ * Splits an edge. v should be one of the vertices in e and
+ * defines the direction of the splitting operation for interpolation
+ * purposes.
+ *
+ * Returns -
+ * the new vert
+ */
+
+BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent) {
+ BMVert *nv, *v2;
+
+ v2 = bmesh_edge_getothervert(e,v);
+ nv = bmesh_semv(bm,v,e,ne);
+ if (nv == NULL) return NULL;
+ VECSUB(nv->co,v2->co,v->co);
+ VECADDFAC(nv->co,v->co,nv->co,percent);
+ if (ne) {
+ if(bmesh_test_sysflag(&(e->head), BM_SELECT)) {
+ bmesh_set_sysflag((BMHeader*)*ne, BM_SELECT);
+ bmesh_set_sysflag((BMHeader*)nv, BM_SELECT);
+ }
+ if(bmesh_test_sysflag(&(e->head), BM_HIDDEN)) {
+ bmesh_set_sysflag((BMHeader*)*ne, BM_HIDDEN);
+ bmesh_set_sysflag((BMHeader*)nv, BM_HIDDEN);
+ }
+ }
+ /*v->nv->v2*/
+ BM_Data_Facevert_Edgeinterp(bm,v2, v, nv, e, percent);
+ BM_Data_Interp_From_Verts(bm, v2, v, nv, percent);
+ return nv;
+}
+
+BMVert *BM_Split_Edge_Multi(BMesh *bm, BMEdge *e, int numcuts)
+{
+ int i;
+ float percent;
+ BMVert *nv = NULL;
+
+ for(i=0; i < numcuts; i++){
+ percent = 1.0f / (float)(numcuts + 1 - i);
+ nv = BM_Split_Edge(bm, e->v2, e, NULL, percent);
+ }
+ return nv;
+}
+
+int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err)
+{
+ BMIter iter;
+ V_DECLARE(verts);
+ BMVert **verts = NULL;
+ BMLoop *l;
+ int ret = 1, i, j;
+
+ if (face->len == 2) {
+ fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
+ fflush(err);
+ }
+
+ for (l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, face);l;l=BMIter_Step(&iter)) {
+ V_GROW(verts);
+ verts[V_COUNT(verts)-1] = l->v;
+
+ if (l->e->v1 == l->e->v2) {
+ fprintf(err, "Found bmesh edge with identical verts!\n");
+ fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1);
+ fflush(err);
+ ret = 0;
+ }
+ }
+
+ for (i=0; i<V_COUNT(verts); i++) {
+ for (j=0; j<V_COUNT(verts); j++) {
+ if (j == i) continue;
+ if (verts[i] == verts[j]) {
+ fprintf(err, "Found duplicate verts in bmesh face!\n");
+ fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]);
+ fflush(err);
+ ret = 0;
+ }
+ }
+ }
+
+ V_FREE(verts);
+ return ret;
+}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
new file mode 100644
index 00000000000..07f1144b37e
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -0,0 +1,324 @@
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <stdio.h>
+
+/*do not rename any operator or slot names! otherwise you must go
+ through the code and find all references to them!*/
+
+BMOpDefine def_finddoubles = {
+ "finddoubles",
+ /*maps welded vertices to verts they should weld to.*/
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ //list of verts to keep
+ {BMOP_OPSLOT_ELEMENT_BUF, "keepverts"},
+ {BMOP_OPSLOT_FLT, "dist"},
+ {BMOP_OPSLOT_MAPPING, "targetmapout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_finddoubles_exec,
+ 0,
+};
+
+BMOpDefine def_removedoubles = {
+ "removedoubles",
+ /*maps welded vertices to verts they should weld to.*/
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {BMOP_OPSLOT_FLT, "dist"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_removedoubles_exec,
+ 0,
+};
+
+BMOpDefine def_weldverts = {
+ "weldverts",
+ /*maps welded vertices to verts they should weld to.*/
+ {{BMOP_OPSLOT_MAPPING, "targetmap"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_weldverts_exec,
+ 0,
+};
+
+BMOpDefine def_makevert = {
+ "makevert",
+ {{BMOP_OPSLOT_VEC, "co"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "newvertout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_makevert_exec,
+ 0,
+};
+
+/*contextual_create is fkey, it creates
+ new faces, makes stuff from edge nets,
+ makes wire edges, etc. it also dissolves
+ faces.*/
+BMOpDefine def_contextual_create= {
+ "contextual_create",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_contextual_create_exec,
+ 0,
+};
+
+BMOpDefine def_edgenet_fill= {
+ "edgenet_fill",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_edgenet_fill_exec,
+ 0,
+};
+
+BMOpDefine def_rotate = {
+ "rotate",
+ {{BMOP_OPSLOT_VEC, "cent"},
+ {BMOP_OPSLOT_MAT, "mat"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_rotate_exec,
+ 0,
+};
+
+BMOpDefine def_translate= {
+ "translate",
+ {{BMOP_OPSLOT_VEC, "vec"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_translate_exec,
+ 0,
+};
+
+
+/*applies a transform to vertices*/
+BMOpDefine def_transform = {
+ "transform",
+ {{BMOP_OPSLOT_MAT, "mat"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_transform_exec,
+ 0,
+};
+
+/*loads a bmesh into an object*/
+BMOpDefine def_object_load_bmesh = {
+ "object_load_bmesh",
+ {{BMOP_OPSLOT_PNT, "scene"},
+ {BMOP_OPSLOT_PNT, "object"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_to_mesh_exec,
+ 0,
+};
+
+
+BMOpDefine def_mesh_to_bmesh = {
+ "mesh_to_bmesh",
+ {{BMOP_OPSLOT_PNT, "mesh"},
+ {0, /*null-terminating sentinel*/}},
+ mesh_to_bmesh_exec,
+ 0
+};
+
+BMOpDefine def_extrudeverts_indiv = {
+ "extrude_vert_indiv",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"},
+ {0} /*null-terminating sentinel*/},
+ extrude_vert_indiv_exec,
+ 0
+};
+
+#if 0
+BMOpDefine def_makeprim = {
+ "makeprim",
+ {{BMOP_OPSLOT_INT, "type"},
+ {BMOP_OPSLOT_INT, "tot", /*rows/cols also applies to spheres*/
+ {BMOP_OPSLOT_INT, "seg",
+ {BMOP_OPSLOT_INT, "subdiv"},
+ {BMOP_OPSLOT_INT, "ext"},
+ {BMOP_OPSLOT_INT, "fill"},
+ {BMOP_OPSLOT_FLT, "dia"},
+ {BMOP_OPSLOT_FLT, "depth"},
+ {BMOP_OPSLOT_PNT, "mat"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //won't be implemented right away
+ {0}}
+ makeprim_exec,
+ 0
+};
+#endif
+
+BMOpDefine def_connectverts = {
+ "connectverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
+ {0} /*null-terminating sentinel*/},
+ connectverts_exec,
+ 0
+};
+
+BMOpDefine def_extrudefaceregion = {
+ "extrudefaceregion",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edgefacein"},
+ {BMOP_OPSLOT_MAPPING, "exclude"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+ {0} /*null-terminating sentinel*/},
+ extrude_edge_context_exec,
+ 0
+};
+
+BMOpDefine def_makefgonsop = {
+ "makefgon",
+ {{BMOP_OPSLOT_INT, "trifan"}, /*use triangle fans instead of
+ real interpolation*/
+ {0} /*null-terminating sentinel*/},
+ bmesh_make_fgons_exec,
+ 0
+};
+
+BMOpDefine def_dissolvevertsop = {
+ "dissolveverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {0} /*null-terminating sentinel*/},
+ dissolveverts_exec,
+ 0
+};
+
+BMOpDefine def_dissolveedgessop = {
+ "dissolveedges",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolveedges_exec,
+ 0
+};
+
+BMOpDefine def_dissolveedgeloopsop = {
+ "dissolveedgeloop",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolve_edgeloop_exec,
+ 0
+};
+
+BMOpDefine def_dissolvefacesop = {
+ "dissolvefaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolvefaces_exec,
+ 0
+};
+
+
+BMOpDefine def_triangop = {
+ "triangulate",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
+ {BMOP_OPSLOT_MAPPING, "facemap"},
+ {0} /*null-terminating sentinel*/},
+ triangulate_exec,
+ 0
+};
+
+BMOpDefine def_subdop = {
+ "esubd",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_INT, "numcuts"},
+ {BMOP_OPSLOT_FLT, "smooth"},
+ {BMOP_OPSLOT_FLT, "fractal"},
+ {BMOP_OPSLOT_INT, "beauty"},
+ {BMOP_OPSLOT_MAPPING, "custompatterns"},
+ {BMOP_OPSLOT_MAPPING, "edgepercents"},
+
+ /*these next two can have multiple types of elements in them.*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "outinner"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"},
+ {0} /*null-terminating sentinel*/,
+ },
+ esubdivide_exec,
+ 0
+};
+
+BMOpDefine def_edit2bmesh = {
+ "editmesh_to_bmesh",
+ {{BMOP_OPSLOT_PNT, "em"}, {BMOP_OPSLOT_MAPPING, "map"},
+ {0} /*null-terminating sentinel*/},
+ edit2bmesh_exec,
+ 0
+};
+
+BMOpDefine def_bmesh2edit = {
+ "bmesh_to_editmesh",
+ {{BMOP_OPSLOT_PNT, "emout"},
+ {0} /*null-terminating sentinel*/},
+ bmesh2edit_exec,
+ 0
+};
+
+BMOpDefine def_delop = {
+ "del",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, {BMOP_OPSLOT_INT, "context"},
+ {0} /*null-terminating sentinel*/},
+ delop_exec,
+ 0
+};
+
+BMOpDefine def_dupeop = {
+ "dupe",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "origout"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "newout"},
+ /*facemap maps from source faces to dupe
+ faces, and from dupe faces to source faces.*/
+ {BMOP_OPSLOT_MAPPING, "facemap"},
+ {BMOP_OPSLOT_MAPPING, "boundarymap"},
+ {BMOP_OPSLOT_MAPPING, "isovertmap"},
+ {0} /*null-terminating sentinel*/},
+ dupeop_exec,
+ 0
+};
+
+BMOpDefine def_splitop = {
+ "split",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+ {BMOP_OPSLOT_MAPPING, "boundarymap"},
+ {BMOP_OPSLOT_MAPPING, "isovertmap"},
+ {0} /*null-terminating sentinel*/},
+ splitop_exec,
+ 0
+};
+
+BMOpDefine *opdefines[] = {
+ &def_splitop,
+ &def_dupeop,
+ &def_delop,
+ &def_edit2bmesh,
+ &def_bmesh2edit,
+ &def_subdop,
+ &def_triangop,
+ &def_dissolvefacesop,
+ &def_dissolveedgessop,
+ &def_dissolveedgeloopsop,
+ &def_dissolvevertsop,
+ &def_makefgonsop,
+ &def_extrudefaceregion,
+ &def_connectverts,
+ //&def_makeprim,
+ &def_extrudeverts_indiv,
+ &def_mesh_to_bmesh,
+ &def_object_load_bmesh,
+ &def_transform,
+ &def_translate,
+ &def_rotate,
+ &def_edgenet_fill,
+ &def_contextual_create,
+ &def_makevert,
+ &def_weldverts,
+ &def_removedoubles,
+ &def_finddoubles,
+};
+
+int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
new file mode 100644
index 00000000000..d168d85b025
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -0,0 +1,1305 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "stdarg.h"
+
+#include <string.h>
+
+/*forward declarations*/
+static void alloc_flag_layer(BMesh *bm);
+static void free_flag_layer(BMesh *bm);
+static void clear_flag_layer(BMesh *bm);
+static int bmesh_name_to_slotcode(BMOpDefine *def, char *name);
+static int bmesh_opname_to_opcode(char *opname);
+
+typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
+
+/*mappings map elements to data, which
+ follows the mapping struct in memory.*/
+typedef struct element_mapping {
+ BMHeader *element;
+ int len;
+} element_mapping;
+
+
+/*operator slot type information - size of one element of the type given.*/
+const int BMOP_OPSLOT_TYPEINFO[] = {
+ 0,
+ sizeof(int),
+ sizeof(float),
+ sizeof(void*),
+ 0, /* unused */
+ 0, /* unused */
+ 0, /* unused */
+ sizeof(void*), /* pointer buffer */
+ sizeof(element_mapping)
+};
+
+/*
+ * BMESH OPSTACK PUSH
+ *
+ * Pushes the opstack down one level
+ * and allocates a new flag layer if
+ * appropriate.
+ *
+*/
+
+void BMO_push(BMesh *bm, BMOperator *op)
+{
+ bm->stackdepth++;
+
+ /*add flag layer, if appropriate*/
+ if (bm->stackdepth > 1)
+ alloc_flag_layer(bm);
+ else
+ clear_flag_layer(bm);
+}
+
+/*
+ * BMESH OPSTACK POP
+ *
+ * Pops the opstack one level
+ * and frees a flag layer if appropriate
+ * TODO: investigate NOT freeing flag
+ * layers.
+ *
+*/
+void BMO_pop(BMesh *bm)
+{
+ if(bm->stackdepth > 1)
+ free_flag_layer(bm);
+
+ bm->stackdepth--;
+}
+
+/*
+ * BMESH OPSTACK INIT OP
+ *
+ * Initializes an operator structure
+ * to a certain type
+ *
+*/
+
+void BMO_Init_Op(BMOperator *op, char *opname)
+{
+ int i, opcode = bmesh_opname_to_opcode(opname);
+
+ memset(op, 0, sizeof(BMOperator));
+ op->type = opcode;
+
+ /*initialize the operator slot types*/
+ for(i = 0; opdefines[opcode]->slottypes[i].type; i++) {
+ op->slots[i].slottype = opdefines[opcode]->slottypes[i].type;
+ op->slots[i].index = i;
+ }
+
+ /*callback*/
+ op->exec = opdefines[opcode]->exec;
+
+ /*memarena, used for operator's slot buffers*/
+ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ BLI_memarena_use_calloc (op->arena);
+}
+
+/*
+ * BMESH OPSTACK EXEC OP
+ *
+ * Executes a passed in operator. This handles
+ * the allocation and freeing of temporary flag
+ * layers and starting/stopping the modelling
+ * loop. Can be called from other operators
+ * exec callbacks as well.
+ *
+*/
+
+void BMO_Exec_Op(BMesh *bm, BMOperator *op)
+{
+
+ BMO_push(bm, op);
+
+ if(bm->stackdepth == 1)
+ bmesh_begin_edit(bm);
+ op->exec(bm, op);
+
+ if(bm->stackdepth == 1)
+ bmesh_end_edit(bm,0);
+
+ BMO_pop(bm);
+}
+
+/*
+ * BMESH OPSTACK FINISH OP
+ *
+ * Does housekeeping chores related to finishing
+ * up an operator.
+ *
+*/
+
+void BMO_Finish_Op(BMesh *bm, BMOperator *op)
+{
+ BMOpSlot *slot;
+ int i;
+
+ for (i=0; opdefines[op->type]->slottypes[i].type; i++) {
+ slot = &op->slots[i];
+ if (slot->slottype == BMOP_OPSLOT_MAPPING) {
+ if (slot->data.ghash)
+ BLI_ghash_free(slot->data.ghash, NULL, NULL);
+ }
+ }
+
+ BLI_memarena_free(op->arena);
+}
+
+/*
+ * BMESH OPSTACK GET SLOT
+ *
+ * Returns a pointer to the slot of
+ * type 'slotcode'
+ *
+*/
+
+BMOpSlot *BMO_GetSlot(BMOperator *op, char *slotname)
+{
+ int slotcode = bmesh_name_to_slotcode(opdefines[op->type], slotname);
+
+ return &(op->slots[slotcode]);
+}
+
+/*
+ * BMESH OPSTACK COPY SLOT
+ *
+ * Copies data from one slot to another
+ *
+*/
+
+void BMO_CopySlot(BMOperator *source_op, BMOperator *dest_op, char *src, char *dst)
+{
+ BMOpSlot *source_slot = BMO_GetSlot(source_op, src);
+ BMOpSlot *dest_slot = BMO_GetSlot(dest_op, dst);
+
+ if(source_slot == dest_slot)
+ return;
+
+ if(source_slot->slottype != dest_slot->slottype)
+ return;
+
+ if (dest_slot->slottype > BMOP_OPSLOT_VEC) {
+ if (dest_slot->slottype != BMOP_OPSLOT_MAPPING) {
+ /*do buffer copy*/
+ dest_slot->data.buf = NULL;
+ dest_slot->len = source_slot->len;
+ if(dest_slot->len){
+ dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
+ memcpy(dest_slot->data.buf, source_slot->data.buf, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
+ }
+ } else {
+ GHashIterator it;
+ element_mapping *srcmap, *dstmap;
+
+ /*sanity check*/
+ if (!source_slot->data.ghash) return;
+
+ if (!dest_slot->data.ghash) {
+ dest_slot->data.ghash =
+ BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp);
+ }
+
+ BLI_ghashIterator_init(&it, source_slot->data.ghash);
+ for (;srcmap=BLI_ghashIterator_getValue(&it);
+ BLI_ghashIterator_step(&it))
+ {
+ dstmap = BLI_memarena_alloc(dest_op->arena,
+ sizeof(*dstmap) + srcmap->len);
+
+ dstmap->element = srcmap->element;
+ dstmap->len = srcmap->len;
+ memcpy(dstmap+1, srcmap+1, srcmap->len);
+
+ BLI_ghash_insert(dest_slot->data.ghash,
+ dstmap->element, dstmap);
+ }
+ }
+ } else {
+ dest_slot->data = source_slot->data;
+ }
+}
+
+/*
+ * BMESH OPSTACK SET XXX
+ *
+ * Sets the value of a slot depending on it's type
+ *
+*/
+
+
+void BMO_Set_Float(BMOperator *op, char *slotname, float f)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_FLT) )
+ return;
+
+ slot->data.f = f;
+}
+
+void BMO_Set_Int(BMOperator *op, char *slotname, int i)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_INT) )
+ return;
+
+ slot->data.i = i;
+}
+
+/*only supports square mats*/
+void BMO_Set_Mat(struct BMOperator *op, char *slotname, float *mat, int size)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ slot->len = 4;
+ slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float)*4*4);
+
+ if (size == 4) {
+ memcpy(slot->data.p, mat, sizeof(float)*4*4);
+ } else if (size == 3) {
+ Mat4CpyMat3(slot->data.p, mat);
+ } else {
+ printf("yeek! invalid size in BMO_Set_Mat!\n");
+
+ memset(slot->data.p, 0, sizeof(float)*4*4);
+ return;
+ }
+}
+
+void BMO_Get_Mat4(struct BMOperator *op, char *slotname, float mat[4][4])
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ memcpy(mat, slot->data.p, sizeof(float)*4*4);
+}
+
+void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3])
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ Mat3CpyMat4(mat, slot->data.p);
+}
+
+void BMO_Set_Pnt(BMOperator *op, char *slotname, void *p)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_PNT) )
+ return;
+
+ slot->data.p = p;
+}
+
+void BMO_Set_Vec(BMOperator *op, char *slotname, float *vec)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_VEC) )
+ return;
+
+ VECCOPY(slot->data.vec, vec);
+}
+
+
+float BMO_Get_Float(BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_FLT) )
+ return 0.0f;
+
+ return slot->data.f;
+}
+
+int BMO_Get_Int(BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_INT) )
+ return 0;
+
+ return slot->data.i;
+}
+
+
+void *BMO_Get_Pnt(BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_PNT) )
+ return NULL;
+
+ return slot->data.p;
+}
+
+void BMO_Get_Vec(BMOperator *op, char *slotname, float *vec_out)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_VEC) )
+ return;
+
+ VECCOPY(vec_out, slot->data.vec);
+}
+
+/*
+ * BMO_SETFLAG
+ *
+ * Sets a flag for a certain element
+ *
+*/
+void BMO_SetFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ head->flags[bm->stackdepth-1].mask |= flag;
+}
+
+/*
+ * BMO_CLEARFLAG
+ *
+ * Clears a specific flag from a given element
+ *
+*/
+
+void BMO_ClearFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ head->flags[bm->stackdepth-1].mask &= ~flag;
+}
+
+/*
+ * BMO_TESTFLAG
+ *
+ * Tests whether or not a flag is set for a specific element
+ *
+ *
+*/
+
+int BMO_TestFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ if(head->flags[bm->stackdepth-1].mask & flag)
+ return 1;
+ return 0;
+}
+
+/*
+ * BMO_COUNTFLAG
+ *
+ * Counts the number of elements of a certain type that
+ * have a specific flag set.
+ *
+*/
+
+int BMO_CountFlag(BMesh *bm, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ int count = 0;
+
+ if(type & BM_VERT){
+ for(e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+ if(type & BM_EDGE){
+ for(e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+ if(type & BM_FACE){
+ for(e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+
+ return count;
+}
+
+int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+ return 0;
+
+ return slot->len;
+}
+
+#if 0
+void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd) {
+ BMOpSlot *slot = &op->slots[slotcode];
+ void *tmp;
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+ return NULL;
+
+ if (slot->flag & BMOS_DYNAMIC_ARRAY) {
+ if (slot->len >= slot->size) {
+ slot->size = (slot->size+1+totadd)*2;
+
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size);
+ MEM_freeN(tmp);
+ }
+
+ slot->len += totadd;
+ } else {
+ slot->flag |= BMOS_DYNAMIC_ARRAY;
+ slot->len += totadd;
+ slot->size = slot->len+2;
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len);
+ }
+
+ return slot->data.buf;
+}
+#endif
+
+void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, void *data, int len) {
+ element_mapping *mapping;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+
+ mapping = BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
+
+ mapping->element = element;
+ mapping->len = len;
+ memcpy(mapping+1, data, len);
+
+ if (!slot->data.ghash) {
+ slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp);
+ }
+
+ BLI_ghash_insert(slot->data.ghash, element, mapping);
+}
+
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
+ char *slotname, int flag)
+{
+ GHashIterator it;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader *ele;
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+ if (!slot->data.ghash) return;
+
+ BLI_ghashIterator_init(&it, slot->data.ghash);
+ for (;ele=BLI_ghashIterator_getKey(&it);BLI_ghashIterator_step(&it)) {
+ BMO_SetFlag(bm, ele, flag);
+ }
+}
+
+void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, float val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
+}
+
+void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, void *val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
+}
+
+int BMO_InMap(BMesh *bm, BMOperator *op, char *slotname, void *element)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
+ if (!slot->data.ghash) return 0;
+
+ return BLI_ghash_haskey(slot->data.ghash, element);
+}
+
+void *BMO_Get_MapData(BMesh *bm, BMOperator *op, char *slotname,
+ void *element)
+{
+ element_mapping *mapping;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
+ if (!slot->data.ghash) return NULL;
+
+ mapping = BLI_ghash_lookup(slot->data.ghash, element);
+
+ if (!mapping) return NULL;
+
+ return mapping + 1;
+}
+
+float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
+ void *element)
+{
+ float *val = BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return 0.0f;
+}
+
+void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ void *element)
+{
+ void **val = BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return NULL;
+}
+
+static void *alloc_slot_buffer(BMOperator *op, char *slotname, int len){
+ int slotcode = bmesh_name_to_slotcode(opdefines[op->type], slotname);
+
+ /*check if its actually a buffer*/
+ if( !(op->slots[slotcode].slottype > BMOP_OPSLOT_VEC) )
+ return NULL;
+
+ op->slots[slotcode].len = len;
+ if(len)
+ op->slots[slotcode].data.buf = BLI_memarena_alloc(op->arena, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * len);
+ return op->slots[slotcode].data.buf;
+}
+
+
+/*
+ *
+ * BMO_ALL_TO_SLOT
+ *
+ * Copies all elements of a certain type into an operator slot.
+ *
+*/
+
+void BMO_All_To_Slot(BMesh *bm, BMOperator *op, char *slotname, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement=0, i=0;
+
+ if (type & BM_VERT) totelement += bm->totvert;
+ if (type & BM_EDGE) totelement += bm->totedge;
+ if (type & BM_FACE) totelement += bm->totface;
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+}
+
+/*
+ *
+ * BMO_HEADERFLAG_TO_SLOT
+ *
+ * Copies elements of a certain type, which have a certain header flag set
+ * into a slot for an operator.
+ *
+*/
+
+void BMO_HeaderFlag_To_Slot(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement=0, i=0;
+
+ totelement = BM_CountFlag(bm, type, flag);
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(e->flag & flag) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(e->flag & flag){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(e->flag & flag){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_TO_SLOT
+ *
+ * Copies elements of a certain type, which have a certain flag set
+ * into an output slot for an operator.
+ *
+*/
+void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement = BMO_CountFlag(bm, flag, type), i=0;
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Header Flags elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ *
+*/
+
+void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ BM_SetHFlag(data[i], flag);
+ if (flag & BM_SELECT)
+ BM_Select(bm, data[i], 1);
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ *
+*/
+
+void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ BM_ClearHFlag(data[i], flag);
+ if (flag & BM_SELECT)
+ BM_Select(bm, data[i], 0);
+ }
+}
+
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Flags elements in a slots buffer
+ *
+*/
+
+void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++)
+ BMO_SetFlag(bm, data[i], flag);
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer
+ *
+*/
+
+void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++)
+ BMO_ClearFlag(bm, data[i], flag);
+}
+
+
+/*
+ *
+ * ALLOC/FREE FLAG LAYER
+ *
+ * Used by operator stack to free/allocate
+ * private flag data. This is allocated
+ * using a mempool so the allocation/frees
+ * should be quite fast.
+ *
+ * TODO:
+ * Investigate not freeing flag layers until
+ * all operators have been executed. This would
+ * save a lot of realloc potentially.
+ *
+*/
+
+static void alloc_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BLI_mempool *oldpool = bm->flagpool; /*old flag pool*/
+ void *oldflags;
+
+ /*allocate new flag pool*/
+ bm->flagpool = BLI_mempool_create(sizeof(BMFlagLayer)*(bm->totflags+1), 512, 512 );
+
+ /*now go through and memcpy all the flags. Loops don't get a flag layer at this time...*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ oldflags = v->head.flags;
+ v->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags); /*dont know if this memcpy usage is correct*/
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ oldflags = e->head.flags;
+ e->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ oldflags = f->head.flags;
+ f->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+ bm->totflags++;
+ BLI_mempool_destroy(oldpool);
+}
+
+static void free_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BLI_mempool *oldpool = bm->flagpool;
+ void *oldflags;
+
+ /*de-increment the totflags first...*/
+ bm->totflags--;
+ /*allocate new flag pool*/
+ bm->flagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512);
+
+ /*now go through and memcpy all the flags*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ oldflags = v->head.flags;
+ v->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags); /*correct?*/
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ oldflags = e->head.flags;
+ e->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ oldflags = f->head.flags;
+ f->head.flags = BLI_mempool_calloc(bm->flagpool);
+ memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+
+ BLI_mempool_destroy(oldpool);
+}
+
+static void clear_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ /*now go through and memcpy all the flags*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ memset(v->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ memset(e->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ memset(f->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
+ }
+}
+
+void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op,
+ char *slotname, int restrict)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ memset(iter, 0, sizeof(BMOIter));
+
+ iter->slot = slot;
+ iter->cur = 0;
+ iter->restrict = restrict;
+
+ if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
+ if (iter->slot->data.ghash)
+ BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
+ else return NULL;
+ }
+
+ return BMO_IterStep(iter);
+}
+
+void *BMO_IterStep(BMOIter *iter)
+{
+ if (iter->slot->slottype == BMOP_OPSLOT_ELEMENT_BUF) {
+ BMHeader *h;
+
+ if (iter->cur >= iter->slot->len) return NULL;
+
+ h = ((void**)iter->slot->data.buf)[iter->cur++];
+ while (!(iter->restrict & h->type)) {
+ if (iter->cur >= iter->slot->len) return NULL;
+ h = ((void**)iter->slot->data.buf)[iter->cur++];
+ }
+
+ return h;
+ } else if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
+ struct element_mapping *map;
+ void *ret = BLI_ghashIterator_getKey(&iter->giter);
+ map = BLI_ghashIterator_getValue(&iter->giter);
+
+ iter->val = map + 1;
+
+ BLI_ghashIterator_step(&iter->giter);
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+/*used for iterating over mappings*/
+void *BMO_IterMapVal(BMOIter *iter)
+{
+ return iter->val;
+}
+
+void *BMO_IterMapValp(BMOIter *iter)
+{
+ return *((void**)iter->val);
+}
+
+float BMO_IterMapValf(BMOIter *iter)
+{
+ return *((float*)iter->val);
+}
+
+/*error system*/
+typedef struct bmop_error {
+ struct bmop_error *next, *prev;
+ int errorcode;
+ BMOperator *op;
+ char *msg;
+} bmop_error;
+
+void BMO_ClearStack(BMesh *bm)
+{
+ while (BMO_PopError(bm, NULL, NULL));
+}
+
+void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg)
+{
+ bmop_error *err = MEM_callocN(sizeof(bmop_error), "bmop_error");
+
+ err->errorcode = errcode;
+ if (!msg) msg = bmop_error_messages[errcode];
+ err->msg = msg;
+ err->op = owner;
+
+ BLI_addhead(&bm->errorstack, err);
+}
+
+int BMO_HasError(BMesh *bm)
+{
+ return bm->errorstack.first != NULL;
+}
+
+/*returns error code or 0 if no error*/
+int BMO_GetError(BMesh *bm, char **msg, BMOperator **op)
+{
+ bmop_error *err = bm->errorstack.first;
+ if (!err) return 0;
+
+ if (msg) *msg = err->msg;
+ if (op) *op = err->op;
+
+ return err->errorcode;
+}
+
+int BMO_PopError(BMesh *bm, char **msg, BMOperator **op)
+{
+ int errorcode = BMO_GetError(bm, msg, op);
+
+ if (errorcode) {
+ bmop_error *err = bm->errorstack.first;
+
+ BLI_remlink(&bm->errorstack, bm->errorstack.first);
+ MEM_freeN(err);
+ }
+
+ return errorcode;
+}
+
+/*
+typedef struct bflag {
+ char *str;
+ int flag;
+} bflag;
+
+#define b(f) {#f, f},
+static char *bmesh_flags = {
+ b(BM_SELECT);
+ b(BM_SEAM);
+ b(BM_FGON);
+ b(BM_HIDDEN);
+ b(BM_SHARP);
+ b(BM_SMOOTH);
+ {NULL, 0};
+};
+
+int bmesh_str_to_flag(char *str)
+{
+ int i;
+
+ while (bmesh_flags[i]->name) {
+ if (!strcmp(bmesh_flags[i]->name, str))
+ return bmesh_flags[i]->flag;
+ }
+
+ return -1;
+}
+*/
+
+//example:
+//BMO_CallOp(bm, "del %d %hv", DEL_ONLYFACES, BM_SELECT);
+/*
+ d - int
+ i - int
+ f - float
+ hv - header flagged verts
+ he - header flagged edges
+ hf - header flagged faces
+ fv - flagged verts
+ fe - flagged edges
+ ff - flagged faces
+
+*/
+
+#define nextc(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
+
+static int bmesh_name_to_slotcode(BMOpDefine *def, char *name)
+{
+ int i;
+
+ for (i=0; def->slottypes[i].type; i++) {
+ if (!strcmp(name, def->slottypes[i].name)) return i;
+ }
+
+ printf("yeek! could not find bmesh slot for name %s!\n", name);
+ return 0;
+}
+
+static int bmesh_opname_to_opcode(char *opname) {
+ int i;
+
+ for (i=0; i<bmesh_total_ops; i++) {
+ if (!strcmp(opname, opdefines[i]->name)) break;
+ }
+
+ if (i == bmesh_total_ops) {
+ printf("yeek!! invalid op name %s!\n", opname);
+ return 0;
+ }
+
+ return i;
+}
+
+int BMO_VInitOpf(BMesh *bm, BMOperator *op, char *fmt, va_list vlist)
+{
+ BMOpDefine *def;
+ char *opname, *ofmt;
+ char slotname[64] = {0};
+ int i, n=strlen(fmt), stop, slotcode = -1, ret, type, state, c;
+ int noslot=0;
+
+ /*we muck around in here, so dup it*/
+ fmt = ofmt = strdup(fmt);
+
+ /*find operator name*/
+ i = strcspn(fmt, " \t");
+
+ opname = fmt;
+ if (!opname[i]) noslot = 1;
+ opname[i] = 0;
+
+ fmt += i + (noslot ? 0 : 1);
+
+ for (i=0; i<bmesh_total_ops; i++) {
+ if (!strcmp(opname, opdefines[i]->name)) break;
+ }
+
+ if (i == bmesh_total_ops) return 0;
+
+ BMO_Init_Op(op, opname);
+ def = opdefines[i];
+
+ i = 0;
+ state = 1; //0: not inside slotcode name, 1: inside slotcode name
+ c = 0;
+
+ while (*fmt) {
+ if (state) {
+ /*jump past leading whitespace*/
+ i = strspn(fmt, " \t");
+ fmt += i;
+
+ /*ignore trailing whitespace*/
+ if (!fmt[i])
+ break;
+
+ /*find end of slot name. currently this is
+ a little flexible, allowing "slot=%f",
+ "slot %f", "slot%f", and "slot\t%f". */
+ i = strcspn(fmt, "= \t%");
+ if (!fmt[i]) goto error;
+
+ fmt[i] = 0;
+
+ if (bmesh_name_to_slotcode(def, fmt) < 0) goto error;
+
+ strcpy(slotname, fmt);
+
+ state = 0;
+ fmt += i;
+ } else {
+ switch (*fmt) {
+ case ' ':
+ case '\t':
+ case '=':
+ case '%':
+ break;
+ case 'm': {
+ int size, c;
+
+ c = nextc(fmt);
+ fmt++;
+
+ if (c == '3') size = 3;
+ else if (c == '4') size = 4;
+ else goto error;
+
+ BMO_Set_Mat(op, slotname, va_arg(vlist, void*), size);
+ state = 1;
+ break;
+ }
+ case 'v': {
+ BMO_Set_Vec(op, slotname, va_arg(vlist, float*));
+ state = 1;
+ break;
+ }
+ case 's': {
+ BMOperator *op2 = va_arg(vlist, void*);
+ char *slotname2 = va_arg(vlist, char*);
+
+ BMO_CopySlot(op2, op, slotname2, slotname);
+ state = 1;
+ break;
+ }
+ case 'i':
+ case 'd':
+ BMO_Set_Int(op, slotname, va_arg(vlist, int));
+ state = 1;
+ break;
+ case 'p':
+ BMO_Set_Pnt(op, slotname, va_arg(vlist, void*));
+ state = 1;
+ break;
+ case 'f':
+ case 'h':
+ case 'a':
+ type = *fmt;
+
+ if (nextc(fmt) == ' ' || nextc(fmt) == '\t' ||
+ nextc(fmt)==0)
+ {
+ BMO_Set_Float(op,slotname,va_arg(vlist,double));
+ } else {
+ ret = 0;
+ stop = 0;
+ while (1) {
+ switch (nextc(fmt)) {
+ case 'f': ret |= BM_FACE;break;
+ case 'e': ret |= BM_EDGE;break;
+ case 'v': ret |= BM_VERT;break;
+ default:
+ stop = 1;
+ break;
+ }
+ if (stop) break;
+ fmt++;
+ }
+
+ if (type == 'h')
+ BMO_HeaderFlag_To_Slot(bm, op,
+ slotname, va_arg(vlist, int), ret);
+ else if (type == 'a')
+ BMO_All_To_Slot(bm, op, slotname, ret);
+ else
+ BMO_Flag_To_Slot(bm, op, slotname,
+ va_arg(vlist, int), ret);
+ }
+
+ state = 1;
+ break;
+ default:
+ printf("unrecognized bmop format char: %c\n", *fmt);
+ break;
+ }
+ }
+ fmt++;
+ }
+
+ free(ofmt);
+ return 1;
+error:
+ BMO_Finish_Op(bm, op);
+ free(fmt);
+ return 0;
+}
+
+
+int BMO_InitOpf(BMesh *bm, BMOperator *op, char *fmt, ...) {
+ va_list list;
+
+ va_start(list, fmt);
+ if (!BMO_VInitOpf(bm, op, fmt, list)) {
+ printf("BMO_InitOpf failed\n");
+ va_end(list);
+ return 0;
+ }
+ va_end(list);
+
+ return 1;
+}
+
+int BMO_CallOpf(BMesh *bm, char *fmt, ...) {
+ va_list list;
+ BMOperator op;
+
+ va_start(list, fmt);
+ if (!BMO_VInitOpf(bm, &op, fmt, list)) {
+ printf("BMO_CallOpf failed\n");
+ va_end(list);
+ return 0;
+ }
+
+ BMO_Exec_Op(bm, &op);
+ BMO_Finish_Op(bm, &op);
+
+ va_end(list);
+ return 1;
+}
+
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
new file mode 100644
index 00000000000..3eaaf4e8913
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -0,0 +1,38 @@
+#ifndef BM_OPERATORS_PRIVATE_H
+#define BM_OPERATORS_PRIVATE_H
+
+struct BMesh;
+struct BMOperator;
+
+void BMO_push(BMesh *bm, BMOperator *op);
+void BMO_pop(BMesh *bm);
+
+void splitop_exec(BMesh *bm, BMOperator *op);
+void dupeop_exec(BMesh *bm, BMOperator *op);
+void delop_exec(BMesh *bm, BMOperator *op);
+void esubdivide_exec(BMesh *bmesh, BMOperator *op);
+void edit2bmesh_exec(BMesh *bmesh, BMOperator *op);
+void bmesh2edit_exec(BMesh *bmesh, BMOperator *op);
+void triangulate_exec(BMesh *bmesh, BMOperator *op);
+void dissolvefaces_exec(BMesh *bmesh, BMOperator *op);
+void dissolveverts_exec(BMesh *bmesh, BMOperator *op);
+void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op);
+void extrude_edge_context_exec(BMesh *bm, BMOperator *op);
+void connectverts_exec(BMesh *bm, BMOperator *op);
+void makeprim_exec(BMesh *bm, BMOperator *op);
+void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op);
+void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_translate_exec(BMesh *bm, BMOperator *op);
+void bmesh_transform_exec(BMesh *bm, BMOperator *op);
+void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op);
+void bmesh_rotate_exec(BMesh *bm, BMOperator *op);
+void bmesh_makevert_exec(BMesh *bm, BMOperator *op);
+void dissolveedges_exec(BMesh *bm, BMOperator *op);
+void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op);
+void bmesh_weldverts_exec(BMesh *bm, BMOperator *op);
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op);
+void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op);
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
new file mode 100644
index 00000000000..c013952a622
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -0,0 +1,838 @@
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+/*
+ *
+ * BME POLYGON.C
+ *
+ * This file contains code for dealing
+ * with polygons (normal/area calculation,
+ * tesselation, ect)
+ *
+ * TODO:
+ * -Add in Tesselator frontend that creates
+ * BMTriangles from copied faces
+ * -Add in Function that checks for and flags
+ * degenerate faces.
+ *
+*/
+
+/*
+ * TEST EDGE SIDE and POINT IN TRIANGLE
+ *
+ * Point in triangle tests stolen from scanfill.c.
+ * Used for tesselator
+ *
+*/
+
+static short testedgeside(double *v1, double *v2, double *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ double inp;
+
+ //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+ inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[0]==v3[0] && v1[1]==v3[1]) return 0;
+ if(v2[0]==v3[0] && v2[1]==v3[1]) return 0;
+ }
+ return 1;
+}
+
+static short testedgesidef(float *v1, float *v2, float *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ double inp;
+
+ //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+ inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[0]==v3[0] && v1[1]==v3[1]) return 0;
+ if(v2[0]==v3[0] && v2[1]==v3[1]) return 0;
+ }
+ return 1;
+}
+
+static int point_in_triangle(double *v1, double *v2, double *v3, double *pt)
+{
+ if(testedgeside(v1,v2,pt) && testedgeside(v2,v3,pt) && testedgeside(v3,v1,pt))
+ return 1;
+ return 0;
+}
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+*/
+static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
+{
+
+ float *u, *v;/*, *w, v1[3], v2[3];*/
+ double n[3] = {0.0, 0.0, 0.0}, l;
+ int i;
+
+ /*this fixes some weird numerical error*/
+ verts[0][0] += 0.0001f;
+ verts[0][1] += 0.0001f;
+ verts[0][2] += 0.0001f;
+
+ for(i = 0; i < nverts; i++){
+ u = verts[i];
+ v = verts[(i+1) % nverts];
+
+ /* newell's method
+
+ so thats?:
+ (a[1] - b[1]) * (a[2] + b[2]);
+ a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2]
+
+ odd. half of that is the cross product. . .what's the
+ other half?
+
+ also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2])
+ */
+
+ n[0] += (u[1] - v[1]) * (u[2] + v[2]);
+ n[1] += (u[2] - v[2]) * (u[0] + v[0]);
+ n[2] += (u[0] - v[0]) * (u[1] + v[1]);
+ }
+
+ l = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ }
+
+ n[0] /= l;
+ n[1] /= l;
+ n[2] /= l;
+
+ normal[0] = (float) n[0];
+ normal[1] = (float) n[1];
+ normal[2] = (float) n[2];
+}
+
+/*
+ * COMPUTE POLY CENTER
+ *
+ * Computes the centroid and
+ * area of a polygon in the X/Y
+ * plane.
+ *
+*/
+
+static int compute_poly_center(float center[3], float *area, float (*verts)[3], int nverts)
+{
+ int i, j;
+ float atmp = 0.0, xtmp = 0.0, ytmp = 0.0, ai;
+
+ center[0] = center[1] = center[2] = 0.0;
+
+ if(nverts < 3)
+ return 0;
+
+ i = nverts-1;
+ j = 0;
+
+ while(j < nverts){
+ ai = verts[i][0] * verts[j][1] - verts[j][0] * verts[i][1];
+ atmp += ai;
+ xtmp += (verts[j][0] + verts[i][0]) * ai;
+ ytmp += (verts[j][1] + verts[i][1]) * ai;
+ i = j;
+ j += 1;
+ }
+
+ if(area)
+ *area = atmp / 2.0f;
+
+ if (atmp != 0){
+ center[0] = xtmp / (3.0f * atmp);
+ center[1] = xtmp / (3.0f * atmp);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+computes center of face in 3d. uses center of bounding box.
+*/
+
+int BM_Compute_Face_Center(BMesh *bm, BMFace *f, float center[3])
+{
+ BMIter iter;
+ BMLoop *l;
+ float min[3], max[3];
+ int i;
+
+ INIT_MINMAX(min, max);
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (i=0; l; l=BMIter_Step(&iter), i++) {
+ DO_MINMAX(l->v->co, min, max);
+ }
+
+ VECADD(center, min, max);
+ VECMUL(center, 0.5f);
+}
+
+/*
+ * COMPUTE POLY PLANE
+ *
+ * Projects a set polygon's vertices to
+ * a plane defined by the average
+ * of its edges cross products
+ *
+*/
+
+void compute_poly_plane(float (*verts)[3], int nverts)
+{
+
+ float avgc[3], norm[3], temp[3], mag, avgn[3];
+ float *v1, *v2, *v3;
+ int i;
+
+ if(nverts < 3)
+ return;
+
+ avgn[0] = avgn[1] = avgn[2] = 0.0;
+ avgc[0] = avgc[1] = avgc[2] = 0.0;
+
+ for(i = 0; i < nverts; i++){
+ v1 = verts[i];
+ v2 = verts[(i+1) % nverts];
+ v3 = verts[(i+2) % nverts];
+ CalcNormFloat(v1, v2, v3, norm);
+
+ avgn[0] += norm[0];
+ avgn[1] += norm[1];
+ avgn[2] += norm[2];
+ }
+
+ /*what was this bit for?*/
+ if(avgn[0] == 0.0 && avgn[1] == 0.0 && avgn[2] == 0.0){
+ avgn[0] = 0.0;
+ avgn[1] = 0.0;
+ avgn[2] = 1.0;
+ } else {
+ avgn[0] /= nverts;
+ avgn[1] /= nverts;
+ avgn[2] /= nverts;
+ Normalize(avgn);
+ }
+
+ for(i = 0; i < nverts; i++){
+ v1 = verts[i];
+ VECCOPY(temp, v1);
+ mag = 0.0;
+ mag += (temp[0] * avgn[0]);
+ mag += (temp[1] * avgn[1]);
+ mag += (temp[2] * avgn[2]);
+
+ temp[0] = (avgn[0] * mag);
+ temp[1] = (avgn[1] * mag);
+ temp[2] = (avgn[2] * mag);
+
+ VecSubf(v1, v1, temp);
+ }
+}
+
+/*
+ BM LEGAL EDGES
+
+ takes in a face and a list of edges, and sets to NULL any edge in
+ the list that bridges a concave region of the face or intersects
+ any of the faces's edges.
+*/
+static void shrink_edged(double *v1, double *v2, double fac)
+{
+ double mid[3];
+
+ VECADD(mid, v1, v2);
+ VECMUL(mid, 0.5);
+
+ VECSUB(v1, v1, mid);
+ VECSUB(v2, v2, mid);
+
+ VECMUL(v1, fac);
+ VECMUL(v2, fac);
+
+ VECADD(v1, v1, mid);
+ VECADD(v2, v2, mid);
+}
+
+static void shrink_edgef(float *v1, float *v2, float fac)
+{
+ float mid[3];
+
+ VECADD(mid, v1, v2);
+ VECMUL(mid, 0.5);
+
+ VECSUB(v1, v1, mid);
+ VECSUB(v2, v2, mid);
+
+ VECMUL(v1, fac);
+ VECMUL(v2, fac);
+
+ VECADD(v1, v1, mid);
+ VECADD(v2, v2, mid);
+}
+
+/*
+ * POLY ROTATE PLANE
+ *
+ * Rotates a polygon so that it's
+ * normal is pointing towards the mesh Z axis
+ *
+*/
+
+void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts)
+{
+
+ float up[3] = {0.0f,0.0f,1.0f}, axis[3], q[4];
+ float mat[3][3];
+ double angle;
+ int i;
+
+ Crossf(axis, up, normal);
+ axis[0] *= -1;
+ axis[1] *= -1;
+ axis[2] *= -1;
+
+ angle = saacos(normal[0]*up[0]+normal[1]*up[1] + normal[2]*up[2]);
+
+ if (angle == 0.0f) return;
+
+ AxisAngleToQuatd(q, axis, angle);
+ QuatToMat3(q, mat);
+
+ for(i = 0; i < nverts; i++)
+ Mat3MulVecfl(mat, verts[i]);
+}
+
+/*
+ * BMESH UPDATE FACE NORMAL
+ *
+ * Updates the stored normal for the
+ * given face. Requires that a buffer
+ * of sufficient length to store projected
+ * coordinates for all of the face's vertices
+ * is passed in as well.
+ *
+*/
+
+void BM_Face_UpdateNormal(BMesh *bm, BMFace *f)
+{
+ float projverts[12][3];
+ float (*proj)[3] = f->len < 12 ? projverts : MEM_mallocN(sizeof(float)*f->len*3, "projvertsn");
+ BMLoop *l = f->loopbase;
+ int i=0;
+
+ if (f->len < 3) return;
+
+ do {
+ VECCOPY(proj[i], l->v->co);
+ i += 1;
+ } while (l != f->loopbase);
+
+ bmesh_update_face_normal(bm, f, proj);
+
+ if (projverts != proj) MEM_freeN(proj);
+}
+
+void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMFace *f;
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_EDGE, e);
+ for (; f; f=BMIter_Step(&iter)) {
+ BM_Face_UpdateNormal(bm, f);
+ }
+
+ BM_Vert_UpdateNormal(bm, e->v1);
+ BM_Vert_UpdateNormal(bm, e->v2);
+}
+
+void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
+{
+ BMIter iter;
+ BMFace *f;
+ int len=0;
+
+ v->no[0] = v->no[1] = v->no[2] = 0.0f;
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&iter), len++) {
+ VecAddf(v->no, f->no, v->no);
+ }
+
+ if (!len) return;
+
+ VecMulf(v->no, 1.0f/(int)len);
+}
+
+void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])
+{
+ BMLoop *l;
+ int i;
+
+ if(f->len > 4){
+ i = 0;
+ l = f->loopbase;
+ do{
+ VECCOPY(projectverts[i], l->v->co);
+ l = (BMLoop*)(l->head.next);
+ i += 1;
+ }while(l!=f->loopbase);
+
+ compute_poly_plane(projectverts, f->len);
+ compute_poly_normal(f->no, projectverts, f->len);
+ }
+ else if(f->len == 3){
+ BMVert *v1, *v2, *v3;
+ v1 = f->loopbase->v;
+ v2 = ((BMLoop*)(f->loopbase->head.next))->v;
+ v3 = ((BMLoop*)(f->loopbase->head.next->next))->v;
+ CalcNormFloat(v1->co, v2->co, v3->co, f->no);
+ }
+ else if(f->len == 4){
+ BMVert *v1, *v2, *v3, *v4;
+ v1 = f->loopbase->v;
+ v2 = ((BMLoop*)(f->loopbase->head.next))->v;
+ v3 = ((BMLoop*)(f->loopbase->head.next->next))->v;
+ v4 = ((BMLoop*)(f->loopbase->head.prev))->v;
+ CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, f->no);
+ }
+ else{ /*horrible, two sided face!*/
+ f->no[0] = 0.0;
+ f->no[1] = 0.0;
+ f->no[2] = 1.0;
+ }
+
+}
+
+
+/*
+ * BMESH FLIP NORMAL
+ *
+ * Reverses the winding of a faces
+ * Note that this does *not* update the calculated
+ * Normal
+*/
+void BM_flip_normal(BMesh *bm, BMFace *f)
+{
+ bmesh_loop_reverse(bm, f);
+}
+
+/* detects if two line segments cross each other (intersects).
+ note, there could be more winding cases then there needs to be. */
+int linecrosses(double *v1, double *v2, double *v3, double *v4)
+{
+ int w1, w2, w3, w4, w5;
+
+ /*w1 = winding(v1, v3, v4);
+ w2 = winding(v2, v3, v4);
+ w3 = winding(v3, v1, v2);
+ w4 = winding(v4, v1, v2);
+
+ return (w1 == w2) && (w3 == w4);*/
+
+ w1 = testedgeside(v1, v3, v2);
+ w2 = testedgeside(v2, v4, v1);
+ w3 = !testedgeside(v1, v2, v3);
+ w4 = testedgeside(v3, v2, v4);
+ w5 = !testedgeside(v3, v1, v4);
+ return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
+}
+
+/* detects if two line segments cross each other (intersects).
+ note, there could be more winding cases then there needs to be. */
+int linecrossesf(float *v1, float *v2, float *v3, float *v4)
+{
+ int w1, w2, w3, w4, w5;
+
+/* int test1_a, test1_a, test2_a, test2_a;
+
+ test1_a = check_tri_clock_dir(l1p1, l1p2, l2p1);
+ test1_b = check_tri_clock_dir(l1p1, l1p2, l2p2);
+ if (test1_a != test1_b)
+ {
+ test2_a = check_tri_clock_dir(l2p1, l2p2, l1p1);
+ test2_b = check_tri_clock_dir(l2p1, l2p2, l1p2);
+ if (test2_a != test2_b)
+ {
+ return 1;
+ }
+ }*/
+ /*w1 = testedgesidef(v1, v2, v3);
+ w2 = testedgesidef(v1, v2, v4);
+ if(w1 != w2) {
+ w3 = testedgesidef(v3, v4, v1);
+ w4 = testedgesidef(v3, v4, v2);
+ if (w3 != w4) return 1;
+ }
+
+ return 0;*/
+
+ /*w1 = testedgesidef(v1, v3, v4);
+ w2 = testedgesidef(v2, v3, v4);
+ w3 = testedgesidef(v3, v1, v2);
+ w4 = testedgesidef(v4, v1, v2);
+
+ return (w1 == w2) && (w2 == w3) && (w3 == w4);*/
+
+ w1 = testedgesidef(v1, v3, v2);
+ w2 = testedgesidef(v2, v4, v1);
+ w3 = !testedgesidef(v1, v2, v3);
+ w4 = testedgesidef(v3, v2, v4);
+ w5 = !testedgesidef(v3, v1, v4);
+ return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
+}
+
+int goodline(float (*projectverts)[3], BMFace *f, int v1i,
+ int v2i, int v3i, int nvert) {
+ BMLoop *l = f->loopbase;
+ double v1[3], v2[3], v3[3], pv1[3], pv2[3];
+ int i;
+
+ VECCOPY(v1, projectverts[v1i]);
+ VECCOPY(v2, projectverts[v2i]);
+ VECCOPY(v3, projectverts[v3i]);
+
+ if (testedgeside(v1, v2, v3)) return 0;
+
+ //for (i=0; i<nvert; i++) {
+ do {
+ i = l->v->head.eflag2;
+ if (i == v1i || i == v2i || i == v3i) {
+ l = (BMLoop*)l->head.next;
+ continue;
+ }
+
+ VECCOPY(pv1, projectverts[l->v->head.eflag2]);
+ VECCOPY(pv2, projectverts[((BMLoop*)l->head.next)->v->head.eflag2]);
+
+ //if (linecrosses(pv1, pv2, v1, v3)) return 0;
+ if (point_in_triangle(v1, v2, v3, pv1)) return 0;
+ if (point_in_triangle(v3, v2, v1, pv1)) return 0;
+
+ l = (BMLoop*)l->head.next;
+ } while (l != f->loopbase);
+ return 1;
+}
+/*
+ * FIND EAR
+ *
+ * Used by tesselator to find
+ * the next triangle to 'clip off'
+ * of a polygon while tesselating.
+ *
+*/
+
+static BMLoop *find_ear(BMesh *bm, BMFace *f, float (*verts)[3],
+ int nvert)
+{
+ BMVert *v1, *v2, *v3;
+ BMLoop *bestear = NULL, *l;
+ float angle, bestangle = 180.0f;
+ int isear, i=0;
+
+ l = f->loopbase;
+ do {
+ isear = 1;
+
+ v1 = ((BMLoop*)(l->head.prev))->v;
+ v2 = l->v;
+ v3 = ((BMLoop*)(l->head.next))->v;
+
+ if (BM_Edge_Exist(v1, v3)) isear = 0;
+
+ if (isear && !goodline(verts, f, v1->head.eflag2, v2->head.eflag2,
+ v3->head.eflag2, nvert))
+ isear = 0;
+
+ if(isear) {
+ /*angle = VecAngle3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]);
+ if(!bestear || ABS(angle-45.0f) < bestangle) {
+ bestear = l;
+ bestangle = ABS(45.0f-angle);
+ }
+
+ if (angle > 20 && angle < 90) break;
+ if (angle < 100 && i > 5) break;
+ i += 1;*/
+ bestear = l;
+ break;
+ }
+ l = (BMLoop*)(l->head.next);
+ }
+ while(l != f->loopbase);
+
+ return bestear;
+}
+
+/*
+ * BMESH TRIANGULATE FACE
+ *
+ * Triangulates a face using a
+ * simple 'ear clipping' algorithm
+ * that tries to favor non-skinny
+ * triangles (angles less than
+ * 90 degrees). If the triangulator
+ * has bits left over (or cannot
+ * triangulate at all) it uses a
+ * simple fan triangulation
+ *
+ * newfaces, if non-null, must be an array of BMFace pointers,
+ * with a length equal to f->len. it will be filled with the new
+ * triangles, and will be NULL-terminated.
+*/
+void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
+ int newedgeflag, int newfaceflag, BMFace **newfaces)
+{
+ int i, done, nvert, nf_i = 0;
+ BMLoop *l, *newl, *nextloop;
+ BMVert *v;
+
+ /*copy vertex coordinates to vertspace array*/
+ i = 0;
+ l = f->loopbase;
+ do{
+ VECCOPY(projectverts[i], l->v->co);
+ l->v->head.eflag2 = i; /*warning, abuse! never duplicate in tools code! never you hear?*/ /*actually, get rid of this completely, use a new structure for this....*/
+ i++;
+ l = (BMLoop*)(l->head.next);
+ }while(l != f->loopbase);
+
+ ///bmesh_update_face_normal(bm, f, projectverts);
+
+ compute_poly_normal(f->no, projectverts, f->len);
+ poly_rotate_plane(f->no, projectverts, i);
+
+ nvert = f->len;
+
+ //compute_poly_plane(projectverts, i);
+ for (i=0; i<nvert; i++) {
+ projectverts[i][2] = 0.0f;
+ }
+
+ done = 0;
+ while(!done && f->len > 3){
+ done = 1;
+ l = find_ear(bm, f, projectverts, nvert);
+ if(l) {
+ done = 0;
+ v = l->v;
+ f = BM_Split_Face(bm, l->f, ((BMLoop*)(l->head.prev))->v,
+ ((BMLoop*)(l->head.next))->v,
+ &newl, NULL);
+ VECCOPY(f->no, l->f->no);
+
+ if (!f) {
+ printf("yeek! triangulator failed to split face!\n");
+ break;
+ }
+
+ BMO_SetFlag(bm, newl->e, newedgeflag);
+ BMO_SetFlag(bm, f, newfaceflag);
+
+ if (newfaces) newfaces[nf_i++] = f;
+
+ /*l = f->loopbase;
+ do {
+ if (l->v == v) {
+ f->loopbase = l;
+ break;
+ }
+ l = l->head.next;
+ } while (l != f->loopbase);*/
+ }
+ }
+
+ if (f->len > 3){
+ l = f->loopbase;
+ while (l->f->len > 3){
+ nextloop = ((BMLoop*)(l->head.next->next));
+ f = BM_Split_Face(bm, l->f, l->v, nextloop->v,
+ &newl, NULL);
+ if (!f) {
+ printf("triangle fan step of triangulator failed.\n");
+
+ /*NULL-terminate*/
+ if (newfaces) newfaces[nf_i] = NULL;
+ return;
+ }
+
+ if (newfaces) newfaces[nf_i++] = f;
+
+ BMO_SetFlag(bm, newl->e, newedgeflag);
+ BMO_SetFlag(bm, f, newfaceflag);
+ l = nextloop;
+ }
+ }
+
+ /*NULL-terminate*/
+ if (newfaces) newfaces[nf_i] = NULL;
+}
+
+/*each pair of loops defines a new edge, a split. this function goes
+ through and sets pairs that are geometrically invalid to null. a
+ split is invalid, if it forms a concave angle or it intersects other
+ edges in the face, or it intersects another split. in the case of
+ intersecting splits, only the first of the set of intersecting
+ splits survives.*/
+void BM_LegalSplits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
+{
+ BMIter iter;
+ BMLoop *l;
+ float v1[3], v2[3], v3[3], v4[3], no[3], mid[3], *p1, *p2, *p3, *p4;
+ float out[3] = {-234324.0f, -234324.0f, 0.0f};
+ float projectverts[100][3];
+ float edgevertsstack[200][3];
+ float (*projverts)[3] = projectverts;
+ float (*edgeverts)[3] = edgevertsstack;
+ float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f;
+ int i, j, a=0, clen;
+
+ if (f->len > 100) projverts = MEM_mallocN(sizeof(float)*3*f->len, "projvertsb");
+ if (len > 100) edgeverts = MEM_mallocN(sizeof(float)*3*2*len, "edgevertsb");
+
+ i = 0;
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ l->head.eflag2 = i;
+ VECCOPY(projverts[i], l->v->co);
+ i++;
+ }
+
+ for (i=0; i<len; i++) {
+ VECCOPY(v1, loops[i][0]->v->co);
+ VECCOPY(v2, loops[i][1]->v->co);
+
+ shrink_edgef(v1, v2, fac2);
+
+ VECCOPY(edgeverts[a], v1);
+ a++;
+ VECCOPY(edgeverts[a], v2);
+ a++;
+ }
+
+ compute_poly_normal(no, projverts, f->len);
+ poly_rotate_plane(no, projverts, f->len);
+ poly_rotate_plane(no, edgeverts, len*2);
+
+ l = f->loopbase;
+ for (i=0; i<f->len; i++) {
+ p1 = projverts[i];
+ out[0] = MAX2(out[0], p1[0]) + 0.01f;
+ out[1] = MAX2(out[1], p1[1]) + 0.01f;
+ out[2] = 0.0f;
+ p1[2] = 0.0f;
+
+ //VECCOPY(l->v->co, p1);
+
+ l = (BMLoop*) l->head.next;
+ }
+
+ for (i=0; i<len; i++) {
+ edgeverts[i*2][2] = 0.0f;
+ edgeverts[i*2+1][2] = 0.0f;
+ }
+
+ /*do convexity test*/
+ for (i=0; i<len; i++) {
+ VECCOPY(v2, edgeverts[i*2]);
+ VECCOPY(v3, edgeverts[i*2+1]);
+
+ VecAddf(mid, v2, v3);
+ VecMulf(mid, 0.5f);
+
+ clen = 0;
+ for (j=0; j<f->len; j++) {
+ p1 = projverts[j];
+ p2 = projverts[(j+1)%f->len];
+
+ VECCOPY(v1, p1);
+ VECCOPY(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ if (linecrossesf(p1, p2, mid, out)) clen++;
+ }
+
+ if (clen%2 == 0) {
+ loops[i][0] = NULL;
+ }
+ }
+
+ /*do line crossing tests*/
+ for (i=0; i<f->len; i++) {
+ p1 = projverts[i];
+ p2 = projverts[(i+1)%f->len];
+
+ VECCOPY(v1, p1);
+ VECCOPY(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ for (j=0; j<len; j++) {
+ if (!loops[j][0]) continue;
+
+ p3 = edgeverts[j*2];
+ p4 = edgeverts[j*2+1];
+
+ if (linecrossesf(v1, v2, p3, p4))
+ {
+ loops[j][0] = NULL;
+ }
+ }
+ }
+
+ for (i=0; i<len; i++) {
+ for (j=0; j<len; j++) {
+ if (j == i) continue;
+ if (!loops[i][0]) continue;
+ if (!loops[j][0]) continue;
+
+ p1 = edgeverts[i*2];
+ p2 = edgeverts[i*2+1];
+ p3 = edgeverts[j*2];
+ p4 = edgeverts[j*2+1];
+
+ VECCOPY(v1, p1);
+ VECCOPY(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ if (linecrossesf(v1, v2, p3, p4)) {
+ loops[i][0]=NULL;
+ }
+ }
+ }
+
+ if (projverts != projectverts) MEM_freeN(projverts);
+ if (edgeverts != edgevertsstack) MEM_freeN(edgeverts);
+}
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
new file mode 100644
index 00000000000..999285a6d12
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -0,0 +1,84 @@
+/**
+ * bmesh_private.h jan 2007
+ *
+ * Private function prototypes for bmesh public API.
+ * This file is a grab-bag of functions from various
+ * parts of the bmesh internals.
+ *
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BMESH_PRIVATE_H
+#define BMESH_PRIVATE_H
+
+#include "bmesh.h"
+
+/*start/stop edit*/
+void bmesh_begin_edit(struct BMesh *bm);
+void bmesh_end_edit(struct BMesh *bm, int flag);
+
+/*internal selection flushing*/
+void bmesh_selectmode_flush(struct BMesh *bm);
+
+/*internal filter API*/
+void *bmesh_get_filter_callback(int type);
+int bmesh_get_filter_argtype(int type);
+
+/*system flag access*/
+void bmesh_set_sysflag(struct BMHeader *element, int flag);
+void bmesh_clear_sysflag(struct BMHeader *element, int flag);
+int bmesh_test_sysflag(struct BMHeader *element, int flag);
+
+/*NOTE: ensure different parts of the API do not conflict
+ on using this! sets and gets the API index member
+ of the current flag layer.*/
+#define bmesh_api_seti(bm, head, i) ((head)->flags[bm->stackdepth-1].pflag = i)
+#define bmesh_api_geti(bm, head) ((head)->flags[bm->stackdepth-1].pflag)
+
+/*Polygon Utilities ? FIXME... where do these each go?*/
+/*newedgeflag sets a flag layer flag, obviously not the header flag.*/
+void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
+ int newedgeflag, int newfaceflag, BMFace **newfaces);
+void bmesh_update_face_normal(struct BMesh *bm, struct BMFace *f,
+ float (*projectverts)[3]);
+void compute_poly_plane(float (*verts)[3], int nverts);
+void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts);
+void bmesh_flip_normal(struct BMesh *bm, struct BMFace *f);
+
+/*Error reporting. Shouldnt be called by tools ever.*/
+void BME_error(void);
+
+/*include the rest of our private declarations*/
+#include "bmesh_structure.h"
+#include "bmesh_operators_private.h"
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
new file mode 100644
index 00000000000..c5a9916ae24
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -0,0 +1,548 @@
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "BLI_arithb.h"
+#include "MTC_vectorops.h"
+
+/*
+ * BM_QUERIES.C
+ *
+ * This file contains functions for answering common
+ * Topological and geometric queries about a mesh, such
+ * as, "What is the angle between these two faces?" or,
+ * "How many faces are incident upon this vertex?" Tool
+ * authors should use the functions in this file instead
+ * of inspecting the mesh structure directly.
+ *
+*/
+
+/*
+ * BMESH COUNT ELEMENT
+ *
+ * Return the amount of element of
+ * type 'type' in a given bmesh.
+ *
+ *
+*/
+
+int BM_Count_Element(BMesh *bm, int type)
+{
+ if(type == BM_VERT) return bm->totvert;
+ else if(type == BM_EDGE) return bm->totedge;
+ else if(type == BM_FACE) return bm->totface;
+
+ return 0;
+}
+
+
+/*
+ * BMESH VERT IN EDGE
+ *
+ * Returns whether or not a given vertex is
+ * is part of a given edge.
+ *
+*/
+
+int BM_Vert_In_Edge(BMEdge *e, BMVert *v)
+{
+ return bmesh_vert_in_edge(e, v);
+}
+
+/*
+ * BMESH OTHER EDGE IN FACE SHARING A VERTEX
+ *
+ * Returns an opposing loop that shares the same face.
+ *
+*/
+
+BMLoop *BM_OtherFaceLoop(BMEdge *e, BMFace *f, BMVert *v)
+{
+ BMLoop *l = f->loopbase, *l2, *l3;
+ int found = 0;
+
+ do {
+ if (l->e == e) break;
+ found = 1;
+ l = l->head.next;
+ } while (l != f->loopbase);
+
+ return l->v == v ? l->head.prev : l->head.next;
+}
+
+/*
+ * BMESH VERT IN FACE
+ *
+ * Returns whether or not a given vertex is
+ * is part of a given face.
+ *
+*/
+
+int BM_Vert_In_Face(BMFace *f, BMVert *v)
+{
+ BMLoop *l;
+
+ l = f->loopbase;
+ do{
+ if(l->v == v) return 1;
+ l = ((BMLoop*)(l->head.next));
+ }while(l != f->loopbase);
+ return 0;
+}
+
+/*
+ * BMESH VERTS IN FACE
+ *
+ * Compares the number of vertices in an array
+ * that appear in a given face
+ *
+*/
+int BM_Verts_In_Face(BMesh *bm, BMFace *f, BMVert **varr, int len)
+{
+ BMLoop *curloop = NULL;
+ int i, count = 0;
+
+ for(i=0; i < len; i++) BMO_SetFlag(bm, varr[i], BM_OVERLAP);
+
+ curloop = f->loopbase;
+ do{
+ if(BMO_TestFlag(bm, curloop->v, BM_OVERLAP)) count++;
+ curloop = (BMLoop*)(curloop->head.next);
+ } while(curloop != f->loopbase);
+
+ for(i=0; i < len; i++) BMO_ClearFlag(bm, varr[i], BM_OVERLAP);
+
+ return count;
+}
+
+/*
+ * BMESH EDGE IN FACE
+ *
+ * Returns whether or not a given edge is
+ * is part of a given face.
+ *
+*/
+
+int BM_Edge_In_Face(BMFace *f, BMEdge *e)
+{
+ BMLoop *l;
+
+ l = f->loopbase;
+ do{
+
+ if(l->e == e) return 1;
+ l = ((BMLoop*)(l->head.next));
+ }while(l != f->loopbase);
+
+ return 0;
+}
+
+/*
+ * BMESH VERTS IN EDGE
+ *
+ * Returns whether or not two vertices are in
+ * a given edge
+ *
+*/
+
+int BM_Verts_In_Edge(BMVert *v1, BMVert *v2, BMEdge *e)
+{
+ return bmesh_verts_in_edge(v1,v2,e);
+}
+
+/*
+ * BMESH GET OTHER EDGEVERT
+ *
+ * Given a edge and one of its vertices, returns
+ * the other vertex.
+ *
+*/
+
+BMVert *BM_OtherEdgeVert(BMEdge *e, BMVert *v)
+{
+ return bmesh_edge_getothervert(e,v);
+}
+
+/**
+ * BMESH EDGE EXIST
+ *
+ * Finds out if two vertices already have an edge
+ * connecting them. Note that multiple edges may
+ * exist between any two vertices, and therefore
+ * This function only returns the first one found.
+ *
+ * Returns -
+ * BMEdge pointer
+ */
+
+BMEdge *BM_Edge_Exist(BMVert *v1, BMVert *v2)
+{
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0;
+
+ if(v1->edge){
+ diskbase = bmesh_disk_getpointer(v1->edge,v1);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i=0,curedge=v1->edge;i<len;i++,curedge = bmesh_disk_nextedge(curedge,v1)){
+ if(bmesh_verts_in_edge(v1,v2,curedge)) return curedge;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * BMESH VERT EDGECOUNT
+ *
+ * Returns the number of edges around this vertex.
+ */
+
+int BM_Vert_EdgeCount(BMVert *v)
+{
+ if (v == v->edge->v1) return bmesh_cycle_length(&v->edge->d1);
+ else return bmesh_cycle_length(&v->edge->d2);
+}
+
+/**
+ * BMESH EDGE FACECOUNT
+ *
+ * Returns the number of faces around this edge
+*/
+
+int BM_Edge_FaceCount(BMEdge *e)
+{
+ int count = 0;
+ BMLoop *curloop = NULL;
+
+ if(e->loop){
+ curloop = e->loop;
+ do{
+ count++;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != e->loop);
+ }
+
+ return count;
+}
+
+/**
+ * BMESH VERT FACECOUNT
+ *
+ * Returns the number of faces around this vert
+*/
+
+int BM_Vert_FaceCount(BMVert *v){
+ int count = 0;
+ BMEdge *curedge = NULL;
+
+ if(v->edge){
+ curedge = v->edge;
+ do{
+ if(curedge->loop) count += BM_Edge_FaceCount(curedge);
+ curedge = bmesh_disk_nextedge(curedge,v);
+ }while(curedge != v->edge);
+ }
+ return count;
+}
+
+/**
+ * BMESH WIRE VERT
+ *
+ * Tests whether or not the vertex is part of a wire edge.
+ * (ie: has no faces attached to it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Wire_Vert(BMesh *bm, BMVert *v)
+{
+ BMEdge *curedge;
+
+ if(!(v->edge)) return 0;
+
+ curedge = v->edge;
+ do{
+ if(curedge->loop) return 0;
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }while(curedge != v->edge);
+
+ return 1;
+}
+
+/**
+ * BMESH WIRE EDGE
+ *
+ * Tests whether or not the edge is part of a wire.
+ * (ie: has no faces attached to it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Wire_Edge(BMesh *bm, BMEdge *e)
+{
+ if(e->loop) return 0;
+ return 1;
+}
+
+/**
+ * BMESH NONMANIFOLD VERT
+ *
+ * A vertex is non-manifold if it meets the following conditions:
+ * 1: Loose - (has no edges/faces incident upon it)
+ * 2: Joins two distinct regions - (two pyramids joined at the tip)
+ * 3: Is part of a non-manifold edge (edge with more than 2 faces)
+ * 4: Is part of a wire edge
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Nonmanifold_Vert(BMesh *bm, BMVert *v) {
+ BMEdge *e, *oe;
+ BMLoop *l;
+ int len, count, flag;
+
+ if (v->edge == NULL) {
+ /* loose vert */
+ return 1;
+ }
+
+ /* count edges while looking for non-manifold edges */
+ oe = v->edge;
+ for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=bmesh_disk_nextedge(e,v)) {
+ if (e->loop == NULL) {
+ /* loose edge */
+ return 1;
+ }
+
+ if (bmesh_cycle_length(&(e->loop->radial)) > 2) {
+ /* edge shared by more than two faces */
+ return 1;
+ }
+ }
+
+ count = 1;
+ flag = 1;
+ e = NULL;
+ oe = v->edge;
+ l = oe->loop;
+ while(e != oe) {
+ if (l->v == v) l = ((BMLoop*)(l->head.prev));
+ else l = ((BMLoop*)(l->head.next));
+ e = l->e;
+ count++; /* count the edges */
+
+ if (flag && l->radial.next->data == l) {
+ /* we've hit the edge of an open mesh, reset once */
+ flag = 0;
+ count = 1;
+ oe = e;
+ e = NULL;
+ l = oe->loop;
+ }
+ else if (l->radial.next->data == l) {
+ /* break the loop */
+ e = oe;
+ }
+ else {
+ l = l->radial.next->data;
+ }
+ }
+
+ if (count < len) {
+ /* vert shared by multiple regions */
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * BMESH NONMANIFOLD EDGE
+ *
+ * Tests whether or not this edge is manifold.
+ * A manifold edge either has 1 or 2 faces attached
+ * to it.
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Nonmanifold_Edge(BMesh *bm, BMEdge *e)
+{
+ int count = BM_Edge_FaceCount(e);
+ if(count != 2 && count != 1) return 1;
+ return 0;
+}
+
+/**
+ * BMESH BOUNDARY EDGE
+ *
+ * Tests whether or not an edge is on the boundary
+ * of a shell (has one face associated with it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Boundary_Edge(BMEdge *e)
+{
+ int count = BM_Edge_FaceCount(e);
+ if(count == 1) return 1;
+ return 0;
+}
+
+/**
+ * BMESH FACE SHAREDEDGES
+ *
+ * Counts the number of edges two faces share (if any)
+ *
+ * TODO:
+ * Move this to structure, and wrap.
+ *
+ * Returns -
+ * Integer
+ */
+
+int BM_Face_Sharededges(BMFace *f1, BMFace *f2){
+ BMLoop *l;
+ int count = 0;
+
+ l = f1->loopbase;
+ do{
+ if(bmesh_radial_find_face(l->e,f2)) count++;
+ l = ((BMLoop*)(l->head.next));
+ }while(l != f1->loopbase);
+
+ return count;
+}
+
+/**
+ *
+ * BMESH EDGE SHARE FACES
+ *
+ * Tests to see if e1 shares any faces with e2
+ *
+*/
+
+int BM_Edge_Share_Faces(BMEdge *e1, BMEdge *e2)
+{
+ BMLoop *l;
+ BMFace *f;
+
+ if(e1->loop && e2->loop){
+ l = e1->loop;
+ do{
+ f = l->f;
+ if(bmesh_radial_find_face(e2,f)){
+ return 1;
+ }
+ l = (BMLoop*)(l->radial.next->data);
+ }while(l != e1->loop);
+ }
+ return 0;
+}
+
+
+
+/**
+ * BMESH FACE ANGLE
+ *
+ * Calculates the angle between two faces. Assumes
+ * That face normals are correct.
+ *
+ * Returns -
+ * Float.
+ */
+
+float BM_Face_Angle(BMesh *bm, BMEdge *e)
+{
+ BMLoop *l1, *l2;
+ int radlen;
+ float edge_angle_cos = 0.0;
+
+ radlen = BM_Edge_FaceCount(e);
+ if(radlen == 2){
+ l1 = e->loop;
+ l2 = e->loop->radial.next->data;
+ edge_angle_cos = MTC_dot3Float(l1->f->no, l2->f->no);
+ }
+ return edge_angle_cos;
+
+}
+
+/*
+ * BMESH EXIST FACE OVERLAPS
+ *
+ * Given a set of vertices (varr), find out if
+ * all those vertices overlap an existing face.
+ *
+ * Returns:
+ * 0 for no overlap
+ * 1 for overlap
+ *
+ *
+*/
+
+int BM_Exist_Face_Overlaps(BMesh *bm, BMVert **varr, int len, BMFace **overlapface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (overlapface) *overlapface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount >= len){
+ if (overlapface) *overlapface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
+
+/*
+ * BMESH FACE EXISTS
+ *
+ * Given a set of vertices (varr), find out if
+ * there is a face with exactly those vertices
+ * (and only those vertices).
+ *
+ * Returns:
+ * 0 for no face found
+ * 1 for face found
+ *
+ *
+*/
+
+int BM_Face_Exists(BMesh *bm, BMVert **varr, int len, BMFace **existface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (existface) *existface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount == len && amount == f->len){
+ if (existface) *existface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
new file mode 100644
index 00000000000..a14f1d662ae
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -0,0 +1,775 @@
+/**
+ * bmesh_structure.c jan 2007
+ *
+ * Low level routines for manipulating the BM structure.
+ *
+ * $Id: bmesh_structure.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <limits.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "BKE_utildefines.h"
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_ghash.h"
+/**
+ * MISC utility functions.
+ *
+ */
+
+int bmesh_vert_in_edge(BMEdge *e, BMVert *v){
+ if(e->v1 == v || e->v2 == v) return 1;
+ return 0;
+}
+int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e){
+ if(e->v1 == v1 && e->v2 == v2) return 1;
+ else if(e->v1 == v2 && e->v2 == v1) return 1;
+ return 0;
+}
+
+BMVert *bmesh_edge_getothervert(BMEdge *e, BMVert *v){
+ if(e->v1 == v) return e->v2;
+ else if(e->v2 == v) return e->v1;
+ return NULL;
+}
+
+int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *new){
+ if(e->v1 == orig){
+ e->v1 = new;
+ e->d1.next = NULL;
+ e->d1.prev = NULL;
+ return 1;
+ }
+ else if(e->v2 == orig){
+ e->v2 = new;
+ e->d2.next = NULL;
+ e->d2.prev = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * ALLOCATION/DEALLOCATION FUNCTIONS
+ */
+
+BMVert *bmesh_addvertlist(BMesh *bm, BMVert *example){
+ BMVert *v=NULL;
+ v = BLI_mempool_calloc(bm->vpool);
+ v->head.next = v->head.prev = NULL;
+ v->head.flag = 0;
+ v->head.EID = bm->nextv;
+ v->head.type = BM_VERT;
+ v->co[0] = v->co[1] = v->co[2] = 0.0f;
+ v->no[0] = v->no[1] = v->no[2] = 0.0f;
+ v->edge = NULL;
+ v->head.data = NULL;
+ v->bweight = 0.0f;
+ BLI_addtail(&(bm->verts), &(v->head));
+ bm->nextv++;
+ bm->totvert++;
+
+ if(example){
+ VECCOPY(v->co,example->co);
+ CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->head.data, &v->head.data);
+ }
+ else
+ CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
+
+ /*allocate flags*/
+ v->head.flags = BLI_mempool_calloc(bm->flagpool);
+
+ return v;
+}
+BMEdge *bmesh_addedgelist(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example){
+ BMEdge *e=NULL;
+ e = BLI_mempool_calloc(bm->epool);
+ e->head.next = e->head.prev = NULL;
+ e->head.EID = bm->nexte;
+ e->head.type = BM_EDGE;
+ e->head.flag = 0;
+ e->v1 = v1;
+ e->v2 = v2;
+ e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL;
+ e->d1.data = e;
+ e->d2.data = e;
+ e->loop = NULL;
+ e->head.data = NULL;
+ e->crease = e->bweight = 0.0f;
+ bm->nexte++;
+ bm->totedge++;
+ BLI_addtail(&(bm->edges), &(e->head));
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->head.data, &e->head.data);
+ else
+ CustomData_bmesh_set_default(&bm->edata, &e->head.data);
+
+ /*allocate flags*/
+ e->head.flags = BLI_mempool_calloc(bm->flagpool);
+
+ return e;
+}
+BMLoop *bmesh_create_loop(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, BMLoop *example){
+ BMLoop *l=NULL;
+ l = BLI_mempool_calloc(bm->lpool);
+ l->head.next = l->head.prev = NULL;
+ l->head.EID = bm->nextl;
+ l->head.type = BM_LOOP;
+ l->head.flag = 0;
+ l->radial.next = l->radial.prev = NULL;
+ l->radial.data = l;
+ l->v = v;
+ l->e = e;
+ l->f = f;
+ l->head.data = NULL;
+ bm->nextl++;
+ bm->totloop++;
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
+ else
+ CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
+
+ return l;
+}
+
+BMFace *bmesh_addpolylist(BMesh *bm, BMFace *example){
+ BMFace *f = NULL;
+ f = BLI_mempool_calloc(bm->ppool);
+ f->head.flag = 0;
+ f->head.next = f->head.prev = NULL;
+ f->head.EID = bm->nextp;
+ f->head.type = BM_FACE;
+ f->loopbase = NULL;
+ f->len = 0;
+ f->head.data = NULL;
+ f->mat_nr = 0;
+ BLI_addtail(&(bm->polys),&(f->head));
+ bm->nextp++;
+ bm->totface++;
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->head.data, &f->head.data);
+ else
+ CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+
+ /*allocate flags*/
+ f->head.flags = BLI_mempool_calloc(bm->flagpool);
+
+ return f;
+}
+
+/* free functions dont do much *yet*. When per-vertex, per-edge and per-face/faceloop
+ data is added though these will be needed.
+*/
+void bmesh_free_vert(BMesh *bm, BMVert *v){
+ bm->totvert--;
+ CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
+ BLI_mempool_free(bm->flagpool, v->head.flags);
+ BLI_mempool_free(bm->vpool, v);
+}
+void bmesh_free_edge(BMesh *bm, BMEdge *e){
+ bm->totedge--;
+ CustomData_bmesh_free_block(&bm->edata, &e->head.data);
+ BLI_mempool_free(bm->flagpool, e->head.flags);
+ BLI_mempool_free(bm->epool, e);
+}
+void bmesh_free_poly(BMesh *bm, BMFace *f){
+ if (f == bm->act_face)
+ bm->act_face = NULL;
+
+ bm->totface--;
+ CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
+ BLI_mempool_free(bm->flagpool, f->head.flags);
+ BLI_mempool_free(bm->ppool, f);
+}
+void bmesh_free_loop(BMesh *bm, BMLoop *l){
+ bm->totloop--;
+ CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
+ BLI_mempool_free(bm->lpool, l);
+}
+/**
+ * BMESH CYCLES
+ *
+ * Cycles are circular doubly linked lists that form the basis of adjacency
+ * information in the BME modeller. Full adjacency relations can be derived
+ * from examining these cycles very quickly. Although each cycle is a double
+ * circular linked list, each one is considered to have a 'base' or 'head',
+ * and care must be taken by Euler code when modifying the contents of a cycle.
+ *
+ * The contents of this file are split into two parts. First there are the
+ * bmesh_cycle family of functions which are generic circular double linked list
+ * procedures. The second part contains higher level procedures for supporting
+ * modification of specific cycle types.
+ *
+ * The three cycles explicitly stored in the BM data structure are as follows:
+ *
+ * 1: The Disk Cycle - A circle of edges around a vertex
+ * Base: vertex->edge pointer.
+ *
+ * This cycle is the most complicated in terms of its structure. Each bmesh_Edge contains
+ * two bmesh_CycleNode structures to keep track of that edge's membership in the disk cycle
+ * of each of its vertices. However for any given vertex it may be the first in some edges
+ * in its disk cycle and the second for others. The bmesh_disk_XXX family of functions contain
+ * some nice utilities for navigating disk cycles in a way that hides this detail from the
+ * tool writer.
+ *
+ * Note that the disk cycle is completley independant from face data. One advantage of this
+ * is that wire edges are fully integrated into the topology database. Another is that the
+ * the disk cycle has no problems dealing with non-manifold conditions involving faces.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_disk_append_edge
+ * bmesh_disk_remove_edge
+ * bmesh_disk_nextedge
+ * bmesh_disk_getpointer
+ *
+ * 2: The Radial Cycle - A circle of face edges (bmesh_Loop) around an edge
+ * Base: edge->loop->radial structure.
+ *
+ * The radial cycle is similar to the radial cycle in the radial edge data structure.*
+ * Unlike the radial edge however, the radial cycle does not require a large amount of memory
+ * to store non-manifold conditions since BM does not keep track of region/shell
+ * information.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_radial_append
+ * bmesh_radial_remove_loop
+ * bmesh_radial_nextloop
+ * bmesh_radial_find_face
+ *
+ *
+ * 3: The Loop Cycle - A circle of face edges around a polygon.
+ * Base: polygon->loopbase.
+ *
+ * The loop cycle keeps track of a faces vertices and edges. It should be noted that the
+ * direction of a loop cycle is either CW or CCW depending on the face normal, and is
+ * not oriented to the faces editedges.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_cycle_XXX family of functions.
+ *
+ *
+ * Note that the order of elements in all cycles except the loop cycle is undefined. This
+ * leads to slightly increased seek time for deriving some adjacency relations, however the
+ * advantage is that no intrinsic properties of the data structures are dependant upon the
+ * cycle order and all non-manifold conditions are represented trivially.
+ *
+*/
+
+
+void bmesh_cycle_append(void *h, void *nt)
+{
+ BMNode *oldtail, *head, *newtail;
+
+ head = (BMNode*)h;
+ newtail = (BMNode*)nt;
+
+ if(head->next == NULL){
+ head->next = newtail;
+ head->prev = newtail;
+ newtail->next = head;
+ newtail->prev = head;
+ }
+ else{
+ oldtail = head->prev;
+ oldtail->next = newtail;
+ newtail->next = head;
+ newtail->prev = oldtail;
+ head->prev = newtail;
+
+ }
+}
+
+/**
+ * bmesh_cycle_length
+ *
+ * Count the nodes in a cycle.
+ *
+ * Returns -
+ * Integer
+ */
+
+int bmesh_cycle_length(void *h){
+
+ int len = 0;
+ BMNode *head, *curnode;
+ head = (BMNode*)h;
+
+ if(head){
+ len = 1;
+ for(curnode = head->next; curnode != head; curnode=curnode->next){
+ if(len == INT_MAX){ //check for infinite loop/corrupted cycle
+ return -1;
+ }
+ len++;
+ }
+ }
+ return len;
+}
+
+
+/**
+ * bmesh_cycle_remove
+ *
+ * Removes a node from a cycle.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_cycle_remove(void *h, void *remn)
+{
+ int i, len;
+ BMNode *head, *remnode, *curnode;
+
+ head = (BMNode*)h;
+ remnode = (BMNode*)remn;
+ len = bmesh_cycle_length(h);
+
+ if(len == 1 && head == remnode){
+ head->next = NULL;
+ head->prev = NULL;
+ return 1;
+ }
+ else{
+ for(i=0, curnode = head; i < len; curnode = curnode->next){
+ if(curnode == remnode){
+ remnode->prev->next = remnode->next;
+ remnode->next->prev = remnode->prev;
+ /*zero out remnode pointers, important!*/
+ //remnode->next = NULL;
+ //remnode->prev = NULL;
+ return 1;
+
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * bmesh_cycle_validate
+ *
+ * Validates a cycle. Takes as an argument the expected length of the cycle and
+ * a pointer to the cycle head or base.
+ *
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_cycle_validate(int len, void *h){
+ int i;
+ BMNode *curnode, *head;
+ head = (BMNode*)h;
+
+ /*forward validation*/
+ for(i = 0, curnode = head; i < len; i++, curnode = curnode->next);
+ if(curnode != head) return 0;
+
+ /*reverse validation*/
+ for(i = 0, curnode = head; i < len; i++, curnode = curnode->prev);
+ if(curnode != head) return 0;
+
+ return 1;
+}
+
+/*Begin Disk Cycle routines*/
+
+/**
+ * bmesh_disk_nextedge
+ *
+ * Find the next edge in a disk cycle
+ *
+ * Returns -
+ * Pointer to the next edge in the disk cycle for the vertex v.
+ */
+
+BMEdge *bmesh_disk_nextedge(BMEdge *e, BMVert *v)
+{
+ if(bmesh_vert_in_edge(e, v)){
+ if(e->v1 == v) return e->d1.next->data;
+ else if(e->v2 == v) return e->d2.next->data;
+ }
+ return NULL;
+}
+
+/**
+ * bmesh_disk_getpointer
+ *
+ * Given an edge and one of its vertices, find the apporpriate CycleNode
+ *
+ * Returns -
+ * Pointer to bmesh_CycleNode.
+ */
+BMNode *bmesh_disk_getpointer(BMEdge *e, BMVert *v){
+ /*returns pointer to the cycle node for the appropriate vertex in this disk*/
+ if(e->v1 == v) return &(e->d1);
+ else if (e->v2 == v) return &(e->d2);
+ return NULL;
+}
+
+/**
+ * bmesh_disk_append_edge
+ *
+ * Appends edge to the end of a vertex disk cycle.
+ *
+ * Returns -
+ * 1 for success, 0 for failure
+ */
+
+int bmesh_disk_append_edge(BMEdge *e, BMVert *v)
+{
+
+ BMNode *base, *tail;
+
+ if(bmesh_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/
+
+ /*check for loose vert first*/
+ if(v->edge == NULL){
+ v->edge = e;
+ base = tail = bmesh_disk_getpointer(e, v);
+ bmesh_cycle_append(base, tail); /*circular reference is ok!*/
+ return 1;
+ }
+
+ /*insert e at the end of disk cycle and make it the new v->edge*/
+ base = bmesh_disk_getpointer(v->edge, v);
+ tail = bmesh_disk_getpointer(e, v);
+ bmesh_cycle_append(base, tail);
+ return 1;
+}
+
+/**
+ * bmesh_disk_remove_edge
+ *
+ * Removes an edge from a disk cycle. If the edge to be removed is
+ * at the base of the cycle, the next edge becomes the new base.
+ *
+ *
+ * Returns -
+ * Nothing
+ */
+
+void bmesh_disk_remove_edge(BMEdge *e, BMVert *v)
+{
+ BMNode *base, *remnode;
+ BMEdge *newbase;
+ int len;
+
+ base = bmesh_disk_getpointer(v->edge, v);
+ remnode = bmesh_disk_getpointer(e, v);
+
+ /*first deal with v->edge pointer...*/
+ len = bmesh_cycle_length(base);
+ if(len == 1) newbase = NULL;
+ else if(v->edge == e) newbase = base->next-> data;
+ else newbase = v->edge;
+
+ /*remove and rebase*/
+ bmesh_cycle_remove(base, remnode);
+ v->edge = newbase;
+}
+
+/**
+ * bmesh_disk_next_edgeflag
+ *
+ * Searches the disk cycle of v, starting with e, for the
+ * next edge that has either eflag or tflag.
+ *
+ * bmesh_Edge pointer.
+ */
+
+BMEdge *bmesh_disk_next_edgeflag(BMEdge *e, BMVert *v, int eflag, int tflag)
+{
+
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int len, ok;
+
+ if(eflag && tflag) return NULL;
+
+ ok = bmesh_vert_in_edge(e,v);
+ if(ok){
+ diskbase = bmesh_disk_getpointer(e, v);
+ len = bmesh_cycle_length(diskbase);
+ curedge = bmesh_disk_nextedge(e,v);
+ while(curedge != e){
+ if(eflag){
+ if(curedge->head.eflag1 == eflag) return curedge;
+ }
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * bmesh_disk_count_edgeflag
+ *
+ * Counts number of edges in this verts disk cycle which have
+ * either eflag or tflag (but not both!)
+ *
+ * Returns -
+ * Integer.
+ */
+
+int bmesh_disk_count_edgeflag(BMVert *v, int eflag, int tflag)
+{
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0, count=0;
+
+ if(v->edge){
+ if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/
+ diskbase = bmesh_disk_getpointer(v->edge, v);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i = 0, curedge=v->edge; i<len; i++){
+ if(eflag){
+ if(curedge->head.eflag1 == eflag) count++;
+ }
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return count;
+}
+
+
+int bmesh_disk_hasedge(BMVert *v, BMEdge *e){
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0;
+
+ if(v->edge){
+ diskbase = bmesh_disk_getpointer(v->edge,v);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i = 0, curedge=v->edge; i<len; i++){
+ if(curedge == e) return 1;
+ else curedge=bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return 0;
+}
+
+BMEdge *bmesh_disk_existedge(BMVert *v1, BMVert *v2){
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0;
+
+ if(v1->edge){
+ diskbase = bmesh_disk_getpointer(v1->edge,v1);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i=0,curedge=v1->edge;i<len;i++,curedge = bmesh_disk_nextedge(curedge,v1)){
+ if(bmesh_verts_in_edge(v1,v2,curedge)) return curedge;
+ }
+ }
+
+ return NULL;
+}
+
+/*end disk cycle routines*/
+
+BMLoop *bmesh_radial_nextloop(BMLoop *l){
+ return (BMLoop*)(l->radial.next->data);
+}
+
+void bmesh_radial_append(BMEdge *e, BMLoop *l){
+ if(e->loop == NULL) e->loop = l;
+ bmesh_cycle_append(&(e->loop->radial), &(l->radial));
+}
+
+void bmesh_radial_remove_loop(BMLoop *l, BMEdge *e)
+{
+ BMLoop *newbase;
+ int len;
+
+ /*deal with edge->loop pointer*/
+ len = bmesh_cycle_length(&(e->loop->radial));
+ if(len == 1) newbase = NULL;
+ else if(e->loop == l) newbase = e->loop->radial.next->data;
+ else newbase = e->loop;
+
+ /*remove and rebase*/
+ bmesh_cycle_remove(&(e->loop->radial), &(l->radial));
+ e->loop = newbase;
+}
+
+int bmesh_radial_find_face(BMEdge *e,BMFace *f)
+{
+
+ BMLoop *curloop;
+ int i, len;
+
+ len = bmesh_cycle_length(&(e->loop->radial));
+ for(i = 0, curloop = e->loop; i < len; i++, curloop = curloop->radial.next->data){
+ if(curloop->f == f) return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * BME RADIAL COUNT FACE VERT
+ *
+ * Returns the number of times a vertex appears
+ * in a radial cycle
+ *
+*/
+
+int bmesh_radial_count_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ int count = 0;
+ curloop = l;
+ do{
+ if(curloop->v == v) count++;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return count;
+}
+
+/*
+ * BME DISK COUNT FACE VERT
+ *
+ * Counts the number of loop users
+ * for this vertex. Note that this is
+ * equivalent to counting the number of
+ * faces incident upon this vertex
+ *
+*/
+
+int bmesh_disk_count_facevert(BMVert *v)
+{
+ BMEdge *curedge;
+ int count = 0;
+
+ /*is there an edge on this vert at all?*/
+ if(!v->edge)
+ return count;
+
+ /*first, loop around edges*/
+ curedge = v->edge;
+ do{
+ if(curedge->loop) count += bmesh_radial_count_facevert(curedge->loop, v);
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }while(curedge != v->edge);
+
+ return count;
+}
+
+/*
+ * BME RADIAL FIND FIRST FACE VERT
+ *
+ * Finds the first loop of v around radial
+ * cycle
+ *
+*/
+BMLoop *bmesh_radial_find_first_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = l;
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return NULL;
+}
+
+BMLoop *bmesh_radial_find_next_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = bmesh_radial_nextloop(l);
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop !=l);
+ return l;
+}
+
+
+/*
+ * BME FIND FIRST FACE EDGE
+ *
+ * Finds the first edge in a vertices
+ * Disk cycle that has one of this
+ * vert's loops attached
+ * to it.
+ *
+ *
+*/
+
+BMEdge *bmesh_disk_find_first_faceedge(BMEdge *e, BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = e;
+ do{
+ if(searchedge->loop && bmesh_radial_count_facevert(searchedge->loop,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge != e);
+
+ return NULL;
+}
+
+BMEdge *bmesh_disk_find_next_faceedge(BMEdge *e, BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = bmesh_disk_nextedge(e,v);
+ do{
+ if(searchedge->loop && bmesh_radial_count_facevert(searchedge->loop,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge !=e);
+ return e;
+}
+
+
+
+
+
+struct BMLoop *bmesh_loop_find_loop(struct BMFace *f, struct BMVert *v) {
+ BMLoop *l;
+ int i, len;
+
+ len = bmesh_cycle_length(f->loopbase);
+ for (i = 0, l=f->loopbase; i < len; i++, l=((BMLoop*)(l->head.next)) ) {
+ if (l->v == v) return l;
+ }
+ return NULL;
+}
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
new file mode 100644
index 00000000000..ba63bb8f65f
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -0,0 +1,100 @@
+/**
+ * bmesh_structure.h jan 2007
+ *
+ * The lowest level of functionality for manipulating bmesh structures.
+ * None of these functions should ever be exported to the rest of Blender.
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BM_STRUCTURE_H
+#define BM_STRUCTURE_H
+
+/*ALLOCATION/DEALLOCATION*/
+struct BMVert *bmesh_addvertlist(struct BMesh *bm, struct BMVert *example);
+struct BMEdge *bmesh_addedgelist(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge *example);
+struct BMFace *bmesh_addpolylist(struct BMesh *bm, struct BMFace *example);
+struct BMLoop *bmesh_create_loop(struct BMesh *bm, struct BMVert *v, struct BMEdge *e, struct BMFace *f, struct BMLoop *example);
+
+void bmesh_free_vert(struct BMesh *bm, struct BMVert *v);
+void bmesh_free_edge(struct BMesh *bm, struct BMEdge *e);
+void bmesh_free_poly(struct BMesh *bm, struct BMFace *f);
+void bmesh_free_loop(struct BMesh *bm, struct BMLoop *l);
+
+/*DOUBLE CIRCULAR LINKED LIST FUNCTIONS*/
+void bmesh_cycle_append(void *h, void *nt);
+int bmesh_cycle_remove(void *h, void *remn);
+int bmesh_cycle_validate(int len, void *h);
+int bmesh_cycle_length(void *h);
+
+/*DISK CYCLE MANAGMENT*/
+int bmesh_disk_append_edge(struct BMEdge *e, struct BMVert *v);
+void bmesh_disk_remove_edge(struct BMEdge *e, struct BMVert *v);
+struct BMEdge *bmesh_disk_nextedge(struct BMEdge *e, struct BMVert *v);
+struct BMNode *bmesh_disk_getpointer(struct BMEdge *e, struct BMVert *v);
+int bmesh_disk_count_facevert(struct BMVert *v);
+struct BMEdge *bmesh_disk_find_first_faceedge(struct BMEdge *e, struct BMVert *v);
+struct BMEdge *bmesh_disk_find_next_faceedge(struct BMEdge *e, struct BMVert *v);
+
+/*RADIAL CYCLE MANAGMENT*/
+void bmesh_radial_append(struct BMEdge *e, struct BMLoop *l);
+void bmesh_radial_remove_loop(struct BMLoop *l, struct BMEdge *e);
+int bmesh_radial_find_face(struct BMEdge *e, struct BMFace *f);
+struct BMLoop *bmesh_radial_nextloop(struct BMLoop *l);
+int bmesh_radial_count_facevert(struct BMLoop *l, struct BMVert *v);
+struct BMLoop *bmesh_radial_find_first_facevert(struct BMLoop *l, struct BMVert *v);
+struct BMLoop *bmesh_radial_find_next_facevert(struct BMLoop *l, struct BMVert *v);
+
+/*EDGE UTILITIES*/
+int bmesh_vert_in_edge(struct BMEdge *e, struct BMVert *v);
+int bmesh_verts_in_edge(struct BMVert *v1, struct BMVert *v2, struct BMEdge *e);
+int bmesh_edge_swapverts(struct BMEdge *e, struct BMVert *orig, struct BMVert *new); /*relink edge*/
+struct BMVert *bmesh_edge_getothervert(struct BMEdge *e, struct BMVert *v);
+int bmesh_disk_hasedge(struct BMVert *v, struct BMEdge *e);
+struct BMEdge *bmesh_disk_existedge(BMVert *v1, BMVert *v2);
+struct BMEdge *bmesh_disk_next_edgeflag(struct BMEdge *e, struct BMVert *v, int eflag, int tflag);
+int bmesh_disk_count_edgeflag(struct BMVert *v, int eflag, int tflag);
+
+/*EULER API - For modifying structure*/
+struct BMVert *bmesh_mv(struct BMesh *bm, float *vec);
+struct BMEdge *bmesh_me(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2);
+struct BMFace *bmesh_mf(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge **elist, int len);
+int bmesh_kv(struct BMesh *bm, struct BMVert *v);
+int bmesh_ke(struct BMesh *bm, struct BMEdge *e);
+int bmesh_kf(struct BMesh *bm, struct BMFace *bply);
+struct BMVert *bmesh_semv(struct BMesh *bm, struct BMVert *tv, struct BMEdge *e, struct BMEdge **re);
+struct BMFace *bmesh_sfme(struct BMesh *bm, struct BMFace *f, struct BMVert *v1, struct BMVert *v2, struct BMLoop **rl);
+int bmesh_jekv(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv);
+int bmesh_loop_reverse(struct BMesh *bm, struct BMFace *f);
+struct BMFace *bmesh_jfke(struct BMesh *bm, struct BMFace *f1, BMFace *f2, BMEdge *e);
+
+struct BMVert *bmesh_urmv(struct BMesh *bm, struct BMFace *sf, struct BMVert *sv);
+//int *bmesh_grkv(struct BMesh *bm, struct BMFace *sf, struct BMVert *kv);
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_to_editmesh.c b/source/blender/bmesh/intern/bmesh_to_editmesh.c
new file mode 100644
index 00000000000..4654d353255
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_to_editmesh.c
@@ -0,0 +1,312 @@
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "bmesh.h"
+
+/*
+ * BMESH TO EDITMESH
+ *
+ * This file contains functions for converting
+ * from a bmesh to an editmesh
+ *
+*/
+
+/*
+ * LOOPS TO EDITMESH CORNERS
+ *
+ * Converts N-Gon loop (face-edge)
+ * data (UVs, Verts Colors, ect) to
+ * face corner data.
+ *
+*/
+
+static void loops_to_editmesh_corners(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ j++;
+ l = ((BMLoop*)(l->head.next));
+ } while(l!=f->loopbase);
+
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ j++;
+ l = ((BMLoop*)(l->head.next));
+ } while(l!=f->loopbase);
+ }
+}
+
+static EditVert *bmeshvert_to_editvert(BMesh *bm, EditMesh *em, BMVert *v, int index, EditVert **evlist)
+{
+ EditVert *eve = NULL;
+
+ v->head.eflag1 = index; /*abuse!*/
+ eve = addvertlist(em, v->co, NULL);
+ eve->keyindex = index;
+ evlist[index]= eve;
+
+ /*copy flags*/
+ if(v->head.flag & BM_HIDDEN) eve->h = 1;
+ if (v->head.flag & BM_SELECT) eve->f |= SELECT;
+
+ eve->bweight = v->bweight;
+ CustomData_em_copy_data(&bm->vdata, &em->vdata, v->head.data, &eve->data);
+ /*copy normal*/
+ eve->no[0] = v->no[0];
+ eve->no[1] = v->no[1];
+ eve->no[2] = v->no[2];
+
+ return eve;
+}
+
+static void bmeshedge_to_editedge_internal(BMesh *bm, EditMesh *em, BMEdge *e, EditEdge *eed)
+{
+ eed->crease = e->crease;
+ eed->bweight = e->bweight;
+
+ //copy relavent flags
+ if (e->head.flag & BM_SELECT) eed->f |= SELECT;
+ if (e->head.flag & BM_SEAM) eed->seam = 1;
+ if (e->head.flag & BM_SHARP) eed->sharp = 1;
+ if (e->head.flag & BM_HIDDEN) eed->h = 1;
+ if (e->head.flag & BM_FGON) eed->h |= EM_FGON;
+
+ CustomData_em_copy_data(&bm->edata, &em->edata, e->head.data, &eed->data);
+}
+
+static EditEdge *bmeshedge_to_editedge(BMesh *bm, EditMesh *em, BMEdge *e, EditVert **evlist)
+{
+ EditEdge *eed = NULL;
+
+ if(!(findedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1]))){
+ eed= addedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1], NULL);
+ bmeshedge_to_editedge_internal(bm, em, e, eed);
+ }
+
+ return eed;
+}
+
+static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditVert **evlist, int numCol, int numTex)
+{
+ EditVert *eve1, *eve2, *eve3, *eve4;
+ EditFace *efa = NULL;
+ int len;
+
+ len = f->len;
+
+ eve1= evlist[f->loopbase->v->head.eflag1];
+ eve2= evlist[((BMLoop*)(f->loopbase->head.next))->v->head.eflag1];
+ eve3= evlist[((BMLoop*)(f->loopbase->head.next->next))->v->head.eflag1];
+ if (len == 4) {
+ eve4= evlist[ ((BMLoop*)(f->loopbase->head.prev))->v->head.eflag1];
+ }
+ else {
+ eve4= NULL;
+ }
+
+ if (eve1==eve2 || eve1==eve3 || eve1==eve4 || eve2==eve3 || eve3==eve4
+ || eve2==eve4) return NULL;
+
+ efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
+ if (!efa) return NULL;
+
+ bmeshedge_to_editedge_internal(bm, em, f->loopbase->e, efa->e1);
+ bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.next))->e, efa->e2);
+ bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.next->next))->e, efa->e3);
+ if(eve4)
+ bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.prev))->e, efa->e4);
+
+ efa->mat_nr = (unsigned char)f->mat_nr;
+
+ /*Copy normal*/
+ efa->n[0] = f->no[0];
+ efa->n[1] = f->no[1];
+ efa->n[2] = f->no[2];
+
+ //copy relavent original flags
+ if (f->head.flag & BM_SELECT) efa->f |= SELECT;
+ if (f->head.flag & BM_HIDDEN) efa->h = 1;
+ if (f->head.flag & BM_SMOOTH) efa->flag |= ME_SMOOTH;
+ if (f->head.flag & BM_ACTIVE) EM_set_actFace(em, efa);
+
+ CustomData_em_copy_data(&bm->pdata, &em->fdata, f->head.data, &efa->data);
+ loops_to_editmesh_corners(bm, &em->fdata, efa->data, f, numCol,numTex);
+
+ return efa;
+}
+
+EditMesh *bmesh_to_editmesh_intern(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ EditMesh *em;
+ EditVert *eve, **evlist;
+
+ int totvert, i, numTex, numCol;
+
+ em = MEM_callocN(sizeof(EditMesh), "EditMesh from bmesh");
+
+ em->selectmode = bm->selectmode;
+
+ CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = BM_Count_Element(bm, BM_VERT);
+ evlist= MEM_mallocN(totvert*sizeof(EditVert *),"evlist");
+
+ /* make vertices */
+ for(i=0, v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts), i++)
+ eve = bmeshvert_to_editvert(bm, em, v, i, evlist);
+
+ /* make edges */
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
+ bmeshedge_to_editedge(bm, em, e, evlist);
+
+ /* make faces */
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
+ bmeshface_to_editface(bm, em, f, evlist, numCol, numTex);
+
+ MEM_freeN(evlist);
+
+ EM_fgon_flags(em);
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+
+ return em;
+}
+
+void bmesh2edit_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMO_Set_Pnt(op, "emout", bmesh_to_editmesh_intern(bmesh));
+}
+
+#define FACE_NGON 1
+
+void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMOperator triop;
+ BMFace *face;
+ BMIter iter, liter;
+ BMEdge *edge;
+ BMLoop *l, *nl;
+ BMOpSlot *eout;
+ int i, trifan = BMO_Get_Int(op, "trifan");
+
+ if (!trifan) BMO_Init_Op(&triop, "triangulate");
+
+ /*instead of properly tesselate, just make a triangle fan, this
+ should make bmesh -> editmesh -> bmesh conversions always properly
+ work.*/
+ for (face = BMIter_New(&iter, bmesh, BM_FACES_OF_MESH, NULL); face; face=BMIter_Step(&iter)) {
+ if (face->len > 4) {
+ BMO_SetFlag(bmesh, face, FACE_NGON);
+ if (trifan) {
+ while (face->len > 4) {
+ BM_Split_Face(bmesh, face,
+ face->loopbase->v,
+ ((BMLoop*)face->loopbase->head.next->next)->v,
+ &nl, NULL);
+ BM_SetHFlag(nl->e, BM_FGON);
+ }
+ }
+ }
+ }
+
+ if (!trifan) {
+ BMO_Flag_To_Slot(bmesh, &triop, "faces", FACE_NGON, BM_FACE);
+ BMO_Exec_Op(bmesh, &triop);
+
+ eout = BMO_GetSlot(&triop, "edgeout");
+ for (i=0; i<eout->len; i++) {
+ edge = ((BMEdge**)eout->data.buf)[i];
+ edge->head.flag |= BM_FGON;
+ face = BMIter_New(&iter, bmesh, BM_FACES_OF_EDGE, edge);
+
+ for (; face; face=BMIter_Step(&iter)) {
+ face->head.flag |= BM_NONORMCALC;
+ }
+ }
+
+ BMO_Finish_Op(bmesh, &triop);
+ }
+}
+
+EditMesh *bmesh_to_editmesh(BMesh *bmesh)
+{
+ BMOperator conv, makefgon;
+ EditMesh *em;
+
+ /*first fgon-afy the mesh*/
+ BMO_Init_Op(&makefgon, "makefgon");
+ BMO_Set_Int(&makefgon, "trifan", 1);
+ BMO_Exec_Op(bmesh, &makefgon);
+ BMO_Finish_Op(bmesh, &makefgon);
+
+ BMO_Init_Op(&conv, "bmesh_to_editmesh");
+ BMO_Exec_Op(bmesh, &conv);
+ em = BMO_Get_Pnt(&conv, "emout");
+ BMO_Finish_Op(bmesh, &conv);
+
+ return em;
+} \ No newline at end of file
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
new file mode 100644
index 00000000000..40f787bf6c2
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -0,0 +1,667 @@
+#include <stdio.h>
+#include <string.h>
+#include "BLI_mempool.h"
+
+#include "bmesh_private.h"
+#include "bmesh_walkers.h"
+
+#include "bmesh.h"
+
+/*
+ - joeedh -
+ design notes:
+
+ original desing: walkers directly emulation recursive functions.
+ functions save their state onto a stack, and also push new states
+ to implement recursive or looping behaviour. generally only one
+ state push per call with a specific state is desired.
+
+ basic design pattern: the walker step function goes through it's
+ list of possible choices for recursion, and recurses (by pushing a new state)
+ using the first non-visited one. this choise is the flagged as visited using
+ the ghash. each time this happens, only one state is pushed.
+
+ * walkers use tool flags, not header flags
+ * walkers now use ghash for storing visited elements,
+ rather then stealing flags. ghash can be rewritten
+ to be faster if necassary, in the far future :) .
+ * tools should ALWAYS have necassary error handling
+ for if walkers fail.
+*/
+
+typedef struct shellWalker{
+ struct shellWalker *prev;
+ BMVert *base;
+ BMEdge *curedge, *current;
+} shellWalker;
+
+typedef struct islandboundWalker {
+ struct islandboundWalker *prev;
+ BMLoop *base;
+ BMVert *lastv;
+ BMLoop *curloop;
+} islandboundWalker;
+
+typedef struct islandWalker {
+ struct islandWalker * prev;
+ BMFace *cur;
+} islandWalker;
+
+typedef struct loopWalker {
+ struct loopWalker * prev;
+ BMEdge *cur, *start;
+ BMVert *lastv, *startv;
+ int startrad, stage2;
+} loopWalker;
+
+typedef struct faceloopWalker {
+ struct faceloopWalker * prev;
+ BMLoop *l;
+} faceloopWalker;
+
+/* NOTE: this comment is out of date, update it - joeedh
+ * BMWalker - change this to use the filters functions.
+ *
+ * A generic structure for maintaing the state and callbacks nessecary for walking over
+ * the surface of a mesh. An example of usage:
+ *
+ * BMEdge *edge;
+ * BMWalker *walker = BMW_create(BM_SHELLWALKER, BM_SELECT);
+ * walker->begin(walker, vert);
+ * for(edge = BMW_walk(walker); edge; edge = bmeshWwalker_walk(walker)){
+ * bmesh_select_edge(edge);
+ * }
+ * BMW_free(walker);
+ *
+ * The above example creates a walker that walks over the surface a mesh by starting at
+ * a vertex and traveling across its edges to other vertices, and repeating the process
+ * over and over again until it has visited each vertex in the shell. An additional restriction
+ * is passed into the BMW_create function stating that we are only interested
+ * in walking over edges that have been flagged with the bitmask 'BM_SELECT'.
+ *
+ *
+*/
+
+/*Forward declerations*/
+static void *BMW_walk(struct BMWalker *walker);
+static void BMW_popstate(struct BMWalker *walker);
+static void BMW_pushstate(struct BMWalker *walker);
+
+static void shellWalker_begin(struct BMWalker *walker, void *data);
+static void *shellWalker_yield(struct BMWalker *walker);
+static void *shellWalker_step(struct BMWalker *walker);
+
+static void islandboundWalker_begin(BMWalker *walker, void *data);
+static void *islandboundWalker_yield(BMWalker *walker);
+static void *islandboundWalker_step(BMWalker *walker);
+
+static void islandWalker_begin(BMWalker *walker, void *data);
+static void *islandWalker_yield(BMWalker *walker);
+static void *islandWalker_step(BMWalker *walker);
+
+static void loopWalker_begin(BMWalker *walker, void *data);
+static void *loopWalker_yield(BMWalker *walker);
+static void *loopWalker_step(BMWalker *walker);
+
+static void faceloopWalker_begin(BMWalker *walker, void *data);
+static void *faceloopWalker_yield(BMWalker *walker);
+static void *faceloopWalker_step(BMWalker *walker);
+
+/* Pointer hiding*/
+typedef struct bmesh_walkerGeneric{
+ struct bmesh_walkerGeneric *prev;
+} bmesh_walkerGeneric;
+
+
+void *BMW_Begin(BMWalker *walker, void *start) {
+ walker->begin(walker, start);
+
+ return walker->step(walker);
+}
+
+/*
+ * BMW_CREATE
+ *
+ * Allocates and returns a new mesh walker of
+ * a given type. The elements visited are filtered
+ * by the bitmask 'searchmask'.
+ *
+*/
+
+void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask)
+{
+ int size = 0;
+
+ memset(walker, 0, sizeof(BMWalker));
+ walker->bm = bm;
+ walker->restrictflag = searchmask;
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ switch(type){
+ case BMW_SHELL:
+ walker->begin = shellWalker_begin;
+ walker->step = shellWalker_step;
+ walker->yield = shellWalker_yield;
+ size = sizeof(shellWalker);
+ break;
+ case BMW_ISLANDBOUND:
+ walker->begin = islandboundWalker_begin;
+ walker->step = islandboundWalker_step;
+ walker->yield = islandboundWalker_yield;
+ size = sizeof(islandboundWalker);
+ break;
+ case BMW_ISLAND:
+ walker->begin = islandWalker_begin;
+ walker->step = islandWalker_step;
+ walker->yield = islandWalker_yield;
+ size = sizeof(islandWalker);
+ break;
+ case BMW_LOOP:
+ walker->begin = loopWalker_begin;
+ walker->step = loopWalker_step;
+ walker->yield = loopWalker_yield;
+ size = sizeof(loopWalker);
+ break;
+ case BMW_FACELOOP:
+ walker->begin = faceloopWalker_begin;
+ walker->step = faceloopWalker_step;
+ walker->yield = faceloopWalker_yield;
+ size = sizeof(faceloopWalker);
+ break;
+ default:
+ break;
+ }
+ walker->stack = BLI_mempool_create(size, 100, 100);
+ walker->currentstate = NULL;
+}
+
+/*
+ * BMW_End
+ *
+ * Frees a walker's stack.
+ *
+*/
+
+void BMW_End(BMWalker *walker)
+{
+ BLI_mempool_destroy(walker->stack);
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+}
+
+
+/*
+ * BMW_Step
+ *
+*/
+
+void *BMW_Step(BMWalker *walker)
+{
+ BMHeader *head;
+
+ head = BMW_walk(walker);
+
+ return head;
+}
+
+/*
+ * BMW_WALK
+ *
+ * Steps a mesh walker forward by one element
+ *
+ * TODO:
+ * -add searchmask filtering
+ *
+*/
+
+static void *BMW_walk(BMWalker *walker)
+{
+ void *current = NULL;
+
+ while(walker->currentstate){
+ current = walker->step(walker);
+ if(current) return current;
+ }
+ return NULL;
+}
+
+/*
+ * BMW_popstate
+ *
+ * Pops the current walker state off the stack
+ * and makes the previous state current
+ *
+*/
+
+static void BMW_popstate(BMWalker *walker)
+{
+ void *oldstate;
+ oldstate = walker->currentstate;
+ walker->currentstate
+ = ((bmesh_walkerGeneric*)walker->currentstate)->prev;
+ BLI_mempool_free(walker->stack, oldstate);
+}
+
+/*
+ * BMW_pushstate
+ *
+ * Pushes the current state down the stack and allocates
+ * a new one.
+ *
+*/
+
+static void BMW_pushstate(BMWalker *walker)
+{
+ bmesh_walkerGeneric *newstate;
+ newstate = BLI_mempool_alloc(walker->stack);
+ newstate->prev = walker->currentstate;
+ walker->currentstate = newstate;
+}
+
+void BMW_reset(BMWalker *walker) {
+ while (walker->currentstate) {
+ BMW_popstate(walker);
+ }
+}
+
+/* Shell Walker:
+ *
+ * Starts at a vertex on the mesh and walks over the 'shell' it belongs
+ * to via visiting connected edges.
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void shellWalker_begin(BMWalker *walker, void *data){
+ BMVert *v = data;
+ shellWalker *shellWalk = NULL;
+
+ BMW_pushstate(walker);
+
+ shellWalk = walker->currentstate;
+ shellWalk->base = NULL;
+ shellWalk->curedge = NULL;
+
+ if(v->edge){
+ shellWalk->base = v;
+ shellWalk->curedge = v->edge;
+ }
+}
+static void *shellWalker_yield(BMWalker *walker)
+{
+ shellWalker *shellWalk = walker->currentstate;
+ return shellWalk->curedge;
+}
+
+static void *shellWalker_step(BMWalker *walker)
+{
+ BMEdge *curedge, *next = NULL;
+ BMVert *ov = NULL;
+ int restrictpass = 1;
+ shellWalker *shellWalk = walker->currentstate;
+
+ if (!BLI_ghash_lookup(walker->visithash, shellWalk->base))
+ BLI_ghash_insert(walker->visithash, shellWalk->base, NULL);
+
+ /*find the next edge whose other vertex has not been visited*/
+ curedge = shellWalk->curedge;
+ do{
+ if (!BLI_ghash_lookup(walker->visithash, curedge)) {
+ BLI_ghash_insert(walker->visithash, curedge, NULL);
+ if(walker->restrictflag &&
+ (!BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
+ {
+ restrictpass = 0;
+ }
+ if(restrictpass) {
+ ov = BM_OtherEdgeVert(curedge, shellWalk->base);
+
+ /*save current state*/
+ shellWalk->curedge = curedge;
+
+ /*push a new state onto the stack*/
+ BMW_pushstate(walker);
+
+ /*populate the new state*/
+ ((shellWalker*)walker->currentstate)->base = ov;
+ ((shellWalker*)walker->currentstate)->curedge = curedge;
+ /*break out of loop*/
+
+ next = curedge;
+ break;
+ }
+ }
+ curedge = bmesh_disk_nextedge(curedge, shellWalk->base);
+ }while(curedge != shellWalk->curedge);
+
+ shellWalk->current = next;
+ return next;
+}
+
+/* Island Boundary Walker:
+ *
+ * Starts at a edge on the mesh and walks over the boundary of an
+ * island it belongs to.
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void islandboundWalker_begin(BMWalker *walker, void *data){
+ BMLoop *l = data;
+ islandboundWalker *iwalk = NULL;
+
+ BMW_pushstate(walker);
+
+ iwalk = walker->currentstate;
+
+ iwalk->base = iwalk->curloop = l;
+ iwalk->lastv = l->v;
+
+ BLI_ghash_insert(walker->visithash, data, NULL);
+
+}
+
+static void *islandboundWalker_yield(BMWalker *walker)
+{
+ islandboundWalker *iwalk = walker->currentstate;
+
+ return iwalk->curloop;
+}
+
+static void *islandboundWalker_step(BMWalker *walker)
+{
+ islandboundWalker *iwalk = walker->currentstate, owalk;
+ BMVert *v;
+ BMEdge *e = iwalk->curloop->e;
+ BMFace *f;
+ BMLoop *l = iwalk->curloop;
+ int found=0;
+
+ owalk = *iwalk;
+
+ if (iwalk->lastv == e->v1) v = e->v2;
+ else v = e->v1;
+
+ if (BM_Nonmanifold_Vert(walker->bm, v)) {
+ BMW_reset(walker);
+ BMO_RaiseError(walker->bm, NULL,BMERR_WALKER_FAILED,
+ "Non-manifold vert"
+ " while searching region boundary");
+ return NULL;
+ }
+
+ /*pop off current state*/
+ BMW_popstate(walker);
+
+ f = l->f;
+
+ while (1) {
+ l = BM_OtherFaceLoop(e, f, v);
+ if (bmesh_radial_nextloop(l) != l) {
+ l = bmesh_radial_nextloop(l);
+ f = l->f;
+ e = l->e;
+ if(!BMO_TestFlag(walker->bm, f, walker->restrictflag)){
+ l = l->radial.next->data;
+ break;
+ }
+ } else {
+ f = l->f;
+ e = l->e;
+ break;
+ }
+ }
+
+ if (l == owalk.curloop) return NULL;
+ if (BLI_ghash_haskey(walker->visithash, l)) return owalk.curloop;
+
+ BLI_ghash_insert(walker->visithash, l, NULL);
+ BMW_pushstate(walker);
+ iwalk = walker->currentstate;
+ iwalk->base = owalk.base;
+
+ //if (!BMO_TestFlag(walker->bm, l->f, walker->restrictflag))
+ // iwalk->curloop = l->radial.next->data;
+ iwalk->curloop = l; //else iwalk->curloop = l;
+ iwalk->lastv = v;
+
+ return owalk.curloop;
+}
+
+
+/* Island Walker:
+ *
+ * Starts at a tool flagged-face and walks over the face region
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void islandWalker_begin(BMWalker *walker, void *data){
+ islandWalker *iwalk = NULL;
+
+ BMW_pushstate(walker);
+
+ iwalk = walker->currentstate;
+ BLI_ghash_insert(walker->visithash, data, NULL);
+
+ iwalk->cur = data;
+}
+
+static void *islandWalker_yield(BMWalker *walker)
+{
+ islandWalker *iwalk = walker->currentstate;
+
+ return iwalk->cur;
+}
+
+static void *islandWalker_step(BMWalker *walker)
+{
+ islandWalker *iwalk = walker->currentstate, *owalk;
+ BMIter iter, liter;
+ BMFace *f, *curf = iwalk->cur;
+ BMLoop *l;
+ owalk = iwalk;
+
+ BMW_popstate(walker);
+
+ l = BMIter_New(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
+ for (; l; l=BMIter_Step(&liter)) {
+ f = BMIter_New(&iter, walker->bm, BM_FACES_OF_EDGE, l->e);
+ for (; f; f=BMIter_Step(&iter)) {
+ if (!BMO_TestFlag(walker->bm, f, walker->restrictflag))
+ continue;
+ if (BLI_ghash_haskey(walker->visithash, f)) continue;
+
+ BMW_pushstate(walker);
+ iwalk = walker->currentstate;
+ iwalk->cur = f;
+ BLI_ghash_insert(walker->visithash, f, NULL);
+ break;
+
+ }
+ }
+
+ return curf;
+}
+
+
+/* Island Walker:
+ *
+ * Starts at a tool flagged-face and walks over the face region
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void loopWalker_begin(BMWalker *walker, void *data){
+ loopWalker *lwalk = NULL, owalk;
+ BMEdge *e = data;
+ BMVert *v;
+ int found=1, val;
+
+ v = e->v1;
+
+ val = BM_Vert_EdgeCount(v);
+
+ BMW_pushstate(walker);
+
+ lwalk = walker->currentstate;
+ BLI_ghash_insert(walker->visithash, e, NULL);
+
+ lwalk->cur = lwalk->start = e;
+ lwalk->lastv = lwalk->startv = v;
+ lwalk->stage2 = 0;
+ lwalk->startrad = BM_Edge_FaceCount(e);
+
+ /*rewind*/
+ while (walker->currentstate) {
+ owalk = *((loopWalker*)walker->currentstate);
+ BMW_walk(walker);
+ }
+
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ *lwalk = owalk;
+
+ if (lwalk->lastv == owalk.cur->v1) lwalk->lastv = owalk.cur->v2;
+ else lwalk->lastv = owalk.cur->v1;
+
+ lwalk->startv = lwalk->lastv;
+
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ BLI_ghash_insert(walker->visithash, owalk.cur, NULL);
+}
+
+static void *loopWalker_yield(BMWalker *walker)
+{
+ loopWalker *lwalk = walker->currentstate;
+
+ return lwalk->cur;
+}
+
+static void *loopWalker_step(BMWalker *walker)
+{
+ loopWalker *lwalk = walker->currentstate, owalk;
+ BMEdge *e = lwalk->cur, *nexte = NULL;
+ BMLoop *l, *l2;
+ BMVert *v;
+ int val, rlen, found=0, i=0, stopi;
+
+ owalk = *lwalk;
+
+ if (e->v1 == lwalk->lastv) v = e->v2;
+ else v = e->v1;
+
+ val = BM_Vert_EdgeCount(v);
+
+ BMW_popstate(walker);
+
+ rlen = owalk.startrad;
+ l = e->loop;
+
+ if (val == 4 || val == 2 || rlen == 1) {
+ i = 0;
+ stopi = val / 2;
+ while (1) {
+ if (rlen != 1 && i == stopi) break;
+
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+ l2 = bmesh_radial_nextloop(l);
+
+ if (l2 == l) {
+ break;
+ }
+
+ l = l2;
+
+ i += 1;
+ }
+ }
+
+ if (l != e->loop && !BLI_ghash_haskey(walker->visithash, l->e)) {
+ if (!(rlen != 1 && i != stopi)) {
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ *lwalk = owalk;
+ lwalk->cur = l->e;
+ lwalk->lastv = v;
+ BLI_ghash_insert(walker->visithash, l->e, NULL);
+ }
+ }
+
+ return owalk.cur;
+}
+
+static void faceloopWalker_begin(BMWalker *walker, void *data)
+{
+ faceloopWalker *lwalk, owalk;
+ BMEdge *e = data;
+
+ BMW_pushstate(walker);
+
+ if (!e->loop) return;
+
+ lwalk = walker->currentstate;
+ lwalk->l = e->loop;
+ BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+
+ /*rewind*/
+ while (walker->currentstate) {
+ owalk = *((faceloopWalker*)walker->currentstate);
+ BMW_walk(walker);
+ }
+
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ *lwalk = owalk;
+
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+}
+
+static void *faceloopWalker_yield(BMWalker *walker)
+{
+ faceloopWalker *lwalk = walker->currentstate;
+
+ if (!lwalk) return NULL;
+
+ return lwalk->l->f;
+}
+
+static void *faceloopWalker_step(BMWalker *walker)
+{
+ faceloopWalker *lwalk = walker->currentstate;
+ BMFace *f = lwalk->l->f;
+ BMLoop *l = lwalk->l;
+
+ BMW_popstate(walker);
+
+ l = l->head.next->next;
+ if (l == l->radial.next->data) {
+ l = l->head.prev->prev;
+ }
+ l = l->radial.next->data;
+
+ if (l->f->len == 4 && !BLI_ghash_haskey(walker->visithash, l->f)) {
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ lwalk->l = l;
+
+ BLI_ghash_insert(walker->visithash, l->f, NULL);
+ }
+
+ return f;
+}
+
diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c
new file mode 100644
index 00000000000..81e3572dec6
--- /dev/null
+++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c
@@ -0,0 +1,473 @@
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "bmesh.h"
+
+/*
+ * EDITMESH TO BMESH.C
+ *
+ * This file contains functions
+ * for converting an editmesh
+ * into a Bmesh
+ *
+*/
+
+/*
+ * EDITMESH CORNERS TO LOOPS
+ *
+ * Converts editmesh face corner data
+ * (UVs, Vert colors, ect) to N-Gon
+ * face-edge ('loop') data.
+ *
+*/
+
+static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ BMIter iter;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texpoly->tpage = texface->tpage;
+ texpoly->flag = texface->flag;
+ texpoly->transp = texface->transp;
+ texpoly->mode = texface->mode;
+ texpoly->tile = texface->tile;
+ texpoly->unwrap = texface->unwrap;
+
+ for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ mloopuv->uv[0] = texface->uv[j][0];
+ mloopuv->uv[1] = texface->uv[j][1];
+ }
+
+ }
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+ for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mloopcol->r = mcol[j].r;
+ mloopcol->g = mcol[j].g;
+ mloopcol->b = mcol[j].b;
+ mloopcol->a = mcol[j].a;
+ }
+ }
+}
+
+/*
+ * EDITVERT TO BMVert
+ *
+ * Converts an editvert to
+ * a BMVert.
+ *
+*/
+
+static BMVert *editvert_to_BMVert(BMesh *bm, BMOperator *op, EditMesh *em, EditVert *eve)
+{
+ BMVert *v = NULL;
+
+ v = BM_Make_Vert(bm, eve->co, NULL);
+ VECCOPY(v->no, eve->no);
+
+ /*transfer flags*/
+ v->head.flag = eve->h ? BM_HIDDEN : 0;
+ if(eve->f & SELECT) BM_Select_Vert(bm, v, 1);
+ v->bweight = eve->bweight;
+
+ BMO_Insert_MapPointer(bm, op, "map", eve, v);
+
+ /*Copy Custom Data*/
+ CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->head.data);
+
+ return v;
+}
+
+/*
+ * EDITEDGE TO BMEdge
+ *
+ * Converts an editedge to
+ * a BMEdge
+ *
+*/
+
+static void editedge_to_BMEdge_internal(BMesh *bm, BMOperator *op, EditMesh *em, BMEdge *e, EditEdge *eed)
+{
+ e->crease = eed->crease;
+ e->bweight = eed->bweight;
+
+ BM_Select(bm, e, eed->f & SELECT);
+ e->head.flag |= eed->seam ? BM_SEAM : 0;
+ e->head.flag |= eed->h & 1 ? BM_HIDDEN : 0;
+ e->head.flag |= eed->h & EM_FGON ? BM_FGON : 0;
+ e->head.flag |= eed->sharp ? BM_SHARP : 0;
+
+ CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->head.data);
+
+ BMO_Insert_MapPointer(bm, op, "map", eed, e);
+}
+
+static BMEdge *editedge_to_BMEdge(BMesh *bm, BMOperator *op, EditMesh *em, EditEdge *eed)
+{
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMEdge *e = NULL;
+
+ v1 = eed->v1->tmp.p;
+ v2 = eed->v2->tmp.p;
+
+ e = BM_Make_Edge(bm, v1, v2,NULL, 0);
+
+ editedge_to_BMEdge_internal(bm, op, em, e, eed);
+
+ return e;
+}
+/*
+ * EDITFACE TO BMFace
+ *
+ * Converts an editface to a BMFace.
+ * Note that this also convert per-face
+ * corner data as well.
+ *
+*/
+
+static BMFace *editface_to_BMFace(BMesh *bm, BMOperator *op, EditMesh *em, EditFace *efa, int numCol, int numTex)
+{
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMFace *f = NULL;
+ BMEdge *edar[4];
+ int len;
+
+ edar[0] = BM_Make_Edge(bm, efa->v1->tmp.p, efa->v2->tmp.p, NULL, 1);
+ edar[1] = BM_Make_Edge(bm, efa->v2->tmp.p, efa->v3->tmp.p, NULL, 1);
+ if(efa->v4){
+ edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v4->tmp.p, NULL, 1);
+ edar[3] = BM_Make_Edge(bm, efa->v4->tmp.p, efa->v1->tmp.p, NULL, 1);
+ }else{
+ edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1);
+ }
+
+ editedge_to_BMEdge_internal(bm, op, em, edar[0], efa->e1);
+ editedge_to_BMEdge_internal(bm, op, em, edar[1], efa->e2);
+ editedge_to_BMEdge_internal(bm, op, em, edar[2], efa->e3);
+ if(efa->v4)
+ editedge_to_BMEdge_internal(bm, op, em, edar[3], efa->e4);
+
+
+ if(efa->e1->fgoni) edar[0]->head.flag |= BM_FGON;
+ if(efa->e2->fgoni) edar[1]->head.flag |= BM_FGON;
+ if(efa->e3->fgoni) edar[2]->head.flag |= BM_FGON;
+ if(efa->v4 && efa->e4->fgoni) edar[3]->head.flag |= BM_FGON;
+
+ if(efa->v4) len = 4;
+ else len = 3;
+
+ /*find v1 and v2*/
+ v1 = efa->v1->tmp.p;
+ v2 = efa->v2->tmp.p;
+
+ f = BM_Make_Ngon(bm, v1, v2, edar, len, 0);
+
+ VECCOPY(f->no, efa->n);
+
+ BMO_Insert_MapPointer(bm, op, "map", efa, f);
+
+ f->head.flag = 0;
+ f->mat_nr = efa->mat_nr;
+ if(efa->f & SELECT) BM_Select_Face(bm, f, 1);
+ if (efa->flag & ME_SMOOTH) f->head.flag |= BM_SMOOTH;
+ if(efa->h) f->head.flag |= BM_HIDDEN;
+
+ if (efa == em->act_face) f->head.flag |= BM_ACTIVE;
+
+ CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->head.data);
+ editmesh_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
+
+ return f;
+}
+
+/*
+ * BMESH FGONCONVERT
+ *
+ * This function and its associated structures
+ * /helpers (fgonsort, sortfgon, fuse_fgon) are
+ * used to convert f-gons to bmesh n-gons. This
+ * is accomplished by sorting a list of fgon faces
+ * such that faces that are part of the same fgon
+ * are next to each other. These faces are then
+ * converted as is into bmesh faces and
+ * fused togather.
+ *
+ * Note that currently, there is no support for
+ * holes in faces in the bmesh structure, so
+ * f-gons with holes will only partially convert.
+ *
+*/
+
+typedef struct fgonsort {
+ unsigned long x;
+ struct EditFace *efa;
+ struct BMFace *f;
+ int done;
+}fgonsort;
+
+static int sortfgon(const void *v1, const void *v2)
+{
+ const struct fgonsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+static void fuse_fgon(BMesh *bm, BMFace *f)
+{
+ BMFace *sf;
+ BMLoop *l;
+ int done, act=0;
+
+ sf = f;
+ done = 0;
+ while(!done){
+ done = 1;
+ l = sf->loopbase;
+ do{
+ if(l->e->head.flag & BM_FGON) {
+ if (l->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
+ if (((BMLoop*)l->radial.next->data)->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
+
+ sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e);
+ if (!sf) {
+ //tesselation error
+ break;
+ }
+
+ sf->head.flag |= act;
+ if(sf){
+ done = 0;
+ break;
+ } else { /*we have to get out of here...*/
+ return;
+ }
+ }
+ l = ((BMLoop*)(l->head.next));
+ }while(l != sf->loopbase);
+ }
+}
+
+static BM_fgonconvert(BMesh *bm, BMOperator *op, EditMesh *em, int numCol, int numTex)
+{
+ EditFace *efa;
+ BMFace *f;
+ BMIter iter;
+ struct fgonsort *sortblock, *sb, *sb1;
+ int a, b, amount=0;
+
+ /*
+ for (efa=em->faces.first; efa; efa=efa->next) {
+ f = editface_to_BMFace(bm, em, efa, numCol, numTex);
+ }
+
+ for (f=bm->polys.first; f; f=f->head.next) {
+ fuse_fgon(bm, f);
+ }
+
+ return;*/
+
+ EM_fgon_flags(em);
+
+ /*zero out efa->tmp, we store fgon index here*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ efa->tmp.l = 0;
+ amount++;
+ }
+ /*go through and give each editface an fgon index*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ if(efa->e1->fgoni) efa->tmp.l = efa->e1->fgoni;
+ else if(efa->e2->fgoni) efa->tmp.l = efa->e2->fgoni;
+ else if(efa->e3->fgoni) efa->tmp.l = efa->e3->fgoni;
+ else if(efa->e4 && efa->e4->fgoni) efa->tmp.l = efa->e4->fgoni;
+ }
+
+ sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block");
+
+ for(efa = em->faces.first; efa; efa=efa->next){
+ sb->x = efa->tmp.l;
+ sb->efa = efa;
+ sb->done = 0;
+ sb++;
+ }
+
+ qsort(sortblock, amount, sizeof(fgonsort), sortfgon);
+
+ sb = sortblock;
+ for(a=0; a<amount; a++, sb++) {
+ if(sb->x && sb->done == 0){
+ /*first pass: add in faces for this fgon*/
+ for(b=a, sb1 = sb; b<amount && sb1->x == sb->x; b++, sb1++){
+ efa = sb1->efa;
+ sb1->f = editface_to_BMFace(bm, op, em, efa, numCol, numTex);
+ sb1->done = 1;
+ }
+ /*fuse fgon*/
+ fuse_fgon(bm, sb->f);
+ }
+ }
+ MEM_freeN(sortblock);
+}
+
+/*
+ * TAG WIRE EDGES
+ *
+ * Flags editedges 'f1' member
+ * if the edge has no faces.
+ *
+*/
+
+static void tag_wire_edges(EditMesh *em){
+ EditFace *efa;
+ EditEdge *eed;
+ for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1;
+ for(efa = em->faces.first; efa; efa = efa->next){
+ efa->e1->f1 = 0;
+ efa->e2->f1 = 0;
+ efa->e3->f1 = 0;
+ if(efa->e4) efa->e4->f1 = 0;
+ }
+}
+
+/*
+ * EDITMESH TO BMESH
+ *
+ * Function to convert an editmesh to a bmesh
+ * Currently all custom data as well as
+ * f-gons should be converted correctly.
+ *
+*/
+
+BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm, BMOperator *op) {
+ BMVert *v;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ BMEdge *e;
+ BMIter iter;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+
+ /*make sure to update FGon flags*/
+ EM_fgon_flags(em);
+
+ /*copy custom data layout*/
+ CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*copy face corner data*/
+ CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ /*copy over selection mode*/
+ bm->selectmode = 0;
+ if(em->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= SCE_SELECT_VERTEX;
+ if(em->selectmode & SCE_SELECT_EDGE) bm->selectmode |= SCE_SELECT_EDGE;
+ if(em->selectmode & SCE_SELECT_FACE) bm->selectmode |= SCE_SELECT_FACE;
+
+
+ /*begin editloop*/
+ //BM_Begin_Edit(bm);
+
+ /*tag wire edges*/
+ tag_wire_edges(em);
+
+ /*add verts*/
+ for(eve = em->verts.first; eve; eve = eve->next){
+ v = editvert_to_BMVert(bm, op, em, eve);
+ eve->tmp.p = v;
+ }
+ /*convert f-gons*/
+ BM_fgonconvert(bm, op, em, numCol, numTex);
+
+ /*clean up any dangling fgon flags*/
+ for (e=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); e; e=BMIter_Step(&iter)){
+ e->head.flag &= ~BM_FGON;
+ }
+
+ /*do quads + triangles*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ if(!efa->tmp.l) editface_to_BMFace(bm, op, em, efa, numCol, numTex);
+ }
+
+ /*add wire edges*/
+ for(eed = em->edges.first; eed; eed = eed->next){
+ if(eed->f1) editedge_to_BMEdge(bm, op, em, eed);
+ }
+ //BM_end_edit(bm, BM_CALC_NORM);
+ return bm;
+}
+
+void edit2bmesh_exec(BMesh *bmesh, BMOperator *op)
+{
+ editmesh_to_bmesh_intern(BMO_Get_Pnt(op, "em"), bmesh, op);
+}
+
+BMesh *editmesh_to_bmesh(EditMesh *em)
+{
+ BMOperator conv;
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512};
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(allocsize);
+
+ BMO_Init_Op(&conv, "editmesh_to_bmesh");
+ BMO_Set_Pnt(&conv, "em", em);
+ BMO_Exec_Op(bm, &conv);
+ BMO_Finish_Op(bm, &conv);
+
+ return bm;
+}
+
+BMesh *init_editmesh_to_bmesh(EditMesh *em, BMOperator *op)
+{
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(allocsize);
+
+ BMO_Init_Op(op, "editmesh_to_bmesh");
+ BMO_Set_Pnt(op, "em", em);
+
+ return bm;
+} \ No newline at end of file
diff --git a/source/blender/bmesh/intern/in-progress/BME_conversions.c b/source/blender/bmesh/intern/in-progress/BME_conversions.c
new file mode 100644
index 00000000000..d39bf689e76
--- /dev/null
+++ b/source/blender/bmesh/intern/in-progress/BME_conversions.c
@@ -0,0 +1,478 @@
+/**
+ * BME_conversions.c August 2008
+ *
+ * BM to Derived Mesh conversion functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "bmesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "bmesh_private.h"
+
+
+
+/*
+ * BMESH DERIVED MESH CONVERSION FUNCTIONS
+ *
+ * The functions in this file provides
+ * methods for converting to and from
+ * a bmesh.
+ *
+*/
+
+
+/*
+ * DMCORNERS TO LOOPS
+ *
+ * Function to convert derived mesh per-face
+ * corner data (uvs, vertex colors), to n-gon
+ * per-loop data.
+ *
+*/
+
+static void DMcorners_to_loops(BMMesh *bm, CustomData *facedata, int index, BMFace *f, int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i< numTex; i++){
+ texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+
+ texpoly->tpage = texface[index].tpage;
+ texpoly->flag = texface[index].flag;
+ texpoly->transp = texface[index].transp;
+ texpoly->mode = texface[index].mode;
+ texpoly->tile = texface[index].tile;
+ texpoly->unwrap = texface[index].unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+ mloopuv->uv[0] = texface[index].uv[j][0];
+ mloopuv->uv[1] = texface[index].uv[j][1];
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_layer_n(facedata, CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+ mloopcol->r = mcol[(index*4)+j].r;
+ mloopcol->g = mcol[(index*4)+j].g;
+ mloopcol->b = mcol[(index*4)+j].b;
+ mloopcol->a = mcol[(index*4)+j].a;
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+}
+
+/*
+ * LOOPS TO DMCORNERS
+ *
+ * Function to convert n-gon per-loop data
+ * (uvs, vertex colors, ect)to derived mesh
+ * face corner data.
+ *
+*/
+
+static void loops_to_DMcorners(BMMesh *bm, CustomData *facedata, int index, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+
+ texface[index].tpage = texpoly->tpage;
+ texface[index].flag = texpoly->flag;
+ texface[index].transp = texpoly->transp;
+ texface[index].mode = texpoly->mode;
+ texface[index].tile = texpoly->tile;
+ texface[index].unwrap = texpoly->unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+ texface[index].uv[j][0] = mloopuv->uv[0];
+ texface[index].uv[j][1] = mloopuv->uv[1];
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+
+ }
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_layer_n(facedata,CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+ mcol[(index*4) + j].r = mloopcol->r;
+ mcol[(index*4) + j].g = mloopcol->g;
+ mcol[(index*4) + j].b = mloopcol->b;
+ mcol[(index*4) + j].a = mloopcol->a;
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+}
+
+/*
+ * MVERT TO BMESHVERT
+ *
+ * Converts a MVert to a BMVert
+ *
+*/
+static BMVert *mvert_to_bmeshvert(BMMesh *bm, BMVert **vert_array, int index, MVert *mv, CustomData *data)
+{
+ BMVert *v = NULL;
+
+ v = bmesh_make_vert(bm, mv->co, NULL);
+ vert_array[index] = v;
+ if(mv->flag & SELECT) bmesh_set_flag(v, BMESH_SELECT);
+ v->bweight = mv->bweight/255.0f;
+ CustomData_to_bmesh_block(data, &bm->vdata, index, &v->data);
+
+ return v;
+}
+
+/*
+ * MEDGE TO BMESHEDGE
+ *
+ * Converts a MEdge to a BMEdge
+ *
+*/
+
+static BMEdge *medge_to_bmeshedge(BMMesh *bm, BMVert **vert_array, int index, MEdge *me, CustomData *data, Edge_Hash *edge_hash)
+{
+ BMVert *v1, *v2;
+ BMEdge *e = NULL;
+
+ v1 = vert_array[me->v1];
+ v2 = vert_array[me->v2];
+ e = bmesh_make_edge(bm, v1, v2, NULL, 0);
+ e->crease = me->crease/255.0f;
+ e->bweight = me->bweight/255.0f;
+ if(me->flag & 1) bmesh_set_flag(e, BMESH_SELECT);
+ if(me->flag & ME_SEAM) bmesh_set_flag(e, BMESH_SEAM);
+ BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
+ CustomData_to_bmesh_block(data, &bm->edata, index, &e->data);
+
+ return e;
+}
+
+/*
+ * MFACE TO BMESHFACE
+ *
+ * Converts a MFace to a BMFace.
+ * Note that this will fail on eekadoodle
+ * faces.
+ *
+*/
+
+static BMFace *mface_to_bmeshface(BMMesh *bm, BMVert **vert_array, int index, MFace *mf, CustomData *data, Edge_Hash *edge_hash)
+{
+ BMVert *v1, *v2;
+ BMEdge *edar[4];
+ BMFace *f = NULL;
+ int len;
+
+ if(mf->v4) len = 4;
+ else len = 3;
+
+ edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
+ edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
+ if(len == 4){
+ edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
+ edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
+ }
+ else
+ edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
+
+ /*find v1 and v2*/
+ v1 = vert_array[mf->v1];
+ v2 = vert_array[mf->v2];
+
+ f = bmesh_make_ngon(bm, v1, v2, edar, len, 0);
+ f->mat_nr = mf->mat_nr;
+ if(mf->flag & 1) bmesh_set_flag(f, BMESH_SELECT);
+ if(mf->flag & ME_HIDE) bmesh_set_flag(f, BMESH_HIDDEN);
+ CustomData_to_bmesh_block(data, &bm->pdata, index, &f->data);
+
+ return f;
+}
+
+/*
+ * DERIVEDMESH TO BMESH
+ *
+ * Converts a derived mesh to a bmesh.
+ *
+*/
+
+BMMesh *derivedmesh_to_bmesh(DerivedMesh *dm)
+{
+
+ BMMesh *bm;
+ BMVert **vert_array;
+ BMFace *f=NULL;
+
+ MVert *mvert, *mv;
+ MEdge *medge, *me;
+ MFace *mface, *mf;
+
+ int totface,totedge,totvert,i,len, numTex, numCol;
+ int allocsize[4] = {512,512,2048,512};
+
+ EdgeHash *edge_hash = BLI_edgehash_new();
+
+ /*allocate a new bmesh*/
+ bm = bmesh_make_mesh(allocsize);
+
+ /*copy custom data layout*/
+ CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*copy face corner data*/
+ CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
+ /*initialize memory pools*/
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+ mvert = dm->getVertArray(dm);
+ medge = dm->getEdgeArray(dm);
+ mface = dm->getFaceArray(dm);
+
+ vert_array = MEM_mallocN(sizeof(BMVert *)* totvert,"derivedmesh to bmesh vertex pointer array");
+
+ bmesh_begin_edit(bm);
+ /*add verts*/
+ for(i=0, mv = mvert; i < totvert; i++, mv++)
+ mvert_to_bmeshvert(bm, vert_array, i, mv, &dm->vertData);
+
+ /*add edges*/
+ for(i=0, me = medge; i < totedge; i++, me++)
+ medge_to_bmeshedge(bm, vert_array, i, me, &dm->edgeData, edge_hash);
+
+ /*add faces.*/
+ for(i=0, mf = mface; i < totface; i++, mf++){
+ f = mface_to_bmeshface(bm, vert_array, mf, &dm->faceData, edge_hash);
+ if(f) DMcorners_to_loops(bm, &dm->faceData, i, f, numCol, numTex);
+ }
+
+ bmesh_end__edit(bm);
+ BLI_edgehash_free(edge_hash, NULL);
+ MEM_freeN(vert_array);
+ return bm;
+}
+
+static void bmeshvert_to_mvert(BMMesh *bm, BMVert *v, MVert *mv, int index, CustomData *data)
+{
+ VECCOPY(mv->co,v->co);
+ if(bmesh_test_flag(v, BMESH_SELECT)) mv->flag |= 1;
+ if(bmesh_test_flag(v, BMESH_HIDDEN)) mv->flag |= ME_HIDE;
+ mv->bweight = (char)(255.0*v1->bweight);
+ CustomData_from_bmesh_block(&bm->vdata, data, &v1->data, index);
+}
+
+static int bmeshedge_to_medge(BMMesh *bm, BMEdge *e, MEdge *me, int index, CustomData *data)
+{
+ if(e->head.eflag2){
+ if(e->v1->head.eflag1 < e->v2->head.eflag1){
+ me->v1 = e->v1->head.eflag1;
+ me->v2 = e->v2->head.eflag1;
+ }
+ else{
+ me->v1 = e->v2->head.eflag1;
+ me->v2 = e->v1->eflag1;
+ }
+
+ me->crease = (char)(255.0*e->crease);
+ me->bweight = (char)(255.0*e->bweight);
+ if(bmesh_test_flag(e, BMESH_SELECT)) me->flag |= 1;
+ if(bmesh_test_flag(e, BMESH_HIDDEN)) me->flag |= ME_HIDE;
+ CustomData_from_bmesh_block(&bm->edata, data, &e->data, index);
+ return 1;
+ }
+ return 0;
+}
+
+static int bmeshface_to_mface(BMMesh *bm, BMFace *f, MFace *mf, int index, CustomData *data)
+{
+ if(f->len==3 || f->len==4){
+ mf->v1 = f->loopbase->v->head.eflag1;
+ mf->v2 = f->loopbase->next->v->head.eflag1;
+ mf->v3 = f->loopbase->next->next->v->head.eflag1;
+ if(len == 4){
+ mf->v4 = f->loopbase->prev->v->head.eflag1;
+ }
+ /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
+ if(mf->v3 == 0 || (f->len == 4 && mf->v4 == 0)){
+ test_index_face(mf, NULL, index, f->len);
+ }
+ mf->mat_nr = (unsigned char)f->mat_nr;
+ if(bmesh_test_flag(f, BMESH_SELECT)) mf->flag |= 1;
+ if(bmesh_test_flag(f, BMESH_HIDDEN)) mf->flag |= ME_HIDE;
+ CustomData_from_bmesh_block(&bm->pdata, data, &f->data, index);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * BMESH TO DERIVEDMESH
+ *
+ * Converts a bmesh to a derived mesh.
+ *
+*/
+
+DerivedMesh *bmesh_to_derivedmesh(BMMesh *bm, DerivedMesh *dm)
+{
+ MFace *mface = NULL, *mf = NULL;
+ MEdge *medge = NULL, *me = NULL;
+ MVert *mvert = NULL, *mv = NULL;
+ DerivedMesh *result = NULL;
+
+ BMVert *v=NULL;
+ BMEdge *e=NULL, *oe=NULL;
+ BMFace *f=NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ int totface = 0,totedge = 0,totvert = 0,i = 0, numTex, numCol;
+
+ EdgeHash *edge_hash = BLI_edgehash_new();
+
+ /*get element counts*/
+ totvert = bmesh_count_element(bm, BMESH_VERT);
+
+ /*store element indices. Note that the abuse of eflag here should NOT be duplicated!*/
+ for(i=0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++)
+ v->head.eflag1 = i;
+
+ /*we cannot have double edges in a derived mesh!*/
+ for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
+ oe = BLI_edgehash_lookup(edge_hash,e->v1->head.eflag1, e->v2->head.eflag1);
+ if(!oe){
+ totedge++;
+ BLI_edgehash_insert(edge_hash,e->v1->head.eflag1,e->v2->head.eflag1,e);
+ e->head.eflag2 = 1;
+ }
+ else{
+ e->head.eflag2 = 0;
+ }
+ }
+
+ /*count quads and tris*/
+ for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){
+ if(f->len == 3 || f->len == 4) totface++;
+ }
+
+ /*Allocate derivedmesh and copy custom data*/
+ result = CDDM_from_template(dm,totvert,totedge,totface);
+ CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
+ CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
+ CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
+ CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ /*Make Verts*/
+ mvert = CDDM_get_verts(result);
+ for(i = 0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++, mv++){
+ bmeshvert_to_mvert(bm,v,mv,i,&result->vertData);
+ }
+
+ /*Make Edges*/
+ medge = CDDM_get_edges(result);
+ i=0;
+ for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
+ me = &medge[i];
+ if(bmeshedge_to_medge(bm, e, me, i, &result->edgeData){
+ me++;
+ i++;
+ }
+ }
+ /*Make Faces*/
+ if(totface){
+ mface = CDDM_get_faces(result);
+ i=0;
+ for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){
+ mf = &mface[i];
+ if(bmeshface_to_mface(bm, f, mf, i, &result->faceData)){
+ loops_to_DMcorners(bm, &result->faceData, i, f, numCol, numTex);
+ i++;
+ }
+ }
+ }
+ BLI_edgehash_free(edge_hash, NULL);
+ return result;
+}
diff --git a/source/blender/bmesh/operators/bmesh_dupeops.c b/source/blender/bmesh/operators/bmesh_dupeops.c
new file mode 100644
index 00000000000..b5c327bc24c
--- /dev/null
+++ b/source/blender/bmesh/operators/bmesh_dupeops.c
@@ -0,0 +1,570 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+/*local flag defines*/
+#define DUPE_INPUT 1 /*input from operator*/
+#define DUPE_NEW 2
+#define DUPE_DONE 4
+#define DUPE_MAPPED 8
+
+/*
+ * COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*Create a new vertex*/
+ target_vertex = BM_Make_Vert(target_mesh, source_vertex->co, NULL);
+
+ /*Insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*Copy attributes*/
+ BM_Copy_Attributes(source_mesh, target_mesh, source_vertex, target_vertex);
+
+ /*Set internal op flags*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
+
+ return target_vertex;
+}
+
+/*
+ * COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh,
+ BMEdge *source_edge, BMesh *target_mesh,
+ GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+ BMFace *face;
+ BMIter fiter;
+ int rlen;
+
+ /*see if any of the neighboring faces are
+ not being duplicated. in that case,
+ add it to the new/old map.*/
+ rlen = 0;
+ for (face=BMIter_New(&fiter,source_mesh, BM_FACES_OF_EDGE,source_edge);
+ face; face=BMIter_Step(&fiter)) {
+ if (BMO_TestFlag(source_mesh, face, DUPE_INPUT)) {
+ rlen++;
+ }
+ }
+
+ /*Lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*Create a new edge*/
+ target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*add to new/old edge map if necassary*/
+ if (rlen < 2) {
+ /*not sure what non-manifold cases of greater then three
+ radial should do.*/
+ BMO_Insert_MapPointer(source_mesh,op, "boundarymap",
+ source_edge, target_edge);
+ }
+
+ /*Insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*Copy attributes*/
+ BM_Copy_Attributes(source_mesh, target_mesh, source_edge, target_edge);
+
+ /*Set internal op flags*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
+
+ return target_edge;
+}
+
+/*
+ * COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+static BMFace *copy_face(BMOperator *op, BMesh *source_mesh,
+ BMFace *source_face, BMesh *target_mesh,
+ BMEdge **edar, GHash *vhash, GHash *ehash)
+{
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ BMIter iter, iter2;
+ int i;
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, BMIter_New(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
+ target_vert2 = BLI_ghash_lookup(vhash, BMIter_Step(&iter));
+
+ /*lookup edges*/
+ for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face);
+ source_loop; source_loop=BMIter_Step(&iter), i++) {
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ }
+
+ /*create new face*/
+ target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
+ BMO_Insert_MapPointer(source_mesh, op,
+ "facemap", source_face, target_face);
+ BMO_Insert_MapPointer(source_mesh, op,
+ "facemap", target_face, source_face);
+
+ BM_Copy_Attributes(source_mesh, target_mesh, source_face, target_face);
+
+ /*mark the face for output*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
+
+ /*copy per-loop custom data*/
+ for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face),
+ target_loop=BMIter_New(&iter2, target_mesh, BM_LOOPS_OF_FACE, target_face);
+ source_loop && target_loop; source_loop=BMIter_Step(&iter), target_loop=BMIter_Step(&iter2),
+ i++) {
+ BM_Copy_Attributes(source_mesh, target_mesh, source_loop, target_loop);
+ }
+
+
+ return target_face;
+}
+ /*
+ * COPY MESH
+ *
+ * Internal Copy function.
+*/
+
+static void copy_mesh(BMOperator *op, BMesh *source, BMesh *target)
+{
+
+ BMVert *v = NULL, *v2;
+ BMEdge *e = NULL, **edar = NULL;
+ BMLoop *l = NULL;
+ BMFace *f = NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ /*initialize edge pointer array*/
+ for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f = BMIter_Step(&faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+
+ for(v = BMIter_New(&verts, source, BM_VERTS_OF_MESH, source); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
+ BMIter iter;
+ int iso = 1;
+
+ v2 = copy_vertex(source, v, target, vhash);
+
+ BM_ITER(f, &iter, source, BM_FACES_OF_VERT, v) {
+ if (BMO_TestFlag(source, f, DUPE_INPUT)) {
+ iso = 0;
+ break;
+ }
+ }
+
+ if (iso) {
+ BM_ITER(e, &iter, source, BM_EDGES_OF_VERT, v) {
+ if (BMO_TestFlag(source, e, DUPE_INPUT)) {
+ iso = 0;
+ break;
+ }
+ }
+ }
+
+ if (iso)
+ BMO_Insert_MapPointer(source, op, "isovertmap", v, v2);
+
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMIter_New(&edges, source, BM_EDGES_OF_MESH, source); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
+ /*make sure that verts are copied*/
+ if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE)) {
+ copy_vertex(source, e->v1, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
+ }
+ if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE)) {
+ copy_vertex(source, e->v2, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
+ }
+ /*now copy the actual edge*/
+ copy_edge(op, source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f= BMIter_Step(&faces)){
+ if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
+ /*vertex pass*/
+ for(v = BMIter_New(&verts, source, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts)){
+ if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){
+ copy_vertex(source,v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*edge pass*/
+ for(e = BMIter_New(&edges, source, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges)){
+ if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
+ copy_edge(op, source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+ copy_face(op, source, f, target, edar, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
+ }
+ }
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ if(edar)
+ MEM_freeN(edar);
+}
+
+/*
+BMesh *bmesh_make_mesh_from_mesh(BMesh *bm, int allocsize[4])
+{
+ BMesh *target = NULL;
+ target = bmesh_make_mesh(allocsize);
+
+
+ CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+
+ CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
+
+ bmesh_begin_edit(bm);
+ bmesh_begin_edit(target);
+
+ bmesh_copy_mesh(bm, target, 0);
+
+ bmesh_end_edit(bm);
+ bmesh_end_edit(target);
+
+ return target;
+
+}
+*/
+
+/*
+ * Duplicate Operator
+ *
+ * Duplicates verts, edges and faces of a mesh.
+ *
+ * INPUT SLOTS:
+ *
+ * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be duplicated
+ * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be duplicated
+ * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be duplicated
+ *
+ * OUTPUT SLOTS:
+ *
+ * BMOP_DUPE_VORIGINAL: Buffer containing pointers to the original mesh vertices
+ * BMOP_DUPE_EORIGINAL: Buffer containing pointers to the original mesh edges
+ * BMOP_DUPE_FORIGINAL: Buffer containing pointers to the original mesh faces
+ * BMOP_DUPE_VNEW: Buffer containing pointers to the new mesh vertices
+ * BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
+ * BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
+ *
+*/
+
+void dupeop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *dupeop = op;
+
+ /*flag input*/
+ BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT);
+ /*use the internal copy function*/
+ copy_mesh(dupeop, bm, bm);
+
+ /*Output*/
+ /*First copy the input buffers to output buffers - original data*/
+ BMO_CopySlot(dupeop, dupeop, "geom", "origout");
+
+ /*Now alloc the new output buffers*/
+ BMO_Flag_To_Slot(bm, dupeop, "newout", DUPE_NEW, BM_ALL);
+}
+
+/*executes the duplicate operation, feeding elements of
+ type flag etypeflag and header flag flag to it. note,
+ to get more useful information (such as the mapping from
+ original to new elements) you should run the dupe op manually.*/
+void BMOP_DupeFromFlag(BMesh *bm, int etypeflag, int flag)
+{
+ BMOperator dupeop;
+
+ BMO_Init_Op(&dupeop, "dupe");
+ BMO_HeaderFlag_To_Slot(bm, &dupeop, "geom", flag, etypeflag);
+
+ BMO_Exec_Op(bm, &dupeop);
+ BMO_Finish_Op(bm, &dupeop);
+}
+
+/*
+ * Split Operator
+ *
+ * Duplicates verts, edges and faces of a mesh but also deletes the originals.
+ *
+ * INPUT SLOTS:
+ *
+ * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be split
+ * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be split
+ * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be split
+ *
+ * OUTPUT SLOTS:
+ *
+ * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
+ * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
+ * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
+ *
+*/
+
+#define SPLIT_INPUT 1
+void splitop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *splitop = op;
+ BMOperator dupeop;
+ BMOperator delop;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter, iter2;
+ int found;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, "dupe");
+ BMO_Init_Op(&delop, "del");
+
+ BMO_CopySlot(splitop, &dupeop, "geom", "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT);
+
+ /*make sure to remove edges and verts we don't need.*/
+ for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
+ found = 0;
+ f = BMIter_New(&iter2, bm, BM_FACES_OF_EDGE, e);
+ for (; f; f=BMIter_Step(&iter2)) {
+ if (!BMO_TestFlag(bm, f, SPLIT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) BMO_SetFlag(bm, e, SPLIT_INPUT);
+ }
+
+ for (v= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);v;v=BMIter_Step(&iter)) {
+ found = 0;
+ e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, v);
+ for (; e; e=BMIter_Step(&iter2)) {
+ if (!BMO_TestFlag(bm, e, SPLIT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) BMO_SetFlag(bm, v, SPLIT_INPUT);
+
+ }
+
+ /*connect outputs of dupe to delete, exluding keep geometry*/
+ BMO_Set_Int(&delop, "context", DEL_FACES);
+ BMO_Flag_To_Slot(bm, &delop, "geom", SPLIT_INPUT, BM_ALL);
+
+ BMO_Exec_Op(bm, &delop);
+
+ /*now we make our outputs by copying the dupe outputs*/
+ BMO_CopySlot(&dupeop, splitop, "newout", "geom");
+ BMO_CopySlot(&dupeop, splitop, "boundarymap",
+ "boundarymap");
+ BMO_CopySlot(&dupeop, splitop, "isovertmap",
+ "isovertmap");
+
+ /*cleanup*/
+ BMO_Finish_Op(bm, &delop);
+ BMO_Finish_Op(bm, &dupeop);
+}
+
+#define DEL_INPUT 1
+#define DEL_WIREVERT 2
+
+static void delete_verts(BMesh *bm);
+static void delete_context(BMesh *bm, int type);
+
+void delop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *delop = op;
+
+ /*Mark Buffers*/
+ BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT);
+
+ delete_context(bm, BMO_Get_Int(op, "context"));
+}
+
+static void delete_verts(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT)) {
+ /*Visit edges*/
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ /*Visit faces*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_VERT, v); f; f = BMIter_Step(&faces))
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ }
+ }
+
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+}
+
+static void delete_edges(BMesh *bm){
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter edges;
+ BMIter faces;
+
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)) {
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BMIter_Step(&faces)){
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ }
+ }
+ }
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+}
+
+/*you need to make remove tagged verts/edges/faces
+ api functions that take a filter callback.....
+ and this new filter type will be for opstack flags.
+ This is because the BM_remove_taggedXXX functions bypass iterator API.
+ -Ops dont care about 'UI' considerations like selection state, hide state, ect. If you want to work on unhidden selections for instance,
+ copy output from a 'select context' operator to another operator....
+*/
+
+/*Break this into smaller functions*/
+
+static void delete_context(BMesh *bm, int type){
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ if(type == DEL_VERTS) delete_verts(bm);
+ else if(type == DEL_EDGES){
+ /*flush down to verts*/
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
+ BMO_SetFlag(bm, (BMHeader*)(e->v1), DEL_INPUT);
+ BMO_SetFlag(bm, (BMHeader*)(e->v2), DEL_INPUT);
+ }
+ }
+ delete_edges(bm);
+ /*remove loose vertices*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT) && (!(v->edge)))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_WIREVERT);
+ }
+ BM_remove_tagged_verts(bm, DEL_WIREVERT);
+ }
+ else if(type == DEL_EDGESFACES) delete_edges(bm);
+ else if(type == DEL_ONLYFACES) BM_remove_tagged_faces(bm, DEL_INPUT);
+ else if (type == DEL_ONLYTAGGED) {
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ } else if(type == DEL_FACES){
+ /*go through and mark all edges and all verts of all faces for delete*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ if(BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
+ }
+ }
+ /*now go through and mark all remaining faces all edges for keeping.*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges))
+ BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts))
+ BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
+ }
+ }
+ /*now delete marked faces*/
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ /*delete marked edges*/
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ /*remove loose vertices*/
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ }
+ /*does this option even belong in here?*/
+ else if(type == DEL_ALL){
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
+
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ }
+} \ No newline at end of file
diff --git a/source/blender/bmesh/operators/connectops.c b/source/blender/bmesh/operators/connectops.c
new file mode 100644
index 00000000000..a8f5899fd65
--- /dev/null
+++ b/source/blender/bmesh/operators/connectops.c
@@ -0,0 +1,126 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define VERT_INPUT 1
+#define EDGE_OUT 1
+#define FACE_NEW 2
+
+void connectverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter, liter;
+ BMFace *f, *nf;
+ BMLoop **loops = NULL, *lastl = NULL;
+ V_DECLARE(loops);
+ BMLoop *l, *nl;
+ BMVert *v1, *v2, **verts = NULL;
+ V_DECLARE(verts);
+ int i;
+
+ BMO_Flag_Buffer(bm, op, "verts", VERT_INPUT);
+
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
+ V_RESET(loops);
+ V_RESET(verts);
+
+ if (BMO_TestFlag(bm, f, FACE_NEW)) continue;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ v1 = v2 = NULL;
+ lastl = NULL;
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BMO_TestFlag(bm, l->v, VERT_INPUT)) {
+ if (!lastl) {
+ lastl = l;
+ continue;
+ }
+
+ if (lastl != l->head.prev && lastl !=
+ l->head.next)
+ {
+ V_GROW(loops);
+ loops[V_COUNT(loops)-1] = lastl;
+
+ V_GROW(loops);
+ loops[V_COUNT(loops)-1] = l;
+
+ }
+ lastl = l;
+ }
+ }
+
+ if (V_COUNT(loops) == 0) continue;
+
+ if (V_COUNT(loops) > 2) {
+ V_GROW(loops);
+ loops[V_COUNT(loops)-1] = loops[V_COUNT(loops)-2];
+
+ V_GROW(loops);
+ loops[V_COUNT(loops)-1] = loops[0];
+ }
+
+ BM_LegalSplits(bm, f, loops, V_COUNT(loops)/2);
+
+ for (i=0; i<V_COUNT(loops)/2; i++) {
+ if (loops[i*2]==NULL) continue;
+
+ V_GROW(verts);
+ verts[V_COUNT(verts)-1] = loops[i*2]->v;
+
+ V_GROW(verts);
+ verts[V_COUNT(verts)-1] = loops[i*2+1]->v;
+ }
+
+ for (i=0; i<V_COUNT(verts)/2; i++) {
+ nf = BM_Split_Face(bm, f, verts[i*2],
+ verts[i*2+1], &nl, NULL);
+ f = nf;
+
+ if (!nl || !nf) {
+ BMO_RaiseError(bm, op,
+ BMERR_CONNECTVERT_FAILED, NULL);
+ V_FREE(loops);
+ return;;;
+ }
+ BMO_SetFlag(bm, nf, FACE_NEW);
+ BMO_SetFlag(bm, nl->e, EDGE_OUT);
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_OUT, BM_EDGE);
+
+ V_FREE(loops);
+ V_FREE(verts);
+}
+
+int BM_ConnectVerts(EditMesh *em, int flag)
+{
+ EditMesh *em2;
+ BMesh *bm = editmesh_to_bmesh(em);
+ BMOperator op;
+
+ BMO_Init_Op(&op, "connectverts");
+ BMO_HeaderFlag_To_Slot(bm, &op, "verts", flag, BM_VERT);
+ BMO_Exec_Op(bm, &op);
+ BMO_Finish_Op(bm, &op);
+
+ if (BMO_GetSlot(&op, "edgeout")->len > 0 &&
+ BMO_GetError(bm, NULL, NULL)==0)
+ {
+ em2 = bmesh_to_editmesh(bm);
+ set_editMesh(em, em2);
+ MEM_freeN(em2);
+
+ return 1;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/source/blender/bmesh/operators/createops.c b/source/blender/bmesh/operators/createops.c
new file mode 100644
index 00000000000..29ec08868ec
--- /dev/null
+++ b/source/blender/bmesh/operators/createops.c
@@ -0,0 +1,156 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#define ELE_NEW 1
+#define ELE_OUT 2
+
+void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
+{
+ /*unimplemented, need to think on how to do this. probably are graph
+ theory stuff that could help with this problem.*/
+}
+
+/* evaluate if entire quad is a proper convex quad */
+static int convex(float *v1, float *v2, float *v3, float *v4)
+{
+ float nor[3], nor1[3], nor2[3], vec[4][2];
+
+ /* define projection, do both trias apart, quad is undefined! */
+ CalcNormFloat(v1, v2, v3, nor1);
+ CalcNormFloat(v1, v3, v4, nor2);
+ nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
+ nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
+ nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
+
+ if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[1];
+ vec[1][0]= v2[0]; vec[1][1]= v2[1];
+ vec[2][0]= v3[0]; vec[2][1]= v3[1];
+ vec[3][0]= v4[0]; vec[3][1]= v4[1];
+ }
+ else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[2];
+ vec[1][0]= v2[0]; vec[1][1]= v2[2];
+ vec[2][0]= v3[0]; vec[2][1]= v3[2];
+ vec[3][0]= v4[0]; vec[3][1]= v4[2];
+ }
+ else {
+ vec[0][0]= v1[1]; vec[0][1]= v1[2];
+ vec[1][0]= v2[1]; vec[1][1]= v2[2];
+ vec[2][0]= v3[1]; vec[2][1]= v3[2];
+ vec[3][0]= v4[1]; vec[3][1]= v4[2];
+ }
+
+ /* linetests, the 2 diagonals have to instersect to be convex */
+ if( IsectLL2Df(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
+ return 0;
+}
+
+/*this is essentially new fkey*/
+void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator op2;
+ BMOIter oiter;
+ BMIter iter, liter;
+ BMHeader *h;
+ BMVert *v, *verts[4];
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+ int totv=0, tote=0, totf=0, amount;
+
+ /*count number of each element type we were passed*/
+ BMO_ITER(h, &oiter, bm, op, "geom", BM_VERT|BM_EDGE|BM_FACE) {
+ switch (h->type) {
+ case BM_VERT: totv++; break;
+ case BM_EDGE: tote++; break;
+ case BM_FACE: totf++; break;
+ }
+
+ BMO_SetFlag(bm, h, ELE_NEW);
+ }
+
+ /*first call dissolve faces*/
+ BMO_InitOpf(bm, &op2, "dissolvefaces faces=%ff", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+ BMO_ITER(f, &oiter, bm, &op2, "regionout", BM_FACE) {
+ BMO_SetFlag(bm, f, ELE_OUT);
+
+ /*unflag verts associated with dissolved faces*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMO_ClearFlag(bm, l->v, ELE_NEW);
+ }
+ }
+ BMO_Finish_Op(bm, &op2);
+
+ /*then call edgenet create, which may still be unimplemented, heh*/
+ BMO_InitOpf(bm, &op2, "edgenet_fill edges=%fe", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+ BMO_ITER(f, &oiter, bm, &op2, "faceout", BM_FACE) {
+ BMO_SetFlag(bm, f, ELE_OUT);
+
+ /*unflag verts associated with the output faces*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMO_ClearFlag(bm, l->v, ELE_NEW);
+ }
+ }
+ BMO_Finish_Op(bm, &op2);
+
+ /*now, count how many verts we have*/
+ amount = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, v, ELE_NEW)) {
+ verts[amount] = v;
+ amount++;
+
+ if (amount > 4) break;
+ }
+ }
+
+ if (amount == 2) {
+ /*create edge*/
+ e = BM_Make_Edge(bm, verts[0], verts[1], NULL, 1);
+ BMO_SetFlag(bm, e, ELE_OUT);
+ } else if (amount == 3) {
+ /*create triangle*/
+ BM_Make_QuadTri(bm, verts[0], verts[1], verts[2], NULL, NULL, 1);
+ } else if (amount == 4) {
+ f = NULL;
+
+ /* the order of vertices can be anything, 6 cases to check */
+ if( convex(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[1], verts[2], verts[3], NULL, 1);
+ }
+ else if( convex(verts[0]->co, verts[2]->co, verts[3]->co, verts[1]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[2], verts[3], verts[1], NULL, 1);
+ }
+ else if( convex(verts[0]->co, verts[2]->co, verts[1]->co, verts[3]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[2], verts[1], verts[3], NULL, 1);
+ }
+ else if( convex(verts[0]->co, verts[1]->co, verts[3]->co, verts[2]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[1], verts[3], verts[2], NULL, 1);
+ }
+ else if( convex(verts[0]->co, verts[3]->co, verts[2]->co, verts[1]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[3], verts[2], verts[1], NULL, 1);
+ }
+ else if( convex(verts[0]->co, verts[3]->co, verts[1]->co, verts[2]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[3], verts[1], verts[2], NULL, 1);
+ }
+ else {
+ printf("cannot find nice quad from concave set of vertices\n");
+ }
+
+ if (f) BMO_SetFlag(bm, f, ELE_OUT);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "faceout", ELE_OUT, BM_FACE);
+}
diff --git a/source/blender/bmesh/operators/dissolveops.c b/source/blender/bmesh/operators/dissolveops.c
new file mode 100644
index 00000000000..997a24d0507
--- /dev/null
+++ b/source/blender/bmesh/operators/dissolveops.c
@@ -0,0 +1,430 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FACE_MARK 1
+#define FACE_ORIG 2
+#define FACE_NEW 4
+#define EDGE_MARK 1
+
+#define VERT_MARK 1
+
+static int check_hole_in_region(BMesh *bm, BMFace *f) {
+ BMWalker regwalker;
+ BMIter liter2;
+ BMLoop *l2, *l3;
+ BMFace *f2;
+
+ /*checks if there are any unmarked boundary edges in the face region*/
+
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK);
+ f2 = BMW_Begin(&regwalker, f);
+ for (; f2; f2=BMW_Step(&regwalker)) {
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ for (; l2; l2=BMIter_Step(&liter2)) {
+ l3 = bmesh_radial_nextloop(l2);
+ if (BMO_TestFlag(bm, l3->f, FACE_MARK)
+ != BMO_TestFlag(bm, l2->f, FACE_MARK))
+ {
+ if (!BMO_TestFlag(bm, l2->e, EDGE_MARK)) {
+ return 0;
+ }
+ }
+ }
+ }
+ BMW_End(&regwalker);
+
+ return 1;
+}
+
+void dissolvefaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter oiter;
+ BMIter liter, liter2, liter3;
+ BMLoop *l, *l2, *l3;
+ BMFace *f, *f2, *nf = NULL;
+ V_DECLARE(region);
+ V_DECLARE(regions);
+ BMLoop ***regions = NULL;
+ BMLoop **region = NULL;
+ BMWalker regwalker;
+ int i, j, fcopied;
+
+ BMO_Flag_Buffer(bm, op, "faces", FACE_MARK);
+
+ /*collect regions*/
+ f = BMO_IterNew(&oiter, bm, op, "faces", BM_FACE);
+ for (; f; f=BMO_IterStep(&oiter)) {
+ if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
+
+ V_RESET(region);
+ region = NULL; /*forces different allocation*/
+
+ /*yay, walk!*/
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK);
+ f2 = BMW_Begin(&regwalker, f);
+ for (; f2; f2=BMW_Step(&regwalker)) {
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ for (; l2; l2=BMIter_Step(&liter2)) {
+ l3 = BMIter_New(&liter3, bm, BM_LOOPS_OF_LOOP, l2);
+ for (; l3; l3=BMIter_Step(&liter3)) {
+ if (!BMO_TestFlag(bm, l3->f, FACE_MARK)) {
+ V_GROW(region);
+ region[V_COUNT(region)-1] = l2;
+ break;
+ }
+ }
+ if (bmesh_radial_nextloop(l2) == l2) {
+ V_GROW(region);
+ region[V_COUNT(region)-1] = l2;
+ }
+ }
+ }
+ BMW_End(&regwalker);
+
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK);
+ f2 = BMW_Begin(&regwalker, f);
+ for (; f2; f2=BMW_Step(&regwalker)) {
+ BMO_ClearFlag(bm, f2, FACE_MARK);
+ BMO_SetFlag(bm, f2, FACE_ORIG);
+ }
+
+ BMW_End(&regwalker);
+
+ if (BMO_HasError(bm)) {
+ BMO_ClearStack(bm);
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
+ goto cleanup;
+ }
+
+ V_GROW(region);
+ V_GROW(regions);
+ regions[V_COUNT(regions)-1] = region;
+ region[V_COUNT(region)-1] = NULL;
+ }
+
+ for (i=0; i<V_COUNT(regions); i++) {
+ BMEdge **edges = NULL;
+ V_DECLARE(edges);
+
+ region = regions[i];
+ for (j=0; region[j]; j++) {
+ V_GROW(edges);
+ edges[V_COUNT(edges)-1] = region[j]->e;
+ }
+
+ if (!region[0]) {
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
+ "Could not find boundary of dissolve region");
+ goto cleanup;
+ }
+
+ if (region[0]->e->v1 == region[0]->v)
+ f= BM_Make_Ngon(bm, region[0]->e->v1, region[0]->e->v2, edges, j, 1);
+ else
+ f= BM_Make_Ngon(bm, region[0]->e->v2, region[0]->e->v1, edges, j, 1);
+
+ V_FREE(edges);
+
+ if (!f) {
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
+ "Could not create merged face");
+ goto cleanup;
+ }
+
+ /*if making the new face failed (e.g. overlapping test)
+ unmark the original faces for deletion.*/
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ BMO_SetFlag(bm, f, FACE_NEW);
+
+ fcopied = 0;
+ l=BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ /*ensure winding is identical*/
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_LOOP, l);
+ for (; l2; l2=BMIter_Step(&liter2)) {
+ if (BMO_TestFlag(bm, l2->f, FACE_ORIG)) {
+ if (l2->v != l->v)
+ bmesh_loop_reverse(bm, l2->f);
+ break;
+ }
+ }
+
+ /*copy over attributes*/
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_LOOP, l);
+ for (; l2; l2=BMIter_Step(&liter2)) {
+ if (BMO_TestFlag(bm, l2->f, FACE_ORIG)) {
+ if (!fcopied) {
+ BM_Copy_Attributes(bm, bm, l2->f, f);
+ fcopied = 1;
+ }
+ BM_Copy_Attributes(bm, bm, l2, l);
+ break;
+ }
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%ff context=%d", FACE_ORIG, DEL_FACES);
+ if (BMO_HasError(bm)) goto cleanup;
+
+ BMO_Flag_To_Slot(bm, op, "regionout", FACE_NEW, BM_FACE);
+
+cleanup:
+ /*free/cleanup*/
+ for (i=0; i<V_COUNT(regions); i++) {
+ if (regions[i]) V_FREE(regions[i]);
+ }
+
+ V_FREE(regions);
+}
+
+/*almost identical to dissolve edge, except it cleans up vertices*/
+void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator fop;
+ BMOIter oiter;
+ BMIter iter;
+ BMVert *v, **verts = NULL;
+ V_DECLARE(verts);
+ BMEdge *e;
+ BMFace *f;
+ int i;
+
+ BMO_ITER(e, &oiter, bm, op, "edges", BM_EDGE) {
+ if (BM_Edge_FaceCount(e) == 2) {
+ BMO_SetFlag(bm, e->v1, VERT_MARK);
+ BMO_SetFlag(bm, e->v2, VERT_MARK);
+
+ BM_Join_Faces(bm, e->loop->f,
+ ((BMLoop*)e->loop->radial.next->data)->f,
+ e);
+ }
+ }
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, v, VERT_MARK) &&
+ BM_Vert_EdgeCount(v) == 2)
+ {
+ V_GROW(verts);
+ verts[V_COUNT(verts)-1] = v;
+ }
+ }
+
+ /*clean up extreneous 2-valence vertices*/
+ for (i=0; i<V_COUNT(verts); i++) {
+ BM_Collapse_Vert(bm, verts[i]->edge, verts[i], 1.0);
+ }
+
+ V_FREE(verts);
+
+ //BMO_InitOpf(bm, &fop, "dissolvefaces faces=%ff", FACE_MARK);
+ //BMO_Exec_Op(bm, &fop);
+
+ //BMO_CopySlot(op, &fop, "regionout", "regionout");
+
+ //BMO_Finish_Op(bm, &fop);
+}
+
+
+void dissolveedges_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator fop;
+ BMOIter oiter;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ int i;
+
+ BMO_ITER(e, &oiter, bm, op, "edges", BM_EDGE) {
+ if (BM_Edge_FaceCount(e) == 2) {
+ BMO_SetFlag(bm, e->v1, VERT_MARK);
+ BMO_SetFlag(bm, e->v2, VERT_MARK);
+
+ BM_Join_Faces(bm, e->loop->f,
+ ((BMLoop*)e->loop->radial.next->data)->f,
+ e);
+ }
+ }
+
+ //BMO_InitOpf(bm, &fop, "dissolvefaces faces=%ff", FACE_MARK);
+ //BMO_Exec_Op(bm, &fop);
+
+ //BMO_CopySlot(op, &fop, "regionout", "regionout");
+
+ //BMO_Finish_Op(bm, &fop);
+}
+
+static int test_extra_verts(BMesh *bm, BMVert *v)
+{
+ BMIter iter, liter, iter2, iter3;
+ BMFace *f, *f2;
+ BMLoop *l;
+ BMEdge *e;
+ int found;
+
+ /*test faces around verts for verts that would be wronly killed
+ by dissolve faces.*/
+ f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&iter)) {
+ l=BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (!BMO_TestFlag(bm, l->v, VERT_MARK)) {
+ /*if an edge around a vert is a boundary edge,
+ then dissolve faces won't destroy it.
+ also if it forms a boundary with one
+ of the face regions*/
+ found = 0;
+ e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, l->v);
+ for (; e; e=BMIter_Step(&iter2)) {
+ if (BM_Edge_FaceCount(e)==1) found = 1;
+ f2 = BMIter_New(&iter3, bm, BM_FACES_OF_EDGE, e);
+ for (; f2; f2=BMIter_Step(&iter3)) {
+ if (!BMO_TestFlag(bm, f2, FACE_MARK)) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) break;
+ }
+ if (!found) return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+void dissolveverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMOpSlot *vinput;
+ BMIter iter, fiter;
+ BMVert *v;
+ BMFace *f;
+ int i;
+
+ vinput = BMO_GetSlot(op, "verts");
+ BMO_Flag_Buffer(bm, op, "verts", VERT_MARK);
+
+ for (v=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ BMO_SetFlag(bm, f, FACE_ORIG);
+ BMO_SetFlag(bm, f, FACE_MARK);
+ }
+
+ /*check if our additions to the input to face dissolve
+ will destroy nonmarked vertices.*/
+ if (!test_extra_verts(bm, v)) {
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ if (BMO_TestFlag(bm, f, FACE_ORIG)) {
+ BMO_ClearFlag(bm, f, FACE_MARK);
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ }
+ }
+ } else {
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ }
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "dissolvefaces faces=%ff", FACE_MARK);
+ if (BMO_HasError(bm)) {
+ char *msg;
+
+ BMO_GetError(bm, &msg, NULL);
+ BMO_ClearStack(bm);
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEVERTS_FAILED,msg);
+ }
+
+ /*clean up any remaining*/
+ for (v=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ if (!BM_Dissolve_Vert(bm, v)) {
+ BMO_RaiseError(bm, op,
+ BMERR_DISSOLVEVERTS_FAILED, NULL);
+ return;
+ }
+ }
+ }
+
+}
+
+/*this code is for cleaning up two-edged faces, it shall become
+ it's own function one day.*/
+#if 0
+ /*clean up two-edged faces*/
+ /*basic idea is to keep joining 2-edged faces until their
+ gone. this however relies on joining two 2-edged faces
+ together to work, which doesn't.*/
+ found3 = 1;
+ while (found3) {
+ found3 = 0;
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
+ if (!BM_Validate_Face(bm, f, stderr)) {
+ printf("error.\n");
+ }
+
+ if (f->len == 2) {
+ //this design relies on join faces working
+ //with two-edged faces properly.
+ //commenting this line disables the
+ //outermost loop.
+ //found3 = 1;
+ found2 = 0;
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ fe = l->e;
+ for (; l; l=BMIter_Step(&liter)) {
+ f2 = BMIter_New(&fiter, bm,
+ BM_FACES_OF_EDGE, l->e);
+ for (; f2; f2=BMIter_Step(&fiter)) {
+ if (f2 != f) {
+ BM_Join_Faces(bm, f, f2, l->e);
+ found2 = 1;
+ break;
+ }
+ }
+ if (found2) break;
+ }
+
+ if (!found2) {
+ bmesh_kf(bm, f);
+ bmesh_ke(bm, fe);
+ }
+ } /*else if (f->len == 3) {
+ BMEdge *ed[3];
+ BMVert *vt[3];
+ BMLoop *lp[3];
+ int i=0;
+
+ //check for duplicate edges
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ ed[i] = l->e;
+ lp[i] = l;
+ vt[i++] = l->v;
+ }
+ if (vt[0] == vt[1] || vt[0] == vt[2]) {
+ i += 1;
+ }
+ }*/
+ }
+ }
+ if (oldlen == len) break;
+ oldlen = len;
+
+#endif
diff --git a/source/blender/bmesh/operators/extrudeops.c b/source/blender/bmesh/operators/extrudeops.c
new file mode 100644
index 00000000000..5417d232205
--- /dev/null
+++ b/source/blender/bmesh/operators/extrudeops.c
@@ -0,0 +1,190 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#define EXT_INPUT 1
+#define EXT_KEEP 2
+#define EXT_DEL 4
+
+void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMVert *v, *dupev;
+ BMEdge *e;
+
+ v = BMO_IterNew(&siter, bm, op, "verts", BM_VERT);
+ for (; v; v=BMO_IterStep(&siter)) {
+ dupev = BM_Make_Vert(bm, v->co, NULL);
+ VECCOPY(dupev->no, v->no);
+ BM_Copy_Attributes(bm, bm, v, dupev);
+
+ e = BM_Make_Edge(bm, v, dupev, NULL, 0);
+
+ BMO_SetFlag(bm, e, EXT_KEEP);
+ BMO_SetFlag(bm, dupev, EXT_KEEP);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "vertout", EXT_KEEP, BM_VERT);
+ BMO_Flag_To_Slot(bm, op, "edgeout", EXT_KEEP, BM_EDGE);
+}
+
+void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator dupeop, delop;
+ BMOIter siter;
+ BMIter iter, fiter, viter;
+ BMEdge *e, *newedge, *e2, *ce;
+ BMLoop *l, *l2;
+ BMVert *verts[4], *v, *v2;
+ BMFace *f;
+ int rlen, found, delorig=0, i, reverse;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, "dupe");
+
+ BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT);
+
+ /*if one flagged face is bordered by an unflagged face, then we delete
+ original geometry.*/
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
+
+ found = 0;
+ f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
+ for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
+ if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
+ found = 1;
+ delorig = 1;
+ break;
+ }
+ }
+
+ if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
+ }
+
+ /*calculate verts to delete*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ found = 0;
+
+ BM_ITER(e, &viter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, EXT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+
+ BM_ITER(f, &viter, bm, BM_FACES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ BMO_SetFlag(bm, v, EXT_DEL);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, f, EXT_INPUT))
+ BMO_SetFlag(bm, f, EXT_DEL);
+ }
+ if (delorig) BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d",
+ EXT_DEL, DEL_ONLYTAGGED);
+
+ BMO_CopySlot(op, &dupeop, "edgefacein", "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ if (bm->act_face && BMO_TestFlag(bm, bm->act_face, EXT_INPUT))
+ bm->act_face = BMO_Get_MapPointer(bm, &dupeop, "facemap", bm->act_face);
+
+ if (delorig) BMO_Exec_Op(bm, &delop);
+
+ /*if not delorig, reverse loops of original faces*/
+ if (!delorig) {
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, f, EXT_INPUT)) {
+ BM_flip_normal(bm, f);
+ }
+ }
+ }
+
+ BMO_CopySlot(&dupeop, op, "newout", "geomout");
+ e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
+ for (; e; e=BMO_IterStep(&siter)) {
+ if (BMO_InMap(bm, op, "exclude", e)) continue;
+
+ newedge = BMO_IterMapVal(&siter);
+ newedge = *(BMEdge**)newedge;
+ if (!newedge) continue;
+ if (!newedge->loop) ce = e;
+ else ce = newedge;
+
+ if (ce->loop && (ce->loop->v == ce->v1)) {
+ verts[0] = e->v1;
+ verts[1] = e->v2;
+ verts[2] = newedge->v2;
+ verts[3] = newedge->v1;
+ } else {
+ verts[3] = e->v1;
+ verts[2] = e->v2;
+ verts[1] = newedge->v2;
+ verts[0] = newedge->v1;
+ }
+
+ /*not sure what to do about example face, pass NULL for now.*/
+ f = BM_Make_Quadtriangle(bm, verts, NULL, 4, NULL, 0);
+
+ /*copy attributes*/
+ l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ if (l->e != e && l->e != newedge) continue;
+ l2 = l->radial.next->data;
+
+ if (l2 == l) {
+ l2 = newedge->loop;
+ BM_Copy_Attributes(bm, bm, l2->f, l->f);
+
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = (BMLoop*) l2->head.next;
+ l = (BMLoop*) l->head.next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ } else {
+ BM_Copy_Attributes(bm, bm, l2->f, l->f);
+
+ /*copy data*/
+ if (l2->v == l->v) {
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = (BMLoop*) l2->head.next;
+ l = (BMLoop*) l->head.next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ } else {
+ l2 = (BMLoop*) l2->head.next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = (BMLoop*) l2->head.prev;
+ l = (BMLoop*) l->head.next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ }
+ }
+ }
+ }
+
+ /*link isolated verts*/
+ v = BMO_IterNew(&siter, bm, &dupeop, "isovertmap", 0);
+ for (; v; v=BMO_IterStep(&siter)) {
+ v2 = *((void**)BMO_IterMapVal(&siter));
+ BM_Make_Edge(bm, v, v2, v->edge, 1);
+ }
+
+ /*cleanup*/
+ if (delorig) BMO_Finish_Op(bm, &delop);
+ BMO_Finish_Op(bm, &dupeop);
+}
diff --git a/source/blender/bmesh/operators/mesh_conv.c b/source/blender/bmesh/operators/mesh_conv.c
new file mode 100644
index 00000000000..3ca95ea1e32
--- /dev/null
+++ b/source/blender/bmesh/operators/mesh_conv.c
@@ -0,0 +1,308 @@
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "bmesh.h"
+
+/*
+ * MESH CONV.C
+ *
+ * This file contains functions
+ * for converting a Mesh
+ * into a Bmesh. will not support non-ngon
+ * meshes at first, use the editmesh functions
+ * until it's implemented, and remove this
+ * comment if it already is. -joeedh
+ *
+*/
+
+void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
+ Mesh *me = BMO_Get_Pnt(op, "mesh");
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *ml;
+ MPoly *mpoly;
+ BMVert *v, **vt=NULL;
+ BMEdge *e, **fedges=NULL, **et;
+ V_DECLARE(fedges);
+ BMFace *f;
+ int i, j, allocsize[4] = {512, 512, 2048, 512};
+
+ if (!me || !me->totvert) return; /*sanity check*/
+
+ mvert = me->mvert;
+
+ vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
+
+ CustomData_copy(&bm->vdata, &me->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &me->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &me->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &me->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ for (i=0; i<me->totvert; i++, mvert++) {
+ v = BM_Make_Vert(bm, mvert->co, NULL);
+ VECCOPY(v->no, mvert->no);
+
+ vt[i] = v;
+ BMINDEX_SET(v, i);
+
+ /*transfer flags*/
+ v->head.flag = (mvert->flag & ME_HIDE) ? BM_HIDDEN : 0;
+ if(mvert->flag & SELECT) BM_Select_Vert(bm, v, 1);
+ v->bweight = (float)mvert->bweight / 255.0f;
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+
+ v->head.flag = MEFlags_To_BMFlags(mvert->flag, BM_VERT);
+ }
+
+ if (!me->totedge) return;
+
+ et = MEM_mallocN(sizeof(void**)*me->totedge, "mesh to bmesh etable");
+
+ medge = me->medge;
+ for (i=0; i<me->totedge; i++, medge++) {
+ e = BM_Make_Edge(bm, vt[medge->v1], vt[medge->v2], NULL, 0);
+ et[i] = e;
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
+
+ e->crease = (float)medge->crease / 255.0f;
+ e->bweight = (float)medge->bweight / 255.0f;
+
+ e->head.flag = MEFlags_To_BMFlags(medge->flag, BM_EDGE);
+ }
+
+ if (!me->totpoly) return;
+
+ mpoly = me->mpoly;
+ for (i=0; i<me->totpoly; i++, mpoly++) {
+ BMVert *v1, *v2;
+
+ V_RESET(fedges);
+ for (j=0; j<mpoly->totloop; j++) {
+ ml = &me->mloop[mpoly->loopstart+j];
+ v = vt[ml->v];
+ e = et[ml->e];
+
+ V_GROW(fedges);
+
+ fedges[j] = e;
+ }
+
+ v1 = vt[me->mloop[mpoly->loopstart].v];
+ v2 = vt[me->mloop[mpoly->loopstart+1].v];
+
+ if (v1 == fedges[0]->v1) v2 = fedges[0]->v2;
+ else {
+ v1 = fedges[0]->v2;
+ v2 = fedges[0]->v1;
+ }
+
+ f = BM_Make_Ngon(bm, v1, v2, fedges, mpoly->totloop, 0);
+
+ f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
+ if (i == me->act_face) bm->act_face = f;
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->fdata, &bm->pdata, i, &f->head.data);
+ }
+}
+
+void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
+ BMesh *bmtess;
+ Object *ob = BMO_Get_Pnt(op, "object");
+ Scene *scene = BMO_Get_Pnt(op, "scene");
+ Mesh *me = ob->data;
+ MLoop *mloop;
+ MPoly *mpoly;
+ MVert *mvert, *oldverts;
+ MEdge *medge;
+ MFace *mface;
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+ BMIter iter, liter;
+ int i, j, ototvert, totloop, numTex, numCol;
+
+ numTex = CustomData_number_of_layers(&me->pdata, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+
+ bmtess = BM_Copy_Mesh(bm);
+ BMO_CallOpf(bmtess, "makefgon trifan=%i", 0);
+
+ /* new Vertex block */
+ if(bm->totvert==0) mvert= NULL;
+ else mvert= MEM_callocN(bm->totvert*sizeof(MVert), "loadeditbMesh vert");
+
+ /* new Edge block */
+ if(bm->totedge==0) medge= NULL;
+ else medge= MEM_callocN(bm->totedge*sizeof(MEdge), "loadeditbMesh edge");
+
+ /* new Face block */
+ if(bmtess->totface==0) mface= NULL;
+ else mface= MEM_callocN(bmtess->totface*sizeof(MFace), "loadeditbMesh face");
+
+ /*build ngon data*/
+ /* new Ngon Face block */
+ if(bm->totface==0) mpoly = NULL;
+ else mpoly= MEM_callocN(bm->totface*sizeof(MPoly), "loadeditbMesh poly");
+
+ /*find number of loops to allocate*/
+ totloop = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ totloop += f->len;
+ }
+
+ if (totloop==0) mloop = NULL;
+ else mloop = MEM_callocN(totloop*sizeof(MLoop), "loadeditbMesh loop");
+
+ /* lets save the old verts just in case we are actually working on
+ * a key ... we now do processing of the keys at the end */
+ oldverts= me->mvert;
+
+ /* don't free this yet */
+ CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
+
+ /* free custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* add new custom data */
+ me->totvert= bm->totvert;
+ me->totedge= bm->totedge;
+ me->totface= bmtess->totface;
+ me->totloop= totloop;
+ me->totpoly= bm->totface;
+
+ CustomData_copy(&bm->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
+ CustomData_copy(&bm->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
+ CustomData_copy(&bm->ldata, &me->ldata, CD_MASK_MESH, CD_CALLOC, me->totloop);
+ CustomData_copy(&bm->pdata, &me->pdata, CD_MASK_MESH, CD_CALLOC, me->totpoly);
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
+ CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
+ CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
+ CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
+ CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+
+ CustomData_from_bmeshpoly(&me->fdata, &bmtess->pdata, &bmtess->ldata, bmtess->totface);
+
+ mesh_update_customdata_pointers(me);
+
+ /*set indices*/
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ VECCOPY(mvert->co, v->co);
+
+ mvert->no[0] = (unsigned char) (v->no[0]*255.0f);
+ mvert->no[1] = (unsigned char) (v->no[1]*255.0f);
+ mvert->no[2] = (unsigned char) (v->no[2]*255.0f);
+
+ mvert->flag = BMFlags_To_MEFlags(v);
+
+ BMINDEX_SET(v, i);
+ i++;
+ mvert++;
+ }
+
+ i = 0;
+ BM_ITER(v, &iter, bmtess, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(v, i);
+ i++;
+ }
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ medge->v1 = BMINDEX_GET(e->v1);
+ medge->v2 = BMINDEX_GET(e->v2);
+
+ medge->flag = BMFlags_To_MEFlags(e);
+
+ BMINDEX_SET(e, i);
+ i++;
+ medge++;
+ }
+
+ i = 0;
+ BM_ITER(f, &iter, bmtess, BM_FACES_OF_MESH, NULL) {
+ mface->mat_nr = f->mat_nr;
+ mface->flag = BMFlags_To_MEFlags(f);
+
+ mface->v1 = BMINDEX_GET(f->loopbase->v);
+ mface->v2 = BMINDEX_GET(((BMLoop*)f->loopbase->head.next)->v);
+ if (f->len < 3) {
+ mface++;
+ i++;
+ continue;
+ }
+
+ mface->v3 = BMINDEX_GET(((BMLoop*)f->loopbase->head.next->next)->v);
+ if (f->len < 4) {
+ mface->v4 = 0;
+ mface++;
+ i++;
+ continue;
+ }
+
+ mface->v4 = BMINDEX_GET(((BMLoop*)f->loopbase->head.next->next->next)->v);
+ test_index_face(mface, &me->fdata, i, 1);
+
+ BM_loops_to_corners(bmtess, me, i, f, numTex, numCol);
+
+ mface++;
+ i++;
+ }
+
+ i = 0;
+ j = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ mpoly->loopstart = j;
+ mpoly->totloop = f->len;
+ mpoly->mat_nr = f->mat_nr;
+ mpoly->flag = BMFlags_To_MEFlags(f);
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for ( ; l; l=BMIter_Step(&liter), j++, mloop++) {
+ mloop->e = BMINDEX_GET(l->e);
+ mloop->v = BMINDEX_GET(l->v);
+ }
+
+ if (f == bm->act_face) me->act_face = i;
+
+ i++;
+ mpoly++;
+ }
+
+ BM_Free_Mesh(bmtess);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c
new file mode 100644
index 00000000000..605626d15e0
--- /dev/null
+++ b/source/blender/bmesh/operators/removedoubles.c
@@ -0,0 +1,309 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+#include "BLI_ghash.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BL(ptr) ((BMLoop*)(ptr))
+
+void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op)
+{
+ BMIter liter;
+ BMLoop *l;
+ BMVert *v2, *doub;
+ int split=0;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", l->v);
+ /*ok: if v2 is NULL (e.g. not in the map) then it's
+ a target vert, otherwise it's a double*/
+ if (v2 && BM_Vert_In_Face(f, v2) && v2 != BL(l->head.prev)->v
+ && v2 != BL(l->head.next)->v)
+ {
+ doub = l->v;
+ split = 1;
+ break;
+ }
+ }
+
+ if (split && doub != v2) {
+ BMLoop *nl;
+ BMFace *f2 = BM_Split_Face(bm, f, doub, v2, &nl, NULL);
+
+ remdoubles_splitface(f, bm, op);
+ remdoubles_splitface(f2, bm, op);
+ }
+}
+
+#define ELE_DEL 1
+#define EDGE_COL 2
+#define FACE_MARK 2
+
+#if 0
+int remdoubles_face_overlaps(BMesh *bm, BMVert **varr,
+ int len, BMFace *exclude,
+ BMFace **overlapface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (overlapface) *overlapface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount >= len){
+ if (overlapface) *overlapface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
+#endif
+
+void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter, liter;
+ BMVert *v, *v2;
+ BMEdge *e, *e2, **edges = NULL;
+ V_DECLARE(edges);
+ BMLoop *l, *l2, **loops = NULL;
+ V_DECLARE(loops);
+ BMFace *f, *f2;
+ int a;
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_Get_MapPointer(bm, op, "targetmap", v))
+ BMO_SetFlag(bm, v, ELE_DEL);
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ remdoubles_splitface(f, bm, op);
+ }
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ v = BMO_Get_MapPointer(bm, op, "targetmap", e->v1);
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", e->v2);
+
+ if (!v) v = e->v1;
+ if (!v2) v2 = e->v2;
+
+ if ((e->v1 != v) || (e->v2 != v2)) {
+ if (v == v2) BMO_SetFlag(bm, e, EDGE_COL);
+ else BM_Make_Edge(bm, v, v2, e, 1);
+
+ BMO_SetFlag(bm, e, ELE_DEL);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BMINDEX_SET(f, 0);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (BMO_TestFlag(bm, l->v, ELE_DEL))
+ BMO_SetFlag(bm, f, FACE_MARK);
+ if (BMO_TestFlag(bm, l->e, EDGE_COL))
+ BMINDEX_SET(f, BMINDEX_GET(f)+1);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
+ if (f->len - BMINDEX_GET(f) < 3) {
+ BMO_SetFlag(bm, f, ELE_DEL);
+ continue;
+ }
+
+ V_RESET(edges);
+ V_RESET(loops);
+ a = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ v = l->v;
+ v2 = BL(l->head.next)->v;
+ if (BMO_TestFlag(bm, v, ELE_DEL))
+ v = BMO_Get_MapPointer(bm, op, "targetmap", v);
+ if (BMO_TestFlag(bm, v2, ELE_DEL))
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
+
+ e2 = v != v2 ? BM_Edge_Exist(v, v2) : NULL;
+ if (e2) {
+ V_GROW(edges);
+ V_GROW(loops);
+
+ edges[a] = e2;
+ loops[a] = l;
+
+ a++;
+ }
+ }
+
+ v = loops[0]->v;
+ v2 = loops[1]->v;
+
+ if (BMO_TestFlag(bm, v, ELE_DEL))
+ v = BMO_Get_MapPointer(bm, op, "targetmap", v);
+ if (BMO_TestFlag(bm, v2, ELE_DEL))
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
+
+
+ f2 = BM_Make_Ngon(bm, v, v2, edges, a, 0);
+ if (f2) {
+ BM_Copy_Attributes(bm, bm, f, f2);
+ BMO_SetFlag(bm, f, ELE_DEL);
+
+ a = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f2) {
+ l2 = loops[a];
+ BM_Copy_Attributes(bm, bm, l2, l);
+
+ a++;
+ }
+ }
+
+ /*need to still copy customdata stuff here, will do later*/
+ }
+
+ BMO_CallOpf(bm, "del geom=%fvef context=%i", ELE_DEL, DEL_ONLYTAGGED);
+
+ V_FREE(edges);
+}
+
+static int vergaverco(const void *e1, const void *e2)
+{
+ const BMVert *v1 = *(void**)e1, *v2 = *(void**)e2;
+ float x1 = v1->co[0] + v1->co[1] + v1->co[2];
+ float x2 = v2->co[0] + v2->co[1] + v2->co[2];
+
+ if (x1 > x2) return 1;
+ else if (x1 < x2) return -1;
+ else return 0;
+}
+
+#define VERT_TESTED 1
+#define VERT_DOUBLE 2
+#define VERT_TARGET 4
+#define VERT_KEEP 8
+
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMOIter oiter;
+ BMVert *v, *v2;
+ BMVert **verts=NULL;
+ V_DECLARE(verts);
+ float dist, distsqr;
+ int i, j, len;
+
+ dist = BMO_Get_Float(op, "dist");
+ distsqr = dist*dist;
+
+ BMO_Init_Op(&weldop, "weldverts");
+
+ i = 0;
+ BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+ V_GROW(verts);
+ verts[i++] = v;
+ }
+
+ /*sort by vertex coordinates added together*/
+ qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
+
+ len = V_COUNT(verts);
+ for (i=0; i<len; i++) {
+ v = verts[i];
+ if (BMO_TestFlag(bm, v, VERT_TESTED)) continue;
+
+ BMO_SetFlag(bm, v, VERT_TESTED);
+ for (j=i+1; j<len; j++) {
+ float vec[3];
+
+ v2 = verts[j];
+ if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+ > distsqr) break;
+
+ vec[0] = v->co[0] - v2->co[0];
+ vec[1] = v->co[1] - v2->co[1];
+ vec[2] = v->co[2] - v2->co[2];
+
+ if (INPR(vec, vec) < distsqr) {
+ BMO_SetFlag(bm, v2, VERT_TESTED);
+ BMO_SetFlag(bm, v2, VERT_DOUBLE);
+ BMO_SetFlag(bm, v, VERT_TARGET);
+
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", v2, v);
+ }
+ }
+ }
+
+ V_FREE(verts);
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+}
+
+
+void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter oiter;
+ BMVert *v, *v2;
+ BMVert **verts=NULL;
+ V_DECLARE(verts);
+ float dist, distsqr;
+ int i, j, len;
+
+ dist = BMO_Get_Float(op, "dist");
+ distsqr = dist*dist;
+
+ i = 0;
+ BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+ V_GROW(verts);
+ verts[i++] = v;
+ }
+
+ /*sort by vertex coordinates added together*/
+ //qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
+
+ BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP);
+
+ len = V_COUNT(verts);
+ for (i=0; i<len; i++) {
+ v = verts[i];
+ if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
+
+ //BMO_SetFlag(bm, v, VERT_TESTED);
+ for (j=0; j<len; j++) {
+ if (j == i) continue;
+
+ //float vec[3];
+ if (BMO_TestFlag(bm, v, VERT_KEEP)) continue;
+
+ v2 = verts[j];
+ //if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+ // > distsqr) break;
+
+ //vec[0] = v->co[0] - v2->co[0];
+ //vec[1] = v->co[1] - v2->co[1];
+ //vec[2] = v->co[2] - v2->co[2];
+
+ if (VecLenCompare(v->co, v2->co, dist)) {
+ BMO_SetFlag(bm, v2, VERT_DOUBLE);
+ BMO_SetFlag(bm, v, VERT_TARGET);
+
+ BMO_Insert_MapPointer(bm, op, "targetmapout", v2, v);
+ }
+ }
+ }
+
+ V_FREE(verts);
+}
diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c
new file mode 100644
index 00000000000..8482fecb7bb
--- /dev/null
+++ b/source/blender/bmesh/operators/subdivideop.c
@@ -0,0 +1,825 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+
+#include "DNA_object_types.h"
+
+#include "ED_mesh.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "subdivideop.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/*flags for all elements share a common bitfield space*/
+#define SUBD_SPLIT 1
+
+#define EDGE_PERCENT 2
+
+/*I don't think new faces are flagged, currently, but
+ better safe than sorry.*/
+#define FACE_NEW 4
+#define FACE_CUSTOMFILL 8
+#define ELE_INNER 16
+#define ELE_SPLIT 32
+#define ELE_CONNECT 64
+
+/*stuff for the flag paramter. note that
+ what used to live in "beauty" and
+ in "seltype" live here. still have to
+ convert the beauty flags over, which
+ is why it starts at 128 (to avoid
+ collision).*/
+#define SELTYPE_INNER 128
+
+/*
+NOTE: beauty has been renamed to flag!
+*/
+
+/*generic subdivision rules:
+
+ * two selected edges in a face should make a link
+ between them.
+
+ * one edge should do, what? make pretty topology, or just
+ split the edge only?
+*/
+
+/*connects face with smallest len, which I think should always be correct for
+ edge subdivision*/
+BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
+ BMIter iter, iter2;
+ BMVert *v;
+ BMLoop *nl;
+ BMFace *face, *curf = NULL;
+
+ /*this isn't the best thing in the world. it doesn't handle cases where there's
+ multiple faces yet. that might require a convexity test to figure out which
+ face is "best," and who knows what for non-manifold conditions.*/
+ for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
+ for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
+ if (v == v2) {
+ if (!curf || face->len < curf->len) curf = face;
+ }
+ }
+ }
+
+ if (curf) {
+ face = BM_Split_Face(bm, curf, v1, v2, &nl, NULL);
+
+ if (nf) *nf = face;
+ return nl ? nl->e : NULL;
+ }
+
+ return NULL;
+}
+/* calculates offset for co, based on fractal, sphere or smooth settings */
+static void alter_co(float *co, BMEdge *edge, subdparams *params, float perc,
+ BMVert *vsta, BMVert *vend)
+{
+ float vec1[3], fac;
+
+ if(params->beauty & B_SMOOTH) {
+ /* we calculate an offset vector vec1[], to be added to *co */
+ float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
+
+ VecSubf(nor, vsta->co, vend->co);
+ len= 0.5f*Normalize(nor);
+
+ VECCOPY(nor1, vsta->no);
+ VECCOPY(nor2, vend->no);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec1[0]= fac*nor1[0];
+ vec1[1]= fac*nor1[1];
+ vec1[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec1[0]+= fac*nor2[0];
+ vec1[1]+= fac*nor2[1];
+ vec1[2]+= fac*nor2[2];
+
+ /* falloff for multi subdivide */
+ smooth *= sqrt(fabs(1.0f - 2.0f*fabs(perc)));
+
+ vec1[0]*= smooth*len;
+ vec1[1]*= smooth*len;
+ vec1[2]*= smooth*len;
+
+ co[0] += vec1[0];
+ co[1] += vec1[1];
+ co[2] += vec1[2];
+ }
+ else if(params->beauty & B_SPHERE) { /* subdivide sphere */
+ Normalize(co);
+ co[0]*= params->smooth;
+ co[1]*= params->smooth;
+ co[2]*= params->smooth;
+ }
+
+ if(params->beauty & B_FRACTAL) {
+ fac= params->fractal*VecLenf(vsta->co, vend->co);
+ vec1[0]= fac*(float)(0.5-BLI_drand());
+ vec1[1]= fac*(float)(0.5-BLI_drand());
+ vec1[2]= fac*(float)(0.5-BLI_drand());
+ VecAddf(co, co, vec1);
+ }
+}
+
+/* assumes in the edge is the correct interpolated vertices already */
+/* percent defines the interpolation, rad and flag are for special options */
+/* results in new vertex with correct coordinate, vertex normal and weight group info */
+static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
+ subdparams *params, float percent,
+ float percent2,
+ BMEdge **out,BMVert *vsta,BMVert *vend)
+{
+ BMVert *ev;
+// float co[3];
+
+ ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
+ BM_Vert_UpdateNormal(bm, ev);
+
+ BMO_SetFlag(bm, ev, ELE_INNER);
+
+ /* offset for smooth or sphere or fractal */
+ alter_co(ev->co, oedge, params, percent2, vsta, vend);
+
+#if 0 //TODO
+ /* clip if needed by mirror modifier */
+ if (edge->v1->f2) {
+ if ( edge->v1->f2 & edge->v2->f2 & 1) {
+ co[0]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 2) {
+ co[1]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 4) {
+ co[2]= 0.0f;
+ }
+ }
+#endif
+
+ return ev;
+}
+
+static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
+ int curpoint, int totpoint, subdparams *params,
+ BMEdge **newe, BMVert *vsta, BMVert *vend)
+{
+ BMVert *ev;
+ float percent, percent2 = 0.0f;
+
+ if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
+ percent = BMO_Get_MapFloat(bm, params->op,
+ "edgepercents", edge);
+ else {
+ percent= 1.0f/(float)(totpoint+1-curpoint);
+ percent2 = (float)curpoint / (float)(totpoint + 1);
+
+ }
+
+ ev= bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
+ percent2, newe, vsta, vend);
+ return ev;
+}
+
+static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
+ BMVert *vsta, BMVert *vend) {
+ BMEdge *eed = edge, *newe, temp = *edge;
+ BMVert *v;
+ int i, numcuts = params->numcuts;
+
+ for(i=0;i<numcuts;i++) {
+ v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params,
+ &newe, vsta, vend);
+ BMO_SetFlag(bm, v, SUBD_SPLIT);
+ BMO_SetFlag(bm, eed, SUBD_SPLIT);
+
+ BMO_SetFlag(bm, v, ELE_SPLIT);
+ BMO_SetFlag(bm, eed, ELE_SPLIT);
+ }
+}
+
+/*note: the patterns are rotated as necassary to
+ match the input geometry. they're based on the
+ pre-split state of the face*/
+
+/*
+
+v3---------v2
+| |
+| |
+| |
+| |
+v4---v0---v1
+
+*/
+static void q_1edge_split(BMesh *bm, BMFace *face,
+ BMVert **verts, subdparams *params) {
+ BMFace *nf;
+ int i, add, numcuts = params->numcuts;
+
+ /*if it's odd, the middle face is a quad, otherwise it's a triangle*/
+ if (numcuts % 2==0) {
+ add = 2;
+ for (i=0; i<numcuts; i++) {
+ if (i == numcuts/2) add -= 1;
+ connect_smallest_face(bm, verts[i], verts[numcuts+add],
+ &nf);
+ }
+ } else {
+ add = 2;
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+add],
+ &nf);
+ if (i == numcuts/2) {
+ add -= 1;
+ connect_smallest_face(bm, verts[i],
+ verts[numcuts+add],
+ &nf);
+ }
+ }
+
+ }
+}
+
+subdpattern q_1edge = {
+ {1, 0, 0, 0},
+ q_1edge_split,
+ 4,
+};
+
+
+/*
+
+v4---v3---v2
+| s |
+| |
+| |
+| s |
+v5---v0---v1
+
+*/
+
+static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i],verts[(numcuts-i-1)+numcuts+2],
+ &nf);
+ }
+}
+
+subdpattern q_2edge_op = {
+ {1, 0, 1, 0},
+ q_2edge_op_split,
+ 4,
+};
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
+ &nf);
+ }
+ connect_smallest_face(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
+}
+
+subdpattern q_2edge = {
+ {1, 1, 0, 0},
+ q_2edge_split,
+ 4,
+};
+
+/* s s
+v8--v7--v6-v5
+| |
+| v4 s
+| |
+| v3 s
+| s s |
+v9-v0--v1-v2
+
+*/
+static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, add=0, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ if (i == numcuts/2) {
+ if (numcuts % 2 != 0) {
+ connect_smallest_face(bm, verts[numcuts-i-1+add],
+ verts[i+numcuts+1], &nf);
+ }
+ add = numcuts*2+2;
+ }
+ connect_smallest_face(bm, verts[numcuts-i-1+add],
+ verts[i+numcuts+1], &nf);
+ }
+
+ for (i=0; i<numcuts/2+1; i++) {
+ connect_smallest_face(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
+ &nf);
+ }
+}
+
+subdpattern q_3edge = {
+ {1, 1, 1, 0},
+ q_3edge_split,
+ 4,
+};
+
+/*
+
+ v8--v7-v6--v5
+ | s |
+ |v9 s s|v4
+first line | | last line
+ |v10s s s|v3
+ v11-v0--v1-v2
+
+ it goes from bottom up
+*/
+static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMVert *v, *v1, *v2;
+ BMEdge *e, *ne, temp;
+ BMVert **lines;
+ int numcuts = params->numcuts;
+ int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
+
+ lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
+ "q_4edge_split");
+ /*build a 2-dimensional array of verts,
+ containing every vert (and all new ones)
+ in the face.*/
+
+ /*first line*/
+ for (i=0; i<numcuts+2; i++) {
+ lines[i] = verts[numcuts*3+2+(numcuts-i+1)];
+ }
+
+ /*last line*/
+ for (i=0; i<numcuts+2; i++) {
+ lines[(s-1)*s+i] = verts[numcuts+i];
+ }
+
+ /*first and last members of middle lines*/
+ for (i=0; i<numcuts; i++) {
+ a = i;
+ b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
+
+ e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ if (!e) continue;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+
+ v1 = lines[(i+1)*s] = verts[a];
+ v2 = lines[(i+1)*s + s-1] = verts[b];
+
+ temp = *e;
+ for (a=0; a<numcuts; a++) {
+ v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
+ v1, v2);
+ BMO_SetFlag(bm, ne, ELE_INNER);
+ lines[(i+1)*s+a+1] = v;
+ }
+ }
+
+ for (i=1; i<numcuts+2; i++) {
+ for (j=1; j<numcuts+1; j++) {
+ a = i*s + j;
+ b = (i-1)*s + j;
+ e = connect_smallest_face(bm, lines[a], lines[b], &nf);
+ if (!e) continue;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+ }
+ }
+
+ MEM_freeN(lines);
+}
+
+/* v3
+ / \
+ / \
+ / \
+ / \
+ / \
+v4--v0--v1--v2
+ s s
+*/
+static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+1], &nf);
+ }
+}
+
+subdpattern t_1edge = {
+ {1, 0, 0},
+ t_1edge_split,
+ 3,
+};
+
+/* v5
+ / \
+ / \ v4 s
+ / \
+ / \ v3 s
+ / \
+v6--v0--v1--v2
+ s s
+*/
+static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+numcuts-i], &nf);
+ }
+}
+
+subdpattern t_2edge = {
+ {1, 1, 0},
+ t_2edge_split,
+ 3,
+};
+
+
+/* v5
+ / \
+ s v6/---\ v4 s
+ / \ / \
+sv7/---v---\ v3 s
+ / \/ \/ \
+ v8--v0--v1--v2
+ s s
+*/
+static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMEdge *e, *ne, temp;
+ BMVert ***lines, *v;
+ void *stackarr[1];
+ int i, j, a, b, numcuts = params->numcuts;
+
+ /*number of verts in each line*/
+ lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
+
+ lines[0] = (BMVert**) stackarr;
+ lines[0][0] = verts[numcuts*2+1];
+
+ lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2),
+ "triangle vert table 2");
+ for (i=0; i<numcuts; i++) {
+ lines[1+numcuts][1+i] = verts[i];
+ }
+ lines[1+numcuts][0] = verts[numcuts*3+2];
+ lines[1+numcuts][1+numcuts] = verts[numcuts];
+
+ for (i=0; i<numcuts; i++) {
+ lines[i+1] = MEM_callocN(sizeof(void*)*(2+i),
+ "triangle vert table row");
+ a = numcuts*2 + 2 + i;
+ b = numcuts + numcuts - i;
+ e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ if (!e) goto cleanup;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+ lines[i+1][0] = verts[a];
+ lines[i+1][1+i] = verts[b];
+
+ temp = *e;
+ for (j=0; j<i; j++) {
+ v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
+ verts[a], verts[b]);
+ lines[i+1][j+1] = v;
+
+ BMO_SetFlag(bm, ne, ELE_INNER);
+ }
+ }
+
+
+/* v5
+ / \
+ s v6/---\ v4 s
+ / \ / \
+sv7/---v---\ v3 s
+ / \/ \/ \
+ v8--v0--v1--v2
+ s s
+*/
+ for (i=1; i<numcuts+1; i++) {
+ for (j=0; j<i; j++) {
+ e= connect_smallest_face(bm, lines[i][j], lines[i+1][j+1],
+ &nf);
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+ e= connect_smallest_face(bm,lines[i][j+1],lines[i+1][j+1],
+ &nf);
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+ }
+ }
+
+cleanup:
+ for (i=1; i<numcuts+2; i++) {
+ if (lines[i]) MEM_freeN(lines[i]);
+ }
+
+ MEM_freeN(lines);
+}
+
+subdpattern t_3edge = {
+ {1, 1, 1},
+ t_3edge_split,
+ 3,
+};
+
+
+subdpattern q_4edge = {
+ {1, 1, 1, 1},
+ q_4edge_split,
+ 4,
+};
+
+subdpattern *patterns[] = {
+ &q_1edge,
+ &q_2edge_op,
+ &q_4edge,
+ &q_3edge,
+ &q_2edge,
+ &t_1edge,
+ &t_2edge,
+ &t_3edge,
+};
+
+#define PLEN (sizeof(patterns) / sizeof(void*))
+
+typedef struct subd_facedata {
+ BMVert *start; subdpattern *pat;
+} subd_facedata;
+
+void esubdivide_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMOpSlot *einput;
+ BMEdge *edge, **edges = NULL;
+ V_DECLARE(edges);
+ BMFace *face;
+ BMLoop *nl;
+ BMVert **verts = NULL;
+ V_DECLARE(verts);
+ BMIter fiter, liter;
+ subdpattern *pat;
+ subdparams params;
+ subd_facedata *facedata = NULL;
+ V_DECLARE(facedata);
+ float smooth, fractal;
+ int beauty;
+ int i, j, matched, a, b, numcuts;
+
+ BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT);
+
+ numcuts = BMO_GetSlot(op, "numcuts")->data.i;
+ smooth = BMO_GetSlot(op, "smooth")->data.f;
+ fractal = BMO_GetSlot(op, "fractal")->data.f;
+ beauty = BMO_GetSlot(op, "beauty")->data.i;
+
+ einput = BMO_GetSlot(op, "edges");
+
+ /*first go through and tag edges*/
+ BMO_Flag_To_Slot(bmesh, op, "edges",
+ SUBD_SPLIT, BM_EDGE);
+
+ params.numcuts = numcuts;
+ params.op = op;
+ params.smooth = smooth;
+ params.fractal = fractal;
+ params.beauty = beauty;
+
+ BMO_Mapping_To_Flag(bmesh, op, "custompatterns",
+ FACE_CUSTOMFILL);
+
+ BMO_Mapping_To_Flag(bmesh, op, "edgepercents",
+ EDGE_PERCENT);
+
+ for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
+ face; face=BMIter_Step(&fiter)) {
+ /*figure out which pattern to use*/
+
+ V_RESET(edges);
+ V_RESET(verts);
+ i = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ V_GROW(edges);
+ V_GROW(verts);
+ edges[i] = nl->e;
+ verts[i] = nl->v;
+ i++;
+ }
+
+ if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
+ pat = BMO_Get_MapData(bmesh, op,
+ "custompatterns", face);
+ for (i=0; i<pat->len; i++) {
+ matched = 1;
+ for (j=0; j<pat->len; j++) {
+ a = (j + i) % pat->len;
+ if ((!!BMO_TestFlag(bmesh, edges[a], SUBD_SPLIT))
+ != (!!pat->seledges[j])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) {
+ V_GROW(facedata);
+ b = V_COUNT(facedata)-1;
+ facedata[b].pat = pat;
+ facedata[b].start = verts[i];
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ break;
+ }
+ }
+ if (!matched) {
+ /*if no match, append null element to array.*/
+ V_GROW(facedata);
+ }
+
+ /*obvously don't test for other patterns matching*/
+ continue;
+ }
+
+ for (i=0; i<PLEN; i++) {
+ pat = patterns[i];
+ if (pat->len == face->len) {
+ for (a=0; a<pat->len; a++) {
+ matched = 1;
+ for (b=0; b<pat->len; b++) {
+ j = (b + a) % pat->len;
+ if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
+ != (!!pat->seledges[b])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) break;
+ }
+ if (matched) {
+ V_GROW(facedata);
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ j = V_COUNT(facedata) - 1;
+ facedata[j].pat = pat;
+ facedata[j].start = verts[a];
+ break;
+ }
+ }
+ }
+ }
+
+ einput = BMO_GetSlot(op, "edges");
+
+ /*go through and split edges*/
+ for (i=0; i<einput->len; i++) {
+ edge = ((BMEdge**)einput->data.p)[i];
+ bm_subdivide_multicut(bmesh, edge,&params, edge->v1, edge->v2);
+ //BM_Split_Edge_Multi(bmesh, edge, numcuts);
+ }
+
+ //if (facedata) V_FREE(facedata);
+ //return;
+
+ i = 0;
+ for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
+ face; face=BMIter_Step(&fiter)) {
+ /*figure out which pattern to use*/
+ V_RESET(verts);
+ if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0) continue;
+
+ pat = facedata[i].pat;
+ if (!pat) continue;
+
+ j = a = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ if (nl->v == facedata[i].start) {
+ a = j+1;
+ break;
+ }
+ j++;
+ }
+
+ for (j=0; j<face->len; j++) {
+ V_GROW(verts);
+ }
+
+ j = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ b = (j-a+face->len) % face->len;
+ verts[b] = nl->v;
+ j += 1;
+ }
+
+ pat->connectexec(bmesh, face, verts, &params);
+ i++;
+ }
+
+ if (facedata) V_FREE(facedata);
+ if (edges) V_FREE(edges);
+ if (verts) V_FREE(verts);
+
+ BMO_Flag_To_Slot(bmesh, op, "outinner",
+ ELE_INNER, BM_ALL);
+ BMO_Flag_To_Slot(bmesh, op, "outsplit",
+ ELE_SPLIT, BM_ALL);
+}
+
+/*editmesh-emulating function*/
+void BM_esubdivideflag(Object *obedit, BMesh *bm, int flag, float smooth,
+ float fractal, int beauty, int numcuts, int seltype) {
+ BMOperator op;
+
+ BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
+ "beauty=%d numcuts=%d", flag, smooth, fractal,
+ beauty, numcuts);
+
+ BMO_Exec_Op(bm, &op);
+
+ if (seltype == SUBDIV_SELECT_INNER) {
+ BMOIter iter;
+ BMHeader *ele;
+ int i;
+
+ ele = BMO_IterNew(&iter,bm,&op, "outinner", BM_EDGE|BM_VERT);
+ for (; ele; ele=BMO_IterStep(&iter)) {
+ BM_Select(bm, ele, 1);
+ }
+ }
+ BMO_Finish_Op(bm, &op);
+}
+
+#if 0
+void BM_esubdivideflag_conv(Object *obedit,EditMesh *em,int selflag, float rad,
+ int flag, int numcuts, int seltype) {
+ BMesh *bm = editmesh_to_bmesh(em);
+ EditMesh *em2;
+
+ BM_esubdivideflag(obedit, bm, selflag, rad, flag, numcuts, seltype);
+ em2 = bmesh_to_editmesh(bm);
+
+ free_editMesh(em);
+ *em = *em2;
+ MEM_freeN(em2);
+ BM_Free_Mesh(bm);
+}
+#endif \ No newline at end of file
diff --git a/source/blender/bmesh/operators/subdivideop.h b/source/blender/bmesh/operators/subdivideop.h
new file mode 100644
index 00000000000..7bb471117d8
--- /dev/null
+++ b/source/blender/bmesh/operators/subdivideop.h
@@ -0,0 +1,38 @@
+#ifndef _SUBDIVIDEOP_H
+#define _SUBDIVIDEOP_H
+
+typedef struct subdparams {
+ int numcuts;
+ float smooth;
+ float fractal;
+ int beauty;
+ BMOperator *op;
+} subdparams;
+
+typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params);
+
+/*
+note: this is a pattern-based edge subdivider.
+it tries to match a pattern to edge selections on faces,
+then executes functions to cut them.
+*/
+typedef struct subdpattern {
+ int seledges[20]; //selected edges mask, for splitting
+
+ /*verts starts at the first new vert cut, not the first vert in the
+ face*/
+ subd_pattern_fill_fp connectexec;
+ int len; /*total number of verts, before any subdivision*/
+} subdpattern;
+
+/*generic subdivision rules:
+
+ * two selected edges in a face should make a link
+ between them.
+
+ * one edge should do, what? make pretty topology, or just
+ split the edge only?
+*/
+
+#endif /* _SUBDIVIDEOP_H */ \ No newline at end of file
diff --git a/source/blender/bmesh/operators/triangulateop.c b/source/blender/bmesh/operators/triangulateop.c
new file mode 100644
index 00000000000..732a3a85860
--- /dev/null
+++ b/source/blender/bmesh/operators/triangulateop.c
@@ -0,0 +1,55 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define EDGE_NEW 1
+#define FACE_NEW 1
+
+void triangulate_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMFace *face, **newfaces = NULL;
+ V_DECLARE(newfaces);
+ float (*projectverts)[3] = NULL;
+ V_DECLARE(projectverts);
+ int i, lastlen=0, count = 0;
+
+ face = BMO_IterNew(&siter, bm, op, "faces", BM_FACE);
+ for (; face; face=BMO_IterStep(&siter)) {
+ if (lastlen < face->len) {
+ V_RESET(projectverts);
+ V_RESET(newfaces);
+ for (lastlen=0; lastlen<face->len; lastlen++) {
+ V_GROW(projectverts);
+ V_GROW(projectverts);
+ V_GROW(projectverts);
+ V_GROW(newfaces);
+ }
+ }
+
+ BM_Triangulate_Face(bm, face, projectverts, EDGE_NEW,
+ FACE_NEW, newfaces);
+
+ BMO_Insert_MapPointer(bm, op, "facemap",
+ face, face);
+ for (i=0; newfaces[i]; i++) {
+ BMO_Insert_MapPointer(bm, op, "facemap",
+ newfaces[i], face);
+
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_NEW, BM_EDGE);
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_NEW, BM_FACE);
+
+ V_FREE(projectverts);
+ V_FREE(newfaces);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/operators/utils.c b/source/blender/bmesh/operators/utils.c
new file mode 100644
index 00000000000..77e0b7083e2
--- /dev/null
+++ b/source/blender/bmesh/operators/utils.c
@@ -0,0 +1,91 @@
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "bmesh.h"
+
+/*
+ * UTILS.C
+ *
+ * utility bmesh operators, e.g. transform,
+ * translate, rotate, scale, etc.
+ *
+*/
+
+void bmesh_makevert_exec(BMesh *bm, BMOperator *op) {
+ float vec[3];
+
+ BMO_Get_Vec(op, "co", vec);
+
+ BMO_SetFlag(bm, BM_Make_Vert(bm, vec, NULL), 1);
+ BMO_Flag_To_Slot(bm, op, "newvertout", 1, BM_VERT);
+}
+
+void bmesh_transform_exec(BMesh *bm, BMOperator *op) {
+ BMOIter iter;
+ BMVert *v;
+ float mat[4][4];
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ BMO_ITER(v, &iter, bm, op, "verts", BM_VERT) {
+ Mat4MulVecfl(mat, v->co);
+ }
+}
+
+/*this operator calls the transform operator, which
+ is a little complex, but makes it easier to make
+ sure the transform op is working, since initially
+ only this one will be used.*/
+void bmesh_translate_exec(BMesh *bm, BMOperator *op) {
+ BMOIter iter;
+ BMVert *v;
+ float mat[4][4], vec[3];
+
+ BMO_Get_Vec(op, "vec", vec);
+
+ Mat4One(mat);
+ VECCOPY(mat[3], vec);
+
+ BMO_CallOpf(bm, "transform mat=%m4 verts=%s", mat, op, "verts");
+}
+
+void bmesh_rotate_exec(BMesh *bm, BMOperator *op) {
+ BMOIter iter;
+ BMVert *v;
+ float mat[4][4], vec[3];
+
+ BMO_Get_Vec(op, "cent", vec);
+
+ /*there has to be a proper matrix way to do this, but
+ this is how editmesh did it and I'm too tired to think
+ through the math right now.*/
+ VecMulf(vec, -1);
+ BMO_CallOpf(bm, "translate verts=%s vec=%v", op, "verts", vec);
+
+ BMO_CallOpf(bm, "transform mat=%s verts=%s", op, "mat", op, "verts");
+
+ VecMulf(vec, -1);
+ BMO_CallOpf(bm, "translate verts=%s vec=%v", op, "verts", vec);
+}
+
diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c
new file mode 100644
index 00000000000..543d64b6131
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_bevel.c
@@ -0,0 +1,918 @@
+/**
+ * BME_tools.c jan 2007
+ *
+ * Functions for changing the topology of a mesh.
+ *
+ * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle and Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+
+#include "blendef.h"
+
+/* ------- Bevel code starts here -------- */
+
+BME_TransData_Head *BME_init_transdata(int bufsize) {
+ BME_TransData_Head *td;
+
+ td = MEM_callocN(sizeof(BME_TransData_Head), "BM transdata header");
+ td->gh = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp);
+ td->ma = BLI_memarena_new(bufsize);
+ BLI_memarena_use_calloc(td->ma);
+
+ return td;
+}
+
+void BME_free_transdata(BME_TransData_Head *td) {
+ BLI_ghash_free(td->gh,NULL,NULL);
+ BLI_memarena_free(td->ma);
+ MEM_freeN(td);
+}
+
+BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BMVert *v,
+ float *co, float *org, float *vec, float *loc,
+ float factor, float weight, float maxfactor, float *max) {
+ BME_TransData *vtd;
+ int is_new = 0;
+
+ if (v == NULL) return NULL;
+
+ if ((vtd = BLI_ghash_lookup(td->gh, v)) == NULL && bm != NULL) {
+ vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd));
+ BLI_ghash_insert(td->gh, v, vtd);
+ td->len++;
+ is_new = 1;
+ }
+
+ vtd->bm = bm;
+ vtd->v = v;
+ if (co != NULL) VECCOPY(vtd->co,co);
+ if (org == NULL && is_new) { VECCOPY(vtd->org,v->co); } /* default */
+ else if (org != NULL) VECCOPY(vtd->org,org);
+ if (vec != NULL) {
+ VECCOPY(vtd->vec,vec);
+ Normalize(vtd->vec);
+ }
+ vtd->loc = loc;
+
+ vtd->factor = factor;
+ vtd->weight = weight;
+ vtd->maxfactor = maxfactor;
+ vtd->max = max;
+
+ return vtd;
+}
+
+BME_TransData *BME_get_transdata(BME_TransData_Head *td, BMVert *v) {
+ BME_TransData *vtd;
+ vtd = BLI_ghash_lookup(td->gh, v);
+ return vtd;
+}
+
+/* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */
+float *BME_new_transdata_float(BME_TransData_Head *td) {
+ return BLI_memarena_alloc(td->ma, sizeof(float));
+}
+
+static int BME_bevel_is_split_vert(BMLoop *l) {
+ /* look for verts that have already been added to the edge when
+ * beveling other polys; this can be determined by testing the
+ * vert and the edges around it for originality
+ */
+ if ((l->v->tflag1 & BME_BEVEL_ORIG)==0
+ && (l->e->tflag1 & BME_BEVEL_ORIG)
+ && (l->prev->e->tflag1 & BME_BEVEL_ORIG))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* get a vector, vec, that points from v1->co to wherever makes sense to
+ * the bevel operation as a whole based on the relationship between v1 and v2
+ * (won't necessarily be a vec from v1->co to v2->co, though it probably will be);
+ * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */
+static int BME_bevel_get_vec(float *vec, BMVert *v1, BMVert *v2, BME_TransData_Head *td) {
+ BME_TransData *vtd1, *vtd2;
+
+ vtd1 = BME_get_transdata(td,v1);
+ vtd2 = BME_get_transdata(td,v2);
+ if (!vtd1 || !vtd2) {
+ //printf("BME_bevel_get_vec() got called without proper BME_TransData\n");
+ return -1;
+ }
+
+ /* compare the transform origins to see if we can use the vert co's;
+ * if they belong to different origins, then we will use the origins to determine
+ * the vector */
+ if (VecCompare(vtd1->org,vtd2->org,0.000001f)) {
+ VECSUB(vec,v2->co,v1->co);
+ if (VecLength(vec) < 0.000001f) {
+ VecMulf(vec,0);
+ }
+ return 0;
+ }
+ else {
+ VECSUB(vec,vtd2->org,vtd1->org);
+ if (VecLength(vec) < 0.000001f) {
+ VecMulf(vec,0);
+ }
+ return 1;
+ }
+}
+
+/* "Projects" a vector perpendicular to vec2 against vec1, such that
+ * the projected vec1 + vec2 has a min distance of 1 from the "edge" defined by vec2.
+ * note: the direction, is_forward, is used in conjunction with up_vec to determine
+ * whether this is a convex or concave corner. If it is a concave corner, it will
+ * be projected "backwards." If vec1 is before vec2, is_forward should be 0 (we are projecting backwards).
+ * vec1 is the vector to project onto (expected to be normalized)
+ * vec2 is the direction of projection (pointing away from vec1)
+ * up_vec is used for orientation (expected to be normalized)
+ * returns the length of the projected vector that lies along vec1 */
+static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *td) {
+ float factor, vec3[3], tmp[3],c1,c2;
+
+ Crossf(tmp,vec1,vec2);
+ Normalize(tmp);
+ factor = Inpf(up_vec,tmp);
+ if ((factor > 0 && is_forward) || (factor < 0 && !is_forward)) {
+ Crossf(vec3,vec2,tmp); /* hmm, maybe up_vec should be used instead of tmp */
+ }
+ else {
+ Crossf(vec3,tmp,vec2); /* hmm, maybe up_vec should be used instead of tmp */
+ }
+ Normalize(vec3);
+ c1 = Inpf(vec3,vec1);
+ c2 = Inpf(vec1,vec1);
+ if (fabs(c1) < 0.000001f || fabs(c2) < 0.000001f) {
+ factor = 0.0f;
+ }
+ else {
+ factor = c2/c1;
+ }
+
+ return factor;
+}
+
+/* BME_bevel_split_edge() is the main math work-house; its responsibilities are:
+ * using the vert and the loop passed, get or make the split vert, set its coordinates
+ * and transform properties, and set the max limits.
+ * Finally, return the split vert. */
+static BMVert *BME_bevel_split_edge(BMesh *bm, BMVert *v, BMVert *v1, BMLoop *l, float *up_vec, float value, BME_TransData_Head *td) {
+ BME_TransData *vtd, *vtd1, *vtd2;
+ BMVert *sv, *v2, *v3, *ov;
+ BMLoop *lv1, *lv2;
+ BMEdge *ne, *e1, *e2;
+ float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3];
+ int is_edge, forward, is_split_vert;
+
+ if (l == NULL) {
+ /* what you call operator overloading in C :)
+ * I wanted to use the same function for both wire edges and poly loops
+ * so... here we walk around edges to find the needed verts */
+ forward = 1;
+ is_split_vert = 0;
+ if (v->edge == NULL) {
+ //printf("We can't split a loose vert's edge!\n");
+ return NULL;
+ }
+ e1 = v->edge; /* we just use the first two edges */
+ e2 = bmesh_disk_nextedge(v->edge, v);
+ if (e1 == e2) {
+ //printf("You need at least two edges to use BME_bevel_split_edge()\n");
+ return NULL;
+ }
+ v2 = BM_OtherEdgeVert(e1, v);
+ v3 = BM_OtherEdgeVert(e2, v);
+ if (v1 != v2 && v1 != v3) {
+ //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n");
+ return NULL;
+ }
+ if (v1 == v2) {
+ v2 = v3;
+ }
+ else {
+ e1 = e2;
+ }
+ ov = BM_OtherEdgeVert(e1,v);
+ sv = BM_Split_Edge(bm,v,e1,&ne,0);
+ //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+ //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+ BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+ sv->tflag1 |= BME_BEVEL_BEVEL;
+ ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+ BME_bevel_get_vec(vec1,v1,v,td);
+ BME_bevel_get_vec(vec2,v2,v,td);
+ Crossf(t_up_vec,vec1,vec2);
+ Normalize(t_up_vec);
+ up_vec = t_up_vec;
+ }
+ else {
+ /* establish loop direction */
+ if (l->v == v) {
+ forward = 1;
+ lv1 = l->next;
+ lv2 = l->prev;
+ v1 = l->next->v;
+ v2 = l->prev->v;
+ }
+ else if (l->next->v == v) {
+ forward = 0;
+ lv1 = l;
+ lv2 = l->next->next;
+ v1 = l->v;
+ v2 = l->next->next->v;
+ }
+ else {
+ //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n");
+ return NULL;
+ }
+
+ if (BME_bevel_is_split_vert(lv1)) {
+ is_split_vert = 1;
+ sv = v1;
+ if (forward) v1 = l->next->next->v;
+ else v1 = l->prev->v;
+ }
+ else {
+ is_split_vert = 0;
+ ov = BM_OtherEdgeVert(l->e,v);
+ sv = BM_Split_Edge(bm,v,l->e,&ne,0);
+ //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+ //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+ BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+ sv->tflag1 |= BME_BEVEL_BEVEL;
+ ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+ }
+
+ if (BME_bevel_is_split_vert(lv2)) {
+ if (forward) v2 = lv2->prev->v;
+ else v2 = lv2->next->v;
+ }
+ }
+
+ is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */
+ BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */
+ len = VecLength(vec1);
+ Normalize(vec1);
+
+ vtd = BME_get_transdata(td, sv);
+ vtd1 = BME_get_transdata(td, v);
+ vtd2 = BME_get_transdata(td,v1);
+
+ if (vtd1->loc == NULL) {
+ /* this is a vert with data only for calculating initial weights */
+ if (vtd1->weight < 0) {
+ vtd1->weight = 0;
+ }
+ scale = vtd1->weight/vtd1->factor;
+ if (!vtd1->max) {
+ vtd1->max = BME_new_transdata_float(td);
+ *vtd1->max = -1;
+ }
+ }
+ else {
+ scale = vtd1->weight;
+ }
+ vtd->max = vtd1->max;
+
+ if (is_edge && vtd1->loc != NULL) {
+ maxfactor = vtd1->maxfactor;
+ }
+ else {
+ maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td);
+ if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) {
+ maxfactor = vtd->maxfactor;
+ }
+ }
+
+ dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2;
+ if (is_edge || dis > maxfactor*value) {
+ dis = maxfactor*value;
+ }
+ VECADDFAC(sv->co,v->co,vec1,dis);
+ VECSUB(vec1,sv->co,vtd1->org);
+ dis = VecLength(vec1);
+ Normalize(vec1);
+ BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max);
+
+ return sv;
+}
+
+static float BME_bevel_set_max(BMVert *v1, BMVert *v2, float value, BME_TransData_Head *td) {
+ BME_TransData *vtd1, *vtd2;
+ float max, fac1, fac2, vec1[3], vec2[3], vec3[3];
+
+ BME_bevel_get_vec(vec1,v1,v2,td);
+ vtd1 = BME_get_transdata(td,v1);
+ vtd2 = BME_get_transdata(td,v2);
+
+ if (vtd1->loc == NULL) {
+ fac1 = 0;
+ }
+ else {
+ VECCOPY(vec2,vtd1->vec);
+ VecMulf(vec2,vtd1->factor);
+ if (Inpf(vec1, vec1)) {
+ Projf(vec2,vec2,vec1);
+ fac1 = VecLength(vec2)/value;
+ }
+ else {
+ fac1 = 0;
+ }
+ }
+
+ if (vtd2->loc == NULL) {
+ fac2 = 0;
+ }
+ else {
+ VECCOPY(vec3,vtd2->vec);
+ VecMulf(vec3,vtd2->factor);
+ if (Inpf(vec1, vec1)) {
+ Projf(vec2,vec3,vec1);
+ fac2 = VecLength(vec2)/value;
+ }
+ else {
+ fac2 = 0;
+ }
+ }
+
+ if (fac1 || fac2) {
+ max = VecLength(vec1)/(fac1 + fac2);
+ if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+ *vtd1->max = max;
+ }
+ if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+ *vtd2->max = max;
+ }
+ }
+ else {
+ max = -1;
+ }
+
+ return max;
+}
+
+static BMVert *BME_bevel_wire(BMesh *bm, BMVert *v, float value, int res, int options, BME_TransData_Head *td) {
+ BMVert *ov1, *ov2, *v1, *v2;
+
+ ov1 = BM_OtherEdgeVert(v->edge, v);
+ ov2 = BM_OtherEdgeVert(bmesh_disk_nextedge(v->edge, v), v);
+
+ /* split the edges */
+ v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td);
+ v1->tflag1 |= BME_BEVEL_NONMAN;
+ v2 = BME_bevel_split_edge(bm,v,ov2,NULL,NULL,value,td);
+ v2->tflag1 |= BME_BEVEL_NONMAN;
+
+ if (value > 0.5) {
+ BME_bevel_set_max(v1,ov1,value,td);
+ BME_bevel_set_max(v2,ov2,value,td);
+ }
+
+ /* remove the original vert */
+ if (res) {
+ bmesh_jekv;
+
+ //void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, int calcnorm){
+ //hrm, why is there a fac here? it just removes a vert
+ BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
+ //bmesh_jekv(bm,v->edge,v);
+ }
+
+ return v1;
+}
+
+static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+ BMVert *v1, *v2, *kv;
+ BMLoop *kl=NULL, *nl;
+ BMEdge *e;
+ BMFace *f;
+
+ f = l->f;
+ e = l->e;
+
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) == 0
+ && ((l->v->tflag1 & BME_BEVEL_BEVEL) || (l->next->v->tflag1 & BME_BEVEL_BEVEL)))
+ { /* sanity check */
+ return l;
+ }
+
+ /* checks and operations for prev edge */
+ /* first, check to see if this edge was inset previously */
+ if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0
+ && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+ kl = l->prev->radial.next->data;
+ if (kl->v == l->v) kl = kl->prev;
+ else kl = kl->next;
+ kv = l->v;
+ }
+ else {
+ kv = NULL;
+ }
+ /* get/make the first vert to be used in SFME */
+ if (l->v->tflag1 & BME_BEVEL_NONMAN){
+ v1 = l->v;
+ }
+ else { /* we'll need to split the previous edge */
+ v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+ }
+ /* if we need to clean up geometry... */
+ if (kv) {
+ l = l->next;
+ if (kl->v == kv) {
+ BM_Split_Face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+ bmesh_jfke(bm,((BMLoop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+
+ }
+ else {
+ BM_Split_Face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+ bmesh_jfke(bm,((BMLoop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ l = l->prev;
+ }
+
+ /* checks and operations for the next edge */
+ /* first, check to see if this edge was inset previously */
+ if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0
+ && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+ kl = l->next->radial.next->data;
+ if (kl->v == l->next->v) kl = kl->prev;
+ else kl = kl->next;
+ kv = l->next->v;
+ }
+ else {
+ kv = NULL;
+ }
+ /* get/make the second vert to be used in SFME */
+ if (l->next->v->tflag1 & BME_BEVEL_NONMAN) {
+ v2 = l->next->v;
+ }
+ else { /* we'll need to split the next edge */
+ v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+ }
+ /* if we need to clean up geometry... */
+ if (kv) {
+ if (kl->v == kv) {
+ BM_Split_Face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+ bmesh_jfke(bm,((BMLoop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ else {
+ BM_Split_Face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+ bmesh_jfke(bm,((BMLoop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ }
+
+ if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) {
+ BM_Split_Face(bm,f,v2,v1,&l,e);
+ l->e->tflag1 = BME_BEVEL_BEVEL;
+ l = l->radial.next->data;
+ }
+
+ if (l->f != f){
+ //printf("Whoops! You got something out of order in BME_bevel_edge()!\n");
+ }
+
+ return l;
+}
+
+static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+ BMVert *v1, *v2;
+ BMFace *f;
+
+ /* get/make the first vert to be used in SFME */
+ /* may need to split the previous edge */
+ v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+
+ /* get/make the second vert to be used in SFME */
+ /* may need to split this edge (so move l) */
+ l = l->prev;
+ v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+ l = l->next->next;
+
+ /* "cut off" this corner */
+ f = BM_Split_Face(bm,l->f,v2,v1,NULL,l->e);
+
+ return l;
+}
+
+/**
+ * BME_bevel_poly
+ *
+ * Polygon inset tool:
+ *
+ * Insets a polygon/face based on the tflag1's of its vertices
+ * and edges. Used by the bevel tool only, for now.
+ * The parameter "value" is the distance to inset (should be negative).
+ * The parameter "options" is not currently used.
+ *
+ * Returns -
+ * A BMFace pointer to the resulting inner face.
+*/
+static BMFace *BME_bevel_poly(BMesh *bm, BMFace *f, float value, int options, BME_TransData_Head *td) {
+ BMLoop *l, *ol;
+ BME_TransData *vtd1, *vtd2;
+ float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1;
+ int len, i;
+
+ up_vec[0] = 0.0f;
+ up_vec[1] = 0.0f;
+ up_vec[2] = 0.0f;
+ /* find a good normal for this face (there's better ways, I'm sure) */
+ ol = f->loopbase;
+ l = ol->next;
+ for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) {
+ BME_bevel_get_vec(vec1,l->next->v,ol->v,td);
+ BME_bevel_get_vec(vec2,l->v,ol->v,td);
+ Crossf(vec3,vec2,vec1);
+ VECADD(up_vec,up_vec,vec3);
+ i++;
+ }
+ VecMulf(up_vec,1.0f/i);
+ Normalize(up_vec);
+
+ for (i=0,len=f->len; i<len; i++,l=l->next) {
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) {
+ max = 1.0f;
+ l = BME_bevel_edge(bm, l, value, options, up_vec, td);
+ }
+
+ else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) {
+ max = 1.0f;
+ l = BME_bevel_vert(bm, l, value, options, up_vec, td);
+ }
+ }
+
+ /* max pass */
+ if (value > 0.5 && max > 0) {
+ max = -1;
+ for (i=0,len=f->len; i<len; i++,l=l->next) {
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) {
+ BME_bevel_get_vec(vec1,l->v,l->next->v,td);
+ vtd1 = BME_get_transdata(td,l->v);
+ vtd2 = BME_get_transdata(td,l->next->v);
+ if (vtd1->loc == NULL) {
+ fac1 = 0;
+ }
+ else {
+ VECCOPY(vec2,vtd1->vec);
+ VecMulf(vec2,vtd1->factor);
+ if (Inpf(vec1, vec1)) {
+ Projf(vec2,vec2,vec1);
+ fac1 = VecLength(vec2)/value;
+ }
+ else {
+ fac1 = 0;
+ }
+ }
+ if (vtd2->loc == NULL) {
+ fac2 = 0;
+ }
+ else {
+ VECCOPY(vec3,vtd2->vec);
+ VecMulf(vec3,vtd2->factor);
+ if (Inpf(vec1, vec1)) {
+ Projf(vec2,vec3,vec1);
+ fac2 = VecLength(vec2)/value;
+ }
+ else {
+ fac2 = 0;
+ }
+ }
+ if (fac1 || fac2) {
+ max = VecLength(vec1)/(fac1 + fac2);
+ if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+ *vtd1->max = max;
+ }
+ if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+ *vtd2->max = max;
+ }
+ }
+ }
+ }
+ }
+
+ return l->f;
+}
+
+static void BME_bevel_add_vweight(BME_TransData_Head *td, BMesh *bm, BMVert *v, float weight, float factor, int options) {
+ BME_TransData *vtd;
+
+ if (v->tflag1 & BME_BEVEL_NONMAN) return;
+ v->tflag1 |= BME_BEVEL_BEVEL;
+ if ( (vtd = BME_get_transdata(td, v)) ) {
+ if (options & BME_BEVEL_EMIN) {
+ vtd->factor = 1.0;
+ if (vtd->weight < 0 || weight < vtd->weight) {
+ vtd->weight = weight;
+ }
+ }
+ else if (options & BME_BEVEL_EMAX) {
+ vtd->factor = 1.0;
+ if (weight > vtd->weight) {
+ vtd->weight = weight;
+ }
+ }
+ else if (vtd->weight < 0) {
+ vtd->factor = factor;
+ vtd->weight = weight;
+ }
+ else {
+ vtd->factor += factor; /* increment number of edges with weights (will be averaged) */
+ vtd->weight += weight; /* accumulate all the weights */
+ }
+ }
+ else {
+ /* we'll use vtd->loc == NULL to mark that this vert is not moving */
+ vtd = BME_assign_transdata(td, bm, v, v->co, NULL, NULL, NULL, factor, weight, -1, NULL);
+ }
+}
+
+
+static bevel_init_verts(BMesh *bm, int options, BME_TransData_Head *td){
+ BMVert *v;
+ float weight;
+ for(v=bm->verts.first; v; v=v->next){
+ weight = 0.0;
+ if(!(v->tflag1 & BME_BEVEL_NONMAN)){
+ if(options & BME_BEVEL_SELECT){
+ if(v->flag & SELECT) weight = 1.0;
+ }
+ else if(options & BME_BEVEL_WEIGHT) weight = v->bweight;
+ else weight = 1.0;
+ if(weight > 0.0){
+ v->tflag1 |= BME_BEVEL_BEVEL;
+ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0,weight, -1, NULL);
+ }
+ }
+ }
+}
+static bevel_init_edges(BMesh *bm, int options, BME_TransData_Head *td){
+ BMEdge *e;
+ int count;
+ float weight;
+ for( e = BM_first_element(bm, BME_EDGE); e; e = BM_next_element(bm, BME_EDGE, e)){
+ weight = 0.0;
+ if(!(e->tflag1 & BME_BEVEL_NONMAN)){
+ if(options & BME_BEVEL_SELECT){
+ if(e->flag & SELECT) weight = 1.0;
+ }
+ else if(options & BME_BEVEL_WEIGHT){
+ weight = e->bweight;
+ }
+ else{
+ weight = 1.0;
+ }
+ if(weight > 0.0){
+ e->tflag1 |= BME_BEVEL_BEVEL;
+ e->v1->tflag1 |= BME_BEVEL_BEVEL;
+ e->v2->tflag1 |= BME_BEVEL_BEVEL;
+ BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options);
+ BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options);
+ }
+ }
+ }
+
+ /*clean up edges with 2 faces that share more than one edge*/
+ for( e = BM_first_element(bm, BME_EDGE); e; e = BM_next_element(bm, BME_EDGE, e)){
+ if(e->tflag1 & BME_BEVEL_BEVEL){
+ count = BM_face_sharededges(e->loop->f, ((BMLoop*)e->loop->radial.next->data)->f);
+ if(count > 1) e->tflag1 &= ~BME_BEVEL_BEVEL;
+ }
+ }
+}
+static BMesh *BME_bevel_initialize(BMesh *bm, int options, int defgrp_index, float angle, BME_TransData_Head *td){
+
+ BMVert *v, *v2;
+ BMEdge *e, *curedge;
+ BMFace *f;
+ BMIter iter;
+ int wire, len;
+
+ for (v = BMIter_New(&iter, bm, BM_VERTS, nm); v; v = BMIter_Step(&iter)) v->tflag1 = 0;
+ for (e = BMIter_New(&iter, bm, BM_EDGES, nm); e; e = BMIter_Step(&iter)) e->tflag1 = 0;
+ for (f = BMIter_New(&iter, bm, BM_FACES, nm); f; f = BMIter_Step(&iter)) f->tflag1 = 0;
+
+ /*tag non-manifold geometry*/
+ for (v = BMIter_New(&iter, bm, BM_VERTS, nm); v; v = BMIter_Step(&iter)) {
+ v->tflag1 = BME_BEVEL_ORIG;
+ if(v->edge){
+ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL);
+ if (BM_Nonmanifold_Vert(bm,v)) v->tflag1 |= BME_BEVEL_NONMAN;
+ /*test wire vert*/
+ len = bmesh_cycle_length(bmesh_disk_getpointer(v->edge,v));
+ if(len == 2 && BME_wirevert(bm, v)) v->tflag1 &= ~BME_BEVEL_NONMAN;
+ }else v->tflag1 |= BME_BEVEL_NONMAN;
+ }
+
+ for (e = BMIter_New(&iter, bm, BM_EDGES, nm); e; e = BMIter_Step(&iter)) {
+ e->tflag1 = BME_BEVEL_ORIG;
+ if (e->loop == NULL || BME_cycle_length(&(e->loop->radial)) > 2){
+ e->v1->tflag1 |= BME_BEVEL_NONMAN;
+ e->v2->tflag1 |= BME_BEVEL_NONMAN;
+ e->tflag1 |= BME_BEVEL_NONMAN;
+ }
+ if((e->v1->tflag1 & BME_BEVEL_NONMAN) || (e->v2->tflag1 & BME_BEVEL_NONMAN)) e->tflag1 |= BME_BEVEL_NONMAN;
+ }
+
+ for (f = BMIter_New(&iter, bm, BM_FACES, nm); f; f = BMIter_Step(&iter))
+ f->tflag1 = BME_BEVEL_ORIG;
+ if(options & BME_BEVEL_VERT) bevel_init_verts(bm, options, td);
+ else bevel_init_edges(bm, options, td);
+ return bm;
+
+}
+static BMesh *BME_bevel_reinitialize(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ for (v = BMIter_New(bm, BM_VERTS, NULL); v; v = BMIter_Step(bm)){
+ v->tflag1 |= BME_BEVEL_ORIG;
+ v->tflag2 = 0;
+ }
+ for (e = BMIter_New(bm, BM_EDGES, NULL); e; e = BMIter_Step(bm)){
+ e->tflag1 |= BME_BEVEL_ORIG;
+ }
+ for (f = BMIter_New(bm, BM_FACES, NULL); f; f = BMIter_Step(bm)){
+ f->tflag1 |= BME_BEVEL_ORIG;
+ }
+ return bm;
+
+}
+
+/**
+ * BME_bevel_mesh
+ *
+ * Mesh beveling tool:
+ *
+ * Bevels an entire mesh. It currently uses the tflag1's of
+ * its vertices and edges to track topological changes.
+ * The parameter "value" is the distance to inset (should be negative).
+ * The parameter "options" is not currently used.
+ *
+ * Returns -
+ * A BMesh pointer to the BM passed as a parameter.
+*/
+
+static BMMesh *BME_bevel_mesh(BMMesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) {
+ BMVert *v, *nv;
+ BMEdge *e, *curedge, *ne;
+ BMLoop *l, *l2;
+ BMFace *f, *nf;
+
+ BMeshIter verts;
+ BMeshIter edges;
+ BMeshIter loops;
+ BMeshIter faces;
+
+ unsigned int i, len;
+
+ /*bevel polys*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f; f = BMeshIter_step(faces)){
+ if(bmesh_test_flag(f, BME_BEVEL_ORIG){
+ bevel_poly(bm,f,value,options,td);
+ }
+ }
+ /*get rid of beveled edges*/
+ for(e = BMeshIter_init(edges, BM_EDGES, bm, 0); e;){
+ ne = BMeshIter_step(edges);
+ if( bmesh_test_flag(e, BME_BEVEL_BEVEL) && bmesh_test_flag(e, BME_BEVEL_ORIG) ) bmesh_join_faces(bm, e->loop->f, ((BMLoop*)e->loop->radial.next->data)->f, e, 1);
+ e = ne;
+ }
+ /*link up corners and clip*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v;){
+ nv = BMeshIter_step(verts)
+ if( bmesh_test_flag(v, BME_BEVEL_ORIG) && bmesh_test_flag(v, BME_BEVEL_BEVEL)){
+ curedge = v->edge;
+ do{
+ l = curedge->loop;
+ l2 = l->radial.next->data;
+ if(l->v != v) l = l->next;
+ if(l2->v != v) l2 = l2->next;
+ if(l->f->len > 3) BM_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */
+ if(l2->f->len > 3) BM_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */
+ curedge = BM_edge_of_vert(curedge, v);
+ }while(curedge != v->edge);
+ BM_dissolve_disk(bm,v);
+ }
+ v = nv;
+ }
+
+ /*Debug print, remove*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f;){
+ if(f->len == 2){
+ printf("warning");
+ }
+ }
+
+ return bm;
+}
+
+BMesh *BME_bevel(BMMesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) {
+ BMVert *v;
+ BMEdge *e;
+ BMIter *verts;
+
+ BME_TransData_Head *td;
+ BME_TransData *vtd;
+ int i;
+ double fac=1, d;
+
+
+ td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE);
+ /* recursion math courtesy of Martin Poirier (theeth) */
+ for (i=0; i<res-1; i++) {
+ if (i==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * i * 2.0f);
+ }
+ d = 1.0f/fac;
+
+
+ for (i=0; i<res || (res==0 && i==0); i++) {
+ BME_bevel_initialize(bm, options, defgrp_index, angle, td);
+ //if (i != 0) BME_bevel_reinitialize(bm);
+ bmesh_begin_edit(bm);
+ BME_bevel_mesh(bm,(float)d,res,options,defgrp_index,td);
+ bmesh_end_edit(bm);
+ if (i==0) d /= 3; else d /= 2;
+ }
+
+ BME_model_begin(bm);
+ BME_tesselate(bm);
+ BME_model_end(bm);
+
+
+ /*interactive preview?*/
+ if (rtd) {
+ *rtd = td;
+ return bm;
+ }
+
+ /* otherwise apply transforms */
+ for( v = BMeshIter_init(verts); v; v = BMeshIter_step(verts)){
+ if ( (vtd = BME_get_transdata(td, v)) ) {
+ if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) {
+ d = *vtd->max;
+ }
+ else {
+ d = value;
+ }
+ VECADDFAC(v->co,vtd->org,vtd->vec,vtd->factor*d);
+ }
+ v->tflag1 = 0;
+ }
+
+ BME_free_transdata(td);
+ return bm;
+}
diff --git a/source/blender/bmesh/tools/BME_dupe_ops.c b/source/blender/bmesh/tools/BME_dupe_ops.c
new file mode 100644
index 00000000000..533e278ea68
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_dupe_ops.c
@@ -0,0 +1,318 @@
+/*
+ * BME_DUPLICATE.C
+ *
+ * This file contains functions for duplicating, copying, and splitting
+ * elements from a bmesh.
+ *
+ */
+
+/*
+ * COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+
+static BMVert *copy_vertex(BMMesh *source_mesh, BMVert *source_vertex, BMMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*create a new vertex*/
+ target_vertex = BM_Make_Vert(target, source_vertex->co, NULL);
+
+ /*insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->data, &target_vertex->data);
+
+ /*Copy Markings*/
+ if(BM_Is_Selected((BMHeader*)source_vertex)) BM_Select_Vert(target_mesh, target_vertex, 1);
+ if(BM_Is_Hidden((BMHeader*)source_vertex)) BM_Mark_Hidden((BMHeader*)target_vertex, 1);
+
+ BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
+
+ return target_vertex;
+}
+
+/*
+ * COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+
+static BMEdge *copy_edge(BMMesh *source_mesh, BMEdge *source_edge, BMMesh *target_mesh, GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+
+ /*lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*create a new edge*/
+ target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->data, &target_edge->data);
+
+ /*copy flags*/
+ if(BM_Is_Selected((BMHeader*) source_edge)) BM_Select_Edge(target_mesh, target_edge, 1);
+ if(BM_Is_Hidden((BMHeader*) source_edge)) BM_Mark_Hidden(target_mesh, target_edge, 1);
+ if(BM_Is_Sharp((BMHeader*) source_edge)) BM_Mark_Sharp(target_edge, 1);
+ if(BM_Is_Seam((BMHeader*) source_edge)) BM_Mark_Seam(target_edge, 1);
+ if(BM_Is_Fgon((BMHeader*) source_edge)) BM_Mark_Fgon(target_edge, 1);
+
+ BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
+
+ return target_edge;
+}
+
+/*
+ * COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+
+static BMFace *copy_face(BMMesh *source_mesh, BMFace *source_face, BMMesh *target_mesh, BMEdge **edar, GHash *verthash, GHash *ehash)
+{
+ BMEdge *target_edge;
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ int i;
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_face->loopbase->v);
+ target_vert2 = BLI_ghash_lookup(vhash, source_face->loopbase->next->v);
+
+ /*lookup edges*/
+ i = 0;
+ source_loop = source_face->loopbase;
+ do{
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ i++;
+ source_loop = source_loop->next;
+ }while(source_loop != source_face->loopbase);
+
+ /*create new face*/
+ target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
+
+ /*we copy custom data by hand, we cannot assume that customdata byte layout will be exactly the same....*/
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->data, &target_face->data);
+
+ /*copy flags*/
+ if(BM_Is_Selected((BMHeader*)source_face)) BM_Select_face(target, target_face, 1);
+ if(BM_Is_Hidden((BMHeader*)source_face)) BM_Mark_Hidden((BMHeader*)target_face, 1);
+
+ /*mark the face for output*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
+
+ /*copy per-loop custom data*/
+ source_loop = source_face->loopbase;
+ target_loop = target_face->loopbase;
+ do{
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->data, &target_loop->data);
+ source_loop = source_loop->next;
+ target_loop = target_loop->next;
+ }while(source_loop != source_face->loopbase);
+
+ return target_face;
+}
+
+/*
+ * COPY MESH
+ *
+ * Internal Copy function.
+*/
+
+/*local flag defines*/
+
+#define DUPE_INPUT 1 /*input from operator*/
+#define DUPE_NEW 2
+#define DUPE_DONE 3
+
+static void copy_mesh(BMMesh *source, BMMesh *target)
+{
+
+ BMVert *v = NULL;
+ BMEdge *e = NULL, **edar = NULL;
+ BMLoop *l = NULL;
+ BMFace *f = NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0, flag;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrrhash, BLI_ghashutil_ptrcmp);
+
+ /*initialize edge pointer array*/
+ for(f = BMIter_New(&faces, source, BM_FACES, source, 0, NULL); f; f = BMIter_Step(&faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMIter_New(&faces, source, BM_FACES, source, 0, NULL); f; f= BMIter_Step(&faces)){
+ if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
+ /*vertex pass*/
+ for(v = BMIter_New(&verts, source, BM_VERT_OF_FACE, f, 0, NULL); v; v = BMIter_Step(&verts)){
+ if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){
+ copy_vertex(source,v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*edge pass*/
+ for(e = BMIter_New(&edges, source, BM_EDGE_OF_FACE, f, 0, NULL); e; e = BMeshIter_step(&edges)){
+ if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
+ copy_edge(source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+ copy_face(source, f, target, edar, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMIter_New(&edges, source, BM_EDGES, source, 0, NULL); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
+ /*make sure that verts are copied*/
+ if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE){
+ copy_vertex(source, e->v1, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
+ }
+ if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE){
+ copy_vertex(source, e->v2, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
+ }
+ /*now copy the actual edge*/
+ copy_edge(source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+
+ /*finally dupe all loose vertices*/
+ for(v = BMIter_New(&verts, source, BM_VERTS, source, 0, NULL); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
+ copy_vertex(source, v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ if(edar)
+ MEM_freeN(edar);
+}
+/*
+BMMesh *bmesh_make_mesh_from_mesh(BMMesh *bm, int allocsize[4])
+{
+ BMMesh *target = NULL;
+ target = bmesh_make_mesh(allocsize);
+
+
+ CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+
+ CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
+
+ bmesh_begin_edit(bm);
+ bmesh_begin_edit(target);
+
+ bmesh_copy_mesh(bm, target, 0);
+
+ bmesh_end_edit(bm);
+ bmesh_end_edit(target);
+
+ return target;
+
+}
+*/
+
+void dupeop_exec(BMMesh *bm, BMOperator *op)
+{
+ BMOperator *dupeop = op;
+ BMOpSlot *vinput, *einput, *finput, *vnew, *enew, *fnew;
+ int i;
+
+ vinput = BMO_Get_Slot(dupeop, BMOP_DUPE_VINPUT);
+ einput = BMO_Get_Slot(dupeop, BMOP_DUPE_EINPUT);
+ finput = BMO_Get_Slot(dupeop, BMOP_DUPE_FINPUT);
+
+ /*go through vinput, einput, and finput and flag elements with private flags*/
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_VINPUT, DUPE_INPUT);
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_EINPUT, DUPE_INPUT);
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_FINPUT, DUPE_INPUT);
+
+ /*use the internal copy function*/
+ copy_mesh(bm, bm);
+
+ /*Output*/
+ /*First copy the input buffers to output buffers - original data*/
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, vinput, BMO_Get_Slot(dupeop, BMOP_DUPE_VORIGINAL));
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, einput, BMO_Get_Slot(dupeop, BMOP_DUPE_EORIGINAL));
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, finput, BMO_Get_Slot(dupeop, BMOP_DUPE_FORIGINAL));
+
+ /*Now alloc the new output buffers*/
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_VNEW, DUPE_NEW, BMESH_VERT);
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_ENEW, DUPE_NEW, BMESH_EDGE);
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_FNEW, DUPE_NEW, BMESH_FACE);
+}
+
+void splitop_exec(BMMesh *bm, BMOperator *op)
+{
+ BMOperator *splitop = op;
+ BMOperator dupeop;
+ BMOperator delop;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, BMOP_DUPE);
+ BMO_Init_Op(&delop, BMOP_DEL);
+
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_VINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_VINPUT));
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_EINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_EINPUT));
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_FINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_FINPUT));
+
+ BMO_Exec_Op(&dupeop);
+
+ /*connect outputs of dupe to delete*/
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_VORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_VINPUT));
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_EORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_EINPUT));
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_FORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_FINPUT));
+
+ BMO_Exec_Op(&delop);
+
+ /*now we make our outputs by copying the dupe outputs*/
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_VNEW), BMO_Get_Slot(splitop, BMOP_SPLIT_VOUTPUT));
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_ENEW), BMO_Get_Slot(splitop, BMOP_SPLIT_EOUTPUT));
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_FNEW), BMO_Get_Slot(splitop, BMOP_SPLIT_FOUTPUT));
+
+ /*cleanup*/
+ BMO_Finish_Op(&dupeop);
+ BMO_Finish_Op(&delop);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/tools/BME_duplicate.c b/source/blender/bmesh/tools/BME_duplicate.c
new file mode 100644
index 00000000000..7c679ff6a89
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_duplicate.c
@@ -0,0 +1,307 @@
+/*
+ * BME_DUPLICATE.C
+ *
+ * This file contains functions for duplicating, copying, and splitting
+ * elements from a bmesh.
+ *
+ */
+
+/*
+ * BMESH COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+
+static BMVert *bmesh_copy_vertex(BMMesh *source_mesh, BMVert *source_vertex, BMMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*create a new vertex*/
+ target_vertex = bmesh_make_vert(target, source_vertex->co, NULL);
+
+ /*insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->data, &target_vertex->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_vertex, BMESH_SELECT)) bmesh_set_flag(target_vertex, BMESH_SELECT);
+ if(bmesh_test_flag(source_vertex, BMESH_HIDDEN)) bmesh_set_flag(target_vertex, BMESH_HIDDEN);
+
+ return target_vertex;
+}
+
+/*
+ * BMESH COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+
+static BMEdge *bmesh_copy_edge(BMMesh *source_mesh, BMEdge *source_edge, BMMesh *target_mesh, GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+
+ /*lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*create a new edge*/
+ target_edge = bmesh_make_edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->data, &target_edge->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_edge, BMESH_SELECT)) bmesh_set_flag(target_edge, BMESH_SELECT);
+ if(bmesh_test_flag(source_edge, BMESH_HIDDEN)) bmesh_set_flag(target_edge, BMESH_SELECT);
+ if(bmesh_test_flag(source_edge, BMESH_SHARP)) bmesh_set_flag(target_edge, BMESH_SHARP);
+ if(bmesh_test_flag(source_edge, BMESH_SEAM)) bmesh_set_flag(target_edge, BMESH_SEAM);
+ if(bmesh_test_flag(source_edge, BMESH_FGON)) bmesh_set_flag(target_edge, BMESH_FGON);
+
+ return target_edge;
+}
+
+/*
+ * BMESH COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+
+static BMFace *bmesh_copy_face(BMMesh *source_mesh, BMFace *source_face, BMMesh *target_mesh, BMEdge **edar, GHash *verthash, GHash *ehash)
+{
+ BMEdge *target_edge;
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ int i;
+
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_face->loopbase->v);
+ target_vert2 = BLI_ghash_lookup(vhash, source_face->loopbase->next->v);
+
+ /*lookup edges*/
+ i = 0;
+ source_loop = source_face->loopbase;
+ do{
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ i++;
+ source_loop = source_loop->next;
+ }while(source_loop != source_face->loopbase);
+
+ /*create new face*/
+ target_face = bmesh_make_ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
+
+ /*we copy custom data by hand, we cannot assume that customdata byte layout will be exactly the same....*/
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->data, &target_face->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_face, BMESH_SELECT)) bmesh_set_flag(target_face, BMESH_SELECT);
+ if(bmesh_test_flag(source_face, BMESH_HIDDEN)) bmesh_set_flag(target_face, BMESH_HIDDEN);
+
+ /*mark the face as dirty for normal and tesselation calcs*/
+ bmesh_set_flag(target_face, BMESH_DIRTY);
+
+ /*copy per-loop custom data*/
+ source_loop = source_face->loopbase;
+ target_loop = target_face->loopbase;
+ do{
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->data, &target_loop->data);
+ source_loop = source_loop->next;
+ target_loop = target_loop->next;
+ }while(source_loop != source_face->loopbase);
+
+ return target_face;
+}
+
+/*
+ * BMESH COPY MESH
+ *
+ * Internal Copy function. copies flagged elements from
+ * source to target, which may in fact be the same mesh.
+ * Note that if __flag is 0, all elements will be copied.
+ *
+*/
+
+static void bmesh_copy_mesh(BMMesh *source, BMMesh *target, int __flag)
+{
+
+ BMVert *v;
+ BMEdge *e, **edar;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0, flag;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrrhash, BLI_ghashutil_ptrcmp);
+
+ /*initialize edge pointer array*/
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f = BMeshIter_step(faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+
+ /*begin modelling loop for target*/
+ bmesh_begin_edit(target);
+
+ /*we make special exception for __flag == 0... we copy all*/
+ if(!__flag){
+ flag = BMESH_DUPE;
+ for(v = BMeshIter_init(verts, BM_VERTS, source, 0); v; v = BMeshIter_step(verts)) bmesh_set_flag(v, BMESH_DUPE);
+ for(e = BMeshIter_init(verts, BM_EDGES, source, 0); e; e = BMeshIter_step(edges)) bmesh_set_flag(e, BMESH_DUPE);
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f = BMeshIter_step(faces)) bmesh_set_flag(f, BMESH_DUPE);
+ } else{
+ flag = __flag;
+ }
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f= BMeshIter_step(faces)){
+ if(bmesh_test_flag(f, flag)){
+ /*vertex pass*/
+ for(l = BMeshIter_init(loops, BMESH_LOOP_OF_MESH, f, 0); l; l = BMeshIter_step(loops)){
+ if(!bmesh_test_flag(l->v, BMESH_DUPED)){
+ bmesh_copy_vertex(source,l->v, target, vhash);
+ bmesh_set_flag(l->v, BMESH_DUPED);
+ }
+ }
+
+ /*edge pass*/
+ for(l = BMeshIter_init(loops, BMESH_LOOP_OF_MESH, f, 0); l; l = BMeshIter_step(loops)){
+ if(!bmesh_test_flag(l->e, BMESH_DUPED)){
+ bmesh_copy_edge(source, l->e, target, vhash, ehash);
+ bmesh_set_flag(l->e, BMESH_DUPED);
+ }
+ }
+ bmesh_copy_face(source, f, target, edar, vhash, ehash);
+ bmesh_set_flag(f, BMESH_DUPED);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMeshIter_init(edges, BM_EDGES, source, 0); e; e = BMeshIter_step(edges)){
+ if(bmesh_test_flag(e, flag) && (!bmesh_test_flag(e, BMESH_DUPED))){
+ /*make sure that verts are copied*/
+ if(!bmesh_test_flag(e->v1, BMESH_DUPED)){
+ bmesh_copy_vertex(source, e->v1, target, vhash);
+ bmesh_set_flag(e->v1, BMESH_DUPED);
+ }
+ if(!bmesh_test_flag(e->v2, BMESH_DUPED)){
+ bmesh_copy_vertex(source, e->v2, target, vhash);
+ bmesh_set_flag(e->v2, BMESH_DUPED);
+ }
+ /*now copy the actual edge*/
+ bmesh_copy_edge(source, e, target, vhash, ehash);
+ bmesh_set_flag(e, BMESH_DUPED);
+ }
+ }
+
+ /*finally dupe all loose vertices*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v; v = BMeshIter_step(verts)){
+ if(bmesh_test_flag(v, flag) && (!bmesh_test_flag(v, BMESH_DUPED))){
+ bmesh_copy_vertex(source, v, target, vhash);
+ bmesh_set_flag(v, BMESH_DUPED);
+ }
+ }
+
+ /*finish*/
+ bmesh_end_edit(target, BMESH_CALC_NORM | BMESH_CALC_TESS);
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ MEM_freeN(edar);
+}
+
+/*
+ * BMESH MAKE MESH FROM MESH
+ *
+ * Creates a new mesh by duplicating an existing one.
+ *
+*/
+
+BMMesh *bmesh_make_mesh_from_mesh(BMMesh *bm, int allocsize[4])
+{
+ BMMesh *target = NULL;
+ target = bmesh_make_mesh(allocsize);
+
+ /*copy custom data layout*/
+ CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*initialize memory pools*/
+ CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
+
+ bmesh_begin_edit(bm);
+ bmesh_begin_edit(target);
+
+ bmesh_copy_mesh(bm, target, 0); /*copy all elements*/
+
+ bmesh_end_edit(bm);
+ bmesh_end_edit(target);
+
+ return target;
+
+}
+
+/*
+ * BMESH SPLIT MESH
+ *
+ * Copies flagged elements then deletes them.
+ *
+*/
+
+void bmesh_split_mesh(BMMesh *bm, int flag){
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ bmesh_begin_edit(bm);
+ bmesh_copy_mesh(bm, bm, flag);
+
+ /*mark verts for deletion*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v; v = BMeshIter_step(verts)){
+ if(bmesh_test_flag(v, flag)) bmesh_delete_vert(bm, v);
+ }
+ /*mark edges for deletion*/
+ for(e = BMeshIter_init(edges, BM_EDGES, bm, 0); e; e = BMeshIter_step(edges)){
+ if(bmesh_test_flag(e, flag)) bmesh_delete_edge(bm, e);
+
+ }
+ /*mark faces for deletion*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f; f= BMeshIter_step(faces)){
+ if(bmesh_tes t_flag(f, flag)) bmesh_delete_face(bm, f);
+
+ }
+ bmesh_end_edit(bm);
+}
+
diff --git a/source/blender/bmesh/tools/BME_extrude.c b/source/blender/bmesh/tools/BME_extrude.c
new file mode 100644
index 00000000000..b7b3a94893d
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_extrude.c
@@ -0,0 +1,216 @@
+/**
+ * BMESH EXTRUDE TOOL
+ *
+ * A rewrite of the old editmesh extrude code with the
+ * redundant parts broken into multiple functions
+ * in an effort to reduce code. This works with multiple
+ * selection modes, and is intended to build the
+ * extrusion in steps, depending on what elements are selected.
+ * Also decoupled the calculation of transform normal
+ * and put it in UI where it probably is more appropriate
+ * for the moment.
+ *
+ * TODO:
+ * -Fit this into the new 'easy' API.
+*/
+
+void BME_extrude_verts(BME_Mesh *bm, GHash *vhash){
+ BMVert *v, *nv = NULL;
+ BMEdge *ne = NULL;
+ float vec[3];
+
+ //extrude the vertices
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v)){
+ VECCOPY(vec,v->co);
+ nv = BME_MV(bm,vec);
+ nv->tflag2 =1; //mark for select
+ ne = BME_ME(bm,v,nv);
+ ne->tflag1 = 2; //mark as part of skirt 'ring'
+ BLI_ghash_insert(vhash,v,nv);
+ BME_VISIT(v);
+ }
+ }
+}
+
+void BME_extrude_skirt(BME_Mesh *bm, GHash *ehash){
+
+ BMFace *nf=NULL;
+ BMEdge *e, *l=NULL, *r=NULL, *edar[4], *ne;
+ BMVert *v, *v1, *v2, *lv, *rv, *nv;
+
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e)){
+ /*find one face incident upon e and use it for winding of new face*/
+ if(e->loop){
+ v1 = e->loop->next->v;
+ v2 = e->loop->v;
+ }
+ else{
+ v1 = e->v1;
+ v2 = e->v2;
+ }
+
+ if(v1->edge->tflag1 == 2) l = v1->edge;
+ else l = BME_disk_next_edgeflag(v1->edge, v1, 0, 2);
+ if(v2->edge->tflag1 == 2) r = v2->edge;
+ else r = BME_disk_next_edgeflag(v2->edge, v2, 0, 2);
+
+ lv = BME_edge_getothervert(l,v1);
+ rv = BME_edge_getothervert(r,v2);
+
+ ne = BME_ME(bm,lv,rv);
+ ne->tflag2 = 1; //mark for select
+ BLI_ghash_insert(ehash,e,ne);
+ BME_VISIT(e);
+
+ edar[0] = e;
+ edar[1] = l;
+ edar[2] = ne;
+ edar[3] = r;
+ BME_MF(bm,v1,v2,edar,4);
+ }
+ }
+}
+
+void BME_cap_skirt(BME_Mesh *bm, GHash *vhash, GHash *ehash){
+ BMVert *v, *nv, *v1, *v2;
+ BMEdge *e, **edar, *ne;
+ BME_Loop *l;
+ BMFace *f, *nf;
+ MemArena *edgearena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ float vec[3];
+ int i, j, del_old =0;
+
+
+ //loop through faces, then loop through their verts. If the verts havnt been visited yet, duplicate these.
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ l = f->loopbase;
+ do{
+ if(!(BME_ISVISITED(l->v))){ //interior vertex
+ //dupe vert
+ VECCOPY(vec,l->v->co);
+ nv = BME_MV(bm,vec);
+ BLI_ghash_insert(vhash,l->v,nv);
+ //mark for delete
+ l->v->tflag1 = 1;
+ BME_VISIT(l->v); //we dont want to dupe it again.
+ }
+ l=l->next;
+ }while(l!=f->loopbase);
+ }
+ }
+
+ //find out if we delete old faces or not. This needs to be improved a lot.....
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e) && e->loop){
+ i= BME_cycle_length(&(e->loop->radial));
+ if(i > 2){
+ del_old = 1;
+ break;
+ }
+ }
+ }
+
+
+ //build a new edge net, insert the new edges into the edge hash
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ l=f->loopbase;
+ do{
+ if(!(BME_ISVISITED(l->e))){ //interior edge
+ //dupe edge
+ ne = BME_ME(bm,BLI_ghash_lookup(vhash,l->e->v1),BLI_ghash_lookup(vhash,l->e->v2));
+ BLI_ghash_insert(ehash,l->e,ne);
+ //mark for delete
+ l->e->tflag1 = 1;
+ BME_VISIT(l->e); //we dont want to dupe it again.
+ }
+ l=l->next;
+ }while(l!=f->loopbase);
+ }
+ }
+
+ //build new faces. grab edges from edge hash.
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ edar = MEM_callocN(sizeof(BMEdge*)*f->len,"Extrude array");
+ v1 = BLI_ghash_lookup(vhash,f->loopbase->v);
+ v2 = BLI_ghash_lookup(vhash,f->loopbase->next->v);
+ for(i=0,l=f->loopbase; i < f->len; i++,l=l->next){
+ ne = BLI_ghash_lookup(ehash,l->e);
+ edar[i] = ne;
+ }
+ nf=BME_MF(bm,v1,v2,edar,f->len);
+ nf->tflag2 = 1; // mark for select
+ if(del_old) f->tflag1 = 1; //mark for delete
+ MEM_freeN(edar);
+ }
+ }
+ BLI_memarena_free(edgearena);
+}
+
+/*unified extrude code*/
+void BME_extrude_mesh(BME_Mesh *bm, int type){
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BME_Loop *l;
+
+ struct GHash *vhash, *ehash;
+ /*Build a hash table of old pointers and new pointers.*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ BME_selectmode_flush(bm); //ensure consistent selection. contains hack to make sure faces get consistent select.
+ if(type & BME_EXTRUDE_FACES){ //Find selected edges with more than one incident face that is also selected. deselect them.
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ int totsel=0;
+ if(e->loop){
+ l= e->loop;
+ do{
+ if(BME_SELECTED(l->f)) totsel++;
+ l=BME_radial_nextloop(l);
+ }while(l!=e->loop);
+ }
+ if(totsel > 1) BME_select_edge(bm,e,0);
+ }
+ }
+
+ /*another hack to ensure consistent selection.....*/
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e)) BME_select_edge(bm,e,1);
+ }
+
+ /*now we are ready to extrude*/
+ if(type & BME_EXTRUDE_VERTS) BME_extrude_verts(bm,vhash);
+ if(type & BME_EXTRUDE_EDGES) BME_extrude_skirt(bm,ehash);
+ if(type & BME_EXTRUDE_FACES) BME_cap_skirt(bm,vhash,ehash);
+
+ /*clear all selection flags*/
+ BME_clear_flag_all(bm, SELECT|BME_VISITED);
+ /*go through and fix up selection flags. Anything with BME_NEW should be selected*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(f->tflag2 == 1) BME_select_poly(bm,f,1);
+ if(f->tflag1 == 1) BME_VISIT(f); //mark for delete
+ }
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(e->tflag2 == 1) BME_select_edge(bm,e,1);
+ if(e->tflag1 == 1) BME_VISIT(e); // mark for delete
+ }
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(v->tflag2 == 1) BME_select_vert(bm,v,1);
+ if(v->tflag1 == 1) BME_VISIT(v); //mark for delete
+ }
+ /*go through and delete all of our old faces , edges and vertices.*/
+ remove_tagged_polys(bm);
+ remove_tagged_edges(bm);
+ remove_tagged_verts(bm);
+ /*free our hash tables*/
+ BLI_ghash_free(vhash,NULL, NULL); //check usage!
+ BLI_ghash_free(ehash,NULL, NULL); //check usage!
+ BME_selectmode_flush(bm);
+}
+
diff --git a/source/blender/bmesh/tools/BME_weld.c b/source/blender/bmesh/tools/BME_weld.c
new file mode 100644
index 00000000000..a17c07addbc
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_weld.c
@@ -0,0 +1,333 @@
+/*
+ * BME_WELD.C
+ *
+ * This file contains functions for welding
+ * elements in a mesh togather (remove doubles,
+ * collapse, ect).
+ *
+ * TODO:
+ * -Rewrite this to fit into the new API
+ * -Seperate out find doubles code and put it in
+ * BME_queries.c
+ *
+*/
+
+
+/********* qsort routines *********/
+
+
+typedef struct xvertsort {
+ float x;
+ BMVert *v1;
+} xvertsort;
+
+static int vergxco(const void *v1, const void *v2)
+{
+ const xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct facesort {
+ unsigned long x;
+ struct BMFace *f;
+};
+
+
+static int vergface(const void *v1, const void *v2)
+{
+ const struct facesort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+
+
+/*break this into two functions.... 'find doubles' and 'remove doubles'?*/
+
+static void BME_remove_doubles__splitface(BME_Mesh *bm,BMFace *f,GHash *vhash){
+ BMVert *doub=NULL, *target=NULL;
+ BME_Loop *l;
+ BMFace *f2=NULL;
+ int split=0;
+
+ l=f->loopbase;
+ do{
+ if(l->v->tflag1 == 2){
+ target = BLI_ghash_lookup(vhash,l->v);
+ if((BME_vert_in_face(target,f)) && (target != l->next->v) && (target != l->prev->v)){
+ doub = l->v;
+ split = 1;
+ break;
+ }
+ }
+
+ l= l->next;
+ }while(l!= f->loopbase);
+
+ if(split){
+ f2 = BME_SFME(bm,f,doub,target,NULL);
+ BME_remove_doubles__splitface(bm,f,vhash);
+ BME_remove_doubles__splitface(bm,f2,vhash);
+ }
+}
+
+int BME_remove_doubles(BME_Mesh *bm, float limit)
+{
+
+ /* all verts with (flag & 'flag') are being evaluated */
+ BMVert *v, *v2, *target;
+ BMEdge *e, **edar, *ne;
+ BME_Loop *l;
+ BMFace *f, *nf;
+ xvertsort *sortblock, *sb, *sb1;
+ struct GHash *vhash;
+ struct facesort *fsortblock, *vsb, *vsb1;
+ int a, b, test, amount=0, found;
+ float dist;
+
+ /*Build a hash table of doubles to thier target vert/edge.*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ /*count amount of selected vertices*/
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v))amount++;
+ }
+
+ /*qsort vertices based upon average of coordinate. We test this way first.*/
+ sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
+
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v)){
+ sb->x = v->co[0]+v->co[1]+v->co[2];
+ sb->v1 = v;
+ sb++;
+ }
+ }
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+ /* test for doubles */
+ sb= sortblock;
+ for(a=0; a<amount; a++) {
+ v= sb->v1;
+ if(!(v->tflag1)) { //have we tested yet?
+ sb1= sb+1;
+ for(b=a+1; b<amount; b++) {
+ /* first test: simple distance. Simple way to discard*/
+ dist= sb1->x - sb->x;
+ if(dist > limit) break;
+
+ /* second test: have we already done this vertex?
+ (eh this should be swapped, simple equality test should be cheaper than math above... small savings
+ though) */
+ v2= sb1->v1;
+ if(!(v2->tflag1)) {
+ dist= (float)fabs(v2->co[0]-v->co[0]);
+ if(dist<=limit) {
+ dist= (float)fabs(v2->co[1]-v->co[1]);
+ if(dist<=limit) {
+ dist= (float)fabs(v2->co[2]-v->co[2]);
+ if(dist<=limit) {
+ /*v2 is a double of v. We want to throw out v1 and relink everything to v*/
+ BLI_ghash_insert(vhash,v2, v);
+ v->tflag1 = 1; //mark this vertex as a target
+ v->tflag2++; //increase user count for this vert.
+ v2->tflag1 = 2; //mark this vertex as a double.
+ BME_VISIT(v2); //mark for delete
+ }
+ }
+ }
+ }
+ sb1++;
+ }
+ }
+ sb++;
+ }
+ MEM_freeN(sortblock);
+
+
+ /*todo... figure out what this is for...
+ for(eve = em->verts.first; eve; eve=eve->next)
+ if((eve->f & flag) && (eve->f & 128))
+ EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
+ */
+
+ /*We cannot collapse a vertex onto another vertex if they share a face and are not connected via a collapsable edge.
+ so to deal with this we simply find these offending vertices and split the faces. Note that this is not optimal, but works.
+ */
+
+
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(!(BME_NEWELEM(f))){
+ BME_remove_doubles__splitface(bm,f,vhash);
+ }
+ }
+
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ /*If either vertices of this edge are a double, we must mark it for removal and we create a new one.*/
+ if(e->v1->tflag1 == 2 || e->v2->tflag1 == 2){
+ v = v2 = NULL;
+ /*For each vertex in the edge, test to find out what it should equal now.*/
+ if(e->v1->tflag1 == 2) v= BLI_ghash_lookup(vhash,e->v1);
+ else v = e->v1;
+ if(e->v2->tflag1 == 2) v2 = BLI_ghash_lookup(vhash,e->v2);
+ else v2 = e->v2;
+
+ /*small optimization, test to see if the edge needs to be rebuilt at all*/
+ if((e->v1 != v) || (e->v2 != v2)){ /*will this always be true of collapsed edges?*/
+ if(v == v2) e->tflag1 = 2; /*mark as a collapsed edge*/
+ else if(!BME_disk_existedge(v,v2)) ne = BME_ME(bm,v,v2);
+ BME_VISIT(e); /*mark for delete*/
+ }
+ }
+ }
+
+
+ /*need to remove double edges as well. To do this we decide on one edge to keep, and if its inserted into hash then we need to remove all other
+ edges incident upon and relink.*/
+ /*
+ * REBUILD FACES
+ *
+ * Loop through double faces and if they have vertices that have been flagged, they need to be rebuilt.
+ * We do this by looking up the face
+ *rebuild faces. loop through original face, for each loop, if the edge it is attached to is marked for delete and has no
+ *other edge in the hash edge, then we know to skip that loop on face recreation. Simple.
+ */
+
+ /*1st loop through, just marking elements*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){ //insert bit here about double edges, mark with a flag (e->tflag2) so that we can nuke it later.
+ l = f->loopbase;
+ do{
+ if(l->v->tflag1 == 2) f->tflag1 = 1; //double, mark for rebuild
+ if(l->e->tflag1 != 2) f->tflag2++; //count number of edges in the new face.
+ l=l->next;
+ }while(l!=f->loopbase);
+ }
+
+ /*now go through and create new faces*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(f->tflag1 && f->tflag2 < 3) BME_VISIT(f); //mark for delete
+ else if (f->tflag1 == 1){ /*is the face marked for rebuild*/
+ edar = MEM_callocN(sizeof(BMEdge *)*f->tflag2,"Remove doubles face creation array.");
+ a=0;
+ l = f->loopbase;
+ do{
+ v = l->v;
+ v2 = l->next->v;
+ if(l->v->tflag1 == 2) v = BLI_ghash_lookup(vhash,l->v);
+ if(l->next->v->tflag1 == 2) v2 = BLI_ghash_lookup(vhash,l->next->v);
+ ne = BME_disk_existedge(v,v2); //use BME_disk_next_edgeflag here or something to find the edge that is marked as 'target'.
+ //add in call here to edge doubles hash array... then bobs your uncle.
+ if(ne){
+ edar[a] = ne;
+ a++;
+ }
+ l=l->next;
+ }while(l!=f->loopbase);
+
+ if(BME_vert_in_edge(edar[1],edar[0]->v2)){
+ v = edar[0]->v1;
+ v2 = edar[0]->v2;
+ }
+ else{
+ v = edar[0]->v2;
+ v2 = edar[0]->v1;
+ }
+
+ nf = BME_MF(bm,v,v2,edar,f->tflag2);
+
+ /*copy per loop data here*/
+ if(nf){
+ BME_VISIT(f); //mark for delete
+ }
+ MEM_freeN(edar);
+ }
+ }
+
+ /*count amount of removed vert doubles*/
+ a = 0;
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(v->tflag1 == 2) a++;
+ }
+
+ /*free memory and return amount removed*/
+ remove_tagged_polys(bm);
+ remove_tagged_edges(bm);
+ remove_tagged_verts(bm);
+ BLI_ghash_free(vhash,NULL, NULL);
+ BME_selectmode_flush(bm);
+ return a;
+}
+
+static void BME_MeshWalk__collapsefunc(void *userData, BMEdge *applyedge){
+ int index;
+ GHash *collected = userData;
+ index = BLI_ghash_size(collected);
+ if(!BLI_ghash_lookup(collected,applyedge->v1)){
+ BLI_ghash_insert(collected,index,applyedge->v1);
+ index++;
+ }
+ if(!BLI_ghash_lookup(collected,applyedge->v2)){
+ BLI_ghash_insert(collected,index,applyedge->v2);
+ }
+}
+
+void BME_collapse_edges(BME_Mesh *bm){
+
+ BMVert *v, *cvert;
+ GHash *collected;
+ float min[3], max[3], cent[3];
+ int size, i=0, j, num=0;
+
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(!(BME_ISVISITED(v)) && v->edge){
+ /*initiate hash table*/
+ collected = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ /*do the walking.*/
+ BME_MeshWalk(bm,v,BME_MeshWalk__collapsefunc,collected,BME_RESTRICTSELECT);
+ /*now loop through the hash table twice, once to calculate bounding box, second time to do the actual collapse*/
+ size = BLI_ghash_size(collected);
+ /*initial values*/
+ VECCOPY(min,v->co);
+ VECCOPY(max,v->co);
+ cent[0] = cent[1] = cent[2]=0;
+ for(i=0; i<size; i++){
+ cvert = BLI_ghash_lookup(collected,i);
+ cent[0] = cent[0] + cvert->co[0];
+ cent[1] = cent[1] + cvert->co[1];
+ cent[2] = cent[2] + cvert->co[2];
+ }
+
+ cent[0] = cent[0] / size;
+ cent[1] = cent[1] / size;
+ cent[2] = cent[2] / size;
+
+ for(i=0; i<size; i++){
+ cvert = BLI_ghash_lookup(collected,i);
+ VECCOPY(cvert->co,cent);
+ num++;
+ }
+ /*free the hash table*/
+ BLI_ghash_free(collected,NULL, NULL);
+ }
+ }
+ /*if any collapsed, call remove doubles*/
+ if(num){
+ //need to change selection mode here, OR do something else? Or does tool change selection mode?
+ //selectgrep
+ //first clear flags
+ BMEdge *e;
+ BMFace *f;
+ BME_clear_flag_all(bm,BME_VISITED);
+ for(v=BME_first(bm,BME_VERT); v; v=BME_next(bm,BME_VERT,v)) v->tflag1 = v->tflag2 = 0;
+ for(e=BME_first(bm,BME_EDGE); e; e=BME_next(bm,BME_EDGE,e)) e->tflag1 = e->tflag2 = 0;
+ for(f=BME_first(bm,BME_POLY); f; f=BME_next(bm,BME_POLY,f)) f->tflag1 = f->tflag2 = 0;
+ /*now call remove doubles*/
+ BME_remove_doubles(bm,0.0000001);
+ }
+ BME_selectmode_flush(bm);
+} \ No newline at end of file
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
deleted file mode 100644
index 7a618f4d222..00000000000
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/**
- * $Id:
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation, Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/* User-Interface Stuff for F-Modifiers:
- * This file defines the (C-Coded) templates + editing callbacks needed
- * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
- * and NLA-Strips in the NLA Editor.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <float.h>
-
-#include "DNA_anim_types.h"
-#include "DNA_action_types.h"
-#include "DNA_object_types.h"
-#include "DNA_space_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_userdef_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_arithb.h"
-#include "BLI_blenlib.h"
-#include "BLI_editVert.h"
-#include "BLI_rand.h"
-
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_context.h"
-#include "BKE_curve.h"
-#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
-#include "BKE_object.h"
-#include "BKE_global.h"
-#include "BKE_nla.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_utildefines.h"
-
-#include "BIF_gl.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "ED_anim_api.h"
-#include "ED_keyframing.h"
-#include "ED_screen.h"
-#include "ED_types.h"
-#include "ED_util.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-// XXX! --------------------------------
-/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
-#define UI_FLT_MAX 10000.0f
-
-/* ********************************************** */
-
-#define B_REDR 1
-#define B_FMODIFIER_REDRAW 20
-
-/* macro for use here to draw background box and set height */
-// XXX for now, roundbox has it's callback func set to NULL to not intercept events
-#define DRAW_BACKDROP(height) \
- { \
- uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
- }
-
-/* callback to verify modifier data */
-static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy)
-{
- FModifier *fcm= (FModifier *)fcm_v;
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* call the verify callback on the modifier if applicable */
- if (fmi && fmi->verify_data)
- fmi->verify_data(fcm);
-}
-
-/* callback to set the active modifier */
-static void activate_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
-{
- ListBase *modifiers = (ListBase *)fmods_v;
- FModifier *fcm= (FModifier *)fcm_v;
-
- /* call API function to set the active modifier for active modifier-stack */
- set_active_fmodifier(modifiers, fcm);
-}
-
-/* callback to remove the given modifier */
-static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
-{
- ListBase *modifiers = (ListBase *)fmods_v;
- FModifier *fcm= (FModifier *)fcm_v;
-
- /* remove the given F-Modifier from the active modifier-stack */
- remove_fmodifier(modifiers, fcm);
-}
-
-/* --------------- */
-
-/* draw settings for generator modifier */
-static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
- uiLayout *col, *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
- /* basic settings (backdrop + mode selector + some padding) */
- col= uiLayoutColumn(layout, 1);
- block= uiLayoutGetBlock(layout);
- uiBlockBeginAlign(block);
- but= uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
-
- uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "additive", -1, 0, 0, -1, -1, NULL);
- uiBlockEndAlign(block);
-
- /* now add settings for individual modes */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
- {
- float *cp = NULL;
- char xval[32];
- unsigned int i;
-
- /* draw polynomial order selector */
- row= uiLayoutRow(layout, 0);
- block= uiLayoutGetBlock(row);
- but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
-
-
- /* draw controls for each coefficient and a + sign at end of row */
- row= uiLayoutRow(layout, 1);
- block= uiLayoutGetBlock(row);
- uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- cp= data->coefficients;
- for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
- /* coefficient */
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
-
- /* 'x' param (and '+' if necessary) */
- if (i) {
- if (i == 1)
- strcpy(xval, "x");
- else
- sprintf(xval, "x^%d", i);
- uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
- }
-
- if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) {
- uiDefBut(block, LABEL, 1, "+", 0,0 , 30, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- /* next coefficient on a new row */
- row= uiLayoutRow(layout, 1);
- block= uiLayoutGetBlock(row);
- }
- }
- }
- break;
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
- {
- float *cp = NULL;
- unsigned int i;
-
- /* draw polynomial order selector */
- row= uiLayoutRow(layout, 0);
- block= uiLayoutGetBlock(row);
- but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 0,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
-
-
- /* draw controls for each pair of coefficients */
- row= uiLayoutRow(layout, 1);
- block= uiLayoutGetBlock(row);
- uiDefBut(block, LABEL, 1, "y=", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- cp= data->coefficients;
- for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
- /* opening bracket */
- uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- /* coefficients */
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
-
- uiDefBut(block, LABEL, 1, "x+", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
-
- /* closing bracket and '+' sign */
- if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) {
- uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- /* set up new row for the next pair of coefficients*/
- row= uiLayoutRow(layout, 1);
- block= uiLayoutGetBlock(row);
- }
- else
- uiDefBut(block, LABEL, 1, ")", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
- }
- }
- break;
- }
-}
-
-/* --------------- */
-
-/* draw settings for noise modifier */
-static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- uiLayout *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
-
- /* add the settings */
- col= uiLayoutColumn(layout, 1);
- uiItemR(col, "", 0, &ptr, "type", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "additive", 0, 0, 1);
-
- col= uiLayoutColumn(layout, 0); // no grouping for now
- uiItemR(col, NULL, 0, &ptr, "amplitude", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "phase_multiplier", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "phase_offset", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "value_offset", 0, 0, 0);
-}
-
-/* --------------- */
-
-/* draw settings for cycles modifier */
-static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- uiLayout *split, *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
-
- /* split into 2 columns
- * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
- */
- split= uiLayoutSplit(layout, 0.5f);
-
- /* before range */
- col= uiLayoutColumn(split, 1);
- uiItemL(col, "Before:", 0);
- uiItemR(col, "", 0, &ptr, "before_mode", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "before_cycles", 0, 0, 0);
-
- /* after range */
- col= uiLayoutColumn(split, 1);
- uiItemL(col, "After:", 0);
- uiItemR(col, "", 0, &ptr, "after_mode", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "after_cycles", 0, 0, 0);
-}
-
-/* --------------- */
-
-/* draw settings for noise modifier */
-static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- uiLayout *split, *col;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
-
- /* blending mode */
- uiItemR(layout, NULL, 0, &ptr, "modification", 0, 0, 0);
-
- /* split into 2 columns */
- split= uiLayoutSplit(layout, 0.5f);
-
- /* col 1 */
- col= uiLayoutColumn(split, 0);
- uiItemR(col, NULL, 0, &ptr, "size", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "strength", 0, 0, 0);
-
- /* col 2 */
- col= uiLayoutColumn(split, 0);
- uiItemR(col, NULL, 0, &ptr, "phase", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "depth", 0, 0, 0);
-}
-
-/* --------------- */
-
-#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
-
-/* Binary search algorithm for finding where to insert Envelope Data Point.
- * Returns the index to insert at (data already at that index will be offset if replace is 0)
- */
-static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
-{
- int start=0, end=arraylen;
- int loopbreaker= 0, maxloop= arraylen * 2;
-
- /* initialise exists-flag first */
- *exists= 0;
-
- /* sneaky optimisations (don't go through searching process if...):
- * - keyframe to be added is to be added out of current bounds
- * - keyframe to be added would replace one of the existing ones on bounds
- */
- if ((arraylen <= 0) || (array == NULL)) {
- printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
- return 0;
- }
- else {
- /* check whether to add before/after/on */
- float framenum;
-
- /* 'First' Point (when only one point, this case is used) */
- framenum= array[0].time;
- if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists = 1;
- return 0;
- }
- else if (frame < framenum)
- return 0;
-
- /* 'Last' Point */
- framenum= array[(arraylen-1)].time;
- if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists= 1;
- return (arraylen - 1);
- }
- else if (frame > framenum)
- return arraylen;
- }
-
-
- /* most of the time, this loop is just to find where to put it
- * - 'loopbreaker' is just here to prevent infinite loops
- */
- for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
- /* compute and get midpoint */
- int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
- float midfra= array[mid].time;
-
- /* check if exactly equal to midpoint */
- if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists = 1;
- return mid;
- }
-
- /* repeat in upper/lower half */
- if (frame > midfra)
- start= mid + 1;
- else if (frame < midfra)
- end= mid - 1;
- }
-
- /* print error if loop-limit exceeded */
- if (loopbreaker == (maxloop-1)) {
- printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
-
- // include debug info
- printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
- }
-
- /* not found, so return where to place it */
- return start;
-}
-
-/* callback to add new envelope data point */
-// TODO: should we have a separate file for things like this?
-static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
-{
- Scene *scene= CTX_data_scene(C);
- FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
- FCM_EnvelopeData *fedn;
- FCM_EnvelopeData fed;
-
- /* init template data */
- fed.min= -1.0f;
- fed.max= 1.0f;
- fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
- fed.f1= fed.f2= 0;
-
- /* check that no data exists for the current frame... */
- if (env->data) {
- short exists = -1;
- int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
-
- /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
- if (exists)
- return;
-
- /* add new */
- fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
-
- /* add the points that should occur before the point to be pasted */
- if (i > 0)
- memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
-
- /* add point to paste at index i */
- *(fedn + i)= fed;
-
- /* add the points that occur after the point to be pasted */
- if (i < env->totvert)
- memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
-
- /* replace (+ free) old with new */
- MEM_freeN(env->data);
- env->data= fedn;
-
- env->totvert++;
- }
- else {
- env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
- *(env->data)= fed;
-
- env->totvert= 1;
- }
-}
-
-/* callback to remove envelope data point */
-// TODO: should we have a separate file for things like this?
-static void fmod_envelope_deletepoint_cb (bContext *C, void *fcm_dv, void *ind_v)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
- FCM_EnvelopeData *fedn;
- int index= GET_INT_FROM_POINTER(ind_v);
-
- /* check that no data exists for the current frame... */
- if (env->totvert > 1) {
- /* allocate a new smaller array */
- fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
-
- memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
- memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
-
- /* free old array, and set the new */
- MEM_freeN(env->data);
- env->data= fedn;
- env->totvert--;
- }
- else {
- /* just free array, since the only vert was deleted */
- if (env->data)
- MEM_freeN(env->data);
- env->totvert= 0;
- }
-}
-
-/* draw settings for envelope modifier */
-static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed;
- uiLayout *col, *row;
- uiBlock *block;
- uiBut *but;
- PointerRNA ptr;
- int i;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
-
- /* general settings */
- col= uiLayoutColumn(layout, 1);
- uiItemL(col, "Envelope:", 0);
- uiItemR(col, NULL, 0, &ptr, "reference_value", 0, 0, 0);
-
- row= uiLayoutRow(col, 1);
- uiItemR(row, "Min", 0, &ptr, "default_minimum", 0, 0, 0);
- uiItemR(row, "Max", 0, &ptr, "default_maximum", 0, 0, 0);
-
- /* control points header */
- // TODO: move this control-point control stuff to using the new special widgets for lists
- // the current way is far too cramped
- row= uiLayoutRow(layout, 0);
- block= uiLayoutGetBlock(row);
-
- uiDefBut(block, LABEL, 1, "Control Points:", 0, 0, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
-
- but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 0,0,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
- uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
-
- /* control points list */
- for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
- /* get a new row to operate on */
- row= uiLayoutRow(layout, 1);
- block= uiLayoutGetBlock(row);
-
- uiBlockBeginAlign(block);
- but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 0, 0, 90, 20, &fed->time, -UI_FLT_MAX, UI_FLT_MAX, 10, 1, "Frame that envelope point occurs");
- uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
-
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 0, 0, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
- uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 0, 0, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
-
- but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
- uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
- uiBlockBeginAlign(block);
- }
-}
-
-/* --------------- */
-
-/* draw settings for limits modifier */
-static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short width)
-{
- uiLayout *split, *col, *row;
- PointerRNA ptr;
-
- /* init the RNA-pointer */
- RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr);
-
- /* row 1: minimum */
- {
- row= uiLayoutRow(layout, 0);
-
- /* split into 2 columns */
- split= uiLayoutSplit(layout, 0.5f);
-
- /* x-minimum */
- col= uiLayoutColumn(split, 1);
- uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "minimum_x", 0, 0, 0);
-
- /* y-minimum*/
- col= uiLayoutColumn(split, 1);
- uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "minimum_y", 0, 0, 0);
- }
-
- /* row 2: minimum */
- {
- row= uiLayoutRow(layout, 0);
-
- /* split into 2 columns */
- split= uiLayoutSplit(layout, 0.5f);
-
- /* x-minimum */
- col= uiLayoutColumn(split, 1);
- uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "maximum_x", 0, 0, 0);
-
- /* y-minimum*/
- col= uiLayoutColumn(split, 1);
- uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0, 0, 0);
- uiItemR(col, NULL, 0, &ptr, "maximum_y", 0, 0, 0);
- }
-}
-
-/* --------------- */
-
-
-void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
-{
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- uiLayout *box, *row, *subrow;
- uiBlock *block;
- uiBut *but;
- short width= 314;
-
- /* draw header */
- {
- /* get layout-row + UI-block for this */
- box= uiLayoutBox(layout);
-
- row= uiLayoutRow(box, 0);
- block= uiLayoutGetBlock(row); // err...
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
-
- /* left-align -------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
- uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
-
- /* expand */
- uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded.");
-
- /* checkbox for 'active' status (for now) */
- but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 0, -1, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one.");
- uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm);
-
- /* name */
- if (fmi)
- uiDefBut(block, LABEL, 1, fmi->name, 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
- else
- uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 0, 0, 150, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type. Click to make modifier active one.");
-
- /* right-align ------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
- uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
-
- /* 'mute' button */
- uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_MUTED, B_REDR, ICON_MUTE_IPO_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is temporarily muted (not evaluated).");
-
- /* delete button */
- but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier.");
- uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
-
- /* when modifier is expanded, draw settings */
- if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
- /* set up the flexible-box layout which acts as the backdrop for the modifier settings */
- box= uiLayoutBox(layout);
-
- /* draw settings for individual modifiers */
- switch (fcm->type) {
- case FMODIFIER_TYPE_GENERATOR: /* Generator */
- draw_modifier__generator(box, id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
- draw_modifier__fn_generator(box, id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_CYCLES: /* Cycles */
- draw_modifier__cycles(box, id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
- draw_modifier__envelope(box, id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_LIMITS: /* Limits */
- draw_modifier__limits(box, id, fcm, width);
- break;
-
- case FMODIFIER_TYPE_NOISE: /* Noise */
- draw_modifier__noise(box, id, fcm, width);
- break;
-
- default: /* unknown type */
- break;
- }
- }
-}
-
-/* ********************************************** */
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 8807b21e653..83179dd3843 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -1151,8 +1151,8 @@ static void meshdeform_ray_tree_create(MeshDeformBind *mdb)
MESHDEFORM_BIND= mdb;
- mface= mdb->cagedm->getFaceArray(mdb->cagedm);
- totface= mdb->cagedm->getNumFaces(mdb->cagedm);
+ mface= mdb->cagedm->getTessFaceArray(mdb->cagedm);
+ totface= mdb->cagedm->getNumTessFaces(mdb->cagedm);
mdb->raytree= RE_ray_tree_create(64, totface, min, max,
meshdeform_ray_coords_func, meshdeform_ray_check_func);
@@ -1178,8 +1178,8 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec)
isec->labda= 1e10;
- mface= mdb->cagedm->getFaceArray(mdb->cagedm);
- totface= mdb->cagedm->getNumFaces(mdb->cagedm);
+ mface= mdb->cagedm->getTessFaceArray(mdb->cagedm);
+ totface= mdb->cagedm->getNumTessFaces(mdb->cagedm);
for(f=0; f<totface; f++, mface++) {
VECCOPY(face[0], mdb->cagecos[mface->v1]);
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 132d9edf8d0..2a012437b42 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -64,6 +64,7 @@
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_customdata.h"
+#include "BKE_mesh.h"
//#include "blendef.h"
@@ -3387,7 +3388,7 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
- EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
+ EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data));
EdgeIndex indexed_edges;
VertexData *data;
ReebGraph *rg = NULL;
@@ -3483,6 +3484,12 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
MEM_freeN(data);
+ /*no need to load the editmesh back into the object, just
+ free it (avoids ngon conversion issues too going back the
+ other way)*/
+ free_editMesh(em);
+ MEM_freeN(em);
+
return rg;
}
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 0face00f82b..dd29f270680 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -36,7 +36,6 @@ struct EditVert;
struct EditEdge;
struct EditFace;
struct bContext;
-struct wmOperator;
struct wmWindowManager;
struct EditSelection;
struct ViewContext;
@@ -49,35 +48,68 @@ struct MCol;
struct UvVertMap;
struct UvMapVert;
struct CustomData;
+struct BMEditSelection;
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
-#define EM_FGON_DRAW 1 // face flag
-#define EM_FGON 2 // edge and face flag both
+// edge and face flag both
+#define EM_FGON 2
+// face flag
+#define EM_FGON_DRAW 1
/* editbutflag */
-#define B_CLOCKWISE 1
-#define B_KEEPORIG 2
-#define B_BEAUTY 4
-#define B_SMOOTH 8
-#define B_BEAUTY_SHORT 0x10
-#define B_AUTOFGON 0x20
-#define B_KNIFE 0x80
+#define B_CLOCKWISE 1
+#define B_KEEPORIG 2
+#define B_BEAUTY 4
+#define B_SMOOTH 8
+#define B_BEAUTY_SHORT 16
+#define B_AUTOFGON 32
+#define B_KNIFE 0x80
#define B_PERCENTSUBD 0x40
#define B_MESH_X_MIRROR 0x100
#define B_JOINTRIA_UV 0x200
#define B_JOINTRIA_VCOL 0X400
#define B_JOINTRIA_SHARP 0X800
#define B_JOINTRIA_MAT 0X1000
-#define B_FRACTAL 0x2000
-#define B_SPHERE 0x4000
+#define B_FRACTAL 0x2000
+#define B_SPHERE 0x4000
+
+/* bmeshutils.c */
+
+/*this function is currently defunct, dead*/
+void EDBM_Tesselate(struct EditMesh *em);
+void EDBM_RecalcNormals(struct BMEditMesh *em);
+void EDBM_MakeEditBMesh(struct Scene *scene, struct Object *ob);
+void EDBM_FreeEditBMesh(struct BMEditMesh *tm);
+void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob);
+void EDBM_init_index_arrays(struct BMEditMesh *tm, int forvert, int foredge, int forface);
+void EDBM_free_index_arrays(struct BMEditMesh *tm);
+struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *tm, int index);
+struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *tm, int index);
+struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *tm, int index);
+struct BMFace *EDBM_get_actFace(struct BMEditMesh *em, int sloppy);
+void EDBM_selectmode_flush(struct BMEditMesh *em);
+int EDBM_get_actSelection(struct BMEditMesh *em, struct BMEditSelection *ese);
+void EDBM_editselection_center(struct BMEditMesh *em, float *center, struct BMEditSelection *ese);
+void EDBM_editselection_plane(struct BMEditMesh *em, float *plane, struct BMEditSelection *ese);
+void EDBM_editselection_normal(float *normal, struct BMEditSelection *ese);
+void EDBM_selectmode_set(struct BMEditMesh *em);
+void EDBM_convertsel(struct BMEditMesh *em, short oldmode, short selectmode);
+
+int EDBM_check_backbuf(unsigned int index);
+int EDBM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
+void EDBM_free_backbuf(void);
+int EDBM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+int EDBM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
/* meshtools.c */
-intptr_t mesh_octree_table(struct Object *ob, struct EditMesh *em, float *co, char mode);
-struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditMesh *em, float *co);
+intptr_t mesh_octree_table(struct Object *ob, struct BMEditMesh *em, float *co, char mode);
+struct BMVert *editmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, float *co);
int mesh_get_x_mirror_vert(struct Object *ob, int index);
-int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em);
-
-int join_mesh_exec(struct bContext *C, struct wmOperator *op);
+int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
/* mesh_ops.c */
void ED_operatortypes_mesh(void);
@@ -89,8 +121,8 @@ void ED_keymap_mesh(struct wmWindowManager *wm);
void ED_spacetypes_init(void);
void ED_keymap_mesh(struct wmWindowManager *wm);
-void make_editMesh(struct Scene *scene, Object *ob);
-void load_editMesh(struct Scene *scene, Object *ob);
+struct EditMesh *make_editMesh(struct Scene *scene, Object *ob);
+void load_editMesh(struct Scene *scene, Object *ob, struct EditMesh *em);
void remake_editMesh(struct Scene *scene, Object *ob);
void free_editMesh(struct EditMesh *em);
@@ -112,6 +144,7 @@ void undo_push_mesh(struct bContext *C, char *name);
struct EditFace *EM_get_actFace(struct EditMesh *em, int sloppy);
void EM_set_actFace(struct EditMesh *em, struct EditFace *efa);
float EM_face_area(struct EditFace *efa);
+void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type);
void EM_select_edge(struct EditEdge *eed, int sel);
void EM_select_face(struct EditFace *efa, int sel);
@@ -135,11 +168,8 @@ struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_
struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
void EM_free_uv_vert_map(struct UvVertMap *vmap);
-void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type);
-void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type);
-
/* editmesh_mods.c */
-extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;
+extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
void mouse_mesh(struct bContext *C, short mval[2], short extend);
int EM_check_backbuf(unsigned int index);
@@ -151,9 +181,6 @@ int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short r
void EM_hide_mesh(struct EditMesh *em, int swap);
void EM_reveal_mesh(struct EditMesh *em);
-void EM_select_by_material(struct EditMesh *em, int index);
-void EM_deselect_by_material(struct EditMesh *em, int index);
-
/* editface.c */
struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b576299c1d0..6360bf49f1a 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -37,9 +37,9 @@ struct bglMats;
struct BPoint;
struct Nurb;
struct BezTriple;
-struct EditVert;
-struct EditEdge;
-struct EditFace;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
struct ImBuf;
struct Scene;
struct bContext;
@@ -52,7 +52,7 @@ typedef struct ViewContext {
struct ARegion *ar;
struct View3D *v3d;
struct RegionView3D *rv3d;
- struct EditMesh *em;
+ struct BMEditMesh *em;
short mval[2];
} ViewContext;
@@ -96,9 +96,9 @@ void view3d_get_object_project_mat(struct RegionView3D *v3d, struct Object *ob,
void view3d_project_float(struct ARegion *a, float *vec, float *adr, float mat[4][4]);
/* drawobject.c itterators */
-void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts);
-void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
-void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData);
+void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BMVert *eve, int x, int y, int index), void *userData, int clipVerts);
+void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
+void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct BMFace *efa, int x, int y, int index), void *userData);
void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData);
void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData);
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
index df1f297698d..80536b5e431 100644
--- a/source/blender/editors/mesh/SConscript
+++ b/source/blender/editors/mesh/SConscript
@@ -7,5 +7,6 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' #/intern/guardedalloc ../../gpu'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+incs += ' ../../bmesh '
env.BlenderLib ( 'bf_editors_mesh', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c
new file mode 100644
index 00000000000..c4f2a294d0b
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_select.c
@@ -0,0 +1,1424 @@
+/**
+ * $Id:
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+BMEditMesh_mods.c, UI level access, no geometry changes
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_render_ext.h" /* externtex */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "bmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "mesh_intern.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* XXX */
+static void waitcursor() {}
+static int pupmenu() {return 0;}
+
+/* ****************************** MIRROR **************** */
+
+void EDBM_select_mirrored(Object *obedit, BMEditMesh *em)
+{
+#if 0 //BMESH_TODO
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve, *v1;
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f & SELECT) {
+ v1= BMEditMesh_get_x_mirror_vert(obedit, em, eve->co);
+ if(v1) {
+ eve->f &= ~SELECT;
+ v1->f |= SELECT;
+ }
+ }
+ }
+ }
+#endif
+}
+
+void EDBM_automerge(int update)
+{
+// XXX int len;
+
+// if ((scene->automerge) &&
+// (obedit && obedit->type==OB_MESH) &&
+// (((Mesh*)obedit->data)->mr==NULL)
+// ) {
+// len = removedoublesflag(1, 1, scene->toolsettings->doublimit);
+// if (len) {
+// em->totvert -= len; /* saves doing a countall */
+// if (update) {
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+// }
+// }
+// }
+}
+
+/* ****************************** SELECTION ROUTINES **************** */
+
+unsigned int bm_solidoffs=0, bm_wireoffs=0, bm_vertoffs=0; /* set in drawobject.c ... for colorindices */
+
+/* facilities for border select and circle select */
+static char *selbuf= NULL;
+
+/* opengl doesn't support concave... */
+static void draw_triangulated(short mcords[][2], short tot)
+{
+ ListBase lb={NULL, NULL};
+ DispList *dl;
+ float *fp;
+ int a;
+
+ /* make displist */
+ dl= MEM_callocN(sizeof(DispList), "poly disp");
+ dl->type= DL_POLY;
+ dl->parts= 1;
+ dl->nr= tot;
+ dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
+ BLI_addtail(&lb, dl);
+
+ for(a=0; a<tot; a++, fp+=3) {
+ fp[0]= (float)mcords[a][0];
+ fp[1]= (float)mcords[a][1];
+ }
+
+ /* do the fill */
+ filldisplist(&lb, &lb);
+
+ /* do the draw */
+ dl= lb.first; /* filldisplist adds in head of list */
+ if(dl->type==DL_INDEX3) {
+ int *index;
+
+ a= dl->parts;
+ fp= dl->verts;
+ index= dl->index;
+ glBegin(GL_TRIANGLES);
+ while(a--) {
+ glVertex3fv(fp+3*index[0]);
+ glVertex3fv(fp+3*index[1]);
+ glVertex3fv(fp+3*index[2]);
+ index+= 3;
+ }
+ glEnd();
+ }
+
+ freedisplist(&lb);
+}
+
+
+/* reads rect, and builds selection array for quick lookup */
+/* returns if all is OK */
+int EDBM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ int a;
+
+ if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(bm_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=bm_vertoffs)
+ selbuf[*dr]= 1;
+ dr++;
+ }
+ IMB_freeImBuf(buf);
+ return 1;
+}
+
+int EDBM_check_backbuf(unsigned int index)
+{
+ if(selbuf==NULL) return 1;
+ if(index>0 && index<=bm_vertoffs)
+ return selbuf[index];
+ return 0;
+}
+
+void EDBM_free_backbuf(void)
+{
+ if(selbuf) MEM_freeN(selbuf);
+ selbuf= NULL;
+}
+
+/* mcords is a polygon mask
+ - grab backbuffer,
+ - draw with black in backbuffer,
+ - grab again and compare
+ returns 'OK'
+*/
+int EDBM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+{
+ unsigned int *dr, *drm;
+ struct ImBuf *buf, *bufmask;
+ int a;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(FACESEL_PAINT_TEST);
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(bm_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* draw the mask */
+ glDisable(GL_DEPTH_TEST);
+
+ glColor3ub(0, 0, 0);
+
+ /* yah, opengl doesn't do concave... tsk! */
+ ED_region_pixelspace(vc->ar);
+ draw_triangulated(mcords, tot);
+
+ glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
+ for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
+ glEnd();
+
+ glFinish(); /* to be sure readpixels sees mask */
+
+ /* grab mask */
+ bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ drm = bufmask->rect;
+ if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=bm_vertoffs && *drm==0) selbuf[*dr]= 1;
+ dr++; drm++;
+ }
+ IMB_freeImBuf(buf);
+ IMB_freeImBuf(bufmask);
+ return 1;
+
+}
+
+/* circle shaped sample area */
+int EDBM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ short xmin, ymin, xmax, ymax, xc, yc;
+ int radsq;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(FACESEL_PAINT_TEST);
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ xmin= xs-rads; xmax= xs+rads;
+ ymin= ys-rads; ymax= ys+rads;
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(bm_vertoffs==0) return 0;
+ if(buf==NULL) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+ radsq= rads*rads;
+ for(yc= -rads; yc<=rads; yc++) {
+ for(xc= -rads; xc<=rads; xc++, dr++) {
+ if(xc*xc + yc*yc < radsq) {
+ if(*dr>0 && *dr<=bm_vertoffs) selbuf[*dr]= 1;
+ }
+ }
+ }
+
+ IMB_freeImBuf(buf);
+ return 1;
+
+}
+
+static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index)
+{
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
+ if (BM_TestHFlag(eve, BM_SELECT) == data->select) {
+ if (data->strict == 1)
+ return;
+ else
+ temp += 5;
+ }
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = eve;
+ data->closestIndex = index;
+ }
+ }
+}
+
+
+
+
+static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
+{
+ BMEditMesh *em= (BMEditMesh *)handle;
+ BMIter iter;
+ BMVert *eve = BMIter_AtIndex(em->bm, BM_VERTS_OF_MESH, NULL, index-1);
+
+ if(eve && BM_TestHFlag(eve, BM_SELECT)) return 0;
+ return 1;
+}
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ * if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ */
+BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
+{
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
+ int distance;
+ unsigned int index;
+ BMVert *eve;
+
+ if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest);
+ else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL);
+
+ eve = BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, index-1);
+
+ if(eve && distance < *dist) {
+ *dist = distance;
+ return eve;
+ } else {
+ return NULL;
+ }
+
+ }
+ else {
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data;
+ static int lastSelectedIndex=0;
+ static BMVert *lastSelected=NULL;
+
+ if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.select = sel;
+ data.dist = *dist;
+ data.strict = strict;
+ data.closest = NULL;
+ data.closestIndex = 0;
+
+ data.pass = 0;
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* returns labda for closest distance v1 to line-piece v2-v3 */
+static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
+{
+ float rc[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0f)
+ return 0.0f;
+
+ return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
+}
+
+/* note; uses v3d, so needs active 3d window */
+static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
+{
+ struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData;
+ float v1[2], v2[2];
+ int distance;
+
+ v1[0] = x0;
+ v1[1] = y0;
+ v2[0] = x1;
+ v2[1] = y1;
+
+ distance= PdistVL2Dfl(data->mval, v1, v2);
+
+ if(BM_TestHFlag(eed, BM_SELECT)) distance+=5;
+ if(distance < data->dist) {
+ if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
+ float vec[3];
+
+ vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
+ vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
+ vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
+ Mat4MulVecfl(data->vc.obedit->obmat, vec);
+
+ if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+ else {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+}
+BMEdge *EDBM_findnearestedge(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ int distance;
+ unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance,0, NULL, NULL);
+ BMEdge *eed = BMIter_AtIndex(vc->em->bm, BM_EDGES_OF_MESH, NULL, index-1);
+
+ if (eed && distance<*dist) {
+ *dist = distance;
+ return eed;
+ } else {
+ return NULL;
+ }
+ }
+ else {
+ struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data;
+
+ data.vc= *vc;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+
+ mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
+
+ *dist = data.dist;
+ return data.closest;
+ }
+}
+
+static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int index)
+{
+ struct { short mval[2]; int dist; BMFace *toFace; } *data = userData;
+
+ if (efa==data->toFace) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist)
+ data->dist = temp;
+ }
+}
+static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index)
+{
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = efa;
+ data->closestIndex = index;
+ }
+ }
+}
+static BMFace *EDBM_findnearestface(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
+ BMFace *efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
+
+ if (efa) {
+ struct { short mval[2]; int dist; BMFace *toFace; } data;
+
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = 0x7FFF; /* largest short */
+ data.toFace = efa;
+
+ mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
+
+ if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
+ *dist= data.dist;
+ return efa;
+ }
+ }
+
+ return NULL;
+ }
+ else {
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data;
+ static int lastSelectedIndex=0;
+ static BMFace *lastSelected=NULL;
+
+ if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+ data.closestIndex = 0;
+
+ data.pass = 0;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* best distance based on screen coords.
+ use em->selectmode to define how to use
+ selected vertices and edges get disadvantage
+ return 1 if found one
+*/
+static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFace **efa)
+{
+ BMEditMesh *em= vc->em;
+ int dist= 75;
+
+ *eve= NULL;
+ *eed= NULL;
+ *efa= NULL;
+
+ /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+ view3d_validate_backbuf(vc);
+
+ if(em->selectmode & SCE_SELECT_VERTEX)
+ *eve= EDBM_findnearestvert(vc, &dist, BM_SELECT, 0);
+ if(em->selectmode & SCE_SELECT_FACE)
+ *efa= EDBM_findnearestface(vc, &dist);
+
+ dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
+ if(em->selectmode & SCE_SELECT_EDGE)
+ *eed= EDBM_findnearestedge(vc, &dist);
+
+ /* return only one of 3 pointers, for frontbuffer redraws */
+ if(*eed) {
+ *efa= NULL; *eve= NULL;
+ }
+ else if(*efa) {
+ *eve= NULL;
+ }
+
+ return (*eve || *eed || *efa);
+}
+
+
+/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
+
+/* selects new faces/edges/verts based on the
+ existing selection
+
+FACES GROUP
+ mode 1: same material
+ mode 2: same image
+ mode 3: same area
+ mode 4: same perimeter
+ mode 5: same normal
+ mode 6: same co-planer
+*/
+
+static EnumPropertyItem prop_simface_types[] = {
+ {1, "MATERIAL", 0, "Material", ""},
+ {2, "IMAGE", 0, "Image", ""},
+ {3, "AREA", 0, "Area", ""},
+ {4, "PERIMETER", 0, "Perimeter", ""},
+ {5, "NORMAL", 0, "Normal", ""},
+ {6, "COPLANAR", 0, "Co-planar", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
+/* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes
+*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
+#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
+
+static int similar_face_select__internal(Scene *scene, BMEditMesh *em, int mode)
+{
+#if 0 //BMESH_TODO
+ BMFace *efa, *base_efa=NULL;
+ unsigned int selcount=0; /*count how many new faces we select*/
+
+ /*deselcount, count how many deselected faces are left, so we can bail out early
+ also means that if there are no deselected faces, we can avoid a lot of looping */
+ unsigned int deselcount=0;
+ float thresh= scene->toolsettings->select_thresh;
+ short ok=0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!efa->h) {
+ if (efa->f & SELECT) {
+ efa->f1=1;
+ ok=1;
+ } else {
+ efa->f1=0;
+ deselcount++; /* a deselected face we may select later */
+ }
+ }
+ }
+
+ if (!ok || !deselcount) /* no data selected OR no more data to select */
+ return 0;
+
+ /*if mode is 3 then record face areas, 4 record perimeter */
+ if (mode==3) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->tmp.fp= EM_face_area(efa);
+ }
+ } else if (mode==4) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->tmp.fp= EM_face_perimeter(efa);
+ }
+ }
+
+ for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
+ if (base_efa->f1) { /* This was one of the faces originaly selected */
+ if (mode==1) { /* same material */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (
+ !(efa->f & SELECT) &&
+ !efa->h &&
+ base_efa->mat_nr == efa->mat_nr
+ ) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==2) { /* same image */
+ MTFace *tf, *base_tf;
+
+ base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
+ CD_MTFACE);
+
+ if(!base_tf)
+ return selcount;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
+ CD_MTFACE);
+
+ if(base_tf->tpage == tf->tpage) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (
+ (!(efa->f & SELECT) && !efa->h) &&
+ SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
+ ) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ } else if (mode==5) { /* same normal */
+ float angle;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ angle= VecAngle2(base_efa->n, efa->n);
+ if (angle/180.0<=thresh) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ } else if (mode==6) { /* same planer */
+ float angle, base_dot, dot;
+ base_dot= Inpf(base_efa->cent, base_efa->n);
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if (!(efa->f & SELECT) && !efa->h) {
+ angle= VecAngle2(base_efa->n, efa->n);
+ if (angle/180.0<=thresh) {
+ dot=Inpf(efa->cent, base_efa->n);
+ if (fabs(base_dot-dot) <= thresh) {
+ EM_select_face(efa, 1);
+ selcount++;
+ deselcount--;
+ if (!deselcount) /*have we selected all posible faces?, if so return*/
+ return selcount;
+ }
+ }
+ }
+ }
+ }
+ }
+ } /* end base_efa loop */
+ return selcount;
+#endif
+}
+
+/* ***************************************************** */
+
+/* **************** LOOP SELECTS *************** */
+static void walker_select(BMEditMesh *em, int walkercode, void *start, int select)
+{
+ BMesh *bm = em->bm;
+ BMHeader *h;
+ BMWalker walker;
+
+ BMW_Init(&walker, bm, walkercode, 0);
+ h = BMW_Begin(&walker, start);
+ for (; h; h=BMW_Step(&walker)) {
+ BM_Select(bm, h, select);
+ }
+ BMW_End(&walker);
+}
+
+#if 0
+/* selects quads in loop direction of indicated edge */
+/* only flush over edges with valence <= 2 */
+void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
+{
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* tag startedge OK*/
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
+
+ /* if edge tagged, select opposing edge and mark face ok */
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* (de)select the faces */
+ if(select!=2) {
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f1) EM_select_face(efa, select);
+ }
+ }
+}
+#endif
+
+
+/* selects or deselects edges that:
+- if edges has 2 faces:
+ - has vertices with valence of 4
+ - not shares face with previous edge
+- if edge has 1 face:
+ - has vertices with valence 4
+ - not shares face with previous edge
+ - but also only 1 face
+- if edge no face:
+ - has vertices with valence 2
+*/
+
+/*
+ Almostly exactly the same code as faceloop select
+*/
+static void edgering_select(BMEditMesh *em, BMEdge *startedge, int select)
+{
+#if 0 //BMESH_TODO
+ BMEdge *eed;
+ BMFace *efa;
+ int looking= 1;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ /* tag startedge OK */
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
+
+ /* if edge tagged, select opposing edge and mark face ok */
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* (de)select the edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+#endif
+}
+
+static int loop_multiselect(bContext *C, wmOperator *op)
+{
+#if 0 //BMESH_TODO
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= EM_GetBMEditMesh(((Mesh *)obedit->data));
+ BMEdge *eed;
+ BMEdge **edarray;
+ int edindex, edfirstcount;
+ int looptype= RNA_boolean_get(op->ptr, "ring");
+
+ /* sets em->totedgesel */
+ EM_nedges_selected(em);
+
+ edarray = MEM_mallocN(sizeof(BMEdge*)*em->totedgesel,"edge array");
+ edindex = 0;
+ edfirstcount = em->totedgesel;
+
+ for(eed=em->edges.first; eed; eed=eed->next){
+ if(eed->f&SELECT){
+ edarray[edindex] = eed;
+ edindex += 1;
+ }
+ }
+
+ if(looptype){
+ for(edindex = 0; edindex < edfirstcount; edindex +=1){
+ eed = edarray[edindex];
+ edgering_select(em, eed,SELECT);
+ }
+ EM_selectmode_flush(em);
+ }
+ else{
+ for(edindex = 0; edindex < edfirstcount; edindex +=1){
+ eed = edarray[edindex];
+ edgeloop_select(em, eed,SELECT);
+ }
+ EM_selectmode_flush(em);
+ }
+ MEM_freeN(edarray);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ EM_EndBMEditMesh(obedit->data, em);
+#endif
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_multi_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Multi Select Loops";
+ ot->idname= "MESH_OT_loop_multi_select";
+
+ /* api callbacks */
+ ot->exec= loop_multiselect;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
+}
+
+
+/* ***************** MAIN MOUSE SELECTION ************** */
+
+
+/* ***************** loop select (non modal) ************** */
+
+static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring)
+{
+ ViewContext vc;
+ BMEditMesh *em;
+ BMEdge *eed;
+ int select= 1;
+ int dist= 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ eed= EDBM_findnearestedge(&vc, &dist);
+ if(eed) {
+ if(extend==0) EDBM_clear_flag_all(em, BM_SELECT);
+
+ if(BM_TestHFlag(em, BM_SELECT)==0) select=1;
+ else if(extend) select=0;
+
+ if(em->selectmode & SCE_SELECT_FACE) {
+ walker_select(em, BMW_FACELOOP, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if(ring)
+ edgering_select(em, eed, select);
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(ring)
+ edgering_select(em, eed, select);
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+
+ EDBM_selectmode_flush(em);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ }
+}
+
+static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "ring"));
+
+ /* cannot do tweaks for as long this keymap is after transform map */
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Loop Select";
+ ot->idname= "MESH_OT_loop_select";
+
+ /* api callbacks */
+ ot->invoke= mesh_select_loop_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
+}
+
+/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
+
+/* since you want to create paths with multiple selects, it doesn't have extend option */
+static void mouse_mesh_shortest_path(bContext *C, short mval[2])
+{
+#if 0 //BMESH_TODO
+ ViewContext vc;
+ BMEditMesh *em;
+ BMEdge *eed;
+ int dist= 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ eed= findnearestedge(&vc, &dist);
+ if(eed) {
+ Mesh *me= vc.obedit->data;
+ int path = 0;
+
+ if (em->selected.last) {
+ EditSelection *ese = em->selected.last;
+
+ if(ese && ese->type == BMEdge) {
+ BMEdge *eed_act;
+ eed_act = (BMEdge*)ese->data;
+ if (eed_act != eed) {
+ if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) {
+ EM_remove_selection(em, eed_act, BMEdge);
+ path = 1;
+ }
+ }
+ }
+ }
+ if (path==0) {
+ int act = (edgetag_context_check(vc.scene, eed)==0);
+ edgetag_context_set(vc.scene, eed, act); /* switch the edge option */
+ }
+
+ EM_selectmode_flush(em);
+
+ /* even if this is selected it may not be in the selection list */
+ if(edgetag_context_check(vc.scene, eed)==0)
+ EDBM_remove_selection(em, eed);
+ else
+ EDBM_store_selection(em, eed);
+
+ /* force drawmode for mesh */
+ switch (vc.scene->toolsettings->edge_mode) {
+
+ case EDGE_MODE_TAG_SEAM:
+ me->drawflag |= ME_DRAWSEAMS;
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ me->drawflag |= ME_DRAWSHARP;
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ me->drawflag |= ME_DRAWCREASES;
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ me->drawflag |= ME_DRAWBWEIGHTS;
+ break;
+ }
+
+ DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ }
+#endif
+}
+
+
+static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_shortest_path(C, event->mval);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_shortest_path(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shortest Path Select";
+ ot->idname= "MESH_OT_select_shortest_path";
+
+ /* api callbacks */
+ ot->invoke= mesh_shortest_path_select_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+}
+
+
+/* ************************************************** */
+/* here actual select happens */
+/* gets called via generic mouse select operator */
+void mouse_mesh(bContext *C, short mval[2], short extend)
+{
+ ViewContext vc;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+
+ if(unified_findnearest(&vc, &eve, &eed, &efa)) {
+
+ if(extend==0) EDBM_clear_flag_all(vc.em, BM_SELECT);
+
+ if(efa) {
+ /* set the last selected face */
+ EDBM_set_actFace(vc.em, efa);
+
+ if(!BM_TestHFlag(efa, BM_SELECT)) {
+ EDBM_store_selection(vc.em, efa);
+ BM_Select(vc.em->bm, efa, 1);
+ }
+ else if(extend) {
+ EDBM_remove_selection(vc.em, efa);
+ BM_Select(vc.em->bm, efa, 1);
+ }
+ }
+ else if(eed) {
+ if(!BM_TestHFlag(eed, BM_SELECT)) {
+ EDBM_store_selection(vc.em, eed);
+ BM_Select(vc.em->bm, eed, 1);
+ }
+ else if(extend) {
+ EDBM_remove_selection(vc.em, eed);
+ BM_Select(vc.em->bm, eed, 0);
+ }
+ }
+ else if(eve) {
+ if(!BM_TestHFlag(eve, BM_SELECT)) {
+ EDBM_store_selection(vc.em, eve);
+ BM_Select(vc.em->bm, eve, 1);
+ }
+ else if(extend){
+ EDBM_remove_selection(vc.em, eve);
+ BM_Select(vc.em->bm, eve, 0);
+ }
+ }
+
+ EDBM_selectmode_flush(vc.em);
+
+// if (EM_texFaceCheck()) {
+
+ if (efa && efa->mat_nr != vc.obedit->actcol-1) {
+ vc.obedit->actcol= efa->mat_nr+1;
+ vc.em->mat_nr= efa->mat_nr;
+// BIF_preview_changed(ID_MA);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+}
+
+static void EDBM_strip_selections(BMEditMesh *em)
+{
+ BMEditSelection *ese, *nextese;
+
+ if(!(em->selectmode & SCE_SELECT_VERTEX)){
+ ese = em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_VERT) BLI_freelinkN(&(em->selected),ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_EDGE)){
+ ese=em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_EDGE) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_FACE)){
+ ese=em->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_FACE) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+ }
+}
+
+/* when switching select mode, makes sure selection is consistant for editing */
+/* also for paranoia checks to make sure edge or face mode works */
+void EDBM_selectmode_set(BMEditMesh *em)
+{
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ em->bm->selectmode = em->selectmode;
+
+ EDBM_strip_selections(em); /*strip BMEditSelections from em->selected that are not relevant to new mode*/
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ BMIter iter;
+
+ /*eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
+
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) BM_Select(em->bm, efa, 0);*/
+
+ EDBM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ /* deselect vertices, and select again based on edge select */
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; eve; eve=BMIter_Step(&iter)) BM_Select(em->bm, eve, 0);
+
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(eed, BM_SELECT))
+ BM_Select(em->bm, eed, 1);
+ }
+
+ /* selects faces based on edge status */
+ EDBM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_FACE) {
+ /* deselect eges, and select again based on face select */
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
+
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(efa, BM_SELECT))
+ BM_Select(em->bm, efa, 1);
+ }
+ }
+}
+
+void EDBM_convertsel(BMEditMesh *em, short oldmode, short selectmode)
+{
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ /*have to find out what the selectionmode was previously*/
+ if(oldmode == SCE_SELECT_VERTEX) {
+ if(selectmode == SCE_SELECT_EDGE) {
+ /*select all edges associated with every selected vertex*/
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if(BM_TestHFlag(eed->v1, BM_SELECT)) BM_Select(em->bm, eed, 1);
+ else if(BM_TestHFlag(eed->v2, BM_SELECT)) BM_Select(em->bm, eed, 1);
+ }
+ }
+ else if(selectmode == SCE_SELECT_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ /*select all faces associated with every selected vertex*/
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ BM_Select(em->bm, efa, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(oldmode == SCE_SELECT_EDGE){
+ if(selectmode == SCE_SELECT_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ /*select all faces associated with every selected vertex*/
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ BM_Select(em->bm, efa, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/editors/mesh/bmesh_selecthistory.c b/source/blender/editors/mesh/bmesh_selecthistory.c
new file mode 100644
index 00000000000..9421a98a11c
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_selecthistory.c
@@ -0,0 +1,270 @@
+/**
+ * $Id:
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* ********* Selection History ************ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "MTC_matrixops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_render_ext.h" /* externtex */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "bmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "mesh_intern.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* XXX */
+static void waitcursor() {}
+static int pupmenu() {return 0;}
+
+/* generic way to get data from an EditSelection type
+These functions were written to be used by the Modifier widget when in Rotate about active mode,
+but can be used anywhere.
+EM_editselection_center
+EM_editselection_normal
+EM_editselection_plane
+*/
+void EDBM_editselection_center(BMEditMesh *em, float *center, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ VecCopyf(center, eve->co);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ VecAddf(center, eed->v1->co, eed->v2->co);
+ VecMulf(center, 0.5);
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ BM_Compute_Face_Center(em->bm, efa, center);
+ }
+}
+
+void EDBM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ VecCopyf(normal, eve->no);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ VecAddf(normal, eed->v1->no, eed->v2->no);
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ for rotate about edge we want them to be at right angles, so we need to
+ do some extra colculation to correct the vert normals,
+ we need the plane for this */
+ Crossf(vec, normal, plane);
+ Crossf(normal, plane, vec);
+ Normalize(normal);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ VecCopyf(normal, efa->no);
+ }
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run allong an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void EDBM_editselection_plane(BMEditMesh *em, float *plane, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ float vec[3]={0,0,0};
+
+ if (ese->prev) { /*use previously selected data to make a usefull vertex plane */
+ EDBM_editselection_center(em, vec, ese->prev);
+ VecSubf(plane, vec, eve->co);
+ } else {
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (eve->no[0]<0.5) vec[0]=1;
+ else if (eve->no[1]<0.5) vec[1]=1;
+ else vec[2]=1;
+ Crossf(plane, eve->no, vec);
+ }
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+
+ /*the plane is simple, it runs allong the edge
+ however selecting different edges can swap the direction of the y axis.
+ this makes it less likely for the y axis of the manipulator
+ (running along the edge).. to flip less often.
+ at least its more pradictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+ else
+ VecSubf(plane, eed->v1->co, eed->v2->co);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+
+ /*for now, use face normal*/
+
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (efa->no[0]<0.5) vec[0]=1.0f;
+ else if (efa->no[1]<0.5) vec[1]=1.0f;
+ else vec[2]=1.0f;
+ Crossf(plane, efa->no, vec);
+#if 0
+
+ if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
+ float vecA[3], vecB[3];
+ VecSubf(vecA, efa->v4->co, efa->v3->co);
+ VecSubf(vecB, efa->v1->co, efa->v2->co);
+ VecAddf(plane, vecA, vecB);
+
+ VecSubf(vecA, efa->v1->co, efa->v4->co);
+ VecSubf(vecB, efa->v2->co, efa->v3->co);
+ VecAddf(vec, vecA, vecB);
+ /*use the biggest edge length*/
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ } else {
+ /*start with v1-2 */
+ VecSubf(plane, efa->v1->co, efa->v2->co);
+
+ /*test the edge between v2-3, use if longer */
+ VecSubf(vec, efa->v2->co, efa->v3->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+
+ /*test the edge between v1-3, use if longer */
+ VecSubf(vec, efa->v3->co, efa->v1->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ }
+#endif
+ }
+ Normalize(plane);
+}
+
+static int EDBM_check_selection(BMEditMesh *em, void *data)
+{
+ BMEditSelection *ese;
+
+ for(ese = em->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void EDBM_remove_selection(BMEditMesh *em, void *data)
+{
+ BMEditSelection *ese;
+ for(ese=em->selected.first; ese; ese = ese->next){
+ if(ese->data == data){
+ BLI_freelinkN(&(em->selected),ese);
+ break;
+ }
+ }
+}
+
+void EDBM_store_selection(BMEditMesh *em, void *data)
+{
+ BMEditSelection *ese;
+ if(!EDBM_check_selection(em, data)){
+ ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
+ ese->type = ((BMHeader*)data)->type;
+ ese->data = data;
+ BLI_addtail(&(em->selected),ese);
+ }
+}
+
+void EDBM_validate_selections(BMEditMesh *em)
+{
+ BMEditSelection *ese, *nextese;
+
+ ese = em->selected.first;
+
+ while(ese){
+ nextese = ese->next;
+ if (!BM_TestHFlag(ese->data, BM_SELECT)) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+}
diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c
new file mode 100644
index 00000000000..103bcbcebce
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_tools.c
@@ -0,0 +1,1321 @@
+ /* $Id: bmesh_tools.c
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+
+#include "UI_interface.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+static void add_normal_aligned(float *nor, float *add)
+{
+ if( INPR(nor, add) < -0.9999f)
+ VecSubf(nor, nor, add);
+ else
+ VecAddf(nor, nor, add);
+}
+
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int cuts= RNA_int_get(op->ptr,"number_cuts");
+ float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness");
+ float fractal= RNA_float_get(op->ptr, "fractal")/100;
+ int flag= 0;
+
+ if(smooth != 0.0f)
+ flag |= B_SMOOTH;
+ if(fractal != 0.0f)
+ flag |= B_FRACTAL;
+
+ BM_esubdivideflag(obedit, em->bm, BM_SELECT, smooth, fractal, scene->toolsettings->editbutflag|flag, cuts, 0);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->idname= "MESH_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+ RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX);
+}
+
+#if 0
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ BM_esubdivideflag(obedit, em->bm, 1, 0.0, scene->toolsettings->editbutflag, 1, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->idname= "MESH_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int subdivide_multi_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ BM_esubdivideflag(obedit, em->bm, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_multi(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Multi";
+ ot->idname= "MESH_OT_subdivide_multi";
+
+ /* api callbacks */
+ ot->exec= subdivide_multi_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
+}
+
+static int subdivide_multi_fractal_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ BM_esubdivideflag(obedit, em->bm, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_multi_fractal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Multi Fractal";
+ ot->idname= "MESH_OT_subdivide_multi_fractal";
+
+ /* api callbacks */
+ ot->exec= subdivide_multi_fractal_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
+ RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
+}
+
+static int subdivide_smooth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ BM_esubdivideflag(obedit, em->bm, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivide_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide Smooth";
+ ot->idname= "MESH_OT_subdivide_smooth";
+
+ /* api callbacks */
+ ot->exec= subdivide_smooth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);
+}
+
+static int subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup= uiPupMenuBegin(C, "Subdivision Type", 0);
+ layout= uiPupMenuLayout(pup);
+ uiItemsEnumO(layout, "MESH_OT_subdivs", "type");
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+}
+
+static int subdivs_exec(bContext *C, wmOperator *op)
+{
+ switch(RNA_int_get(op->ptr, "type"))
+ {
+ case 0: // simple
+ subdivide_exec(C,op);
+ break;
+ case 1: // multi
+ subdivide_multi_exec(C,op);
+ break;
+ case 2: // fractal;
+ subdivide_multi_fractal_exec(C,op);
+ break;
+ case 3: //smooth
+ subdivide_smooth_exec(C,op);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_subdivs(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ {0, "SIMPLE", 0, "Simple", ""},
+ {1, "MULTI", 0, "Multi", ""},
+ {2, "FRACTAL", 0, "Fractal", ""},
+ {3, "SMOOTH", 0, "Smooth", ""},
+ {0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "subdivs";
+ ot->idname= "MESH_OT_subdivs";
+
+ /* api callbacks */
+ ot->invoke= subdivs_invoke;
+ ot->exec= subdivs_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+
+ /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
+ RNA_def_int(ot->srna, "number_cuts", 4, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+ RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
+ RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);
+}
+#endif
+
+/* individual face extrude */
+/* will use vertex normals for extrusion directions, so *nor is unaffected */
+short EDBM_Extrude_face_indiv(BMEditMesh *em, short flag, float *nor)
+{
+#if 0
+ EditVert *eve, *v1, *v2, *v3, *v4;
+ EditEdge *eed;
+ EditFace *efa, *nextfa;
+
+ if(em==NULL) return 0;
+
+ /* selected edges with 1 or more selected face become faces */
+ /* selected faces each makes new faces */
+ /* always remove old faces, keeps volumes manifold */
+ /* select the new extrusion, deselect old */
+
+ /* step 1; init, count faces in edges */
+ recalc_editnormals(em);
+
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f2= 0; // amount of unselected faces
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT);
+ else {
+ efa->e1->f2++;
+ efa->e2->f2++;
+ efa->e3->f2++;
+ if(efa->e4) efa->e4->f2++;
+ }
+ }
+
+ /* step 2: make new faces from faces */
+ for(efa= em->faces.last; efa; efa= efa->prev) {
+ if(efa->f & SELECT) {
+ v1= addvertlist(em, efa->v1->co, efa->v1);
+ v2= addvertlist(em, efa->v2->co, efa->v2);
+ v3= addvertlist(em, efa->v3->co, efa->v3);
+
+ v1->f1= v2->f1= v3->f1= 1;
+ VECCOPY(v1->no, efa->n);
+ VECCOPY(v2->no, efa->n);
+ VECCOPY(v3->no, efa->n);
+ if(efa->v4) {
+ v4= addvertlist(em, efa->v4->co, efa->v4);
+ v4->f1= 1;
+ VECCOPY(v4->no, efa->n);
+ }
+ else v4= NULL;
+
+ /* side faces, clockwise */
+ addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL);
+ addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL);
+ if(efa->v4) {
+ addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL);
+ addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL);
+ }
+ else {
+ addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL);
+ }
+ /* top face */
+ addfacelist(em, v1, v2, v3, v4, efa, NULL);
+ }
+ }
+
+ /* step 3: remove old faces */
+ efa= em->faces.first;
+ while(efa) {
+ nextfa= efa->next;
+ if(efa->f & SELECT) {
+ BLI_remlink(&em->faces, efa);
+ free_editface(em, efa);
+ }
+ efa= nextfa;
+ }
+
+ /* step 4: redo selection */
+ EM_clear_flag_all(em, SELECT);
+
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1) eve->f |= SELECT;
+ }
+
+ EM_select_flush(em);
+
+ return 'n';
+#endif
+}
+
+
+/* extrudes individual edges */
+/* nor is filled with constraint vector */
+short EDBM_Extrude_edges_indiv(BMEditMesh *em, short flag, float *nor)
+{
+#if 0
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+
+ for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->tmp.f = NULL;
+ eed->f2= ((eed->f & flag)!=0);
+ }
+
+ set_edge_directions_f2(em, 2);
+
+ /* sample for next loop */
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->e1->tmp.f = efa;
+ efa->e2->tmp.f = efa;
+ efa->e3->tmp.f = efa;
+ if(efa->e4) efa->e4->tmp.f = efa;
+ }
+ /* make the faces */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f & flag) {
+ if(eed->v1->tmp.v == NULL)
+ eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
+ if(eed->v2->tmp.v == NULL)
+ eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
+
+ if(eed->dir==1)
+ addfacelist(em, eed->v1, eed->v2,
+ eed->v2->tmp.v, eed->v1->tmp.v,
+ eed->tmp.f, NULL);
+ else
+ addfacelist(em, eed->v2, eed->v1,
+ eed->v1->tmp.v, eed->v2->tmp.v,
+ eed->tmp.f, NULL);
+
+ /* for transform */
+ if(eed->tmp.f) {
+ efa = eed->tmp.f;
+ if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
+ }
+ }
+ }
+ Normalize(nor);
+
+ /* set correct selection */
+ EM_clear_flag_all(em, SELECT);
+ for(eve= em->verts.last; eve; eve= eve->prev) {
+ if(eve->tmp.v) {
+ eve->tmp.v->f |= flag;
+ }
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
+ }
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
+#endif
+ return 'n'; // n is for normal constraint
+}
+
+/* extrudes individual vertices */
+short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
+{
+ BMOperator bmop;
+ BMOIter siter;
+ BMVert *v;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag);
+
+ /*deselect original verts*/
+ v = BMO_IterNew(&siter, em->bm, &bmop, "verts", BM_VERT);
+ for (; v; v=BMO_IterStep(&siter)) {
+ BM_Select(em->bm, v, 0);
+ }
+
+ BMO_Exec_Op(em->bm, &bmop);
+
+ v = BMO_IterNew(&siter, em->bm, &bmop, "vertout", BM_VERT);
+ for (; v; v=BMO_IterStep(&siter)) {
+ BM_Select(em->bm, v, 1);
+ }
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 'g'; // g is grab
+}
+
+short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int flag, float *nor)
+{
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMOIter siter;
+ BMOperator extop;
+ BMVert *vert;
+ BMEdge *edge;
+ BMFace *f;
+ ModifierData *md;
+ BMHeader *el;
+
+ BMO_Init_Op(&extop, "extrudefaceregion");
+ BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein",
+ flag, BM_VERT|BM_EDGE|BM_FACE);
+
+ BM_ITER(vert, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_Select(bm, vert, 0);
+ }
+
+ BM_ITER(edge, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BM_Select(bm, edge, 0);
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_Select(bm, f, 0);
+ }
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ md = obedit->modifiers.first;
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ Mat4Invert(imtx, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, obedit->obmat, imtx);
+ }
+
+ for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL);
+ edge; edge=BMIter_Step(&iter))
+ {
+ if(edge->head.flag & flag) {
+ float co1[3], co2[3];
+
+ VecCopyf(co1, edge->v1->co);
+ VecCopyf(co2, edge->v2->co);
+
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(co1, mtx, co1);
+ VecMat4MulVecfl(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ if ( (fabs(co1[0]) < mmd->tolerance) &&
+ (fabs(co2[0]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ if ( (fabs(co1[1]) < mmd->tolerance) &&
+ (fabs(co2[1]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ if ( (fabs(co1[2]) < mmd->tolerance) &&
+ (fabs(co2[2]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ BMO_Exec_Op(bm, &extop);
+
+ nor[0] = nor[1] = nor[2] = 0.0f;
+
+ BMO_ITER(el, &siter, bm, &extop, "geomout", BM_ALL) {
+ BM_Select(bm, el, 1);
+
+ if (el->type == BM_FACE) {
+ f = (BMFace*)el;
+ add_normal_aligned(nor, f->no);
+ };
+ }
+
+ Normalize(nor);
+
+ BMO_Finish_Op(bm, &extop);
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
+ return 'n'; // normal constraint
+
+}
+short EDBM_Extrude_vert(Object *obedit, BMEditMesh *em, short flag, float *nor)
+{
+ BMIter iter;
+ BMEdge *eed;
+
+ /*ensure vert flags are consistent for edge selections*/
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(eed, flag)) {
+ if (flag != BM_SELECT) {
+ BM_SetHFlag(eed->v1, flag);
+ BM_SetHFlag(eed->v2, flag);
+ } else {
+ BM_Select(em->bm, eed->v1, 1);
+ BM_Select(em->bm, eed->v2, 1);
+ }
+ } else {
+ if (BM_TestHFlag(eed->v1, flag) && BM_TestHFlag(eed->v2, flag)) {
+ if (flag != BM_SELECT)
+ BM_SetHFlag(eed, flag);
+ else BM_Select(em->bm, eed, 1);
+ }
+ }
+ }
+
+ return EDBM_Extrude_edge(obedit, em, flag, nor);
+
+}
+
+static int extrude_repeat_mesh(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ int steps = RNA_int_get(op->ptr,"steps");
+
+ float offs = RNA_float_get(op->ptr,"offset");
+
+ float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
+ short a;
+
+ /* dvec */
+ dvec[0]= rv3d->persinv[2][0];
+ dvec[1]= rv3d->persinv[2][1];
+ dvec[2]= rv3d->persinv[2][2];
+ Normalize(dvec);
+ dvec[0]*= offs;
+ dvec[1]*= offs;
+ dvec[2]*= offs;
+
+ /* base correction */
+ Mat3CpyMat4(bmat, obedit->obmat);
+ Mat3Inv(tmat, bmat);
+ Mat3MulVecfl(tmat, dvec);
+
+ for(a=0; a<steps; a++) {
+ EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
+ //BMO_CallOpf(em->bm, "extrudefaceregion edgefacein=%hef", BM_SELECT);
+ BMO_CallOpf(em->bm, "translate vec=%v verts=%hv", (float*)dvec, BM_SELECT);
+ //extrudeflag(obedit, em, SELECT, nor);
+ //translateflag(em, SELECT, dvec);
+ }
+
+ EDBM_RecalcNormals(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_repeat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Repeat Mesh";
+ ot->idname= "MESH_OT_extrude_repeat";
+
+ /* api callbacks */
+ ot->exec= extrude_repeat_mesh;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
+ RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
+}
+
+/* generic extern called extruder */
+int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *norin)
+{
+ Scene *scene= NULL; // XXX CTX!
+ short nr, transmode= 0;
+ float stacknor[3] = {0.0f, 0.0f, 0.0f};
+ float *nor = norin ? norin : stacknor;
+
+ nor[0] = nor[1] = nor[2] = 0.0f;
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->bm->totvertsel==0) nr= 0;
+ else if(em->bm->totvertsel==1) nr= 4;
+ else if(em->bm->totedgesel==0) nr= 4;
+ else if(em->bm->totfacesel==0)
+ nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ else if(em->bm->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if (em->bm->totedgesel==0) nr = 0;
+
+ nr = 1;
+ /*else if (em->totedgesel==1) nr = 3;
+ else if(em->totfacesel==0) nr = 3;
+ else if(em->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ */
+ }
+ else {
+ if (em->bm->totfacesel == 0) nr = 0;
+ else if (em->bm->totfacesel == 1) nr = 1;
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ }
+
+ if(nr<1) return 'g';
+
+ if(nr==1 && em->selectmode & SCE_SELECT_VERTEX)
+ transmode= EDBM_Extrude_vert(obedit, em, SELECT, nor);
+ else if (nr == 1) transmode= EDBM_Extrude_edge(obedit, em, SELECT, nor);
+ else if(nr==4) transmode= EDBM_Extrude_verts_indiv(em, op, SELECT, nor);
+ else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, SELECT, nor);
+ else transmode= EDBM_Extrude_face_indiv(em, SELECT, nor);
+
+ if(transmode==0) {
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ }
+ else {
+
+ /* We need to force immediate calculation here because
+ * transform may use derived objects (which are now stale).
+ *
+ * This shouldn't be necessary, derived queries should be
+ * automatically building this data if invalid. Or something.
+ */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ object_handle_update(scene, obedit);
+
+ /* individual faces? */
+// BIF_TransformSetUndo("Extrude");
+ if(nr==2) {
+// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
+// Transform();
+ }
+ else {
+// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
+ if(transmode=='n') {
+ Mat4MulVecfl(obedit->obmat, nor);
+ VecSubf(nor, nor, obedit->obmat[3]);
+// BIF_setSingleAxisConstraint(nor, "along normal");
+ }
+// Transform();
+ }
+ }
+
+ return transmode;
+}
+
+static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ int constraint_axis[3] = {0, 0, 1};
+ int tmode;
+
+ tmode = EDBM_Extrude_Mesh(obedit, em, op, NULL);
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ RNA_enum_set(op->ptr, "proportional", 0);
+ RNA_boolean_set(op->ptr, "mirror", 0);
+
+ if (tmode == 'n') {
+ RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
+ RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
+ }
+ WM_operator_name_call(C, "TFM_OT_translation", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+/* extrude without transform */
+static int mesh_extrude_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ EDBM_Extrude_Mesh(obedit, em, op, NULL);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude";
+ ot->idname= "MESH_OT_extrude";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_invoke;
+ ot->exec= mesh_extrude_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ Properties_Proportional(ot);
+ Properties_Constraints(ot);
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+/* ******************** (de)select all operator **************** */
+
+void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */
+{
+ if(em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
+ EDBM_clear_flag_all(em, SELECT);
+ else
+ EDBM_set_flag_all(em, SELECT);
+}
+
+static int toggle_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ EDBM_toggle_select_all(em);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_all_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select/Deselect All";
+ ot->idname= "MESH_OT_select_all_toggle";
+
+ /* api callbacks */
+ ot->exec= toggle_select_all_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *************** add-click-mesh (extrude) operator ************** */
+
+static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewContext vc;
+ BMVert *eve, *v1;
+ BMIter iter;
+ float min[3], max[3];
+ int done= 0;
+
+ em_setup_viewcontext(C, &vc);
+
+ INIT_MINMAX(min, max);
+
+ BM_ITER(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(v1, BM_SELECT)) {
+ DO_MINMAX(v1->co, min, max);
+ done= 1;
+ }
+ }
+
+ /* call extrude? */
+ if(done) {
+ BMEdge *eed;
+ float vec[3], cent[3], mat[3][3];
+ float nor[3]= {0.0, 0.0, 0.0};
+
+ /* check for edges that are half selected, use for rotation */
+ done= 0;
+ BM_ITER(eed, &iter, vc.em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed->v1, BM_SELECT) ^ BM_TestHFlag(eed->v2, BM_SELECT)) {
+ if(BM_TestHFlag(eed->v1, BM_SELECT))
+ VecSubf(vec, eed->v1->co, eed->v2->co);
+ else
+ VecSubf(vec, eed->v2->co, eed->v1->co);
+ VecAddf(nor, nor, vec);
+ done= 1;
+ }
+ }
+ if(done) Normalize(nor);
+
+ /* center */
+ VecAddf(cent, min, max);
+ VecMulf(cent, 0.5f);
+ VECCOPY(min, cent);
+
+ Mat4MulVecfl(vc.obedit->obmat, min); // view space
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval);
+ Mat4Invert(vc.obedit->imat, vc.obedit->obmat);
+ Mat4MulVecfl(vc.obedit->imat, min); // back in object space
+
+ VecSubf(min, min, cent);
+
+ /* calculate rotation */
+ Mat3One(mat);
+ if(done) {
+ float dot;
+
+ VECCOPY(vec, min);
+ Normalize(vec);
+ dot= INPR(vec, nor);
+
+ if( fabs(dot)<0.999) {
+ float cross[3], si, q1[4];
+
+ Crossf(cross, nor, vec);
+ Normalize(cross);
+ dot= 0.5f*saacos(dot);
+ si= (float)sin(dot);
+ q1[0]= (float)cos(dot);
+ q1[1]= cross[0]*si;
+ q1[2]= cross[1]*si;
+ q1[3]= cross[2]*si;
+
+ QuatToMat3(q1, mat);
+ }
+ }
+
+
+ EDBM_Extrude_edge(vc.obedit, vc.em, SELECT, nor);
+ EDBM_CallOpf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3",
+ BM_SELECT, cent, mat);
+ EDBM_CallOpf(vc.em, op, "translate verts=%hv vec=%v",
+ BM_SELECT, min);
+ }
+ else {
+ float *curs= give_cursor(vc.scene, vc.v3d);
+ BMOperator bmop;
+ BMOIter oiter;
+
+ VECCOPY(min, curs);
+
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval);
+ Mat4Invert(vc.obedit->imat, vc.obedit->obmat);
+ Mat4MulVecfl(vc.obedit->imat, min); // back in object space
+
+ EDBM_InitOpf(vc.em, &bmop, op, "makevert co=%v", min);
+ BMO_Exec_Op(vc.em->bm, &bmop);
+
+ BMO_ITER(v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) {
+ BM_Select(vc.em->bm, v1, 1);
+ }
+
+ if (!EDBM_FinishOp(vc.em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+ }
+
+ //retopo_do_all();
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
+ DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate or Extrude at 3D Cursor";
+ ot->idname= "MESH_OT_dupli_extrude_cursor";
+
+ /* api callbacks */
+ ot->invoke= dupli_extrude_cursor;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int delete_mesh(Object *obedit, wmOperator *op, int event, Scene *scene)
+{
+ BMEditMesh *bem = ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(event<1) return OPERATOR_CANCELLED;
+
+ if(event==10 ) {
+ //"Erase Vertices";
+
+ if (!EDBM_CallOpf(bem, op, "del geom=%hv context=%i", BM_SELECT, DEL_VERTS))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==11) {
+ //"Edge Loop"
+ if (!EDBM_CallOpf(bem, op, "dissolveedgeloop edges=%he", BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==7) {
+ //"Dissolve"
+ if (bem->selectmode & SCE_SELECT_FACE) {
+ if (!EDBM_CallOpf(bem, op, "dissolvefaces faces=%hf",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ } else if (bem->selectmode & SCE_SELECT_EDGE) {
+ if (!EDBM_CallOpf(bem, op, "dissolveedges edges=%he",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ } else if (bem->selectmode & SCE_SELECT_VERTEX) {
+ if (!EDBM_CallOpf(bem, op, "dissolveverts verts=%hv",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if(event==4) {
+ //Edges and Faces
+ if (!EDBM_CallOpf(bem, op, "del geom=%hef context=%i", BM_SELECT, DEL_EDGESFACES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==1) {
+ //"Erase Edges"
+ if (!EDBM_CallOpf(bem, op, "del geom=%he context=%i", BM_SELECT, DEL_EDGES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==2) {
+ //"Erase Faces";
+ if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%i", BM_SELECT, DEL_FACES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==5) {
+ //"Erase Only Faces";
+ if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%d",
+ BM_SELECT, DEL_ONLYFACES))
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+/* Note, these values must match delete_mesh() event values */
+static EnumPropertyItem prop_mesh_delete_types[] = {
+ {7, "DISSOLVE", 0, "Dissolve", ""},
+ {10,"VERT", 0, "Vertices", ""},
+ {1, "EDGE", 0, "Edges", ""},
+ {2, "FACE", 0, "Faces", ""},
+ {11, "EDGE_LOOP", 0, "Edge Loop", ""},
+ {4, "EDGE_FACE", 0, "Edges & Faces", ""},
+ {5, "ONLY_FACE", 0, "Only Faces", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int delete_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ delete_mesh(obedit, op, RNA_enum_get(op->ptr, "type"), scene);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "MESH_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= delete_mesh_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
+}
+
+
+static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
+{
+ BMOperator bmop;
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "contextual_create geom=%hfev", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_face_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Edge/Face";
+ ot->idname= "MESH_OT_edge_face_add";
+
+ /* api callbacks */
+ ot->exec= addedgeface_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+static EnumPropertyItem prop_mesh_edit_types[] = {
+ {1, "VERT", 0, "Vertices", ""},
+ {2, "EDGE", 0, "Edges", ""},
+ {3, "FACE", 0, "Faces", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int mesh_selection_type_exec(bContext *C, wmOperator *op)
+{
+
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int type = RNA_enum_get(op->ptr,"type");
+
+ switch (type) {
+ case 1:
+ em->selectmode = SCE_SELECT_VERTEX;
+ break;
+ case 2:
+ em->selectmode = SCE_SELECT_EDGE;
+ break;
+ case 3:
+ em->selectmode = SCE_SELECT_FACE;
+ break;
+ }
+
+ EDBM_selectmode_set(em);
+ CTX_data_scene(C)->toolsettings->selectmode = em->selectmode;
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_selection_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Selection Mode";
+ ot->idname= "MESH_OT_selection_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= mesh_selection_type_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
+ RNA_def_boolean(ot->srna, "inclusive", 0, "Inclusive", "Selects geometry around selected geometry, occording to selection mode");
+}
+
+/* ************************* SEAMS AND EDGES **************** */
+
+static int editbmesh_mark_seam(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= ((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMEdge *eed;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ /* auto-enable seams drawing */
+ if(clear==0) {
+ me->drawflag |= ME_DRAWSEAMS;
+ }
+
+ if(clear) {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
+ BM_TestHFlag(eed, BM_SELECT) != 0)
+ {
+ BM_ClearHFlag(eed, BM_SEAM);
+ }
+ }
+ }
+ else {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
+ BM_TestHFlag(eed, BM_SELECT) != 0)
+ {
+ BM_SetHFlag(eed, BM_SEAM);
+ }
+ }
+ }
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_seam(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Seam";
+ ot->idname= "MESH_OT_mark_seam";
+
+ /* api callbacks */
+ ot->exec= editbmesh_mark_seam;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+static int editbmesh_mark_sharp(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= ((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMEdge *eed;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ /* auto-enable sharp edge drawing */
+ if(clear == 0) {
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
+ if(!clear) {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
+ BM_TestHFlag(eed, BM_SELECT) != 0)
+ {
+ BM_SetHFlag(eed, BM_SHARP);
+ }
+ }
+ } else {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
+ BM_TestHFlag(eed, BM_SELECT) != 0)
+ {
+ BM_ClearHFlag(eed, BM_SHARP);
+ }
+ }
+ }
+
+
+ DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Sharp";
+ ot->idname= "MESH_OT_mark_sharp";
+
+ /* api callbacks */
+ ot->exec= editbmesh_mark_sharp;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c
new file mode 100644
index 00000000000..e3ec1c16ce3
--- /dev/null
+++ b/source/blender/editors/mesh/bmeshutils.c
@@ -0,0 +1,523 @@
+ /* $Id: bmeshutils.c
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+void EDBM_RecalcNormals(BMEditMesh *em)
+{
+ BM_Compute_Normals(em->bm);
+}
+
+void EDBM_stats_update(BMEditMesh *em)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ tots[0] = &em->bm->totvertsel;
+ tots[1] = &em->bm->totedgesel;
+ tots[2] = &em->bm->totfacesel;
+
+ em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, em->bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(ele, BM_SELECT)) {
+ *tots[i]++;
+ }
+ }
+ }
+}
+
+/*this function is defunct, dead*/
+void EDBM_Tesselate(EditMesh *em)
+{
+ EditMesh *em2;
+ EditFace *efa;
+ BMesh *bm;
+ int found=0;
+
+ for (efa=em->faces.first; efa; efa=efa->next) {
+ if ((efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||
+ (efa->e3->h & EM_FGON) || (efa->e4&&(efa->e4->h&EM_FGON)))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ bm = editmesh_to_bmesh(em);
+ em2 = bmesh_to_editmesh(bm);
+ set_editMesh(em, em2);
+
+ MEM_freeN(em2);
+ BM_Free_Mesh(bm);
+ }
+}
+
+int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, bmop, fmt, list)) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Parse error in EDBM_CallOpf");
+ va_end(list);
+ return 0;
+ }
+
+ em->emcopy = BMEdit_Copy(em);
+
+ va_end(list);
+}
+
+
+/*returns 0 on error, 1 on success. executes and finishes a bmesh operator*/
+int EDBM_FinishOp(BMEditMesh *em, BMOperator *bmop, wmOperator *op, int report) {
+ char *errmsg;
+
+ BMO_Finish_Op(em->bm, bmop);
+
+ if (BMO_GetError(em->bm, &errmsg, NULL)) {
+ BMEditMesh *emcopy = em->emcopy;
+
+ if (report) BKE_report(op->reports, RPT_ERROR, errmsg);
+
+ BMEdit_Free(em);
+ *em = *emcopy;
+
+ MEM_freeN(emcopy);
+ return 0;
+ } else {
+ BMEdit_Free(em->emcopy);
+ MEM_freeN(em->emcopy);
+ em->emcopy = NULL;
+ }
+
+ return 1;
+}
+
+int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Parse error in EDBM_CallOpf");
+ va_end(list);
+ return 0;
+ }
+
+ em->emcopy = BMEdit_Copy(em);
+
+ BMO_Exec_Op(bm, &bmop);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, op, 1);
+}
+
+int EDBM_CallOpfSilent(BMEditMesh *em, char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
+ va_end(list);
+ return 0;
+ }
+
+ em->emcopy = BMEdit_Copy(em);
+
+ BMO_Exec_Op(bm, &bmop);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, NULL, 0);
+}
+
+void EDBM_MakeEditBMesh(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ EditMesh *em;
+ BMesh *bm;
+
+ if (!me->mpoly && me->totface) {
+ em = make_editMesh(scene, ob);
+ bm = editmesh_to_bmesh(em);
+
+ free_editMesh(em);
+ } else {
+ bm = BKE_mesh_to_bmesh(me);
+ }
+
+ me->edit_btmesh = BMEdit_Create(bm);
+ me->edit_btmesh->selectmode = scene->toolsettings->selectmode;
+}
+
+void EDBM_LoadEditBMesh(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ BMesh *bm = me->edit_btmesh->bm;
+
+ BMO_CallOpf(bm, "object_load_bmesh scene=%p object=%p", scene, ob);
+
+#if 0
+ EditMesh *em = bmesh_to_editmesh(me->edit_btmesh->bm);
+
+ load_editMesh(scene, ob, em);
+ free_editMesh(em);
+ MEM_freeN(em);
+#endif
+}
+
+void EDBM_FreeEditBMesh(BMEditMesh *tm)
+{
+ BMEdit_Free(tm);
+}
+
+void EDBM_init_index_arrays(BMEditMesh *tm, int forvert, int foredge, int forface)
+{
+ EDBM_free_index_arrays(tm);
+
+ if (forvert) {
+ BMIter iter;
+ BMVert *ele;
+ int i=0;
+
+ tm->vert_index = MEM_mallocN(sizeof(void**)*tm->bm->totvert, "tm->vert_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->vert_index[i++] = ele;
+ }
+ }
+
+ if (foredge) {
+ BMIter iter;
+ BMEdge *ele;
+ int i=0;
+
+ tm->edge_index = MEM_mallocN(sizeof(void**)*tm->bm->totedge, "tm->edge_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->edge_index[i++] = ele;
+ }
+ }
+
+ if (forface) {
+ BMIter iter;
+ BMFace *ele;
+ int i=0;
+
+ tm->face_index = MEM_mallocN(sizeof(void**)*tm->bm->totface, "tm->face_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->face_index[i++] = ele;
+ }
+ }
+}
+
+void EDBM_free_index_arrays(BMEditMesh *tm)
+{
+ if (tm->vert_index) {
+ MEM_freeN(tm->vert_index);
+ tm->vert_index = NULL;
+ }
+
+ if (tm->edge_index) {
+ MEM_freeN(tm->edge_index);
+ tm->edge_index = NULL;
+ }
+
+ if (tm->face_index) {
+ MEM_freeN(tm->face_index);
+ tm->face_index = NULL;
+ }
+}
+
+BMVert *EDBM_get_vert_for_index(BMEditMesh *tm, int index)
+{
+ return tm->vert_index?tm->vert_index[index]:NULL;
+}
+
+BMEdge *EDBM_get_edge_for_index(BMEditMesh *tm, int index)
+{
+ return tm->edge_index?tm->edge_index[index]:NULL;
+}
+
+BMFace *EDBM_get_face_for_index(BMEditMesh *tm, int index)
+{
+ return tm->face_index?tm->face_index[index]:NULL;
+}
+
+/* this replaces the active flag used in uv/face mode */
+void EDBM_set_actFace(BMEditMesh *em, BMFace *efa)
+{
+ em->bm->act_face = efa;
+}
+
+BMFace *EDBM_get_actFace(BMEditMesh *em, int sloppy)
+{
+ if (em->bm->act_face) {
+ return em->bm->act_face;
+ } else if (sloppy) {
+ BMFace *efa= NULL;
+ BMEditSelection *ese;
+
+ ese = em->selected.last;
+ for (; ese; ese=ese->prev){
+ if(ese->type == BM_FACE) {
+ efa = (BMFace *)ese->data;
+
+ if (BM_TestHFlag(efa, BM_HIDDEN)) efa= NULL;
+ else break;
+ }
+ }
+ if (efa==NULL) {
+ BMIter iter;
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(efa, BM_SELECT))
+ break;
+ }
+ }
+ return efa; /* can still be null */
+ }
+ return NULL;
+
+}
+
+void EDBM_selectmode_flush(BMEditMesh *em)
+{
+ em->bm->selectmode = em->selectmode;
+ BM_SelectMode_Flush(em->bm);
+}
+
+
+int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
+{
+ BMEditSelection *ese_last = em->selected.last;
+ BMFace *efa = EDBM_get_actFace(em, 0);
+
+ ese->next = ese->prev = NULL;
+
+ if (ese_last) {
+ if (ese_last->type == BM_FACE) { /* if there is an active face, use it over the last selected face */
+ if (efa) {
+ ese->data = (void *)efa;
+ } else {
+ ese->data = ese_last->data;
+ }
+ ese->type = BM_FACE;
+ } else {
+ ese->data = ese_last->data;
+ ese->type = ese_last->type;
+ }
+ } else if (efa) { /* no */
+ ese->data = (void *)efa;
+ ese->type = BM_FACE;
+ } else {
+ ese->data = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void EDBM_clear_flag_all(BMEditMesh *em, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ for (i=0; i<3; i++) {
+ switch (i) {
+ case 0:
+ type = BM_VERTS_OF_MESH;
+ break;
+ case 1:
+ type = BM_EDGES_OF_MESH;
+ break;
+ case 2:
+ type = BM_FACES_OF_MESH;
+ break;
+ }
+ ele = BMIter_New(&iter, em->bm, type, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (flag & BM_SELECT) BM_Select(em->bm, ele, 0);
+ BM_ClearHFlag(ele, flag);
+ }
+ }
+}
+
+
+void EDBM_set_flag_all(BMEditMesh *em, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ for (i=0; i<3; i++) {
+ switch (i) {
+ case 0:
+ type = BM_VERTS_OF_MESH;
+ break;
+ case 1:
+ type = BM_EDGES_OF_MESH;
+ break;
+ case 2:
+ type = BM_FACES_OF_MESH;
+ break;
+ }
+ ele = BMIter_New(&iter, em->bm, type, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (flag & BM_SELECT) BM_Select(em->bm, ele, 1);
+ BM_SetHFlag(ele, flag);
+ }
+ }
+}
+
+/**************-------------- Undo ------------*****************/
+
+/* for callbacks */
+
+static void *getEditMesh(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ return me->edit_btmesh;
+ }
+ return NULL;
+}
+
+/*undo simply makes copies of a bmesh*/
+static void *editbtMesh_to_undoMesh(void *emv)
+{
+ /*we recalc the tesselation here, to avoid seeding calls to
+ BMEdit_RecalcTesselation throughout the code.*/
+ BMEdit_RecalcTesselation(emv);
+
+ return BMEdit_Copy(emv);
+}
+
+static void undoMesh_to_editbtMesh(void *umv, void *emv)
+{
+ BMEditMesh *bm1 = umv, *bm2 = emv;
+
+ BMEdit_Free(bm2);
+
+ *bm2 = *BMEdit_Copy(bm1);
+}
+
+
+static void free_undo(void *umv)
+{
+ BMEditMesh *em = umv;
+
+ BMEdit_Free(em);
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_mesh(bContext *C, char *name)
+{
+ undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
+}
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index 6c66ae468fa..49872eae897 100644
--- a/source/blender/editors/mesh/editmesh.c
+++ b/source/blender/editors/mesh/editmesh.c
@@ -53,6 +53,7 @@
#include "BLI_editVert.h"
#include "BLI_dynstr.h"
#include "BLI_rand.h"
+#include "BLI_mempool.h"
#include "BKE_cloth.h"
#include "BKE_context.h"
@@ -71,6 +72,7 @@
#include "BKE_softbody.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "LBM_fluidsim.h"
@@ -91,6 +93,8 @@
/* own include */
#include "mesh_intern.h"
+#include "bmesh.h"
+
/*
editmesh.c:
- add/alloc/free data
@@ -112,22 +116,21 @@ static void error() {}
/* ************ ADD / REMOVE / FIND ****************** */
-static void *calloc_em(EditMesh *em, size_t size, size_t nr)
-{
- return calloc(size, nr);
+static void init_editMesh(EditMesh *em) {
+ if (!em->vertpool) em->vertpool = BLI_mempool_create(sizeof(EditVert), 1, 512);
+ if (!em->edgepool) em->edgepool = BLI_mempool_create(sizeof(EditEdge), 1, 512);
+ if (!em->facepool) em->facepool = BLI_mempool_create(sizeof(EditFace), 1, 512);
}
-/* used to bypass normal calloc with fast one */
-static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em;
-static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em;
-static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em;
-
EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example)
{
EditVert *eve;
static int hashnr= 0;
+
+ if (!em->vertpool) init_editMesh(em);
+
+ eve= BLI_mempool_calloc(em->vertpool);
- eve= callocvert(em, sizeof(EditVert), 1);
BLI_addtail(&em->verts, eve);
em->totvert++;
@@ -157,8 +160,7 @@ void free_editvert (EditMesh *em, EditVert *eve)
EM_remove_selection(em, eve, EDITVERT);
CustomData_em_free_block(&em->vdata, &eve->data);
- if(eve->fast==0)
- free(eve);
+ BLI_mempool_free(em->vertpool, eve);
em->totvert--;
}
@@ -256,11 +258,12 @@ EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *exampl
}
/* find in hashlist */
+ if (!em->edgepool) init_editMesh(em);
eed= findedgelist(em, v1, v2);
if(eed==NULL) {
- eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1);
+ eed= (EditEdge *)BLI_mempool_calloc(em->edgepool);
eed->v1= v1;
eed->v2= v2;
BLI_addtail(&em->edges, eed);
@@ -293,9 +296,8 @@ void remedge(EditMesh *em, EditEdge *eed)
void free_editedge(EditMesh *em, EditEdge *eed)
{
EM_remove_selection(em, eed, EDITEDGE);
- if(eed->fast==0){
- free(eed);
- }
+
+ BLI_mempool_free(em->edgepool, eed);
}
void free_editface(EditMesh *em, EditFace *efa)
@@ -307,8 +309,7 @@ void free_editface(EditMesh *em, EditFace *efa)
}
CustomData_em_free_block(&em->fdata, &efa->data);
- if(efa->fast==0)
- free(efa);
+ BLI_mempool_free(em->facepool, efa);
em->totface--;
}
@@ -384,7 +385,9 @@ EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, Ed
if(v1==v2 || v2==v3 || v1==v3) return NULL;
if(e2==0) return NULL;
- efa= (EditFace *)callocface(em, sizeof(EditFace), 1);
+ if (!em->facepool) init_editMesh(em);
+ efa= (EditFace *)BLI_mempool_calloc(em->facepool);
+
efa->v1= v1;
efa->v2= v2;
efa->v3= v3;
@@ -467,55 +470,10 @@ int editface_containsEdge(EditFace *efa, EditEdge *eed)
/* ************************ stuct EditMesh manipulation ***************************** */
-/* fake callocs for fastmalloc below */
-static void *calloc_fastvert(EditMesh *em, size_t size, size_t nr)
-{
- EditVert *eve= em->curvert++;
- eve->fast= 1;
- return eve;
-}
-static void *calloc_fastedge(EditMesh *em, size_t size, size_t nr)
-{
- EditEdge *eed= em->curedge++;
- eed->fast= 1;
- return eed;
-}
-static void *calloc_fastface(EditMesh *em, size_t size, size_t nr)
-{
- EditFace *efa= em->curface++;
- efa->fast= 1;
- return efa;
-}
-
-/* allocate 1 chunk for all vertices, edges, faces. These get tagged to
- prevent it from being freed
-*/
-static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
-{
- if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
- else em->allverts= NULL;
- em->curvert= em->allverts;
-
- if(totedge==0) totedge= 4*totface; // max possible
-
- if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
- else em->alledges= NULL;
- em->curedge= em->alledges;
-
- if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
- else em->allfaces= NULL;
- em->curface= em->allfaces;
-
- callocvert= calloc_fastvert;
- callocedge= calloc_fastedge;
- callocface= calloc_fastface;
-}
-
-static void end_editmesh_fastmalloc(void)
+void set_editMesh(EditMesh *dst, EditMesh *src)
{
- callocvert= calloc_em;
- callocedge= calloc_em;
- callocface= calloc_em;
+ free_editMesh(dst);
+ *dst = *src;
}
/* do not free editmesh itself here */
@@ -527,7 +485,12 @@ void free_editMesh(EditMesh *em)
if(em->edges.first) free_edgelist(em, &em->edges);
if(em->faces.first) free_facelist(em, &em->faces);
if(em->selected.first) BLI_freelistN(&(em->selected));
-
+
+ if (em->vertpool) BLI_mempool_destroy(em->vertpool);
+ if (em->edgepool) BLI_mempool_destroy(em->edgepool);
+ if (em->facepool) BLI_mempool_destroy(em->facepool);
+ em->vertpool = em->edgepool = em->facepool = NULL;
+
CustomData_free(&em->vdata, 0);
CustomData_free(&em->fdata, 0);
@@ -815,7 +778,7 @@ static int editmesh_pointcache_edit(Scene *scene, Object *ob, int totvert, PTCac
}
/* turns Mesh into editmesh */
-void make_editMesh(Scene *scene, Object *ob)
+EditMesh *make_editMesh(Scene *scene, Object *ob)
{
Mesh *me= ob->data;
MFace *mface;
@@ -833,13 +796,7 @@ void make_editMesh(Scene *scene, Object *ob)
float cacheco[3], cachemat[4][4], *co;
int tot, a, cacheedit= 0, eekadoodle= 0;
- if(me->edit_mesh==NULL)
- me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
- else
- /* because of reload */
- free_editMesh(me->edit_mesh);
-
- em= me->edit_mesh;
+ em= MEM_callocN(sizeof(EditMesh), "editmesh");
em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
em->act_face = NULL;
@@ -847,18 +804,9 @@ void make_editMesh(Scene *scene, Object *ob)
em->totedge= me->totedge;
em->totface= me->totface;
- if(tot==0) {
- return;
- }
-
- /* initialize fastmalloc for editmesh */
- init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
-
actkey = ob_get_keyblock(ob);
if(actkey) {
tot= actkey->totelem;
- /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
- undo_editmode_clear();
}
@@ -979,8 +927,6 @@ void make_editMesh(Scene *scene, Object *ob)
error("This Mesh has old style edgecodes, please put it in the bugtracker!");
MEM_freeN(evlist);
-
- end_editmesh_fastmalloc(); // resets global function pointers
if(me->mselect){
//restore editselections
@@ -1014,18 +960,18 @@ void make_editMesh(Scene *scene, Object *ob)
/* vertex coordinates change with cache edit, need to recalc */
if(cacheedit)
recalc_editnormals(em);
-
+
+ return em;
}
/* makes Mesh out of editmesh */
-void load_editMesh(Scene *scene, Object *ob)
+void load_editMesh(Scene *scene, Object *ob, EditMesh *em)
{
Mesh *me= ob->data;
MVert *mvert, *oldverts;
MEdge *medge;
MFace *mface;
MSelect *mselect;
- EditMesh *em= me->edit_mesh;
EditVert *eve;
EditFace *efa, *efa_act;
EditEdge *eed;
@@ -1489,8 +1435,8 @@ static int mesh_separate_selected(Scene *scene, Base *editbase)
/* 2 */
basenew->object->data= menew= add_mesh(me->id.name); /* empty */
me->id.us--;
- make_editMesh(scene, basenew->object);
- emnew= menew->edit_mesh;
+ emnew = make_editMesh(scene, basenew->object);
+ //emnew= menew->edit_mesh;
/* 3 */
/* SPLIT: first make duplicate */
@@ -1531,7 +1477,7 @@ static int mesh_separate_selected(Scene *scene, Base *editbase)
}
/* 5 */
- load_editMesh(scene, basenew->object);
+ load_editMesh(scene, basenew->object, emnew);
free_editMesh(emnew);
/* hashedges are invalid now, make new! */
@@ -1682,6 +1628,7 @@ typedef struct UndoMesh {
EditVertC *verts;
EditEdgeC *edges;
EditFaceC *faces;
+ EditFaceC *act_face;
EditSelectionC *selected;
int totvert, totedge, totface, totsel;
short selectmode;
@@ -1690,247 +1637,6 @@ typedef struct UndoMesh {
CustomData vdata, edata, fdata;
} UndoMesh;
-/* for callbacks */
-
-static void free_undoMesh(void *umv)
-{
- UndoMesh *um= umv;
-
- if(um->verts) MEM_freeN(um->verts);
- if(um->edges) MEM_freeN(um->edges);
- if(um->faces) MEM_freeN(um->faces);
- if(um->selected) MEM_freeN(um->selected);
-// XXX if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
- CustomData_free(&um->vdata, um->totvert);
- CustomData_free(&um->edata, um->totedge);
- CustomData_free(&um->fdata, um->totface);
- MEM_freeN(um);
-}
-
-static void *editMesh_to_undoMesh(void *emv)
-{
- EditMesh *em= (EditMesh *)emv;
- UndoMesh *um;
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- EditSelection *ese;
- EditVertC *evec=NULL;
- EditEdgeC *eedc=NULL;
- EditFaceC *efac=NULL;
- EditSelectionC *esec=NULL;
- int a;
-
- um= MEM_callocN(sizeof(UndoMesh), "undomesh");
-
- um->selectmode = em->selectmode;
-
- for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
- for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
- for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
- for(ese=em->selected.first; ese; ese=ese->next) um->totsel++;
- /* malloc blocks */
-
- if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
- if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
- if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
- if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
-
- if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
- if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
- if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
-
- /* now copy vertices */
- a = 0;
- for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
- VECCOPY(evec->co, eve->co);
- VECCOPY(evec->no, eve->no);
-
- evec->f= eve->f;
- evec->h= eve->h;
- evec->keyindex= eve->keyindex;
- eve->tmp.l = a; /*store index*/
- evec->bweight= (short)(eve->bweight*255.0);
-
- CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
- }
-
- /* copy edges */
- a = 0;
- for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) {
- eedc->v1= (int)eed->v1->tmp.l;
- eedc->v2= (int)eed->v2->tmp.l;
- eedc->f= eed->f;
- eedc->h= eed->h;
- eedc->seam= eed->seam;
- eedc->sharp= eed->sharp;
- eedc->crease= (short)(eed->crease*255.0);
- eedc->bweight= (short)(eed->bweight*255.0);
- eedc->fgoni= eed->fgoni;
- eed->tmp.l = a; /*store index*/
- CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
-
- }
-
- /* copy faces */
- a = 0;
- for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
- efac->v1= (int)efa->v1->tmp.l;
- efac->v2= (int)efa->v2->tmp.l;
- efac->v3= (int)efa->v3->tmp.l;
- if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
- else efac->v4= -1;
-
- efac->mat_nr= efa->mat_nr;
- efac->flag= efa->flag;
- efac->f= efa->f;
- efac->h= efa->h;
- efac->fgonf= efa->fgonf;
-
- efa->tmp.l = a; /*store index*/
-
- CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
- }
-
- a = 0;
- for(ese=em->selected.first; ese; ese=ese->next, esec++){
- esec->type = ese->type;
- if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l;
- else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l;
- else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
- }
-
-// XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
-// um->retopo_mode= scene->toolsettings->retopo_mode;
-
- return um;
-}
-
-static void undoMesh_to_editMesh(void *umv, void *emv)
-{
- EditMesh *em= (EditMesh *)emv;
- UndoMesh *um= (UndoMesh *)umv;
- EditVert *eve, **evar=NULL;
- EditEdge *eed;
- EditFace *efa;
- EditSelection *ese;
- EditVertC *evec;
- EditEdgeC *eedc;
- EditFaceC *efac;
- EditSelectionC *esec;
- int a=0;
-
- free_editMesh(em);
-
- /* malloc blocks */
- memset(em, 0, sizeof(EditMesh));
-
- em->selectmode = um->selectmode;
-
- init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
-
- CustomData_free(&em->vdata, 0);
- CustomData_free(&em->edata, 0);
- CustomData_free(&em->fdata, 0);
-
- CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
-
- /* now copy vertices */
-
- if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
- for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
- eve= addvertlist(em, evec->co, NULL);
- evar[a]= eve;
-
- VECCOPY(eve->no, evec->no);
- eve->f= evec->f;
- eve->h= evec->h;
- eve->keyindex= evec->keyindex;
- eve->bweight= ((float)evec->bweight)/255.0f;
-
- CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
- }
-
- /* copy edges */
- for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
- eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);
-
- eed->f= eedc->f;
- eed->h= eedc->h;
- eed->seam= eedc->seam;
- eed->sharp= eedc->sharp;
- eed->fgoni= eedc->fgoni;
- eed->crease= ((float)eedc->crease)/255.0f;
- eed->bweight= ((float)eedc->bweight)/255.0f;
- CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
- }
-
- /* copy faces */
- for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
- if(efac->v4 != -1)
- efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
- else
- efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
-
- efa->mat_nr= efac->mat_nr;
- efa->flag= efac->flag;
- efa->f= efac->f;
- efa->h= efac->h;
- efa->fgonf= efac->fgonf;
-
- CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
- }
-
- end_editmesh_fastmalloc();
- if(evar) MEM_freeN(evar);
-
- em->totvert = um->totvert;
- em->totedge = um->totedge;
- em->totface = um->totface;
- /*restore stored editselections*/
- if(um->totsel){
- EM_init_index_arrays(em, 1,1,1);
- for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
- ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
- ese->type = esec->type;
- if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
- if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
- if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
- BLI_addtail(&(em->selected),ese);
- }
- EM_free_index_arrays();
- }
-
-// XXX retopo_free_paint();
-// em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
-// scene->toolsettings->retopo_mode= um->retopo_mode;
-// if(scene->toolsettings->retopo_mode) {
-// XXX if(G.vd->depths) G.vd->depths->damaged= 1;
-// retopo_queue_updates(G.vd);
-// retopo_paint_view_update(G.vd);
-// }
-
-}
-
-static void *getEditMesh(bContext *C)
-{
- Object *obedit= CTX_data_edit_object(C);
- if(obedit && obedit->type==OB_MESH) {
- Mesh *me= obedit->data;
- return me->edit_mesh;
- }
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_mesh(bContext *C, char *name)
-{
- undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
-}
-
-
/* *************** END UNDO *************/
@@ -2033,6 +1739,6 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc)
if(vc->obedit) {
Mesh *me= vc->obedit->data;
- vc->em= me->edit_mesh;
+ vc->em= me->edit_btmesh;
}
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index c24670aa856..4b891843f5e 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -60,6 +60,7 @@
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,6 +72,8 @@
#include "ED_util.h"
#include "ED_view3d.h"
+#include "bmesh.h"
+
#include "mesh_intern.h"
/* bpymenu removed XXX */
@@ -116,127 +119,6 @@ static short icoface[20][3] = {
{10,9,11}
};
-/* *************** add-click-mesh (extrude) operator ************** */
-
-static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
-{
- ViewContext vc;
- EditVert *eve, *v1;
- float min[3], max[3];
- int done= 0;
-
- em_setup_viewcontext(C, &vc);
-
- INIT_MINMAX(min, max);
-
- for(v1= vc.em->verts.first;v1; v1=v1->next) {
- if(v1->f & SELECT) {
- DO_MINMAX(v1->co, min, max);
- done= 1;
- }
- }
-
- /* call extrude? */
- if(done) {
- EditEdge *eed;
- float vec[3], cent[3], mat[3][3];
- float nor[3]= {0.0, 0.0, 0.0};
-
- /* check for edges that are half selected, use for rotation */
- done= 0;
- for(eed= vc.em->edges.first; eed; eed= eed->next) {
- if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) {
- if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co);
- else VecSubf(vec, eed->v2->co, eed->v1->co);
- VecAddf(nor, nor, vec);
- done= 1;
- }
- }
- if(done) Normalize(nor);
-
- /* center */
- VecAddf(cent, min, max);
- VecMulf(cent, 0.5f);
- VECCOPY(min, cent);
-
- Mat4MulVecfl(vc.obedit->obmat, min); // view space
- view3d_get_view_aligned_coordinate(&vc, min, event->mval);
- Mat4Invert(vc.obedit->imat, vc.obedit->obmat);
- Mat4MulVecfl(vc.obedit->imat, min); // back in object space
-
- VecSubf(min, min, cent);
-
- /* calculate rotation */
- Mat3One(mat);
- if(done) {
- float dot;
-
- VECCOPY(vec, min);
- Normalize(vec);
- dot= INPR(vec, nor);
-
- if( fabs(dot)<0.999) {
- float cross[3], si, q1[4];
-
- Crossf(cross, nor, vec);
- Normalize(cross);
- dot= 0.5f*saacos(dot);
- si= (float)sin(dot);
- q1[0]= (float)cos(dot);
- q1[1]= cross[0]*si;
- q1[2]= cross[1]*si;
- q1[3]= cross[2]*si;
-
- QuatToMat3(q1, mat);
- }
- }
-
- extrudeflag(vc.obedit, vc.em, SELECT, nor);
- rotateflag(vc.em, SELECT, cent, mat);
- translateflag(vc.em, SELECT, min);
-
- recalc_editnormals(vc.em);
- }
- else {
- float mat[3][3],imat[3][3];
- float *curs= give_cursor(vc.scene, vc.v3d);
-
- VECCOPY(min, curs);
- view3d_get_view_aligned_coordinate(&vc, min, event->mval);
-
- eve= addvertlist(vc.em, 0, NULL);
-
- Mat3CpyMat4(mat, vc.obedit->obmat);
- Mat3Inv(imat, mat);
-
- VECCOPY(eve->co, min);
- Mat3MulVecfl(imat, eve->co);
- VecSubf(eve->co, eve->co, vc.obedit->obmat[3]);
-
- eve->f= SELECT;
- }
-
- //retopo_do_all();
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
- DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Duplicate or Extrude at 3D Cursor";
- ot->idname= "MESH_OT_dupli_extrude_cursor";
-
- /* api callbacks */
- ot->invoke= dupli_extrude_cursor;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
/* ********************** */
@@ -666,12 +548,53 @@ void addfaces_from_edgenet(EditMesh *em)
// XXX DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
}
-static void addedgeface_mesh(EditMesh *em, wmOperator *op)
+static void addedgeface_mesh(Mesh *me, BMEditMesh *bem, wmOperator *op)
{
+ EditMesh *em;
EditVert *eve, *neweve[4];
EditEdge *eed;
EditFace *efa;
short amount=0;
+
+ /*return if bmesh vert connect does anything.*/
+ if (bem->selectmode & SCE_SELECT_VERTEX) {
+ BMesh *bm = bem->bm;
+ BMOperator bmop;
+ int len, ok;
+
+ EDBM_InitOpf(bem, &bmop, op, "connectverts verts=%hv", BM_SELECT);
+ BMO_Exec_Op(bem->bm, &bmop);
+
+ len = BMO_GetSlot(&bmop, "edgeout")->len;
+
+ ok = EDBM_FinishOp(bem, &bmop, op, 1);
+ if (!ok) return OPERATOR_CANCELLED;
+
+ if (len) return;
+ }
+
+ /*return if bmesh face dissolve finds stuff to
+ dissolve. this entire tool should be
+ bmeshafied eventually, but until then
+ hacks like this to integrate with it
+ are necassary.*/
+ if (bem->selectmode & SCE_SELECT_VERTEX) {
+ BMesh *bm = bem->bm;
+ BMOperator bmop;
+ int len, ok;
+
+ EDBM_InitOpf(bem, &bmop, op, "dissolvefaces faces=%hf", BM_SELECT);
+ BMO_Exec_Op(bem->bm, &bmop);
+
+ len = BMO_GetSlot(&bmop, "regionout")->len;
+
+ ok = EDBM_FinishOp(bem, &bmop, op, 1);
+ if (!ok) return OPERATOR_CANCELLED;
+
+ if (len) return;
+ }
+
+ em = BKE_mesh_get_editmesh(me);
/* how many selected ? */
if(em->selectmode & SCE_SELECT_EDGE) {
@@ -691,16 +614,19 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
if(amount==2) {
eed= addedgelist(em, neweve[0], neweve[1], NULL);
EM_select_edge(eed, 1);
-
+
+ BKE_mesh_end_editmesh(me, em);
// XXX DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
return;
}
else if(amount > 4) {
addfaces_from_edgenet(em);
+ BKE_mesh_end_editmesh(me, em);
return;
}
else if(amount<2) {
BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face");
+ BKE_mesh_end_editmesh(me, em);
return;
}
@@ -739,6 +665,7 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
if(count++ > 4){
addfaces_from_edgenet(em);
+ BKE_mesh_end_editmesh(me, em);
return;
} else {
/* if 4 edges exist, we just create the face, convex or not */
@@ -780,40 +707,10 @@ static void addedgeface_mesh(EditMesh *em, wmOperator *op)
recalc_editnormals(em);
}
- }
-static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- addedgeface_mesh(em, op);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_edge_face_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Make Edge/Face";
- ot->idname= "MESH_OT_edge_face_add";
-
- /* api callbacks */
- ot->exec= addedgeface_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
+ BKE_mesh_end_editmesh(me, em);
}
-
-
/* ************************ primitives ******************* */
// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
@@ -1104,7 +1001,9 @@ static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int se
}
dia*=200;
- for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1,0);
+
+ for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0.0, 0, 1, 0);
+
/* and now do imat */
eve= em->verts.first;
while(eve) {
diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c
index e1b63022dd4..d9e0cc0f339 100644
--- a/source/blender/editors/mesh/editmesh_lib.c
+++ b/source/blender/editors/mesh/editmesh_lib.c
@@ -61,6 +61,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
#include "ED_view3d.h"
#include "mesh_intern.h"
+#include "bmesh.h"
/* ****************** stats *************** */
@@ -1139,10 +1140,128 @@ short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor)
return 'g'; // g is grab
}
+short BM_extrude_edgeflag(Object *obedit, BMesh *bm, int eflag, float *nor)
+{
+ BMIter iter;
+ BMOIter siter;
+ BMOperator extop;
+ BMEdge *edge;
+ BMFace *f;
+ void *el;
+ ModifierData *md;
+ int flag;
+
+ switch (eflag) {
+ case SELECT:
+ flag = BM_SELECT;
+ break;
+ default:
+ flag = BM_SELECT;
+ break;
+ }
+
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);f;f=BMIter_Step(&iter)) {
+ add_normal_aligned(nor, f->no);
+ }
+ Normalize(nor);
+
+ BMO_Init_Op(&extop, "extrudefaceregion");
+ BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein",
+ flag, BM_VERT|BM_EDGE|BM_FACE);
+
+ for (edge=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); edge; edge=BMIter_Step(&iter)) {
+ BM_Select_Edge(bm, edge, 0);
+ }
+
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) {
+ BM_Select_Face(bm, f, 0);
+ }
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ md = obedit->modifiers.first;
+ for (; md; md=md->next) {
+ if (md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ Mat4Invert(imtx, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, obedit->obmat, imtx);
+ }
+
+ for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL);
+ edge; edge=BMIter_Step(&iter))
+ {
+ if(edge->head.flag & flag) {
+ float co1[3], co2[3];
+
+ VecCopyf(co1, edge->v1->co);
+ VecCopyf(co2, edge->v2->co);
+
+ if (mmd->mirror_ob) {
+ VecMat4MulVecfl(co1, mtx, co1);
+ VecMat4MulVecfl(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ if ( (fabs(co1[0]) < mmd->tolerance) &&
+ (fabs(co2[0]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ if ( (fabs(co1[1]) < mmd->tolerance) &&
+ (fabs(co2[1]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ if ( (fabs(co1[2]) < mmd->tolerance) &&
+ (fabs(co2[2]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+ }
+ }
+ }
+ }
+ }
+
+
+ BMO_Exec_Op(bm, &extop);
+
+ el = BMO_IterNew(&siter, bm, &extop, "geomout", BM_ALL);
+ for (; el; el=BMO_IterStep(&siter)) {
+ BM_Select(bm, el, 1);
+ }
+
+ BMO_Finish_Op(bm, &extop);
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
+ return 'n'; // normal constraint
+
+}
+
+
+static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) {
+ short ret;
+ EditMesh *em2;
+ BMesh *bm = editmesh_to_bmesh(em);
+
+ ret = BM_extrude_edgeflag(obedit, bm, flag, nor);
+ em2 = bmesh_to_editmesh(bm);
+
+ set_editMesh(em, em2);
+ MEM_freeN(em2);
+
+ EM_select_flush(em);
+
+ return ret;
+}
/* this is actually a recode of extrudeflag(), using proper edge/face select */
/* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */
-static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor)
+static short extrudeflag_edge_old(Object *obedit, EditMesh *em, short flag, float *nor)
{
/* all select edges/faces: extrude */
/* old select is cleared, in new ones it is set */
@@ -1686,9 +1805,22 @@ short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor)
/* generic extrude */
short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor)
{
- if(em->selectmode & SCE_SELECT_VERTEX)
- return extrudeflag_vert(obedit, em, flag, nor);
- else
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ EditEdge *eed;
+
+ /*ensure vert flags are consistent for edge selections*/
+ for (eed=em->edges.first; eed; eed=eed->next) {
+ if (eed->f & flag) {
+ eed->v1->f |= flag;
+ eed->v2->f |= flag;
+ } else {
+ if ((eed->v1->f & flag) && (eed->v2->f & flag))
+ eed->f |= flag;
+ }
+ }
+
+ return extrudeflag_edge(obedit, em, flag, nor);
+ } else
return extrudeflag_edge(obedit, em, flag, nor);
}
@@ -1912,6 +2044,9 @@ void recalc_editnormals(EditMesh *em)
}
for(efa= em->faces.first; efa; efa=efa->next) {
+ if (efa->e1->fgoni||efa->e2->fgoni||efa->e3->fgoni) continue;
+ if (efa->e4 && efa->e4->fgoni) continue;
+
if(efa->v4) {
CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c
index 7fc3753eefb..9b5de48a644 100644
--- a/source/blender/editors/mesh/editmesh_loop.c
+++ b/source/blender/editors/mesh/editmesh_loop.c
@@ -61,6 +61,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "PIL_time.h"
@@ -77,6 +78,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
#include "ED_view3d.h"
#include "mesh_intern.h"
+#include "bmesh.h"
/* **** XXX ******** */
static void BIF_undo_push() {}
@@ -201,6 +203,7 @@ static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int prev
}
void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
{
+#if 0
ViewContext vc; // XXX
EditEdge *nearest=NULL, *eed;
float fac;
@@ -391,6 +394,7 @@ void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
return;
+#endif
}
@@ -474,7 +478,7 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct
float m1, b1, m2, b2, x21, x22, y21, y22, xi;
float yi, x1min, x1max, y1max, y1min, perc=0;
float *scr;
- float threshold;
+ float threshold = 0.0;
int i;
threshold = 0.000001; /*tolerance for vertex intersection*/
@@ -620,26 +624,184 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct
}
+static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode,
+ struct GHash *gh, int *isected)
+{
+#define MAXSLOPE 100000
+ float x11, y11, x12=0, y12=0, x2max, x2min, y2max;
+ float y2min, dist, lastdist=0, xdiff2, xdiff1;
+ float m1, b1, m2, b2, x21, x22, y21, y22, xi;
+ float yi, x1min, x1max, y1max, y1min, perc=0;
+ float *scr;
+ float threshold = 0.0;
+ int i;
+
+ //threshold = 0.000001; /*tolerance for vertex intersection*/
+ // XXX threshold = scene->toolsettings->select_thresh / 100;
+
+ /* Get screen coords of verts */
+ scr = BLI_ghash_lookup(gh, e->v1);
+ x21=scr[0];
+ y21=scr[1];
+
+ scr = BLI_ghash_lookup(gh, e->v2);
+ x22=scr[0];
+ y22=scr[1];
+
+ xdiff2=(x22-x21);
+ if (xdiff2) {
+ m2=(y22-y21)/xdiff2;
+ b2= ((x22*y21)-(x21*y22))/xdiff2;
+ }
+ else {
+ m2=MAXSLOPE; /* Verticle slope */
+ b2=x22;
+ }
+
+ *isected = 0;
+
+ /*check for *exact* vertex intersection first*/
+ if(mode!=KNIFE_MULTICUT){
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /*test e->v1*/
+ if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
+ perc = 0;
+ *isected = 1;
+ return(perc);
+ }
+ /*test e->v2*/
+ else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
+ perc = 0;
+ *isected = 2;
+ return(perc);
+ }
+ }
+ }
+
+ /*now check for edge interesect (may produce vertex intersection as well)*/
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /* Perp. Distance from point to line */
+ if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
+ /* change in sign. Skip extra math */
+ else dist=x22-x12;
+
+ if (i==0) lastdist=dist;
+
+ /* if dist changes sign, and intersect point in edge's Bound Box*/
+ if ((lastdist*dist)<=0){
+ xdiff1=(x12-x11); /* Equation of line between last 2 points */
+ if (xdiff1){
+ m1=(y12-y11)/xdiff1;
+ b1= ((x12*y11)-(x11*y12))/xdiff1;
+ }
+ else{
+ m1=MAXSLOPE;
+ b1=x12;
+ }
+ x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */
+ x2min=MIN2(x21,x22)-0.001; /* due to round off error */
+ y2max=MAX2(y21,y22)+0.001;
+ y2min=MIN2(y21,y22)-0.001;
+
+ /* Found an intersect, calc intersect point */
+ if (m1==m2){ /* co-incident lines */
+ /* cut at 50% of overlap area*/
+ x1max=MAX2(x11, x12);
+ x1min=MIN2(x11, x12);
+ xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;
+
+ y1max=MAX2(y11, y12);
+ y1min=MIN2(y11, y12);
+ yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
+ }
+ else if (m2==MAXSLOPE){
+ xi=x22;
+ yi=m1*x22+b1;
+ }
+ else if (m1==MAXSLOPE){
+ xi=x12;
+ yi=m2*x12+b2;
+ }
+ else {
+ xi=(b1-b2)/(m2-m1);
+ yi=(b1*m2-m1*b2)/(m2-m1);
+ }
+
+ /* Intersect inside bounding box of edge?*/
+ if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
+ /*test for vertex intersect that may be 'close enough'*/
+ if(mode!=KNIFE_MULTICUT){
+ if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
+ if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
+ *isected = 1;
+ perc = 0;
+ break;
+ }
+ }
+ if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
+ if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
+ *isected = 2;
+ perc = 0;
+ break;
+ }
+ }
+ }
+ if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);
+ else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
+ //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
+
+ break;
+ }
+ }
+ lastdist=dist;
+ }
+ return(perc);
+}
+
#define MAX_CUTS 256
static int knife_cut_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMesh *bm = em->bm;
ARegion *ar= CTX_wm_region(C);
- EditEdge *eed;
- EditVert *eve;
+ BMVert *bv;
+ BMIter iter;
+ BMEdge **edges = NULL, *be;
+ BMOperator bmop;
CutCurve curve[MAX_CUTS];
struct GHash *gh;
float isect=0.0;
- float *scr, co[4];
- int len=0;
+ float *scr, co[4], *percents = NULL;
+ int len=0, isected, flag, i;
short numcuts=1, mode= RNA_int_get(op->ptr, "type");
- if (EM_nvertices_selected(em) < 2) {
+ if (bm->totvertsel < 2) {
error("No edges are selected to operate on");
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;;
}
@@ -653,57 +815,60 @@ static int knife_cut_exec(bContext *C, wmOperator *op)
RNA_END;
if(len<2) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
- /*store percentage of edge cut for KNIFE_EXACT here.*/
- for(eed=em->edges.first; eed; eed= eed->next)
- eed->tmp.fp = 0.0;
-
/*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
- for(eve=em->verts.first; eve; eve=eve->next){
+ for(bv=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);bv;bv=BMIter_Step(&iter)){
scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
- VECCOPY(co, eve->co);
+ VECCOPY(co, bv->co);
co[3]= 1.0;
Mat4MulVec4fl(obedit->obmat, co);
project_float(ar, co, scr);
- BLI_ghash_insert(gh, eve, scr);
- eve->f1 = 0; /*store vertex intersection flag here*/
-
+ BLI_ghash_insert(gh, bv, scr);
}
- eed= em->edges.first;
- while(eed) {
- if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet
- isect= seg_intersect(eed, curve, len, mode, gh);
- if (isect!=0.0f) eed->f2= 1;
- else eed->f2=0;
- eed->tmp.fp= isect;
- //printf("isect=%i\n", isect);
- }
- else {
- eed->f2=0;
- eed->f1=0;
+ BMO_Init_Op(&bmop, "esubd");
+
+ i = 0;
+ /*store percentage of edge cut for KNIFE_EXACT here.*/
+ for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) {
+ if( BM_Is_Selected(bm, be) ) {
+ isect= bm_seg_intersect(be, curve, len, mode, gh, &isected);
+
+ if (isect != 0.0f) {
+ if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
+ BMO_Insert_MapFloat(bm, &bmop,
+ "edgepercents",
+ be, isect);
+
+ }
+ BMO_SetFlag(bm, be, 1);
+ }
}
- eed= eed->next;
}
- if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
- else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
- else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
+ BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE);
- eed=em->edges.first;
- while(eed){
- eed->f2=0;
- eed->f1=0;
- eed=eed->next;
- }
+ BMO_Set_Int(&bmop, "numcuts", numcuts);
+ flag = B_KNIFE;
+ if (mode == KNIFE_MIDPOINT) numcuts = 1;
+ BMO_Set_Int(&bmop, "flag", flag);
+ BMO_Set_Float(&bmop, "radius", 0);
- BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Finish_Op(bm, &bmop);
- BKE_mesh_end_editmesh(obedit->data, em);
+ V_FREE(edges);
+ V_FREE(percents);
+
+ //if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
+ //else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
+ //else esubdivideflag(obedit, em, SELECT, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
+
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN);
+
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
index 5fc2ce46792..aa7a5e6b292 100644
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -83,6 +83,7 @@ editmesh_mods.c, UI level access, no geometry changes
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "bmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -99,6 +100,7 @@ static int pupmenu() {return 0;}
void EM_select_mirrored(Object *obedit, EditMesh *em)
{
+#if 0
if(em->selectmode & SCE_SELECT_VERTEX) {
EditVert *eve, *v1;
@@ -112,6 +114,7 @@ void EM_select_mirrored(Object *obedit, EditMesh *em)
}
}
}
+#endif
}
void EM_automerge(int update)
@@ -326,320 +329,6 @@ int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
}
-static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
-{
- struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
-
- if (data->pass==0) {
- if (index<=data->lastIndex)
- return;
- } else {
- if (index>data->lastIndex)
- return;
- }
-
- if (data->dist>3) {
- int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
- if ((eve->f&1) == data->select) {
- if (data->strict == 1)
- return;
- else
- temp += 5;
- }
-
- if (temp<data->dist) {
- data->dist = temp;
- data->closest = eve;
- data->closestIndex = index;
- }
- }
-}
-
-
-
-
-static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
-{
- EditMesh *em= (EditMesh *)handle;
- EditVert *eve = BLI_findlink(&em->verts, index-1);
-
- if(eve && (eve->f & SELECT)) return 0;
- return 1;
-}
-/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual distance
- * sel: selection bias
- * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
- * if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
- */
-EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
-{
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
- int distance;
- unsigned int index;
- EditVert *eve;
-
- if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest);
- else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL);
-
- eve = BLI_findlink(&vc->em->verts, index-1);
-
- if(eve && distance < *dist) {
- *dist = distance;
- return eve;
- } else {
- return NULL;
- }
-
- }
- else {
- struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
- static int lastSelectedIndex=0;
- static EditVert *lastSelected=NULL;
-
- if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
- }
-
- data.lastIndex = lastSelectedIndex;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.select = sel;
- data.dist = *dist;
- data.strict = strict;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
-
- if (data.dist>3) {
- data.pass = 1;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
- }
-
- *dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
-
- return data.closest;
- }
-}
-
-/* returns labda for closest distance v1 to line-piece v2-v3 */
-static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
-{
- float rc[2], len;
-
- rc[0]= v3[0]-v2[0];
- rc[1]= v3[1]-v2[1];
- len= rc[0]*rc[0]+ rc[1]*rc[1];
- if(len==0.0f)
- return 0.0f;
-
- return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
-}
-
-/* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
-{
- struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
- float v1[2], v2[2];
- int distance;
-
- v1[0] = x0;
- v1[1] = y0;
- v2[0] = x1;
- v2[1] = y1;
-
- distance= PdistVL2Dfl(data->mval, v1, v2);
-
- if(eed->f & SELECT) distance+=5;
- if(distance < data->dist) {
- if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
- float vec[3];
-
- vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
- vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
- vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
- Mat4MulVecfl(data->vc.obedit->obmat, vec);
-
- if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
- data->dist = distance;
- data->closest = eed;
- }
- }
- else {
- data->dist = distance;
- data->closest = eed;
- }
- }
-}
-EditEdge *findnearestedge(ViewContext *vc, int *dist)
-{
-
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- int distance;
- unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL);
- EditEdge *eed = BLI_findlink(&vc->em->edges, index-1);
-
- if (eed && distance<*dist) {
- *dist = distance;
- return eed;
- } else {
- return NULL;
- }
- }
- else {
- struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data;
-
- data.vc= *vc;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = *dist;
- data.closest = NULL;
-
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
-
- *dist = data.dist;
- return data.closest;
- }
-}
-
-static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
-{
- struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
-
- if (efa==data->toFace) {
- int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
-
- if (temp<data->dist)
- data->dist = temp;
- }
-}
-static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
-{
- struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
-
- if (data->pass==0) {
- if (index<=data->lastIndex)
- return;
- } else {
- if (index>data->lastIndex)
- return;
- }
-
- if (data->dist>3) {
- int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
-
- if (temp<data->dist) {
- data->dist = temp;
- data->closest = efa;
- data->closestIndex = index;
- }
- }
-}
-static EditFace *findnearestface(ViewContext *vc, int *dist)
-{
-
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
- EditFace *efa = BLI_findlink(&vc->em->faces, index-1);
-
- if (efa) {
- struct { short mval[2]; int dist; EditFace *toFace; } data;
-
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = 0x7FFF; /* largest short */
- data.toFace = efa;
-
- mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
-
- if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
- *dist= data.dist;
- return efa;
- }
- }
-
- return NULL;
- }
- else {
- struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
- static int lastSelectedIndex=0;
- static EditFace *lastSelected=NULL;
-
- if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
- }
-
- data.lastIndex = lastSelectedIndex;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = *dist;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
-
- if (data.dist>3) {
- data.pass = 1;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
- }
-
- *dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
-
- return data.closest;
- }
-}
-
-/* best distance based on screen coords.
- use em->selectmode to define how to use
- selected vertices and edges get disadvantage
- return 1 if found one
-*/
-static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa)
-{
- EditMesh *em= vc->em;
- int dist= 75;
-
- *eve= NULL;
- *eed= NULL;
- *efa= NULL;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(vc);
-
- if(em->selectmode & SCE_SELECT_VERTEX)
- *eve= findnearestvert(vc, &dist, SELECT, 0);
- if(em->selectmode & SCE_SELECT_FACE)
- *efa= findnearestface(vc, &dist);
-
- dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
- if(em->selectmode & SCE_SELECT_EDGE)
- *eed= findnearestedge(vc, &dist);
-
- /* return only one of 3 pointers, for frontbuffer redraws */
- if(*eed) {
- *efa= NULL; *eve= NULL;
- }
- else if(*efa) {
- *eve= NULL;
- }
-
- return (*eve || *eed || *efa);
-}
-
-
/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
/* selects new faces/edges/verts based on the existing selection */
@@ -1715,9 +1404,9 @@ void mesh_copy_menu(EditMesh *em, wmOperator *op)
}
}
-
/* **************** LOOP SELECTS *************** */
+#if 0
/* selects quads in loop direction of indicated edge */
/* only flush over edges with valence <= 2 */
void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
@@ -1787,6 +1476,7 @@ void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
}
}
}
+#endif
/* helper for edgeloop_select, checks for eed->f2 tag in faces */
@@ -1819,6 +1509,34 @@ static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed)
*/
static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select)
{
+ BMesh *bm;
+ BMEdge *e;
+ EditMesh *em2;
+ BMOperator op;
+ BMWalker walker;
+
+ bm = init_editmesh_to_bmesh(em, &op);
+ BMO_Exec_Op(bm, &op);
+
+ e = BMO_Get_MapPointer(bm, &op, "map", starteed);
+
+ BMW_Init(&walker, bm, BMW_LOOP, 0);
+ e = BMW_Begin(&walker, e);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(bm, e, 1);
+ }
+ BMW_End(&walker);
+
+ BMO_Finish_Op(bm, &op);
+
+ em2 = bmesh_to_editmesh(bm);
+ BM_Free_Mesh(bm);
+ set_editMesh(em, em2);
+ MEM_freeN(em2);
+}
+
+static void edgeloop_select_old(EditMesh *em, EditEdge *starteed, int select)
+{
EditVert *eve;
EditEdge *eed;
EditFace *efa;
@@ -1995,6 +1713,7 @@ static int loop_multiselect(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+#if 0 //moved to bmeshutils_mods.c
void MESH_OT_loop_multi_select(wmOperatorType *ot)
{
/* identifiers */
@@ -2011,255 +1730,15 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
}
-
+#endif
/* ***************** MAIN MOUSE SELECTION ************** */
-/* ***************** loop select (non modal) ************** */
-
-static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring)
-{
- ViewContext vc;
- EditMesh *em;
- EditEdge *eed;
- int select= 1;
- int dist= 50;
-
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
- em= vc.em;
-
- eed= findnearestedge(&vc, &dist);
- if(eed) {
- if(extend==0) EM_clear_flag_all(em, SELECT);
-
- if((eed->f & SELECT)==0) select=1;
- else if(extend) select=0;
-
- if(em->selectmode & SCE_SELECT_FACE) {
- faceloop_select(em, eed, select);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- if(ring)
- edgering_select(em, eed, select);
- else
- edgeloop_select(em, eed, select);
- }
- else if(em->selectmode & SCE_SELECT_VERTEX) {
- if(ring)
- edgering_select(em, eed, select);
- else
- edgeloop_select(em, eed, select);
- }
-
- EM_selectmode_flush(em);
-// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
- }
-}
-
-static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
- view3d_operator_needs_opengl(C);
-
- mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "ring"));
-
- /* cannot do tweaks for as long this keymap is after transform map */
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_loop_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Loop Select";
- ot->idname= "MESH_OT_loop_select";
-
- /* api callbacks */
- ot->invoke= mesh_select_loop_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
- RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
-}
-
/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
-/* since you want to create paths with multiple selects, it doesn't have extend option */
-static void mouse_mesh_shortest_path(bContext *C, short mval[2])
-{
- ViewContext vc;
- EditMesh *em;
- EditEdge *eed;
- int dist= 50;
-
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
- em= vc.em;
-
- eed= findnearestedge(&vc, &dist);
- if(eed) {
- Mesh *me= vc.obedit->data;
- int path = 0;
-
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
-
- if(ese && ese->type == EDITEDGE) {
- EditEdge *eed_act;
- eed_act = (EditEdge*)ese->data;
- if (eed_act != eed) {
- if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) {
- EM_remove_selection(em, eed_act, EDITEDGE);
- path = 1;
- }
- }
- }
- }
- if (path==0) {
- int act = (edgetag_context_check(vc.scene, eed)==0);
- edgetag_context_set(vc.scene, eed, act); /* switch the edge option */
- }
-
- EM_selectmode_flush(em);
-
- /* even if this is selected it may not be in the selection list */
- if(edgetag_context_check(vc.scene, eed)==0)
- EM_remove_selection(em, eed, EDITEDGE);
- else
- EM_store_selection(em, eed, EDITEDGE);
-
- /* force drawmode for mesh */
- switch (vc.scene->toolsettings->edge_mode) {
-
- case EDGE_MODE_TAG_SEAM:
- me->drawflag |= ME_DRAWSEAMS;
- break;
- case EDGE_MODE_TAG_SHARP:
- me->drawflag |= ME_DRAWSHARP;
- break;
- case EDGE_MODE_TAG_CREASE:
- me->drawflag |= ME_DRAWCREASES;
- break;
- case EDGE_MODE_TAG_BEVEL:
- me->drawflag |= ME_DRAWBWEIGHTS;
- break;
- }
-
- DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
- }
-}
-
-
-static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
- view3d_operator_needs_opengl(C);
-
- mouse_mesh_shortest_path(C, event->mval);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_shortest_path(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shortest Path Select";
- ot->idname= "MESH_OT_select_shortest_path";
-
- /* api callbacks */
- ot->invoke= mesh_shortest_path_select_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
-}
-
-
/* ************************************************** */
-
-/* here actual select happens */
-/* gets called via generic mouse select operator */
-void mouse_mesh(bContext *C, short mval[2], short extend)
-{
- ViewContext vc;
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
-
- if(unified_findnearest(&vc, &eve, &eed, &efa)) {
-
- if(extend==0) EM_clear_flag_all(vc.em, SELECT);
-
- if(efa) {
- /* set the last selected face */
- EM_set_actFace(vc.em, efa);
-
- if( (efa->f & SELECT)==0 ) {
- EM_store_selection(vc.em, efa, EDITFACE);
- EM_select_face_fgon(vc.em, efa, 1);
- }
- else if(extend) {
- EM_remove_selection(vc.em, efa, EDITFACE);
- EM_select_face_fgon(vc.em, efa, 0);
- }
- }
- else if(eed) {
- if((eed->f & SELECT)==0) {
- EM_store_selection(vc.em, eed, EDITEDGE);
- EM_select_edge(eed, 1);
- }
- else if(extend) {
- EM_remove_selection(vc.em, eed, EDITEDGE);
- EM_select_edge(eed, 0);
- }
- }
- else if(eve) {
- if((eve->f & SELECT)==0) {
- eve->f |= SELECT;
- EM_store_selection(vc.em, eve, EDITVERT);
- }
- else if(extend){
- EM_remove_selection(vc.em, eve, EDITVERT);
- eve->f &= ~SELECT;
- }
- }
-
- EM_selectmode_flush(vc.em);
-
-// if (EM_texFaceCheck()) {
-
- if (efa && efa->mat_nr != vc.obedit->actcol-1) {
- vc.obedit->actcol= efa->mat_nr+1;
- vc.em->mat_nr= efa->mat_nr;
-// BIF_preview_changed(ID_MA);
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
-
-}
-
/* *********** select linked ************* */
/* for use with selectconnected_delimit_mesh only! */
@@ -2277,6 +1756,7 @@ else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
/* legacy warning, this function combines too much :) */
static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
{
+#if 0 //BMESH_TODO
EditMesh *em= vc->em;
EditFace *efa;
EditEdge *eed;
@@ -2367,7 +1847,7 @@ static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
EM_select_face(efa, 1);
// if (EM_texFaceCheck())
-
+#endif
return OPERATOR_FINISHED;
}
@@ -2377,6 +1857,7 @@ static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
+#if 0 //BMESH_TODO
Object *obedit= CTX_data_edit_object(C);
ViewContext vc;
EditVert *eve, *v1, *v2;
@@ -2461,6 +1942,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
return OPERATOR_FINISHED;
+#endif
}
void MESH_OT_select_linked_pick(wmOperatorType *ot)
@@ -3264,40 +2746,21 @@ void MESH_OT_select_inverse(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-/* ******************** (de)select all operator **************** */
-
-void EM_toggle_select_all(EditMesh *em) /* exported for UV */
+static int bmesh_test_exec(bContext *C, wmOperator *op)
{
- if(EM_nvertices_selected(em))
- EM_clear_flag_all(em, SELECT);
- else
- EM_set_flag_all(em, SELECT);
-}
-
-static int toggle_select_all_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_toggle_select_all(em);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
- BKE_mesh_end_editmesh(obedit->data, em);
-
return OPERATOR_FINISHED;
}
-void MESH_OT_select_all_toggle(wmOperatorType *ot)
+void MESH_OT_bmesh_test(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Select/Deselect All";
- ot->idname= "MESH_OT_select_all_toggle";
+ ot->name= "bmesh test op";
+ ot->idname= "MESH_OT_bmesh_test";
/* api callbacks */
- ot->exec= toggle_select_all_exec;
+ ot->exec= bmesh_test_exec;
ot->poll= ED_operator_editmesh;
-
- /* flags */
+
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
@@ -3585,157 +3048,6 @@ static void mesh_selection_type(Scene *scene, EditMesh *em, int val)
}
}
-static EnumPropertyItem prop_mesh_edit_types[] = {
- {1, "VERT", 0, "Vertices", ""},
- {2, "EDGE", 0, "Edges", ""},
- {3, "FACE", 0, "Faces", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int mesh_selection_type_exec(bContext *C, wmOperator *op)
-{
-
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- mesh_selection_type(CTX_data_scene(C), em, RNA_enum_get(op->ptr,"type"));
-
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_selection_type(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Selection Mode";
- ot->idname= "MESH_OT_selection_type";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= mesh_selection_type_exec;
-
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
-
-}
-/* ************************* SEAMS AND EDGES **************** */
-
-static int editmesh_mark_seam(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- Mesh *me= ((Mesh *)obedit->data);
- EditEdge *eed;
- int clear = RNA_boolean_get(op->ptr, "clear");
-
- /* auto-enable seams drawing */
- if(clear==0) {
- me->drawflag |= ME_DRAWSEAMS;
- }
-
- if(clear) {
- eed= em->edges.first;
- while(eed) {
- if((eed->h==0) && (eed->f & SELECT)) {
- eed->seam = 0;
- }
- eed= eed->next;
- }
- }
- else {
- eed= em->edges.first;
- while(eed) {
- if((eed->h==0) && (eed->f & SELECT)) {
- eed->seam = 1;
- }
- eed= eed->next;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_seam(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Seam";
- ot->idname= "MESH_OT_mark_seam";
-
- /* api callbacks */
- ot->exec= editmesh_mark_seam;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
-}
-
-static int editmesh_mark_sharp(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- Mesh *me= ((Mesh *)obedit->data);
- int clear = RNA_boolean_get(op->ptr, "clear");
- EditEdge *eed;
-
- /* auto-enable sharp edge drawing */
- if(clear == 0) {
- me->drawflag |= ME_DRAWSHARP;
- }
-
- if(!clear) {
- eed= em->edges.first;
- while(eed) {
- if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
- eed = eed->next;
- }
- } else {
- eed= em->edges.first;
- while(eed) {
- if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
- eed = eed->next;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_sharp(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Sharp";
- ot->idname= "MESH_OT_mark_sharp";
-
- /* api callbacks */
- ot->exec= editmesh_mark_sharp;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
-}
-
/* **************** NORMALS ************** */
/* XXX value of select is messed up, it means two things */
@@ -3954,6 +3266,7 @@ static int righthandfaces_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
+
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
/* 'standard' behaviour - check if selected, then apply relevant selection */
@@ -4163,6 +3476,7 @@ void editmesh_align_view_to_selected(Object *obedit, EditMesh *em, wmOperator *o
static int smooth_vertex(bContext *C, wmOperator *op)
{
+#if 0 //BMESH_TODO
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
@@ -4173,12 +3487,18 @@ static int smooth_vertex(bContext *C, wmOperator *op)
int teller=0;
ModifierData *md;
+ if(em==NULL) {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
/* count */
eve= em->verts.first;
while(eve) {
if(eve->f & SELECT) teller++;
eve= eve->next;
}
+
if(teller==0) {
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
@@ -4296,6 +3616,7 @@ static int smooth_vertex(bContext *C, wmOperator *op)
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+#endif
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index efb68f69dac..50ac7894120 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -75,6 +75,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "BKE_utildefines.h"
#include "BKE_bmesh.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -91,6 +93,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "UI_interface.h"
#include "mesh_intern.h"
+#include "bmesh.h"
/* XXX */
static int extern_qread() {return 0;}
@@ -529,6 +532,7 @@ static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y,
/* all verts with (flag & 'flag') are sorted */
void xsortvert_flag(bContext *C, int flag)
{
+#if 0 //BMESH_TODO
ViewContext vc;
EditVert *eve;
xvertsort *sortblock;
@@ -560,7 +564,7 @@ void xsortvert_flag(bContext *C, int flag)
addlisttolist(&vc.em->verts, &tbase);
MEM_freeN(sortblock);
-
+#endif
}
/* called from buttons */
@@ -641,12 +645,15 @@ void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op)
}
else if(em->selectmode & SCE_SELECT_EDGE) {
if (em->totedgesel==0) nr = 0;
- else if (em->totedgesel==1) nr = 3;
+
+ nr = 1;
+ /*else if (em->totedgesel==1) nr = 3;
else if(em->totfacesel==0) nr = 3;
else if(em->totfacesel==1)
nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
else
nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ */
}
else {
if (em->totfacesel == 0) nr = 0;
@@ -696,6 +703,8 @@ void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op)
}
+#if 0
+//need to see if this really had new stuff I should merge over
// XXX should be a menu item
static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
@@ -752,6 +761,7 @@ void MESH_OT_extrude(wmOperatorType *ot)
Properties_Proportional(ot);
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
}
+#endif
static int split_mesh(bContext *C, wmOperator *op)
{
@@ -790,7 +800,9 @@ void MESH_OT_split(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-
+#if 0
+//this also showed up in a merge, need to check if it
+//needs changes ported over to new extrude code too
static int extrude_repeat_mesh(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
@@ -853,7 +865,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
}
-
+#endif
/* ************************** spin operator ******************** */
@@ -1146,190 +1158,6 @@ static void erase_vertices(EditMesh *em, ListBase *l)
}
}
-void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
-{
- EditFace *efa, *nextvl;
- EditVert *eve,*nextve;
- EditEdge *eed,*nexted;
- int count;
- char *str="Erase";
-
-
- if(event<1) return;
-
- if(event==10 ) {
- str= "Erase Vertices";
- erase_edges(em, &em->edges);
- erase_faces(em, &em->faces);
- erase_vertices(em, &em->verts);
- }
- else if(event==6) {
- if(!EdgeLoopDelete(em, op))
- return;
-
- str= "Erase Edge Loop";
- }
- else if(event==4) {
- str= "Erase Edges & Faces";
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- /* delete only faces with 1 or more edges selected */
- count= 0;
- if(efa->e1->f & SELECT) count++;
- if(efa->e2->f & SELECT) count++;
- if(efa->e3->f & SELECT) count++;
- if(efa->e4 && (efa->e4->f & SELECT)) count++;
- if(count) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextvl;
- }
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
- if(eed->f & SELECT) {
- remedge(em, eed);
- free_editedge(em, eed);
- }
- eed= nexted;
- }
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- event=0;
- if( efa->v1->f & SELECT) event++;
- if( efa->v2->f & SELECT) event++;
- if( efa->v3->f & SELECT) event++;
- if(efa->v4 && (efa->v4->f & SELECT)) event++;
-
- if(event>1) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextvl;
- }
- }
- else if(event==1) {
- str= "Erase Edges";
- // faces first
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- event=0;
- if( efa->e1->f & SELECT) event++;
- if( efa->e2->f & SELECT) event++;
- if( efa->e3->f & SELECT) event++;
- if(efa->e4 && (efa->e4->f & SELECT)) event++;
-
- if(event) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextvl;
- }
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
- if(eed->f & SELECT) {
- remedge(em, eed);
- free_editedge(em, eed);
- }
- eed= nexted;
- }
- /* to remove loose vertices: */
- eed= em->edges.first;
- while(eed) {
- if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
- if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
- eed= eed->next;
- }
- eve= em->verts.first;
- while(eve) {
- nextve= eve->next;
- if(eve->f & SELECT) {
- BLI_remlink(&em->verts,eve);
- free_editvert(em, eve);
- }
- eve= nextve;
- }
-
- }
- else if(event==2) {
- str="Erase Faces";
- delfaceflag(em, SELECT);
- }
- else if(event==3) {
- str= "Erase All";
- if(em->verts.first) free_vertlist(em, &em->verts);
- if(em->edges.first) free_edgelist(em, &em->edges);
- if(em->faces.first) free_facelist(em, &em->faces);
- if(em->selected.first) BLI_freelistN(&(em->selected));
- }
- else if(event==5) {
- str= "Erase Only Faces";
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- if(efa->f & SELECT) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextvl;
- }
- }
-
- EM_fgon_flags(em); // redo flags and indices for fgons
-}
-
-/* Note, these values must match delete_mesh() event values */
-static EnumPropertyItem prop_mesh_delete_types[] = {
- {10,"VERT", 0, "Vertices", ""},
- {1, "EDGE", 0, "Edges", ""},
- {2, "FACE", 0, "Faces", ""},
- {3, "ALL", 0, "All", ""},
- {4, "EDGE_FACE",0, "Edges & Faces", ""},
- {5, "ONLY_FACE",0, "Only Faces", ""},
- {6, "EDGE_LOOP",0, "Edge Loop", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int delete_mesh_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- delete_mesh(obedit, em, op, RNA_enum_get(op->ptr, "type"));
-
- DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Delete";
- ot->idname= "MESH_OT_delete";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= delete_mesh_exec;
-
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /*props */
- RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
-}
-
-
/*GB*/
/*-------------------------------------------------------------------------------*/
/*--------------------------- Edge Based Subdivide ------------------------------*/
@@ -1382,7 +1210,7 @@ static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int
co[1] += vec1[1];
co[2] += vec1[2];
}
- else if(beauty & B_SPHERE) { /* subdivide sphere */
+ /*else if(beauty & B_SPHERE) { // subdivide sphere
Normalize(co);
co[0]*= smooth;
co[1]*= smooth;
@@ -1395,7 +1223,7 @@ static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int
vec1[1]= fac*(float)(0.5-BLI_drand());
vec1[2]= fac*(float)(0.5-BLI_drand());
VecAddf(co, co, vec1);
- }
+ }*/
}
/* assumes in the edge is the correct interpolated vertices already */
@@ -2243,7 +2071,7 @@ static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, i
for(i=1;i<=numcuts;i++) {
/* we create a fake edge for the next loop */
- temp.v2 = innerverts[i][0] = verts[1][i];
+ temp.v2 = innerverts[i][0] = verts[1][i];
temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
for(j=1;j<=numcuts;j++) {
@@ -2382,7 +2210,7 @@ static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int n
MEM_freeN(innerverts);
}
-//Next two fill types are for knife exact only and are provided to allow for knifing through vertices
+//Next two fill types are for exact only and are provided to allow for knifing through vertices
//This means there is no multicut!
static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
{
@@ -4780,6 +4608,7 @@ static void mesh_rip_setface(EditMesh *em, EditFace *sefa)
/* based on mouse cursor position, it defines how is being ripped */
static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
+#if 0 //BMESH_TODO
Scene *scene= CTX_data_scene(C);
ARegion *ar= CTX_wm_region(C);
RegionView3D *rv3d= ar->regiondata;
@@ -4984,6 +4813,7 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
RNA_enum_set(op->ptr, "proportional", 0);
RNA_boolean_set(op->ptr, "mirror", 0);
WM_operator_name_call(C, "TFM_OT_translation", WM_OP_INVOKE_REGION_WIN, op->ptr);
+#endif
return OPERATOR_FINISHED;
}
@@ -5053,6 +4883,7 @@ void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock)
{
+#if 0 //BMESH_TODO
EditVert *ev = NULL;
short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ;
float perc = 0;
@@ -5129,6 +4960,7 @@ void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock
}
}
return;
+#endif
}
@@ -6645,52 +6477,6 @@ void MESH_OT_colors_mirror(wmOperatorType *ot)
RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
}
-/********************** Subdivide Operator *************************/
-
-static int subdivide_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int cuts= RNA_int_get(op->ptr,"number_cuts");
- float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness");
- float fractal= RNA_float_get(op->ptr, "fractal")/100;
- int flag= 0;
-
- if(smooth != 0.0f)
- flag |= B_SMOOTH;
- if(fractal != 0.0f)
- flag |= B_FRACTAL;
-
- esubdivideflag(obedit, em, 1, smooth, fractal, scene->toolsettings->editbutflag|flag, cuts, 0);
-
- DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_subdivide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Subdivide";
- ot->idname= "MESH_OT_subdivide";
-
- /* api callbacks */
- ot->exec= subdivide_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
- RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
- RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX);
-}
-
-/********************** Fill Operators *************************/
-
/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
edge/face flags, with very mixed results.... */
static void beauty_fill(EditMesh *em)
@@ -7002,14 +6788,15 @@ static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
- convert_to_triface(em,0);
+ //convert_to_triface(em,0);
+ if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 6e098e04a14..7f974a532d8 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -32,11 +32,54 @@
#ifndef MESH_INTERN_H
#define MESH_INTERN_H
+#include "BLI_editVert.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
struct bContext;
struct wmOperatorType;
+struct ViewContext;
+struct BMEditMesh;
+struct BMesh;
+struct BMEdge;
+struct BMFace;
#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
+/* ******************** bmeshutils.c */
+
+/*
+ok: the EDBM module is for editmode bmesh stuff. in contrast, the
+ BMEdit module is for code shared with blenkernel that concerns
+ the BMEditMesh structure.
+*/
+
+/*calls a bmesh op, reporting errors to the user, doing conversions,
+ etc.*/
+int EDBM_CallOpf(struct BMEditMesh *em, struct wmOperator *op, char *fmt, ...);
+
+/*same as above, but doesn't report errors.*/
+int EDBM_CallOpfSilent(struct BMEditMesh *em, char *fmt, ...);
+
+/*these next two functions are the split version of EDBM_CallOpf, so you can
+ do stuff with a bmesh operator, after initializing it but before executing
+ it.
+
+ execute the operator with BM_Exec_Op*/
+int EDBM_InitOpf(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, char *fmt, ...);
+/*cleans up after a bmesh operator*/
+int EDBM_FinishOp(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, int report);
+
+void EDBM_clear_flag_all(struct BMEditMesh *em, int flag);
+void EDBM_set_actFace(struct BMEditMesh *em, struct BMFace *efa);
+void EDBM_store_selection(struct BMEditMesh *em, void *data);
+void EDBM_validate_selections(struct BMEditMesh *em);
+void EDBM_remove_selection(struct BMEditMesh *em, void *data);
+void EDBM_stats_update(struct BMEditMesh *em);
+
/* ******************** editface.c */
int edgetag_context_check(Scene *scene, EditEdge *eed);
@@ -45,11 +88,18 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge
/* ******************* editmesh.c */
+void EM_beginEditMesh(struct Object *ob);
+void EM_endEditMesh(struct Object *ob, EditMesh *em);
+
extern void free_editvert(EditMesh *em, EditVert *eve);
extern void free_editedge(EditMesh *em, EditEdge *eed);
extern void free_editface(EditMesh *em, EditFace *efa);
void free_editMesh(EditMesh *em);
+/*frees dst mesh, then copies the contents of
+ *src (the struct) to dst. */
+void set_editMesh(EditMesh *dst, EditMesh *src);
+
extern void free_vertlist(EditMesh *em, ListBase *edve);
extern void free_edgelist(EditMesh *em, ListBase *lb);
extern void free_facelist(EditMesh *em, ListBase *lb);
@@ -67,7 +117,7 @@ int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve);
int editface_containsVert(struct EditFace *efa, struct EditVert *eve);
int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed);
-void em_setup_viewcontext(struct bContext *C, ViewContext *vc);
+void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc);
void MESH_OT_separate(struct wmOperatorType *ot);
@@ -149,6 +199,7 @@ void MESH_OT_knife_cut(struct wmOperatorType *ot);
/* ******************* editmesh_mods.c */
void MESH_OT_loop_select(struct wmOperatorType *ot);
void MESH_OT_select_all_toggle(struct wmOperatorType *ot);
+void MESH_OT_bmesh_test(struct wmOperatorType *ot);
void MESH_OT_select_more(struct wmOperatorType *ot);
void MESH_OT_select_less(struct wmOperatorType *ot);
void MESH_OT_select_inverse(struct wmOperatorType *ot);
@@ -172,13 +223,13 @@ void MESH_OT_mark_sharp(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_flip_normals(struct wmOperatorType *ot);
-extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
+extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist);
extern void EM_automerge(int update);
void editmesh_select_by_material(EditMesh *em, int index);
void righthandfaces(EditMesh *em, int select); /* makes faces righthand turning */
void EM_select_more(EditMesh *em);
void selectconnected_mesh_all(EditMesh *em);
-void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
+void faceloop_select(struct BMEditMesh *em, struct BMEdge *startedge, int select);
/**
* findnearestvert
@@ -189,7 +240,7 @@ void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
* if 0, unselected vertice are given the bias
* strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
*/
-extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict);
+extern EditVert *findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict);
/* ******************* editmesh_tools.c */
@@ -202,7 +253,7 @@ extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short st
void join_triangles(EditMesh *em);
int removedoublesflag(EditMesh *em, short flag, short automerge, float limit); /* return amount */
void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int seltype);
-int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc);
+int EdgeSlide(EditMesh *em, struct wmOperator *op, short immediate, float imperc);
void MESH_OT_merge(struct wmOperatorType *ot);
void MESH_OT_subdivide(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_layers.c b/source/blender/editors/mesh/mesh_layers.c
index 99d50d1a9b0..bad2fa99434 100644
--- a/source/blender/editors/mesh/mesh_layers.c
+++ b/source/blender/editors/mesh/mesh_layers.c
@@ -44,6 +44,7 @@
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BLI_editVert.h"
@@ -57,10 +58,11 @@
#include "ED_view3d.h"
#include "mesh_intern.h"
+#include "bmesh.h"
static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
{
- CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ CustomData *data= (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
int type= layer->type;
int index= CustomData_get_layer_index(data, type);
@@ -79,8 +81,8 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
CustomData_set_layer_active(data, type, layer - &data->layers[index]);
- if(me->edit_mesh) {
- EM_free_data_layer(me->edit_mesh, data, type);
+ if(me->edit_btmesh) {
+ BM_free_data_layer(me->edit_btmesh->bm, data, type);
}
else {
CustomData_free_layer_active(data, type, me->totface);
@@ -88,7 +90,7 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
}
if(!CustomData_has_layer(data, type))
- if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
+ if(type == CD_MLOOPCOL && (G.f & G_VERTEXPAINT))
G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
/* reconstruct active layer */
@@ -156,7 +158,7 @@ static int uv_texture_add_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
Mesh *me;
- EditMesh *em;
+ BMEditMesh *em;
int layernum;
if(!ob || ob->type!=OB_MESH)
@@ -165,26 +167,30 @@ static int uv_texture_add_exec(bContext *C, wmOperator *op)
me= (Mesh*)ob->data;
if(scene->obedit == ob) {
- em= me->edit_mesh;
+ em= me->edit_btmesh;
- layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
+ layernum= CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
if(layernum >= MAX_MTFACE)
return OPERATOR_CANCELLED;
- EM_add_data_layer(em, &em->fdata, CD_MTFACE);
- CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
+ CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum);
}
else if(ob) {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ layernum= CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
if(layernum >= MAX_MTFACE)
return OPERATOR_CANCELLED;
- if(me->mtface)
- CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
- else
- CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
-
- CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
+ if (me->mtpoly) {
+ CustomData_add_layer(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly);
+ CustomData_add_layer(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop);
+ } else {
+ CustomData_add_layer(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly);
+ CustomData_add_layer(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop);
+ }
+
+ CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum);
mesh_update_customdata_pointers(me);
}
@@ -212,20 +218,24 @@ static int uv_texture_remove_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
Mesh *me;
- CustomDataLayer *cdl;
+ CustomDataLayer *cdl, *cdl2;
int index;
if(!ob || ob->type!=OB_MESH)
return OPERATOR_CANCELLED;
me= (Mesh*)ob->data;
- index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl= (index == -1)? NULL: &me->fdata.layers[index];
+ index= CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+ cdl= (index == -1)? NULL: &me->pdata.layers[index];
+
+ index= CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
+ cdl2= (index == -1)? NULL: &me->ldata.layers[index];
if(!cdl)
return OPERATOR_CANCELLED;
delete_customdata_layer(me, cdl);
+ delete_customdata_layer(me, cdl2);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
@@ -253,8 +263,8 @@ static int vertex_color_add_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
Mesh *me;
- EditMesh *em;
- MCol *mcol;
+ BMEditMesh *em;
+ MLoopCol *mcol;
int layernum;
if(!ob || ob->type!=OB_MESH)
@@ -263,28 +273,28 @@ static int vertex_color_add_exec(bContext *C, wmOperator *op)
me= (Mesh*)ob->data;
if(scene->obedit == ob) {
- em= me->edit_mesh;
+ em= me->edit_btmesh;
- layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
+ layernum= CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
if(layernum >= MAX_MCOL)
return OPERATOR_CANCELLED;
- EM_add_data_layer(em, &em->fdata, CD_MCOL);
- CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
}
else {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
+ layernum= CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
if(layernum >= MAX_MCOL)
return OPERATOR_CANCELLED;
- mcol= me->mcol;
+ mcol= me->mloopcol;
- if(me->mcol)
- CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
+ if(me->mloopcol)
+ CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop);
else
- CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
+ CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
- CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
mesh_update_customdata_pointers(me);
if(!mcol)
@@ -322,8 +332,8 @@ static int vertex_color_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
me= (Mesh*)ob->data;
- index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
- cdl= (index == -1)? NULL: &me->fdata.layers[index];
+ index= CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL);
+ cdl= (index == -1)? NULL: &me->ldata.layers[index];
if(!cdl)
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c10fdbcfd8f..5f406cb4db8 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -72,6 +72,7 @@
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
@@ -118,15 +119,17 @@ int join_mesh_exec(bContext *C, wmOperator *op)
MVert *mvert, *mv, *mvertmain;
MEdge *medge = NULL, *medgemain;
MFace *mface = NULL, *mfacemain;
+ MPoly *mpoly = NULL, *mpolymain;
+ MLoop *mloop = NULL, *mloopmain;
Key *key, *nkey=NULL;
KeyBlock *kb, *okb, *kbn;
float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0;
- int vertofs, *matmap;
- int i, j, index, haskey=0, edgeofs, faceofs;
+ int totloop=0, totpoly=0, vertofs, *matmap;
+ int i, j, index, haskey=0, edgeofs, faceofs, loopofs, polyofs;
bDeformGroup *dg, *odg;
MDeformVert *dvert;
- CustomData vdata, edata, fdata;
+ CustomData vdata, edata, fdata, ldata, pdata;
if(scene->obedit)
return OPERATOR_CANCELLED;
@@ -143,6 +146,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
totvert+= me->totvert;
totedge+= me->totedge;
totface+= me->totface;
+ totloop+= me->totloop;
+ totpoly+= me->totpoly;
totmat+= base->object->totcol;
if(base->object == ob)
@@ -290,18 +295,26 @@ int join_mesh_exec(bContext *C, wmOperator *op)
memset(&vdata, 0, sizeof(vdata));
memset(&edata, 0, sizeof(edata));
memset(&fdata, 0, sizeof(fdata));
+ memset(&ldata, 0, sizeof(ldata));
+ memset(&pdata, 0, sizeof(pdata));
mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+ mloop= CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+ mpoly= CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
mvertmain= mvert;
medgemain= medge;
mfacemain= mface;
+ mloopmain = mloop;
+ mpolymain = mpoly;
vertofs= 0;
edgeofs= 0;
faceofs= 0;
+ loopofs= 0;
+ polyofs= 0;
/* inverse transform for all selected meshes in this object */
Mat4Invert(imat, ob->obmat);
@@ -451,7 +464,43 @@ int join_mesh_exec(bContext *C, wmOperator *op)
edgeofs += me->totedge;
}
+
+ if (me->totloop) {
+ CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
+ CustomData_copy_data(&me->ldata, &ldata, 0, loopofs, me->totloop);
+
+ for(a=0; a<me->totloop; a++, mloop++) {
+ mloop->v += vertofs;
+ mloop->e += edgeofs;
+ }
+
+ loopofs += me->totloop;
+ }
+ if(me->totpoly) {
+ /* make mapping for materials */
+ for(a=1; a<=base->object->totcol; a++) {
+ ma= give_current_material(base->object, a);
+
+ for(b=0; b<totcol; b++) {
+ if(ma == matar[b]) {
+ matmap[a-1]= b;
+ break;
+ }
+ }
+ }
+
+ CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
+ CustomData_copy_data(&me->pdata, &pdata, 0, polyofs, me->totpoly);
+
+ for(a=0; a<me->totpoly; a++, mpoly++) {
+ mpoly->loopstart += loopofs;
+ mpoly->mat_nr= matmap[(int)mpoly->mat_nr];
+ }
+
+ polyofs += me->totface;
+ }
+
/* vertofs is used to help newly added verts be reattached to their edge/face
* (cannot be set earlier, or else reattaching goes wrong)
*/
@@ -470,14 +519,20 @@ int join_mesh_exec(bContext *C, wmOperator *op)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
me->totvert= totvert;
me->totedge= totedge;
me->totface= totface;
+ me->totloop= totloop;
+ me->totpoly= totpoly;
me->vdata= vdata;
me->edata= edata;
me->fdata= fdata;
+ me->ldata= ldata;
+ me->pdata= pdata;
mesh_update_customdata_pointers(me);
@@ -838,7 +893,7 @@ static struct {
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
-intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
+intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
{
MocNode **bt;
@@ -864,10 +919,12 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
* we are using the undeformed coordinates*/
INIT_MINMAX(min, max);
- if(em && me->edit_mesh==em) {
- EditVert *eve;
+ if(em && me->edit_btmesh==em) {
+ BMIter iter;
+ BMVert *eve;
- for(eve= em->verts.first; eve; eve= eve->next)
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter))
DO_MINMAX(eve->co, min, max)
}
else {
@@ -905,10 +962,12 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table");
- if(em && me->edit_mesh==em) {
- EditVert *eve;
+ if(em && me->edit_btmesh==em) {
+ BMVert *eve;
+ BMIter iter;
- for(eve= em->verts.first; eve; eve= eve->next) {
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter)) {
mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (intptr_t)(eve));
}
}
@@ -964,7 +1023,7 @@ int mesh_get_x_mirror_vert(Object *ob, int index)
return mesh_octree_table(ob, NULL, vec, 'u');
}
-EditVert *editmesh_get_x_mirror_vert(Object *ob, EditMesh *em, float *co)
+BMVert *editmesh_get_x_mirror_vert(Object *ob, BMEditMesh *em, float *co)
{
float vec[3];
intptr_t poinval;
@@ -982,7 +1041,7 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, EditMesh *em, float *co)
poinval= mesh_octree_table(ob, em, vec, 'u');
if(poinval != -1)
- return (EditVert *)(poinval);
+ return (BMVert *)(poinval);
return NULL;
}
@@ -1032,7 +1091,7 @@ static int mirror_facecmp(void *a, void *b)
return (mirror_facerotation((MFace*)a, (MFace*)b) == -1);
}
-int *mesh_get_x_mirror_faces(Object *ob, EditMesh *em)
+int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
{
Mesh *me= ob->data;
MVert *mv, *mvert= me->mvert;
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript
index 3371e172a82..0b7a4e41192 100644
--- a/source/blender/editors/object/SConscript
+++ b/source/blender/editors/object/SConscript
@@ -6,7 +6,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc'
incs += ' #/intern/guardedalloc'
-incs += ' ../../makesrna ../../python'
+incs += ' ../../makesrna ../../python ../../bmesh'
defs = []
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 0746fbaefb6..a938018d97b 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -96,6 +96,7 @@
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BKE_nla.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -845,13 +846,14 @@ static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
}
-static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
+static int return_editmesh_indexar(BMEditMesh *em, int *tot, int **indexar, float *cent)
{
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
int *index, nr, totvert=0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) totvert++;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) totvert++;
}
if(totvert==0) return 0;
@@ -860,8 +862,8 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float
nr= 0;
cent[0]= cent[1]= cent[2]= 0.0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
*index= nr; index++;
VecAddf(cent, cent, eve->co);
}
@@ -873,19 +875,19 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float
return totvert;
}
-static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
+static int return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *name, float *cent)
{
MDeformVert *dvert;
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
int i, totvert=0;
cent[0]= cent[1]= cent[2]= 0.0;
if(obedit->actdef) {
-
/* find the vertices */
- for(eve= em->verts.first; eve; eve= eve->next) {
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_em_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert) {
for(i=0; i<dvert->totweight; i++){
@@ -910,19 +912,18 @@ static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, floa
static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
{
Mesh *me= ob->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em= me->edit_btmesh;
+ BMVert *eve;
+ BMIter iter;
int index=0, nr=0;
- for(eve= em->verts.first; eve; eve= eve->next, nr++) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if(nr==hmd->indexar[index]) {
- eve->f |= SELECT;
+ BM_Select(em->bm, eve, 1);
if(index < hmd->totindex-1) index++;
}
+ nr++;
}
- EM_select_flush(em);
-
- BKE_mesh_end_editmesh(me, em);
}
static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
@@ -1095,16 +1096,13 @@ int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, floa
case OB_MESH:
{
Mesh *me= obedit->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
/* check selected vertices first */
if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
- BKE_mesh_end_editmesh(me, em);
return 1;
} else {
- int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
- BKE_mesh_end_editmesh(me, em);
- return ret;
+ return return_editmesh_vgroup(obedit, em, name, cent_r);
}
}
case OB_CURVE:
@@ -2541,10 +2539,10 @@ void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- eve= em->verts.first;
- while(eve) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if(eve->f & 1) {
if(v1==0) v1= nr;
else if(v2==0) v2= nr;
@@ -2553,10 +2551,7 @@ void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
else break;
}
nr++;
- eve= eve->next;
}
-
- BKE_mesh_end_editmesh(me, em);
}
else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
ListBase *editnurb= curve_get_editcurve(obedit);
@@ -3179,9 +3174,10 @@ static int object_center_set_exec(bContext *C, wmOperator *op)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- for(eve= em->verts.first; eve; eve= eve->next) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if(v3d->around==V3D_CENTROID) {
total++;
VECADD(cent, cent, eve->co);
@@ -3200,14 +3196,13 @@ static int object_center_set_exec(bContext *C, wmOperator *op)
cent[2]= (min[2]+max[2])/2.0f;
}
- for(eve= em->verts.first; eve; eve= eve->next) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
VecSubf(eve->co, eve->co, cent);
}
- recalc_editnormals(em);
+ EDBM_RecalcNormals(em);
tot_change++;
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- BKE_mesh_end_editmesh(me, em);
}
}
@@ -3504,16 +3499,17 @@ void ED_object_exit_editmode(bContext *C, int flag)
// if(retopo_mesh_paint_check())
// retopo_end_okee();
- if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
+ if(me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) {
error("Too many vertices");
return;
}
- load_editMesh(scene, obedit);
+
+ EDBM_LoadEditBMesh(scene, obedit);
if(freedata) {
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
}
if(G.f & G_WEIGHTPAINT)
@@ -3597,7 +3593,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
ok= 1;
scene->obedit= ob; // context sees this
- make_editMesh(scene, ob);
+ EDBM_MakeEditBMesh(scene, ob);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
}
diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c
index 3f7880b7fef..da8bcaab0b5 100644
--- a/source/blender/editors/physics/editparticle.c
+++ b/source/blender/editors/physics/editparticle.c
@@ -1015,7 +1015,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
mvert=dm->getVertDataArray(dm,CD_MVERT);
for(i=0; i<totface; i++, vec+=6, nor+=6) {
- mface=dm->getFaceData(dm,i,CD_MFACE);
+ mface=dm->getTessFaceData(dm,i,CD_MFACE);
mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
VECCOPY(vec,mvert->co);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 113e7249e65..19cbf93a83c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -201,7 +201,7 @@ int ED_operator_editmesh(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
if(obedit && obedit->type==OB_MESH)
- return NULL != ((Mesh *)obedit->data)->edit_mesh;
+ return NULL != ((Mesh *)obedit->data)->edit_btmesh;
return 0;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 720e64d260f..08a1c014a10 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -2966,11 +2966,11 @@ static void project_paint_begin(ProjPaintState *ps)
return;
}
ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getFaceArray(ps->dm);
- ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface= ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totface = ps->dm->getNumFaces(ps->dm);
+ ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
/* use clone mtface? */
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 85ea55331dc..46d41c043bd 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -80,9 +80,9 @@ static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, fl
void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceindex, int *xy, float *uv)
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf;
- int numfaces = dm->getNumFaces(dm), a;
+ int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf;
+ int numfaces = dm->getNumTessFaces(dm), a;
float p[2], w[3], absw, minabsw;
MFace mf;
MVert mv[4];
@@ -93,7 +93,7 @@ void imapaint_pick_uv(Scene *scene, Object *ob, Mesh *mesh, unsigned int faceind
/* test all faces in the derivedmesh with the original index of the picked face */
for(a = 0; a < numfaces; a++) {
if(index[a] == faceindex) {
- dm->getFace(dm, a, &mf);
+ dm->getTessFace(dm, a, &mf);
dm->getVert(dm, mf.v1, &mv[0]);
dm->getVert(dm, mf.v2, &mv[1]);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 7245218c688..f3108e02159 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1001,8 +1001,8 @@ static void sculpt_update_mesh_elements(bContext *C)
ss->totvert = dm->getNumVerts(dm);
ss->totface = dm->getNumFaces(dm);
ss->mvert = dm->getVertDataArray(dm, CD_MVERT);
- ss->mface = dm->getFaceDataArray(dm, CD_MFACE);
- ss->face_normals = dm->getFaceDataArray(dm, CD_NORMAL);
+ ss->mface = dm->getTessFaceDataArray(dm, CD_MFACE);
+ ss->face_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
}
else {
Mesh *me = get_mesh(ob);
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index a0a7dad4077..71530d6f92d 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../makesrna ../../render/extern/include'
+incs += ' ../../makesrna ../../render/extern/include ../../bmesh'
defs = []
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index fb1e9d1214d..0c3bda5b9b8 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -50,6 +50,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_world.h"
+#include "BKE_tessmesh.h"
#include "BLI_editVert.h"
#include "BLI_listbase.h"
@@ -128,12 +129,13 @@ static int material_slot_assign_exec(bContext *C, wmOperator *op)
if(ob && ob->actcol>0) {
if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
- EditFace *efa;
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
if(em) {
- for(efa= em->faces.first; efa; efa=efa->next)
- if(efa->f & SELECT)
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL)
+ if(BM_TestHFlag(efa, BM_SELECT))
efa->mat_nr= ob->actcol-1;
}
}
@@ -185,7 +187,7 @@ static int material_slot_de_select(bContext *C, int select)
return OPERATOR_CANCELLED;
if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
+ EditMesh *em= BKE_mesh_get_editmesh(((Mesh*)ob->data));
if(em) {
if(select)
@@ -193,6 +195,8 @@ static int material_slot_de_select(bContext *C, int select)
else
EM_deselect_by_material(em, ob->actcol-1);
}
+
+ BKE_mesh_end_editmesh(ob->data, em);
}
else if ELEM(ob->type, OB_CURVE, OB_SURF) {
ListBase *editnurb= ((Curve*)ob->data)->editnurb;
diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c
index 35088f0e4d1..e4cd5c77703 100644
--- a/source/blender/editors/space_image/image_header.c
+++ b/source/blender/editors/space_image/image_header.c
@@ -48,6 +48,7 @@
#include "BKE_mesh.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index 7d51d237ef0..b90ac30cd41 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -7,7 +7,7 @@ defs = []
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include #/intern/guardedalloc'
-incs += ' ../../gpu ../../makesrna ../../blenfont'
+incs += ' ../../gpu ../../makesrna ../../blenfont ../../bmesh '
if env['WITH_BF_GAMEENGINE']:
defs.append('GAMEBLENDER=1')
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 1807de9efbb..a04d6d07d24 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -550,6 +550,7 @@ void draw_mesh_text(Scene *scene, Object *ob, int glsl)
void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect)
{
+#if 0
Mesh *me= ob->data;
/* correct for negative scale */
@@ -586,5 +587,6 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o
/* in editmode, the blend mode needs to be set incase it was ADD */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+#endif
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 93c6c535a31..0c521512c12 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -88,6 +88,7 @@
#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -227,7 +228,7 @@ static int check_material_alpha(Base *base, Mesh *me, int glsl)
if(G.f & G_PICKSEL)
return 0;
- if(me->edit_mesh)
+ if(me->edit_btmesh)
return 0;
return (glsl || (base->object->dtx & OB_DRAWTRANSP));
@@ -1278,10 +1279,10 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
short s[2]= {IS_CLIPPED, 0};
if (data->clipVerts) {
@@ -1295,30 +1296,30 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co
}
}
-void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
+void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts)
{
- struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
data.clipVerts = clipVerts;
- EM_init_index_arrays(vc->em, 1, 0, 0);
+ EDBM_init_index_arrays(vc->em, 1, 0, 0);
dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
{
- struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
- EditEdge *eed = EM_get_edge_for_index(index);
+ struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
short s[2][2];
- if (eed->h==0) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
if (data->clipVerts==1) {
view3d_project_short_clip(data->vc.ar, v0co, s[0]);
view3d_project_short_clip(data->vc.ar, v1co, s[1]);
@@ -1337,48 +1338,48 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0
}
}
-void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
+void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
{
- struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
data.clipVerts = clipVerts;
- EM_init_index_arrays(vc->em, 0, 1, 0);
+ EDBM_init_index_arrays(vc->em, 0, 1, 0);
dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
{
- struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
- EditFace *efa = EM_get_face_for_index(index);
+ struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
short s[2];
- if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
view3d_project_short_clip(data->vc.ar, cent, s);
data->func(data->userData, efa, s[0], s[1], index);
}
}
-void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
+void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
{
- struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
- EM_init_index_arrays(vc->em, 0, 0, 1);
+ EDBM_init_index_arrays(vc->em, 0, 0, 1);
dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
@@ -1441,46 +1442,54 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
{
+ Scene *scene= ((void **)userData)[0];
+ BMEditMesh *em = ((void **)userData)[1];
+ BMFace *efa = EDBM_get_face_for_index(em, index);
ToolSettings *ts= ((Scene *)userData)->toolsettings;
- EditFace *efa = EM_get_face_for_index(index);
- if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
glVertex3fv(cent);
glVertex3f( cent[0] + no[0]*ts->normalsize,
cent[1] + no[1]*ts->normalsize,
cent[2] + no[2]*ts->normalsize);
}
}
-static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
+static void draw_dm_face_normals(BMEditMesh *tm, Scene *scene, DerivedMesh *dm)
{
+ void *ptrs[2] = {scene, tm};
+
glBegin(GL_LINES);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
glEnd();
}
static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
{
- EditFace *efa = EM_get_face_for_index(index);
- int sel = *((int*) userData);
+ BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
+ BMEditMesh *em = ((void **)userData)[0];
+ int sel = *(((int **)userData)[1]);
- if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
bglVertex3fv(cent);
}
}
-static void draw_dm_face_centers(DerivedMesh *dm, int sel)
+static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
{
+ void *ptrs[2] = {em, &sel};
+
bglBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
bglEnd();
}
static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- Scene *scene= (Scene *)userData;
+ Scene *scene= ((void **)userData)[0];
ToolSettings *ts= scene->toolsettings;
- EditVert *eve = EM_get_vert_for_index(index);
+ BMEditMesh *em = ((void **)userData)[1];
+ BMVert *eve = EDBM_get_vert_for_index(em, index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
glVertex3fv(co);
if (no_f) {
@@ -1494,20 +1503,22 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co,
}
}
}
-static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
+static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
{
+ void *ptrs[2] = {scene, em};
+
glBegin(GL_LINES);
- dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
+ dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
glEnd();
}
/* Draw verts with color set based on selection */
static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- struct { int sel; EditVert *eve_act; } * data = userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
+ BMVert *eve = EDBM_get_vert_for_index(data->em, index);
- if (eve->h==0 && (eve->f&SELECT)==data->sel) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
/* draw active larger - need to stop/start point drawing for this :/ */
if (eve==data->eve_act) {
float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
@@ -1528,11 +1539,12 @@ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *
}
}
}
-static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
+static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
{
- struct { int sel; EditVert *eve_act; } data;
+ struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
data.sel = sel;
data.eve_act = eve_act;
+ data.em = em;
bglBegin(GL_POINTS);
dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
@@ -1542,16 +1554,18 @@ static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
/* Draw edges with color set based on selection */
static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed;
//unsigned char **cols = userData, *col;
- struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
+ struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
unsigned char *col;
- if (eed->h==0) {
+ eed = EDBM_get_edge_for_index(data->em, index);
+
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
if (eed==data->eed_act) {
glColor4ubv(data->actCol);
} else {
- if (eed->f&SELECT) {
+ if (BM_TestHFlag(eed, BM_SELECT)) {
col = data->selCol;
} else {
col = data->baseCol;
@@ -1566,13 +1580,15 @@ static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
return 0;
}
}
-static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
+static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+ unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
{
- struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
+ struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
data.baseCol = baseCol;
data.selCol = selCol;
data.actCol = actCol;
+ data.em = em;
data.eed_act = eed_act;
dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
}
@@ -1580,60 +1596,65 @@ static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned
/* Draw edges */
static int draw_dm_edges__setDrawOptions(void *userData, int index)
{
- return EM_get_edge_for_index(index)->h==0;
+ return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
}
-static void draw_dm_edges(DerivedMesh *dm)
+static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
}
/* Draw edges with color interpolated based on selection */
static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
{
- return EM_get_edge_for_index(index)->h==0;
+ return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[1], index), BM_HIDDEN);
}
static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
{
- EditEdge *eed = EM_get_edge_for_index(index);
- unsigned char **cols = userData;
- unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
- unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
+ BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[1], index);
+ unsigned char **cols = ((void**)userData)[0];
+ unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?1:0];
+ unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?1:0];
glColor4ub( col0[0] + (col1[0]-col0[0])*t,
col0[1] + (col1[1]-col0[1])*t,
col0[2] + (col1[2]-col0[2])*t,
col0[3] + (col1[3]-col0[3])*t);
}
-static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
+static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm,
+ unsigned char *baseCol, unsigned char *selCol)
{
unsigned char *cols[2];
+ void *ptrs[2] = {cols, em};
+
cols[0] = baseCol;
cols[1] = selCol;
- dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
+ dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions,
+ draw_dm_edges_sel_interp__setDrawInterpOptions, ptrs);
}
/* Draw only seam edges */
static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- return (eed->h==0 && eed->seam);
+ return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
}
-static void draw_dm_edges_seams(DerivedMesh *dm)
+
+static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
}
/* Draw only sharp edges */
static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- return (eed->h==0 && eed->sharp);
+ return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
}
-static void draw_dm_edges_sharp(DerivedMesh *dm)
+static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
}
@@ -1641,16 +1662,16 @@ static void draw_dm_edges_sharp(DerivedMesh *dm)
* return 2 for the active face so it renders with stipple enabled */
static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
- EditFace *efa = EM_get_face_for_index(index);
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; } *data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->em, index);
unsigned char *col;
- if (efa->h==0) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
if (efa == data->efa_act) {
glColor4ubv(data->cols[2]);
return 2; /* stipple */
} else {
- col = data->cols[(efa->f&SELECT)?1:0];
+ col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
if (col[3]==0) return 0;
glColor4ubv(col);
return 1;
@@ -1660,10 +1681,13 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra
}
/* also draws the active face */
-static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
+static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+ unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; } data;
+
data.cols[0] = baseCol;
+ data.em = em;
data.cols[1] = selCol;
data.cols[2] = actCol;
data.efa_act = efa_act;
@@ -1673,27 +1697,27 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned
static int draw_dm_creases__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- if (eed->h==0 && eed->crease!=0.0) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN) && eed->crease!=0.0) {
UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
return 1;
} else {
return 0;
}
}
-static void draw_dm_creases(DerivedMesh *dm)
+static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
{
glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
glLineWidth(1.0);
}
static int draw_dm_bweights__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- if (eed->h==0 && eed->bweight!=0.0) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN) && eed->bweight!=0.0) {
UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
return 1;
} else {
@@ -1702,26 +1726,26 @@ static int draw_dm_bweights__setDrawOptions(void *userData, int index)
}
static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- EditVert *eve = EM_get_vert_for_index(index);
+ BMVert *eve = EDBM_get_vert_for_index(userData, index);
- if (eve->h==0 && eve->bweight!=0.0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN) && eve->bweight!=0.0) {
UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
bglVertex3fv(co);
}
}
-static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
+static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
{
ToolSettings *ts= scene->toolsettings;
if (ts->selectmode & SCE_SELECT_VERTEX) {
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
bglBegin(GL_POINTS);
- dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
+ dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
bglEnd();
}
else {
glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
glLineWidth(1.0);
}
}
@@ -1735,7 +1759,8 @@ static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
/* EditMesh drawing routines*/
-static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
+static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
+ BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
{
ToolSettings *ts= scene->toolsettings;
int sel;
@@ -1772,13 +1797,13 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
if(ts->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size);
glColor4ubv((GLubyte *)col);
- draw_dm_verts(cageDM, sel, eve_act);
+ draw_dm_verts(em, cageDM, sel, eve_act);
}
if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
glPointSize(fsize);
glColor4ubv((GLubyte *)fcol);
- draw_dm_face_centers(cageDM, sel);
+ draw_dm_face_centers(em, cageDM, sel);
}
if (pass==0) {
@@ -1792,7 +1817,9 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
glPointSize(1.0);
}
-static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
+static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
+ Mesh *me, DerivedMesh *cageDM, short sel_only,
+ BMEdge *eed_act)
{
ToolSettings *ts= scene->toolsettings;
int pass;
@@ -1825,21 +1852,21 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
}
if(ts->selectmode == SCE_SELECT_FACE) {
- draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
glShadeModel(GL_SMOOTH);
- draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
+ draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
glShadeModel(GL_FLAT);
} else {
- draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
}
else {
if (!sel_only) {
glColor4ubv(wireCol);
- draw_dm_edges(cageDM);
+ draw_dm_edges(em, cageDM);
}
}
@@ -1850,8 +1877,10 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
}
}
-static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em)
+static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
+ Object *ob, BMEditMesh *em)
{
+#if 0
Mesh *me= ob->data;
EditEdge *eed;
EditFace *efa;
@@ -2014,13 +2043,14 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
glEnable(GL_DEPTH_TEST);
bglPolygonOffset(rv3d->dist, 0.0);
}
+#endif
}
static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(userData, index);
- if (efa->h==0) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
GPU_enable_material(efa->mat_nr+1, NULL);
return 1;
}
@@ -2030,31 +2060,33 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth
static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(userData, index);
- return (efa->h==0);
+ return !BM_TestHFlag(efa, BM_HIDDEN);
}
-static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
+ BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+
{
Mesh *me = ob->data;
- EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
- EditEdge *eed_act = NULL;
- EditVert *eve_act = NULL;
+ BMFace *efa_act = EDBM_get_actFace(em, 0); /* annoying but active faces is stored differently */
+ BMEdge *eed_act = NULL;
+ BMVert *eve_act = NULL;
if (em->selected.last) {
- EditSelection *ese = em->selected.last;
+ BMEditSelection *ese = em->selected.last;
/* face is handeled above */
/*if (ese->type == EDITFACE ) {
efa_act = (EditFace *)ese->data;
} else */ if ( ese->type == EDITEDGE ) {
- eed_act = (EditEdge *)ese->data;
+ eed_act = (BMEdge *)ese->data;
} else if ( ese->type == EDITVERT ) {
- eve_act = (EditVert *)ese->data;
+ eve_act = (BMVert *)ese->data;
}
}
- EM_init_index_arrays(em, 1, 1, 1);
+ EDBM_init_index_arrays(em, 1, 1, 1);
if(dt>OB_WIRE) {
if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
@@ -2062,7 +2094,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
- draw_em_fancy__setGLSLFaceOpts, NULL);
+ draw_em_fancy__setGLSLFaceOpts, em);
GPU_disable_material();
glFrontFace(GL_CCW);
@@ -2077,7 +2109,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
- finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
+ finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, em, 0);
glFrontFace(GL_CCW);
glDisable(GL_LIGHTING);
@@ -2111,7 +2143,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
if CHECK_OB_DRAWTEXTURE(v3d, dt)
col1[3] = 0;
- draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2126,7 +2158,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glEnable(GL_BLEND);
glDepthMask(0); // disable write in zbuffer, needed for nice transp
- draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2138,14 +2170,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
/* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
/* only draw selected edges otherwise there is no way of telling if a face is selected */
- draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
+ draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
} else {
if(me->drawflag & ME_DRAWSEAMS) {
UI_ThemeColor(TH_EDGE_SEAM);
glLineWidth(2);
- draw_dm_edges_seams(cageDM);
+ draw_dm_edges_seams(em, cageDM);
glColor3ub(0,0,0);
glLineWidth(1);
@@ -2155,20 +2187,20 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
UI_ThemeColor(TH_EDGE_SHARP);
glLineWidth(2);
- draw_dm_edges_sharp(cageDM);
+ draw_dm_edges_sharp(em, cageDM);
glColor3ub(0,0,0);
glLineWidth(1);
}
if(me->drawflag & ME_DRAWCREASES) {
- draw_dm_creases(cageDM);
+ draw_dm_creases(em, cageDM);
}
if(me->drawflag & ME_DRAWBWEIGHTS) {
- draw_dm_bweights(scene, cageDM);
+ draw_dm_bweights(em, scene, cageDM);
}
- draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
+ draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
}
if(em) {
// XXX retopo_matrix_update(v3d);
@@ -2177,11 +2209,11 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
if(me->drawflag & ME_DRAWNORMALS) {
UI_ThemeColor(TH_NORMAL);
- draw_dm_face_normals(scene, cageDM);
+ draw_dm_face_normals(em, scene, cageDM);
}
if(me->drawflag & ME_DRAW_VNORMALS) {
UI_ThemeColor(TH_NORMAL);
- draw_dm_vert_normals(scene, cageDM);
+ draw_dm_vert_normals(em, scene, cageDM);
}
if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
@@ -2249,7 +2281,7 @@ static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
/* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
if(dt!=OB_SHADED)
@@ -2443,7 +2475,7 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
Object *ob= base->object;
Object *obedit= scene->obedit;
Mesh *me= ob->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
if(obedit && ob!=obedit && ob->data==obedit->data) {
@@ -2455,9 +2487,9 @@ static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base
DerivedMesh *finalDM, *cageDM;
if (obedit!=ob)
- finalDM = cageDM = editmesh_get_derived_base(ob, em);
+ finalDM = cageDM = editbmesh_get_derived_base(ob, em);
else
- cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
+ cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
v3d->customdata_mask);
if(dt>OB_WIRE) {
@@ -5432,44 +5464,49 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- int offset = (intptr_t) userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ void **ptrs = userData;
+ int offset = (intptr_t) ptrs[0];
+ BMVert *eve = EDBM_get_vert_for_index(ptrs[1], index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
WM_set_framebuffer_index_color(offset+index);
bglVertex3fv(co);
}
}
-static void bbs_mesh_verts(DerivedMesh *dm, int offset)
+static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
{
+ void *ptrs[2] = {(void*)(intptr_t) offset, em};
+
glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
bglBegin(GL_POINTS);
- dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
+ dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs);
bglEnd();
glPointSize(1.0);
}
static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
{
- int offset = (intptr_t) userData;
- EditEdge *eed = EM_get_edge_for_index(index);
+ void **ptrs = userData;
+ int offset = (intptr_t) ptrs[0];
+ BMEdge *eed = EDBM_get_edge_for_index(ptrs[1], index);
- if (eed->h==0) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
WM_set_framebuffer_index_color(offset+index);
return 1;
} else {
return 0;
}
}
-static void bbs_mesh_wire(DerivedMesh *dm, int offset)
+static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
+ void *ptrs[2] = {(void*)(intptr_t) offset, em};
+ dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs);
}
static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
{
- if (EM_get_face_for_index(index)->h==0) {
- if (userData) {
+ if (!BM_TestHFlag(EDBM_get_face_for_index(((void**)userData)[0], index), BM_HIDDEN)) {
+ if (((void**)userData)[1]) {
WM_set_framebuffer_index_color(index+1);
}
return 1;
@@ -5480,9 +5517,9 @@ static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *d
static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *no)
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index);
- if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
WM_set_framebuffer_index_color(index+1);
bglVertex3fv(cent);
@@ -5490,23 +5527,26 @@ static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, f
}
/* two options, facecolors or black */
-static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol)
+static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
+ Object *ob, DerivedMesh *dm, int facecol)
{
+ void *ptrs[2] = {em, NULL}; //second one being null means to draw black
cpack(0);
if (facecol) {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0);
+ ptrs[1] = (void*)(intptr_t) 1;
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0);
if( CHECK_OB_DRAWFACEDOT(scene, v3d, ob->dt) ) {
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
bglBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, ptrs);
bglEnd();
}
} else {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0);
}
}
@@ -5548,36 +5588,36 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
{
if(ob == scene->obedit) {
Mesh *me= ob->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
- DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+ DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
- EM_init_index_arrays(em, 1, 1, 1);
+ EDBM_init_index_arrays(em, 1, 1, 1);
- bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
+ bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
if(ts->selectmode & SCE_SELECT_FACE)
- em_solidoffs = 1+em->totface;
+ bm_solidoffs = 1+em->bm->totface;
else
- em_solidoffs= 1;
+ bm_solidoffs= 1;
bglPolygonOffset(rv3d->dist, 1.0);
// we draw edges always, for loop (select) tools
- bbs_mesh_wire(dm, em_solidoffs);
- em_wireoffs= em_solidoffs + em->totedge;
+ bbs_mesh_wire(em, dm, bm_solidoffs);
+ bm_wireoffs= bm_solidoffs + em->bm->totedge;
// we draw verts if vert select mode or if in transform (for snap).
if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
- bbs_mesh_verts(dm, em_wireoffs);
- em_vertoffs= em_wireoffs + em->totvert;
+ bbs_mesh_verts(em, dm, bm_wireoffs);
+ bm_vertoffs= bm_wireoffs + em->bm->totvert;
}
- else em_vertoffs= em_wireoffs;
+ else bm_vertoffs= bm_wireoffs;
bglPolygonOffset(rv3d->dist, 0.0);
dm->release(dm);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
else bbs_mesh_solid(scene, v3d, ob);
}
@@ -5603,7 +5643,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
int glsl;
if(ob == scene->obedit)
- edm= editmesh_get_derived_base(ob, me->edit_mesh);
+ edm= editbmesh_get_derived_base(ob, me->edit_btmesh);
else
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 7db577bf139..fcfc48eff84 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -69,6 +69,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
@@ -164,31 +165,30 @@ static void v3d_editvertex_buts(const bContext *C, uiBlock *block, View3D *v3d,
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve, *evedef=NULL;
- EditEdge *eed;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMVert *eve, *evedef=NULL;
+ BMEdge *eed;
+ BMIter iter;
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
evedef= eve;
tot++;
VecAddf(median, median, eve->co);
}
- eve= eve->next;
}
- eed= em->edges.first;
- while(eed) {
- if((eed->f & SELECT)) {
+
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
totedge++;
median[3]+= eed->crease;
}
- eed= eed->next;
}
/* check for defgroups */
if(evedef)
- dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
+ dvert= CustomData_bmesh_get(&em->bm->vdata, evedef->head.data, CD_MDEFORMVERT);
if(tot==1 && dvert && dvert->totweight) {
bDeformGroup *dg;
int i, max=1, init=1;
@@ -212,8 +212,6 @@ static void v3d_editvertex_buts(const bContext *C, uiBlock *block, View3D *v3d,
tfp->defweightp= &dvert->dw[0].weight;
}
}
-
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
Curve *cu= ob->data;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index e68a1c8a10a..51ba58b3020 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -64,6 +64,7 @@
#include "BKE_particle.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h" /* for VECCOPY */
+#include "BKE_tessmesh.h"
#include "ED_armature.h"
#include "ED_particle.h"
@@ -4012,11 +4013,11 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
Base *basact= CTX_data_active_base(C);
Object *ob= CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
int bit, ctrl= win->eventstate->ctrl, shift= win->eventstate->shift;
if(obedit && obedit->type==OB_MESH) {
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
}
/* watch it: if sa->win does not exist, check that when calling direct drawing routines */
@@ -4142,7 +4143,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
if(shift==0 || em->selectmode==0)
em->selectmode= SCE_SELECT_VERTEX;
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Vertex");
}
@@ -4151,12 +4152,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
if(em) {
if(shift==0 || em->selectmode==0){
if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){
- if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
+ if(ctrl) EDBM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
}
em->selectmode = SCE_SELECT_EDGE;
}
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Edge");
}
@@ -4165,12 +4166,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
if(em) {
if( shift==0 || em->selectmode==0){
if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
- if(ctrl) EM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+ if(ctrl) EDBM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
}
em->selectmode = SCE_SELECT_FACE;
}
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
ED_undo_push(C, "Selectmode Set: Face");
}
@@ -4253,9 +4254,6 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
}
break;
}
-
- if(obedit && obedit->type==OB_MESH)
- BKE_mesh_end_editmesh(obedit->data, em);
}
static void view3d_header_pulldowns(const bContext *C, uiBlock *block, Object *ob, int *xcoord, int yco)
@@ -4622,7 +4620,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* selection modus */
if(obedit && (obedit->type == OB_MESH)) {
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
uiBlockBeginAlign(block);
uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode (Ctrl Tab 1)");
@@ -4638,8 +4636,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
uiBlockEndAlign(block);
header_xco_step(ar, &xco, &yco, &maxco, XIC);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
else if(G.f & G_PARTICLEEDIT) {
uiBlockBeginAlign(block);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 112847272e5..32305b5c76b 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -203,7 +203,7 @@ void view3d_keymap(wmWindowManager *wm)
/* selection*/
WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
- RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", 1);
WM_keymap_add_item(keymap, "VIEW3D_OT_select_border", BKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT|KM_CTRL, 0)->ptr, "deselect", 1);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2537982210a..31ea1070b32 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -62,6 +62,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "RE_pipeline.h" // make_stars
@@ -78,10 +79,10 @@
#include "ED_particle.h"
#include "ED_mesh.h"
#include "ED_object.h"
-#include "ED_retopo.h"
#include "ED_screen.h"
#include "ED_types.h"
#include "ED_util.h"
+#include "ED_retopo.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -149,43 +150,49 @@ static void BIF_undo_push() {}
/* local prototypes */
-void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select)
+void EM_backbuf_checkAndSelectVerts(BMEditMesh *em, int select)
{
- EditVert *eve;
- int index= em_wireoffs;
+ BMVert *eve;
+ BMIter iter;
+ int index= bm_wireoffs;
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->h==0) {
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; eve; eve=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
if(EM_check_backbuf(index)) {
- eve->f = select?(eve->f|1):(eve->f&~1);
+ BM_Select_Vert(em->bm, eve, select);
}
}
}
}
-void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select)
+void EM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select)
{
- EditEdge *eed;
- int index= em_solidoffs;
+ BMEdge *eed;
+ BMIter iter;
+ int index= bm_solidoffs;
- for(eed= em->edges.first; eed; eed= eed->next, index++) {
- if(eed->h==0) {
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(eed, BM_HIDDEN)) {
if(EM_check_backbuf(index)) {
- EM_select_edge(eed, select);
+ BM_Select_Edge(em->bm, eed, select);
}
}
}
}
-void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
+void EM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select)
{
- EditFace *efa;
+ BMFace *efa;
+ BMIter iter;
int index= 1;
- for(efa= em->faces.first; efa; efa= efa->next, index++) {
- if(efa->h==0) {
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(efa, BM_HIDDEN)) {
if(EM_check_backbuf(index)) {
- EM_select_face_fgon(em, efa, select);
+ BM_Select_Face(em->bm, efa, select);
}
}
}
@@ -399,53 +406,52 @@ void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves)
}
}
-static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int index)
{
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select_Vert(data->vc.em->bm, eve, data->select);
}
}
-static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
{
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
- if (EM_check_backbuf(em_solidoffs+index)) {
+ if (EM_check_backbuf(bm_solidoffs+index)) {
if (data->pass==0) {
if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) &&
lasso_inside(data->mcords, data->moves, x0, y0) &&
lasso_inside(data->mcords, data->moves, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select_Edge(data->vc.em->bm, eed, data->select);
data->done = 1;
}
} else {
if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select_Edge(data->vc.em->bm, eed, data->select);
}
}
}
}
-static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int x, int y, int index)
{
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
- EM_select_face_fgon(data->vc.em, efa, data->select);
+ BM_Select_Face(data->vc.em->bm, efa, data->select);
}
}
static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select)
{
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data;
- ToolSettings *ts= vc->scene->toolsettings;
rcti rect;
int bbsel;
lasso_select_boundbox(&rect, mcords, moves);
/* set editmesh */
- vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+ vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
data.vc= *vc;
data.rect = &rect;
@@ -457,14 +463,14 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, select);
} else {
mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
@@ -476,7 +482,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, select);
} else {
@@ -485,7 +491,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
}
EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_selectmode_flush(vc->em);
}
#if 0
@@ -647,7 +653,7 @@ static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short m
if(me==NULL || me->mtface==NULL) return;
if(me->totface==0) return;
- em_vertoffs= me->totface+1; /* max index array */
+ bm_vertoffs= me->totface+1; /* max index array */
lasso_select_boundbox(&rect, mcords, moves);
EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -715,6 +721,12 @@ void view3d_lasso_select(bContext *C, ViewContext *vc, short mcords[][2], short
}
+static EnumPropertyItem lasso_select_types[] = {
+ {0, "SELECT", 0, "Select", ""},
+ {1, "DESELECT", 0, "Deselect", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
/* lasso operator gives properties, but since old code works
with short array we convert */
@@ -741,7 +753,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
/* setup view context for argument to callbacks */
view3d_set_viewcontext(C, &vc);
- select= !RNA_boolean_get(op->ptr, "deselect");
+ select= RNA_enum_is_equal(C, op->ptr, "type", "SELECT");
view3d_lasso_select(C, &vc, mcords, i, select);
return OPERATOR_FINISHED;
@@ -763,7 +775,7 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot)
ot->flag= OPTYPE_UNDO;
RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items.");
+ RNA_def_enum(ot->srna, "type", lasso_select_types, 0, "Type", "");
}
@@ -1236,43 +1248,47 @@ static void do_lattice_box_select(ViewContext *vc, rcti *rect, int select)
lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data);
}
-static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, int x, int y, int index)
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y)) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select_Vert(data->vc.em->bm, eve, data->select);
}
}
-static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
- if(EM_check_backbuf(em_solidoffs+index)) {
+ if(EM_check_backbuf(bm_solidoffs+index)) {
if (data->pass==0) {
if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select_Edge(data->vc.em->bm, eed, data->select);
data->done = 1;
}
} else {
if (edge_inside_rect(data->rect, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select_Edge(data->vc.em->bm, eed, data->select);
}
}
}
}
-static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+
+static void
+do_mesh_box_select__doSelectFace(void *userData, BMFace
+ *efa, int x, int y,
+ int index)
+
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y)) {
- EM_select_face_fgon(data->vc.em, efa, data->select);
+ BM_Select_Face(data->vc.em->bm, efa, data->select);
}
}
static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } data;
- ToolSettings *ts= vc->scene->toolsettings;
int bbsel;
data.vc= *vc;
@@ -1281,16 +1297,16 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
data.pass = 0;
data.done = 0;
- bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ bbsel= EDBM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, select);
} else {
mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
@@ -1302,7 +1318,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, select);
} else {
@@ -1312,7 +1328,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_selectmode_flush(vc->em);
}
static int view3d_borderselect_exec(bContext *C, wmOperator *op)
@@ -1351,7 +1367,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
if(obedit) {
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- vc.em= me->edit_mesh;
+ vc.em= me->edit_btmesh;
do_mesh_box_select(&vc, &rect, (val==LEFTMOUSE));
// if (EM_texFaceCheck())
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
@@ -1436,7 +1452,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
}
}
- ED_armature_sync_selection(arm->edbo);
}
else if(obedit->type==OB_LATTICE) {
do_lattice_box_select(&vc, &rect, val==LEFTMOUSE);
@@ -1522,6 +1537,11 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
/* *****************Selection Operators******************* */
+static EnumPropertyItem prop_select_types[] = {
+ {0, "EXCLUSIVE", 0, "Exclusive", ""},
+ {1, "EXTEND", 0, "Extend", ""},
+ {0, NULL, 0, NULL, NULL}
+};
/* ****** Border Select ****** */
void VIEW3D_OT_select_border(wmOperatorType *ot)
@@ -1547,7 +1567,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everyting first.");
+ RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", "");
}
/* ****** Mouse Select ****** */
@@ -1556,7 +1576,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Object *obedit= CTX_data_edit_object(C);
- short extend= RNA_boolean_get(op->ptr, "extend");
+ short extend= RNA_enum_is_equal(C, op->ptr, "type", "EXTEND");
view3d_operator_needs_opengl(C);
@@ -1594,44 +1614,43 @@ void VIEW3D_OT_select(wmOperatorType *ot)
ot->flag= OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everyting first.");
+ RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", "");
}
/* -------------------- circle select --------------------------------------------- */
-static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
+static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int index)
{
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
int mx = x - data->mval[0], my = y - data->mval[1];
float r = sqrt(mx*mx + my*my);
if (r<=data->radius) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select_Vert(data->vc->em->bm, eve, data->select);
}
}
-static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
{
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select_Edge(data->vc->em->bm, eed, data->select);
}
}
-static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
+static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int index)
{
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
int mx = x - data->mval[0], my = y - data->mval[1];
float r = sqrt(mx*mx + my*my);
if (r<=data->radius) {
- EM_select_face_fgon(data->vc->em, efa, data->select);
+ BM_Select_Face(data->vc->em->bm, efa, data->select);
}
}
static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
{
- ToolSettings *ts= vc->scene->toolsettings;
int bbsel;
if(vc->obedit==NULL && (FACESEL_PAINT_TEST)) {
@@ -1639,9 +1658,9 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
Mesh *me = ob?ob->data:NULL;
if (me) {
- em_vertoffs= me->totface+1; /* max index array */
+ bm_vertoffs= me->totface+1; /* max index array */
- bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE);
EM_free_backbuf();
@@ -1651,15 +1670,15 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
else {
struct {ViewContext *vc; short select, mval[2]; float radius; } data;
- bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
- vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+ bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
data.select = selecting;
data.mval[0] = mval[0];
data.mval[1] = mval[1];
data.radius = rad;
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) {
if(bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1667,7 +1686,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
}
- if(ts->selectmode & SCE_SELECT_EDGE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) {
if (bbsel) {
EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1675,7 +1694,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
}
- if(ts->selectmode & SCE_SELECT_FACE) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1684,7 +1703,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_selectmode_flush(vc->em);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index fba8d13c6a5..98980548b86 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: view3d_snap.c 18967 2009-02-14 13:07:09Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -66,6 +66,7 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -110,7 +111,7 @@ static void special_transvert_update(Scene *scene, Object *obedit)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- recalc_editnormals(me->edit_mesh); // does face centers too
+ BM_Compute_Normals(me->edit_btmesh->bm); // does face centers too
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu= obedit->data;
@@ -178,7 +179,8 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
BPoint *bp;
TransVert *tv=NULL;
MetaElem *ml;
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
EditBone *ebo;
float total, center[3], centroid[3];
int a;
@@ -190,45 +192,70 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
+ BMesh *bm = em->bm;
int proptrans= 0;
// transform now requires awareness for select mode, so we tag the f1 flags in verts
tottrans= 0;
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0 && (eve->f & SELECT)) {
- eve->f1= SELECT;
+ if(em->bm->selectmode & SCE_SELECT_VERTEX) {
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
+ BMINDEX_SET(eve, 1);
tottrans++;
}
- else eve->f1= 0;
+ else BMINDEX_SET(eve, 0);
}
}
- else if(em->selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
+ else if(em->bm->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter))
+ BMINDEX_SET(eve, 0);
+
+ eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for (; eed; eed=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT))
+ BMINDEX_SET(eed->v1, 0), BMINDEX_SET(eed->v2, 0);
}
- for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter))
+ if(BMINDEX_GET(eve)) tottrans++;
}
else {
- EditFace *efa;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && (efa->f & SELECT)) {
- efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
- if(efa->v4) efa->v4->f1= SELECT;
+ BMFace *efa;
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter))
+ BMINDEX_SET(eve, 0);
+
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for (; efa; efa=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
+ BMIter liter;
+ BMLoop *l;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&iter)) {
+ BMINDEX_SET(l->v, 1);
+ }
}
}
- for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter))
+ if(BMINDEX_GET(eve)) tottrans++;
}
/* proportional edit exception... */
if((mode & 1) && tottrans) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- eve->f1 |= 2;
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter)) {
+ if(BMINDEX_GET(eve)) tottrans++;
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ BMINDEX_SET(eve, BMINDEX_GET(eve)|2);
proptrans++;
}
}
@@ -239,13 +266,14 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
if(tottrans) {
tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f1) {
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (; eve; eve=BMIter_Step(&iter)) {
+ if(BMINDEX_GET(eve)) {
VECCOPY(tv->oldloc, eve->co);
tv->loc= eve->co;
if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
tv->nor= eve->no; // note this is a hackish signal (ton)
- tv->flag= eve->f1 & SELECT;
+ tv->flag= BMINDEX_GET(eve) & SELECT;
tv++;
}
}
@@ -846,10 +874,10 @@ static int snap_curs_to_active(bContext *C, wmOperator *op)
if (obedit->type == OB_MESH) {
/* check active */
Mesh *me= obedit->data;
- EditSelection ese;
+ BMEditSelection ese;
- if (EM_get_actSelection(me->edit_mesh, &ese)) {
- EM_editselection_center(curs, &ese);
+ if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
+ EDBM_editselection_center(me->edit_btmesh, curs, &ese);
}
Mat4MulVecfl(obedit->obmat, curs);
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index b2dee8c3358..8501a95b981 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -6,6 +6,6 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include #/intern/guardedalloc'
-incs += ' ../../gpu ../../makesrna'
+incs += ' ../../gpu ../../makesrna ../../bmesh'
env.BlenderLib ( 'bf_editors_transform', sources, Split(incs), [], libtype=['core'], priority=[40] ) \ No newline at end of file
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index d45a6f42232..c62ea07e398 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1170,7 +1170,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if (RNA_struct_find_property(op->ptr, "constraint_axis"))
{
- RNA_int_set(op->ptr, "constraint_orientation", t->current_orientation);
+ RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation);
if (t->con.mode & CON_APPLY)
{
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 3d643a2dec1..aeccaee070e 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -100,6 +100,7 @@
#include "BKE_bmesh.h"
#include "BKE_context.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
//#include "BIF_editview.h"
//#include "BIF_editlattice.h"
@@ -149,6 +150,7 @@
extern ListBase editelems;
#include "transform.h"
+#include "bmesh.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -1883,22 +1885,31 @@ static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *v
}
/* loop-in-a-loop I know, but we need it! (ton) */
-static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
+ static void get_face_center(float *centout, BMesh *bm, BMVert *eve)
+
{
- EditFace *efa;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter;
+ float cent[3] = {0.0, 0.0, 0.0};
- for(efa= em->faces.first; efa; efa= efa->next)
- if(efa->f & SELECT)
- if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
- break;
- if(efa) {
- VECCOPY(cent, efa->cent);
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_VERT, eve);
+ if (efa) {
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for ( ; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, l->v->co);
+ }
+
+ VECMUL(cent, 1.0f / (float)efa->len);
}
+
+ if (cent[0] == 0.0f && cent[1] == 0.0f && cent[2] == 0.0f) cent[2] = 1.0f;
+ VECCOPY(centout, cent);
}
//way to overwrite what data is edited with transform
//static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
-static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
+static void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve)
{
td->flag = 0;
//if(key)
@@ -1965,13 +1976,13 @@ static float *get_crazy_mapped_editverts(TransInfo *t)
/* disable subsurf temporal, get mapped cos, and enable it */
if(modifiers_disable_subsurf_temporary(t->obedit)) {
/* need to make new derivemesh */
- makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
+ makeDerivedMesh(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH);
}
/* now get the cage */
- dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
+ dm= editbmesh_get_derived_cage(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH);
- vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map");
+ vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map");
dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
dm->release(dm);
@@ -2000,17 +2011,18 @@ static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3,
}
#undef TAN_MAKE_VEC
-static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
+static void set_crazyspace_quats(BMEditMesh *em, float *origcos, float *mappedcos, float *quats)
{
- EditVert *eve, *prev;
- EditFace *efa;
+#if 0
+ BMVert *eve, *prev;
+ BMFace *efa;
float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
intptr_t index= 0;
/* two abused locations in vertices */
for(eve= em->verts.first; eve; eve= eve->next, index++) {
eve->tmp.p = NULL;
- eve->prev= (EditVert *)index;
+ eve->prev= (BMVert *)index;
}
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
@@ -2068,7 +2080,7 @@ static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos,
/* restore abused prev pointer */
for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
eve->prev= prev;
-
+#endif
}
void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
@@ -2100,10 +2112,12 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
{
ToolSettings *ts = CTX_data_tool_settings(C);
TransData *tob = NULL;
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
- EditVert *eve;
- EditVert **nears = NULL;
- EditVert *eve_act = NULL;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMVert **nears = NULL;
+ BMIter iter;
+ BMVert *eve_act = NULL;
float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
int count=0, countsel=0, a, totleft;
@@ -2117,36 +2131,49 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
// transform now requires awareness for select mode, so we tag the f1 flags in verts
if(ts->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0 && (eve->f & SELECT))
- eve->f1= SELECT;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT))
+ BMINDEX_SET(eve, SELECT);
else
- eve->f1= 0;
+ BMINDEX_SET(eve, 0);
}
}
else if(ts->selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT))
- eed->v1->f1= eed->v2->f1= SELECT;
+ BMEdge *eed;
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) BMINDEX_SET(eve, 0);
+
+ eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for( ; eed; eed=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT))
+ BMINDEX_SET(eed->v1, SELECT), BMINDEX_SET(eed->v2, SELECT);
}
}
else {
- EditFace *efa;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && (efa->f & SELECT)) {
- efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
- if(efa->v4) efa->v4->f1= SELECT;
+ BMFace *efa;
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) BMINDEX_SET(eve, 0);
+
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for( ; efa; efa=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
+ BMIter liter;
+ BMLoop *l;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ BMINDEX_SET(l->v, SELECT);
+ }
}
}
}
/* now we can count */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- if(eve->f1) countsel++;
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(BMINDEX_GET(eve)) countsel++;
if(propmode) count++;
}
}
@@ -2156,9 +2183,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
/* check active */
if (em->selected.last) {
- EditSelection *ese = em->selected.last;
+ BMEditSelection *ese = em->selected.last;
if ( ese->type == EDITVERT ) {
- eve_act = (EditVert *)ese->data;
+ eve_act = (BMVert *)ese->data;
}
}
@@ -2168,7 +2195,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
/* allocating scratch arrays */
vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
- nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
+ nears = (BMVert**)MEM_mallocN(t->total * sizeof(BMVert*), "scratch nears");
}
else t->total = countsel;
tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
@@ -2176,7 +2203,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
Mat3CpyMat4(mtx, t->obedit->obmat);
Mat3Inv(smtx, mtx);
- if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
+ //BMESH_TODO if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
/* detect CrazySpace [tm] */
if(propmode==0) {
@@ -2184,7 +2211,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
if(modifiers_isDeformed(t->scene, t->obedit)) {
/* check if we can use deform matrices for modifier from the
start up to stack, they are more accurate than quats */
- totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
+ totleft= editbmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
/* if we still have more modifiers, also do crazyspace
correction with quats, relative to the coordinates after
@@ -2205,8 +2232,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
/* find out which half we do */
if(mirror) {
- for (eve=em->verts.first; eve; eve=eve->next) {
- if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BMINDEX_GET(eve) && eve->co[0]!=0.0f) {
if(eve->co[0]<0.0f)
mirror = -1;
break;
@@ -2214,36 +2242,41 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
}
- for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
- if(eve->h==0) {
- if(propmode || eve->f1) {
- VertsToTransData(t, tob, em, eve);
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(propmode || BMINDEX_GET(eve)) {
+ VertsToTransData(t, tob, bm, eve);
/* selected */
- if(eve->f1) tob->flag |= TD_SELECTED;
+ if(BMINDEX_GET(eve)) tob->flag |= TD_SELECTED;
/* active */
if(eve == eve_act) tob->flag |= TD_ACTIVE;
if(propmode) {
+ /*BMESH_TODO
+ this has to do with edge connectivity
+ PEP mode, I think. -joeedh
if (eve->f2) {
float vec[3];
VECCOPY(vec, E_VEC(eve));
Mat3MulVecfl(mtx, vec);
tob->dist= VecLength(vec);
}
- else {
+ else {*/
tob->flag |= TD_NOTCONNECTED;
tob->dist = MAXFLOAT;
- }
+ //}
}
/* CrazySpace */
- if(defmats || (quats && eve->tmp.p)) {
+ if(defmats) { // || (quats && eve->tmp.p)) {
float mat[3][3], imat[3][3], qmat[3][3];
/* use both or either quat and defmat correction */
- if(quats && eve->tmp.f) {
+ //BMESH_TODO, need to restore this quats thing
+ /*if(quats && eve->tmp.f) {
QuatToMat3(eve->tmp.p, qmat);
if(defmats)
@@ -2252,7 +2285,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
else
Mat3MulMat3(mat, mtx, qmat);
}
- else
+ else*/
Mat3MulMat3(mat, mtx, defmats[a]);
Mat3Inv(imat, mat);
@@ -2266,10 +2299,12 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
/* Mirror? */
- if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
- EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
- if(vmir != eve) tob->extra = vmir;
- }
+
+ //BMESH_TODO
+ //if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
+ // EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
+ // if(vmir != eve) tob->extra = vmir;
+ //}
tob++;
}
}
@@ -2416,6 +2451,7 @@ static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, f
static void createTransUVs(bContext *C, TransInfo *t)
{
+#if 0
SpaceImage *sima = (SpaceImage*)CTX_wm_space_data(C);
Image *ima = CTX_data_edit_image(C);
Scene *scene = CTX_data_scene(C);
@@ -2482,6 +2518,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
if (sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
+#endif
}
void flushTransUVs(TransInfo *t)
@@ -4856,7 +4893,7 @@ void special_aftertrans_update(TransInfo *t)
if (t->obedit->type == OB_MESH)
{
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
/* table needs to be created for each edit command, since vertices can move etc */
mesh_octree_table(t->obedit, em, NULL, 'e');
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 560b37caf0a..3fc9fe73a5b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -83,6 +83,7 @@
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -241,10 +242,11 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
}
/* assumes obedit set to mesh object */
-static void editmesh_apply_to_mirror(TransInfo *t)
+static void editbmesh_apply_to_mirror(TransInfo *t)
{
TransData *td = t->data;
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
int i;
for(i = 0 ; i < t->total; i++, td++) {
@@ -607,7 +609,7 @@ void recalcData(TransInfo *t)
DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA);
} else {
- EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
+ BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
/* mirror modifier clipping? */
if(t->state != TRANS_CANCEL) {
/* TRANSFORM_FIX_ME */
@@ -618,11 +620,12 @@ void recalcData(TransInfo *t)
clipMirrorModifier(t, t->obedit);
}
if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
- editmesh_apply_to_mirror(t);
+ editbmesh_apply_to_mirror(t);
DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
- recalc_editnormals(em);
+ EDBM_RecalcNormals(em);
+ BMEdit_RecalcTesselation(em);
}
}
else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
@@ -886,7 +889,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
if (op && RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_orientation"))
{
- t->current_orientation = RNA_int_get(op->ptr, "constraint_orientation");
+ t->current_orientation = RNA_enum_get(op->ptr, "constraint_orientation");
if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C) - 1)
{
@@ -1018,8 +1021,7 @@ void postTrans (TransInfo *t)
else if(ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
if (t->customData)
MEM_freeN(t->customData);
- }
-}
+ }}
void applyTransObjects(TransInfo *t)
{
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index c656b097cb9..bf87319d05c 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -63,6 +63,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
@@ -204,20 +205,22 @@ int calc_manipulator_stats(const bContext *C)
if((ob->lay & v3d->lay)==0) return 0;
if(obedit->type==OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
- EditVert *eve;
- EditSelection ese;
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMEditSelection ese;
+ BMIter iter;
float vec[3]= {0,0,0};
/* USE LAST SELECTE WITH ACTIVE */
- if (v3d->around==V3D_ACTIVE && EM_get_actSelection(em, &ese)) {
- EM_editselection_center(vec, &ese);
+ if (v3d->around==V3D_ACTIVE && EDBM_get_actSelection(em, &ese)) {
+ EDBM_editselection_center(em, vec, &ese);
calc_tw_center(scene, vec);
totsel= 1;
} else {
/* do vertices for center, and if still no normal found, use vertex normals */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
totsel++;
calc_tw_center(scene, eve->co);
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index f2630f40c9c..2fc3d2f1e53 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -81,6 +81,13 @@ EnumPropertyItem proportional_falloff_types[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem orientation_items[]= {
+ {V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", ""},
+ {V3D_MANIP_NORMAL, "NORMAL", 0, "Normal", ""},
+ {V3D_MANIP_LOCAL, "LOCAL", 0, "Local", ""},
+ {V3D_MANIP_VIEW, "VIEW", 0, "View", ""},
+ {0, NULL, 0, NULL, NULL}};
+
char OP_TRANSLATION[] = "TFM_OT_translation";
char OP_ROTATION[] = "TFM_OT_rotation";
char OP_TOSPHERE[] = "TFM_OT_tosphere";
@@ -137,12 +144,6 @@ static EnumPropertyItem *select_orientation_itemf(bContext *C, PointerRNA *ptr,
void TFM_OT_select_orientation(struct wmOperatorType *ot)
{
PropertyRNA *prop;
- static EnumPropertyItem orientation_items[]= {
- {V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", ""},
- {V3D_MANIP_NORMAL, "NORMAL", 0, "Normal", ""},
- {V3D_MANIP_LOCAL, "LOCAL", 0, "Local", ""},
- {V3D_MANIP_VIEW, "VIEW", 0, "View", ""},
- {0, NULL, 0, NULL, NULL}};
/* identifiers */
ot->name = "Select Orientation";
@@ -293,8 +294,11 @@ void Properties_Snapping(struct wmOperatorType *ot, short align)
void Properties_Constraints(struct wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
- RNA_def_int(ot->srna, "constraint_orientation", 0, 0, INT_MAX, "Constraint Orientation", "", 0, INT_MAX);
+ prop= RNA_def_enum(ot->srna, "constraint_orientation", orientation_items, V3D_MANIP_GLOBAL, "Orientation", "DOC_BROKEN");
+ RNA_def_enum_funcs(prop, select_orientation_itemf);
}
void TFM_OT_translation(struct wmOperatorType *ot)
@@ -557,9 +561,8 @@ void TFM_OT_transform(struct wmOperatorType *ot)
Properties_Proportional(ot);
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
-
- RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
- RNA_def_int(ot->srna, "constraint_orientation", 0, 0, INT_MAX, "Constraint Orientation", "", 0, INT_MAX);
+
+ Properties_Constraints(ot);
}
void transform_operatortypes(void)
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 6d60c7602f4..6cda535516e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -43,6 +43,7 @@
#include "BKE_utildefines.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@@ -590,16 +591,16 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
if(ob->type==OB_MESH)
{
Mesh *me= ob->data;
- EditMesh *em = me->edit_mesh;
- EditVert *eve;
- EditSelection ese;
+ BMEditMesh *em = me->edit_btmesh;
+ BMVert *eve;
+ BMEditSelection ese;
float vec[3]= {0,0,0};
/* USE LAST SELECTED WITH ACTIVE */
- if (activeOnly && EM_get_actSelection(em, &ese))
+ if (activeOnly && EDBM_get_actSelection(em, &ese))
{
- EM_editselection_normal(normal, &ese);
- EM_editselection_plane(plane, &ese);
+ EDBM_editselection_normal(normal, &ese);
+ EDBM_editselection_plane(em, plane, &ese);
switch (ese.type)
{
@@ -616,30 +617,30 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
else
{
- if (em->totfacesel >= 1)
+ if (em->bm->totfacesel >= 1)
{
- EditFace *efa;
-
- for(efa= em->faces.first; efa; efa= efa->next)
- {
- if(efa->f & SELECT)
- {
- VECADD(normal, normal, efa->n);
- VecSubf(vec, efa->v2->co, efa->v1->co);
+ BMFace *efa;
+ BMIter iter;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_TestHFlag(efa, BM_SELECT)) {
+ VECADD(normal, normal, efa->no);
+ VecSubf(vec, efa->loopbase->v->co,
+ ((BMLoop*)efa->loopbase->head.next)->v->co);
VECADD(plane, plane, vec);
}
}
result = ORIENTATION_FACE;
}
- else if (em->totvertsel == 3)
+ else if (em->bm->totvertsel == 3)
{
- EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
+ BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
+ BMIter iter;
float cotangent[3];
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
if (v1 == NULL) {
v1 = eve;
}
@@ -658,12 +659,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
/* if there's an edge available, use that for the tangent */
- if (em->totedgesel >= 1)
+ if (em->bm->totedgesel >= 1)
{
- EditEdge *eed = NULL;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
+ BMEdge *eed = NULL;
+ BMIter iter;
+
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
VecSubf(plane, eed->v2->co, eed->v1->co);
break;
}
@@ -672,12 +674,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
result = ORIENTATION_FACE;
}
- else if (em->totedgesel == 1)
+ else if (em->bm->totedgesel == 1)
{
- EditEdge *eed;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
+ BMEdge *eed = NULL;
+ BMIter iter;
+
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
/* use average vert normals as plane and edge vector as normal */
VECCOPY(plane, eed->v1->no);
VECADD(plane, plane, eed->v2->no);
@@ -687,13 +690,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
result = ORIENTATION_EDGE;
}
- else if (em->totvertsel == 2)
+ else if (em->bm->totvertsel == 2)
{
- EditVert *v1 = NULL, *v2 = NULL;
-
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMIter iter;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
if (v1 == NULL) {
v1 = eve;
}
@@ -709,24 +712,25 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
result = ORIENTATION_EDGE;
}
- else if (em->totvertsel == 1)
+ else if (em->bm->totvertsel == 1)
{
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BMIter iter;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
VECCOPY(normal, eve->no);
break;
}
}
result = ORIENTATION_VERT;
}
- else if (em->totvertsel > 3)
+ else if (em->bm->totvertsel > 3)
{
+ BMIter iter;
normal[0] = normal[1] = normal[2] = 0;
-
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
VecAddf(normal, normal, eve->no);
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 9438581409b..575e8f2150a 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -69,6 +69,8 @@
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
+#include "BKE_mesh.h"
#include "ED_armature.h"
#include "ED_image.h"
@@ -1109,11 +1111,11 @@ int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float
return retval;
}
-int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
+int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
if (totvert > 0) {
float imat[4][4];
@@ -1148,19 +1150,19 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
case SCE_SNAP_MODE_FACE:
{
MVert *verts = dm->getVertArray(dm);
- MFace *faces = dm->getFaceArray(dm);
+ MFace *faces = dm->getTessFaceArray(dm);
int *index_array = NULL;
int index = 0;
int i;
if (em != NULL)
{
- index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 0, 0, 1);
+ index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ EDBM_init_index_arrays(em, 0, 0, 1);
}
for( i = 0; i < totface; i++) {
- EditFace *efa = NULL;
+ BMFace *efa = NULL;
MFace *f = faces + i;
test = 1; /* reset for every face */
@@ -1182,11 +1184,22 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
}
else
{
- efa = EM_get_face_for_index(index);
+ efa = EDBM_get_face_for_index(em, index);
- if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT)))
+ if (efa && BM_TestHFlag(efa, BM_HIDDEN))
{
test = 0;
+ } else if (efa) {
+ BMIter iter;
+ BMLoop *l;
+
+ l = BMIter_New(&iter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for ( ; l; l=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ test = 0;
+ break;
+ }
+ }
}
}
}
@@ -1214,7 +1227,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
break;
}
@@ -1228,11 +1241,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
if (em != NULL)
{
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 1, 0, 0);
+ EDBM_init_index_arrays(em, 1, 0, 0);
}
for( i = 0; i < totvert; i++) {
- EditVert *eve = NULL;
+ BMVert *eve = NULL;
MVert *v = verts + i;
test = 1; /* reset for every vert */
@@ -1254,9 +1267,9 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
}
else
{
- eve = EM_get_vert_for_index(index);
+ eve = EDBM_get_vert_for_index(em, index);
- if (eve && (eve->h || (eve->f & SELECT)))
+ if (eve && (BM_TestHFlag(eve, BM_HIDDEN) || BM_TestHFlag(eve, BM_SELECT)))
{
test = 0;
}
@@ -1272,7 +1285,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
break;
}
@@ -1288,11 +1301,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
if (em != NULL)
{
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 0, 1, 0);
+ EDBM_init_index_arrays(em, 0, 1, 0);
}
for( i = 0; i < totedge; i++) {
- EditEdge *eed = NULL;
+ BMEdge *eed = NULL;
MEdge *e = edges + i;
test = 1; /* reset for every vert */
@@ -1314,9 +1327,11 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
}
else
{
- eed = EM_get_edge_for_index(index);
+ eed = EDBM_get_edge_for_index(em, index);
- if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT)))
+ if (eed && (BM_TestHFlag(eed, BM_HIDDEN) ||
+ BM_TestHFlag(eed->v1, BM_SELECT) ||
+ BM_TestHFlag(eed->v2, BM_SELECT)))
{
test = 0;
}
@@ -1332,7 +1347,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
break;
}
@@ -1349,13 +1364,13 @@ int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obma
int retval = 0;
if (ob->type == OB_MESH) {
- EditMesh *em;
+ BMEditMesh *em;
DerivedMesh *dm;
if (editobject)
{
- em = ((Mesh *)ob->data)->edit_mesh;
- dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+ em = ((Mesh *)ob->data)->edit_btmesh;
+ dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
}
else
{
@@ -1491,7 +1506,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
if (totvert > 0) {
float imat[4][4];
@@ -1521,7 +1536,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
if (test == 1) {
MVert *verts = dm->getVertArray(dm);
- MFace *faces = dm->getFaceArray(dm);
+ MFace *faces = dm->getTessFaceArray(dm);
int i;
for( i = 0; i < totface; i++) {
@@ -1617,6 +1632,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
Object *ob = dupli_ob->ob;
if (ob->type == OB_MESH) {
+#if 0 //BMESH_TODO
EditMesh *em;
DerivedMesh *dm = NULL;
int val;
@@ -1638,6 +1654,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
retval = retval || val;
dm->release(dm);
+#endif
}
}
@@ -1645,7 +1662,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
}
if (ob->type == OB_MESH) {
- EditMesh *em;
+ BMEditMesh *em;
DerivedMesh *dm = NULL;
int val;
@@ -1657,8 +1674,8 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
}
else
{
- em = ((Mesh *)ob->data)->edit_mesh;
- dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
+ em = ((Mesh *)ob->data)->edit_btmesh;
+ dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
}
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index ae1e932bb81..93760ab77e3 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -72,10 +72,10 @@ void ED_editors_exit(bContext *C)
if(ob) {
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- if(me->edit_mesh) {
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ if(me->edit_btmesh) {
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
}
}
else if(ob->type==OB_ARMATURE) {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index a58ee9772e9..0a747c951f5 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -41,6 +41,7 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
@@ -452,7 +453,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* first try existing derivedmesh */
if(!draw_uvs_dm_shadow(em->derivedFinal)) {
/* create one if it does not exist */
- cagedm = editmesh_get_derived_cage_and_final(scene, obedit, em, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
+ cagedm = editbmesh_get_derived_cage_and_final(scene, obedit, me->edit_btmesh, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
/* when sync selection is enabled, all faces are drawn (except for hidden)
* so if cage is the same as the final, theres no point in drawing this */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 801da08e611..6f8d710ed3e 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1374,7 +1374,7 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
ima= CTX_data_edit_image(C);
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_toggle_select_all(em);
+ EDBM_toggle_select_all(((Mesh*)obedit->data)->edit_btmesh);
}
else {
sel= 0;
@@ -2172,7 +2172,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
-
+
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -2706,6 +2706,7 @@ static int hide_exec(bContext *C, wmOperator *op)
EM_hide_mesh(em, swap);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 18c18d9e9dd..98cf7379df9 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -76,7 +76,9 @@ typedef struct CustomData {
#define CD_TANGENT 18
#define CD_MDISPS 19
#define CD_WEIGHT_MCOL 20 /* for displaying weightpaint colors */
-#define CD_NUMTYPES 21
+#define CD_MPOLY 21
+#define CD_MLOOP 22
+#define CD_NUMTYPES 23
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@@ -100,6 +102,8 @@ typedef struct CustomData {
#define CD_MASK_TANGENT (1 << CD_TANGENT)
#define CD_MASK_MDISPS (1 << CD_MDISPS)
#define CD_MASK_WEIGHT_MCOL (1 << CD_WEIGHT_MCOL)
+#define CD_MASK_MPOLY (1 << CD_MPOLY)
+#define CD_MASK_MLOOP (1 << CD_MLOOP)
/* derivedmesh wants CustomDataMask for weightpaint too, is not customdata though */
#define CD_MASK_WEIGHTPAINT (1 << CD_WEIGHTPAINT)
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 3ecfe416c79..01c009a7971 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -44,6 +44,11 @@ struct MCol;
struct MSticky;
struct Mesh;
struct OcInfo;
+struct MPoly;
+struct MTexPoly;
+struct MLoop;
+struct MLoopUV;
+struct MLoopCol;
struct Multires;
struct PartialVisibility;
struct EditMesh;
@@ -58,23 +63,35 @@ typedef struct Mesh {
struct Ipo *ipo;
struct Key *key;
struct Material **mat;
-
- struct MFace *mface; /* array of mesh object mode faces */
- struct MTFace *mtface; /* store face UV's and texture here */
+
+ /*new face structures*/
+ struct MPoly *mpoly;
+ struct MTexPoly *mtpoly;
+ struct MLoop *mloop;
+ struct MLoopUV *mloopuv;
+ struct MLoopCol *mloopcol;
+
+ /*mface stores the tesselation (triangulation) of the mesh,
+ real faces are now stored in nface.*/
+ struct MFace *mface; /* array of mesh object mode faces for tesselation */
+ struct MTFace *mtface; /* store tesselation face UV's and texture here */
struct TFace *tface; /* depecrated, use mtface */
struct MVert *mvert; /* array of verts */
struct MEdge *medge; /* array of edges */
struct MDeformVert *dvert; /* deformgroup vertices */
- struct MCol *mcol; /* array of colors, this must be the number of faces * 4 */
+
+ /* array of colors for the tesselated faces, must be number of tesselated
+ faces * 4 in length */
+ struct MCol *mcol;
struct MSticky *msticky;
struct Mesh *texcomesh;
struct MSelect *mselect;
- struct EditMesh *edit_mesh; /* not saved in file! */
+ struct BMEditMesh *edit_btmesh; /* not saved in file! */
- struct CustomData vdata, edata, fdata;
+ struct CustomData vdata, edata, fdata, pdata, ldata;
- int totvert, totedge, totface, totselect;
+ int totvert, totedge, totface, totpoly, totloop, totselect;
/* the last selected vertex/edge/face are used for the active face however
* this means the active face must always be selected, this is to keep track
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index d53a7833d0e..94713cf0d76 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -71,7 +71,22 @@ typedef struct MCol {
char a, r, g, b;
} MCol;
-/*bmesh custom data stuff*/
+/*new face structure, replaces MFace, which is now
+ only used for storing tesselations.*/
+typedef struct MPoly {
+ /*offset into loop array and number of loops in the face*/
+ int loopstart, totloop;
+ short mat_nr;
+ short flag;
+} MPoly;
+
+/*the e here is because we want to move away from
+ relying on edge hashes.*/
+typedef struct MLoop {
+ int v; /*vertex index*/
+ int e; /*edge index*/
+} MLoop;
+
typedef struct MTexPoly{
struct Image *tpage;
char flag, transp;
@@ -217,7 +232,9 @@ typedef struct PartialVisibility {
/* flag (mface) */
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
- /* flag ME_HIDE==16 is used here too */
+/* flag ME_HIDE==16 is used here too */
+#define ME_DRAW_ACT 4
+
/* mselect->type */
#define ME_VSEl 0
#define ME_ESEl 1
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 2b0ede846af..93980e58f8c 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -116,7 +116,7 @@ typedef struct Object {
/* materials */
struct Material **mat; /* material slots */
- char *matbits; /* 1 if material linked to object */
+ char *matbits; /* a bitfield, with each bit 1 if corrusponding material linked to object */
int totcol; /* copy of mesh or curve or meta */
int actcol; /* currently selected material in the UI */
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index 1c716019e80..29d57f095e7 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -46,21 +46,25 @@ targetdir = normpath(root_build_dir + '/makesdna')
if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
targetdir = '#' + targetdir
+ #root_build_dir = "#"
makesdna = makesdna_tool.Program (target = targetdir, source = source_files, LIBS=['bf_guardedalloc'])
dna_dict = dna.Dictionary()
dna.Depends ('dna.c', makesdna)
dna.Depends ('dna.c', header_files)
+
+ap = os.path.abspath
+
if env['OURPLATFORM'] != 'linuxcross':
if USE_WINE:
- dna.Command ('dna.c', '', 'wine ' + root_build_dir+os.sep+"makesdna $TARGET")
+ dna.Command ('dna.c', '', 'wine ' + ap(root_build_dir+os.sep+"makesdna $TARGET"))
else:
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
dna.Command ('dna.c', '', "\"" + root_build_dir+os.sep+"makesdna\" $TARGET")
else:
dna.Command ('dna.c', '', root_build_dir+os.sep+"makesdna $TARGET")
else:
- dna.Command ('dna.c', '', root_build_dir+os.sep+"makesdna.exe $TARGET")
+ dna.Command ('dna.c', '', ap(root_build_dir+os.sep+"makesdna.exe $TARGET"))
obj = ['intern/dna.c', 'intern/dna_genfile.c']
Return ('obj')
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 89118850b20..2a1ae7be543 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -7,7 +7,7 @@ o = SConscript('intern/SConscript')
objs += o
incs = '#/intern/guardedalloc ../blenkernel ../blenlib ../makesdna intern .'
-incs += ' ../windowmanager ../editors/include ../imbuf'
+incs += ' ../windowmanager ../editors/include ../imbuf ../bmesh'
defs = []
diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile
index 7f9bfbfea67..4a3715fb9a9 100644
--- a/source/blender/makesrna/intern/Makefile
+++ b/source/blender/makesrna/intern/Makefile
@@ -52,6 +52,7 @@ CPPFLAGS += -I../../imbuf
CPPFLAGS += -I../../makesdna
CPPFLAGS += -I../../windowmanager
CPPFLAGS += -I../../editors/include
+CPPFLAGS += -I../../bmesh
CPPFLAGS += -I..
CPPFLAGS += -I.
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index 7cd3fde21be..53243fd97a0 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -29,7 +29,7 @@ makesrna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesrna/\\"" '
defs = []
-incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel'
+incs = '#/intern/guardedalloc ../../bmesh ../../blenlib ../../blenkernel'
incs += ' ../../imbuf ../../makesdna ../../makesrna'
incs += ' ../../windowmanager ../../editors/include'
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
deleted file mode 100644
index 6d56b2b00f9..00000000000
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#ifdef RNA_RUNTIME
-
-#include "BKE_main.h"
-#include "BKE_mesh.h"
-#include "BKE_library.h"
-
-#include "DNA_mesh_types.h"
-
-Mesh *rna_Main_add_mesh(Main *main, char *name)
-{
- Mesh *me= add_mesh(name);
- me->id.us--;
- return me;
-}
-
-void rna_Main_remove_mesh(Main *main, ReportList *reports, Mesh *me)
-{
- if(me->id.us == 0)
- free_libblock(&main->mesh, me);
- else
- BKE_report(reports, RPT_ERROR, "Mesh must have zero users to be removed.");
-
- /* XXX python now has invalid pointer? */
-}
-
-#else
-
-void RNA_api_main(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *prop;
-
- func= RNA_def_function(srna, "add_mesh", "rna_Main_add_mesh");
- RNA_def_function_ui_description(func, "Add a new mesh.");
- prop= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock.");
- prop= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh.");
- RNA_def_function_return(func, prop);
-
- func= RNA_def_function(srna, "remove_mesh", "rna_Main_remove_mesh");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_function_ui_description(func, "Remove a mesh if it has zero users.");
- prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove.");
- RNA_def_property_flag(prop, PROP_REQUIRED);
-}
-
-#endif
-
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 3a7015b65be..0a0d70fa9eb 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -45,6 +45,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -212,7 +213,7 @@ static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *ma
static CustomData *rna_mesh_fdata(Mesh *me)
{
- return (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ return (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
}
static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
deleted file mode 100644
index c98b3fb7b09..00000000000
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#ifdef RNA_RUNTIME
-
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_main.h"
-#include "BKE_mesh.h"
-
-#include "BLI_edgehash.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-static void rna_Mesh_calc_edges(Mesh *mesh)
-{
- CustomData edata;
- EdgeHashIterator *ehi;
- MFace *mf = mesh->mface;
- MEdge *med;
- EdgeHash *eh = BLI_edgehash_new();
- int i, *index, totedge, totface = mesh->totface;
-
- for (i = 0; i < totface; i++, mf++) {
- if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
- BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
- BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
-
- if (mf->v4) {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
- BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
- BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
- } else {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
- BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
- }
- }
-
- totedge = BLI_edgehash_size(eh);
-
- /* write new edges into a temporary CustomData */
- memset(&edata, 0, sizeof(edata));
- CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
-
- ehi = BLI_edgehashIterator_new(eh);
- med = CustomData_get_layer(&edata, CD_MEDGE);
- for(i = 0; !BLI_edgehashIterator_isDone(ehi);
- BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
- BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
-
- med->flag = ME_EDGEDRAW|ME_EDGERENDER;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* free old CustomData and assign new one */
- CustomData_free(&mesh->edata, mesh->totedge);
- mesh->edata = edata;
- mesh->totedge = totedge;
-
- mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
-
- BLI_edgehash_free(eh, NULL);
-}
-
-static void rna_Mesh_update(Mesh *mesh, bContext *C)
-{
- Main *bmain= CTX_data_main(C);
- Object *ob;
-
- if(mesh->totface && mesh->totedge == 0)
- rna_Mesh_calc_edges(mesh);
-
- mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
-
- for(ob=bmain->object.first; ob; ob=ob->id.next) {
- if(ob->data == mesh) {
- ob->recalc |= OB_RECALC_DATA;
- WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
- }
- }
-}
-
-static void rna_Mesh_add_verts(Mesh *mesh, int len)
-{
- CustomData vdata;
- MVert *mvert;
- int i, totvert;
-
- if(len == 0)
- return;
-
- totvert= mesh->totvert + len;
- CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
- CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
-
- if(!CustomData_has_layer(&vdata, CD_MVERT))
- CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
-
- CustomData_free(&mesh->vdata, mesh->totvert);
- mesh->vdata= vdata;
- mesh_update_customdata_pointers(mesh);
-
- /* scan the input list and insert the new vertices */
-
- mvert= &mesh->mvert[mesh->totvert];
- for(i=0; i<len; i++, mvert++)
- mvert->flag |= SELECT;
-
- /* set final vertex list size */
- mesh->totvert= totvert;
-}
-
-static void rna_Mesh_add_edges(Mesh *mesh, int len)
-{
- CustomData edata;
- MEdge *medge;
- int i, totedge;
-
- if(len == 0)
- return;
-
- totedge= mesh->totedge+len;
-
- /* update customdata */
- CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
- CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
-
- if(!CustomData_has_layer(&edata, CD_MEDGE))
- CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
-
- CustomData_free(&mesh->edata, mesh->totedge);
- mesh->edata= edata;
- mesh_update_customdata_pointers(mesh);
-
- /* set default flags */
- medge= &mesh->medge[mesh->totedge];
- for(i=0; i<len; i++, medge++)
- medge->flag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
-
- mesh->totedge= totedge;
-}
-
-static void rna_Mesh_add_faces(Mesh *mesh, int len)
-{
- CustomData fdata;
- MFace *mface;
- int i, totface;
-
- if(len == 0)
- return;
-
- totface= mesh->totface + len; /* new face count */
-
- /* update customdata */
- CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
- CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
-
- if(!CustomData_has_layer(&fdata, CD_MFACE))
- CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
-
- CustomData_free(&mesh->fdata, mesh->totface);
- mesh->fdata= fdata;
- mesh_update_customdata_pointers(mesh);
-
- /* set default flags */
- mface= &mesh->mface[mesh->totface];
- for(i=0; i<len; i++, mface++)
- mface->flag= SELECT;
-
- mesh->totface= totface;
-}
-
-static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces)
-{
- if(verts)
- rna_Mesh_add_verts(mesh, verts);
- if(edges)
- rna_Mesh_add_edges(mesh, edges);
- if(faces)
- rna_Mesh_add_faces(mesh, faces);
-}
-
-#else
-
-void RNA_api_mesh(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *parm;
-
- func= RNA_def_function(srna, "add_geometry", "rna_Mesh_add_geometry");
- parm= RNA_def_int(func, "verts", 0, 0, INT_MAX, "Number", "Number of vertices to add.", 0, INT_MAX);
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_int(func, "edges", 0, 0, INT_MAX, "Number", "Number of edges to add.", 0, INT_MAX);
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_int(func, "faces", 0, 0, INT_MAX, "Number", "Number of faces to add.", 0, INT_MAX);
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "update", "rna_Mesh_update");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-}
-
-#endif
-
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
deleted file mode 100644
index bc636af6849..00000000000
--- a/source/blender/makesrna/intern/rna_nla.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * Contributor(s): Blender Foundation (2009), Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#include "rna_internal.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_action_types.h"
-#include "DNA_scene_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#ifdef RNA_RUNTIME
-
-#include <stdio.h>
-#include <math.h>
-
-/* needed for some of the validation stuff... */
-#include "BKE_animsys.h"
-#include "BKE_nla.h"
-
-/* temp constant defined for these funcs only... */
-#define NLASTRIP_MIN_LEN_THRESH 0.1f
-
-void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value)
-{
- NlaStrip *data= (NlaStrip *)ptr->data;
-
- /* copy the name first */
- BLI_strncpy(data->name, value, sizeof(data->name));
-
- /* validate if there's enough info to do so */
- if (ptr->id.data) {
- AnimData *adt= BKE_animdata_from_id(ptr->id.data);
- BKE_nlastrip_validate_name(adt, data);
- }
-}
-
-
-static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
-
- /* clamp value to lie within valid limits
- * - cannot start past the end of the strip + some flexibility threshold
- * - cannot start before the previous strip (if present) ends
- * -> but if it was a transition, we could go up to the start of the strip + some flexibility threshold
- * as long as we re-adjust the transition afterwards
- * - minimum frame is -MAXFRAME so that we don't get clipping on frame 0
- */
- if (data->prev) {
- if (data->prev->type == NLASTRIP_TYPE_TRANSITION) {
- CLAMP(value, data->prev->start+NLASTRIP_MIN_LEN_THRESH, data->end-NLASTRIP_MIN_LEN_THRESH);
-
- /* readjust the transition to stick to the endpoints of the action-clips */
- data->prev->end= value;
- }
- else {
- CLAMP(value, data->prev->end, data->end-NLASTRIP_MIN_LEN_THRESH);
- }
- }
- else {
- CLAMP(value, MINAFRAME, data->end);
- }
- data->start= value;
-}
-
-static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
-
- /* clamp value to lie within valid limits
- * - must not have zero or negative length strip, so cannot start before the first frame
- * + some minimum-strip-length threshold
- * - cannot end later than the start of the next strip (if present)
- * -> but if it was a transition, we could go up to the start of the end - some flexibility threshold
- * as long as we re-adjust the transition afterwards
- */
- if (data->next) {
- if (data->next->type == NLASTRIP_TYPE_TRANSITION) {
- CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->end-NLASTRIP_MIN_LEN_THRESH);
-
- /* readjust the transition to stick to the endpoints of the action-clips */
- data->next->start= value;
- }
- else {
- CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, data->next->start);
- }
- }
- else {
- CLAMP(value, data->start+NLASTRIP_MIN_LEN_THRESH, MAXFRAME);
- }
- data->end= value;
-
-
- /* calculate the lengths the strip and its action (if applicable) */
- if (data->type == NLASTRIP_TYPE_CLIP) {
- float len, actlen;
-
- len= data->end - data->start;
- actlen= data->actend - data->actstart;
- if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
-
- /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */
- data->scale= len / ((actlen) * data->repeat);
- }
-}
-
-static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- float actlen, mapping;
-
- /* set scale value */
- CLAMP(value, 0.0001f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
- data->scale= value;
-
- /* calculate existing factors */
- actlen= data->actend - data->actstart;
- if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
- mapping= data->scale * data->repeat;
-
- /* adjust endpoint of strip in response to this */
- if (IS_EQ(mapping, 0.0f) == 0)
- data->end = (actlen * mapping) + data->start;
- else
- printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat);
-}
-
-static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- float actlen, mapping;
-
- /* set scale value */
- CLAMP(value, 0.01f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
- data->repeat= value;
-
- /* calculate existing factors */
- actlen= data->actend - data->actstart;
- if (IS_EQ(actlen, 0.0f)) actlen= 1.0f;
- mapping= data->scale * data->repeat;
-
- /* adjust endpoint of strip in response to this */
- if (IS_EQ(mapping, 0.0f) == 0)
- data->end = (actlen * mapping) + data->start;
- else
- printf("NlaStrip Set Repeat Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat);
-}
-
-static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- float len;
-
- /* blend-in is limited to the length of the strip, and also cannot overlap with blendout */
- len= (data->end - data->start) - data->blendout;
- CLAMP(value, 0, len);
-
- data->blendin= value;
-}
-
-static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- float len;
-
- /* blend-out is limited to the length of the strip */
- len= (data->end - data->start);
- CLAMP(value, 0, len);
-
- /* it also cannot overlap with blendin */
- if ((len - value) < data->blendin)
- value= len - data->blendin;
-
- data->blendout= value;
-}
-
-static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- CLAMP(value, MINAFRAME, data->actend);
- data->actstart= value;
-}
-
-static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
- CLAMP(value, data->actstart, MAXFRAME);
- data->actend= value;
-}
-
-static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
-
- if (value) {
- /* set the flag, then make sure a curve for this exists */
- data->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
- BKE_nlastrip_validate_fcurves(data);
- }
- else
- data->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
-}
-
-static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value)
-{
- NlaStrip *data= (NlaStrip*)ptr->data;
-
- if (value) {
- /* set the flag, then make sure a curve for this exists */
- data->flag |= NLASTRIP_FLAG_USR_TIME;
- BKE_nlastrip_validate_fcurves(data);
- }
- else
- data->flag &= ~NLASTRIP_FLAG_USR_TIME;
-}
-
-#else
-
-void rna_def_nlastrip(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* enum defs */
- static EnumPropertyItem prop_type_items[] = {
- {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action."},
- {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips."},
- {NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips."},
- {0, NULL, 0, NULL, NULL}};
- static EnumPropertyItem prop_mode_blend_items[] = {
- {NLASTRIP_MODE_REPLACE, "REPLACE", 0, "Replace", "Result strip replaces the accumulated results by amount specified by influence."},
- {NLASTRIP_MODE_ADD, "ADD", 0, "Add", "Weighted result of strip is added to the accumlated results."},
- {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", 0, "Subtract", "Weighted result of strip is removed from the accumlated results."},
- {NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply", "Weighted result of strip is multiplied with the accumlated results."},
- {0, NULL, 0, NULL, NULL}};
- static EnumPropertyItem prop_mode_extend_items[] = {
- {NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents."},
- {NLASTRIP_EXTEND_HOLD, "HOLD", 0, "Hold", "Hold the first frame if no previous strips in track, and always hold last frame."},
- {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame."},
- {0, NULL, 0, NULL, NULL}};
-
- /* struct definition */
- srna= RNA_def_struct(brna, "NlaStrip", NULL);
- RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action.");
- RNA_def_struct_ui_icon(srna, ICON_NLA); // XXX
-
- /* name property */
- prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NlaStrip_name_set");
- RNA_def_struct_name_property(srna, prop);
-
- /* Enums */
- prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable, since this is dangerous
- RNA_def_property_enum_items(prop, prop_type_items);
- RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip.");
-
- prop= RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "extendmode");
- RNA_def_property_enum_items(prop, prop_mode_extend_items);
- RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents.");
-
- prop= RNA_def_property(srna, "blending", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "blendmode");
- RNA_def_property_enum_items(prop, prop_mode_blend_items);
- RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result.");
-
- /* Strip extents */
- prop= RNA_def_property(srna, "start_frame", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "start");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL);
- RNA_def_property_ui_text(prop, "Start Frame", "");
-
- prop= RNA_def_property(srna, "end_frame", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "end");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL);
- RNA_def_property_ui_text(prop, "End Frame", "");
-
- /* Blending */
- prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "blendin");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL);
- RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence.");
-
- prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "blendout");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL);
- RNA_def_property_ui_text(prop, "Blend Out", "");
-
- prop= RNA_def_property(srna, "auto_blending", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS);
- RNA_def_property_ui_text(prop, "Auto Blend In/Out", "Number of frames for Blending In/Out is automatically determined from overlapping strips.");
-
- /* Action */
- prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "act");
- RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip.");
-
- /* Action extents */
- prop= RNA_def_property(srna, "action_start_frame", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "actstart");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL);
- RNA_def_property_ui_text(prop, "Action Start Frame", "");
-
- prop= RNA_def_property(srna, "action_end_frame", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "actend");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL);
- RNA_def_property_ui_text(prop, "Action End Frame", "");
-
- /* Action Reuse */
- prop= RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "repeat");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL);
- RNA_def_property_range(prop, 0.1f, 1000.0f); /* these limits have currently be chosen arbitarily, but could be extended (minimum should still be > 0 though) if needed... */
- RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range.");
-
- prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "scale");
- RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL);
- RNA_def_property_range(prop, 0.0001f, 1000.0f); /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs due to numeric errors */
- RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action.");
-
- /* Strip's F-Curves */
- prop= RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "FCurve");
- RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing.");
-
- /* Strip's F-Modifiers */
- prop= RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "FModifier");
- RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action.");
-
- /* Strip's Sub-Strips (for Meta-Strips) */
- prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "NlaStrip");
- RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips that this strip acts as a container for (if it is of type Meta).");
-
- /* Settings - Values necessary for evaluation */
- prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result.");
-
- prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate.");
-
- // TODO: should the animated_influence/time settings be animatable themselves?
- prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_influence_set");
- RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined.");
-
- prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set");
- RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined.");
-
- /* settings */
- prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE);
- RNA_def_property_ui_text(prop, "Active", "NLA Strip is active.");
-
- prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT);
- RNA_def_property_ui_text(prop, "Selected", "NLA Strip is selected.");
-
- prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED);
- RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated.");
-
- prop= RNA_def_property(srna, "reversed", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE);
- RNA_def_property_ui_text(prop, "Reversed", "NLA Strip is played back in reverse order (only when timing is automatically determined).");
-
- // TODO:
- // - sync length
-}
-
-void rna_def_nlatrack(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna= RNA_def_struct(brna, "NlaTrack", NULL);
- RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips.");
- RNA_def_struct_ui_icon(srna, ICON_NLA);
-
- /* strips collection */
- prop= RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "NlaStrip");
- RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track.");
-
- /* name property */
- prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "");
- RNA_def_struct_name_property(srna, prop);
-
- /* settings */
- prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE);
- RNA_def_property_ui_text(prop, "Active", "NLA Track is active.");
-
- prop= RNA_def_property(srna, "solo", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* can be made editable by hooking it up to the necessary NLA API methods */
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO);
- RNA_def_property_ui_text(prop, "Solo", "NLA Track is evaluated itself (i.e. active Action and all other NLA Tracks in the same AnimData block are disabled).");
-
- prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED);
- RNA_def_property_ui_text(prop, "Selected", "NLA Track is selected.");
-
- prop= RNA_def_property(srna, "muted", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED);
- RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated.");
-
- prop= RNA_def_property(srna, "locked", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED);
- RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked.");
-}
-
-/* --------- */
-
-void RNA_def_nla(BlenderRNA *brna)
-{
- rna_def_nlatrack(brna);
- rna_def_nlastrip(brna);
-}
-
-
-#endif
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
deleted file mode 100644
index 053ab115b3b..00000000000
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#ifdef RNA_RUNTIME
-
-#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
-
-/* copied from init_render_mesh (render code) */
-Mesh *rna_Object_create_render_mesh(Object *ob, Scene *scene)
-{
- CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
- DerivedMesh *dm;
- Mesh *me;
-
- /* TODO: other types */
- if(ob->type != OB_MESH)
- return NULL;
-
- dm= mesh_create_derived_render(scene, ob, mask);
-
- if(!dm)
- return NULL;
-
- me= add_mesh("tmp_render_mesh");
- me->id.us--; /* we don't assign it to anything */
- DM_to_mesh(dm, me);
- dm->release(dm);
-
- return me;
-}
-
-#else
-
-void RNA_api_object(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *prop;
-
- func= RNA_def_function(srna, "create_render_mesh", "rna_Object_create_render_mesh");
- RNA_def_function_ui_description(func, "Create a Mesh datablock with all modifiers applied.");
- prop= RNA_def_pointer(func, "scene", "Scene", "", "");
- RNA_def_property_flag(prop, PROP_REQUIRED);
- prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export.");
- RNA_def_function_return(func, prop);
-}
-
-#endif
-
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
deleted file mode 100644
index 404befc9bb2..00000000000
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- * $Id:
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#ifdef RNA_RUNTIME
-
-#else
-
-#define DEF_ICON(name) {name, #name, 0, #name, ""},
-static EnumPropertyItem icon_items[] = {
-#include "UI_icons.h"
- {0, NULL, 0, NULL, NULL}};
-#undef DEF_ICON
-
-static void api_ui_item_common(FunctionRNA *func)
-{
- PropertyRNA *prop;
-
- RNA_def_string(func, "text", "", 0, "", "Override automatic text of the item.");
-
- prop= RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, icon_items);
- RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item.");
-
-}
-
-static void api_ui_item_op_common(FunctionRNA *func)
-{
- PropertyRNA *parm;
-
- api_ui_item_common(func);
- parm= RNA_def_string(func, "operator", "", 0, "", "Identifier of the operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-}
-
-static void api_ui_item_rna_common(FunctionRNA *func)
-{
- PropertyRNA *parm;
-
- parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in data.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-}
-
-void RNA_api_ui_layout(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *parm;
-
- static EnumPropertyItem curve_type_items[] = {
- {0, "NONE", 0, "None", ""},
- {'v', "VECTOR", 0, "Vector", ""},
- {'c', "COLOR", 0, "Color", ""},
- {0, NULL, 0, NULL, NULL}};
-
- /* simple layout specifiers */
- func= RNA_def_function(srna, "row", "uiLayoutRow");
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other.");
-
- func= RNA_def_function(srna, "column", "uiLayoutColumn");
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other.");
-
- func= RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow");
- parm= RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic.", 0, INT_MAX);
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other.");
-
- /* box layout */
- func= RNA_def_function(srna, "box", "uiLayoutBox");
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
-
- /* split layout */
- func= RNA_def_function(srna, "split", "uiLayoutSplit");
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
- RNA_def_float(func, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at.", 0.0f, 1.0f);
-
- /* items */
- func= RNA_def_function(srna, "itemR", "uiItemR");
- api_ui_item_common(func);
- api_ui_item_rna_common(func);
- RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail.");
- RNA_def_boolean(func, "slider", 0, "", "Use slider widget for numeric values.");
- RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values.");
-
- func= RNA_def_function(srna, "items_enumR", "uiItemsEnumR");
- api_ui_item_rna_common(func);
-
- func= RNA_def_function(srna, "item_menu_enumR", "uiItemMenuEnumR");
- api_ui_item_common(func);
- api_ui_item_rna_common(func);
-
- func= RNA_def_function(srna, "item_enumR", "uiItemEnumR_string");
- api_ui_item_common(func);
- api_ui_item_rna_common(func);
- parm= RNA_def_string(func, "value", "", 0, "", "Enum property value.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_pointerR", "uiItemPointerR");
- api_ui_item_common(func);
- api_ui_item_rna_common(func);
- parm= RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_string(func, "search_property", "", 0, "", "Identifier of search collection property.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "itemO", "uiItemO");
- api_ui_item_op_common(func);
-
- func= RNA_def_function(srna, "item_enumO", "uiItemEnumO_string");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_string(func, "value", "", 0, "", "Enum property value.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "items_enumO", "uiItemsEnumO");
- parm= RNA_def_string(func, "operator", "", 0, "", "Identifier of the operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_menu_enumO", "uiItemMenuEnumO");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_booleanO", "uiItemBooleanO");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_boolean(func, "value", 0, "", "Value of the property to call the operator with.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_intO", "uiItemIntO");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_int(func, "value", 0, INT_MIN, INT_MAX, "", "Value of the property to call the operator with.", INT_MIN, INT_MAX);
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_floatO", "uiItemFloatO");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_float(func, "value", 0, -FLT_MAX, FLT_MAX, "", "Value of the property to call the operator with.", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "item_stringO", "uiItemStringO");
- api_ui_item_op_common(func);
- parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_string(func, "value", "", 0, "", "Value of the property to call the operator with.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "itemL", "uiItemL");
- api_ui_item_common(func);
-
- func= RNA_def_function(srna, "itemM", "uiItemM");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- api_ui_item_common(func);
- parm= RNA_def_string(func, "menu", "", 0, "", "Identifier of the menu.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "itemS", "uiItemS");
-
- /* context */
- func= RNA_def_function(srna, "set_context_pointer", "uiLayoutSetContextPointer");
- parm= RNA_def_string(func, "name", "", 0, "Name", "Name of entry in the context.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_pointer(func, "data", "AnyType", "", "Pointer to put in context.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
-
- /* templates */
- func= RNA_def_function(srna, "template_header", "uiTemplateHeader");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-
- func= RNA_def_function(srna, "template_ID", "uiTemplateID");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- api_ui_item_rna_common(func);
- RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
- RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
-
- func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
- parm= RNA_def_pointer(func, "data", "Modifier", "", "Modifier data.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
-
- func= RNA_def_function(srna, "template_constraint", "uiTemplateConstraint");
- parm= RNA_def_pointer(func, "data", "Constraint", "", "Constraint data.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
- RNA_def_function_return(func, parm);
-
- func= RNA_def_function(srna, "template_preview", "uiTemplatePreview");
- parm= RNA_def_pointer(func, "id", "ID", "", "ID datablock.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "template_curve_mapping", "uiTemplateCurveMapping");
- parm= RNA_def_pointer(func, "curvemap", "CurveMapping", "", "Curve mapping pointer.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_enum(func, "type", curve_type_items, 0, "Type", "Type of curves to display.");
-
- func= RNA_def_function(srna, "template_color_ramp", "uiTemplateColorRamp");
- parm= RNA_def_pointer(func, "ramp", "ColorRamp", "", "Color ramp pointer.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail.");
-
- func= RNA_def_function(srna, "template_layers", "uiTemplateLayers");
- api_ui_item_rna_common(func);
-
- func= RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- parm= RNA_def_pointer(func, "image", "Image", "", "");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_pointer(func, "image_user", "ImageUser", "", "");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- func= RNA_def_function(srna, "template_list", "uiTemplateList");
- api_ui_item_rna_common(func);
- parm= RNA_def_pointer(func, "active_data", "AnyType", "", "Data from which to take property for the active element.");
- RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
- parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element.");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX);
- parm= RNA_def_int(func, "columns", 5, 0, INT_MAX, "", "Number of columns to display.", 0, INT_MAX);
- parm= RNA_def_boolean(func, "compact", 0, "", "Use compact, single row list template.");
- parm= RNA_def_collection(func, "items", 0, "", "Items visible in the list.");
- RNA_def_function_return(func, parm);
-
- func= RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-
- func= RNA_def_function(srna, "template_operator_search", "uiTemplateOperatorSearch");
-
- func= RNA_def_function(srna, "template_header_3D", "uiTemplateHeader3D");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
-}
-
-#endif
-
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
deleted file mode 100644
index fd34d7c4d70..00000000000
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#ifdef RNA_RUNTIME
-
-#include "BKE_context.h"
-
-#include "WM_api.h"
-
-#else
-
-void RNA_api_wm(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *prop;
-
- func= RNA_def_function(srna, "add_fileselect", "WM_event_add_fileselect");
- RNA_def_function_flag(func, FUNC_NO_SELF|FUNC_USE_CONTEXT);
- RNA_def_function_ui_description(func, "Show up the file selector.");
- prop= RNA_def_pointer(func, "operator", "Operator", "", "Operator to call.");
- RNA_def_property_flag(prop, PROP_REQUIRED);
-}
-
-#endif
-
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_at.c b/source/blender/nodes/intern/TEX_nodes/TEX_at.c
deleted file mode 100644
index 80f232ccd0c..00000000000
--- a/source/blender/nodes/intern/TEX_nodes/TEX_at.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): R Allen
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "../TEX_util.h"
-
-static bNodeSocketType inputs[]= {
- { SOCK_RGBA, 1, "Texture", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
- { SOCK_VECTOR, 1, "Coordinates", 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f },
- { -1, 0, "" }
-};
-static bNodeSocketType outputs[]= {
- { SOCK_RGBA, 0, "Texture", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
- { -1, 0, "" }
-};
-
-static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
-{
- float new_coord[3];
-
- tex_input_vec(new_coord, in[1], coord, thread);
- tex_input_rgba(out, in[0], new_coord, thread);
-}
-
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- tex_output(node, in, out[0], &colorfn);
-}
-
-bNodeType tex_node_at = {
- /* *next,*prev */ NULL, NULL,
- /* type code */ TEX_NODE_AT,
- /* name */ "At",
- /* width+range */ 100, 60, 150,
- /* class+opts */ NODE_CLASS_DISTORT, 0,
- /* input sock */ inputs,
- /* output sock */ outputs,
- /* storage */ "",
- /* execfunc */ exec,
- /* butfunc */ NULL,
- /* initfunc */ NULL,
- /* freestoragefunc */ NULL,
- /* copystoragefunc */ NULL,
- /* id */ NULL
-
-};
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index c6972793372..ff3e89a6e25 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BPY_extern.h 12334 2007-10-21 23:00:29Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -50,8 +50,6 @@ struct bConstraintTarget; /* DNA_constraint_types.h*/
struct Script; /* DNA_screen_types.h */
struct BPyMenu;
struct bContext;
-struct ReportList;
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -99,8 +97,8 @@ extern "C" {
int BPY_menu_invoke( struct BPyMenu *pym, short menutype );
/* 2.5 UI Scripts */
- int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text, struct ReportList *reports ); // 2.5 working
- int BPY_run_script_space_draw(const struct bContext *C, struct SpaceScript * sc); // 2.5 working
+ int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text ); // 2.5 working
+ int BPY_run_script_space_draw(struct bContext *C, struct SpaceScript * sc); // 2.5 working
void BPY_run_ui_scripts(struct bContext *C, int reload);
// int BPY_run_script_space_listener(struct bContext *C, struct SpaceScript * sc, struct ARegion *ar, struct wmNotifier *wmn); // 2.5 working
void BPY_update_modules( void ); // XXX - annoying, need this for pointers that get out of date
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
new file mode 100644
index 00000000000..b67f1e717da
--- /dev/null
+++ b/source/blender/python/BPY_menus.c
@@ -0,0 +1,1118 @@
+/*
+ * $Id: BPY_menus.c 12932 2007-12-17 20:21:06Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Michael Reimpell
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+/*
+ *This is the main file responsible for having bpython scripts accessible
+ * from Blender menus. To know more, please start with its header file.
+ */
+
+#include "BPY_menus.h"
+
+#include <Python.h>
+#ifndef WIN32
+ #include <dirent.h>
+#else
+ #include "BLI_winstuff.h"
+#endif
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+#include "DNA_userdef_types.h" /* for U.pythondir */
+#include "api2_2x/EXPP_interface.h" /* for bpy_gethome() */
+
+#define BPYMENU_DATAFILE "Bpymenus"
+#define MAX_DIR_DEPTH 4 /* max depth for traversing scripts dirs */
+#define MAX_DIR_NUMBER 30 /* max number of dirs in scripts dirs trees */
+
+static int DEBUG;
+static int Dir_Depth;
+static int Dirs_Number;
+
+/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
+ * where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
+*/
+BPyMenu *BPyMenuTable[PYMENU_TOTAL];
+
+static int bpymenu_group_atoi( char *str )
+{
+ if( !strcmp( str, "Export" ) )
+ return PYMENU_EXPORT;
+ else if( !strcmp( str, "Import" ) )
+ return PYMENU_IMPORT;
+ else if( !strcmp( str, "Help" ) )
+ return PYMENU_HELP;
+ else if( !strcmp( str, "HelpWebsites" ) )
+ return PYMENU_HELPWEBSITES;
+ else if( !strcmp( str, "HelpSystem" ) )
+ return PYMENU_HELPSYSTEM;
+ else if( !strcmp( str, "Render" ) )
+ return PYMENU_RENDER;
+ else if( !strcmp( str, "System" ) )
+ return PYMENU_SYSTEM;
+ else if( !strcmp( str, "Object" ) )
+ return PYMENU_OBJECT;
+ else if( !strcmp( str, "Mesh" ) )
+ return PYMENU_MESH;
+ else if( !strncmp( str, "Theme", 5 ) )
+ return PYMENU_THEMES;
+ else if( !strcmp( str, "Add" ) )
+ return PYMENU_ADD;
+ else if( !strcmp( str, "Wizards" ) )
+ return PYMENU_WIZARDS;
+ else if( !strcmp( str, "Animation" ) )
+ return PYMENU_ANIMATION;
+ else if( !strcmp( str, "Materials" ) )
+ return PYMENU_MATERIALS;
+ else if( !strcmp( str, "UV" ) )
+ return PYMENU_UV;
+ else if( !strcmp( str, "Image" ) )
+ return PYMENU_IMAGE;
+ else if( !strcmp( str, "FaceSelect" ) )
+ return PYMENU_FACESELECT;
+ else if( !strcmp( str, "WeightPaint" ) )
+ return PYMENU_WEIGHTPAINT;
+ else if( !strcmp( str, "VertexPaint" ) )
+ return PYMENU_VERTEXPAINT;
+ else if( !strcmp( str, "UVCalculation" ) )
+ return PYMENU_UVCALCULATION;
+ else if( !strcmp( str, "Armature" ) )
+ return PYMENU_ARMATURE;
+ else if( !strcmp( str, "ScriptTemplate" ) )
+ return PYMENU_SCRIPTTEMPLATE;
+ else if( !strcmp( str, "MeshFaceKey" ) )
+ return PYMENU_MESHFACEKEY;
+ else if( !strcmp( str, "AddMesh" ) )
+ return PYMENU_ADDMESH;
+ /* "Misc" or an inexistent group name: use misc */
+ else
+ return PYMENU_MISC;
+}
+
+char *BPyMenu_group_itoa( short menugroup )
+{
+ switch ( menugroup ) {
+ case PYMENU_EXPORT:
+ return "Export";
+ break;
+ case PYMENU_IMPORT:
+ return "Import";
+ break;
+ case PYMENU_ADD:
+ return "Add";
+ break;
+ case PYMENU_HELP:
+ return "Help";
+ break;
+ case PYMENU_HELPWEBSITES:
+ return "HelpWebsites";
+ break;
+ case PYMENU_HELPSYSTEM:
+ return "HelpSystem";
+ break;
+ case PYMENU_RENDER:
+ return "Render";
+ break;
+ case PYMENU_SYSTEM:
+ return "System";
+ break;
+ case PYMENU_OBJECT:
+ return "Object";
+ break;
+ case PYMENU_MESH:
+ return "Mesh";
+ break;
+ case PYMENU_THEMES:
+ return "Themes";
+ break;
+ case PYMENU_WIZARDS:
+ return "Wizards";
+ break;
+ case PYMENU_ANIMATION:
+ return "Animation";
+ break;
+ case PYMENU_MATERIALS:
+ return "Materials";
+ break;
+ case PYMENU_UV:
+ return "UV";
+ break;
+ case PYMENU_IMAGE:
+ return "Image";
+ break;
+ case PYMENU_FACESELECT:
+ return "FaceSelect";
+ break;
+ case PYMENU_WEIGHTPAINT:
+ return "WeightPaint";
+ break;
+ case PYMENU_VERTEXPAINT:
+ return "VertexPaint";
+ break;
+ case PYMENU_UVCALCULATION:
+ return "UVCalculation";
+ break;
+ case PYMENU_ARMATURE:
+ return "Armature";
+ break;
+ case PYMENU_SCRIPTTEMPLATE:
+ return "ScriptTemplate";
+ break;
+ case PYMENU_MESHFACEKEY:
+ return "MeshFaceKey";
+ break;
+ case PYMENU_ADDMESH:
+ return "AddMesh";
+ break;
+ case PYMENU_MISC:
+ return "Misc";
+ break;
+ }
+ return NULL;
+}
+
+/* BPyMenu_CreatePupmenuStr:
+ * build and return a meaninful string to be used by pupmenu(). The
+ * string is made of a bpymenu name as title and its submenus as possible
+ * choices for the user.
+*/
+char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short menugroup )
+{
+ BPySubMenu *pysm = pym->submenus;
+ char str[1024], str2[100];
+ int i = 0, rlen;
+
+ if( !pym || !pysm )
+ return NULL;
+
+ str[0] = '\0';
+
+ PyOS_snprintf( str2, sizeof( str2 ), "%s: %s%%t",
+ BPyMenu_group_itoa( menugroup ), pym->name );
+ strcat( str, str2 );
+
+ while( pysm ) {
+ PyOS_snprintf( str2, sizeof( str2 ), "|%s%%x%d", pysm->name,
+ i );
+ rlen = sizeof( str ) - strlen( str );
+ strncat( str, str2, rlen );
+ i++;
+ pysm = pysm->next;
+ }
+
+ return BLI_strdup( str );
+}
+
+static void bpymenu_RemoveAllSubEntries( BPySubMenu * smenu )
+{
+ BPySubMenu *tmp;
+
+ while( smenu ) {
+ tmp = smenu->next;
+ if( smenu->name )
+ MEM_freeN( smenu->name );
+ if( smenu->arg )
+ MEM_freeN( smenu->arg );
+ MEM_freeN( smenu );
+ smenu = tmp;
+ }
+ return;
+}
+
+void BPyMenu_RemoveAllEntries( void )
+{
+ BPyMenu *tmp, *pymenu;
+ int i;
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ while( pymenu ) {
+ tmp = pymenu->next;
+ if( pymenu->name )
+ MEM_freeN( pymenu->name );
+ if( pymenu->filename )
+ MEM_freeN( pymenu->filename );
+ if( pymenu->tooltip )
+ MEM_freeN( pymenu->tooltip );
+ if( pymenu->submenus )
+ bpymenu_RemoveAllSubEntries( pymenu->
+ submenus );
+ MEM_freeN( pymenu );
+ pymenu = tmp;
+ }
+ BPyMenuTable[i] = NULL;
+ }
+
+ Dirs_Number = 0;
+ Dir_Depth = 0;
+
+ return;
+}
+
+static BPyMenu *bpymenu_FindEntry( short group, char *name )
+{
+ BPyMenu *pymenu;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+
+ pymenu = BPyMenuTable[group];
+
+ while( pymenu ) {
+ if( !strcmp( pymenu->name, name ) )
+ return pymenu;
+ pymenu = pymenu->next;
+ }
+
+ return NULL;
+}
+
+/* BPyMenu_GetEntry:
+ * given a group and a position, return the entry in that position from
+ * that group.
+*/
+BPyMenu *BPyMenu_GetEntry( short group, short pos )
+{
+ BPyMenu *pym = NULL;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+
+ pym = BPyMenuTable[group];
+
+ while( pos-- ) {
+ if( pym )
+ pym = pym->next;
+ else
+ break;
+ }
+
+ return pym; /* found entry or NULL */
+}
+
+static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip )
+{
+ if( !pymenu )
+ return;
+
+ if( pymenu->tooltip )
+ MEM_freeN( pymenu->tooltip );
+ pymenu->tooltip = BLI_strdup( tip );
+
+ return;
+}
+
+/* bpymenu_AddEntry:
+ * try to find an existing pymenu entry with the given type and name;
+ * if found, update it with new info, otherwise create a new one and fill it.
+ */
+static BPyMenu *bpymenu_AddEntry( short group, short version, char *name,
+ char *fname, int is_userdir, char *tooltip )
+{
+ BPyMenu *menu, *next = NULL, **iter;
+ int nameclash = 0;
+
+ if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
+ return NULL;
+ if( !name || !fname )
+ return NULL;
+
+ menu = bpymenu_FindEntry( group, name ); /* already exists? */
+
+ /* if a menu with this name already exists in the same group:
+ * - if one script is in the default dir and the other in U.pythondir,
+ * accept and let the new one override the other.
+ * - otherwise, report the error and return NULL. */
+ if( menu ) {
+ if( menu->dir < is_userdir ) { /* new one is in U.pythondir */
+ nameclash = 1;
+ if( menu->name )
+ MEM_freeN( menu->name );
+ if( menu->filename )
+ MEM_freeN( menu->filename );
+ if( menu->tooltip )
+ MEM_freeN( menu->tooltip );
+ if( menu->submenus )
+ bpymenu_RemoveAllSubEntries( menu->submenus );
+ next = menu->next;
+ } else { /* they are in the same dir */
+ if (DEBUG) {
+ fprintf(stderr, "\n\
+Warning: script %s's menu name is already in use.\n\
+Edit the script and change its \n\
+Name: '%s'\n\
+field, please.\n\
+Note: if you really want to have two scripts for the same menu with\n\
+the same name, keep one in the default dir and the other in\n\
+the user defined dir (only the later will be registered).\n", fname, name);
+ }
+ return NULL;
+ }
+ } else
+ menu = MEM_mallocN( sizeof( BPyMenu ), "pymenu" );
+
+ if( !menu )
+ return NULL;
+
+ menu->name = BLI_strdup( name );
+ menu->version = version;
+ menu->filename = BLI_strdup( fname );
+ menu->tooltip = NULL;
+ if( tooltip )
+ menu->tooltip = BLI_strdup( tooltip );
+ menu->dir = is_userdir;
+ menu->submenus = NULL;
+ menu->next = next; /* non-NULL if menu already existed */
+
+ if( nameclash )
+ return menu; /* no need to place it, it's already at the list */
+ else { /* insert the new entry in its correct position at the table */
+ BPyMenu *prev = NULL;
+ char *s = NULL;
+
+ iter = &BPyMenuTable[group];
+ while( *iter ) {
+ s = ( *iter )->name;
+ if( s )
+ if( strcmp( menu->name, s ) < 0 )
+ break; /* sort by names */
+ prev = *iter;
+ iter = &( ( *iter )->next );
+ }
+
+ if( *iter ) { /* prepend */
+ menu->next = *iter;
+ if( prev )
+ prev->next = menu;
+ else
+ BPyMenuTable[group] = menu; /* is first entry */
+ } else
+ *iter = menu; /* append */
+ }
+
+ return menu;
+}
+
+/* bpymenu_AddSubEntry:
+ * add a submenu to an existing python menu.
+ */
+static int bpymenu_AddSubEntry( BPyMenu * mentry, char *name, char *arg )
+{
+ BPySubMenu *smenu, **iter;
+
+ smenu = MEM_mallocN( sizeof( BPySubMenu ), "pysubmenu" );
+ if( !smenu )
+ return -1;
+
+ smenu->name = BLI_strdup( name );
+ smenu->arg = BLI_strdup( arg );
+ smenu->next = NULL;
+
+ if( !smenu->name || !smenu->arg )
+ return -1;
+
+ iter = &( mentry->submenus );
+ while( *iter )
+ iter = &( ( *iter )->next );
+
+ *iter = smenu;
+
+ return 0;
+}
+
+/* bpymenu_CreateFromFile:
+ * parse the bpymenus data file where Python menu data is stored;
+ * based on this data, create and fill the pymenu structs.
+ */
+static int bpymenu_CreateFromFile( void )
+{
+ FILE *fp;
+ char line[255], w1[255], w2[255], tooltip[255], *tip;
+ char *homedir = NULL;
+ int parsing, version, is_userdir;
+ short group;
+ BPyMenu *pymenu = NULL;
+
+ /* init global bpymenu table (it is a list of pointers to struct BPyMenus
+ * for each available cathegory: import, export, etc.) */
+ for( group = 0; group < PYMENU_TOTAL; group++ )
+ BPyMenuTable[group] = NULL;
+
+ /* let's try to open the file with bpymenu data */
+ homedir = bpy_gethome(0);
+ if (!homedir) {
+ if( DEBUG )
+ fprintf(stderr,
+ "BPyMenus error: couldn't open config file Bpymenus: no home dir.\n");
+ return -1;
+ }
+
+ BLI_make_file_string( "/", line, homedir, BPYMENU_DATAFILE );
+
+ fp = fopen( line, "rb" );
+
+ if( !fp ) {
+ if( DEBUG )
+ fprintf(stderr, "BPyMenus error: couldn't open config file %s.\n", line );
+ return -1;
+ }
+
+ fgets( line, 255, fp ); /* header */
+
+ /* check if the U.pythondir we saved at the file is different from the
+ * current one. If so, return to force updating from dirs */
+ w1[0] = '\0';
+ fscanf( fp, "# User defined scripts dir: %[^\n]\n", w1 );
+ if( w1 ) {
+ char upythondir[FILE_MAXDIR];
+
+ BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ if( strcmp( w1, upythondir ) != 0 )
+ return -1;
+ w1[0] = '\0';
+ }
+
+ while( fgets( line, 255, fp ) ) { /* parsing file lines */
+
+ switch ( line[0] ) { /* check first char */
+ case '#': /* comment */
+ continue;
+ break;
+ case '\n':
+ continue;
+ break;
+ default:
+ parsing = sscanf( line, "%s {\n", w1 ); /* menu group */
+ break;
+ }
+
+ if( parsing == 1 ) { /* got menu group string */
+ group = (short)bpymenu_group_atoi( w1 );
+ if( group < 0 && DEBUG ) { /* invalid type */
+ fprintf(stderr,
+ "BPyMenus error parsing config file: wrong group: %s,\n\
+will use 'Misc'.\n", w1 );
+ }
+ } else
+ continue;
+
+ for(;;) {
+ tip = NULL; /* optional tooltip */
+ fgets( line, 255, fp );
+ if( line[0] == '}' )
+ break;
+ else if( line[0] == '\n' )
+ continue;
+ else if( line[0] == '\'' ) { /* menu entry */
+ parsing =
+ sscanf( line,
+ "'%[^']' %d %s %d '%[^']'\n",
+ w1, &version, w2, &is_userdir,
+ tooltip );
+
+ if( parsing <= 0 ) { /* invalid line, get rid of it */
+ fgets( line, 255, fp );
+ } else if( parsing == 5 )
+ tip = tooltip; /* has tooltip */
+
+ pymenu = bpymenu_AddEntry( group,
+ ( short ) version,
+ w1, w2, is_userdir,
+ tip );
+ if( !pymenu ) {
+ puts( "BPyMenus error: couldn't create bpymenu entry.\n" );
+ fclose( fp );
+ return -1;
+ }
+ } else if( line[0] == '|' && line[1] == '_' ) { /* menu sub-entry */
+ if( !pymenu )
+ continue; /* no menu yet, skip this line */
+ sscanf( line, "|_%[^:]: %s\n", w1, w2 );
+ bpymenu_AddSubEntry( pymenu, w1, w2 );
+ }
+ }
+ }
+
+ fclose( fp );
+ return 0;
+}
+
+/* bpymenu_WriteDataFile:
+ * writes the registered scripts info to the user's home dir, for faster
+ * access when the scripts dir hasn't changed.
+*/
+static void bpymenu_WriteDataFile( void )
+{
+ BPyMenu *pymenu;
+ BPySubMenu *smenu;
+ FILE *fp;
+ char fname[FILE_MAXDIR], *homedir;
+ int i;
+
+ homedir = bpy_gethome(0);
+
+ if (!homedir) {
+ if( DEBUG )
+ fprintf(stderr,
+ "BPyMenus error: couldn't write Bpymenus file: no home dir.\n\n");
+ return;
+ }
+
+ BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
+
+ fp = fopen( fname, "w" );
+ if( !fp ) {
+ if( DEBUG )
+ fprintf(stderr, "BPyMenus error: couldn't write %s file.\n\n",
+ fname );
+ return;
+ }
+
+ fprintf( fp,
+ "# Blender: registered menu entries for bpython scripts\n" );
+
+ if (U.pythondir[0] != '\0' &&
+ strcmp(U.pythondir, "/") != 0 && strcmp(U.pythondir, "//") != 0)
+ {
+ char upythondir[FILE_MAXDIR];
+
+ BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ fprintf( fp, "# User defined scripts dir: %s\n", upythondir );
+ }
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ if( !pymenu )
+ continue;
+ fprintf( fp, "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
+ while( pymenu ) {
+ fprintf( fp, "'%s' %d %s %d", pymenu->name,
+ pymenu->version, pymenu->filename,
+ pymenu->dir );
+ if( pymenu->tooltip )
+ fprintf( fp, " '%s'\n", pymenu->tooltip );
+ else
+ fprintf( fp, "\n" );
+ smenu = pymenu->submenus;
+ while( smenu ) {
+ fprintf( fp, "|_%s: %s\n", smenu->name,
+ smenu->arg );
+ smenu = smenu->next;
+ }
+ pymenu = pymenu->next;
+ }
+ fprintf( fp, "}\n" );
+ }
+
+ fclose( fp );
+ return;
+}
+
+/* BPyMenu_PrintAllEntries:
+ * useful for debugging.
+ */
+void BPyMenu_PrintAllEntries( void )
+{
+ BPyMenu *pymenu;
+ BPySubMenu *smenu;
+ int i;
+
+ printf( "# Blender: registered menu entries for bpython scripts\n" );
+
+ for( i = 0; i < PYMENU_TOTAL; i++ ) {
+ pymenu = BPyMenuTable[i];
+ printf( "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
+ while( pymenu ) {
+ printf( "'%s' %d %s %d", pymenu->name, pymenu->version,
+ pymenu->filename, pymenu->dir );
+ if( pymenu->tooltip )
+ printf( " '%s'\n", pymenu->tooltip );
+ else
+ printf( "\n" );
+ smenu = pymenu->submenus;
+ while( smenu ) {
+ printf( "|_%s: %s\n", smenu->name,
+ smenu->arg );
+ smenu = smenu->next;
+ }
+ pymenu = pymenu->next;
+ }
+ printf( "}\n" );
+ }
+}
+
+/* bpymenu_ParseFile:
+ * recursively scans folders looking for scripts to register.
+ *
+ * This function scans the scripts directory looking for .py files with the
+ * right header and menu info, using that to fill the bpymenu structs.
+ * is_userdir defines if the script is in the default scripts dir or the
+ * user defined one (U.pythondir: is_userdir == 1).
+ * Speed is important.
+ *
+ * The first line of the script must be '#!BPY'.
+ * The header registration lines must appear between the first pair of
+ * '\"\"\"' and follow this order (the single-quotes are part of
+ * the format):
+ *
+ * # \"\"\"<br>
+ * # Name: 'script name for the menu'
+ * # Blender: <code>short int</code> (minimal Blender version)
+ * # Group: 'group name' (defines menu)
+ * # Submenu: 'submenu name' related_1word_arg
+ * # Tooltip: 'tooltip for the menu'
+ * # \"\"\"
+ *
+ * Notes:
+ *
+ * - Commenting out header lines with "#" is optional, but recommended.
+ * - There may be more than one submenu line, or none:
+ * submenus and the tooltip are optional;
+ * - The Blender version is the same number reported by
+ * Blender.Get('version') in BPython or G.version in C;
+ * - Line length must be less than 99.
+ */
+static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir)
+{
+ char line[100];
+ char head[100];
+ char middle[100];
+ char tail[100];
+ int matches;
+ int parser_state;
+
+ char script_name[100];
+ int script_version = 1;
+ int script_group;
+
+ BPyMenu *scriptMenu = NULL;
+
+ if (file != NULL) {
+ parser_state = 1; /* state of parser, 0 to terminate */
+
+ while ((parser_state != 0) && (fgets(line, 100, file) != NULL)) {
+
+ switch (parser_state) {
+
+ case 1: /* !BPY */
+ if (strncmp(line, "#!BPY", 5) == 0) {
+ parser_state++;
+ } else {
+ parser_state = 0;
+ }
+ break;
+
+ case 2: /* \"\"\" */
+ if ((strstr(line, "\"\"\""))) {
+ parser_state++;
+ }
+ break;
+
+ case 3: /* Name: 'script name for the menu' */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, script_name, tail);
+ if ((matches == 3) && (strstr(head, "Name:") != NULL)) {
+ parser_state++;
+ } else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 4: /* Blender: <short int> */
+ matches = sscanf(line, "%[^1234567890]%i%c", head, &script_version,
+ tail);
+ if (matches == 3) {
+ parser_state++;
+ } else {
+ if (DEBUG)
+ fprintf(stderr,"BPyMenus error: Wrong 'Blender' line: %s\n",fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 5: /* Group: 'group name' */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((matches == 3) && (strstr(head, "Group:") != NULL)) {
+ script_group = bpymenu_group_atoi(middle);
+ if (script_group < 0) {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n",
+ middle, fname);
+ parser_state = 0;
+ }
+
+ else { /* register script */
+ scriptMenu = bpymenu_AddEntry((short)script_group,
+ (short int)script_version, script_name, fname, is_userdir,NULL);
+ if (scriptMenu == NULL) {
+ if (DEBUG)
+ fprintf(stderr,
+ "BPyMenus error: Couldn't create entry for: %s\n", fname);
+ parser_state = 0;
+ } else {
+ parser_state++;
+ }
+ }
+
+ } else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n",fname);
+ parser_state = 0;
+ }
+ break;
+
+ case 6: /* optional elements */
+ /* Submenu: 'submenu name' related_1word_arg */
+ matches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail);
+ if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) {
+ bpymenu_AddSubEntry(scriptMenu, middle, tail);
+ } else {
+ /* Tooltip: 'tooltip for the menu */
+ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) ||
+ (strstr(head, "Tip:") != NULL))) {
+ bpymenu_set_tooltip(scriptMenu, middle);
+ }
+ parser_state = 0;
+ }
+ break;
+
+ default:
+ parser_state = 0;
+ break;
+ }
+ }
+ }
+
+ else { /* shouldn't happen, it's checked in bpymenus_ParseDir */
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", fname);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* bpymenu_ParseDir:
+ * recursively scans folders looking for scripts to register.
+ *
+ * This function scans the scripts directory looking for .py files with the
+ * right header and menu info.
+ * - is_userdir defines if the script is in the default scripts dir or the
+ * user defined one (U.pythondir: is_userdir == 1);
+ * - parentdir is the parent dir name to store as part of the script filename,
+ * if we're down a subdir.
+ * Speed is important.
+ */
+static int bpymenu_ParseDir(char *dirname, char *parentdir, int is_userdir )
+{
+ DIR *dir;
+ FILE *file = NULL;
+ struct dirent *de;
+ struct stat status;
+ char *file_extension;
+ char path[FILE_MAX];
+ char subdir[FILE_MAX];
+ char *s = NULL;
+
+ dir = opendir(dirname);
+
+ if (dir != NULL) {
+ while ((de = readdir(dir)) != NULL) {
+
+ /* skip files and dirs starting with '.' or 'bpy' */
+ if ((de->d_name[0] == '.') || !strncmp(de->d_name, "bpy", 3)) {
+ continue;
+ }
+
+ BLI_make_file_string("/", path, dirname, de->d_name);
+
+ if (stat(path, &status) != 0) {
+ if (DEBUG)
+ fprintf(stderr, "stat %s failed: %s\n", path, strerror(errno));
+ }
+
+ if (S_ISREG(status.st_mode)) { /* is file */
+
+ file_extension = strstr(de->d_name, ".py");
+
+ if (file_extension && *(file_extension + 3) == '\0') {
+ file = fopen(path, "rb");
+
+ if (file) {
+ s = de->d_name;
+ if (parentdir) {
+ /* Join parentdir and de->d_name */
+ BLI_join_dirfile(subdir, parentdir, de->d_name);
+
+ s = subdir;
+ }
+ bpymenu_ParseFile(file, s, is_userdir);
+ fclose(file);
+ }
+
+ else {
+ if (DEBUG)
+ fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", path);
+ }
+ }
+ }
+
+ else if (S_ISDIR(status.st_mode)) { /* is subdir */
+ Dirs_Number++;
+ Dir_Depth++;
+ if (Dirs_Number > MAX_DIR_NUMBER) {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: too many subdirs.\n");
+ }
+ closedir(dir);
+ return -1;
+ }
+ else if (Dir_Depth > MAX_DIR_DEPTH) {
+ if (DEBUG)
+ fprintf(stderr,
+ "BPyMenus error: max depth reached traversing dir tree.\n");
+ closedir(dir);
+ return -1;
+ }
+ s = de->d_name;
+ if (parentdir) {
+ /* Join parentdir and de->d_name */
+ BLI_join_dirfile(subdir, parentdir, de->d_name);
+ s = subdir;
+ }
+ if (bpymenu_ParseDir(path, s, is_userdir) == -1) {
+ closedir(dir);
+ return -1;
+ }
+ Dir_Depth--;
+ }
+
+ }
+ closedir(dir);
+ }
+
+ else { /* open directory stream failed */
+ if (DEBUG)
+ fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )
+{
+ struct stat st;
+ int result;
+
+ result = stat( name, &st );
+
+ if( result == -1 )
+ return -1;
+
+ if( is_file ) {
+ if( !S_ISREG( st.st_mode ) )
+ return -2;
+ } else if( !S_ISDIR( st.st_mode ) )
+ return -2;
+
+ *mtime = st.st_mtime;
+
+ return 0;
+}
+
+/* BPyMenu_Init:
+ * import the bpython menus data to Blender, either from:
+ * - the BPYMENU_DATAFILE file (?/.blender/Bpymenus) or
+ * - the scripts dir(s), case newer than the datafile (then update the file).
+ * then fill the bpymenu table with this data.
+ * if param usedir != 0, then the data is recreated from the dir(s) anyway.
+*/
+int BPyMenu_Init( int usedir )
+{
+ char fname[FILE_MAXDIR];
+ char dirname[FILE_MAXDIR];
+ char upythondir[FILE_MAXDIR];
+ char *upydir = U.pythondir, *sdir = NULL;
+ time_t time_dir1 = 0, time_dir2 = 0, time_file = 0;
+ int stat_dir1 = 0, stat_dir2 = 0, stat_file = 0;
+ int i;
+
+ DEBUG = G.f & G_DEBUG; /* is Blender in debug mode (started with -d) ? */
+
+ /* init global bpymenu table (it is a list of pointers to struct BPyMenus
+ * for each available group: import, export, etc.) */
+ for( i = 0; i < PYMENU_TOTAL; i++ )
+ BPyMenuTable[i] = NULL;
+
+ if( DEBUG )
+ fprintf(stdout, "\nRegistering scripts in Blender menus ...\n\n" );
+
+ if( U.pythondir[0] == '\0') {
+ upydir = NULL;
+ }
+ else if (strcmp(U.pythondir, "/") == 0 || strcmp(U.pythondir, "//") == 0) {
+ /* these are not accepted to prevent possible slight slowdowns on startup;
+ * they should not be used as user defined scripts dir, anyway, also from
+ * speed considerations, since they'd not be dedicated scripts dirs */
+ if (DEBUG) fprintf(stderr,
+ "BPyMenus: invalid user defined Python scripts dir: \"/\" or \"//\".\n");
+ upydir = NULL;
+ }
+ else {
+ BLI_strncpy(upythondir, upydir, FILE_MAXDIR);
+ BLI_convertstringcode(upythondir, G.sce, 0);
+ }
+
+ sdir = bpy_gethome(1);
+
+ if (sdir) {
+ BLI_strncpy(dirname, sdir, FILE_MAXDIR);
+ stat_dir1 = bpymenu_GetStatMTime( dirname, 0, &time_dir1 );
+
+ if( stat_dir1 < 0 ) {
+ time_dir1 = 0;
+ if( DEBUG ) {
+ fprintf(stderr,
+ "\nDefault scripts dir: %s:\n%s\n", dirname, strerror(errno));
+ if( upydir )
+ fprintf(stdout,
+ "Getting scripts menu data from user defined dir: %s.\n",
+ upythondir );
+ }
+ }
+ }
+ else stat_dir1 = -1;
+
+ if( upydir ) {
+ stat_dir2 = bpymenu_GetStatMTime( upythondir, 0, &time_dir2 );
+
+ if( stat_dir2 < 0 ) {
+ time_dir2 = 0;
+ upydir = NULL;
+ if( DEBUG )
+ fprintf(stderr, "\nUser defined scripts dir: %s:\n%s.\n",
+ upythondir, strerror( errno ) );
+ if( stat_dir1 < 0 ) {
+ if( DEBUG )
+ fprintf(stderr, "\
+To have scripts in menus, please add them to the default scripts dir:\n\
+%s\n\
+and / or go to 'Info window -> File Paths tab' and set a valid path for\n\
+the user defined Python scripts dir.\n", dirname );
+ return -1;
+ }
+ }
+ }
+ else stat_dir2 = -1;
+
+ if( ( stat_dir1 < 0 ) && ( stat_dir2 < 0 ) ) {
+ if( DEBUG ) {
+ fprintf(stderr, "\nCannot register scripts in menus, no scripts dir"
+ " available.\nExpected default dir at: %s \n", dirname );
+ }
+ return -1;
+ }
+
+ if (usedir) stat_file = -1;
+ else { /* if we're not forced to use the dir */
+ char *homedir = bpy_gethome(0);
+
+ if (homedir) {
+ BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
+ stat_file = bpymenu_GetStatMTime( fname, 1, &time_file );
+ if( stat_file < 0 )
+ time_file = 0;
+
+ /* comparing dates */
+
+ if((stat_file == 0)
+ && (time_file > time_dir1) && (time_file > time_dir2))
+ { /* file is newer */
+ stat_file = bpymenu_CreateFromFile( ); /* -1 if an error occurred */
+ if( !stat_file && DEBUG )
+ fprintf(stdout,
+ "Getting menu data for scripts from file:\n%s\n\n", fname );
+ }
+ else stat_file = -1;
+ }
+ else stat_file = -1; /* -1 to use dirs: didn't use file or it was corrupted */
+ }
+
+ if( stat_file == -1 ) { /* use dirs */
+ if( DEBUG ) {
+ fprintf(stdout,
+ "Getting menu data for scripts from dir(s):\ndefault: %s\n", dirname );
+ if( upydir )
+ fprintf(stdout, "user defined: %s\n", upythondir );
+ fprintf(stdout, "\n");
+ }
+ if( stat_dir1 == 0 ) {
+ i = bpymenu_ParseDir( dirname, NULL, 0 );
+ if (i == -1 && DEBUG)
+ fprintf(stderr, "Default scripts dir does not seem valid.\n\n");
+ }
+ if( stat_dir2 == 0 ) {
+ BLI_strncpy(dirname, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(dirname, G.sce, 0);
+ i = bpymenu_ParseDir( dirname, NULL, 1 );
+ if (i == -1 && DEBUG)
+ fprintf(stderr, "User defined scripts dir does not seem valid.\n\n");
+ }
+
+ /* check if we got any data */
+ for( i = 0; i < PYMENU_TOTAL; i++ )
+ if( BPyMenuTable[i] )
+ break;
+
+ /* if we got, recreate the file */
+ if( i < PYMENU_TOTAL )
+ bpymenu_WriteDataFile( );
+ else if( DEBUG ) {
+ fprintf(stderr, "\n\
+Warning: Registering scripts in menus -- no info found.\n\
+Either your scripts dirs have no .py scripts or the scripts\n\
+don't have a header with registration data.\n\
+Default scripts dir is:\n\
+%s\n", dirname );
+ if( upydir )
+ fprintf(stderr, "User defined scripts dir is: %s\n",
+ upythondir );
+ }
+ }
+
+ return 0;
+}
diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h
new file mode 100644
index 00000000000..6cdea608b10
--- /dev/null
+++ b/source/blender/python/BPY_menus.h
@@ -0,0 +1,128 @@
+/*
+ * $Id: BPY_menus.h 12931 2007-12-17 18:20:48Z theeth $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano, Matt Ebb
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef BPY_MENUS_H
+#define BPY_MENUS_H
+
+/* This header exposes BPyMenu related public declarations. The implementation
+ * adds 'dynamic' menus to Blender, letting scripts register themselves in any
+ * of a few pre-defined (trivial to upgrade) places in menus. These places or
+ * slots are called groups here (Import, Export, etc). This is how it works:
+ * - scripts at dirs user pref U.pythondir and .blender/scripts/ are scanned
+ * for registration info.
+ * - this data is also saved to a Bpymenus file at the user's .blender/ dir and
+ * only re-created when the scripts folder gets modified.
+ * - on start-up Blender uses this info to fill a table, which is used to
+ * create the menu entries when they are needed (see header_info.c or
+ * header_script.c, under source/blender/src/, for examples).
+*/
+
+/* These two structs hold py menu/submenu info.
+ * BPyMenu holds a script's name (as should appear in the menu) and filename,
+ * plus an optional list of submenus. Each submenu is related to a string
+ * (arg) that the script can get from the __script__ pydict, to know which
+ * submenu was chosen. */
+
+typedef struct BPySubMenu {
+ char *name;
+ char *arg;
+ struct BPySubMenu *next;
+} BPySubMenu;
+
+typedef struct BPyMenu {
+ char *name;
+ char *filename;
+ char *tooltip;
+ short version; /* Blender version */
+ int dir; /* 0: default, 1: U.pythondir */
+ struct BPySubMenu *submenus;
+ struct BPyMenu *next;
+} BPyMenu;
+
+/* Scripts can be added to only a few pre-defined places in menus, like
+ * File->Import, File->Export, etc. (for speed and better control).
+ * To make a new menu 'slot' available for scripts:
+ * - add an entry to the enum below, before PYMENU_TOTAL, of course;
+ * - update the bpymenu_group_atoi() and BPyMenu_group_itoa() functions in
+ * BPY_menus.c;
+ * - add the necessary code to the header_***.c file in
+ * source/blender/src/, like done in header_info.c for import/export;
+*/
+typedef enum {
+ PYMENU_ADD,/* creates new objects */
+ PYMENU_ANIMATION,
+ PYMENU_EXPORT,
+ PYMENU_IMPORT,
+ PYMENU_MATERIALS,
+ PYMENU_MESH,
+ PYMENU_MISC,
+ PYMENU_OBJECT,
+ PYMENU_RENDER,/* exporters to external renderers */
+ PYMENU_SYSTEM,
+ PYMENU_THEMES,
+ PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */
+ PYMENU_IMAGE,/* Image editing tools, to go in UV/Image editor space, 'Image' menu */
+ PYMENU_WIZARDS,/* complex 'app' scripts */
+
+ /* entries put after Wizards don't appear at the Scripts win->Scripts menu;
+ * see define right below */
+
+ PYMENU_FACESELECT,
+ PYMENU_WEIGHTPAINT,
+ PYMENU_VERTEXPAINT,
+ PYMENU_UVCALCULATION,
+ PYMENU_ARMATURE,
+ PYMENU_SCRIPTTEMPLATE,
+ PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/
+ PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */
+ PYMENU_HELPWEBSITES,/* Help -> Websites submenu */
+ PYMENU_MESHFACEKEY, /* face key in mesh editmode */
+ PYMENU_ADDMESH, /* adds mesh */
+ PYMENU_TOTAL
+} PYMENUHOOKS;
+
+#define PYMENU_SCRIPTS_MENU_TOTAL (PYMENU_WIZARDS + 1)
+
+/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
+ * where they can appear (see PYMENUHOOKS enum above).
+*/
+extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */
+
+/* public functions: */
+int BPyMenu_Init( int usedir );
+void BPyMenu_RemoveAllEntries( void );
+void BPyMenu_PrintAllEntries( void );
+char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short group );
+char *BPyMenu_group_itoa( short group );
+struct BPyMenu *BPyMenu_GetEntry( short group, short pos );
+
+#endif /* BPY_MENUS_H */
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index 7700e6bc2aa..d15970e1df4 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -24,12 +24,10 @@
# ***** END GPL LICENSE BLOCK *****
FILE(GLOB SRC intern/*.c)
-FILE(GLOB GENSRC generic/*.c)
SET(INC
. ../../../intern/guardedalloc ../blenlib ../makesdna ../makesrna
../blenkernel ../editors/include ../windowmanager ${PYTHON_INC}
- ../../../extern/glew/include
)
IF(WITH_OPENEXR)
@@ -49,5 +47,3 @@ ENDIF(WITH_FFMPEG)
ADD_DEFINITIONS(-DWITH_CCGSUBSURF)
BLENDERLIB(bf_python "${SRC}" "${INC}")
-BLENDERLIB(bf_gen_python "${GENSRC}" "${INC}")
-
diff --git a/source/blender/python/Makefile b/source/blender/python/Makefile
index 8e2a04b8449..c830fbb3ccf 100644
--- a/source/blender/python/Makefile
+++ b/source/blender/python/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -29,6 +29,6 @@
# Bounces make to subdirectories.
SOURCEDIR = source/blender/python
-DIRS = intern generic
+DIRS = intern
include nan_subdirs.mk
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 73dc171fc3e..9d7fcf6a9cf 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c')
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
-incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
+incs += ' #intern/guardedalloc #intern/memutil'
incs += ' ' + env['BF_PYTHON_INC']
defs = []
@@ -15,7 +15,3 @@ if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc') and env['BF_DEBUG']:
env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [140])
-
-# generic
-sources = env.Glob('generic/*.c')
-env.BlenderLib( libname = 'bf_gen_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [361]) # ketsji is 360
diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c
deleted file mode 100644
index de82781cf3a..00000000000
--- a/source/blender/python/generic/BGL.c
+++ /dev/null
@@ -1,1610 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Willian P. Germano
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-
-/* This file is the Blender.BGL part of opy_draw.c, from the old
- * bpython/intern dir, with minor changes to adapt it to the new Python
- * implementation. The BGL submodule "wraps" OpenGL functions and constants,
- * allowing script writers to make OpenGL calls in their Python scripts. */
-
-#include "BGL.h" /*This must come first */
-
-#include "MEM_guardedalloc.h"
-
-static int type_size( int type );
-static Buffer *make_buffer( int type, int ndimensions, int *dimensions );
-
-static char Method_Buffer_doc[] =
- "(type, dimensions, [template]) - Create a new Buffer object\n\n\
-(type) - The format to store data in\n\
-(dimensions) - An int or sequence specifying the dimensions of the buffer\n\
-[template] - A sequence of matching dimensions to the buffer to be created\n\
- which will be used to initialize the Buffer.\n\n\
-If a template is not passed in all fields will be initialized to 0.\n\n\
-The type should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, or GL_DOUBLE.\n\
-If the dimensions are specified as an int a linear buffer will be\n\
-created. If a sequence is passed for the dimensions the buffer\n\
-will have len(sequence) dimensions, where the size for each dimension\n\
-is determined by the value in the sequence at that index.\n\n\
-For example, passing [100, 100] will create a 2 dimensional\n\
-square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\
-buffer which is twice as deep as it is wide or high.";
-
-static PyObject *Method_Buffer( PyObject * self, PyObject * args );
-
-/* Buffer sequence methods */
-
-static int Buffer_len( PyObject * self );
-static PyObject *Buffer_item( PyObject * self, int i );
-static PyObject *Buffer_slice( PyObject * self, int begin, int end );
-static int Buffer_ass_item( PyObject * self, int i, PyObject * v );
-static int Buffer_ass_slice( PyObject * self, int begin, int end,
- PyObject * seq );
-
-static PySequenceMethods Buffer_SeqMethods = {
- ( inquiry ) Buffer_len, /*sq_length */
- ( binaryfunc ) 0, /*sq_concat */
- ( ssizeargfunc ) 0, /*sq_repeat */
- ( ssizeargfunc ) Buffer_item, /*sq_item */
- ( ssizessizeargfunc ) Buffer_slice, /*sq_slice */
- ( ssizeobjargproc ) Buffer_ass_item, /*sq_ass_item */
- ( ssizessizeobjargproc ) Buffer_ass_slice, /*sq_ass_slice */
-};
-
-static void Buffer_dealloc( PyObject * self );
-static PyObject *Buffer_tolist( PyObject * self );
-static PyObject *Buffer_dimensions( PyObject * self );
-static PyObject *Buffer_getattr( PyObject * self, char *name );
-static PyObject *Buffer_repr( PyObject * self );
-
-PyTypeObject buffer_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- "buffer", /*tp_name */
- sizeof( Buffer ), /*tp_basicsize */
- 0, /*tp_itemsize */
- ( destructor ) Buffer_dealloc, /*tp_dealloc */
- ( printfunc ) 0, /*tp_print */
- ( getattrfunc ) Buffer_getattr, /*tp_getattr */
- ( setattrfunc ) 0, /*tp_setattr */
- 0, /*tp_compare */
- ( reprfunc ) Buffer_repr, /*tp_repr */
- 0, /*tp_as_number */
- &Buffer_SeqMethods, /*tp_as_sequence */
-};
-
-/* #ifndef __APPLE__ */
-
-#define BGL_Wrap(nargs, funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
- arg_def##nargs arg_list; \
- ret_def_##ret; \
- if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\
- ret_set_##ret gl##funcname (arg_var##nargs arg_list);\
- ret_ret_##ret; \
-}
-
-#define BGLU_Wrap(nargs, funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\
- arg_def##nargs arg_list; \
- ret_def_##ret; \
- if(!PyArg_ParseTuple(args, arg_str##nargs arg_list, arg_ref##nargs arg_list)) return NULL;\
- ret_set_##ret glu##funcname (arg_var##nargs arg_list);\
- ret_ret_##ret; \
-}
-
-/* #endif */
-
-/********/
-static int type_size(int type)
-{
- switch (type) {
- case GL_BYTE:
- return sizeof(char);
- case GL_SHORT:
- return sizeof(short);
- case GL_INT:
- return sizeof(int);
- case GL_FLOAT:
- return sizeof(float);
- case GL_DOUBLE:
- return sizeof(double);
- }
- return -1;
-}
-
-static Buffer *make_buffer(int type, int ndimensions, int *dimensions)
-{
- Buffer *buffer;
- void *buf= NULL;
- int i, size, length;
-
- length= 1;
- for (i=0; i<ndimensions; i++)
- length*= dimensions[i];
-
- size= type_size(type);
-
- buf= MEM_mallocN(length*size, "Buffer buffer");
-
- buffer= (Buffer *) PyObject_NEW(Buffer, &buffer_Type);
- buffer->parent= NULL;
- buffer->ndimensions= ndimensions;
- buffer->dimensions= dimensions;
- buffer->type= type;
- buffer->buf.asvoid= buf;
-
- for (i= 0; i<length; i++) {
- if (type==GL_BYTE)
- buffer->buf.asbyte[i]= 0;
- else if (type==GL_SHORT)
- buffer->buf.asshort[i]= 0;
- else if (type==GL_INT)
- buffer->buf.asint[i]= 0;
- else if (type==GL_FLOAT)
- buffer->buf.asfloat[i]= 0.0f;
- else if (type==GL_DOUBLE)
- buffer->buf.asdouble[i]= 0.0;
- }
- return buffer;
-}
-
-static PyObject *Method_Buffer (PyObject *self, PyObject *args)
-{
- PyObject *length_ob= NULL, *template= NULL;
- Buffer *buffer;
-
- int i, type;
- int *dimensions = 0, ndimensions = 0;
-
- if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template)) {
- PyErr_SetString(PyExc_AttributeError, "expected an int and one or two PyObjects");
- return NULL;
- }
- if (type!=GL_BYTE && type!=GL_SHORT && type!=GL_INT && type!=GL_FLOAT && type!=GL_DOUBLE) {
- PyErr_SetString(PyExc_AttributeError, "invalid first argument type, should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE");
- return NULL;
- }
-
- if (PyNumber_Check(length_ob)) {
- ndimensions= 1;
- dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
- dimensions[0]= PyLong_AsLong(length_ob);
- } else if (PySequence_Check(length_ob)) {
- ndimensions= PySequence_Length(length_ob);
- dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions");
- for (i=0; i<ndimensions; i++) {
- PyObject *ob= PySequence_GetItem(length_ob, i);
-
- if (!PyNumber_Check(ob)) dimensions[i]= 1;
- else dimensions[i]= PyLong_AsLong(ob);
- Py_DECREF(ob);
- }
- }
-
- buffer= make_buffer(type, ndimensions, dimensions);
- if (template && ndimensions) {
- if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], template)) {
- Py_DECREF(buffer);
- return NULL;
- }
- }
-
- return (PyObject *) buffer;
-}
-
-/*@ Buffer sequence methods */
-
-static int Buffer_len(PyObject *self)
-{
- Buffer *buf= (Buffer *) self;
- return buf->dimensions[0];
-}
-
-static PyObject *Buffer_item(PyObject *self, int i)
-{
- Buffer *buf= (Buffer *) self;
-
- if (i >= buf->dimensions[0]) {
- PyErr_SetString(PyExc_IndexError, "array index out of range");
- return NULL;
- }
-
- if (buf->ndimensions==1) {
- switch (buf->type) {
- case GL_BYTE: return Py_BuildValue("b", buf->buf.asbyte[i]);
- case GL_SHORT: return Py_BuildValue("h", buf->buf.asshort[i]);
- case GL_INT: return Py_BuildValue("i", buf->buf.asint[i]);
- case GL_FLOAT: return PyFloat_FromDouble(buf->buf.asfloat[i]);
- case GL_DOUBLE: return Py_BuildValue("d", buf->buf.asdouble[i]);
- }
- } else {
- Buffer *newbuf;
- int j, length, size;
-
- length= 1;
- for (j=1; j<buf->ndimensions; j++) {
- length*= buf->dimensions[j];
- }
- size= type_size(buf->type);
-
- newbuf= (Buffer *) PyObject_NEW(Buffer, &buffer_Type);
-
- Py_INCREF(self);
- newbuf->parent= self;
-
- newbuf->ndimensions= buf->ndimensions-1;
- newbuf->type= buf->type;
- newbuf->buf.asvoid= buf->buf.asbyte + i*length*size;
- newbuf->dimensions= MEM_mallocN(newbuf->ndimensions*sizeof(int),
- "Buffer dimensions");
- memcpy(newbuf->dimensions, buf->dimensions+1,
- newbuf->ndimensions*sizeof(int));
-
- return (PyObject *) newbuf;
- }
-
- return NULL;
-}
-
-static PyObject *Buffer_slice(PyObject *self, int begin, int end)
-{
- Buffer *buf= (Buffer *) self;
- PyObject *list;
- int count;
-
- if (begin<0) begin= 0;
- if (end>buf->dimensions[0])
- end= buf->dimensions[0];
- if (begin>end) begin= end;
-
- list= PyList_New(end-begin);
-
- for (count= begin; count<end; count++)
- PyList_SetItem(list, count-begin, Buffer_item(self, count));
-
- return list;
-}
-
-static int Buffer_ass_item(PyObject *self, int i, PyObject *v)
-{
- Buffer *buf= (Buffer *) self;
-
- if (i >= buf->dimensions[0]) {
- PyErr_SetString(PyExc_IndexError, "array assignment index out of range");
- return -1;
- }
-
- if (buf->ndimensions!=1) {
- PyObject *row= Buffer_item(self, i);
- int ret;
-
- if (!row) return -1;
- ret= Buffer_ass_slice(row, 0, buf->dimensions[1], v);
- Py_DECREF(row);
- return ret;
- }
-
- if (buf->type==GL_BYTE) {
- if (!PyArg_Parse(v, "b;Coordinates must be ints", &buf->buf.asbyte[i]))
- return -1;
- } else if (buf->type==GL_SHORT) {
- if (!PyArg_Parse(v, "h;Coordinates must be ints", &buf->buf.asshort[i]))
- return -1;
-
- } else if (buf->type==GL_INT) {
- if (!PyArg_Parse(v, "i;Coordinates must be ints", &buf->buf.asint[i]))
- return -1;
- } else if (buf->type==GL_FLOAT) {
- if (!PyArg_Parse(v, "f;Coordinates must be floats", &buf->buf.asfloat[i]))
- return -1;
- } else if (buf->type==GL_DOUBLE) {
- if (!PyArg_Parse(v, "d;Coordinates must be floats", &buf->buf.asdouble[i]))
- return -1;
- }
- return 0;
-}
-
-static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq)
-{
- Buffer *buf= (Buffer *) self;
- PyObject *item;
- int count, err=0;
-
- if (begin<0) begin= 0;
- if (end>buf->dimensions[0]) end= buf->dimensions[0];
- if (begin>end) begin= end;
-
- if (!PySequence_Check(seq)) {
- PyErr_SetString(PyExc_TypeError,
- "illegal argument type for built-in operation");
- return -1;
- }
-
- if (PySequence_Length(seq)!=(end-begin)) {
- PyErr_SetString(PyExc_TypeError, "size mismatch in assignment");
- return -1;
- }
-
- for (count= begin; count<end; count++) {
- item= PySequence_GetItem(seq, count-begin);
- err= Buffer_ass_item(self, count, item);
- Py_DECREF(item);
- if (err) break;
- }
- return err;
-}
-
-static void Buffer_dealloc(PyObject *self)
-{
- Buffer *buf = (Buffer *)self;
-
- if (buf->parent) Py_DECREF (buf->parent);
- else MEM_freeN (buf->buf.asvoid);
-
- MEM_freeN (buf->dimensions);
-
- PyObject_DEL (self);
-}
-
-static PyObject *Buffer_tolist(PyObject *self)
-{
- int i, len= ((Buffer *)self)->dimensions[0];
- PyObject *list= PyList_New(len);
-
- for (i=0; i<len; i++) {
- PyList_SetItem(list, i, Buffer_item(self, i));
- }
-
- return list;
-}
-
-static PyObject *Buffer_dimensions(PyObject *self)
-{
- Buffer *buffer= (Buffer *) self;
- PyObject *list= PyList_New(buffer->ndimensions);
- int i;
-
- for (i= 0; i<buffer->ndimensions; i++) {
- PyList_SetItem(list, i, PyLong_FromLong(buffer->dimensions[i]));
- }
-
- return list;
-}
-
-static PyObject *Buffer_getattr(PyObject *self, char *name)
-{
- if (strcmp(name, "list")==0) return Buffer_tolist(self);
- else if (strcmp(name, "dimensions")==0) return Buffer_dimensions(self);
-
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
-}
-
-static PyObject *Buffer_repr(PyObject *self)
-{
- PyObject *list= Buffer_tolist(self);
- PyObject *repr= PyObject_Repr(list);
- Py_DECREF(list);
-
- return repr;
-}
-
-
-BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
-BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
-BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
-BGL_Wrap(1, Begin, void, (GLenum))
-BGL_Wrap(2, BindTexture, void, (GLenum, GLuint))
-BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat,
- GLfloat, GLfloat, GLfloat, GLubyteP))
-BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum))
-BGL_Wrap(1, CallList, void, (GLuint))
-BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP))
-BGL_Wrap(1, Clear, void, (GLbitfield))
-BGL_Wrap(4, ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(4, ClearColor, void, (GLclampf, GLclampf, GLclampf, GLclampf))
-BGL_Wrap(1, ClearDepth, void, (GLclampd))
-BGL_Wrap(1, ClearIndex, void, (GLfloat))
-BGL_Wrap(1, ClearStencil, void, (GLint))
-BGL_Wrap(2, ClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(3, Color3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Color3bv, void, (GLbyteP))
-BGL_Wrap(3, Color3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Color3dv, void, (GLdoubleP))
-BGL_Wrap(3, Color3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Color3fv, void, (GLfloatP))
-BGL_Wrap(3, Color3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Color3iv, void, (GLintP))
-BGL_Wrap(3, Color3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Color3sv, void, (GLshortP))
-BGL_Wrap(3, Color3ub, void, (GLubyte, GLubyte, GLubyte))
-BGL_Wrap(1, Color3ubv, void, (GLubyteP))
-BGL_Wrap(3, Color3ui, void, (GLuint, GLuint, GLuint))
-BGL_Wrap(1, Color3uiv, void, (GLuintP))
-BGL_Wrap(3, Color3us, void, (GLushort, GLushort, GLushort))
-BGL_Wrap(1, Color3usv, void, (GLushortP))
-BGL_Wrap(4, Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Color4bv, void, (GLbyteP))
-BGL_Wrap(4, Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Color4dv, void, (GLdoubleP))
-BGL_Wrap(4, Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Color4fv, void, (GLfloatP))
-BGL_Wrap(4, Color4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, Color4iv, void, (GLintP))
-BGL_Wrap(4, Color4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, Color4sv, void, (GLshortP))
-BGL_Wrap(4, Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(1, Color4ubv, void, (GLubyteP))
-BGL_Wrap(4, Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
-BGL_Wrap(1, Color4uiv, void, (GLuintP))
-BGL_Wrap(4, Color4us, void, (GLushort, GLushort, GLushort, GLushort))
-BGL_Wrap(1, Color4usv, void, (GLushortP))
-BGL_Wrap(4, ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
-BGL_Wrap(2, ColorMaterial, void, (GLenum, GLenum))
-BGL_Wrap(5, CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
-BGL_Wrap(1, CullFace, void, (GLenum))
-BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei))
-BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(1, DepthFunc, void, (GLenum))
-BGL_Wrap(1, DepthMask, void, (GLboolean))
-BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
-BGL_Wrap(1, Disable, void, (GLenum))
-BGL_Wrap(1, DrawBuffer, void, (GLenum))
-BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(1, EdgeFlag, void, (GLboolean))
-BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
-BGL_Wrap(1, Enable, void, (GLenum))
-BGL_Wrap(1, End, void, (void))
-BGL_Wrap(1, EndList, void, (void))
-BGL_Wrap(1, EvalCoord1d, void, (GLdouble))
-BGL_Wrap(1, EvalCoord1dv, void, (GLdoubleP))
-BGL_Wrap(1, EvalCoord1f, void, (GLfloat))
-BGL_Wrap(1, EvalCoord1fv, void, (GLfloatP))
-BGL_Wrap(2, EvalCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, EvalCoord2dv, void, (GLdoubleP))
-BGL_Wrap(2, EvalCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, EvalCoord2fv, void, (GLfloatP))
-BGL_Wrap(3, EvalMesh1, void, (GLenum, GLint, GLint))
-BGL_Wrap(5, EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(1, EvalPoint1, void, (GLint))
-BGL_Wrap(2, EvalPoint2, void, (GLint, GLint))
-BGL_Wrap(3, FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
-BGL_Wrap(1, Finish, void, (void))
-BGL_Wrap(1, Flush, void, (void))
-BGL_Wrap(2, Fogf, void, (GLenum, GLfloat))
-BGL_Wrap(2, Fogfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, Fogi, void, (GLenum, GLint))
-BGL_Wrap(2, Fogiv, void, (GLenum, GLintP))
-BGL_Wrap(1, FrontFace, void, (GLenum))
-BGL_Wrap(6, Frustum, void, (GLdouble, GLdouble,
- GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, GenLists, GLuint, (GLsizei))
-BGL_Wrap(2, GenTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(2, GetBooleanv, void, (GLenum, GLbooleanP))
-BGL_Wrap(2, GetClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(2, GetDoublev, void, (GLenum, GLdoubleP))
-BGL_Wrap(1, GetError, GLenum, (void))
-BGL_Wrap(2, GetFloatv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, GetIntegerv, void, (GLenum, GLintP))
-BGL_Wrap(3, GetLightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetLightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetMapdv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, GetMapfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetMapiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetMaterialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, GetPixelMapfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, GetPixelMapuiv, void, (GLenum, GLuintP))
-BGL_Wrap(2, GetPixelMapusv, void, (GLenum, GLushortP))
-BGL_Wrap(1, GetPolygonStipple,void, (GLubyteP))
-BGL_Wrap(1, GetString, GLstring, (GLenum))
-BGL_Wrap(3, GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(5, GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(4, GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
-BGL_Wrap(4, GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
-BGL_Wrap(3, GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, GetTexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, Hint, void, (GLenum, GLenum))
-BGL_Wrap(1, IndexMask, void, (GLuint))
-BGL_Wrap(1, Indexd, void, (GLdouble))
-BGL_Wrap(1, Indexdv, void, (GLdoubleP))
-BGL_Wrap(1, Indexf, void, (GLfloat))
-BGL_Wrap(1, Indexfv, void, (GLfloatP))
-BGL_Wrap(1, Indexi, void, (GLint))
-BGL_Wrap(1, Indexiv, void, (GLintP))
-BGL_Wrap(1, Indexs, void, (GLshort))
-BGL_Wrap(1, Indexsv, void, (GLshortP))
-BGL_Wrap(1, InitNames, void, (void))
-BGL_Wrap(1, IsEnabled, GLboolean, (GLenum))
-BGL_Wrap(1, IsList, GLboolean, (GLuint))
-BGL_Wrap(1, IsTexture, GLboolean, (GLuint))
-BGL_Wrap(2, LightModelf, void, (GLenum, GLfloat))
-BGL_Wrap(2, LightModelfv, void, (GLenum, GLfloatP))
-BGL_Wrap(2, LightModeli, void, (GLenum, GLint))
-BGL_Wrap(2, LightModeliv, void, (GLenum, GLintP))
-BGL_Wrap(3, Lightf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, Lightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(2, LineStipple, void, (GLint, GLushort))
-BGL_Wrap(1, LineWidth, void, (GLfloat))
-BGL_Wrap(1, ListBase, void, (GLuint))
-BGL_Wrap(1, LoadIdentity, void, (void))
-BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP))
-BGL_Wrap(1, LoadMatrixf, void, (GLfloatP))
-BGL_Wrap(1, LoadName, void, (GLuint))
-BGL_Wrap(1, LogicOp, void, (GLenum))
-BGL_Wrap(6, Map1d, void, (GLenum, GLdouble, GLdouble,
- GLint, GLint, GLdoubleP))
-BGL_Wrap(6, Map1f, void, (GLenum, GLfloat, GLfloat,
- GLint, GLint, GLfloatP))
-BGL_Wrap(10, Map2d, void, (GLenum, GLdouble, GLdouble,
- GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(10, Map2f, void, (GLenum, GLfloat, GLfloat,
- GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(3, MapGrid1d, void, (GLint, GLdouble, GLdouble))
-BGL_Wrap(3, MapGrid1f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(6, MapGrid2d, void, (GLint, GLdouble, GLdouble,
- GLint, GLdouble, GLdouble))
-BGL_Wrap(6, MapGrid2f, void, (GLint, GLfloat, GLfloat,
- GLint, GLfloat, GLfloat))
-BGL_Wrap(3, Materialf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, Materialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, Materiali, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, Materialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(1, MatrixMode, void, (GLenum))
-BGL_Wrap(1, MultMatrixd, void, (GLdoubleP))
-BGL_Wrap(1, MultMatrixf, void, (GLfloatP))
-BGL_Wrap(2, NewList, void, (GLuint, GLenum))
-BGL_Wrap(3, Normal3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(1, Normal3bv, void, (GLbyteP))
-BGL_Wrap(3, Normal3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Normal3dv, void, (GLdoubleP))
-BGL_Wrap(3, Normal3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Normal3fv, void, (GLfloatP))
-BGL_Wrap(3, Normal3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Normal3iv, void, (GLintP))
-BGL_Wrap(3, Normal3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Normal3sv, void, (GLshortP))
-BGL_Wrap(6, Ortho, void, (GLdouble, GLdouble,
- GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, PassThrough, void, (GLfloat))
-BGL_Wrap(3, PixelMapfv, void, (GLenum, GLint, GLfloatP))
-BGL_Wrap(3, PixelMapuiv, void, (GLenum, GLint, GLuintP))
-BGL_Wrap(3, PixelMapusv, void, (GLenum, GLint, GLushortP))
-BGL_Wrap(2, PixelStoref, void, (GLenum, GLfloat))
-BGL_Wrap(2, PixelStorei, void, (GLenum, GLint))
-BGL_Wrap(2, PixelTransferf, void, (GLenum, GLfloat))
-BGL_Wrap(2, PixelTransferi, void, (GLenum, GLint))
-BGL_Wrap(2, PixelZoom, void, (GLfloat, GLfloat))
-BGL_Wrap(1, PointSize, void, (GLfloat))
-BGL_Wrap(2, PolygonMode, void, (GLenum, GLenum))
-BGL_Wrap(2, PolygonOffset, void, (GLfloat, GLfloat))
-BGL_Wrap(1, PolygonStipple, void, (GLubyteP))
-BGL_Wrap(1, PopAttrib, void, (void))
-BGL_Wrap(1, PopClientAttrib, void, (void))
-BGL_Wrap(1, PopMatrix, void, (void))
-BGL_Wrap(1, PopName, void, (void))
-BGL_Wrap(3, PrioritizeTextures, void, (GLsizei, GLuintP, GLclampfP))
-BGL_Wrap(1, PushAttrib, void, (GLbitfield))
-BGL_Wrap(1, PushClientAttrib, void, (GLbitfield))
-BGL_Wrap(1, PushMatrix, void, (void))
-BGL_Wrap(1, PushName, void, (GLuint))
-BGL_Wrap(2, RasterPos2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos2dv, void, (GLdoubleP))
-BGL_Wrap(2, RasterPos2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos2fv, void, (GLfloatP))
-BGL_Wrap(2, RasterPos2i, void, (GLint, GLint))
-BGL_Wrap(1, RasterPos2iv, void, (GLintP))
-BGL_Wrap(2, RasterPos2s, void, (GLshort, GLshort))
-BGL_Wrap(1, RasterPos2sv, void, (GLshortP))
-BGL_Wrap(3, RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos3dv, void, (GLdoubleP))
-BGL_Wrap(3, RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos3fv, void, (GLfloatP))
-BGL_Wrap(3, RasterPos3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, RasterPos3iv, void, (GLintP))
-BGL_Wrap(3, RasterPos3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, RasterPos3sv, void, (GLshortP))
-BGL_Wrap(4, RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, RasterPos4dv, void, (GLdoubleP))
-BGL_Wrap(4, RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, RasterPos4fv, void, (GLfloatP))
-BGL_Wrap(4, RasterPos4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, RasterPos4iv, void, (GLintP))
-BGL_Wrap(4, RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, RasterPos4sv, void, (GLshortP))
-BGL_Wrap(1, ReadBuffer, void, (GLenum))
-BGL_Wrap(7, ReadPixels, void, (GLint, GLint, GLsizei,
- GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(4, Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(2, Rectdv, void, (GLdoubleP, GLdoubleP))
-BGL_Wrap(4, Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(2, Rectfv, void, (GLfloatP, GLfloatP))
-BGL_Wrap(4, Recti, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(2, Rectiv, void, (GLintP, GLintP))
-BGL_Wrap(4, Rects, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(2, Rectsv, void, (GLshortP, GLshortP))
-BGL_Wrap(1, RenderMode, GLint, (GLenum))
-BGL_Wrap(4, Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(4, Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(3, Scaled, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(3, Scalef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(4, Scissor, void, (GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(2, SelectBuffer, void, (GLsizei, GLuintP))
-BGL_Wrap(1, ShadeModel, void, (GLenum))
-BGL_Wrap(3, StencilFunc, void, (GLenum, GLint, GLuint))
-BGL_Wrap(1, StencilMask, void, (GLuint))
-BGL_Wrap(3, StencilOp, void, (GLenum, GLenum, GLenum))
-BGL_Wrap(1, TexCoord1d, void, (GLdouble))
-BGL_Wrap(1, TexCoord1dv, void, (GLdoubleP))
-BGL_Wrap(1, TexCoord1f, void, (GLfloat))
-BGL_Wrap(1, TexCoord1fv, void, (GLfloatP))
-BGL_Wrap(1, TexCoord1i, void, (GLint))
-BGL_Wrap(1, TexCoord1iv, void, (GLintP))
-BGL_Wrap(1, TexCoord1s, void, (GLshort))
-BGL_Wrap(1, TexCoord1sv, void, (GLshortP))
-BGL_Wrap(2, TexCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord2dv, void, (GLdoubleP))
-BGL_Wrap(2, TexCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord2fv, void, (GLfloatP))
-BGL_Wrap(2, TexCoord2i, void, (GLint, GLint))
-BGL_Wrap(1, TexCoord2iv, void, (GLintP))
-BGL_Wrap(2, TexCoord2s, void, (GLshort, GLshort))
-BGL_Wrap(1, TexCoord2sv, void, (GLshortP))
-BGL_Wrap(3, TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord3dv, void, (GLdoubleP))
-BGL_Wrap(3, TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord3fv, void, (GLfloatP))
-BGL_Wrap(3, TexCoord3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, TexCoord3iv, void, (GLintP))
-BGL_Wrap(3, TexCoord3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, TexCoord3sv, void, (GLshortP))
-BGL_Wrap(4, TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, TexCoord4dv, void, (GLdoubleP))
-BGL_Wrap(4, TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, TexCoord4fv, void, (GLfloatP))
-BGL_Wrap(4, TexCoord4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, TexCoord4iv, void, (GLintP))
-BGL_Wrap(4, TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, TexCoord4sv, void, (GLshortP))
-BGL_Wrap(3, TexEnvf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexEnvi, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, TexGend, void, (GLenum, GLenum, GLdouble))
-BGL_Wrap(3, TexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(3, TexGenf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexGeni, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexGeniv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(8, TexImage1D, void, (GLenum, GLint, GLint,
- GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(9, TexImage2D, void, (GLenum, GLint, GLint,
- GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
-BGL_Wrap(3, TexParameterf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(3, TexParameterfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(3, TexParameteri, void, (GLenum, GLenum, GLint))
-BGL_Wrap(3, TexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(3, Translated, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(3, Translatef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(2, Vertex2d, void, (GLdouble, GLdouble))
-BGL_Wrap(1, Vertex2dv, void, (GLdoubleP))
-BGL_Wrap(2, Vertex2f, void, (GLfloat, GLfloat))
-BGL_Wrap(1, Vertex2fv, void, (GLfloatP))
-BGL_Wrap(2, Vertex2i, void, (GLint, GLint))
-BGL_Wrap(1, Vertex2iv, void, (GLintP))
-BGL_Wrap(2, Vertex2s, void, (GLshort, GLshort))
-BGL_Wrap(1, Vertex2sv, void, (GLshortP))
-BGL_Wrap(3, Vertex3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Vertex3dv, void, (GLdoubleP))
-BGL_Wrap(3, Vertex3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Vertex3fv, void, (GLfloatP))
-BGL_Wrap(3, Vertex3i, void, (GLint, GLint, GLint))
-BGL_Wrap(1, Vertex3iv, void, (GLintP))
-BGL_Wrap(3, Vertex3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(1, Vertex3sv, void, (GLshortP))
-BGL_Wrap(4, Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(1, Vertex4dv, void, (GLdoubleP))
-BGL_Wrap(4, Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(1, Vertex4fv, void, (GLfloatP))
-BGL_Wrap(4, Vertex4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(1, Vertex4iv, void, (GLintP))
-BGL_Wrap(4, Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(1, Vertex4sv, void, (GLshortP))
-BGL_Wrap(4, Viewport, void, (GLint, GLint, GLsizei, GLsizei))
-BGLU_Wrap(4, Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(9, LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(4, Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(5, PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
-BGLU_Wrap(9, Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-BGLU_Wrap(9, UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-
-#undef MethodDef
-#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS, "no string"}
-#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, "no string"}
-/* So that MethodDef(Accum) becomes:
- * {"glAccum", Method_Accumfunc, METH_VARARGS} */
-
-static struct PyMethodDef BGL_methods[] = {
- {"Buffer", Method_Buffer, METH_VARARGS, Method_Buffer_doc},
-
-/* #ifndef __APPLE__ */
- MethodDef(Accum),
- MethodDef(AlphaFunc),
- MethodDef(AreTexturesResident),
- MethodDef(Begin),
- MethodDef(BindTexture),
- MethodDef(Bitmap),
- MethodDef(BlendFunc),
- MethodDef(CallList),
- MethodDef(CallLists),
- MethodDef(Clear),
- MethodDef(ClearAccum),
- MethodDef(ClearColor),
- MethodDef(ClearDepth),
- MethodDef(ClearIndex),
- MethodDef(ClearStencil),
- MethodDef(ClipPlane),
- MethodDef(Color3b),
- MethodDef(Color3bv),
- MethodDef(Color3d),
- MethodDef(Color3dv),
- MethodDef(Color3f),
- MethodDef(Color3fv),
- MethodDef(Color3i),
- MethodDef(Color3iv),
- MethodDef(Color3s),
- MethodDef(Color3sv),
- MethodDef(Color3ub),
- MethodDef(Color3ubv),
- MethodDef(Color3ui),
- MethodDef(Color3uiv),
- MethodDef(Color3us),
- MethodDef(Color3usv),
- MethodDef(Color4b),
- MethodDef(Color4bv),
- MethodDef(Color4d),
- MethodDef(Color4dv),
- MethodDef(Color4f),
- MethodDef(Color4fv),
- MethodDef(Color4i),
- MethodDef(Color4iv),
- MethodDef(Color4s),
- MethodDef(Color4sv),
- MethodDef(Color4ub),
- MethodDef(Color4ubv),
- MethodDef(Color4ui),
- MethodDef(Color4uiv),
- MethodDef(Color4us),
- MethodDef(Color4usv),
- MethodDef(ColorMask),
- MethodDef(ColorMaterial),
- MethodDef(CopyPixels),
- MethodDef(CullFace),
- MethodDef(DeleteLists),
- MethodDef(DeleteTextures),
- MethodDef(DepthFunc),
- MethodDef(DepthMask),
- MethodDef(DepthRange),
- MethodDef(Disable),
- MethodDef(DrawBuffer),
- MethodDef(DrawPixels),
- MethodDef(EdgeFlag),
- MethodDef(EdgeFlagv),
- MethodDef(Enable),
- MethodDef(End),
- MethodDef(EndList),
- MethodDef(EvalCoord1d),
- MethodDef(EvalCoord1dv),
- MethodDef(EvalCoord1f),
- MethodDef(EvalCoord1fv),
- MethodDef(EvalCoord2d),
- MethodDef(EvalCoord2dv),
- MethodDef(EvalCoord2f),
- MethodDef(EvalCoord2fv),
- MethodDef(EvalMesh1),
- MethodDef(EvalMesh2),
- MethodDef(EvalPoint1),
- MethodDef(EvalPoint2),
- MethodDef(FeedbackBuffer),
- MethodDef(Finish),
- MethodDef(Flush),
- MethodDef(Fogf),
- MethodDef(Fogfv),
- MethodDef(Fogi),
- MethodDef(Fogiv),
- MethodDef(FrontFace),
- MethodDef(Frustum),
- MethodDef(GenLists),
- MethodDef(GenTextures),
- MethodDef(GetBooleanv),
- MethodDef(GetClipPlane),
- MethodDef(GetDoublev),
- MethodDef(GetError),
- MethodDef(GetFloatv),
- MethodDef(GetIntegerv),
- MethodDef(GetLightfv),
- MethodDef(GetLightiv),
- MethodDef(GetMapdv),
- MethodDef(GetMapfv),
- MethodDef(GetMapiv),
- MethodDef(GetMaterialfv),
- MethodDef(GetMaterialiv),
- MethodDef(GetPixelMapfv),
- MethodDef(GetPixelMapuiv),
- MethodDef(GetPixelMapusv),
- MethodDef(GetPolygonStipple),
- MethodDef(GetString),
- MethodDef(GetTexEnvfv),
- MethodDef(GetTexEnviv),
- MethodDef(GetTexGendv),
- MethodDef(GetTexGenfv),
- MethodDef(GetTexGeniv),
- MethodDef(GetTexImage),
- MethodDef(GetTexLevelParameterfv),
- MethodDef(GetTexLevelParameteriv),
- MethodDef(GetTexParameterfv),
- MethodDef(GetTexParameteriv),
- MethodDef(Hint),
- MethodDef(IndexMask),
- MethodDef(Indexd),
- MethodDef(Indexdv),
- MethodDef(Indexf),
- MethodDef(Indexfv),
- MethodDef(Indexi),
- MethodDef(Indexiv),
- MethodDef(Indexs),
- MethodDef(Indexsv),
- MethodDef(InitNames),
- MethodDef(IsEnabled),
- MethodDef(IsList),
- MethodDef(IsTexture),
- MethodDef(LightModelf),
- MethodDef(LightModelfv),
- MethodDef(LightModeli),
- MethodDef(LightModeliv),
- MethodDef(Lightf),
- MethodDef(Lightfv),
- MethodDef(Lighti),
- MethodDef(Lightiv),
- MethodDef(LineStipple),
- MethodDef(LineWidth),
- MethodDef(ListBase),
- MethodDef(LoadIdentity),
- MethodDef(LoadMatrixd),
- MethodDef(LoadMatrixf),
- MethodDef(LoadName),
- MethodDef(LogicOp),
- MethodDef(Map1d),
- MethodDef(Map1f),
- MethodDef(Map2d),
- MethodDef(Map2f),
- MethodDef(MapGrid1d),
- MethodDef(MapGrid1f),
- MethodDef(MapGrid2d),
- MethodDef(MapGrid2f),
- MethodDef(Materialf),
- MethodDef(Materialfv),
- MethodDef(Materiali),
- MethodDef(Materialiv),
- MethodDef(MatrixMode),
- MethodDef(MultMatrixd),
- MethodDef(MultMatrixf),
- MethodDef(NewList),
- MethodDef(Normal3b),
- MethodDef(Normal3bv),
- MethodDef(Normal3d),
- MethodDef(Normal3dv),
- MethodDef(Normal3f),
- MethodDef(Normal3fv),
- MethodDef(Normal3i),
- MethodDef(Normal3iv),
- MethodDef(Normal3s),
- MethodDef(Normal3sv),
- MethodDef(Ortho),
- MethodDef(PassThrough),
- MethodDef(PixelMapfv),
- MethodDef(PixelMapuiv),
- MethodDef(PixelMapusv),
- MethodDef(PixelStoref),
- MethodDef(PixelStorei),
- MethodDef(PixelTransferf),
- MethodDef(PixelTransferi),
- MethodDef(PixelZoom),
- MethodDef(PointSize),
- MethodDef(PolygonMode),
- MethodDef(PolygonOffset),
- MethodDef(PolygonStipple),
- MethodDef(PopAttrib),
- MethodDef(PopClientAttrib),
- MethodDef(PopMatrix),
- MethodDef(PopName),
- MethodDef(PrioritizeTextures),
- MethodDef(PushAttrib),
- MethodDef(PushClientAttrib),
- MethodDef(PushMatrix),
- MethodDef(PushName),
- MethodDef(RasterPos2d),
- MethodDef(RasterPos2dv),
- MethodDef(RasterPos2f),
- MethodDef(RasterPos2fv),
- MethodDef(RasterPos2i),
- MethodDef(RasterPos2iv),
- MethodDef(RasterPos2s),
- MethodDef(RasterPos2sv),
- MethodDef(RasterPos3d),
- MethodDef(RasterPos3dv),
- MethodDef(RasterPos3f),
- MethodDef(RasterPos3fv),
- MethodDef(RasterPos3i),
- MethodDef(RasterPos3iv),
- MethodDef(RasterPos3s),
- MethodDef(RasterPos3sv),
- MethodDef(RasterPos4d),
- MethodDef(RasterPos4dv),
- MethodDef(RasterPos4f),
- MethodDef(RasterPos4fv),
- MethodDef(RasterPos4i),
- MethodDef(RasterPos4iv),
- MethodDef(RasterPos4s),
- MethodDef(RasterPos4sv),
- MethodDef(ReadBuffer),
- MethodDef(ReadPixels),
- MethodDef(Rectd),
- MethodDef(Rectdv),
- MethodDef(Rectf),
- MethodDef(Rectfv),
- MethodDef(Recti),
- MethodDef(Rectiv),
- MethodDef(Rects),
- MethodDef(Rectsv),
- MethodDef(RenderMode),
- MethodDef(Rotated),
- MethodDef(Rotatef),
- MethodDef(Scaled),
- MethodDef(Scalef),
- MethodDef(Scissor),
- MethodDef(SelectBuffer),
- MethodDef(ShadeModel),
- MethodDef(StencilFunc),
- MethodDef(StencilMask),
- MethodDef(StencilOp),
- MethodDef(TexCoord1d),
- MethodDef(TexCoord1dv),
- MethodDef(TexCoord1f),
- MethodDef(TexCoord1fv),
- MethodDef(TexCoord1i),
- MethodDef(TexCoord1iv),
- MethodDef(TexCoord1s),
- MethodDef(TexCoord1sv),
- MethodDef(TexCoord2d),
- MethodDef(TexCoord2dv),
- MethodDef(TexCoord2f),
- MethodDef(TexCoord2fv),
- MethodDef(TexCoord2i),
- MethodDef(TexCoord2iv),
- MethodDef(TexCoord2s),
- MethodDef(TexCoord2sv),
- MethodDef(TexCoord3d),
- MethodDef(TexCoord3dv),
- MethodDef(TexCoord3f),
- MethodDef(TexCoord3fv),
- MethodDef(TexCoord3i),
- MethodDef(TexCoord3iv),
- MethodDef(TexCoord3s),
- MethodDef(TexCoord3sv),
- MethodDef(TexCoord4d),
- MethodDef(TexCoord4dv),
- MethodDef(TexCoord4f),
- MethodDef(TexCoord4fv),
- MethodDef(TexCoord4i),
- MethodDef(TexCoord4iv),
- MethodDef(TexCoord4s),
- MethodDef(TexCoord4sv),
- MethodDef(TexEnvf),
- MethodDef(TexEnvfv),
- MethodDef(TexEnvi),
- MethodDef(TexEnviv),
- MethodDef(TexGend),
- MethodDef(TexGendv),
- MethodDef(TexGenf),
- MethodDef(TexGenfv),
- MethodDef(TexGeni),
- MethodDef(TexGeniv),
- MethodDef(TexImage1D),
- MethodDef(TexImage2D),
- MethodDef(TexParameterf),
- MethodDef(TexParameterfv),
- MethodDef(TexParameteri),
- MethodDef(TexParameteriv),
- MethodDef(Translated),
- MethodDef(Translatef),
- MethodDef(Vertex2d),
- MethodDef(Vertex2dv),
- MethodDef(Vertex2f),
- MethodDef(Vertex2fv),
- MethodDef(Vertex2i),
- MethodDef(Vertex2iv),
- MethodDef(Vertex2s),
- MethodDef(Vertex2sv),
- MethodDef(Vertex3d),
- MethodDef(Vertex3dv),
- MethodDef(Vertex3f),
- MethodDef(Vertex3fv),
- MethodDef(Vertex3i),
- MethodDef(Vertex3iv),
- MethodDef(Vertex3s),
- MethodDef(Vertex3sv),
- MethodDef(Vertex4d),
- MethodDef(Vertex4dv),
- MethodDef(Vertex4f),
- MethodDef(Vertex4fv),
- MethodDef(Vertex4i),
- MethodDef(Vertex4iv),
- MethodDef(Vertex4s),
- MethodDef(Vertex4sv),
- MethodDef(Viewport),
- MethodDefu(Perspective),
- MethodDefu(LookAt),
- MethodDefu(Ortho2D),
- MethodDefu(PickMatrix),
- MethodDefu(Project),
- MethodDefu(UnProject),
-/* #endif */
- {NULL, NULL, 0, NULL}
-};
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static struct PyModuleDef BGL_module_def = {
- PyModuleDef_HEAD_INIT,
- "BGL", /* m_name */
- 0, /* m_doc */
- 0, /* m_size */
- BGL_methods, /* m_methods */
- 0, /* m_reload */
- 0, /* m_traverse */
- 0, /* m_clear */
- 0, /* m_free */
-};
-#endif
-
-PyObject *BGL_Init(const char *from)
-{
- PyObject *mod, *dict, *item;
-#if (PY_VERSION_HEX >= 0x03000000)
- mod = PyModule_Create(&BGL_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), BGL_module_def.m_name, mod);
-#else
- mod= Py_InitModule(from, BGL_methods);
-#endif
- dict= PyModule_GetDict(mod);
-
- if( PyType_Ready( &buffer_Type) < 0)
- return NULL; /* should never happen */
-
-#define EXPP_ADDCONST(x) PyDict_SetItemString(dict, #x, item=PyLong_FromLong((int)x)); Py_DECREF(item)
-
-/* So, for example:
- * EXPP_ADDCONST(GL_CURRENT_BIT) becomes
- * PyDict_SetItemString(dict, "GL_CURRENT_BIT", item=PyLong_FromLong(GL_CURRENT_BIT)); Py_DECREF(item) */
-
- EXPP_ADDCONST(GL_CURRENT_BIT);
- EXPP_ADDCONST(GL_POINT_BIT);
- EXPP_ADDCONST(GL_LINE_BIT);
- EXPP_ADDCONST(GL_POLYGON_BIT);
- EXPP_ADDCONST(GL_POLYGON_STIPPLE_BIT);
- EXPP_ADDCONST(GL_PIXEL_MODE_BIT);
- EXPP_ADDCONST(GL_LIGHTING_BIT);
- EXPP_ADDCONST(GL_FOG_BIT);
- EXPP_ADDCONST(GL_DEPTH_BUFFER_BIT);
- EXPP_ADDCONST(GL_ACCUM_BUFFER_BIT);
- EXPP_ADDCONST(GL_STENCIL_BUFFER_BIT);
- EXPP_ADDCONST(GL_VIEWPORT_BIT);
- EXPP_ADDCONST(GL_TRANSFORM_BIT);
- EXPP_ADDCONST(GL_ENABLE_BIT);
- EXPP_ADDCONST(GL_COLOR_BUFFER_BIT);
- EXPP_ADDCONST(GL_HINT_BIT);
- EXPP_ADDCONST(GL_EVAL_BIT);
- EXPP_ADDCONST(GL_LIST_BIT);
- EXPP_ADDCONST(GL_TEXTURE_BIT);
- EXPP_ADDCONST(GL_SCISSOR_BIT);
- EXPP_ADDCONST(GL_ALL_ATTRIB_BITS);
- EXPP_ADDCONST(GL_CLIENT_ALL_ATTRIB_BITS);
-
- EXPP_ADDCONST(GL_FALSE);
- EXPP_ADDCONST(GL_TRUE);
-
- EXPP_ADDCONST(GL_POINTS);
- EXPP_ADDCONST(GL_LINES);
- EXPP_ADDCONST(GL_LINE_LOOP);
- EXPP_ADDCONST(GL_LINE_STRIP);
- EXPP_ADDCONST(GL_TRIANGLES);
- EXPP_ADDCONST(GL_TRIANGLE_STRIP);
- EXPP_ADDCONST(GL_TRIANGLE_FAN);
- EXPP_ADDCONST(GL_QUADS);
- EXPP_ADDCONST(GL_QUAD_STRIP);
- EXPP_ADDCONST(GL_POLYGON);
-
- EXPP_ADDCONST(GL_ACCUM);
- EXPP_ADDCONST(GL_LOAD);
- EXPP_ADDCONST(GL_RETURN);
- EXPP_ADDCONST(GL_MULT);
- EXPP_ADDCONST(GL_ADD);
-
- EXPP_ADDCONST(GL_NEVER);
- EXPP_ADDCONST(GL_LESS);
- EXPP_ADDCONST(GL_EQUAL);
- EXPP_ADDCONST(GL_LEQUAL);
- EXPP_ADDCONST(GL_GREATER);
- EXPP_ADDCONST(GL_NOTEQUAL);
- EXPP_ADDCONST(GL_GEQUAL);
- EXPP_ADDCONST(GL_ALWAYS);
-
- EXPP_ADDCONST(GL_ZERO);
- EXPP_ADDCONST(GL_ONE);
- EXPP_ADDCONST(GL_SRC_COLOR);
- EXPP_ADDCONST(GL_ONE_MINUS_SRC_COLOR);
- EXPP_ADDCONST(GL_SRC_ALPHA);
- EXPP_ADDCONST(GL_ONE_MINUS_SRC_ALPHA);
- EXPP_ADDCONST(GL_DST_ALPHA);
- EXPP_ADDCONST(GL_ONE_MINUS_DST_ALPHA);
-
- EXPP_ADDCONST(GL_DST_COLOR);
- EXPP_ADDCONST(GL_ONE_MINUS_DST_COLOR);
- EXPP_ADDCONST(GL_SRC_ALPHA_SATURATE);
-
- EXPP_ADDCONST(GL_NONE);
- EXPP_ADDCONST(GL_FRONT_LEFT);
- EXPP_ADDCONST(GL_FRONT_RIGHT);
- EXPP_ADDCONST(GL_BACK_LEFT);
- EXPP_ADDCONST(GL_BACK_RIGHT);
- EXPP_ADDCONST(GL_FRONT);
- EXPP_ADDCONST(GL_BACK);
- EXPP_ADDCONST(GL_LEFT);
- EXPP_ADDCONST(GL_RIGHT);
- EXPP_ADDCONST(GL_FRONT_AND_BACK);
- EXPP_ADDCONST(GL_AUX0);
- EXPP_ADDCONST(GL_AUX1);
- EXPP_ADDCONST(GL_AUX2);
- EXPP_ADDCONST(GL_AUX3);
-
- EXPP_ADDCONST(GL_NO_ERROR);
- EXPP_ADDCONST(GL_INVALID_ENUM);
- EXPP_ADDCONST(GL_INVALID_VALUE);
- EXPP_ADDCONST(GL_INVALID_OPERATION);
- EXPP_ADDCONST(GL_STACK_OVERFLOW);
- EXPP_ADDCONST(GL_STACK_UNDERFLOW);
- EXPP_ADDCONST(GL_OUT_OF_MEMORY);
-
- EXPP_ADDCONST(GL_2D);
- EXPP_ADDCONST(GL_3D);
- EXPP_ADDCONST(GL_3D_COLOR);
- EXPP_ADDCONST(GL_3D_COLOR_TEXTURE);
- EXPP_ADDCONST(GL_4D_COLOR_TEXTURE);
-
- EXPP_ADDCONST(GL_PASS_THROUGH_TOKEN);
- EXPP_ADDCONST(GL_POINT_TOKEN);
- EXPP_ADDCONST(GL_LINE_TOKEN);
- EXPP_ADDCONST(GL_POLYGON_TOKEN);
- EXPP_ADDCONST(GL_BITMAP_TOKEN);
- EXPP_ADDCONST(GL_DRAW_PIXEL_TOKEN);
- EXPP_ADDCONST(GL_COPY_PIXEL_TOKEN);
- EXPP_ADDCONST(GL_LINE_RESET_TOKEN);
-
- EXPP_ADDCONST(GL_EXP);
- EXPP_ADDCONST(GL_EXP2);
-
- EXPP_ADDCONST(GL_CW);
- EXPP_ADDCONST(GL_CCW);
-
- EXPP_ADDCONST(GL_COEFF);
- EXPP_ADDCONST(GL_ORDER);
- EXPP_ADDCONST(GL_DOMAIN);
-
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I);
- EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A);
- EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R);
- EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G);
- EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B);
- EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A);
-
- EXPP_ADDCONST(GL_CURRENT_COLOR);
- EXPP_ADDCONST(GL_CURRENT_INDEX);
- EXPP_ADDCONST(GL_CURRENT_NORMAL);
- EXPP_ADDCONST(GL_CURRENT_TEXTURE_COORDS);
- EXPP_ADDCONST(GL_CURRENT_RASTER_COLOR);
- EXPP_ADDCONST(GL_CURRENT_RASTER_INDEX);
- EXPP_ADDCONST(GL_CURRENT_RASTER_TEXTURE_COORDS);
- EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION);
- EXPP_ADDCONST(GL_CURRENT_RASTER_POSITION_VALID);
- EXPP_ADDCONST(GL_CURRENT_RASTER_DISTANCE);
- EXPP_ADDCONST(GL_POINT_SMOOTH);
- EXPP_ADDCONST(GL_POINT_SIZE);
- EXPP_ADDCONST(GL_POINT_SIZE_RANGE);
- EXPP_ADDCONST(GL_POINT_SIZE_GRANULARITY);
- EXPP_ADDCONST(GL_LINE_SMOOTH);
- EXPP_ADDCONST(GL_LINE_WIDTH);
- EXPP_ADDCONST(GL_LINE_WIDTH_RANGE);
- EXPP_ADDCONST(GL_LINE_WIDTH_GRANULARITY);
- EXPP_ADDCONST(GL_LINE_STIPPLE);
- EXPP_ADDCONST(GL_LINE_STIPPLE_PATTERN);
- EXPP_ADDCONST(GL_LINE_STIPPLE_REPEAT);
- EXPP_ADDCONST(GL_LIST_MODE);
- EXPP_ADDCONST(GL_MAX_LIST_NESTING);
- EXPP_ADDCONST(GL_LIST_BASE);
- EXPP_ADDCONST(GL_LIST_INDEX);
- EXPP_ADDCONST(GL_POLYGON_MODE);
- EXPP_ADDCONST(GL_POLYGON_SMOOTH);
- EXPP_ADDCONST(GL_POLYGON_STIPPLE);
- EXPP_ADDCONST(GL_EDGE_FLAG);
- EXPP_ADDCONST(GL_CULL_FACE);
- EXPP_ADDCONST(GL_CULL_FACE_MODE);
- EXPP_ADDCONST(GL_FRONT_FACE);
- EXPP_ADDCONST(GL_LIGHTING);
- EXPP_ADDCONST(GL_LIGHT_MODEL_LOCAL_VIEWER);
- EXPP_ADDCONST(GL_LIGHT_MODEL_TWO_SIDE);
- EXPP_ADDCONST(GL_LIGHT_MODEL_AMBIENT);
- EXPP_ADDCONST(GL_SHADE_MODEL);
- EXPP_ADDCONST(GL_COLOR_MATERIAL_FACE);
- EXPP_ADDCONST(GL_COLOR_MATERIAL_PARAMETER);
- EXPP_ADDCONST(GL_COLOR_MATERIAL);
- EXPP_ADDCONST(GL_FOG);
- EXPP_ADDCONST(GL_FOG_INDEX);
- EXPP_ADDCONST(GL_FOG_DENSITY);
- EXPP_ADDCONST(GL_FOG_START);
- EXPP_ADDCONST(GL_FOG_END);
- EXPP_ADDCONST(GL_FOG_MODE);
- EXPP_ADDCONST(GL_FOG_COLOR);
- EXPP_ADDCONST(GL_DEPTH_RANGE);
- EXPP_ADDCONST(GL_DEPTH_TEST);
- EXPP_ADDCONST(GL_DEPTH_WRITEMASK);
- EXPP_ADDCONST(GL_DEPTH_CLEAR_VALUE);
- EXPP_ADDCONST(GL_DEPTH_FUNC);
- EXPP_ADDCONST(GL_ACCUM_CLEAR_VALUE);
- EXPP_ADDCONST(GL_STENCIL_TEST);
- EXPP_ADDCONST(GL_STENCIL_CLEAR_VALUE);
- EXPP_ADDCONST(GL_STENCIL_FUNC);
- EXPP_ADDCONST(GL_STENCIL_VALUE_MASK);
- EXPP_ADDCONST(GL_STENCIL_FAIL);
- EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_FAIL);
- EXPP_ADDCONST(GL_STENCIL_PASS_DEPTH_PASS);
- EXPP_ADDCONST(GL_STENCIL_REF);
- EXPP_ADDCONST(GL_STENCIL_WRITEMASK);
- EXPP_ADDCONST(GL_MATRIX_MODE);
- EXPP_ADDCONST(GL_NORMALIZE);
- EXPP_ADDCONST(GL_VIEWPORT);
- EXPP_ADDCONST(GL_MODELVIEW_STACK_DEPTH);
- EXPP_ADDCONST(GL_PROJECTION_STACK_DEPTH);
- EXPP_ADDCONST(GL_TEXTURE_STACK_DEPTH);
- EXPP_ADDCONST(GL_MODELVIEW_MATRIX);
- EXPP_ADDCONST(GL_PROJECTION_MATRIX);
- EXPP_ADDCONST(GL_TEXTURE_MATRIX);
- EXPP_ADDCONST(GL_ATTRIB_STACK_DEPTH);
- EXPP_ADDCONST(GL_ALPHA_TEST);
- EXPP_ADDCONST(GL_ALPHA_TEST_FUNC);
- EXPP_ADDCONST(GL_ALPHA_TEST_REF);
- EXPP_ADDCONST(GL_DITHER);
- EXPP_ADDCONST(GL_BLEND_DST);
- EXPP_ADDCONST(GL_BLEND_SRC);
- EXPP_ADDCONST(GL_BLEND);
- EXPP_ADDCONST(GL_LOGIC_OP_MODE);
- EXPP_ADDCONST(GL_LOGIC_OP);
- EXPP_ADDCONST(GL_AUX_BUFFERS);
- EXPP_ADDCONST(GL_DRAW_BUFFER);
- EXPP_ADDCONST(GL_READ_BUFFER);
- EXPP_ADDCONST(GL_SCISSOR_BOX);
- EXPP_ADDCONST(GL_SCISSOR_TEST);
- EXPP_ADDCONST(GL_INDEX_CLEAR_VALUE);
- EXPP_ADDCONST(GL_INDEX_WRITEMASK);
- EXPP_ADDCONST(GL_COLOR_CLEAR_VALUE);
- EXPP_ADDCONST(GL_COLOR_WRITEMASK);
- EXPP_ADDCONST(GL_INDEX_MODE);
- EXPP_ADDCONST(GL_RGBA_MODE);
- EXPP_ADDCONST(GL_DOUBLEBUFFER);
- EXPP_ADDCONST(GL_STEREO);
- EXPP_ADDCONST(GL_RENDER_MODE);
- EXPP_ADDCONST(GL_PERSPECTIVE_CORRECTION_HINT);
- EXPP_ADDCONST(GL_POINT_SMOOTH_HINT);
- EXPP_ADDCONST(GL_LINE_SMOOTH_HINT);
- EXPP_ADDCONST(GL_POLYGON_SMOOTH_HINT);
- EXPP_ADDCONST(GL_FOG_HINT);
- EXPP_ADDCONST(GL_TEXTURE_GEN_S);
- EXPP_ADDCONST(GL_TEXTURE_GEN_T);
- EXPP_ADDCONST(GL_TEXTURE_GEN_R);
- EXPP_ADDCONST(GL_TEXTURE_GEN_Q);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_I_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_S_TO_S_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_R_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_G_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_B_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_I_TO_A_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_R_TO_R_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_G_TO_G_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_B_TO_B_SIZE);
- EXPP_ADDCONST(GL_PIXEL_MAP_A_TO_A_SIZE);
- EXPP_ADDCONST(GL_UNPACK_SWAP_BYTES);
- EXPP_ADDCONST(GL_UNPACK_LSB_FIRST);
- EXPP_ADDCONST(GL_UNPACK_ROW_LENGTH);
- EXPP_ADDCONST(GL_UNPACK_SKIP_ROWS);
- EXPP_ADDCONST(GL_UNPACK_SKIP_PIXELS);
- EXPP_ADDCONST(GL_UNPACK_ALIGNMENT);
- EXPP_ADDCONST(GL_PACK_SWAP_BYTES);
- EXPP_ADDCONST(GL_PACK_LSB_FIRST);
- EXPP_ADDCONST(GL_PACK_ROW_LENGTH);
- EXPP_ADDCONST(GL_PACK_SKIP_ROWS);
- EXPP_ADDCONST(GL_PACK_SKIP_PIXELS);
- EXPP_ADDCONST(GL_PACK_ALIGNMENT);
- EXPP_ADDCONST(GL_MAP_COLOR);
- EXPP_ADDCONST(GL_MAP_STENCIL);
- EXPP_ADDCONST(GL_INDEX_SHIFT);
- EXPP_ADDCONST(GL_INDEX_OFFSET);
- EXPP_ADDCONST(GL_RED_SCALE);
- EXPP_ADDCONST(GL_RED_BIAS);
- EXPP_ADDCONST(GL_ZOOM_X);
- EXPP_ADDCONST(GL_ZOOM_Y);
- EXPP_ADDCONST(GL_GREEN_SCALE);
- EXPP_ADDCONST(GL_GREEN_BIAS);
- EXPP_ADDCONST(GL_BLUE_SCALE);
- EXPP_ADDCONST(GL_BLUE_BIAS);
- EXPP_ADDCONST(GL_ALPHA_SCALE);
- EXPP_ADDCONST(GL_ALPHA_BIAS);
- EXPP_ADDCONST(GL_DEPTH_SCALE);
- EXPP_ADDCONST(GL_DEPTH_BIAS);
- EXPP_ADDCONST(GL_MAX_EVAL_ORDER);
- EXPP_ADDCONST(GL_MAX_LIGHTS);
- EXPP_ADDCONST(GL_MAX_CLIP_PLANES);
- EXPP_ADDCONST(GL_MAX_TEXTURE_SIZE);
- EXPP_ADDCONST(GL_MAX_PIXEL_MAP_TABLE);
- EXPP_ADDCONST(GL_MAX_ATTRIB_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_MODELVIEW_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_NAME_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_PROJECTION_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_TEXTURE_STACK_DEPTH);
- EXPP_ADDCONST(GL_MAX_VIEWPORT_DIMS);
- EXPP_ADDCONST(GL_SUBPIXEL_BITS);
- EXPP_ADDCONST(GL_INDEX_BITS);
- EXPP_ADDCONST(GL_RED_BITS);
- EXPP_ADDCONST(GL_GREEN_BITS);
- EXPP_ADDCONST(GL_BLUE_BITS);
- EXPP_ADDCONST(GL_ALPHA_BITS);
- EXPP_ADDCONST(GL_DEPTH_BITS);
- EXPP_ADDCONST(GL_STENCIL_BITS);
- EXPP_ADDCONST(GL_ACCUM_RED_BITS);
- EXPP_ADDCONST(GL_ACCUM_GREEN_BITS);
- EXPP_ADDCONST(GL_ACCUM_BLUE_BITS);
- EXPP_ADDCONST(GL_ACCUM_ALPHA_BITS);
- EXPP_ADDCONST(GL_NAME_STACK_DEPTH);
- EXPP_ADDCONST(GL_AUTO_NORMAL);
- EXPP_ADDCONST(GL_MAP1_COLOR_4);
- EXPP_ADDCONST(GL_MAP1_INDEX);
- EXPP_ADDCONST(GL_MAP1_NORMAL);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_1);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_2);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_3);
- EXPP_ADDCONST(GL_MAP1_TEXTURE_COORD_4);
- EXPP_ADDCONST(GL_MAP1_VERTEX_3);
- EXPP_ADDCONST(GL_MAP1_VERTEX_4);
- EXPP_ADDCONST(GL_MAP2_COLOR_4);
- EXPP_ADDCONST(GL_MAP2_INDEX);
- EXPP_ADDCONST(GL_MAP2_NORMAL);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_1);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_2);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_3);
- EXPP_ADDCONST(GL_MAP2_TEXTURE_COORD_4);
- EXPP_ADDCONST(GL_MAP2_VERTEX_3);
- EXPP_ADDCONST(GL_MAP2_VERTEX_4);
- EXPP_ADDCONST(GL_MAP1_GRID_DOMAIN);
- EXPP_ADDCONST(GL_MAP1_GRID_SEGMENTS);
- EXPP_ADDCONST(GL_MAP2_GRID_DOMAIN);
- EXPP_ADDCONST(GL_MAP2_GRID_SEGMENTS);
- EXPP_ADDCONST(GL_TEXTURE_1D);
- EXPP_ADDCONST(GL_TEXTURE_2D);
-
- EXPP_ADDCONST(GL_TEXTURE_WIDTH);
- EXPP_ADDCONST(GL_TEXTURE_HEIGHT);
- EXPP_ADDCONST(GL_TEXTURE_COMPONENTS);
- EXPP_ADDCONST(GL_TEXTURE_BORDER_COLOR);
- EXPP_ADDCONST(GL_TEXTURE_BORDER);
-
- EXPP_ADDCONST(GL_DONT_CARE);
- EXPP_ADDCONST(GL_FASTEST);
- EXPP_ADDCONST(GL_NICEST);
-
- EXPP_ADDCONST(GL_AMBIENT);
- EXPP_ADDCONST(GL_DIFFUSE);
- EXPP_ADDCONST(GL_SPECULAR);
- EXPP_ADDCONST(GL_POSITION);
- EXPP_ADDCONST(GL_SPOT_DIRECTION);
- EXPP_ADDCONST(GL_SPOT_EXPONENT);
- EXPP_ADDCONST(GL_SPOT_CUTOFF);
- EXPP_ADDCONST(GL_CONSTANT_ATTENUATION);
- EXPP_ADDCONST(GL_LINEAR_ATTENUATION);
- EXPP_ADDCONST(GL_QUADRATIC_ATTENUATION);
-
- EXPP_ADDCONST(GL_COMPILE);
- EXPP_ADDCONST(GL_COMPILE_AND_EXECUTE);
-
- EXPP_ADDCONST(GL_BYTE);
- EXPP_ADDCONST(GL_UNSIGNED_BYTE);
- EXPP_ADDCONST(GL_SHORT);
- EXPP_ADDCONST(GL_UNSIGNED_SHORT);
- EXPP_ADDCONST(GL_INT);
- EXPP_ADDCONST(GL_UNSIGNED_INT);
- EXPP_ADDCONST(GL_FLOAT);
- EXPP_ADDCONST(GL_DOUBLE);
- EXPP_ADDCONST(GL_2_BYTES);
- EXPP_ADDCONST(GL_3_BYTES);
- EXPP_ADDCONST(GL_4_BYTES);
-
- EXPP_ADDCONST(GL_CLEAR);
- EXPP_ADDCONST(GL_AND);
- EXPP_ADDCONST(GL_AND_REVERSE);
- EXPP_ADDCONST(GL_COPY);
- EXPP_ADDCONST(GL_AND_INVERTED);
- EXPP_ADDCONST(GL_NOOP);
- EXPP_ADDCONST(GL_XOR);
- EXPP_ADDCONST(GL_OR);
- EXPP_ADDCONST(GL_NOR);
- EXPP_ADDCONST(GL_EQUIV);
- EXPP_ADDCONST(GL_INVERT);
- EXPP_ADDCONST(GL_OR_REVERSE);
- EXPP_ADDCONST(GL_COPY_INVERTED);
- EXPP_ADDCONST(GL_OR_INVERTED);
- EXPP_ADDCONST(GL_NAND);
- EXPP_ADDCONST(GL_SET);
-
- EXPP_ADDCONST(GL_EMISSION);
- EXPP_ADDCONST(GL_SHININESS);
- EXPP_ADDCONST(GL_AMBIENT_AND_DIFFUSE);
- EXPP_ADDCONST(GL_COLOR_INDEXES);
-
- EXPP_ADDCONST(GL_MODELVIEW);
- EXPP_ADDCONST(GL_PROJECTION);
- EXPP_ADDCONST(GL_TEXTURE);
-
- EXPP_ADDCONST(GL_COLOR);
- EXPP_ADDCONST(GL_DEPTH);
- EXPP_ADDCONST(GL_STENCIL);
-
- EXPP_ADDCONST(GL_COLOR_INDEX);
- EXPP_ADDCONST(GL_STENCIL_INDEX);
- EXPP_ADDCONST(GL_DEPTH_COMPONENT);
- EXPP_ADDCONST(GL_RED);
- EXPP_ADDCONST(GL_GREEN);
- EXPP_ADDCONST(GL_BLUE);
- EXPP_ADDCONST(GL_ALPHA);
- EXPP_ADDCONST(GL_RGB);
- EXPP_ADDCONST(GL_RGBA);
- EXPP_ADDCONST(GL_LUMINANCE);
- EXPP_ADDCONST(GL_LUMINANCE_ALPHA);
-
- EXPP_ADDCONST(GL_BITMAP);
-
- EXPP_ADDCONST(GL_POINT);
- EXPP_ADDCONST(GL_LINE);
- EXPP_ADDCONST(GL_FILL);
-
- EXPP_ADDCONST(GL_RENDER);
- EXPP_ADDCONST(GL_FEEDBACK);
- EXPP_ADDCONST(GL_SELECT);
-
- EXPP_ADDCONST(GL_FLAT);
- EXPP_ADDCONST(GL_SMOOTH);
-
- EXPP_ADDCONST(GL_KEEP);
- EXPP_ADDCONST(GL_REPLACE);
- EXPP_ADDCONST(GL_INCR);
- EXPP_ADDCONST(GL_DECR);
-
- EXPP_ADDCONST(GL_VENDOR);
- EXPP_ADDCONST(GL_RENDERER);
- EXPP_ADDCONST(GL_VERSION);
- EXPP_ADDCONST(GL_EXTENSIONS);
-
- EXPP_ADDCONST(GL_S);
- EXPP_ADDCONST(GL_T);
- EXPP_ADDCONST(GL_R);
- EXPP_ADDCONST(GL_Q);
-
- EXPP_ADDCONST(GL_MODULATE);
- EXPP_ADDCONST(GL_DECAL);
-
- EXPP_ADDCONST(GL_TEXTURE_ENV_MODE);
- EXPP_ADDCONST(GL_TEXTURE_ENV_COLOR);
-
- EXPP_ADDCONST(GL_TEXTURE_ENV);
-
- EXPP_ADDCONST(GL_EYE_LINEAR);
- EXPP_ADDCONST(GL_OBJECT_LINEAR);
- EXPP_ADDCONST(GL_SPHERE_MAP);
-
- EXPP_ADDCONST(GL_TEXTURE_GEN_MODE);
- EXPP_ADDCONST(GL_OBJECT_PLANE);
- EXPP_ADDCONST(GL_EYE_PLANE);
-
- EXPP_ADDCONST(GL_NEAREST);
- EXPP_ADDCONST(GL_LINEAR);
-
- EXPP_ADDCONST(GL_NEAREST_MIPMAP_NEAREST);
- EXPP_ADDCONST(GL_LINEAR_MIPMAP_NEAREST);
- EXPP_ADDCONST(GL_NEAREST_MIPMAP_LINEAR);
- EXPP_ADDCONST(GL_LINEAR_MIPMAP_LINEAR);
-
- EXPP_ADDCONST(GL_TEXTURE_MAG_FILTER);
- EXPP_ADDCONST(GL_TEXTURE_MIN_FILTER);
- EXPP_ADDCONST(GL_TEXTURE_WRAP_S);
- EXPP_ADDCONST(GL_TEXTURE_WRAP_T);
-
- EXPP_ADDCONST(GL_CLAMP);
- EXPP_ADDCONST(GL_REPEAT);
-
- EXPP_ADDCONST(GL_CLIP_PLANE0);
- EXPP_ADDCONST(GL_CLIP_PLANE1);
- EXPP_ADDCONST(GL_CLIP_PLANE2);
- EXPP_ADDCONST(GL_CLIP_PLANE3);
- EXPP_ADDCONST(GL_CLIP_PLANE4);
- EXPP_ADDCONST(GL_CLIP_PLANE5);
-
- EXPP_ADDCONST(GL_LIGHT0);
- EXPP_ADDCONST(GL_LIGHT1);
- EXPP_ADDCONST(GL_LIGHT2);
- EXPP_ADDCONST(GL_LIGHT3);
- EXPP_ADDCONST(GL_LIGHT4);
- EXPP_ADDCONST(GL_LIGHT5);
- EXPP_ADDCONST(GL_LIGHT6);
- EXPP_ADDCONST(GL_LIGHT7);
-
- EXPP_ADDCONST(GL_POLYGON_OFFSET_UNITS);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_POINT);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_LINE);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_FILL);
- EXPP_ADDCONST(GL_POLYGON_OFFSET_FACTOR);
-
- EXPP_ADDCONST(GL_TEXTURE_PRIORITY);
- EXPP_ADDCONST(GL_TEXTURE_RESIDENT);
- EXPP_ADDCONST(GL_TEXTURE_BINDING_1D);
- EXPP_ADDCONST(GL_TEXTURE_BINDING_2D);
-
- return mod;
-}
-
diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h
deleted file mode 100755
index 938c916bcea..00000000000
--- a/source/blender/python/generic/BGL.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Willian P. Germano
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-
-/* This is the Blender.BGL part of opy_draw.c, from the old bpython/intern
- * dir, with minor changes to adapt it to the new Python implementation.
- * The BGL submodule "wraps" OpenGL functions and constants, allowing script
- * writers to make OpenGL calls in their Python scripts for Blender. The
- * more important original comments are marked with an @ symbol. */
-
-#ifndef EXPP_BGL_H
-#define EXPP_BGL_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <Python.h>
-#include <GL/glew.h>
-#include "../intern/bpy_compat.h"
-
-PyObject *BGL_Init( const char *from );
-
-/*@ Buffer Object */
-/*@ For Python access to OpenGL functions requiring a pointer. */
-
-typedef struct _Buffer {
- PyObject_VAR_HEAD
- PyObject * parent;
-
- int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */
- int ndimensions;
- int *dimensions;
-
- union {
- char *asbyte;
- short *asshort;
- int *asint;
- float *asfloat;
- double *asdouble;
-
- void *asvoid;
- } buf;
-} Buffer;
-
-
-/*@ By golly George! It looks like fancy pants macro time!!! */
-
-/*
-#define int_str "i"
-#define int_var(number) bgl_int##number
-#define int_ref(number) &bgl_int##number
-#define int_def(number) int int_var(number)
-
-#define float_str "f"
-#define float_var(number) bgl_float##number
-#define float_ref(number) &bgl_float##number
-#define float_def(number) float float_var(number)
-*/
-
-/* TYPE_str is the string to pass to Py_ArgParse (for the format) */
-/* TYPE_var is the name to pass to the GL function */
-/* TYPE_ref is the pointer to pass to Py_ArgParse (to store in) */
-/* TYPE_def is the C initialization of the variable */
-
-#define void_str ""
-#define void_var(num)
-#define void_ref(num) &bgl_var##num
-#define void_def(num) char bgl_var##num
-
-#define buffer_str "O!"
-#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
-#define buffer_ref(number) &buffer_Type, &bgl_buffer##number
-#define buffer_def(number) Buffer *bgl_buffer##number
-
-/* GL Pointer fields, handled by buffer type */
-/* GLdoubleP, GLfloatP, GLintP, GLuintP, GLshortP */
-
-#define GLbooleanP_str "O!"
-#define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLbooleanP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLbooleanP_def(number) Buffer *bgl_buffer##number
-
-#define GLbyteP_str "O!"
-#define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLbyteP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLbyteP_def(number) Buffer *bgl_buffer##number
-
-#define GLubyteP_str "O!"
-#define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLubyteP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLubyteP_def(number) Buffer *bgl_buffer##number
-
-#define GLintP_str "O!"
-#define GLintP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLintP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLintP_def(number) Buffer *bgl_buffer##number
-
-#define GLuintP_str "O!"
-#define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLuintP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLuintP_def(number) Buffer *bgl_buffer##number
-
-#define GLshortP_str "O!"
-#define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLshortP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLshortP_def(number) Buffer *bgl_buffer##number
-
-#define GLushortP_str "O!"
-#define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLushortP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLushortP_def(number) Buffer *bgl_buffer##number
-
-#define GLfloatP_str "O!"
-#define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLfloatP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLfloatP_def(number) Buffer *bgl_buffer##number
-
-#define GLdoubleP_str "O!"
-#define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLdoubleP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLdoubleP_def(number) Buffer *bgl_buffer##number
-
-#define GLclampfP_str "O!"
-#define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLclampfP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLclampfP_def(number) Buffer *bgl_buffer##number
-
-#define GLvoidP_str "O!"
-#define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid
-#define GLvoidP_ref(number) &buffer_Type, &bgl_buffer##number
-#define GLvoidP_def(number) Buffer *bgl_buffer##number
-
-#define buffer_str "O!"
-#define buffer_var(number) (bgl_buffer##number)->buf.asvoid
-#define buffer_ref(number) &buffer_Type, &bgl_buffer##number
-#define buffer_def(number) Buffer *bgl_buffer##number
-
-/*@The standard GL typedefs are used as prototypes, we can't
- * use the GL type directly because Py_ArgParse expects normal
- * C types.
- *
- * Py_ArgParse doesn't grok writing into unsigned variables,
- * so we use signed everything (even stuff that should be unsigned.
- */
-
-/* typedef unsigned int GLenum; */
-#define GLenum_str "i"
-#define GLenum_var(num) bgl_var##num
-#define GLenum_ref(num) &bgl_var##num
-#define GLenum_def(num) /* unsigned */ int GLenum_var(num)
-
-/* typedef unsigned int GLboolean; */
-#define GLboolean_str "b"
-#define GLboolean_var(num) bgl_var##num
-#define GLboolean_ref(num) &bgl_var##num
-#define GLboolean_def(num) /* unsigned */ char GLboolean_var(num)
-
-/* typedef unsigned int GLbitfield; */
-#define GLbitfield_str "i"
-#define GLbitfield_var(num) bgl_var##num
-#define GLbitfield_ref(num) &bgl_var##num
-#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
-
-/* typedef signed char GLbyte; */
-#define GLbyte_str "b"
-#define GLbyte_var(num) bgl_var##num
-#define GLbyte_ref(num) &bgl_var##num
-#define GLbyte_def(num) signed char GLbyte_var(num)
-
-/* typedef short GLshort; */
-#define GLshort_str "h"
-#define GLshort_var(num) bgl_var##num
-#define GLshort_ref(num) &bgl_var##num
-#define GLshort_def(num) short GLshort_var(num)
-
-/* typedef int GLint; */
-#define GLint_str "i"
-#define GLint_var(num) bgl_var##num
-#define GLint_ref(num) &bgl_var##num
-#define GLint_def(num) int GLint_var(num)
-
-/* typedef int GLsizei; */
-#define GLsizei_str "i"
-#define GLsizei_var(num) bgl_var##num
-#define GLsizei_ref(num) &bgl_var##num
-#define GLsizei_def(num) int GLsizei_var(num)
-
-/* typedef unsigned char GLubyte; */
-#define GLubyte_str "b"
-#define GLubyte_var(num) bgl_var##num
-#define GLubyte_ref(num) &bgl_var##num
-#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
-
-/* typedef unsigned short GLushort; */
-#define GLushort_str "h"
-#define GLushort_var(num) bgl_var##num
-#define GLushort_ref(num) &bgl_var##num
-#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
-
-/* typedef unsigned int GLuint; */
-#define GLuint_str "i"
-#define GLuint_var(num) bgl_var##num
-#define GLuint_ref(num) &bgl_var##num
-#define GLuint_def(num) /* unsigned */ int GLuint_var(num)
-
-/* typedef float GLfloat; */
-#define GLfloat_str "f"
-#define GLfloat_var(num) bgl_var##num
-#define GLfloat_ref(num) &bgl_var##num
-#define GLfloat_def(num) float GLfloat_var(num)
-
-/* typedef float GLclampf; */
-#define GLclampf_str "f"
-#define GLclampf_var(num) bgl_var##num
-#define GLclampf_ref(num) &bgl_var##num
-#define GLclampf_def(num) float GLclampf_var(num)
-
-/* typedef double GLdouble; */
-#define GLdouble_str "d"
-#define GLdouble_var(num) bgl_var##num
-#define GLdouble_ref(num) &bgl_var##num
-#define GLdouble_def(num) double GLdouble_var(num)
-
-/* typedef double GLclampd; */
-#define GLclampd_str "d"
-#define GLclampd_var(num) bgl_var##num
-#define GLclampd_ref(num) &bgl_var##num
-#define GLclampd_def(num) double GLclampd_var(num)
-
-/* typedef void GLvoid; */
-/* #define GLvoid_str "" */
-/* #define GLvoid_var(num) bgl_var##num */
-/* #define GLvoid_ref(num) &bgl_var##num */
-/* #define GLvoid_def(num) char bgl_var##num */
-
-#define arg_def1(a1) a1##_def(1)
-#define arg_def2(a1, a2) arg_def1(a1); a2##_def(2)
-#define arg_def3(a1, a2, a3) arg_def2(a1, a2); a3##_def(3)
-#define arg_def4(a1, a2, a3, a4) arg_def3(a1, a2, a3); a4##_def(4)
-#define arg_def5(a1, a2, a3, a4, a5) arg_def4(a1, a2, a3, a4); a5##_def(5)
-#define arg_def6(a1, a2, a3, a4, a5, a6)arg_def5(a1, a2, a3, a4, a5); a6##_def(6)
-#define arg_def7(a1, a2, a3, a4, a5, a6, a7)arg_def6(a1, a2, a3, a4, a5, a6); a7##_def(7)
-#define arg_def8(a1, a2, a3, a4, a5, a6, a7, a8)arg_def7(a1, a2, a3, a4, a5, a6, a7); a8##_def(8)
-#define arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_def8(a1, a2, a3, a4, a5, a6, a7, a8); a9##_def(9)
-#define arg_def10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_def9(a1, a2, a3, a4, a5, a6, a7, a8, a9); a10##_def(10)
-
-#define arg_var1(a1) a1##_var(1)
-#define arg_var2(a1, a2) arg_var1(a1), a2##_var(2)
-#define arg_var3(a1, a2, a3) arg_var2(a1, a2), a3##_var(3)
-#define arg_var4(a1, a2, a3, a4) arg_var3(a1, a2, a3), a4##_var(4)
-#define arg_var5(a1, a2, a3, a4, a5) arg_var4(a1, a2, a3, a4), a5##_var(5)
-#define arg_var6(a1, a2, a3, a4, a5, a6)arg_var5(a1, a2, a3, a4, a5), a6##_var(6)
-#define arg_var7(a1, a2, a3, a4, a5, a6, a7)arg_var6(a1, a2, a3, a4, a5, a6), a7##_var(7)
-#define arg_var8(a1, a2, a3, a4, a5, a6, a7, a8)arg_var7(a1, a2, a3, a4, a5, a6, a7), a8##_var(8)
-#define arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_var8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_var(9)
-#define arg_var10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_var9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_var(10)
-
-#define arg_ref1(a1) a1##_ref(1)
-#define arg_ref2(a1, a2) arg_ref1(a1), a2##_ref(2)
-#define arg_ref3(a1, a2, a3) arg_ref2(a1, a2), a3##_ref(3)
-#define arg_ref4(a1, a2, a3, a4) arg_ref3(a1, a2, a3), a4##_ref(4)
-#define arg_ref5(a1, a2, a3, a4, a5) arg_ref4(a1, a2, a3, a4), a5##_ref(5)
-#define arg_ref6(a1, a2, a3, a4, a5, a6)arg_ref5(a1, a2, a3, a4, a5), a6##_ref(6)
-#define arg_ref7(a1, a2, a3, a4, a5, a6, a7)arg_ref6(a1, a2, a3, a4, a5, a6), a7##_ref(7)
-#define arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8)arg_ref7(a1, a2, a3, a4, a5, a6, a7), a8##_ref(8)
-#define arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_ref8(a1, a2, a3, a4, a5, a6, a7, a8), a9##_ref(9)
-#define arg_ref10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_ref9(a1, a2, a3, a4, a5, a6, a7, a8, a9), a10##_ref(10)
-
-#define arg_str1(a1) a1##_str
-#define arg_str2(a1, a2) arg_str1(a1) a2##_str
-#define arg_str3(a1, a2, a3) arg_str2(a1, a2) a3##_str
-#define arg_str4(a1, a2, a3, a4) arg_str3(a1, a2, a3) a4##_str
-#define arg_str5(a1, a2, a3, a4, a5) arg_str4(a1, a2, a3, a4) a5##_str
-#define arg_str6(a1, a2, a3, a4, a5, a6)arg_str5(a1, a2, a3, a4, a5) a6##_str
-#define arg_str7(a1, a2, a3, a4, a5, a6, a7)arg_str6(a1, a2, a3, a4, a5, a6) a7##_str
-#define arg_str8(a1, a2, a3, a4, a5, a6, a7, a8)arg_str7(a1, a2, a3, a4, a5, a6, a7) a8##_str
-#define arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9)arg_str8(a1, a2, a3, a4, a5, a6, a7, a8) a9##_str
-#define arg_str10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)arg_str9(a1, a2, a3, a4, a5, a6, a7, a8, a9) a10##_str
-
-#define ret_def_void
-#define ret_set_void
-/* would use Py_RETURN_NONE - except for py 2.3 doesnt have it */
-#define ret_ret_void { Py_INCREF(Py_None); return Py_None; }
-
-#define ret_def_GLint int ret_int
-#define ret_set_GLint ret_int=
-#define ret_ret_GLint return PyLong_FromLong(ret_int);
-
-#define ret_def_GLuint unsigned int ret_uint
-#define ret_set_GLuint ret_uint=
-#define ret_ret_GLuint return PyLong_FromLong((long) ret_uint);
-
-#define ret_def_GLenum unsigned int ret_uint
-#define ret_set_GLenum ret_uint=
-#define ret_ret_GLenum return PyLong_FromLong((long) ret_uint);
-
-#define ret_def_GLboolean unsigned char ret_bool
-#define ret_set_GLboolean ret_bool=
-#define ret_ret_GLboolean return PyLong_FromLong((long) ret_bool);
-
-#define ret_def_GLstring const unsigned char *ret_str;
-#define ret_set_GLstring ret_str=
-
-#define ret_ret_GLstring \
- if (ret_str) {\
- return PyUnicode_FromString(ret_str);\
- } else {\
- PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\
- return NULL;\
- }
-
-#endif /* EXPP_BGL_H */
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c
deleted file mode 100644
index b4a34d30051..00000000000
--- a/source/blender/python/generic/Geometry.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert, Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Geometry.h"
-
-/* - Not needed for now though other geometry functions will probably need them
-#include "BLI_arithb.h"
-#include "BKE_utildefines.h"
-*/
-
-/* Used for PolyFill */
-#include "BKE_displist.h"
-#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-
-#include "BKE_utildefines.h"
-#include "BKE_curve.h"
-#include "BLI_boxpack2d.h"
-#include "BLI_arithb.h"
-
-#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
-#define eul 0.000001
-
-/*-- forward declarations -- */
-static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq );
-static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * args );
-static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args );
-
-
-/*-------------------------DOC STRINGS ---------------------------*/
-static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
-static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
-static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
-static char M_Geometry_ClosestPointOnLine_doc[] = "(pt, line_p1, line_p2) - takes a point and a line and returns a (Vector, float) for the point on the line, and the bool so you can know if the point was between the 2 points";
-static char M_Geometry_PointInTriangle2D_doc[] = "(pt, tri_p1, tri_p2, tri_p3) - takes 4 vectors, one is the point and the next 3 define the triangle, only the x and y are used from the vectors";
-static char M_Geometry_PointInQuad2D_doc[] = "(pt, quad_p1, quad_p2, quad_p3, quad_p4) - takes 5 vectors, one is the point and the next 4 define the quad, only the x and y are used from the vectors";
-static char M_Geometry_BoxPack2D_doc[] = "";
-static char M_Geometry_BezierInterp_doc[] = "";
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-struct PyMethodDef M_Geometry_methods[] = {
- {"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_O, M_Geometry_PolyFill_doc},
- {"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
- {"ClosestPointOnLine", ( PyCFunction ) M_Geometry_ClosestPointOnLine, METH_VARARGS, M_Geometry_ClosestPointOnLine_doc},
- {"PointInTriangle2D", ( PyCFunction ) M_Geometry_PointInTriangle2D, METH_VARARGS, M_Geometry_PointInTriangle2D_doc},
- {"PointInQuad2D", ( PyCFunction ) M_Geometry_PointInQuad2D, METH_VARARGS, M_Geometry_PointInQuad2D_doc},
- {"BoxPack2D", ( PyCFunction ) M_Geometry_BoxPack2D, METH_O, M_Geometry_BoxPack2D_doc},
- {"BezierInterp", ( PyCFunction ) M_Geometry_BezierInterp, METH_VARARGS, M_Geometry_BezierInterp_doc},
- {NULL, NULL, 0, NULL}
-};
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static struct PyModuleDef M_Geometry_module_def = {
- PyModuleDef_HEAD_INIT,
- "Geometry", /* m_name */
- M_Geometry_doc, /* m_doc */
- 0, /* m_size */
- M_Geometry_methods, /* m_methods */
- 0, /* m_reload */
- 0, /* m_traverse */
- 0, /* m_clear */
- 0, /* m_free */
-};
-#endif
-
-/*----------------------------MODULE INIT-------------------------*/
-PyObject *Geometry_Init(const char *from)
-{
- PyObject *submodule;
-
-#if (PY_VERSION_HEX >= 0x03000000)
- submodule = PyModule_Create(&M_Geometry_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), M_Geometry_module_def.m_name, submodule);
-#else
- submodule = Py_InitModule3(from, M_Geometry_methods, M_Geometry_doc);
-#endif
-
- return (submodule);
-}
-
-/*----------------------------------Geometry.PolyFill() -------------------*/
-/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
-static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
-{
- PyObject *tri_list; /*return this list of tri's */
- PyObject *polyLine, *polyVec;
- int i, len_polylines, len_polypoints, ls_error = 0;
-
- /* display listbase */
- ListBase dispbase={NULL, NULL};
- DispList *dl;
- float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
- int index, *dl_face, totpoints=0;
-
-
- dispbase.first= dispbase.last= NULL;
-
-
- if(!PySequence_Check(polyLineSeq)) {
- PyErr_SetString( PyExc_TypeError, "expected a sequence of poly lines" );
- return NULL;
- }
-
- len_polylines = PySequence_Size( polyLineSeq );
-
- for( i = 0; i < len_polylines; ++i ) {
- polyLine= PySequence_GetItem( polyLineSeq, i );
- if (!PySequence_Check(polyLine)) {
- freedisplist(&dispbase);
- Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/
- PyErr_SetString( PyExc_TypeError, "One or more of the polylines is not a sequence of Mathutils.Vector's" );
- return NULL;
- }
-
- len_polypoints= PySequence_Size( polyLine );
- if (len_polypoints>0) { /* dont bother adding edges as polylines */
-#if 0
- if (EXPP_check_sequence_consistency( polyLine, &vector_Type ) != 1) {
- freedisplist(&dispbase);
- Py_DECREF(polyLine);
- PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
- return NULL;
- }
-#endif
- dl= MEM_callocN(sizeof(DispList), "poly disp");
- BLI_addtail(&dispbase, dl);
- dl->type= DL_INDEX3;
- dl->nr= len_polypoints;
- dl->type= DL_POLY;
- dl->parts= 1; /* no faces, 1 edge loop */
- dl->col= 0; /* no material */
- dl->verts= fp= MEM_callocN( sizeof(float)*3*len_polypoints, "dl verts");
- dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index");
-
- for( index = 0; index<len_polypoints; ++index, fp+=3) {
- polyVec= PySequence_GetItem( polyLine, index );
- if(VectorObject_Check(polyVec)) {
-
- if(!BaseMath_ReadCallback((VectorObject *)polyVec))
- ls_error= 1;
-
- fp[0] = ((VectorObject *)polyVec)->vec[0];
- fp[1] = ((VectorObject *)polyVec)->vec[1];
- if( ((VectorObject *)polyVec)->size > 2 )
- fp[2] = ((VectorObject *)polyVec)->vec[2];
- else
- fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */
- }
- else {
- ls_error= 1;
- }
-
- totpoints++;
- Py_DECREF(polyVec);
- }
- }
- Py_DECREF(polyLine);
- }
-
- if(ls_error) {
- freedisplist(&dispbase); /* possible some dl was allocated */
- PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" );
- return NULL;
- }
- else if (totpoints) {
- /* now make the list to return */
- filldisplist(&dispbase, &dispbase);
-
- /* The faces are stored in a new DisplayList
- thats added to the head of the listbase */
- dl= dispbase.first;
-
- tri_list= PyList_New(dl->parts);
- if( !tri_list ) {
- freedisplist(&dispbase);
- PyErr_SetString( PyExc_RuntimeError, "Geometry.PolyFill failed to make a new list" );
- return NULL;
- }
-
- index= 0;
- dl_face= dl->index;
- while(index < dl->parts) {
- PyList_SetItem(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]) );
- dl_face+= 3;
- index++;
- }
- freedisplist(&dispbase);
- } else {
- /* no points, do this so scripts dont barf */
- freedisplist(&dispbase); /* possible some dl was allocated */
- tri_list= PyList_New(0);
- }
-
- return tri_list;
-}
-
-
-static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
-{
- VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
- float a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, newvec[2];
- if( !PyArg_ParseTuple ( args, "O!O!O!O!",
- &vector_Type, &line_a1,
- &vector_Type, &line_a2,
- &vector_Type, &line_b1,
- &vector_Type, &line_b2)
- ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2))
- return NULL;
-
- a1x= line_a1->vec[0];
- a1y= line_a1->vec[1];
- a2x= line_a2->vec[0];
- a2y= line_a2->vec[1];
-
- b1x= line_b1->vec[0];
- b1y= line_b1->vec[1];
- b2x= line_b2->vec[0];
- b2y= line_b2->vec[1];
-
- if((MIN2(a1x, a2x) > MAX2(b1x, b2x)) ||
- (MAX2(a1x, a2x) < MIN2(b1x, b2x)) ||
- (MIN2(a1y, a2y) > MAX2(b1y, b2y)) ||
- (MAX2(a1y, a2y) < MIN2(b1y, b2y)) ) {
- Py_RETURN_NONE;
- }
- /* Make sure the hoz/vert line comes first. */
- if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) {
- SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/
- SWAP_FLOAT(a1y, b1y, xi);
- SWAP_FLOAT(a2x, b2x, xi);
- SWAP_FLOAT(a2y, b2y, xi);
- }
-
- if (fabs(a1x-a2x) < eul) { /* verticle line */
- if (fabs(b1x-b2x) < eul){ /*verticle second line */
- Py_RETURN_NONE; /* 2 verticle lines dont intersect. */
- }
- else if (fabs(b1y-b2y) < eul) {
- /*X of vert, Y of hoz. no calculation needed */
- newvec[0]= a1x;
- newvec[1]= b1y;
- return newVectorObject(newvec, 2, Py_NEW, NULL);
- }
-
- yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x)));
-
- if (yi > MAX2(a1y, a2y)) {/* New point above seg1's vert line */
- Py_RETURN_NONE;
- } else if (yi < MIN2(a1y, a2y)) { /* New point below seg1's vert line */
- Py_RETURN_NONE;
- }
- newvec[0]= a1x;
- newvec[1]= yi;
- return newVectorObject(newvec, 2, Py_NEW, NULL);
- } else if (fabs(a2y-a1y) < eul) { /* hoz line1 */
- if (fabs(b2y-b1y) < eul) { /*hoz line2*/
- Py_RETURN_NONE; /*2 hoz lines dont intersect*/
- }
-
- /* Can skip vert line check for seg 2 since its covered above. */
- xi = (float)(((b1x / fabs(b1y - b2y)) * fabs(b2y - a1y)) + ((b2x / fabs(b1y - b2y)) * fabs(b1y - a1y)));
- if (xi > MAX2(a1x, a2x)) { /* New point right of hoz line1's */
- Py_RETURN_NONE;
- } else if (xi < MIN2(a1x, a2x)) { /*New point left of seg1's hoz line */
- Py_RETURN_NONE;
- }
- newvec[0]= xi;
- newvec[1]= a1y;
- return newVectorObject(newvec, 2, Py_NEW, NULL);
- }
-
- b1 = (a2y-a1y)/(a2x-a1x);
- b2 = (b2y-b1y)/(b2x-b1x);
- a1 = a1y-b1*a1x;
- a2 = b1y-b2*b1x;
-
- if (b1 - b2 == 0.0) {
- Py_RETURN_NONE;
- }
-
- xi = - (a1-a2)/(b1-b2);
- yi = a1+b1*xi;
- if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) {
- newvec[0]= xi;
- newvec[1]= yi;
- return newVectorObject(newvec, 2, Py_NEW, NULL);
- }
- Py_RETURN_NONE;
-}
-
-static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args )
-{
- VectorObject *pt, *line_1, *line_2;
- float pt_in[3], pt_out[3], l1[3], l2[3];
- float lambda;
- PyObject *ret;
-
- if( !PyArg_ParseTuple ( args, "O!O!O!",
- &vector_Type, &pt,
- &vector_Type, &line_1,
- &vector_Type, &line_2)
- ) {
- PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2))
- return NULL;
-
- /* accept 2d verts */
- if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
- else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) }
-
- if (line_1->size==3) { VECCOPY(l1, line_1->vec);}
- else { l1[2]=0.0; VECCOPY2D(l1, line_1->vec) }
-
- if (line_2->size==3) { VECCOPY(l2, line_2->vec);}
- else { l2[2]=0.0; VECCOPY2D(l2, line_2->vec) }
-
- /* do the calculation */
- lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out);
-
- ret = PyTuple_New(2);
- PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL) );
- PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) );
- return ret;
-}
-
-static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args )
-{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
-
- if( !PyArg_ParseTuple ( args, "O!O!O!O!",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3)
- ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3))
- return NULL;
-
- return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
-}
-
-static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args )
-{
- VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
-
- if( !PyArg_ParseTuple ( args, "O!O!O!O!O!",
- &vector_Type, &pt_vec,
- &vector_Type, &quad_p1,
- &vector_Type, &quad_p2,
- &vector_Type, &quad_p3,
- &vector_Type, &quad_p4)
- ) {
- PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4))
- return NULL;
-
- return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
-}
-
-static int boxPack_FromPyObject(PyObject * value, boxPack **boxarray )
-{
- int len, i;
- PyObject *list_item, *item_1, *item_2;
- boxPack *box;
-
-
- /* Error checking must alredy be done */
- if( !PyList_Check( value ) ) {
- PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
- return -1;
- }
-
- len = PyList_Size( value );
-
- (*boxarray) = MEM_mallocN( len*sizeof(boxPack), "boxPack box");
-
-
- for( i = 0; i < len; i++ ) {
- list_item = PyList_GET_ITEM( value, i );
- if( !PyList_Check( list_item ) || PyList_Size( list_item ) < 4 ) {
- MEM_freeN(*boxarray);
- PyErr_SetString( PyExc_TypeError, "can only back a list of [x,y,x,w]" );
- return -1;
- }
-
- box = (*boxarray)+i;
-
- item_1 = PyList_GET_ITEM(list_item, 2);
- item_2 = PyList_GET_ITEM(list_item, 3);
-
- if (!PyNumber_Check(item_1) || !PyNumber_Check(item_2)) {
- MEM_freeN(*boxarray);
- PyErr_SetString( PyExc_TypeError, "can only back a list of 2d boxes [x,y,x,w]" );
- return -1;
- }
-
- box->w = (float)PyFloat_AsDouble( item_1 );
- box->h = (float)PyFloat_AsDouble( item_2 );
- box->index = i;
- /* verts will be added later */
- }
- return 0;
-}
-
-static void boxPack_ToPyObject(PyObject * value, boxPack **boxarray)
-{
- int len, i;
- PyObject *list_item;
- boxPack *box;
-
- len = PyList_Size( value );
-
- for( i = 0; i < len; i++ ) {
- box = (*boxarray)+i;
- list_item = PyList_GET_ITEM( value, box->index );
- PyList_SET_ITEM( list_item, 0, PyFloat_FromDouble( box->x ));
- PyList_SET_ITEM( list_item, 1, PyFloat_FromDouble( box->y ));
- }
- MEM_freeN(*boxarray);
-}
-
-
-static PyObject *M_Geometry_BoxPack2D( PyObject * self, PyObject * boxlist )
-{
- boxPack *boxarray = NULL;
- float tot_width, tot_height;
- int len;
- int error;
-
- if(!PyList_Check(boxlist)) {
- PyErr_SetString( PyExc_TypeError, "expected a sequence of boxes [[x,y,w,h], ... ]" );
- return NULL;
- }
-
- len = PyList_Size( boxlist );
-
- if (!len)
- return Py_BuildValue( "ff", 0.0, 0.0);
-
- error = boxPack_FromPyObject(boxlist, &boxarray);
- if (error!=0) return NULL;
-
- /* Non Python function */
- boxPack2D(boxarray, len, &tot_width, &tot_height);
-
- boxPack_ToPyObject(boxlist, &boxarray);
-
- return Py_BuildValue( "ff", tot_width, tot_height);
-}
-
-static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args )
-{
- VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
- int resolu;
- int dims;
- int i;
- float *coord_array, *fp;
- PyObject *list;
-
- float k1[4] = {0.0, 0.0, 0.0, 0.0};
- float h1[4] = {0.0, 0.0, 0.0, 0.0};
- float k2[4] = {0.0, 0.0, 0.0, 0.0};
- float h2[4] = {0.0, 0.0, 0.0, 0.0};
-
-
- if( !PyArg_ParseTuple ( args, "O!O!O!O!i",
- &vector_Type, &vec_k1,
- &vector_Type, &vec_h1,
- &vector_Type, &vec_h2,
- &vector_Type, &vec_k2, &resolu) || (resolu<=1)
- ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types and an int greater then 1\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2))
- return NULL;
-
- dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
-
- for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];
- for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i];
- for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i];
- for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i];
-
- coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp");
- for(i=0; i<dims; i++) {
- forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, dims);
- }
-
- list= PyList_New(resolu);
- fp= coord_array;
- for(i=0; i<resolu; i++, fp= fp+dims) {
- PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW, NULL));
- }
- MEM_freeN(coord_array);
- return list;
-}
diff --git a/source/blender/python/generic/Geometry.h b/source/blender/python/generic/Geometry.h
deleted file mode 100644
index ebfb054c54a..00000000000
--- a/source/blender/python/generic/Geometry.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-/*Include this file for access to vector, quat, matrix, euler, etc...*/
-
-#ifndef EXPP_Geometry_H
-#define EXPP_Geometry_H
-
-#include <Python.h>
-#include "Mathutils.h"
-
-PyObject *Geometry_Init( const char *from );
-
-#endif /* EXPP_Geometry_H */
diff --git a/source/blender/python/generic/Makefile b/source/blender/python/generic/Makefile
deleted file mode 100644
index 0dbfbd1d102..00000000000
--- a/source/blender/python/generic/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# $Id$
-#
-# ***** 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.
-#
-# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = gen_python
-DIR = $(OCGDIR)/blender/$(LIBNAME)
-
-include nan_compile.mk
-
-CFLAGS += $(LEVEL_1_C_WARNINGS)
-
-# OpenGL and Python
-CPPFLAGS += -I$(NAN_GLEW)/include
-CPPFLAGS += $(OGL_CPPFLAGS)
-CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-
-# PreProcessor stuff
-
-CPPFLAGS += -I$(NAN_GHOST)/include
-CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include $(NAN_SDLCFLAGS)
-
-# modules
-CPPFLAGS += -I../../editors/include
-CPPFLAGS += -I../../python
-CPPFLAGS += -I../../makesdna
-CPPFLAGS += -I../../makesrna
-CPPFLAGS += -I../../blenlib
-CPPFLAGS += -I../../blenkernel
-CPPFLAGS += -I../../nodes
-CPPFLAGS += -I../../imbuf
-CPPFLAGS += -I../../blenloader
-CPPFLAGS += -I../../windowmanager
-CPPFLAGS += -I../../render/extern/include
-
-# path to the guarded memory allocator
-CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
-CPPFLAGS += -I$(NAN_MEMUTIL)/include
-
-# path to our own headerfiles
-CPPFLAGS += -I..
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
deleted file mode 100644
index 53077659655..00000000000
--- a/source/blender/python/generic/Mathutils.c
+++ /dev/null
@@ -1,1266 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert, Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Mathutils.h"
-
-#include "BLI_arithb.h"
-#include "PIL_time.h"
-#include "BLI_rand.h"
-#include "BKE_utildefines.h"
-
-//-------------------------DOC STRINGS ---------------------------
-static char M_Mathutils_doc[] = "The Blender Mathutils module\n\n";
-static char M_Mathutils_Rand_doc[] = "() - return a random number";
-static char M_Mathutils_AngleBetweenVecs_doc[] = "() - returns the angle between two vectors in degrees";
-static char M_Mathutils_MidpointVecs_doc[] = "() - return the vector to the midpoint between two vectors";
-static char M_Mathutils_ProjectVecs_doc[] = "() - returns the projection vector from the projection of vecA onto vecB";
-static char M_Mathutils_RotationMatrix_doc[] = "() - construct a rotation matrix from an angle and axis of rotation";
-static char M_Mathutils_ScaleMatrix_doc[] = "() - construct a scaling matrix from a scaling factor";
-static char M_Mathutils_OrthoProjectionMatrix_doc[] = "() - construct a orthographic projection matrix from a selected plane";
-static char M_Mathutils_ShearMatrix_doc[] = "() - construct a shearing matrix from a plane of shear and a shear factor";
-static char M_Mathutils_TranslationMatrix_doc[] = "(vec) - create a translation matrix from a vector";
-static char M_Mathutils_Slerp_doc[] = "() - returns the interpolation between two quaternions";
-static char M_Mathutils_DifferenceQuats_doc[] = "() - return the angular displacment difference between two quats";
-static char M_Mathutils_Intersect_doc[] = "(v1, v2, v3, ray, orig, clip=1) - returns the intersection between a ray and a triangle, if possible, returns None otherwise";
-static char M_Mathutils_TriangleArea_doc[] = "(v1, v2, v3) - returns the area size of the 2D or 3D triangle defined";
-static char M_Mathutils_TriangleNormal_doc[] = "(v1, v2, v3) - returns the normal of the 3D triangle defined";
-static char M_Mathutils_QuadNormal_doc[] = "(v1, v2, v3, v4) - returns the normal of the 3D quad defined";
-static char M_Mathutils_LineIntersect_doc[] = "(v1, v2, v3, v4) - returns a tuple with the points on each line respectively closest to the other";
-//-----------------------METHOD DEFINITIONS ----------------------
-
-static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * value);
-static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args);
-static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args );
-static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args );
-
-struct PyMethodDef M_Mathutils_methods[] = {
- {"Rand", (PyCFunction) M_Mathutils_Rand, METH_VARARGS, M_Mathutils_Rand_doc},
- {"AngleBetweenVecs", (PyCFunction) M_Mathutils_AngleBetweenVecs, METH_VARARGS, M_Mathutils_AngleBetweenVecs_doc},
- {"MidpointVecs", (PyCFunction) M_Mathutils_MidpointVecs, METH_VARARGS, M_Mathutils_MidpointVecs_doc},
- {"ProjectVecs", (PyCFunction) M_Mathutils_ProjectVecs, METH_VARARGS, M_Mathutils_ProjectVecs_doc},
- {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc},
- {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc},
- {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc},
- {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc},
- {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc},
- {"DifferenceQuats", (PyCFunction) M_Mathutils_DifferenceQuats, METH_VARARGS,M_Mathutils_DifferenceQuats_doc},
- {"Slerp", (PyCFunction) M_Mathutils_Slerp, METH_VARARGS, M_Mathutils_Slerp_doc},
- {"Intersect", ( PyCFunction ) M_Mathutils_Intersect, METH_VARARGS, M_Mathutils_Intersect_doc},
- {"TriangleArea", ( PyCFunction ) M_Mathutils_TriangleArea, METH_VARARGS, M_Mathutils_TriangleArea_doc},
- {"TriangleNormal", ( PyCFunction ) M_Mathutils_TriangleNormal, METH_VARARGS, M_Mathutils_TriangleNormal_doc},
- {"QuadNormal", ( PyCFunction ) M_Mathutils_QuadNormal, METH_VARARGS, M_Mathutils_QuadNormal_doc},
- {"LineIntersect", ( PyCFunction ) M_Mathutils_LineIntersect, METH_VARARGS, M_Mathutils_LineIntersect_doc},
- {NULL, NULL, 0, NULL}
-};
-
-/*----------------------------MODULE INIT-------------------------*/
-/* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static struct PyModuleDef M_Mathutils_module_def = {
- PyModuleDef_HEAD_INIT,
- "Mathutils", /* m_name */
- M_Mathutils_doc, /* m_doc */
- 0, /* m_size */
- M_Mathutils_methods, /* m_methods */
- 0, /* m_reload */
- 0, /* m_traverse */
- 0, /* m_clear */
- 0, /* m_free */
-};
-#endif
-
-PyObject *Mathutils_Init(const char *from)
-{
- PyObject *submodule;
-
- //seed the generator for the rand function
- BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF));
-
-#if (PY_VERSION_HEX < 0x03000000)
- vector_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
- matrix_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
- euler_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
- quaternion_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
-#endif
-
- if( PyType_Ready( &vector_Type ) < 0 )
- return NULL;
- if( PyType_Ready( &matrix_Type ) < 0 )
- return NULL;
- if( PyType_Ready( &euler_Type ) < 0 )
- return NULL;
- if( PyType_Ready( &quaternion_Type ) < 0 )
- return NULL;
-
-#if (PY_VERSION_HEX >= 0x03000000)
- submodule = PyModule_Create(&M_Mathutils_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), M_Mathutils_module_def.m_name, submodule);
-#else
- submodule = Py_InitModule3(from, M_Mathutils_methods, M_Mathutils_doc);
-#endif
-
- /* each type has its own new() function */
- PyModule_AddObject( submodule, "Vector", (PyObject *)&vector_Type );
- PyModule_AddObject( submodule, "Matrix", (PyObject *)&matrix_Type );
- PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type );
- PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type );
-
- mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb);
-
- return (submodule);
-}
-
-//-----------------------------METHODS----------------------------
-//-----------------quat_rotation (internal)-----------
-//This function multiplies a vector/point * quat or vice versa
-//to rotate the point/vector by the quaternion
-//arguments should all be 3D
-PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
-{
- float rot[3];
- QuaternionObject *quat = NULL;
- VectorObject *vec = NULL;
-
- if(QuaternionObject_Check(arg1)){
- quat = (QuaternionObject*)arg1;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
- if(VectorObject_Check(arg2)){
- vec = (VectorObject*)arg2;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
- 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
- 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
- quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
- rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] +
- 2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] -
- quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] -
- 2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
- rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] +
- quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
- quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
- quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
- return newVectorObject(rot, 3, Py_NEW, NULL);
- }
- }else if(VectorObject_Check(arg1)){
- vec = (VectorObject*)arg1;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- if(QuaternionObject_Check(arg2)){
- quat = (QuaternionObject*)arg2;
- if(!BaseMath_ReadCallback(quat))
- return NULL;
-
- rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] -
- 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] +
- 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] -
- quat->quat[3]*quat->quat[3]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[0];
- rot[1] = 2*quat->quat[1]*quat->quat[2]*vec->vec[0] + quat->quat[2]*quat->quat[2]*vec->vec[1] +
- 2*quat->quat[3]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[3]*vec->vec[0] -
- quat->quat[3]*quat->quat[3]*vec->vec[1] + quat->quat[0]*quat->quat[0]*vec->vec[1] -
- 2*quat->quat[1]*quat->quat[0]*vec->vec[2] - quat->quat[1]*quat->quat[1]*vec->vec[1];
- rot[2] = 2*quat->quat[1]*quat->quat[3]*vec->vec[0] + 2*quat->quat[2]*quat->quat[3]*vec->vec[1] +
- quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] -
- quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] -
- quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2];
- return newVectorObject(rot, 3, Py_NEW, NULL);
- }
- }
-
- PyErr_SetString(PyExc_RuntimeError, "quat_rotation(internal): internal problem rotating vector/point\n");
- return NULL;
-
-}
-
-//----------------------------------Mathutils.Rand() --------------------
-//returns a random number between a high and low value
-static PyObject *M_Mathutils_Rand(PyObject * self, PyObject * args)
-{
- float high, low, range;
- double drand;
- //initializers
- high = 1.0;
- low = 0.0;
-
- if(!PyArg_ParseTuple(args, "|ff", &low, &high)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Rand(): expected nothing or optional (float, float)\n");
- return NULL;
- }
-
- if((high < low) || (high < 0 && low > 0)) {
- PyErr_SetString(PyExc_ValueError, "Mathutils.Rand(): high value should be larger than low value\n");
- return NULL;
- }
- //get the random number 0 - 1
- drand = BLI_drand();
-
- //set it to range
- range = high - low;
- drand = drand * range;
- drand = drand + low;
-
- return PyFloat_FromDouble(drand);
-}
-//----------------------------------VECTOR FUNCTIONS---------------------
-//----------------------------------Mathutils.AngleBetweenVecs() ---------
-//calculates the angle between 2 vectors
-static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f;
- int x, size;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2))
- goto AttributeError1; //not vectors
- if(vec1->size != vec2->size)
- goto AttributeError1; //bad sizes
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- //since size is the same....
- size = vec1->size;
-
- for(x = 0; x < size; x++) {
- test_v1 += vec1->vec[x] * vec1->vec[x];
- test_v2 += vec2->vec[x] * vec2->vec[x];
- }
- if (!test_v1 || !test_v2){
- goto AttributeError2; //zero-length vector
- }
-
- //dot product
- for(x = 0; x < size; x++) {
- dot += vec1->vec[x] * vec2->vec[x];
- }
- dot /= (sqrt(test_v1) * sqrt(test_v2));
-
- angleRads = (double)saacos(dot);
-
-#ifdef USE_MATHUTILS_DEG
- return PyFloat_FromDouble(angleRads * (180/ Py_PI));
-#else
- return PyFloat_FromDouble(angleRads);
-#endif
-AttributeError1:
- PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n");
- return NULL;
-
-AttributeError2:
- PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): zero length vectors are not acceptable arguments\n");
- return NULL;
-}
-//----------------------------------Mathutils.MidpointVecs() -------------
-//calculates the midpoint between 2 vectors
-static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- float vec[4];
- int x;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- for(x = 0; x < vec1->size; x++) {
- vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
- }
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.ProjectVecs() -------------
-//projects vector 1 onto vector 2
-static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- float vec[4];
- double dot = 0.0f, dot2 = 0.0f;
- int x, size;
-
- if(!PyArg_ParseTuple(args, "O!O!", &vector_Type, &vec1, &vector_Type, &vec2)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.ProjectVecs(): expects (2) vector objects of the same size\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
-
- //since they are the same size...
- size = vec1->size;
-
- //get dot products
- for(x = 0; x < size; x++) {
- dot += vec1->vec[x] * vec2->vec[x];
- dot2 += vec2->vec[x] * vec2->vec[x];
- }
- //projection
- dot /= dot2;
- for(x = 0; x < size; x++) {
- vec[x] = (float)(dot * vec2->vec[x]);
- }
- return newVectorObject(vec, size, Py_NEW, NULL);
-}
-//----------------------------------MATRIX FUNCTIONS--------------------
-//----------------------------------Mathutils.RotationMatrix() ----------
-//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates a rotation matrix
-static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
-{
- VectorObject *vec = NULL;
- char *axis = NULL;
- int matSize;
- float angle = 0.0f, norm = 0.0f, cosAngle = 0.0f, sinAngle = 0.0f;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!PyArg_ParseTuple(args, "fi|sO!", &angle, &matSize, &axis, &vector_Type, &vec)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n");
- return NULL;
- }
-
-#ifdef USE_MATHUTILS_DEG
- /* Clamp to -360:360 */
- while (angle<-360.0f)
- angle+=360.0;
- while (angle>360.0f)
- angle-=360.0;
-#else
- while (angle<-(Py_PI*2))
- angle+=(Py_PI*2);
- while (angle>(Py_PI*2))
- angle-=(Py_PI*2);
-#endif
-
- if(matSize != 2 && matSize != 3 && matSize != 4) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
- return NULL;
- }
- if(matSize == 2 && (axis != NULL || vec != NULL)) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n");
- return NULL;
- }
- if((matSize == 3 || matSize == 4) && axis == NULL) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n");
- return NULL;
- }
- if(axis) {
- if(((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) && vec == NULL) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): please define the arbitrary axis of rotation\n");
- return NULL;
- }
- }
- if(vec) {
- if(vec->size != 3) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- }
-#ifdef USE_MATHUTILS_DEG
- //convert to radians
- angle = angle * (float) (Py_PI / 180);
-#endif
-
- if(axis == NULL && matSize == 2) {
- //2D rotation matrix
- mat[0] = (float) cos (angle);
- mat[1] = (float) sin (angle);
- mat[2] = -((float) sin(angle));
- mat[3] = (float) cos(angle);
- } else if((strcmp(axis, "x") == 0) || (strcmp(axis, "X") == 0)) {
- //rotation around X
- mat[0] = 1.0f;
- mat[4] = (float) cos(angle);
- mat[5] = (float) sin(angle);
- mat[7] = -((float) sin(angle));
- mat[8] = (float) cos(angle);
- } else if((strcmp(axis, "y") == 0) || (strcmp(axis, "Y") == 0)) {
- //rotation around Y
- mat[0] = (float) cos(angle);
- mat[2] = -((float) sin(angle));
- mat[4] = 1.0f;
- mat[6] = (float) sin(angle);
- mat[8] = (float) cos(angle);
- } else if((strcmp(axis, "z") == 0) || (strcmp(axis, "Z") == 0)) {
- //rotation around Z
- mat[0] = (float) cos(angle);
- mat[1] = (float) sin(angle);
- mat[3] = -((float) sin(angle));
- mat[4] = (float) cos(angle);
- mat[8] = 1.0f;
- } else if((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) {
- //arbitrary rotation
- //normalize arbitrary axis
- norm = (float) sqrt(vec->vec[0] * vec->vec[0] +
- vec->vec[1] * vec->vec[1] +
- vec->vec[2] * vec->vec[2]);
- vec->vec[0] /= norm;
- vec->vec[1] /= norm;
- vec->vec[2] /= norm;
-
- if (isnan(vec->vec[0]) || isnan(vec->vec[1]) || isnan(vec->vec[2])) {
- /* zero length vector, return an identity matrix, could also return an error */
- mat[0]= mat[4] = mat[8] = 1.0f;
- } else {
- /* create matrix */
- cosAngle = (float) cos(angle);
- sinAngle = (float) sin(angle);
- mat[0] = ((vec->vec[0] * vec->vec[0]) * (1 - cosAngle)) +
- cosAngle;
- mat[1] = ((vec->vec[0] * vec->vec[1]) * (1 - cosAngle)) +
- (vec->vec[2] * sinAngle);
- mat[2] = ((vec->vec[0] * vec->vec[2]) * (1 - cosAngle)) -
- (vec->vec[1] * sinAngle);
- mat[3] = ((vec->vec[0] * vec->vec[1]) * (1 - cosAngle)) -
- (vec->vec[2] * sinAngle);
- mat[4] = ((vec->vec[1] * vec->vec[1]) * (1 - cosAngle)) +
- cosAngle;
- mat[5] = ((vec->vec[1] * vec->vec[2]) * (1 - cosAngle)) +
- (vec->vec[0] * sinAngle);
- mat[6] = ((vec->vec[0] * vec->vec[2]) * (1 - cosAngle)) +
- (vec->vec[1] * sinAngle);
- mat[7] = ((vec->vec[1] * vec->vec[2]) * (1 - cosAngle)) -
- (vec->vec[0] * sinAngle);
- mat[8] = ((vec->vec[2] * vec->vec[2]) * (1 - cosAngle)) +
- cosAngle;
- }
- } else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n");
- return NULL;
- }
- if(matSize == 4) {
- //resize matrix
- mat[10] = mat[8];
- mat[9] = mat[7];
- mat[8] = mat[6];
- mat[7] = 0.0f;
- mat[6] = mat[5];
- mat[5] = mat[4];
- mat[4] = mat[3];
- mat[3] = 0.0f;
- }
- //pass to matrix creation
- return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.TranslationMatrix() -------
-//creates a translation matrix
-static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec)
-{
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!VectorObject_Check(vec)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): expected vector\n");
- return NULL;
- }
- if(vec->size != 3 && vec->size != 4) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- //create a identity matrix and add translation
- Mat4One((float(*)[4]) mat);
- mat[12] = vec->vec[0];
- mat[13] = vec->vec[1];
- mat[14] = vec->vec[2];
-
- return newMatrixObject(mat, 4, 4, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.ScaleMatrix() -------------
-//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates a scaling matrix
-static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
-{
- VectorObject *vec = NULL;
- float norm = 0.0f, factor;
- int matSize, x;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.ScaleMatrix(): expected float int and optional vector\n");
- return NULL;
- }
- if(matSize != 2 && matSize != 3 && matSize != 4) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
- return NULL;
- }
- if(vec) {
- if(vec->size > 2 && matSize == 2) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- }
- if(vec == NULL) { //scaling along axis
- if(matSize == 2) {
- mat[0] = factor;
- mat[3] = factor;
- } else {
- mat[0] = factor;
- mat[4] = factor;
- mat[8] = factor;
- }
- } else { //scaling in arbitrary direction
- //normalize arbitrary axis
- for(x = 0; x < vec->size; x++) {
- norm += vec->vec[x] * vec->vec[x];
- }
- norm = (float) sqrt(norm);
- for(x = 0; x < vec->size; x++) {
- vec->vec[x] /= norm;
- }
- if(matSize == 2) {
- mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0]));
- mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
- mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
- mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1]));
- } else {
- mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0]));
- mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
- mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2]));
- mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1]));
- mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1]));
- mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2]));
- mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2]));
- mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2]));
- mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2]));
- }
- }
- if(matSize == 4) {
- //resize matrix
- mat[10] = mat[8];
- mat[9] = mat[7];
- mat[8] = mat[6];
- mat[7] = 0.0f;
- mat[6] = mat[5];
- mat[5] = mat[4];
- mat[4] = mat[3];
- mat[3] = 0.0f;
- }
- //pass to matrix creation
- return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.OrthoProjectionMatrix() ---
-//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//creates an ortho projection matrix
-static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args)
-{
- VectorObject *vec = NULL;
- char *plane;
- int matSize, x;
- float norm = 0.0f;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n");
- return NULL;
- }
- if(matSize != 2 && matSize != 3 && matSize != 4) {
- PyErr_SetString(PyExc_AttributeError,"Mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
- return NULL;
- }
- if(vec) {
- if(vec->size > 2 && matSize == 2) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- }
- if(vec == NULL) { //ortho projection onto cardinal plane
- if(((strcmp(plane, "x") == 0)
- || (strcmp(plane, "X") == 0)) && matSize == 2) {
- mat[0] = 1.0f;
- } else if(((strcmp(plane, "y") == 0)
- || (strcmp(plane, "Y") == 0))
- && matSize == 2) {
- mat[3] = 1.0f;
- } else if(((strcmp(plane, "xy") == 0)
- || (strcmp(plane, "XY") == 0))
- && matSize > 2) {
- mat[0] = 1.0f;
- mat[4] = 1.0f;
- } else if(((strcmp(plane, "xz") == 0)
- || (strcmp(plane, "XZ") == 0))
- && matSize > 2) {
- mat[0] = 1.0f;
- mat[8] = 1.0f;
- } else if(((strcmp(plane, "yz") == 0)
- || (strcmp(plane, "YZ") == 0))
- && matSize > 2) {
- mat[4] = 1.0f;
- mat[8] = 1.0f;
- } else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: x, y, xy, xz, yz\n");
- return NULL;
- }
- } else { //arbitrary plane
- //normalize arbitrary axis
- for(x = 0; x < vec->size; x++) {
- norm += vec->vec[x] * vec->vec[x];
- }
- norm = (float) sqrt(norm);
- for(x = 0; x < vec->size; x++) {
- vec->vec[x] /= norm;
- }
- if(((strcmp(plane, "r") == 0)
- || (strcmp(plane, "R") == 0)) && matSize == 2) {
- mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
- mat[1] = -(vec->vec[0] * vec->vec[1]);
- mat[2] = -(vec->vec[0] * vec->vec[1]);
- mat[3] = 1 - (vec->vec[1] * vec->vec[1]);
- } else if(((strcmp(plane, "r") == 0)
- || (strcmp(plane, "R") == 0))
- && matSize > 2) {
- mat[0] = 1 - (vec->vec[0] * vec->vec[0]);
- mat[1] = -(vec->vec[0] * vec->vec[1]);
- mat[2] = -(vec->vec[0] * vec->vec[2]);
- mat[3] = -(vec->vec[0] * vec->vec[1]);
- mat[4] = 1 - (vec->vec[1] * vec->vec[1]);
- mat[5] = -(vec->vec[1] * vec->vec[2]);
- mat[6] = -(vec->vec[0] * vec->vec[2]);
- mat[7] = -(vec->vec[1] * vec->vec[2]);
- mat[8] = 1 - (vec->vec[2] * vec->vec[2]);
- } else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n");
- return NULL;
- }
- }
- if(matSize == 4) {
- //resize matrix
- mat[10] = mat[8];
- mat[9] = mat[7];
- mat[8] = mat[6];
- mat[7] = 0.0f;
- mat[6] = mat[5];
- mat[5] = mat[4];
- mat[4] = mat[3];
- mat[3] = 0.0f;
- }
- //pass to matrix creation
- return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.ShearMatrix() -------------
-//creates a shear matrix
-static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args)
-{
- int matSize;
- char *plane;
- float factor;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) {
- PyErr_SetString(PyExc_TypeError,"Mathutils.ShearMatrix(): expected string float and int\n");
- return NULL;
- }
- if(matSize != 2 && matSize != 3 && matSize != 4) {
- PyErr_SetString(PyExc_AttributeError,"Mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
- return NULL;
- }
-
- if(((strcmp(plane, "x") == 0) || (strcmp(plane, "X") == 0))
- && matSize == 2) {
- mat[0] = 1.0f;
- mat[2] = factor;
- mat[3] = 1.0f;
- } else if(((strcmp(plane, "y") == 0)
- || (strcmp(plane, "Y") == 0)) && matSize == 2) {
- mat[0] = 1.0f;
- mat[1] = factor;
- mat[3] = 1.0f;
- } else if(((strcmp(plane, "xy") == 0)
- || (strcmp(plane, "XY") == 0)) && matSize > 2) {
- mat[0] = 1.0f;
- mat[4] = 1.0f;
- mat[6] = factor;
- mat[7] = factor;
- } else if(((strcmp(plane, "xz") == 0)
- || (strcmp(plane, "XZ") == 0)) && matSize > 2) {
- mat[0] = 1.0f;
- mat[3] = factor;
- mat[4] = 1.0f;
- mat[5] = factor;
- mat[8] = 1.0f;
- } else if(((strcmp(plane, "yz") == 0)
- || (strcmp(plane, "YZ") == 0)) && matSize > 2) {
- mat[0] = 1.0f;
- mat[1] = factor;
- mat[2] = factor;
- mat[4] = 1.0f;
- mat[8] = 1.0f;
- } else {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n");
- return NULL;
- }
- if(matSize == 4) {
- //resize matrix
- mat[10] = mat[8];
- mat[9] = mat[7];
- mat[8] = mat[6];
- mat[7] = 0.0f;
- mat[6] = mat[5];
- mat[5] = mat[4];
- mat[4] = mat[3];
- mat[3] = 0.0f;
- }
- //pass to matrix creation
- return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL);
-}
-//----------------------------------QUATERNION FUNCTIONS-----------------
-
-//----------------------------------Mathutils.DifferenceQuats() ---------
-//returns the difference between 2 quaternions
-static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
-{
- QuaternionObject *quatU = NULL, *quatV = NULL;
- float quat[4], tempQuat[4];
- double dot = 0.0f;
- int x;
-
- if(!PyArg_ParseTuple(args, "O!O!", &quaternion_Type, &quatU, &quaternion_Type, &quatV)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
- tempQuat[0] = quatU->quat[0];
- tempQuat[1] = -quatU->quat[1];
- tempQuat[2] = -quatU->quat[2];
- tempQuat[3] = -quatU->quat[3];
-
- dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] * tempQuat[1] +
- tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
-
- for(x = 0; x < 4; x++) {
- tempQuat[x] /= (float)(dot * dot);
- }
- QuatMul(quat, tempQuat, quatV->quat);
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.Slerp() ------------------
-//attemps to interpolate 2 quaternions and return the result
-static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args)
-{
- QuaternionObject *quatU = NULL, *quatV = NULL;
- float quat[4], quat_u[4], quat_v[4], param;
- double x, y, dot, sinT, angle, IsinT;
- int z;
-
- if(!PyArg_ParseTuple(args, "O!O!f", &quaternion_Type, &quatU, &quaternion_Type, &quatV, &param)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
- return NULL;
-
- if(param > 1.0f || param < 0.0f) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
- return NULL;
- }
-
- //copy quats
- for(z = 0; z < 4; z++){
- quat_u[z] = quatU->quat[z];
- quat_v[z] = quatV->quat[z];
- }
-
- //dot product
- dot = quat_u[0] * quat_v[0] + quat_u[1] * quat_v[1] +
- quat_u[2] * quat_v[2] + quat_u[3] * quat_v[3];
-
- //if negative negate a quat (shortest arc)
- if(dot < 0.0f) {
- quat_v[0] = -quat_v[0];
- quat_v[1] = -quat_v[1];
- quat_v[2] = -quat_v[2];
- quat_v[3] = -quat_v[3];
- dot = -dot;
- }
- if(dot > .99999f) { //very close
- x = 1.0f - param;
- y = param;
- } else {
- //calculate sin of angle
- sinT = sqrt(1.0f - (dot * dot));
- //calculate angle
- angle = atan2(sinT, dot);
- //caluculate inverse of sin(theta)
- IsinT = 1.0f / sinT;
- x = sin((1.0f - param) * angle) * IsinT;
- y = sin(param * angle) * IsinT;
- }
- //interpolate
- quat[0] = (float)(quat_u[0] * x + quat_v[0] * y);
- quat[1] = (float)(quat_u[1] * x + quat_v[1] * y);
- quat[2] = (float)(quat_u[2] * x + quat_v[2] * y);
- quat[3] = (float)(quat_u[3] * x + quat_v[3] * y);
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//----------------------------------EULER FUNCTIONS----------------------
-//---------------------------------INTERSECTION FUNCTIONS--------------------
-//----------------------------------Mathutils.Intersect() -------------------
-static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
-{
- VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
- float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
- float det, inv_det, u, v, t;
- int clip = 1;
-
- if(!PyArg_ParseTuple(args, "O!O!O!O!O!|i", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off , &clip)) {
- PyErr_SetString( PyExc_TypeError, "expected 5 vector types\n" );
- return NULL;
- }
- if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors for all parameters\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off))
- return NULL;
-
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
-
- VECCOPY(dir, ray->vec);
- Normalize(dir);
-
- VECCOPY(orig, ray_off->vec);
-
- /* find vectors for two edges sharing v1 */
- VecSubf(e1, v2, v1);
- VecSubf(e2, v3, v1);
-
- /* begin calculating determinant - also used to calculated U parameter */
- Crossf(pvec, dir, e2);
-
- /* if determinant is near zero, ray lies in plane of triangle */
- det = Inpf(e1, pvec);
-
- if (det > -0.000001 && det < 0.000001) {
- Py_RETURN_NONE;
- }
-
- inv_det = 1.0f / det;
-
- /* calculate distance from v1 to ray origin */
- VecSubf(tvec, orig, v1);
-
- /* calculate U parameter and test bounds */
- u = Inpf(tvec, pvec) * inv_det;
- if (clip && (u < 0.0f || u > 1.0f)) {
- Py_RETURN_NONE;
- }
-
- /* prepare to test the V parameter */
- Crossf(qvec, tvec, e1);
-
- /* calculate V parameter and test bounds */
- v = Inpf(dir, qvec) * inv_det;
-
- if (clip && (v < 0.0f || u + v > 1.0f)) {
- Py_RETURN_NONE;
- }
-
- /* calculate t, ray intersects triangle */
- t = Inpf(e2, qvec) * inv_det;
-
- VecMulf(dir, t);
- VecAddf(pvec, orig, dir);
-
- return newVectorObject(pvec, 3, Py_NEW, NULL);
-}
-//----------------------------------Mathutils.LineIntersect() -------------------
-/* Line-Line intersection using algorithm from mathworld.wolfram.com */
-static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
-{
- PyObject * tuple;
- VectorObject *vec1, *vec2, *vec3, *vec4;
- float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
-
- if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec2->size) {
- PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- return NULL;
-
- if( vec1->size == 3 || vec1->size == 2) {
- int result;
-
- if (vec1->size == 3) {
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
- VECCOPY(v4, vec4->vec);
- }
- else {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
- v1[2] = 0.0f;
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
- v2[2] = 0.0f;
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
- v3[2] = 0.0f;
-
- v4[0] = vec4->vec[0];
- v4[1] = vec4->vec[1];
- v4[2] = 0.0f;
- }
-
- result = LineIntersectLine(v1, v2, v3, v4, i1, i2);
-
- if (result == 0) {
- /* colinear */
- Py_RETURN_NONE;
- }
- else {
- tuple = PyTuple_New( 2 );
- PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) );
- PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) );
- return tuple;
- }
- }
- else {
- PyErr_SetString( PyExc_TypeError, "2D/3D vectors only\n" );
- return NULL;
- }
-}
-
-
-
-//---------------------------------NORMALS FUNCTIONS--------------------
-//----------------------------------Mathutils.QuadNormal() -------------------
-static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
-{
- VectorObject *vec1;
- VectorObject *vec2;
- VectorObject *vec3;
- VectorObject *vec4;
- float v1[3], v2[3], v3[3], v4[3], e1[3], e2[3], n1[3], n2[3];
-
- if( !PyArg_ParseTuple( args, "O!O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
- PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
- return NULL;
- }
- if( vec1->size != 3 ) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4))
- return NULL;
-
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
- VECCOPY(v4, vec4->vec);
-
- /* find vectors for two edges sharing v2 */
- VecSubf(e1, v1, v2);
- VecSubf(e2, v3, v2);
-
- Crossf(n1, e2, e1);
- Normalize(n1);
-
- /* find vectors for two edges sharing v4 */
- VecSubf(e1, v3, v4);
- VecSubf(e2, v1, v4);
-
- Crossf(n2, e2, e1);
- Normalize(n2);
-
- /* adding and averaging the normals of both triangles */
- VecAddf(n1, n2, n1);
- Normalize(n1);
-
- return newVectorObject(n1, 3, Py_NEW, NULL);
-}
-
-//----------------------------Mathutils.TriangleNormal() -------------------
-static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
-{
- VectorObject *vec1, *vec2, *vec3;
- float v1[3], v2[3], v3[3], e1[3], e2[3], n[3];
-
- if( !PyArg_ParseTuple( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size ) {
- PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
- return NULL;
- }
- if( vec1->size != 3 ) {
- PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
-
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
-
- /* find vectors for two edges sharing v2 */
- VecSubf(e1, v1, v2);
- VecSubf(e2, v3, v2);
-
- Crossf(n, e2, e1);
- Normalize(n);
-
- return newVectorObject(n, 3, Py_NEW, NULL);
-}
-
-//--------------------------------- AREA FUNCTIONS--------------------
-//----------------------------------Mathutils.TriangleArea() -------------------
-static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
-{
- VectorObject *vec1, *vec2, *vec3;
- float v1[3], v2[3], v3[3];
-
- if( !PyArg_ParseTuple
- ( args, "O!O!O!", &vector_Type, &vec1, &vector_Type, &vec2
- , &vector_Type, &vec3 ) ) {
- PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n");
- return NULL;
- }
- if( vec1->size != vec2->size || vec1->size != vec3->size ) {
- PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
- return NULL;
-
- if (vec1->size == 3) {
- VECCOPY(v1, vec1->vec);
- VECCOPY(v2, vec2->vec);
- VECCOPY(v3, vec3->vec);
-
- return PyFloat_FromDouble( AreaT3Dfl(v1, v2, v3) );
- }
- else if (vec1->size == 2) {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
-
- return PyFloat_FromDouble( AreaF2Dfl(v1, v2, v3) );
- }
- else {
- PyErr_SetString( PyExc_TypeError, "only 2D,3D vectors are supported\n" );
- return NULL;
- }
-}
-
-/* Utility functions */
-
-/*---------------------- EXPP_FloatsAreEqual -------------------------
- Floating point comparisons
- floatStep = number of representable floats allowable in between
- float A and float B to be considered equal. */
-int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
-{
- int a, b, delta;
- assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
- a = *(int*)&A;
- if (a < 0)
- a = 0x80000000 - a;
- b = *(int*)&B;
- if (b < 0)
- b = 0x80000000 - b;
- delta = abs(a - b);
- if (delta <= floatSteps)
- return 1;
- return 0;
-}
-/*---------------------- EXPP_VectorsAreEqual -------------------------
- Builds on EXPP_FloatsAreEqual to test vectors */
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
-{
- int x;
- for (x=0; x< size; x++){
- if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
- return 0;
- }
- return 1;
-}
-
-
-/* Mathutils Callbacks */
-
-/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
-Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
-
-int Mathutils_RegisterCallback(Mathutils_Callback *cb)
-{
- int i;
-
- /* find the first free slot */
- for(i= 0; mathutils_callbacks[i]; i++) {
- if(mathutils_callbacks[i]==cb) /* alredy registered? */
- return i;
- }
-
- mathutils_callbacks[i] = cb;
- return i;
-}
-
-/* use macros to check for NULL */
-int _BaseMathObject_ReadCallback(BaseMathObject *self)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->get(self->cb_user, self->cb_subtype, self->data))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_WriteCallback(BaseMathObject *self)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->set(self->cb_user, self->cb_subtype, self->data))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->get_index(self->cb_user, self->cb_subtype, self->data, index))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
-{
- Mathutils_Callback *cb= mathutils_callbacks[self->cb_type];
- if(cb->set_index(self->cb_user, self->cb_subtype, self->data, index))
- return 1;
-
- PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
- return 0;
-}
-
-/* BaseMathObject generic functions for all mathutils types */
-PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type )
-{
- PyObject *ret= self->cb_user ? self->cb_user : Py_None;
- Py_INCREF(ret);
- return ret;
-}
-
-PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type )
-{
- return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
-}
-
-void BaseMathObject_dealloc(BaseMathObject * self)
-{
- /* only free non wrapped */
- if(self->wrapped != Py_WRAP)
- PyMem_Free(self->data);
-
- Py_XDECREF(self->cb_user);
- Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
-}
-
diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h
deleted file mode 100644
index 5bdd9d9cfe0..00000000000
--- a/source/blender/python/generic/Mathutils.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-//Include this file for access to vector, quat, matrix, euler, etc...
-
-#ifndef EXPP_Mathutils_H
-#define EXPP_Mathutils_H
-
-#include <Python.h>
-#include "../intern/bpy_compat.h"
-#include "vector.h"
-#include "matrix.h"
-#include "quat.h"
-#include "euler.h"
-
-/* #define USE_MATHUTILS_DEG - for backwards compat */
-
-/* Can cast different mathutils types to this, use for generic funcs */
-
-typedef struct {
- PyObject_VAR_HEAD
- float *data; /*array of data (alias), wrapped status depends on wrapped status */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
-} BaseMathObject;
-
-PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * );
-PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * );
-void BaseMathObject_dealloc(BaseMathObject * self);
-
-
-
-
-PyObject *Mathutils_Init( const char * from );
-
-PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
-
-int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
-
-
-#define Py_PI 3.14159265358979323846
-
-#define Py_NEW 1
-#define Py_WRAP 2
-
-
-/* Mathutils is used by the BGE and Blender so have to define
- * some things here for luddite mac users of py2.3 */
-#ifndef Py_RETURN_NONE
-#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-#ifndef Py_RETURN_FALSE
-#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
-#endif
-#ifndef Py_RETURN_TRUE
-#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
-#endif
-
-typedef struct Mathutils_Callback Mathutils_Callback;
-
-typedef int (*BaseMathCheckFunc)(PyObject *);
-typedef int (*BaseMathGetFunc)(PyObject *, int, float *);
-typedef int (*BaseMathSetFunc)(PyObject *, int, float *);
-typedef int (*BaseMathGetIndexFunc)(PyObject *, int, float *, int);
-typedef int (*BaseMathSetIndexFunc)(PyObject *, int, float *, int);
-
-struct Mathutils_Callback {
- int (*check)(PyObject *user); /* checks the user is still valid */
- int (*get)(PyObject *user, int subtype, float *from); /* gets the vector from the user */
- int (*set)(PyObject *user, int subtype, float *to); /* sets the users vector values once the vector is modified */
- int (*get_index)(PyObject *user, int subtype, float *from,int index); /* same as above but only for an index */
- int (*set_index)(PyObject *user, int subtype, float *to, int index); /* same as above but only for an index */
-};
-
-int Mathutils_RegisterCallback(Mathutils_Callback *cb);
-
-int _BaseMathObject_ReadCallback(BaseMathObject *self);
-int _BaseMathObject_WriteCallback(BaseMathObject *self);
-int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
-int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
-
-/* since this is called so often avoid where possible */
-#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1))
-#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1))
-#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1))
-#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1))
-
-#endif /* EXPP_Mathutils_H */
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
deleted file mode 100644
index c41ea386c0e..00000000000
--- a/source/blender/python/generic/bpy_internal_import.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Willian P. Germano
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-
-#include "bpy_internal_import.h"
-#include "DNA_text_types.h"
-#include "DNA_ID.h"
-
-#include "MEM_guardedalloc.h"
-#include "BKE_text.h" /* txt_to_buf */
-#include "BKE_main.h"
-
-static Main *bpy_import_main= NULL;
-
-static void free_compiled_text(Text *text)
-{
- if(text->compiled) {
- Py_DECREF(( PyObject * )text->compiled);
- }
- text->compiled= NULL;
-}
-
-struct Main *bpy_import_main_get(void)
-{
- return bpy_import_main;
-}
-
-void bpy_import_main_set(struct Main *maggie)
-{
- bpy_import_main= maggie;
-}
-
-
-PyObject *bpy_text_import( char *name, int *found )
-{
- Text *text;
- char txtname[22]; /* 21+NULL */
- char *buf = NULL;
- int namelen = strlen( name );
-//XXX Main *maggie= bpy_import_main ? bpy_import_main:G.main;
- Main *maggie= bpy_import_main;
-
- *found= 0;
-
- if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
-
- memcpy( txtname, name, namelen );
- memcpy( &txtname[namelen], ".py", 4 );
-
- for(text = maggie->text.first; text; text = text->id.next) {
- if( !strcmp( txtname, text->id.name+2 ) )
- break;
- }
-
- if( !text )
- return NULL;
- else
- *found = 1;
-
- if( !text->compiled ) {
- buf = txt_to_buf( text );
- text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
- MEM_freeN( buf );
-
- if( PyErr_Occurred( ) ) {
- PyErr_Print( );
- PyErr_Clear( );
- PySys_SetObject("last_traceback", NULL);
- free_compiled_text( text );
- return NULL;
- }
- }
-
- return PyImport_ExecCodeModule( name, text->compiled );
-}
-
-
-/*
- * find in-memory module and recompile
- */
-
-PyObject *bpy_text_reimport( PyObject *module, int *found )
-{
- Text *text;
- char *txtname;
- char *name;
- char *buf = NULL;
-//XXX Main *maggie= bpy_import_main ? bpy_import_main:G.main;
- Main *maggie= bpy_import_main;
-
- *found= 0;
-
- /* get name, filename from the module itself */
-
- txtname = PyModule_GetFilename( module );
- name = PyModule_GetName( module );
- if( !txtname || !name)
- return NULL;
-
- /* look up the text object */
- text = ( Text * ) & ( maggie->text.first );
- while( text ) {
- if( !strcmp( txtname, text->id.name+2 ) )
- break;
- text = text->id.next;
- }
-
- /* uh-oh.... didn't find it */
- if( !text )
- return NULL;
- else
- *found = 1;
-
- /* if previously compiled, free the object */
- /* (can't see how could be NULL, but check just in case) */
- if( text->compiled ){
- Py_DECREF( (PyObject *)text->compiled );
- }
-
- /* compile the buffer */
- buf = txt_to_buf( text );
- text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
- MEM_freeN( buf );
-
- /* if compile failed.... return this error */
- if( PyErr_Occurred( ) ) {
- PyErr_Print( );
- PyErr_Clear( );
- PySys_SetObject("last_traceback", NULL);
- free_compiled_text( text );
- return NULL;
- }
-
- /* make into a module */
- return PyImport_ExecCodeModule( name, text->compiled );
-}
-
-
-static PyObject *blender_import( PyObject * self, PyObject * args, PyObject * kw)
-{
- PyObject *exception, *err, *tb;
- char *name;
- int found= 0;
- PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
- PyObject *newmodule;
-
- //PyObject_Print(args, stderr, 0);
-#if (PY_VERSION_HEX >= 0x02060000)
- int dummy_val; /* what does this do?*/
- static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
-
- if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bpy_import_meth", kwlist,
- &name, &globals, &locals, &fromlist, &dummy_val) )
- return NULL;
-#else
- static char *kwlist[] = {"name", "globals", "locals", "fromlist", 0};
-
- if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOO:bpy_import_meth", kwlist,
- &name, &globals, &locals, &fromlist ) )
- return NULL;
-#endif
-
- /* import existing builtin modules or modules that have been imported alredy */
- newmodule = PyImport_ImportModuleEx( name, globals, locals, fromlist );
-
- if(newmodule)
- return newmodule;
-
- PyErr_Fetch( &exception, &err, &tb ); /* get the python error incase we cant import as blender text either */
-
- /* importing from existing modules failed, see if we have this module as blender text */
- newmodule = bpy_text_import( name, &found );
-
- if( newmodule ) {/* found module as blender text, ignore above exception */
- PyErr_Clear( );
- Py_XDECREF( exception );
- Py_XDECREF( err );
- Py_XDECREF( tb );
- /* printf( "imported from text buffer...\n" ); */
- }
- else if (found==1) { /* blender text module failed to execute but was found, use its error message */
- Py_XDECREF( exception );
- Py_XDECREF( err );
- Py_XDECREF( tb );
- return NULL;
- }
- else {
- /* no blender text was found that could import the module
- * rause the original error from PyImport_ImportModuleEx */
- PyErr_Restore( exception, err, tb );
- }
- return newmodule;
-}
-
-
-/*
- * our reload() module, to handle reloading in-memory scripts
- */
-
-static PyObject *blender_reload( PyObject * self, PyObject * args )
-{
- PyObject *exception, *err, *tb;
- PyObject *module = NULL;
- PyObject *newmodule = NULL;
- int found= 0;
-
- /* check for a module arg */
- if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
- return NULL;
-
- /* try reimporting from file */
- newmodule = PyImport_ReloadModule( module );
- if( newmodule )
- return newmodule;
-
- /* no file, try importing from memory */
- PyErr_Fetch( &exception, &err, &tb ); /*restore for probable later use */
-
- newmodule = bpy_text_reimport( module, &found );
- if( newmodule ) {/* found module as blender text, ignore above exception */
- PyErr_Clear( );
- Py_XDECREF( exception );
- Py_XDECREF( err );
- Py_XDECREF( tb );
- /* printf( "imported from text buffer...\n" ); */
- }
- else if (found==1) { /* blender text module failed to execute but was found, use its error message */
- Py_XDECREF( exception );
- Py_XDECREF( err );
- Py_XDECREF( tb );
- return NULL;
- }
- else {
- /* no blender text was found that could import the module
- * rause the original error from PyImport_ImportModuleEx */
- PyErr_Restore( exception, err, tb );
- }
-
- return newmodule;
-}
-
-PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"} };
-PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", blender_reload, METH_VARARGS, "blenders reload"} };
-
-
-/* Clear user modules.
- * This is to clear any modules that could be defined from running scripts in blender.
- *
- * Its also needed for the BGE Python api so imported scripts are not used between levels
- *
- * This clears every modules that has a __file__ attribute (is not a builtin)
- *
- * Note that clearing external python modules is important for the BGE otherwise
- * it wont reload scripts between loading different blend files or while making the game.
- * - use 'clear_all' arg in this case.
- *
- * Since pythons bultins include a full path even for win32.
- * even if we remove a python module a reimport will bring it back again.
- */
-
-#if 0 // not used anymore but may still come in handy later
-
-#if defined(WIN32) || defined(WIN64)
-#define SEPSTR "\\"
-#else
-#define SEPSTR "/"
-#endif
-
-
-void bpy_text_clear_modules(int clear_all)
-{
- PyObject *modules= PySys_GetObject("modules");
-
- char *fname;
- char *file_extension;
-
- /* looping over the dict */
- PyObject *key, *value;
- int pos = 0;
-
- /* new list */
- PyObject *list;
-
- if (modules==NULL)
- return; /* should never happen but just incase */
-
- list= PyList_New(0);
-
- /* go over sys.modules and remove anything with a
- * sys.modukes[x].__file__ thats ends with a .py and has no path
- */
- while (PyDict_Next(modules, &pos, &key, &value)) {
- fname= PyModule_GetFilename(value);
- if(fname) {
- if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
- file_extension = strstr(fname, ".py");
- if(file_extension && (*(file_extension + 3) == '\0' || *(file_extension + 4) == '\0')) { /* .py or pyc extension? */
- /* now we can be fairly sure its a python import from the blendfile */
- PyList_Append(list, key); /* free'd with the list */
- }
- }
- }
- else {
- PyErr_Clear();
- }
- }
-
- /* remove all our modules */
- for(pos=0; pos < PyList_Size(list); pos++) {
- /* PyObject_Print(key, stderr, 0); */
- key= PyList_GET_ITEM(list, pos);
- PyDict_DelItem(modules, key);
- }
-
- Py_DECREF(list); /* removes all references from append */
-}
-#endif
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
deleted file mode 100644
index aeeafb7c1c4..00000000000
--- a/source/blender/python/generic/bpy_internal_import.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Willian P. Germano, Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
-*/
-
-/* Note, the BGE needs to use this too, keep it minimal */
-
-#ifndef EXPP_bpy_import_h
-#define EXPP_bpy_import_h
-
-#include <Python.h>
-#include "../intern/bpy_compat.h"
-#include "compile.h" /* for the PyCodeObject */
-#include "eval.h" /* for PyEval_EvalCode */
-
-PyObject* bpy_text_import( char *name, int *found );
-PyObject* bpy_text_reimport( PyObject *module, int *found );
-/* void bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */
-extern PyMethodDef bpy_import_meth[];
-extern PyMethodDef bpy_reload_meth[];
-
-/* The game engine has its own Main struct, if this is set search this rather then G.main */
-struct Main *bpy_import_main_get(void);
-void bpy_import_main_set(struct Main *maggie);
-
-
-#endif /* EXPP_bpy_import_h */
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
deleted file mode 100644
index 69373b1aa36..00000000000
--- a/source/blender/python/generic/euler.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Mathutils.h"
-
-#include "BLI_arithb.h"
-#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
-
-
-//-------------------------DOC STRINGS ---------------------------
-
-static PyObject *Euler_Zero( EulerObject * self );
-static PyObject *Euler_Unique( EulerObject * self );
-static PyObject *Euler_ToMatrix( EulerObject * self );
-static PyObject *Euler_ToQuat( EulerObject * self );
-static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
-static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
-static PyObject *Euler_copy( EulerObject * self, PyObject *args );
-
-//-----------------------METHOD DEFINITIONS ----------------------
-static struct PyMethodDef Euler_methods[] = {
- {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL},
- {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL},
- {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL},
- {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL},
- {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
- {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL},
- {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
- {"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-//----------------------------------Mathutils.Euler() -------------------
-//makes a new euler for you to play with
-static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
-{
- PyObject *listObject = NULL;
- int size, i;
- float eul[3];
- PyObject *e;
-
- size = PyTuple_GET_SIZE(args);
- if (size == 1) {
- listObject = PyTuple_GET_ITEM(args, 0);
- if (PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- } else { // Single argument was not a sequence
- PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
- return NULL;
- }
- } else if (size == 0) {
- //returns a new empty 3d euler
- return newEulerObject(NULL, Py_NEW, NULL);
- } else {
- listObject = args;
- }
-
- if (size != 3) { // Invalid euler size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
- return NULL;
- }
-
- for (i=0; i<size; i++) {
- e = PySequence_GetItem(listObject, i);
- if (e == NULL) { // Failed to read sequence
- Py_DECREF(listObject);
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
- return NULL;
- }
-
- eul[i]= (float)PyFloat_AsDouble(e);
- Py_DECREF(e);
-
- if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
- PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
- return NULL;
- }
- }
- return newEulerObject(eul, Py_NEW, NULL);
-}
-
-//-----------------------------METHODS----------------------------
-//----------------------------Euler.toQuat()----------------------
-//return a quaternion representation of the euler
-static PyObject *Euler_ToQuat(EulerObject * self)
-{
- float quat[4];
-#ifdef USE_MATHUTILS_DEG
- float eul[3];
- int x;
-#endif
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- for(x = 0; x < 3; x++) {
- eul[x] = self->eul[x] * ((float)Py_PI / 180);
- }
- EulToQuat(eul, quat);
-#else
- EulToQuat(self->eul, quat);
-#endif
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//----------------------------Euler.toMatrix()---------------------
-//return a matrix representation of the euler
-static PyObject *Euler_ToMatrix(EulerObject * self)
-{
- float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- {
- float eul[3];
- int x;
-
- for(x = 0; x < 3; x++) {
- eul[x] = self->eul[x] * ((float)Py_PI / 180);
- }
- EulToMat3(eul, (float (*)[3]) mat);
- }
-#else
- EulToMat3(self->eul, (float (*)[3]) mat);
-#endif
- return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
-}
-//----------------------------Euler.unique()-----------------------
-//sets the x,y,z values to a unique euler rotation
-static PyObject *Euler_Unique(EulerObject * self)
-{
-#define PI_2 (Py_PI * 2.0)
-#define PI_HALF (Py_PI / 2.0)
-#define PI_INV (1.0 / Py_PI)
-
- double heading, pitch, bank;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- //radians
- heading = self->eul[0] * (float)Py_PI / 180;
- pitch = self->eul[1] * (float)Py_PI / 180;
- bank = self->eul[2] * (float)Py_PI / 180;
-#else
- heading = self->eul[0];
- pitch = self->eul[1];
- bank = self->eul[2];
-#endif
-
- //wrap heading in +180 / -180
- pitch += Py_PI;
- pitch -= floor(pitch * PI_INV) * PI_2;
- pitch -= Py_PI;
-
-
- if(pitch < -PI_HALF) {
- pitch = -Py_PI - pitch;
- heading += Py_PI;
- bank += Py_PI;
- } else if(pitch > PI_HALF) {
- pitch = Py_PI - pitch;
- heading += Py_PI;
- bank += Py_PI;
- }
- //gimbal lock test
- if(fabs(pitch) > PI_HALF - 1e-4) {
- heading += bank;
- bank = 0.0f;
- } else {
- bank += Py_PI;
- bank -= (floor(bank * PI_INV)) * PI_2;
- bank -= Py_PI;
- }
-
- heading += Py_PI;
- heading -= (floor(heading * PI_INV)) * PI_2;
- heading -= Py_PI;
-
-#ifdef USE_MATHUTILS_DEG
- //back to degrees
- self->eul[0] = (float)(heading * 180 / (float)Py_PI);
- self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
- self->eul[2] = (float)(bank * 180 / (float)Py_PI);
-#endif
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-//----------------------------Euler.zero()-------------------------
-//sets the euler to 0,0,0
-static PyObject *Euler_Zero(EulerObject * self)
-{
- self->eul[0] = 0.0;
- self->eul[1] = 0.0;
- self->eul[2] = 0.0;
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-//----------------------------Euler.rotate()-----------------------
-//rotates a euler a certain amount and returns the result
-//should return a unique euler rotation (i.e. no 720 degree pitches :)
-static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
-{
- float angle = 0.0f;
- char *axis;
-
- if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
- PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
- return NULL;
- }
- if(!STREQ3(axis,"x","y","z")){
- PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
-
- //covert to radians
- angle *= ((float)Py_PI / 180);
- for(x = 0; x < 3; x++) {
- self->eul[x] *= ((float)Py_PI / 180);
- }
- }
-#endif
- euler_rot(self->eul, angle, *axis);
-
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
- //convert back from radians
- for(x = 0; x < 3; x++) {
- self->eul[x] *= (180 / (float)Py_PI);
- }
- }
-#endif
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
-{
-#ifdef USE_MATHUTILS_DEG
- float eul_from_rad[3];
- int x;
-#endif
-
- if(!EulerObject_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- //covert to radians
- for(x = 0; x < 3; x++) {
- self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
- eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
- }
- compatible_eul(self->eul, eul_from_rad);
-#else
- compatible_eul(self->eul, value->eul);
-#endif
-
-#ifdef USE_MATHUTILS_DEG
- //convert back from radians
- for(x = 0; x < 3; x++) {
- self->eul[x] *= (180 / (float)Py_PI);
- }
-#endif
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-//----------------------------Euler.rotate()-----------------------
-// return a copy of the euler
-static PyObject *Euler_copy(EulerObject * self, PyObject *args)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
-}
-
-//----------------------------print object (internal)--------------
-//print the object to screen
-static PyObject *Euler_repr(EulerObject * self)
-{
- char str[64];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
- return PyUnicode_FromString(str);
-}
-//------------------------tp_richcmpr
-//returns -1 execption, 0 false, 1 true
-static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
-{
- EulerObject *eulA = NULL, *eulB = NULL;
- int result = 0;
-
- if(EulerObject_Check(objectA)) {
- eulA = (EulerObject*)objectA;
- if(!BaseMath_ReadCallback(eulA))
- return NULL;
- }
- if(EulerObject_Check(objectB)) {
- eulB = (EulerObject*)objectB;
- if(!BaseMath_ReadCallback(eulB))
- return NULL;
- }
-
- if (!eulA || !eulB){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
- eulA = (EulerObject*)objectA;
- eulB = (EulerObject*)objectB;
-
- switch (comparison_type){
- case Py_EQ:
- result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
- break;
- case Py_NE:
- result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
- if (result == 0){
- result = 1;
- }else{
- result = 0;
- }
- break;
- default:
- printf("The result of the comparison could not be evaluated");
- break;
- }
- if (result == 1){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
-}
-
-//---------------------SEQUENCE PROTOCOLS------------------------
-//----------------------------len(object)------------------------
-//sequence length
-static int Euler_len(EulerObject * self)
-{
- return 3;
-}
-//----------------------------object[]---------------------------
-//sequence accessor (get)
-static PyObject *Euler_item(EulerObject * self, int i)
-{
- if(i<0) i= 3-i;
-
- if(i < 0 || i >= 3) {
- PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
- return NULL;
- }
-
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
- return PyFloat_FromDouble(self->eul[i]);
-
-}
-//----------------------------object[]-------------------------
-//sequence accessor (set)
-static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
-{
- float f = PyFloat_AsDouble(value);
-
- if(f == -1 && PyErr_Occurred()) { // parsed item not a number
- PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
- return -1;
- }
-
- if(i<0) i= 3-i;
-
- if(i < 0 || i >= 3){
- PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
- return -1;
- }
-
- self->eul[i] = f;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
-
- return 0;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (get)
-static PyObject *Euler_slice(EulerObject * self, int begin, int end)
-{
- PyObject *list = NULL;
- int count;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- CLAMP(begin, 0, 3);
- if (end<0) end= 4+end;
- CLAMP(end, 0, 3);
- begin = MIN2(begin,end);
-
- list = PyList_New(end - begin);
- for(count = begin; count < end; count++) {
- PyList_SetItem(list, count - begin,
- PyFloat_FromDouble(self->eul[count]));
- }
-
- return list;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (set)
-static int Euler_ass_slice(EulerObject * self, int begin, int end,
- PyObject * seq)
-{
- int i, y, size = 0;
- float eul[3];
- PyObject *e;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- CLAMP(begin, 0, 3);
- if (end<0) end= 4+end;
- CLAMP(end, 0, 3);
- begin = MIN2(begin,end);
-
- size = PySequence_Length(seq);
- if(size != (end - begin)){
- PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
- return -1;
- }
-
- for (i = 0; i < size; i++) {
- e = PySequence_GetItem(seq, i);
- if (e == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
- return -1;
- }
-
- eul[i] = (float)PyFloat_AsDouble(e);
- Py_DECREF(e);
-
- if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
- PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
- return -1;
- }
- }
- //parsed well - now set in vector
- for(y = 0; y < 3; y++){
- self->eul[begin + y] = eul[y];
- }
-
- BaseMath_WriteCallback(self);
- return 0;
-}
-//-----------------PROTCOL DECLARATIONS--------------------------
-static PySequenceMethods Euler_SeqMethods = {
- (inquiry) Euler_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (ssizeargfunc) 0, /* sq_repeat */
- (ssizeargfunc) Euler_item, /* sq_item */
- (ssizessizeargfunc) Euler_slice, /* sq_slice */
- (ssizeobjargproc) Euler_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc) Euler_ass_slice, /* sq_ass_slice */
-};
-
-
-/*
- * vector axis, vector.x/y/z/w
- */
-
-static PyObject *Euler_getAxis( EulerObject * self, void *type )
-{
- return Euler_item(self, GET_INT_FROM_POINTER(type));
-}
-
-static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
-{
- return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
-}
-
-/*****************************************************************************/
-/* Python attributes get/set structure: */
-/*****************************************************************************/
-static PyGetSetDef Euler_getseters[] = {
- {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
- {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
- {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
-
- {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
- {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
-};
-
-//------------------PY_OBECT DEFINITION--------------------------
-PyTypeObject euler_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- "euler", //tp_name
- sizeof(EulerObject), //tp_basicsize
- 0, //tp_itemsize
- (destructor)BaseMathObject_dealloc, //tp_dealloc
- 0, //tp_print
- 0, //tp_getattr
- 0, //tp_setattr
- 0, //tp_compare
- (reprfunc) Euler_repr, //tp_repr
- 0, //tp_as_number
- &Euler_SeqMethods, //tp_as_sequence
- 0, //tp_as_mapping
- 0, //tp_hash
- 0, //tp_call
- 0, //tp_str
- 0, //tp_getattro
- 0, //tp_setattro
- 0, //tp_as_buffer
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
- 0, //tp_doc
- 0, //tp_traverse
- 0, //tp_clear
- (richcmpfunc)Euler_richcmpr, //tp_richcompare
- 0, //tp_weaklistoffset
- 0, //tp_iter
- 0, //tp_iternext
- Euler_methods, //tp_methods
- 0, //tp_members
- Euler_getseters, //tp_getset
- 0, //tp_base
- 0, //tp_dict
- 0, //tp_descr_get
- 0, //tp_descr_set
- 0, //tp_dictoffset
- 0, //tp_init
- 0, //tp_alloc
- Euler_new, //tp_new
- 0, //tp_free
- 0, //tp_is_gc
- 0, //tp_bases
- 0, //tp_mro
- 0, //tp_cache
- 0, //tp_subclasses
- 0, //tp_weaklist
- 0 //tp_del
-};
-//------------------------newEulerObject (internal)-------------
-//creates a new euler object
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
- pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
-{
- EulerObject *self;
- int x;
-
- if(base_type) self = (EulerObject *)base_type->tp_alloc(base_type, 0);
- else self = PyObject_NEW(EulerObject, &euler_Type);
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
-
- if(type == Py_WRAP){
- self->eul = eul;
- self->wrapped = Py_WRAP;
- }else if (type == Py_NEW){
- self->eul = PyMem_Malloc(3 * sizeof(float));
- if(!eul) { //new empty
- for(x = 0; x < 3; x++) {
- self->eul[x] = 0.0f;
- }
- }else{
- VECCOPY(self->eul, eul);
- }
- self->wrapped = Py_NEW;
- }else{ //bad type
- return NULL;
- }
- return (PyObject *)self;
-}
-
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
-{
- EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h
deleted file mode 100644
index a3706d53756..00000000000
--- a/source/blender/python/generic/euler.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-#ifndef EXPP_euler_h
-#define EXPP_euler_h
-
-#include <Python.h>
-#include "../intern/bpy_compat.h"
-
-extern PyTypeObject euler_Type;
-#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type)
-
-typedef struct {
- PyObject_VAR_HEAD
- float *eul; /*1D array of data */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
-} EulerObject;
-
-/*struct data contains a pointer to the actual data that the
-object uses. It can use either PyMem allocated data (which will
-be stored in py_data) or be a wrapper for data allocated through
-blender (stored in blend_data). This is an either/or struct not both*/
-
-//prototypes
-PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type);
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
-
-#endif /* EXPP_euler_h */
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
deleted file mode 100644
index 5bdbf804618..00000000000
--- a/source/blender/python/generic/matrix.c
+++ /dev/null
@@ -1,1358 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * Contributor(s): Michel Selten & Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Mathutils.h"
-
-#include "BKE_utildefines.h"
-#include "BLI_arithb.h"
-#include "BLI_blenlib.h"
-
-static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); /* utility func */
-
-
-/* matrix vector callbacks */
-int mathutils_matrix_vector_cb_index= -1;
-
-static int mathutils_matrix_vector_check(MatrixObject *self)
-{
- return BaseMath_ReadCallback(self);
-}
-
-static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- for(i=0; i<self->colSize; i++)
- vec_from[i]= self->matrix[subtype][i];
-
- return 1;
-}
-
-static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- for(i=0; i<self->colSize; i++)
- self->matrix[subtype][i]= vec_to[i];
-
- BaseMath_WriteCallback(self);
- return 1;
-}
-
-static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index)
-{
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- vec_from[index]= self->matrix[subtype][index];
- return 1;
-}
-
-static int mathutils_matrix_vector_set_index(MatrixObject *self, int subtype, float *vec_to, int index)
-{
- if(!BaseMath_ReadCallback(self))
- return 0;
-
- self->matrix[subtype][index]= vec_to[index];
-
- BaseMath_WriteCallback(self);
- return 1;
-}
-
-Mathutils_Callback mathutils_matrix_vector_cb = {
- mathutils_matrix_vector_check,
- mathutils_matrix_vector_get,
- mathutils_matrix_vector_set,
- mathutils_matrix_vector_get_index,
- mathutils_matrix_vector_set_index
-};
-/* matrix vector callbacks, this is so you can do matrix[i][j] = val */
-
-/*-------------------------DOC STRINGS ---------------------------*/
-
-static PyObject *Matrix_Zero( MatrixObject * self );
-static PyObject *Matrix_Identity( MatrixObject * self );
-static PyObject *Matrix_Transpose( MatrixObject * self );
-static PyObject *Matrix_Determinant( MatrixObject * self );
-static PyObject *Matrix_Invert( MatrixObject * self );
-static PyObject *Matrix_TranslationPart( MatrixObject * self );
-static PyObject *Matrix_RotationPart( MatrixObject * self );
-static PyObject *Matrix_scalePart( MatrixObject * self );
-static PyObject *Matrix_Resize4x4( MatrixObject * self );
-static PyObject *Matrix_toEuler( MatrixObject * self, PyObject *args );
-static PyObject *Matrix_toQuat( MatrixObject * self );
-static PyObject *Matrix_copy( MatrixObject * self );
-
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-static struct PyMethodDef Matrix_methods[] = {
- {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL},
- {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL},
- {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL},
- {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL},
- {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL},
- {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL},
- {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL},
- {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL},
- {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL},
- {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL},
- {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL},
- {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
- {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-//----------------------------------Mathutils.Matrix() -----------------
-//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc.
-//create a new matrix type
-static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *argObject, *m, *s;
- MatrixObject *mat;
- int argSize, seqSize = 0, i, j;
- float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- float scalar;
-
- argSize = PyTuple_GET_SIZE(args);
- if(argSize > 4){ //bad arg nums
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
- return NULL;
- } else if (argSize == 0) { //return empty 4D matrix
- return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, NULL);
- }else if (argSize == 1){
- //copy constructor for matrix objects
- argObject = PyTuple_GET_ITEM(args, 0);
- if(MatrixObject_Check(argObject)){
- mat = (MatrixObject*)argObject;
- if(!BaseMath_ReadCallback(mat))
- return NULL;
-
- memcpy(matrix, mat->contigPtr, sizeof(float) * mat->rowSize * mat->colSize);
- }
- }else{ //2-4 arguments (all seqs? all same size?)
- for(i =0; i < argSize; i++){
- argObject = PyTuple_GET_ITEM(args, i);
- if (PySequence_Check(argObject)) { //seq?
- if(seqSize){ //0 at first
- if(PySequence_Length(argObject) != seqSize){ //seq size not same
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
- return NULL;
- }
- }
- seqSize = PySequence_Length(argObject);
- }else{ //arg not a sequence
- PyErr_SetString(PyExc_TypeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
- return NULL;
- }
- }
- //all is well... let's continue parsing
- for (i = 0; i < argSize; i++){
- m = PyTuple_GET_ITEM(args, i);
- if (m == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
- return NULL;
- }
-
- for (j = 0; j < seqSize; j++) {
- s = PySequence_GetItem(m, j);
- if (s == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Matrix(): failed to parse arguments...\n");
- return NULL;
- }
-
- scalar= (float)PyFloat_AsDouble(s);
- Py_DECREF(s);
-
- if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n");
- return NULL;
- }
-
- matrix[(seqSize*i)+j]= scalar;
- }
- }
- }
- return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL);
-}
-
-/*-----------------------------METHODS----------------------------*/
-/*---------------------------Matrix.toQuat() ---------------------*/
-static PyObject *Matrix_toQuat(MatrixObject * self)
-{
- float quat[4];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- /*must be 3-4 cols, 3-4 rows, square matrix*/
- if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
- PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
- return NULL;
- }
- if(self->colSize == 3){
- Mat3ToQuat((float (*)[3])*self->matrix, quat);
- }else{
- Mat4ToQuat((float (*)[4])*self->matrix, quat);
- }
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-/*---------------------------Matrix.toEuler() --------------------*/
-PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
-{
- float eul[3], eul_compatf[3];
- EulerObject *eul_compat = NULL;
-#ifdef USE_MATHUTILS_DEG
- int x;
-#endif
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
- return NULL;
-
- if(eul_compat) {
- if(!BaseMath_ReadCallback(eul_compat))
- return NULL;
-
-#ifdef USE_MATHUTILS_DEG
- for(x = 0; x < 3; x++) {
- eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
- }
-#else
- VECCOPY(eul_compatf, eul_compat->eul);
-#endif
- }
-
- /*must be 3-4 cols, 3-4 rows, square matrix*/
- if(self->colSize ==3 && self->rowSize ==3) {
- if(eul_compat) Mat3ToCompatibleEul((float (*)[3])*self->matrix, eul, eul_compatf);
- else Mat3ToEul((float (*)[3])*self->matrix, eul);
- }else if (self->colSize ==4 && self->rowSize ==4) {
- float tempmat3[3][3];
- Mat3CpyMat4(tempmat3, (float (*)[4])*self->matrix);
- Mat3ToEul(tempmat3, eul);
- if(eul_compat) Mat3ToCompatibleEul(tempmat3, eul, eul_compatf);
- else Mat3ToEul(tempmat3, eul);
-
- }else {
- PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
- return NULL;
- }
-#ifdef USE_MATHUTILS_DEG
- /*have to convert to degrees*/
- for(x = 0; x < 3; x++) {
- eul[x] *= (float) (180 / Py_PI);
- }
-#endif
- return newEulerObject(eul, Py_NEW, NULL);
-}
-/*---------------------------Matrix.resize4x4() ------------------*/
-PyObject *Matrix_Resize4x4(MatrixObject * self)
-{
- int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
-
- if(self->wrapped==Py_WRAP){
- PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - make a copy and resize that");
- return NULL;
- }
- if(self->cb_user){
- PyErr_SetString(PyExc_TypeError, "cannot resize owned data - make a copy and resize that");
- return NULL;
- }
-
- self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16));
- if(self->contigPtr == NULL) {
- PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
- return NULL;
- }
- self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4));
- if(self->matrix == NULL) {
- PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space");
- return NULL;
- }
- /*set row pointers*/
- for(x = 0; x < 4; x++) {
- self->matrix[x] = self->contigPtr + (x * 4);
- }
- /*move data to new spot in array + clean*/
- for(blank_rows = (4 - self->rowSize); blank_rows > 0; blank_rows--){
- for(x = 0; x < 4; x++){
- index = (4 * (self->rowSize + (blank_rows - 1))) + x;
- if (index == 10 || index == 15){
- self->contigPtr[index] = 1.0f;
- }else{
- self->contigPtr[index] = 0.0f;
- }
- }
- }
- for(x = 1; x <= self->rowSize; x++){
- first_row_elem = (self->colSize * (self->rowSize - x));
- curr_pos = (first_row_elem + (self->colSize -1));
- new_pos = (4 * (self->rowSize - x )) + (curr_pos - first_row_elem);
- for(blank_columns = (4 - self->colSize); blank_columns > 0; blank_columns--){
- self->contigPtr[new_pos + blank_columns] = 0.0f;
- }
- for(curr_pos = curr_pos; curr_pos >= first_row_elem; curr_pos--){
- self->contigPtr[new_pos] = self->contigPtr[curr_pos];
- new_pos--;
- }
- }
- self->rowSize = 4;
- self->colSize = 4;
-
- Py_INCREF(self);
- return (PyObject *)self;
-}
-/*---------------------------Matrix.translationPart() ------------*/
-PyObject *Matrix_TranslationPart(MatrixObject * self)
-{
- float vec[4];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->colSize < 3 || self->rowSize < 4){
- PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
- return NULL;
- }
-
- vec[0] = self->matrix[3][0];
- vec[1] = self->matrix[3][1];
- vec[2] = self->matrix[3][2];
-
- return newVectorObject(vec, 3, Py_NEW, NULL);
-}
-/*---------------------------Matrix.rotationPart() ---------------*/
-PyObject *Matrix_RotationPart(MatrixObject * self)
-{
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->colSize < 3 || self->rowSize < 3){
- PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
- return NULL;
- }
-
- mat[0] = self->matrix[0][0];
- mat[1] = self->matrix[0][1];
- mat[2] = self->matrix[0][2];
- mat[3] = self->matrix[1][0];
- mat[4] = self->matrix[1][1];
- mat[5] = self->matrix[1][2];
- mat[6] = self->matrix[2][0];
- mat[7] = self->matrix[2][1];
- mat[8] = self->matrix[2][2];
-
- return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self));
-}
-/*---------------------------Matrix.scalePart() --------------------*/
-PyObject *Matrix_scalePart(MatrixObject * self)
-{
- float scale[3], rot[3];
- float mat[3][3], imat[3][3], tmat[3][3];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- /*must be 3-4 cols, 3-4 rows, square matrix*/
- if(self->colSize == 4 && self->rowSize == 4)
- Mat3CpyMat4(mat, (float (*)[4])*self->matrix);
- else if(self->colSize == 3 && self->rowSize == 3)
- Mat3CpyMat3(mat, (float (*)[3])*self->matrix);
- else {
- PyErr_SetString(PyExc_AttributeError, "Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
- return NULL;
- }
- /* functionality copied from editobject.c apply_obmat */
- Mat3ToEul(mat, rot);
- EulToMat3(rot, tmat);
- Mat3Inv(imat, tmat);
- Mat3MulMat3(tmat, imat, mat);
-
- scale[0]= tmat[0][0];
- scale[1]= tmat[1][1];
- scale[2]= tmat[2][2];
- return newVectorObject(scale, 3, Py_NEW, NULL);
-}
-/*---------------------------Matrix.invert() ---------------------*/
-PyObject *Matrix_Invert(MatrixObject * self)
-{
-
- int x, y, z = 0;
- float det = 0.0f;
- PyObject *f = NULL;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->rowSize != self->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported");
- return NULL;
- }
-
- /*calculate the determinant*/
- f = Matrix_Determinant(self);
- det = (float)PyFloat_AS_DOUBLE(f); /*Increfs, so we need to decref*/
- Py_DECREF(f);
-
- if(det != 0) {
- /*calculate the classical adjoint*/
- if(self->rowSize == 2) {
- mat[0] = self->matrix[1][1];
- mat[1] = -self->matrix[0][1];
- mat[2] = -self->matrix[1][0];
- mat[3] = self->matrix[0][0];
- } else if(self->rowSize == 3) {
- Mat3Adj((float (*)[3]) mat,(float (*)[3]) *self->matrix);
- } else if(self->rowSize == 4) {
- Mat4Adj((float (*)[4]) mat, (float (*)[4]) *self->matrix);
- }
- /*divide by determinate*/
- for(x = 0; x < (self->rowSize * self->colSize); x++) {
- mat[x] /= det;
- }
- /*set values*/
- for(x = 0; x < self->rowSize; x++) {
- for(y = 0; y < self->colSize; y++) {
- self->matrix[x][y] = mat[z];
- z++;
- }
- }
- /*transpose
- Matrix_Transpose(self);*/
- } else {
- PyErr_SetString(PyExc_ValueError, "matrix does not have an inverse");
- return NULL;
- }
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-
-/*---------------------------Matrix.determinant() ----------------*/
-PyObject *Matrix_Determinant(MatrixObject * self)
-{
- float det = 0.0f;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->rowSize != self->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported");
- return NULL;
- }
-
- if(self->rowSize == 2) {
- det = Det2x2(self->matrix[0][0], self->matrix[0][1],
- self->matrix[1][0], self->matrix[1][1]);
- } else if(self->rowSize == 3) {
- det = Det3x3(self->matrix[0][0], self->matrix[0][1],
- self->matrix[0][2], self->matrix[1][0],
- self->matrix[1][1], self->matrix[1][2],
- self->matrix[2][0], self->matrix[2][1],
- self->matrix[2][2]);
- } else {
- det = Det4x4((float (*)[4]) *self->matrix);
- }
-
- return PyFloat_FromDouble( (double) det );
-}
-/*---------------------------Matrix.transpose() ------------------*/
-PyObject *Matrix_Transpose(MatrixObject * self)
-{
- float t = 0.0f;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->rowSize != self->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported");
- return NULL;
- }
-
- if(self->rowSize == 2) {
- t = self->matrix[1][0];
- self->matrix[1][0] = self->matrix[0][1];
- self->matrix[0][1] = t;
- } else if(self->rowSize == 3) {
- Mat3Transp((float (*)[3])*self->matrix);
- } else {
- Mat4Transp((float (*)[4])*self->matrix);
- }
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-
-/*---------------------------Matrix.zero() -----------------------*/
-PyObject *Matrix_Zero(MatrixObject * self)
-{
- int row, col;
-
- for(row = 0; row < self->rowSize; row++) {
- for(col = 0; col < self->colSize; col++) {
- self->matrix[row][col] = 0.0f;
- }
- }
-
- if(!BaseMath_WriteCallback(self))
- return NULL;
-
- Py_INCREF(self);
- return (PyObject *)self;
-}
-/*---------------------------Matrix.identity(() ------------------*/
-PyObject *Matrix_Identity(MatrixObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(self->rowSize != self->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n");
- return NULL;
- }
-
- if(self->rowSize == 2) {
- self->matrix[0][0] = 1.0f;
- self->matrix[0][1] = 0.0f;
- self->matrix[1][0] = 0.0f;
- self->matrix[1][1] = 1.0f;
- } else if(self->rowSize == 3) {
- Mat3One((float (*)[3]) *self->matrix);
- } else {
- Mat4One((float (*)[4]) *self->matrix);
- }
-
- if(!BaseMath_WriteCallback(self))
- return NULL;
-
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-/*---------------------------Matrix.inverted() ------------------*/
-PyObject *Matrix_copy(MatrixObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self));
-}
-
-/*----------------------------print object (internal)-------------*/
-/*print the object to screen*/
-static PyObject *Matrix_repr(MatrixObject * self)
-{
- int x, y;
- char buffer[48], str[1024];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- BLI_strncpy(str,"",1024);
- for(x = 0; x < self->rowSize; x++){
- sprintf(buffer, "[");
- strcat(str,buffer);
- for(y = 0; y < (self->colSize - 1); y++) {
- sprintf(buffer, "%.6f, ", self->matrix[x][y]);
- strcat(str,buffer);
- }
- if(x < (self->rowSize-1)){
- sprintf(buffer, "%.6f](matrix [row %d])\n", self->matrix[x][y], x);
- strcat(str,buffer);
- }else{
- sprintf(buffer, "%.6f](matrix [row %d])", self->matrix[x][y], x);
- strcat(str,buffer);
- }
- }
-
- return PyUnicode_FromString(str);
-}
-/*------------------------tp_richcmpr*/
-/*returns -1 execption, 0 false, 1 true*/
-static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
-{
- MatrixObject *matA = NULL, *matB = NULL;
- int result = 0;
-
- if (!MatrixObject_Check(objectA) || !MatrixObject_Check(objectB)){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
- matA = (MatrixObject*)objectA;
- matB = (MatrixObject*)objectB;
-
- if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB))
- return NULL;
-
- if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
-
- switch (comparison_type){
- case Py_EQ:
- /*contigPtr is basically a really long vector*/
- result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
- (matA->rowSize * matA->colSize), 1);
- break;
- case Py_NE:
- result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
- (matA->rowSize * matA->colSize), 1);
- if (result == 0){
- result = 1;
- }else{
- result = 0;
- }
- break;
- default:
- printf("The result of the comparison could not be evaluated");
- break;
- }
- if (result == 1){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
-}
-
-/*---------------------SEQUENCE PROTOCOLS------------------------
- ----------------------------len(object)------------------------
- sequence length*/
-static int Matrix_len(MatrixObject * self)
-{
- return (self->rowSize);
-}
-/*----------------------------object[]---------------------------
- sequence accessor (get)
- the wrapped vector gives direct access to the matrix data*/
-static PyObject *Matrix_item(MatrixObject * self, int i)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(i < 0 || i >= self->rowSize) {
- PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range");
- return NULL;
- }
- return newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, i);
-}
-/*----------------------------object[]-------------------------
- sequence accessor (set)*/
-static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
-{
- int y, x, size = 0;
- float vec[4];
- PyObject *m, *f;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- if(i >= self->rowSize || i < 0){
- PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n");
- return -1;
- }
-
- if(PySequence_Check(ob)){
- size = PySequence_Length(ob);
- if(size != self->colSize){
- PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad sequence size\n");
- return -1;
- }
- for (x = 0; x < size; x++) {
- m = PySequence_GetItem(ob, x);
- if (m == NULL) { /*Failed to read sequence*/
- PyErr_SetString(PyExc_RuntimeError, "matrix[attribute] = x: unable to read sequence\n");
- return -1;
- }
-
- f = PyNumber_Float(m);
- if(f == NULL) { /*parsed item not a number*/
- Py_DECREF(m);
- PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: sequence argument not a number\n");
- return -1;
- }
-
- vec[x] = (float)PyFloat_AS_DOUBLE(f);
- Py_DECREF(m);
- Py_DECREF(f);
- }
- /*parsed well - now set in matrix*/
- for(y = 0; y < size; y++){
- self->matrix[i][y] = vec[y];
- }
-
- BaseMath_WriteCallback(self);
- return 0;
- }else{
- PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n");
- return -1;
- }
-}
-/*----------------------------object[z:y]------------------------
- sequence slice (get)*/
-static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
-{
-
- PyObject *list = NULL;
- int count;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- CLAMP(begin, 0, self->rowSize);
- CLAMP(end, 0, self->rowSize);
- begin = MIN2(begin,end);
-
- list = PyList_New(end - begin);
- for(count = begin; count < end; count++) {
- PyList_SetItem(list, count - begin,
- newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, count));
-
- }
-
- return list;
-}
-/*----------------------------object[z:y]------------------------
- sequence slice (set)*/
-static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * seq)
-{
- int i, x, y, size, sub_size = 0;
- float mat[16], f;
- PyObject *subseq;
- PyObject *m;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- CLAMP(begin, 0, self->rowSize);
- CLAMP(end, 0, self->rowSize);
- begin = MIN2(begin,end);
-
- if(PySequence_Check(seq)){
- size = PySequence_Length(seq);
- if(size != (end - begin)){
- PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
- return -1;
- }
- /*parse sub items*/
- for (i = 0; i < size; i++) {
- /*parse each sub sequence*/
- subseq = PySequence_GetItem(seq, i);
- if (subseq == NULL) { /*Failed to read sequence*/
- PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence");
- return -1;
- }
-
- if(PySequence_Check(subseq)){
- /*subsequence is also a sequence*/
- sub_size = PySequence_Length(subseq);
- if(sub_size != self->colSize){
- Py_DECREF(subseq);
- PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment\n");
- return -1;
- }
- for (y = 0; y < sub_size; y++) {
- m = PySequence_GetItem(subseq, y);
- if (m == NULL) { /*Failed to read sequence*/
- Py_DECREF(subseq);
- PyErr_SetString(PyExc_RuntimeError, "matrix[begin:end] = []: unable to read sequence\n");
- return -1;
- }
-
- f = PyFloat_AsDouble(m); /* faster to assume a float and raise an error after */
- if(f == -1 && PyErr_Occurred()) { /*parsed item not a number*/
- Py_DECREF(m);
- Py_DECREF(subseq);
- PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: sequence argument not a number\n");
- return -1;
- }
-
- mat[(i * self->colSize) + y] = f;
- Py_DECREF(m);
- }
- }else{
- Py_DECREF(subseq);
- PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
- return -1;
- }
- Py_DECREF(subseq);
- }
- /*parsed well - now set in matrix*/
- for(x = 0; x < (size * sub_size); x++){
- self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
- }
-
- BaseMath_WriteCallback(self);
- return 0;
- }else{
- PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n");
- return -1;
- }
-}
-/*------------------------NUMERIC PROTOCOLS----------------------
- ------------------------obj + obj------------------------------*/
-static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
-{
- int x, y;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- MatrixObject *mat1 = NULL, *mat2 = NULL;
-
- mat1 = (MatrixObject*)m1;
- mat2 = (MatrixObject*)m2;
-
- if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
- PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
- return NULL;
-
- if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
- return NULL;
- }
-
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] + mat2->matrix[x][y];
- }
- }
-
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
-}
-/*------------------------obj - obj------------------------------
- subtraction*/
-static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
-{
- int x, y;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- MatrixObject *mat1 = NULL, *mat2 = NULL;
-
- mat1 = (MatrixObject*)m1;
- mat2 = (MatrixObject*)m2;
-
- if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
- PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation....");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
- return NULL;
-
- if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
- PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation");
- return NULL;
- }
-
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] - mat2->matrix[x][y];
- }
- }
-
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
-}
-/*------------------------obj * obj------------------------------
- mulplication*/
-static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
-{
- int x, y, z;
- float scalar;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- double dot = 0.0f;
- MatrixObject *mat1 = NULL, *mat2 = NULL;
-
- if(MatrixObject_Check(m1)) {
- mat1 = (MatrixObject*)m1;
- if(!BaseMath_ReadCallback(mat1))
- return NULL;
- }
- if(MatrixObject_Check(m2)) {
- mat2 = (MatrixObject*)m2;
- if(!BaseMath_ReadCallback(mat2))
- return NULL;
- }
-
- if(mat1 && mat2) { /*MATRIX * MATRIX*/
- if(mat1->colSize != mat2->rowSize){
- PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize");
- return NULL;
- }
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat2->colSize; y++) {
- for(z = 0; z < mat1->colSize; z++) {
- dot += (mat1->matrix[x][z] * mat2->matrix[z][y]);
- }
- mat[((x * mat1->rowSize) + y)] = (float)dot;
- dot = 0.0f;
- }
- }
-
- return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL);
- }
-
- if(mat1==NULL){
- scalar=PyFloat_AsDouble(m1); // may not be a float...
- if ((scalar == -1.0 && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX, this line annoys theeth, lets see if he finds it */
- for(x = 0; x < mat2->rowSize; x++) {
- for(y = 0; y < mat2->colSize; y++) {
- mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y];
- }
- }
- return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW, NULL);
- }
-
- PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
- return NULL;
- }
- else /* if(mat1) { */ {
-
- if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */
- return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */
- }
- else {
- scalar= PyFloat_AsDouble(m2);
- if ((scalar == -1.0 && PyErr_Occurred())==0) { /* MATRIX*FLOAT/INT */
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y];
- }
- }
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL);
- }
- }
- PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation");
- return NULL;
- }
-
- PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation\n");
- return NULL;
-}
-static PyObject* Matrix_inv(MatrixObject *self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- return Matrix_Invert(self);
-}
-
-/*-----------------PROTOCOL DECLARATIONS--------------------------*/
-static PySequenceMethods Matrix_SeqMethods = {
- (inquiry) Matrix_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (ssizeargfunc) 0, /* sq_repeat */
- (ssizeargfunc) Matrix_item, /* sq_item */
- (ssizessizeargfunc) Matrix_slice, /* sq_slice */
- (ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc) Matrix_ass_slice, /* sq_ass_slice */
-};
-
-
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i;
- i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += self->rowSize;
- return Matrix_item(self, i);
- } else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
- return NULL;
-
- if (slicelength <= 0) {
- return PyList_New(0);
- }
- else if (step == 1) {
- return Matrix_slice(self, start, stop);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
- return NULL;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "vector indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return NULL;
- }
-}
-
-static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0)
- i += self->rowSize;
- return Matrix_ass_item(self, i, value);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
- return -1;
-
- if (step == 1)
- return Matrix_ass_slice(self, start, stop, value);
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
- return -1;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "matrix indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return -1;
- }
-}
-
-static PyMappingMethods Matrix_AsMapping = {
- (lenfunc)Matrix_len,
- (binaryfunc)Matrix_subscript,
- (objobjargproc)Matrix_ass_subscript
-};
-#endif /* (PY_VERSION_HEX >= 0x03000000) */
-
-
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Matrix_NumMethods = {
- (binaryfunc) Matrix_add, /*nb_add*/
- (binaryfunc) Matrix_sub, /*nb_subtract*/
- (binaryfunc) Matrix_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) 0, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) Matrix_inv, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
-static PyNumberMethods Matrix_NumMethods = {
- (binaryfunc) Matrix_add, /* __add__ */
- (binaryfunc) Matrix_sub, /* __sub__ */
- (binaryfunc) Matrix_mul, /* __mul__ */
- (binaryfunc) 0, /* __div__ */
- (binaryfunc) 0, /* __mod__ */
- (binaryfunc) 0, /* __divmod__ */
- (ternaryfunc) 0, /* __pow__ */
- (unaryfunc) 0, /* __neg__ */
- (unaryfunc) 0, /* __pos__ */
- (unaryfunc) 0, /* __abs__ */
- (inquiry) 0, /* __nonzero__ */
- (unaryfunc) Matrix_inv, /* __invert__ */
- (binaryfunc) 0, /* __lshift__ */
- (binaryfunc) 0, /* __rshift__ */
- (binaryfunc) 0, /* __and__ */
- (binaryfunc) 0, /* __xor__ */
- (binaryfunc) 0, /* __or__ */
- /*(coercion)*/ 0, /* __coerce__ */
- (unaryfunc) 0, /* __int__ */
- (unaryfunc) 0, /* __long__ */
- (unaryfunc) 0, /* __float__ */
- (unaryfunc) 0, /* __oct__ */
- (unaryfunc) 0, /* __hex__ */
-};
-#endif
-
-static PyObject *Matrix_getRowSize( MatrixObject * self, void *type )
-{
- return PyLong_FromLong((long) self->rowSize);
-}
-
-static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
-{
- return PyLong_FromLong((long) self->colSize);
-}
-
-/*****************************************************************************/
-/* Python attributes get/set structure: */
-/*****************************************************************************/
-static PyGetSetDef Matrix_getseters[] = {
- {"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
- {"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
- {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
- {"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "",
- NULL},
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
-};
-
-/*------------------PY_OBECT DEFINITION--------------------------*/
-PyTypeObject matrix_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- "matrix", /*tp_name*/
- sizeof(MatrixObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)BaseMathObject_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- (reprfunc) Matrix_repr, /*tp_repr*/
- &Matrix_NumMethods, /*tp_as_number*/
- &Matrix_SeqMethods, /*tp_as_sequence*/
-#if (PY_VERSION_HEX >= 0x03000000)
- &Matrix_AsMapping, /*tp_as_mapping*/
-#else
- 0,
-#endif
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- Matrix_methods, /*tp_methods*/
- 0, /*tp_members*/
- Matrix_getseters, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- 0, /*tp_init*/
- 0, /*tp_alloc*/
- Matrix_new, /*tp_new*/
- 0, /*tp_free*/
- 0, /*tp_is_gc*/
- 0, /*tp_bases*/
- 0, /*tp_mro*/
- 0, /*tp_cache*/
- 0, /*tp_subclasses*/
- 0, /*tp_weaklist*/
- 0 /*tp_del*/
-};
-
-/*------------------------newMatrixObject (internal)-------------
-creates a new matrix object
-self->matrix self->contiguous_ptr (reference to data.xxx)
- [0]------------->[0]
- [1]
- [2]
- [1]------------->[3]
- [4]
- [5]
- ....
-self->matrix[1][1] = self->contigPtr[4] */
-
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
- pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type)
-{
- MatrixObject *self;
- int x, row, col;
-
- /*matrix objects can be any 2-4row x 2-4col matrix*/
- if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4){
- PyErr_SetString(PyExc_RuntimeError, "matrix(): row and column sizes must be between 2 and 4");
- return NULL;
- }
-
- if(base_type) self = (MatrixObject *)base_type->tp_alloc(base_type, 0);
- else self = PyObject_NEW(MatrixObject, &matrix_Type);
-
- self->rowSize = rowSize;
- self->colSize = colSize;
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
-
- if(type == Py_WRAP){
- self->contigPtr = mat;
- /*create pointer array*/
- self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
- if(self->matrix == NULL) { /*allocation failure*/
- PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
- return NULL;
- }
- /*pointer array points to contigous memory*/
- for(x = 0; x < rowSize; x++) {
- self->matrix[x] = self->contigPtr + (x * colSize);
- }
- self->wrapped = Py_WRAP;
- }else if (type == Py_NEW){
- self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float));
- if(self->contigPtr == NULL) { /*allocation failure*/
- PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n");
- return NULL;
- }
- /*create pointer array*/
- self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
- if(self->matrix == NULL) { /*allocation failure*/
- PyMem_Free(self->contigPtr);
- PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space");
- return NULL;
- }
- /*pointer array points to contigous memory*/
- for(x = 0; x < rowSize; x++) {
- self->matrix[x] = self->contigPtr + (x * colSize);
- }
- /*parse*/
- if(mat) { /*if a float array passed*/
- for(row = 0; row < rowSize; row++) {
- for(col = 0; col < colSize; col++) {
- self->matrix[row][col] = mat[(row * colSize) + col];
- }
- }
- } else if (rowSize == colSize ) { /*or if no arguments are passed return identity matrix for square matrices */
- Matrix_Identity(self);
- Py_DECREF(self);
- }
- self->wrapped = Py_NEW;
- }else{ /*bad type*/
- return NULL;
- }
- return (PyObject *) self;
-}
-
-PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
-{
- MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW, NULL);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
- return (PyObject *) self;
-}
-
-//----------------column_vector_multiplication (internal)---------
-//COLUMN VECTOR Multiplication (Matrix X Vector)
-// [1][2][3] [a]
-// [4][5][6] * [b]
-// [7][8][9] [c]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
-{
- float vecNew[4], vecCopy[4];
- double dot = 0.0f;
- int x, y, z = 0;
-
- if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec))
- return NULL;
-
- if(mat->rowSize != vec->size){
- if(mat->rowSize == 4 && vec->size != 3){
- PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
- return NULL;
- }else{
- vecCopy[3] = 1.0f;
- }
- }
-
- for(x = 0; x < vec->size; x++){
- vecCopy[x] = vec->vec[x];
- }
-
- for(x = 0; x < mat->rowSize; x++) {
- for(y = 0; y < mat->colSize; y++) {
- dot += mat->matrix[x][y] * vecCopy[y];
- }
- vecNew[z++] = (float)dot;
- dot = 0.0f;
- }
- return newVectorObject(vecNew, vec->size, Py_NEW, NULL);
-}
diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h
deleted file mode 100644
index 856c711c4ef..00000000000
--- a/source/blender/python/generic/matrix.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-#ifndef EXPP_matrix_h
-#define EXPP_matrix_h
-
-#include <Python.h>
-
-extern PyTypeObject matrix_Type;
-#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type)
-
-typedef float **ptRow;
-typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */
- PyObject_VAR_HEAD
- float *contigPtr; /*1D array of data (alias)*/
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /*is wrapped data?*/
- /* end BaseMathObject */
-
- unsigned char rowSize;
- unsigned int colSize;
- ptRow matrix; /*ptr to the contigPtr (accessor)*/
-
-} MatrixObject;
-
-/*struct data contains a pointer to the actual data that the
-object uses. It can use either PyMem allocated data (which will
-be stored in py_data) or be a wrapper for data allocated through
-blender (stored in blend_data). This is an either/or struct not both*/
-
-/*prototypes*/
-PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type);
-PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype);
-
-extern int mathutils_matrix_vector_cb_index;
-extern struct Mathutils_Callback mathutils_matrix_vector_cb;
-
-#endif /* EXPP_matrix_H */
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
deleted file mode 100644
index a353f73c854..00000000000
--- a/source/blender/python/generic/quat.c
+++ /dev/null
@@ -1,879 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Mathutils.h"
-
-#include "BLI_arithb.h"
-#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
-
-
-//-------------------------DOC STRINGS ---------------------------
-
-static PyObject *Quaternion_Identity( QuaternionObject * self );
-static PyObject *Quaternion_Negate( QuaternionObject * self );
-static PyObject *Quaternion_Conjugate( QuaternionObject * self );
-static PyObject *Quaternion_Inverse( QuaternionObject * self );
-static PyObject *Quaternion_Normalize( QuaternionObject * self );
-static PyObject *Quaternion_ToEuler( QuaternionObject * self, PyObject *args );
-static PyObject *Quaternion_ToMatrix( QuaternionObject * self );
-static PyObject *Quaternion_Cross( QuaternionObject * self, QuaternionObject * value );
-static PyObject *Quaternion_Dot( QuaternionObject * self, QuaternionObject * value );
-static PyObject *Quaternion_copy( QuaternionObject * self );
-
-//-----------------------METHOD DEFINITIONS ----------------------
-static struct PyMethodDef Quaternion_methods[] = {
- {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL},
- {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL},
- {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL},
- {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL},
- {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL},
- {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL},
- {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL},
- {"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL},
- {"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL},
- {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
- {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-//----------------------------------Mathutils.Quaternion() --------------
-static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *listObject = NULL, *n, *q;
- int size, i;
- float quat[4];
- double angle = 0.0f;
-
- size = PyTuple_GET_SIZE(args);
- if (size == 1 || size == 2) { //seq?
- listObject = PyTuple_GET_ITEM(args, 0);
- if (PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- if ((size == 4 && PySequence_Length(args) !=1) ||
- (size == 3 && PySequence_Length(args) !=2) || (size >4 || size < 3)) {
- // invalid args/size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- if(size == 3){ //get angle in axis/angle
- n = PySequence_GetItem(args, 1);
- if(n == NULL) { // parsed item not a number or getItem fail
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
-
- angle = PyFloat_AsDouble(n);
- Py_DECREF(n);
-
- if (angle==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
- }else{
- listObject = PyTuple_GET_ITEM(args, 1);
- if (size>1 && PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- if (size != 3) {
- // invalid args/size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- angle = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0));
-
- if (angle==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- } else { // argument was not a sequence
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
- } else if (size == 0) { //returns a new empty quat
- return newQuaternionObject(NULL, Py_NEW, NULL);
- } else {
- listObject = args;
- }
-
- if (size == 3) { // invalid quat size
- if(PySequence_Length(args) != 2){
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }else{
- if(size != 4){
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
-
- for (i=0; i<size; i++) { //parse
- q = PySequence_GetItem(listObject, i);
- if (q == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
-
- quat[i] = PyFloat_AsDouble(q);
- Py_DECREF(q);
-
- if (quat[i]==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
- return NULL;
- }
- }
-
- if(size == 3) //calculate the quat based on axis/angle
-#ifdef USE_MATHUTILS_DEG
- AxisAngleToQuat(quat, quat, angle * (Py_PI / 180));
-#else
- AxisAngleToQuat(quat, quat, angle);
-#endif
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-
-//-----------------------------METHODS------------------------------
-//----------------------------Quaternion.toEuler()------------------
-//return the quat as a euler
-static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
-{
- float eul[3];
- EulerObject *eul_compat = NULL;
-
- if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
- return NULL;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if(eul_compat) {
- float mat[3][3];
-
- if(!BaseMath_ReadCallback(eul_compat))
- return NULL;
-
- QuatToMat3(self->quat, mat);
-
-#ifdef USE_MATHUTILS_DEG
- {
- float eul_compatf[3];
- int x;
-
- for(x = 0; x < 3; x++) {
- eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
- }
- Mat3ToCompatibleEul(mat, eul, eul_compatf);
- }
-#else
- Mat3ToCompatibleEul(mat, eul, eul_compat->eul);
-#endif
- }
- else {
- QuatToEul(self->quat, eul);
- }
-
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
-
- for(x = 0; x < 3; x++) {
- eul[x] *= (180 / (float)Py_PI);
- }
- }
-#endif
- return newEulerObject(eul, Py_NEW, NULL);
-}
-//----------------------------Quaternion.toMatrix()------------------
-//return the quat as a matrix
-static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
-{
- float mat[9]; /* all values are set */
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatToMat3(self->quat, (float (*)[3]) mat);
- return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
-}
-
-//----------------------------Quaternion.cross(other)------------------
-//return the cross quat
-static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
-{
- float quat[4];
-
- if (!QuaternionObject_Check(value)) {
- PyErr_SetString( PyExc_TypeError, "quat.cross(value): expected a quaternion argument" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- QuatMul(quat, self->quat, value->quat);
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-
-//----------------------------Quaternion.dot(other)------------------
-//return the dot quat
-static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
-{
- if (!QuaternionObject_Check(value)) {
- PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- return PyFloat_FromDouble(QuatDot(self->quat, value->quat));
-}
-
-//----------------------------Quaternion.normalize()----------------
-//normalize the axis of rotation of [theta,vector]
-static PyObject *Quaternion_Normalize(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- NormalQuat(self->quat);
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-//----------------------------Quaternion.inverse()------------------
-//invert the quat
-static PyObject *Quaternion_Inverse(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatInv(self->quat);
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-//----------------------------Quaternion.identity()-----------------
-//generate the identity quaternion
-static PyObject *Quaternion_Identity(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatOne(self->quat);
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-//----------------------------Quaternion.negate()-------------------
-//negate the quat
-static PyObject *Quaternion_Negate(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatMulf(self->quat, -1.0f);
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-//----------------------------Quaternion.conjugate()----------------
-//negate the vector part
-static PyObject *Quaternion_Conjugate(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- QuatConj(self->quat);
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-//----------------------------Quaternion.copy()----------------
-//return a copy of the quat
-static PyObject *Quaternion_copy(QuaternionObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
-}
-
-//----------------------------print object (internal)--------------
-//print the object to screen
-static PyObject *Quaternion_repr(QuaternionObject * self)
-{
- char str[64];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
- return PyUnicode_FromString(str);
-}
-//------------------------tp_richcmpr
-//returns -1 execption, 0 false, 1 true
-static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
-{
- QuaternionObject *quatA = NULL, *quatB = NULL;
- int result = 0;
-
- if(QuaternionObject_Check(objectA)) {
- quatA = (QuaternionObject*)objectA;
- if(!BaseMath_ReadCallback(quatA))
- return NULL;
- }
- if(QuaternionObject_Check(objectB)) {
- quatB = (QuaternionObject*)objectB;
- if(!BaseMath_ReadCallback(quatB))
- return NULL;
- }
-
- if (!quatA || !quatB){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
-
- switch (comparison_type){
- case Py_EQ:
- result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
- break;
- case Py_NE:
- result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
- if (result == 0){
- result = 1;
- }else{
- result = 0;
- }
- break;
- default:
- printf("The result of the comparison could not be evaluated");
- break;
- }
- if (result == 1){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
-}
-
-//---------------------SEQUENCE PROTOCOLS------------------------
-//----------------------------len(object)------------------------
-//sequence length
-static int Quaternion_len(QuaternionObject * self)
-{
- return 4;
-}
-//----------------------------object[]---------------------------
-//sequence accessor (get)
-static PyObject *Quaternion_item(QuaternionObject * self, int i)
-{
- if(i<0) i= 4-i;
-
- if(i < 0 || i >= 4) {
- PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
- return NULL;
- }
-
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
- return PyFloat_FromDouble(self->quat[i]);
-
-}
-//----------------------------object[]-------------------------
-//sequence accessor (set)
-static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
-{
- float scalar= (float)PyFloat_AsDouble(ob);
- if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
- return -1;
- }
-
- if(i<0) i= 4-i;
-
- if(i < 0 || i >= 4){
- PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
- return -1;
- }
- self->quat[i] = scalar;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
-
- return 0;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (get)
-static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
-{
- PyObject *list = NULL;
- int count;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- CLAMP(begin, 0, 4);
- if (end<0) end= 5+end;
- CLAMP(end, 0, 4);
- begin = MIN2(begin,end);
-
- list = PyList_New(end - begin);
- for(count = begin; count < end; count++) {
- PyList_SetItem(list, count - begin,
- PyFloat_FromDouble(self->quat[count]));
- }
-
- return list;
-}
-//----------------------------object[z:y]------------------------
-//sequence slice (set)
-static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
-{
- int i, y, size = 0;
- float quat[4];
- PyObject *q;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- CLAMP(begin, 0, 4);
- if (end<0) end= 5+end;
- CLAMP(end, 0, 4);
- begin = MIN2(begin,end);
-
- size = PySequence_Length(seq);
- if(size != (end - begin)){
- PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment\n");
- return -1;
- }
-
- for (i = 0; i < size; i++) {
- q = PySequence_GetItem(seq, i);
- if (q == NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "quaternion[begin:end] = []: unable to read sequence\n");
- return -1;
- }
-
- quat[i]= (float)PyFloat_AsDouble(q);
- Py_DECREF(q);
-
- if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
- return -1;
- }
- }
- //parsed well - now set in vector
- for(y = 0; y < size; y++)
- self->quat[begin + y] = quat[y];
-
- BaseMath_WriteCallback(self);
- return 0;
-}
-//------------------------NUMERIC PROTOCOLS----------------------
-//------------------------obj + obj------------------------------
-//addition
-static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
-{
- float quat[4];
- QuaternionObject *quat1 = NULL, *quat2 = NULL;
-
- if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
- PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
- return NULL;
- }
- quat1 = (QuaternionObject*)q1;
- quat2 = (QuaternionObject*)q2;
-
- if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
- return NULL;
-
- QuatAdd(quat, quat1->quat, quat2->quat, 1.0f);
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//------------------------obj - obj------------------------------
-//subtraction
-static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
-{
- int x;
- float quat[4];
- QuaternionObject *quat1 = NULL, *quat2 = NULL;
-
- if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
- PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
- return NULL;
- }
-
- quat1 = (QuaternionObject*)q1;
- quat2 = (QuaternionObject*)q2;
-
- if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
- return NULL;
-
- for(x = 0; x < 4; x++) {
- quat[x] = quat1->quat[x] - quat2->quat[x];
- }
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-//------------------------obj * obj------------------------------
-//mulplication
-static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
-{
- float quat[4], scalar;
- QuaternionObject *quat1 = NULL, *quat2 = NULL;
- VectorObject *vec = NULL;
-
- if(QuaternionObject_Check(q1)) {
- quat1 = (QuaternionObject*)q1;
- if(!BaseMath_ReadCallback(quat1))
- return NULL;
- }
- if(QuaternionObject_Check(q2)) {
- quat2 = (QuaternionObject*)q2;
- if(!BaseMath_ReadCallback(quat2))
- return NULL;
- }
-
- if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
- return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat));
- }
-
- /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
- if(!QuaternionObject_Check(q1)) {
- scalar= PyFloat_AsDouble(q1);
- if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
- QUATCOPY(quat, quat2->quat);
- QuatMulf(quat, scalar);
- return newQuaternionObject(quat, Py_NEW, NULL);
- }
- PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
- return NULL;
- }
- else { /* QUAT*SOMETHING */
- if(VectorObject_Check(q2)){ /* QUAT*VEC */
- vec = (VectorObject*)q2;
- if(vec->size != 3){
- PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
- return NULL;
- }
- return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
- }
-
- scalar= PyFloat_AsDouble(q2);
- if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
- QUATCOPY(quat, quat1->quat);
- QuatMulf(quat, scalar);
- return newQuaternionObject(quat, Py_NEW, NULL);
- }
- }
-
- PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
- return NULL;
-}
-
-//-----------------PROTOCOL DECLARATIONS--------------------------
-static PySequenceMethods Quaternion_SeqMethods = {
- (inquiry) Quaternion_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (ssizeargfunc) 0, /* sq_repeat */
- (ssizeargfunc) Quaternion_item, /* sq_item */
- (ssizessizeargfunc) Quaternion_slice, /* sq_slice */
- (ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */
-};
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Quaternion_NumMethods = {
- (binaryfunc) Quaternion_add, /*nb_add*/
- (binaryfunc) Quaternion_sub, /*nb_subtract*/
- (binaryfunc) Quaternion_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) 0, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) 0, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
-static PyNumberMethods Quaternion_NumMethods = {
- (binaryfunc) Quaternion_add, /* __add__ */
- (binaryfunc) Quaternion_sub, /* __sub__ */
- (binaryfunc) Quaternion_mul, /* __mul__ */
- (binaryfunc) 0, /* __div__ */
- (binaryfunc) 0, /* __mod__ */
- (binaryfunc) 0, /* __divmod__ */
- (ternaryfunc) 0, /* __pow__ */
- (unaryfunc) 0, /* __neg__ */
- (unaryfunc) 0, /* __pos__ */
- (unaryfunc) 0, /* __abs__ */
- (inquiry) 0, /* __nonzero__ */
- (unaryfunc) 0, /* __invert__ */
- (binaryfunc) 0, /* __lshift__ */
- (binaryfunc) 0, /* __rshift__ */
- (binaryfunc) 0, /* __and__ */
- (binaryfunc) 0, /* __xor__ */
- (binaryfunc) 0, /* __or__ */
- /*(coercion)*/ 0, /* __coerce__ */
- (unaryfunc) 0, /* __int__ */
- (unaryfunc) 0, /* __long__ */
- (unaryfunc) 0, /* __float__ */
- (unaryfunc) 0, /* __oct__ */
- (unaryfunc) 0, /* __hex__ */
-};
-#endif
-
-static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
-{
- return Quaternion_item(self, GET_INT_FROM_POINTER(type));
-}
-
-static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
-{
- return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
-}
-
-static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
-{
- return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat)));
-}
-
-static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
-{
- double ang = self->quat[0];
- ang = 2 * (saacos(ang));
-#ifdef USE_MATHUTILS_DEG
- ang *= (180 / Py_PI);
-#endif
- return PyFloat_FromDouble(ang);
-}
-
-static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
-{
- int i;
- float vec[3];
- double mag = self->quat[0] * (Py_PI / 180);
- mag = 2 * (saacos(mag));
- mag = sin(mag / 2);
- for(i = 0; i < 3; i++)
- vec[i] = (float)(self->quat[i + 1] / mag);
-
- Normalize(vec);
- //If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
- if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
- EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
- EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
- vec[0] = 1.0f;
- }
- return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
-}
-
-
-/*****************************************************************************/
-/* Python attributes get/set structure: */
-/*****************************************************************************/
-static PyGetSetDef Quaternion_getseters[] = {
- {"w",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion W value",
- (void *)0},
- {"x",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion X axis",
- (void *)1},
- {"y",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion Y axis",
- (void *)2},
- {"z",
- (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
- "Quaternion Z axis",
- (void *)3},
- {"magnitude",
- (getter)Quaternion_getMagnitude, (setter)NULL,
- "Size of the quaternion",
- NULL},
- {"angle",
- (getter)Quaternion_getAngle, (setter)NULL,
- "angle of the quaternion",
- NULL},
- {"axis",
- (getter)Quaternion_getAxisVec, (setter)NULL,
- "quaternion axis as a vector",
- NULL},
- {"wrapped",
- (getter)BaseMathObject_getWrapped, (setter)NULL,
- "True when this wraps blenders internal data",
- NULL},
- {"__owner__",
- (getter)BaseMathObject_getOwner, (setter)NULL,
- "Read only owner for vectors that depend on another object",
- NULL},
-
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
-};
-
-
-//------------------PY_OBECT DEFINITION--------------------------
-PyTypeObject quaternion_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- "quaternion", //tp_name
- sizeof(QuaternionObject), //tp_basicsize
- 0, //tp_itemsize
- (destructor)BaseMathObject_dealloc, //tp_dealloc
- 0, //tp_print
- 0, //tp_getattr
- 0, //tp_setattr
- 0, //tp_compare
- (reprfunc) Quaternion_repr, //tp_repr
- &Quaternion_NumMethods, //tp_as_number
- &Quaternion_SeqMethods, //tp_as_sequence
- 0, //tp_as_mapping
- 0, //tp_hash
- 0, //tp_call
- 0, //tp_str
- 0, //tp_getattro
- 0, //tp_setattro
- 0, //tp_as_buffer
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
- 0, //tp_doc
- 0, //tp_traverse
- 0, //tp_clear
- (richcmpfunc)Quaternion_richcmpr, //tp_richcompare
- 0, //tp_weaklistoffset
- 0, //tp_iter
- 0, //tp_iternext
- Quaternion_methods, //tp_methods
- 0, //tp_members
- Quaternion_getseters, //tp_getset
- 0, //tp_base
- 0, //tp_dict
- 0, //tp_descr_get
- 0, //tp_descr_set
- 0, //tp_dictoffset
- 0, //tp_init
- 0, //tp_alloc
- Quaternion_new, //tp_new
- 0, //tp_free
- 0, //tp_is_gc
- 0, //tp_bases
- 0, //tp_mro
- 0, //tp_cache
- 0, //tp_subclasses
- 0, //tp_weaklist
- 0 //tp_del
-};
-//------------------------newQuaternionObject (internal)-------------
-//creates a new quaternion object
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
- pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
-{
- QuaternionObject *self;
-
- if(base_type) self = (QuaternionObject *)base_type->tp_alloc(base_type, 0);
- else self = PyObject_NEW(QuaternionObject, &quaternion_Type);
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
-
- if(type == Py_WRAP){
- self->quat = quat;
- self->wrapped = Py_WRAP;
- }else if (type == Py_NEW){
- self->quat = PyMem_Malloc(4 * sizeof(float));
- if(!quat) { //new empty
- QuatOne(self->quat);
- }else{
- QUATCOPY(self->quat, quat);
- }
- self->wrapped = Py_NEW;
- }else{ //bad type
- return NULL;
- }
- return (PyObject *) self;
-}
-
-PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
-{
- QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h
deleted file mode 100644
index a7cfb7898b1..00000000000
--- a/source/blender/python/generic/quat.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-#ifndef EXPP_quat_h
-#define EXPP_quat_h
-
-#include <Python.h>
-#include "../intern/bpy_compat.h"
-
-extern PyTypeObject quaternion_Type;
-#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type)
-
-typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
- PyObject_VAR_HEAD
- float *quat; /* 1D array of data (alias) */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
-} QuaternionObject;
-
-/*struct data contains a pointer to the actual data that the
-object uses. It can use either PyMem allocated data (which will
-be stored in py_data) or be a wrapper for data allocated through
-blender (stored in blend_data). This is an either/or struct not both*/
-
-//prototypes
-PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type);
-PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
-
-#endif /* EXPP_quat_h */
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
deleted file mode 100644
index cf2396b30d4..00000000000
--- a/source/blender/python/generic/vector.c
+++ /dev/null
@@ -1,2078 +0,0 @@
-/*
- * $Id$
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- *
- * Contributor(s): Willian P. Germano, Joseph Gilbert, Ken Hughes, Alex Fraser, Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include "Mathutils.h"
-
-#include "BLI_blenlib.h"
-#include "BKE_utildefines.h"
-#include "BLI_arithb.h"
-
-#define MAX_DIMENSIONS 4
-/* Swizzle axes get packed into a single value that is used as a closure. Each
- axis uses SWIZZLE_BITS_PER_AXIS bits. The first bit (SWIZZLE_VALID_AXIS) is
- used as a sentinel: if it is unset, the axis is not valid. */
-#define SWIZZLE_BITS_PER_AXIS 3
-#define SWIZZLE_VALID_AXIS 0x4
-#define SWIZZLE_AXIS 0x3
-
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
-
-/*-----------------------METHOD DEFINITIONS ----------------------*/
-static PyObject *Vector_Zero( VectorObject * self );
-static PyObject *Vector_Normalize( VectorObject * self );
-static PyObject *Vector_Negate( VectorObject * self );
-static PyObject *Vector_Resize2D( VectorObject * self );
-static PyObject *Vector_Resize3D( VectorObject * self );
-static PyObject *Vector_Resize4D( VectorObject * self );
-static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
-static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value );
-static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
-static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
-static PyObject *Vector_copy( VectorObject * self );
-
-static struct PyMethodDef Vector_methods[] = {
- {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL},
- {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL},
- {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL},
- {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL},
- {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL},
- {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL},
- {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL},
- {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL},
- {"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL},
- {"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL},
- {"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
- {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-//----------------------------------Mathutils.Vector() ------------------
-// Supports 2D, 3D, and 4D vector objects both int and float values
-// accepted. Mixed float and int values accepted. Ints are parsed to float
-static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *listObject = NULL;
- int size, i;
- float vec[4], f;
- PyObject *v;
-
- size = PyTuple_GET_SIZE(args); /* we know its a tuple because its an arg */
- if (size == 1) {
- listObject = PyTuple_GET_ITEM(args, 0);
- if (PySequence_Check(listObject)) {
- size = PySequence_Length(listObject);
- } else { // Single argument was not a sequence
- PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
- return NULL;
- }
- } else if (size == 0) {
- //returns a new empty 3d vector
- return newVectorObject(NULL, 3, Py_NEW, type);
- } else {
- listObject = args;
- }
-
- if (size<2 || size>4) { // Invalid vector size
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
- return NULL;
- }
-
- for (i=0; i<size; i++) {
- v=PySequence_GetItem(listObject, i);
- if (v==NULL) { // Failed to read sequence
- PyErr_SetString(PyExc_RuntimeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
- return NULL;
- }
-
- f= PyFloat_AsDouble(v);
- if(f==-1 && PyErr_Occurred()) { // parsed item not a number
- Py_DECREF(v);
- PyErr_SetString(PyExc_TypeError, "Mathutils.Vector(): 2-4 floats or ints expected (optionally in a sequence)\n");
- return NULL;
- }
-
- vec[i]= f;
- Py_DECREF(v);
- }
- return newVectorObject(vec, size, Py_NEW, type);
-}
-
-/*-----------------------------METHODS---------------------------- */
-/*----------------------------Vector.zero() ----------------------
- set the vector data to 0,0,0 */
-static PyObject *Vector_Zero(VectorObject * self)
-{
- int i;
- for(i = 0; i < self->size; i++) {
- self->vec[i] = 0.0f;
- }
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-/*----------------------------Vector.normalize() -----------------
- normalize the vector data to a unit vector */
-static PyObject *Vector_Normalize(VectorObject * self)
-{
- int i;
- float norm = 0.0f;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++) {
- norm += self->vec[i] * self->vec[i];
- }
- norm = (float) sqrt(norm);
- for(i = 0; i < self->size; i++) {
- self->vec[i] /= norm;
- }
-
- BaseMath_WriteCallback(self);
- Py_INCREF(self);
- return (PyObject*)self;
-}
-
-
-/*----------------------------Vector.resize2D() ------------------
- resize the vector to x,y */
-static PyObject *Vector_Resize2D(VectorObject * self)
-{
- if(self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
- return NULL;
- }
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
- self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
- if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
- return NULL;
- }
-
- self->size = 2;
- Py_INCREF(self);
- return (PyObject*)self;
-}
-/*----------------------------Vector.resize3D() ------------------
- resize the vector to x,y,z */
-static PyObject *Vector_Resize3D(VectorObject * self)
-{
- if (self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
- return NULL;
- }
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
- self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
- if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
- return NULL;
- }
-
- if(self->size == 2)
- self->vec[2] = 0.0f;
-
- self->size = 3;
- Py_INCREF(self);
- return (PyObject*)self;
-}
-/*----------------------------Vector.resize4D() ------------------
- resize the vector to x,y,z,w */
-static PyObject *Vector_Resize4D(VectorObject * self)
-{
- if(self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
- return NULL;
- }
- if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
- return NULL;
- }
-
- self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
- if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
- return NULL;
- }
- if(self->size == 2){
- self->vec[2] = 0.0f;
- self->vec[3] = 1.0f;
- }else if(self->size == 3){
- self->vec[3] = 1.0f;
- }
- self->size = 4;
- Py_INCREF(self);
- return (PyObject*)self;
-}
-/*----------------------------Vector.toTrackQuat(track, up) ----------------------
- extract a quaternion from the vector and the track and up axis */
-static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
-{
- float vec[3], quat[4];
- char *strack, *sup;
- short track = 2, up = 1;
-
- if( !PyArg_ParseTuple ( args, "|ss", &strack, &sup ) ) {
- PyErr_SetString( PyExc_TypeError, "expected optional two strings\n" );
- return NULL;
- }
- if (self->size != 3) {
- PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- if (strack) {
- if (strlen(strack) == 2) {
- if (strack[0] == '-') {
- switch(strack[1]) {
- case 'X':
- case 'x':
- track = 3;
- break;
- case 'Y':
- case 'y':
- track = 4;
- break;
- case 'z':
- case 'Z':
- track = 5;
- break;
- default:
- PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
- return NULL;
- }
- }
- else {
- PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
- return NULL;
- }
- }
- else if (strlen(strack) == 1) {
- switch(strack[0]) {
- case '-':
- case 'X':
- case 'x':
- track = 0;
- break;
- case 'Y':
- case 'y':
- track = 1;
- break;
- case 'z':
- case 'Z':
- track = 2;
- break;
- default:
- PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
- return NULL;
- }
- }
- else {
- PyErr_SetString( PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis\n" );
- return NULL;
- }
- }
-
- if (sup) {
- if (strlen(sup) == 1) {
- switch(*sup) {
- case 'X':
- case 'x':
- up = 0;
- break;
- case 'Y':
- case 'y':
- up = 1;
- break;
- case 'z':
- case 'Z':
- up = 2;
- break;
- default:
- PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
- return NULL;
- }
- }
- else {
- PyErr_SetString( PyExc_ValueError, "only X, Y or Z for up axis\n" );
- return NULL;
- }
- }
-
- if (track == up) {
- PyErr_SetString( PyExc_ValueError, "Can't have the same axis for track and up\n" );
- return NULL;
- }
-
- /*
- flip vector around, since vectoquat expect a vector from target to tracking object
- and the python function expects the inverse (a vector to the target).
- */
- vec[0] = -self->vec[0];
- vec[1] = -self->vec[1];
- vec[2] = -self->vec[2];
-
- vectoquat(vec, track, up, quat);
-
- return newQuaternionObject(quat, Py_NEW, NULL);
-}
-
-/*----------------------------Vector.reflect(mirror) ----------------------
- return a reflected vector on the mirror normal
- ((2 * DotVecs(vec, mirror)) * mirror) - vec
- using arithb.c would be nice here */
-static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
-{
- float mirror[3];
- float vec[3];
- float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- float dot2;
-
- /* for normalizing */
- int i;
- float norm = 0.0f;
-
- if (!VectorObject_Check(value)) {
- PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" );
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- mirror[0] = value->vec[0];
- mirror[1] = value->vec[1];
- if (value->size > 2) mirror[2] = value->vec[2];
- else mirror[2] = 0.0;
-
- /* normalize, whos idea was it not to use arithb.c? :-/ */
- for(i = 0; i < 3; i++) {
- norm += mirror[i] * mirror[i];
- }
- norm = (float) sqrt(norm);
- for(i = 0; i < 3; i++) {
- mirror[i] /= norm;
- }
- /* done */
-
- vec[0] = self->vec[0];
- vec[1] = self->vec[1];
- if (self->size > 2) vec[2] = self->vec[2];
- else vec[2] = 0.0;
-
- dot2 = 2 * vec[0]*mirror[0]+vec[1]*mirror[1]+vec[2]*mirror[2];
-
- reflect[0] = (dot2 * mirror[0]) - vec[0];
- reflect[1] = (dot2 * mirror[1]) - vec[1];
- reflect[2] = (dot2 * mirror[2]) - vec[2];
-
- return newVectorObject(reflect, self->size, Py_NEW, NULL);
-}
-
-static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
-{
- VectorObject *vecCross = NULL;
-
- if (!VectorObject_Check(value)) {
- PyErr_SetString( PyExc_TypeError, "vec.cross(value): expected a vector argument" );
- return NULL;
- }
-
- if(self->size != 3 || value->size != 3) {
- PyErr_SetString(PyExc_AttributeError, "vec.cross(value): expects both vectors to be 3D\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW, NULL);
- Crossf(vecCross->vec, self->vec, value->vec);
- return (PyObject *)vecCross;
-}
-
-static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
-{
- double dot = 0.0;
- int x;
-
- if (!VectorObject_Check(value)) {
- PyErr_SetString( PyExc_TypeError, "vec.cross(value): expected a vector argument" );
- return NULL;
- }
-
- if(self->size != value->size) {
- PyErr_SetString(PyExc_AttributeError, "vec.dot(value): expects both vectors to have the same size\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
- return NULL;
-
- for(x = 0; x < self->size; x++) {
- dot += self->vec[x] * value->vec[x];
- }
- return PyFloat_FromDouble(dot);
-}
-
-/*----------------------------Vector.copy() --------------------------------------
- return a copy of the vector */
-static PyObject *Vector_copy(VectorObject * self)
-{
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- return newVectorObject(self->vec, self->size, Py_NEW, Py_TYPE(self));
-}
-
-/*----------------------------print object (internal)-------------
- print the object to screen */
-static PyObject *Vector_repr(VectorObject * self)
-{
- int i;
- char buffer[48], str[1024];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- BLI_strncpy(str,"[",1024);
- for(i = 0; i < self->size; i++){
- if(i < (self->size - 1)){
- sprintf(buffer, "%.6f, ", self->vec[i]);
- strcat(str,buffer);
- }else{
- sprintf(buffer, "%.6f", self->vec[i]);
- strcat(str,buffer);
- }
- }
- strcat(str, "](vector)");
-
- return PyUnicode_FromString(str);
-}
-/*---------------------SEQUENCE PROTOCOLS------------------------
- ----------------------------len(object)------------------------
- sequence length*/
-static int Vector_len(VectorObject * self)
-{
- return self->size;
-}
-/*----------------------------object[]---------------------------
- sequence accessor (get)*/
-static PyObject *Vector_item(VectorObject * self, int i)
-{
- if(i<0) i= self->size-i;
-
- if(i < 0 || i >= self->size) {
- PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n");
- return NULL;
- }
-
- if(!BaseMath_ReadIndexCallback(self, i))
- return NULL;
-
- return PyFloat_FromDouble(self->vec[i]);
-
-}
-/*----------------------------object[]-------------------------
- sequence accessor (set)*/
-static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
-{
- float scalar= (float)PyFloat_AsDouble(ob);
- if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "vector[index] = x: index argument not a number\n");
- return -1;
- }
-
- if(i<0) i= self->size-i;
-
- if(i < 0 || i >= self->size){
- PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n");
- return -1;
- }
- self->vec[i] = scalar;
-
- if(!BaseMath_WriteIndexCallback(self, i))
- return -1;
- return 0;
-}
-
-/*----------------------------object[z:y]------------------------
- sequence slice (get) */
-static PyObject *Vector_slice(VectorObject * self, int begin, int end)
-{
- PyObject *list = NULL;
- int count;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- CLAMP(begin, 0, self->size);
- if (end<0) end= self->size+end+1;
- CLAMP(end, 0, self->size);
- begin = MIN2(begin,end);
-
- list = PyList_New(end - begin);
- for(count = begin; count < end; count++) {
- PyList_SetItem(list, count - begin,
- PyFloat_FromDouble(self->vec[count]));
- }
-
- return list;
-}
-/*----------------------------object[z:y]------------------------
- sequence slice (set) */
-static int Vector_ass_slice(VectorObject * self, int begin, int end,
- PyObject * seq)
-{
- int i, y, size = 0;
- float vec[4], scalar;
- PyObject *v;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- CLAMP(begin, 0, self->size);
- if (end<0) end= self->size+end+1;
- CLAMP(end, 0, self->size);
- begin = MIN2(begin,end);
-
- size = PySequence_Length(seq);
- if(size != (end - begin)){
- PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: size mismatch in slice assignment\n");
- return -1;
- }
-
- for (i = 0; i < size; i++) {
- v = PySequence_GetItem(seq, i);
- if (v == NULL) { /* Failed to read sequence */
- PyErr_SetString(PyExc_RuntimeError, "vector[begin:end] = []: unable to read sequence\n");
- return -1;
- }
-
- scalar= (float)PyFloat_AsDouble(v);
- if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- Py_DECREF(v);
- PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: sequence argument not a number\n");
- return -1;
- }
-
- vec[i] = scalar;
- Py_DECREF(v);
- }
- /*parsed well - now set in vector*/
- for(y = 0; y < size; y++){
- self->vec[begin + y] = vec[y];
- }
-
- if(!BaseMath_WriteCallback(self))
- return -1;
-
- return 0;
-}
-/*------------------------NUMERIC PROTOCOLS----------------------
- ------------------------obj + obj------------------------------
- addition*/
-static PyObject *Vector_add(PyObject * v1, PyObject * v2)
-{
- int i;
- float vec[4];
-
- VectorObject *vec1 = NULL, *vec2 = NULL;
-
- if VectorObject_Check(v1)
- vec1= (VectorObject *)v1;
-
- if VectorObject_Check(v2)
- vec2= (VectorObject *)v2;
-
- /* make sure v1 is always the vector */
- if (vec1 && vec2 ) {
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- /*VECTOR + VECTOR*/
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
- return NULL;
- }
- for(i = 0; i < vec1->size; i++) {
- vec[i] = vec1->vec[i] + vec2->vec[i];
- }
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
- }
-
- PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
- return NULL;
-}
-
-/* ------------------------obj += obj------------------------------
- addition in place */
-static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
-{
- int i;
-
- VectorObject *vec1 = NULL, *vec2 = NULL;
-
- if VectorObject_Check(v1)
- vec1= (VectorObject *)v1;
-
- if VectorObject_Check(v2)
- vec2= (VectorObject *)v2;
-
- /* make sure v1 is always the vector */
- if (vec1 && vec2 ) {
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- /*VECTOR + VECTOR*/
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
- return NULL;
- }
- for(i = 0; i < vec1->size; i++) {
- vec1->vec[i] += vec2->vec[i];
- }
- Py_INCREF( v1 );
- return v1;
- }
-
- BaseMath_WriteCallback(vec1);
- PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
- return NULL;
-}
-
-/*------------------------obj - obj------------------------------
- subtraction*/
-static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
-{
- int i;
- float vec[4];
- VectorObject *vec1 = NULL, *vec2 = NULL;
-
- if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
- PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation....\n");
- return NULL;
- }
- vec1 = (VectorObject*)v1;
- vec2 = (VectorObject*)v2;
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
- return NULL;
- }
- for(i = 0; i < vec1->size; i++) {
- vec[i] = vec1->vec[i] - vec2->vec[i];
- }
-
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
-}
-
-/*------------------------obj -= obj------------------------------
- subtraction*/
-static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
-{
- int i;
- VectorObject *vec1 = NULL, *vec2 = NULL;
-
- if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
- PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation....\n");
- return NULL;
- }
- vec1 = (VectorObject*)v1;
- vec2 = (VectorObject*)v2;
-
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
- return NULL;
- }
-
- if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
- return NULL;
-
- for(i = 0; i < vec1->size; i++) {
- vec1->vec[i] = vec1->vec[i] - vec2->vec[i];
- }
-
- BaseMath_WriteCallback(vec1);
- Py_INCREF( v1 );
- return v1;
-}
-
-/*------------------------obj * obj------------------------------
- mulplication*/
-static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
-{
- VectorObject *vec1 = NULL, *vec2 = NULL;
- float scalar;
-
- if VectorObject_Check(v1) {
- vec1= (VectorObject *)v1;
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
- }
- if VectorObject_Check(v2) {
- vec2= (VectorObject *)v2;
- if(!BaseMath_ReadCallback(vec2))
- return NULL;
- }
-
-
- /* make sure v1 is always the vector */
- if (vec1 && vec2 ) {
- int i;
- double dot = 0.0f;
-
- if(vec1->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Vector multiplication: vectors must have the same dimensions for this operation\n");
- return NULL;
- }
-
- /*dot product*/
- for(i = 0; i < vec1->size; i++) {
- dot += vec1->vec[i] * vec2->vec[i];
- }
- return PyFloat_FromDouble(dot);
- }
-
- /*swap so vec1 is always the vector */
- if (vec2) {
- vec1= vec2;
- v2= v1;
- }
-
- if (MatrixObject_Check(v2)) {
- /* VEC * MATRIX */
- return row_vector_multiplication(vec1, (MatrixObject*)v2);
- } else if (QuaternionObject_Check(v2)) {
- QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */
-
- if(vec1->size != 3) {
- PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
- return NULL;
- }
- return quat_rotation((PyObject*)vec1, (PyObject*)quat);
- }
- else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */
- int i;
- float vec[4];
-
- for(i = 0; i < vec1->size; i++) {
- vec[i] = vec1->vec[i] * scalar;
- }
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
-
- }
-
- PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
- return NULL;
-}
-
-/*------------------------obj *= obj------------------------------
- in place mulplication */
-static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
-{
- VectorObject *vec = (VectorObject *)v1;
- int i;
- float scalar;
-
- if(!BaseMath_ReadCallback(vec))
- return NULL;
-
- /* only support vec*=float and vec*=mat
- vec*=vec result is a float so that wont work */
- if (MatrixObject_Check(v2)) {
- float vecCopy[4];
- int x,y, size = vec->size;
- MatrixObject *mat= (MatrixObject*)v2;
-
- if(!BaseMath_ReadCallback(mat))
- return NULL;
-
- if(mat->colSize != size){
- if(mat->rowSize == 4 && vec->size != 3){
- PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
- return NULL;
- } else {
- vecCopy[3] = 1.0f;
- }
- }
-
- for(i = 0; i < size; i++){
- vecCopy[i] = vec->vec[i];
- }
-
- size = MIN2(size, mat->colSize);
-
- /*muliplication*/
- for(x = 0, i = 0; x < size; x++, i++) {
- double dot = 0.0f;
- for(y = 0; y < mat->rowSize; y++) {
- dot += mat->matrix[y][x] * vecCopy[y];
- }
- vec->vec[i] = (float)dot;
- }
- }
- else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
-
- for(i = 0; i < vec->size; i++) {
- vec->vec[i] *= scalar;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
- return NULL;
- }
-
- BaseMath_WriteCallback(vec);
- Py_INCREF( v1 );
- return v1;
-}
-
-/*------------------------obj / obj------------------------------
- divide*/
-static PyObject *Vector_div(PyObject * v1, PyObject * v2)
-{
- int i;
- float vec[4], scalar;
- VectorObject *vec1 = NULL;
-
- if(!VectorObject_Check(v1)) { /* not a vector */
- PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
- return NULL;
- }
- vec1 = (VectorObject*)v1; /* vector */
-
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
-
- scalar = (float)PyFloat_AsDouble(v2);
- if(scalar== -1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
- return NULL;
- }
-
- if(scalar==0.0) { /* not a vector */
- PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
- return NULL;
- }
-
- for(i = 0; i < vec1->size; i++) {
- vec[i] = vec1->vec[i] / scalar;
- }
- return newVectorObject(vec, vec1->size, Py_NEW, NULL);
-}
-
-/*------------------------obj /= obj------------------------------
- divide*/
-static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
-{
- int i;
- float scalar;
- VectorObject *vec1 = (VectorObject*)v1;
-
- if(!BaseMath_ReadCallback(vec1))
- return NULL;
-
- scalar = (float)PyFloat_AsDouble(v2);
- if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
- PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
- return NULL;
- }
-
- if(scalar==0.0) { /* not a vector */
- PyErr_SetString(PyExc_ZeroDivisionError, "Vector division: divide by zero error.\n");
- return NULL;
- }
- for(i = 0; i < vec1->size; i++) {
- vec1->vec[i] /= scalar;
- }
-
- BaseMath_WriteCallback(vec1);
-
- Py_INCREF( v1 );
- return v1;
-}
-
-/*-------------------------- -obj -------------------------------
- returns the negative of this object*/
-static PyObject *Vector_neg(VectorObject *self)
-{
- int i;
- float vec[4];
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++){
- vec[i] = -self->vec[i];
- }
-
- return newVectorObject(vec, self->size, Py_NEW, Py_TYPE(self));
-}
-
-/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
-static double vec_magnitude_nosqrt(float *data, int size)
-{
- double dot = 0.0f;
- int i;
-
- for(i=0; i<size; i++){
- dot += data[i];
- }
- /*return (double)sqrt(dot);*/
- /* warning, line above removed because we are not using the length,
- rather the comparing the sizes and for this we do not need the sqrt
- for the actual length, the dot must be sqrt'd */
- return (double)dot;
-}
-
-
-/*------------------------tp_richcmpr
- returns -1 execption, 0 false, 1 true */
-static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
-{
- VectorObject *vecA = NULL, *vecB = NULL;
- int result = 0;
- float epsilon = .000001f;
- double lenA,lenB;
-
- if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
- vecA = (VectorObject*)objectA;
- vecB = (VectorObject*)objectB;
-
- if(!BaseMath_ReadCallback(vecA) || !BaseMath_ReadCallback(vecB))
- return NULL;
-
- if (vecA->size != vecB->size){
- if (comparison_type == Py_NE){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
- }
-
- switch (comparison_type){
- case Py_LT:
- lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
- lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
- if( lenA < lenB ){
- result = 1;
- }
- break;
- case Py_LE:
- lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
- lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
- if( lenA < lenB ){
- result = 1;
- }else{
- result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
- }
- break;
- case Py_EQ:
- result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
- break;
- case Py_NE:
- result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
- if (result == 0){
- result = 1;
- }else{
- result = 0;
- }
- break;
- case Py_GT:
- lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
- lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
- if( lenA > lenB ){
- result = 1;
- }
- break;
- case Py_GE:
- lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
- lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
- if( lenA > lenB ){
- result = 1;
- }else{
- result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
- }
- break;
- default:
- printf("The result of the comparison could not be evaluated");
- break;
- }
- if (result == 1){
- Py_RETURN_TRUE;
- }else{
- Py_RETURN_FALSE;
- }
-}
-
-/*-----------------PROTCOL DECLARATIONS--------------------------*/
-static PySequenceMethods Vector_SeqMethods = {
- (inquiry) Vector_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (ssizeargfunc) 0, /* sq_repeat */
- (ssizeargfunc) Vector_item, /* sq_item */
-#if (PY_VERSION_HEX < 0x03000000)
- (ssizessizeargfunc) Vector_slice, /* sq_slice */ /* PY2 ONLY */
-#else
- NULL,
-#endif
- (ssizeobjargproc) Vector_ass_item, /* sq_ass_item */
-#if (PY_VERSION_HEX < 0x03000000)
- (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ /* PY2 ONLY */
-#else
- NULL,
-#endif
-};
-
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyObject *Vector_subscript(VectorObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i;
- i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += self->size;
- return Vector_item(self, i);
- } else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0)
- return NULL;
-
- if (slicelength <= 0) {
- return PyList_New(0);
- }
- else if (step == 1) {
- return Vector_slice(self, start, stop);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
- return NULL;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "vector indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return NULL;
- }
-}
-
-static int Vector_ass_subscript(VectorObject* self, PyObject* item, PyObject* value)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0)
- i += self->size;
- return Vector_ass_item(self, i, value);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0)
- return -1;
-
- if (step == 1)
- return Vector_ass_slice(self, start, stop, value);
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
- return -1;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "vector indices must be integers, not %.200s",
- item->ob_type->tp_name);
- return -1;
- }
-}
-
-static PyMappingMethods Vector_AsMapping = {
- (lenfunc)Vector_len,
- (binaryfunc)Vector_subscript,
- (objobjargproc)Vector_ass_subscript
-};
-#endif /* (PY_VERSION_HEX >= 0x03000000) */
-
-#if (PY_VERSION_HEX >= 0x03000000)
-static PyNumberMethods Vector_NumMethods = {
- (binaryfunc) Vector_add, /*nb_add*/
- (binaryfunc) Vector_sub, /*nb_subtract*/
- (binaryfunc) Vector_mul, /*nb_multiply*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- (unaryfunc) Vector_neg, /*nb_negative*/
- (unaryfunc) 0, /*tp_positive*/
- (unaryfunc) 0, /*tp_absolute*/
- (inquiry) 0, /*tp_bool*/
- (unaryfunc) 0, /*nb_invert*/
- 0, /*nb_lshift*/
- (binaryfunc)0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- 0, /*nb_int*/
- 0, /*nb_reserved*/
- 0, /*nb_float*/
- Vector_iadd, /* nb_inplace_add */
- Vector_isub, /* nb_inplace_subtract */
- Vector_imul, /* nb_inplace_multiply */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- Vector_div, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- Vector_idiv, /* nb_inplace_true_divide */
- 0, /* nb_index */
-};
-#else
-static PyNumberMethods Vector_NumMethods = {
- (binaryfunc) Vector_add, /* __add__ */
- (binaryfunc) Vector_sub, /* __sub__ */
- (binaryfunc) Vector_mul, /* __mul__ */
- (binaryfunc) Vector_div, /* __div__ */
- (binaryfunc) NULL, /* __mod__ */
- (binaryfunc) NULL, /* __divmod__ */
- (ternaryfunc) NULL, /* __pow__ */
- (unaryfunc) Vector_neg, /* __neg__ */
- (unaryfunc) NULL, /* __pos__ */
- (unaryfunc) NULL, /* __abs__ */
- (inquiry) NULL, /* __nonzero__ */
- (unaryfunc) NULL, /* __invert__ */
- (binaryfunc) NULL, /* __lshift__ */
- (binaryfunc) NULL, /* __rshift__ */
- (binaryfunc) NULL, /* __and__ */
- (binaryfunc) NULL, /* __xor__ */
- (binaryfunc) NULL, /* __or__ */
- /*(coercion)*/ NULL, /* __coerce__ */
- (unaryfunc) NULL, /* __int__ */
- (unaryfunc) NULL, /* __long__ */
- (unaryfunc) NULL, /* __float__ */
- (unaryfunc) NULL, /* __oct__ */
- (unaryfunc) NULL, /* __hex__ */
-
- /* Added in release 2.0 */
- (binaryfunc) Vector_iadd, /*__iadd__*/
- (binaryfunc) Vector_isub, /*__isub__*/
- (binaryfunc) Vector_imul, /*__imul__*/
- (binaryfunc) Vector_idiv, /*__idiv__*/
- (binaryfunc) NULL, /*__imod__*/
- (ternaryfunc) NULL, /*__ipow__*/
- (binaryfunc) NULL, /*__ilshift__*/
- (binaryfunc) NULL, /*__irshift__*/
- (binaryfunc) NULL, /*__iand__*/
- (binaryfunc) NULL, /*__ixor__*/
- (binaryfunc) NULL, /*__ior__*/
-
- /* Added in release 2.2 */
- /* The following require the Py_TPFLAGS_HAVE_CLASS flag */
- (binaryfunc) NULL, /*__floordiv__ __rfloordiv__*/
- (binaryfunc) NULL, /*__truediv__ __rfloordiv__*/
- (binaryfunc) NULL, /*__ifloordiv__*/
- (binaryfunc) NULL, /*__itruediv__*/
-};
-#endif
-
-/*------------------PY_OBECT DEFINITION--------------------------*/
-
-/*
- * vector axis, vector.x/y/z/w
- */
-
-static PyObject *Vector_getAxis( VectorObject * self, void *type )
-{
- return Vector_item(self, GET_INT_FROM_POINTER(type));
-}
-
-static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
-{
- return Vector_ass_item(self, GET_INT_FROM_POINTER(type), value);
-}
-
-/* vector.length */
-static PyObject *Vector_getLength( VectorObject * self, void *type )
-{
- double dot = 0.0f;
- int i;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++){
- dot += (self->vec[i] * self->vec[i]);
- }
- return PyFloat_FromDouble(sqrt(dot));
-}
-
-static int Vector_setLength( VectorObject * self, PyObject * value )
-{
- double dot = 0.0f, param;
- int i;
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- param= PyFloat_AsDouble( value );
- if(param==-1.0 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "length must be set to a number");
- return -1;
- }
-
- if (param < 0) {
- PyErr_SetString( PyExc_TypeError, "cannot set a vectors length to a negative value" );
- return -1;
- }
- if (param==0) {
- for(i = 0; i < self->size; i++){
- self->vec[i]= 0;
- }
- return 0;
- }
-
- for(i = 0; i < self->size; i++){
- dot += (self->vec[i] * self->vec[i]);
- }
-
- if (!dot) /* cant sqrt zero */
- return 0;
-
- dot = sqrt(dot);
-
- if (dot==param)
- return 0;
-
- dot= dot/param;
-
- for(i = 0; i < self->size; i++){
- self->vec[i]= self->vec[i] / (float)dot;
- }
-
- BaseMath_WriteCallback(self); /* checked alredy */
-
- return 0;
-}
-
-/* Get a new Vector according to the provided swizzle. This function has little
- error checking, as we are in control of the inputs: the closure is set by us
- in Vector_createSwizzleGetSeter. */
-static PyObject *Vector_getSwizzle(VectorObject * self, void *closure)
-{
- size_t axisA;
- size_t axisB;
- float vec[MAX_DIMENSIONS];
- unsigned int swizzleClosure;
-
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- /* Unpack the axes from the closure into an array. */
- axisA = 0;
- swizzleClosure = (unsigned int) closure;
- while (swizzleClosure & SWIZZLE_VALID_AXIS)
- {
- axisB = swizzleClosure & SWIZZLE_AXIS;
- vec[axisA] = self->vec[axisB];
- swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
- axisA++;
- }
-
- return newVectorObject(vec, axisA, Py_NEW, Py_TYPE(self));
-}
-
-/* Set the items of this vector using a swizzle.
- - If value is a vector or list this operates like an array copy, except that
- the destination is effectively re-ordered as defined by the swizzle. At
- most min(len(source), len(dest)) values will be copied.
- - If the value is scalar, it is copied to all axes listed in the swizzle.
- - If an axis appears more than once in the swizzle, the final occurrance is
- the one that determines its value.
-
- Returns 0 on success and -1 on failure. On failure, the vector will be
- unchanged. */
-static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closure)
-{
- VectorObject *vecVal;
- PyObject *item;
- size_t listLen;
- float scalarVal;
-
- size_t axisB;
- size_t axisA;
- unsigned int swizzleClosure;
-
- float vecTemp[MAX_DIMENSIONS];
-
- if(!BaseMath_ReadCallback(self))
- return -1;
-
- /* Check that the closure can be used with this vector: even 2D vectors have
- swizzles defined for axes z and w, but they would be invalid. */
- swizzleClosure = (unsigned int) closure;
- while (swizzleClosure & SWIZZLE_VALID_AXIS)
- {
- axisA = swizzleClosure & SWIZZLE_AXIS;
- if (axisA >= self->size)
- {
- PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n");
- return -1;
- }
- swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
- }
-
- if (VectorObject_Check(value))
- {
- /* Copy vector contents onto swizzled axes. */
- vecVal = (VectorObject*) value;
- axisB = 0;
- swizzleClosure = (unsigned int) closure;
- while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < vecVal->size)
- {
- axisA = swizzleClosure & SWIZZLE_AXIS;
- vecTemp[axisA] = vecVal->vec[axisB];
-
- swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
- axisB++;
- }
- memcpy(self->vec, vecTemp, axisB * sizeof(float));
- /* continue with BaseMathObject_WriteCallback at the end */
- }
- else if (PyList_Check(value))
- {
- /* Copy list contents onto swizzled axes. */
- listLen = PyList_Size(value);
- swizzleClosure = (unsigned int) closure;
- axisB = 0;
- while (swizzleClosure & SWIZZLE_VALID_AXIS && axisB < listLen)
- {
- item = PyList_GetItem(value, axisB);
- scalarVal = (float)PyFloat_AsDouble(item);
-
- if (scalarVal==-1.0 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis.\n");
- return -1;
- }
-
-
- axisA = swizzleClosure & SWIZZLE_AXIS;
- vecTemp[axisA] = scalarVal;
-
- swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
- axisB++;
- }
- memcpy(self->vec, vecTemp, axisB * sizeof(float));
- /* continue with BaseMathObject_WriteCallback at the end */
- }
- else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0)
- {
- /* Assign the same value to each axis. */
- swizzleClosure = (unsigned int) closure;
- while (swizzleClosure & SWIZZLE_VALID_AXIS)
- {
- axisA = swizzleClosure & SWIZZLE_AXIS;
- self->vec[axisA] = scalarVal;
-
- swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
- }
- /* continue with BaseMathObject_WriteCallback at the end */
- }
- else {
- PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." );
- return -1;
- }
-
- if(!BaseMath_WriteCallback(vecVal))
- return -1;
- else
- return 0;
-}
-
-/*****************************************************************************/
-/* Python attributes get/set structure: */
-/*****************************************************************************/
-static PyGetSetDef Vector_getseters[] = {
- {"x",
- (getter)Vector_getAxis, (setter)Vector_setAxis,
- "Vector X axis",
- (void *)0},
- {"y",
- (getter)Vector_getAxis, (setter)Vector_setAxis,
- "Vector Y axis",
- (void *)1},
- {"z",
- (getter)Vector_getAxis, (setter)Vector_setAxis,
- "Vector Z axis",
- (void *)2},
- {"w",
- (getter)Vector_getAxis, (setter)Vector_setAxis,
- "Vector Z axis",
- (void *)3},
- {"length",
- (getter)Vector_getLength, (setter)Vector_setLength,
- "Vector Length",
- NULL},
- {"magnitude",
- (getter)Vector_getLength, (setter)Vector_setLength,
- "Vector Length",
- NULL},
- {"wrapped",
- (getter)BaseMathObject_getWrapped, (setter)NULL,
- "True when this wraps blenders internal data",
- NULL},
- {"__owner__",
- (getter)BaseMathObject_getOwner, (setter)NULL,
- "Read only owner for vectors that depend on another object",
- NULL},
-
- /* autogenerated swizzle attrs, see python script below */
- {"xx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 36 */
- {"xxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 292 */
- {"xxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2340 */
- {"xxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2852 */
- {"xxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3364 */
- {"xxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3876 */
- {"xxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 356 */
- {"xxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2404 */
- {"xxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2916 */
- {"xxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3428 */
- {"xxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3940 */
- {"xxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 420 */
- {"xxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2468 */
- {"xxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2980 */
- {"xxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3492 */
- {"xxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4004 */
- {"xxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 484 */
- {"xxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2532 */
- {"xxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3044 */
- {"xxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3556 */
- {"xxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4068 */
- {"xy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 44 */
- {"xyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 300 */
- {"xyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2348 */
- {"xyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2860 */
- {"xyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3372 */
- {"xyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3884 */
- {"xyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 364 */
- {"xyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2412 */
- {"xyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2924 */
- {"xyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3436 */
- {"xyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3948 */
- {"xyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 428 */
- {"xyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2476 */
- {"xyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2988 */
- {"xyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3500 */
- {"xyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4012 */
- {"xyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 492 */
- {"xywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2540 */
- {"xywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3052 */
- {"xywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3564 */
- {"xyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4076 */
- {"xz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 52 */
- {"xzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 308 */
- {"xzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2356 */
- {"xzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2868 */
- {"xzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3380 */
- {"xzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3892 */
- {"xzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 372 */
- {"xzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2420 */
- {"xzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2932 */
- {"xzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3444 */
- {"xzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3956 */
- {"xzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 436 */
- {"xzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2484 */
- {"xzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2996 */
- {"xzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3508 */
- {"xzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4020 */
- {"xzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 500 */
- {"xzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2548 */
- {"xzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3060 */
- {"xzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3572 */
- {"xzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4084 */
- {"xw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 60 */
- {"xwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 316 */
- {"xwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2364 */
- {"xwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2876 */
- {"xwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3388 */
- {"xwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3900 */
- {"xwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 380 */
- {"xwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2428 */
- {"xwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2940 */
- {"xwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3452 */
- {"xwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3964 */
- {"xwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 444 */
- {"xwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2492 */
- {"xwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3004 */
- {"xwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3516 */
- {"xwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4028 */
- {"xww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 508 */
- {"xwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2556 */
- {"xwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3068 */
- {"xwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3580 */
- {"xwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4092 */
- {"yx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 37 */
- {"yxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 293 */
- {"yxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2341 */
- {"yxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2853 */
- {"yxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3365 */
- {"yxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3877 */
- {"yxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 357 */
- {"yxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2405 */
- {"yxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2917 */
- {"yxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3429 */
- {"yxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3941 */
- {"yxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 421 */
- {"yxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2469 */
- {"yxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2981 */
- {"yxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3493 */
- {"yxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4005 */
- {"yxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 485 */
- {"yxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2533 */
- {"yxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3045 */
- {"yxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3557 */
- {"yxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4069 */
- {"yy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 45 */
- {"yyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 301 */
- {"yyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2349 */
- {"yyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2861 */
- {"yyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3373 */
- {"yyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3885 */
- {"yyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 365 */
- {"yyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2413 */
- {"yyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2925 */
- {"yyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3437 */
- {"yyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3949 */
- {"yyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 429 */
- {"yyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2477 */
- {"yyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2989 */
- {"yyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3501 */
- {"yyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4013 */
- {"yyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 493 */
- {"yywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2541 */
- {"yywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3053 */
- {"yywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3565 */
- {"yyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4077 */
- {"yz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 53 */
- {"yzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 309 */
- {"yzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2357 */
- {"yzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2869 */
- {"yzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3381 */
- {"yzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3893 */
- {"yzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 373 */
- {"yzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2421 */
- {"yzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2933 */
- {"yzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3445 */
- {"yzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3957 */
- {"yzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 437 */
- {"yzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2485 */
- {"yzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2997 */
- {"yzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3509 */
- {"yzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4021 */
- {"yzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 501 */
- {"yzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2549 */
- {"yzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3061 */
- {"yzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3573 */
- {"yzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4085 */
- {"yw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 61 */
- {"ywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 317 */
- {"ywxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2365 */
- {"ywxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2877 */
- {"ywxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3389 */
- {"ywxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3901 */
- {"ywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 381 */
- {"ywyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2429 */
- {"ywyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2941 */
- {"ywyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3453 */
- {"ywyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3965 */
- {"ywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 445 */
- {"ywzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2493 */
- {"ywzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3005 */
- {"ywzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3517 */
- {"ywzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4029 */
- {"yww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 509 */
- {"ywwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2557 */
- {"ywwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3069 */
- {"ywwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3581 */
- {"ywww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((1|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4093 */
- {"zx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 38 */
- {"zxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 294 */
- {"zxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2342 */
- {"zxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2854 */
- {"zxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3366 */
- {"zxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3878 */
- {"zxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 358 */
- {"zxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2406 */
- {"zxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2918 */
- {"zxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3430 */
- {"zxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3942 */
- {"zxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 422 */
- {"zxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2470 */
- {"zxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2982 */
- {"zxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3494 */
- {"zxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4006 */
- {"zxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 486 */
- {"zxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2534 */
- {"zxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3046 */
- {"zxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3558 */
- {"zxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4070 */
- {"zy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 46 */
- {"zyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 302 */
- {"zyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2350 */
- {"zyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2862 */
- {"zyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3374 */
- {"zyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3886 */
- {"zyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 366 */
- {"zyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2414 */
- {"zyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2926 */
- {"zyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3438 */
- {"zyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3950 */
- {"zyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 430 */
- {"zyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2478 */
- {"zyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2990 */
- {"zyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3502 */
- {"zyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4014 */
- {"zyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 494 */
- {"zywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2542 */
- {"zywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3054 */
- {"zywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3566 */
- {"zyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4078 */
- {"zz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 54 */
- {"zzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 310 */
- {"zzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2358 */
- {"zzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2870 */
- {"zzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3382 */
- {"zzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3894 */
- {"zzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 374 */
- {"zzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2422 */
- {"zzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2934 */
- {"zzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3446 */
- {"zzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3958 */
- {"zzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 438 */
- {"zzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2486 */
- {"zzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2998 */
- {"zzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3510 */
- {"zzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4022 */
- {"zzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 502 */
- {"zzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2550 */
- {"zzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3062 */
- {"zzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3574 */
- {"zzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4086 */
- {"zw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 62 */
- {"zwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 318 */
- {"zwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2366 */
- {"zwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2878 */
- {"zwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3390 */
- {"zwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3902 */
- {"zwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 382 */
- {"zwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2430 */
- {"zwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2942 */
- {"zwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3454 */
- {"zwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3966 */
- {"zwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 446 */
- {"zwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2494 */
- {"zwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3006 */
- {"zwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3518 */
- {"zwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4030 */
- {"zww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 510 */
- {"zwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2558 */
- {"zwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3070 */
- {"zwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3582 */
- {"zwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((2|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4094 */
- {"wx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 39 */
- {"wxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 295 */
- {"wxxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2343 */
- {"wxxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2855 */
- {"wxxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3367 */
- {"wxxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3879 */
- {"wxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 359 */
- {"wxyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2407 */
- {"wxyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2919 */
- {"wxyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3431 */
- {"wxyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3943 */
- {"wxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 423 */
- {"wxzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2471 */
- {"wxzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2983 */
- {"wxzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3495 */
- {"wxzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4007 */
- {"wxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 487 */
- {"wxwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2535 */
- {"wxwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3047 */
- {"wxwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3559 */
- {"wxww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4071 */
- {"wy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 47 */
- {"wyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 303 */
- {"wyxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2351 */
- {"wyxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2863 */
- {"wyxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3375 */
- {"wyxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3887 */
- {"wyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 367 */
- {"wyyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2415 */
- {"wyyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2927 */
- {"wyyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3439 */
- {"wyyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3951 */
- {"wyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 431 */
- {"wyzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2479 */
- {"wyzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2991 */
- {"wyzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3503 */
- {"wyzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4015 */
- {"wyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 495 */
- {"wywx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2543 */
- {"wywy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3055 */
- {"wywz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3567 */
- {"wyww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4079 */
- {"wz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 55 */
- {"wzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 311 */
- {"wzxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2359 */
- {"wzxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2871 */
- {"wzxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3383 */
- {"wzxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3895 */
- {"wzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 375 */
- {"wzyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2423 */
- {"wzyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2935 */
- {"wzyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3447 */
- {"wzyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3959 */
- {"wzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 439 */
- {"wzzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2487 */
- {"wzzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2999 */
- {"wzzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3511 */
- {"wzzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4023 */
- {"wzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 503 */
- {"wzwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2551 */
- {"wzwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3063 */
- {"wzwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3575 */
- {"wzww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4087 */
- {"ww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 63 */
- {"wwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 319 */
- {"wwxx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2367 */
- {"wwxy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2879 */
- {"wwxz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3391 */
- {"wwxw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3903 */
- {"wwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 383 */
- {"wwyx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2431 */
- {"wwyy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2943 */
- {"wwyz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3455 */
- {"wwyw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3967 */
- {"wwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 447 */
- {"wwzx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2495 */
- {"wwzy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3007 */
- {"wwzz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3519 */
- {"wwzw", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4031 */
- {"www", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2))))}, /* 511 */
- {"wwwx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((0|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 2559 */
- {"wwwy", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((1|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3071 */
- {"wwwz", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((2|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 3583 */
- {"wwww", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)((3|SWIZZLE_VALID_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((3|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) )}, /* 4095 */
- {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
-};
-
-/* Python script used to make swizzle array */
-/*
-SWIZZLE_BITS_PER_AXIS = 3
-SWIZZLE_VALID_AXIS = 0x4
-
-axis_dict = {}
-axis_pos = {'x':0, 'y':1, 'z':2, 'w':3}
-axises = 'xyzw'
-while len(axises) >= 2:
-
- for axis_0 in axises:
- axis_0_pos = axis_pos[axis_0]
- for axis_1 in axises:
- axis_1_pos = axis_pos[axis_1]
- axis_dict[axis_0+axis_1] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS))' % (axis_0_pos, axis_1_pos)
- if len(axises)>2:
- for axis_2 in axises:
- axis_2_pos = axis_pos[axis_2]
- axis_dict[axis_0+axis_1+axis_2] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)))' % (axis_0_pos, axis_1_pos, axis_2_pos)
- if len(axises)>3:
- for axis_3 in axises:
- axis_3_pos = axis_pos[axis_3]
- axis_dict[axis_0+axis_1+axis_2+axis_3] = '((%s|SWIZZLE_VALID_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*2)) | ((%s|SWIZZLE_VALID_AXIS)<<(SWIZZLE_BITS_PER_AXIS*3))) ' % (axis_0_pos, axis_1_pos, axis_2_pos, axis_3_pos)
-
- axises = axises[:-1]
-
-
-items = axis_dict.items()
-items.sort(key = lambda a: a[0].replace('x', '0').replace('y', '1').replace('z', '2').replace('w', '3'))
-
-unique = set()
-for key, val in items:
- num = eval(val)
- print '\t{"%s", %s(getter)Vector_getSwizzle, (setter)Vector_setSwizzle, NULL, (void *)((unsigned int)%s)}, // %s' % (key, (' '*(4-len(key))), axis_dict[key], num)
- unique.add(num)
-
-if len(unique) != len(items):
- print "ERROR"
-
-*/
-
-
-
-
-/* Note
- Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
- but this means for eg that
- vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order
-*/
-
-PyTypeObject vector_Type = {
-#if (PY_VERSION_HEX >= 0x02060000)
- PyVarObject_HEAD_INIT(NULL, 0)
-#else
- /* python 2.5 and below */
- PyObject_HEAD_INIT( NULL ) /* required py macro */
- 0, /* ob_size */
-#endif
- /* For printing, in format "<module>.<name>" */
- "vector", /* char *tp_name; */
- sizeof( VectorObject ), /* int tp_basicsize; */
- 0, /* tp_itemsize; For allocation */
-
- /* Methods to implement standard operations */
-
- ( destructor ) BaseMathObject_dealloc,/* destructor tp_dealloc; */
- NULL, /* printfunc tp_print; */
- NULL, /* getattrfunc tp_getattr; */
- NULL, /* setattrfunc tp_setattr; */
- NULL, /* cmpfunc tp_compare; */
- ( reprfunc ) Vector_repr, /* reprfunc tp_repr; */
-
- /* Method suites for standard classes */
-
- &Vector_NumMethods, /* PyNumberMethods *tp_as_number; */
- &Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */
-#if (PY_VERSION_HEX >= 0x03000000)
- &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */
-#else
- NULL,
-#endif
-
- /* More standard operations (here for binary compatibility) */
-
- NULL, /* hashfunc tp_hash; */
- NULL, /* ternaryfunc tp_call; */
- NULL, /* reprfunc tp_str; */
- NULL, /* getattrofunc tp_getattro; */
- NULL, /* setattrofunc tp_setattro; */
-
- /* Functions to access object as input/output buffer */
- NULL, /* PyBufferProcs *tp_as_buffer; */
-
- /*** Flags to define presence of optional/expanded features ***/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- NULL, /* char *tp_doc; Documentation string */
- /*** Assigned meaning in release 2.0 ***/
- /* call function for all accessible objects */
- NULL, /* traverseproc tp_traverse; */
-
- /* delete references to contained objects */
- NULL, /* inquiry tp_clear; */
-
- /*** Assigned meaning in release 2.1 ***/
- /*** rich comparisons ***/
- (richcmpfunc)Vector_richcmpr, /* richcmpfunc tp_richcompare; */
-
- /*** weak reference enabler ***/
- 0, /* long tp_weaklistoffset; */
-
- /*** Added in release 2.2 ***/
- /* Iterators */
- NULL, /* getiterfunc tp_iter; */
- NULL, /* iternextfunc tp_iternext; */
-
- /*** Attribute descriptor and subclassing stuff ***/
- Vector_methods, /* struct PyMethodDef *tp_methods; */
- NULL, /* struct PyMemberDef *tp_members; */
- Vector_getseters, /* struct PyGetSetDef *tp_getset; */
- NULL, /* struct _typeobject *tp_base; */
- NULL, /* PyObject *tp_dict; */
- NULL, /* descrgetfunc tp_descr_get; */
- NULL, /* descrsetfunc tp_descr_set; */
- 0, /* long tp_dictoffset; */
- NULL, /* initproc tp_init; */
- NULL, /* allocfunc tp_alloc; */
- Vector_new, /* newfunc tp_new; */
- /* Low-level free-memory routine */
- NULL, /* freefunc tp_free; */
- /* For PyObject_IS_GC */
- NULL, /* inquiry tp_is_gc; */
- NULL, /* PyObject *tp_bases; */
- /* method resolution order */
- NULL, /* PyObject *tp_mro; */
- NULL, /* PyObject *tp_cache; */
- NULL, /* PyObject *tp_subclasses; */
- NULL, /* PyObject *tp_weaklist; */
- NULL
-};
-
-
-/*------------------------newVectorObject (internal)-------------
- creates a new vector object
- pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
- pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type)
-{
- int i;
- VectorObject *self;
-
- if(base_type) self = (VectorObject *)base_type->tp_alloc(base_type, 0);
- else self = PyObject_NEW(VectorObject, &vector_Type);
-
- if(size > 4 || size < 2)
- return NULL;
- self->size = size;
-
- /* init callbacks as NULL */
- self->cb_user= NULL;
- self->cb_type= self->cb_subtype= 0;
-
- if(type == Py_WRAP) {
- self->vec = vec;
- self->wrapped = Py_WRAP;
- } else if (type == Py_NEW) {
- self->vec = PyMem_Malloc(size * sizeof(float));
- if(!vec) { /*new empty*/
- for(i = 0; i < size; i++){
- self->vec[i] = 0.0f;
- }
- if(size == 4) /* do the homogenous thing */
- self->vec[3] = 1.0f;
- }else{
- for(i = 0; i < size; i++){
- self->vec[i] = vec[i];
- }
- }
- self->wrapped = Py_NEW;
- }else{ /*bad type*/
- return NULL;
- }
- return (PyObject *) self;
-}
-
-PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype)
-{
- float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */
- VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW, NULL);
- if(self) {
- Py_INCREF(cb_user);
- self->cb_user= cb_user;
- self->cb_type= (unsigned char)cb_type;
- self->cb_subtype= (unsigned char)cb_subtype;
- }
-
- return (PyObject *)self;
-}
-
-//-----------------row_vector_multiplication (internal)-----------
-//ROW VECTOR Multiplication - Vector X Matrix
-//[x][y][z] * [1][2][3]
-// [4][5][6]
-// [7][8][9]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
-{
- float vecNew[4], vecCopy[4];
- double dot = 0.0f;
- int x, y, z = 0, vec_size = vec->size;
-
- if(mat->colSize != vec_size){
- if(mat->rowSize == 4 && vec_size != 3){
- PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
- return NULL;
- }else{
- vecCopy[3] = 1.0f;
- }
- }
-
- if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat))
- return NULL;
-
- for(x = 0; x < vec_size; x++){
- vecCopy[x] = vec->vec[x];
- }
-
- //muliplication
- for(x = 0; x < mat->colSize; x++) {
- for(y = 0; y < mat->rowSize; y++) {
- dot += mat->matrix[y][x] * vecCopy[y];
- }
- vecNew[z++] = (float)dot;
- dot = 0.0f;
- }
- return newVectorObject(vecNew, vec_size, Py_NEW, NULL);
-}
-
-/*----------------------------Vector.negate() --------------------
- set the vector to it's negative -x, -y, -z */
-static PyObject *Vector_Negate(VectorObject * self)
-{
- int i;
- if(!BaseMath_ReadCallback(self))
- return NULL;
-
- for(i = 0; i < self->size; i++)
- self->vec[i] = -(self->vec[i]);
-
- BaseMath_WriteCallback(self); // alredy checked for error
-
- Py_INCREF(self);
- return (PyObject*)self;
-}
diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h
deleted file mode 100644
index f6babac7ed9..00000000000
--- a/source/blender/python/generic/vector.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$
- *
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Willian P. Germano & Joseph Gilbert
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-#ifndef EXPP_vector_h
-#define EXPP_vector_h
-
-#include <Python.h>
-#include "../intern/bpy_compat.h"
-
-extern PyTypeObject vector_Type;
-#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type)
-
-typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */
- PyObject_VAR_HEAD
- float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */
- PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
- unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
- unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
- unsigned char wrapped; /* wrapped data type? */
- /* end BaseMathObject */
-
- unsigned char size; /* vec size 2,3 or 4 */
-} VectorObject;
-
-/*prototypes*/
-PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type);
-PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype);
-
-#endif /* EXPP_vector_h */
diff --git a/source/blender/python/intern/Makefile b/source/blender/python/intern/Makefile
index d210cfaf973..3e28f5aac31 100644
--- a/source/blender/python/intern/Makefile
+++ b/source/blender/python/intern/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -37,7 +37,6 @@ CFLAGS += $(LEVEL_1_C_WARNINGS)
# OpenGL and Python
CPPFLAGS += $(OGL_CPPFLAGS)
-CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
# PreProcessor stuff
diff --git a/source/blender/python/intern/bpy_compat.h b/source/blender/python/intern/bpy_compat.h
index e999f57c733..ad6b7a5e85c 100644
--- a/source/blender/python/intern/bpy_compat.h
+++ b/source/blender/python/intern/bpy_compat.h
@@ -85,34 +85,8 @@ typedef Py_ssize_t (*lenfunc)(PyObject *);
#ifndef Py_RETURN_TRUE
#define Py_RETURN_TRUE return PyBool_FromLong(1)
#endif
-
-#define PyInt_FromSsize_t PyInt_FromLong
-#define PyNumber_AsSsize_t(ob, exc) PyInt_AsLong(ob)
-#define PyIndex_Check(ob) PyInt_Check(ob)
-
-
-#endif
-
-
-#if PY_VERSION_HEX < 0x03000000
-#ifndef ssizeargfunc
-#define ssizeargfunc intargfunc
#endif
-#ifndef ssizessizeargfunc
-#define ssizessizeargfunc intintargfunc
-#endif
-
-#ifndef ssizeobjargproc
-#define ssizeobjargproc intobjargproc
-#endif
-
-#ifndef ssizessizeobjargproc
-#define ssizessizeobjargproc intintobjargproc
-#endif
-#endif
-
-
/* defined in bpy_util.c */
#if PY_VERSION_HEX < 0x03000000
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index a07c447c718..7b3a67ebff5 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -36,14 +36,6 @@
#include "BPY_extern.h"
-#include "../generic/bpy_internal_import.h" // our own imports
-/* external util modules */
-
-#include "../generic/Mathutils.h"
-#include "../generic/Geometry.h"
-#include "../generic/BGL.h"
-
-
void BPY_free_compiled_text( struct Text *text )
{
if( text->compiled ) {
@@ -64,19 +56,12 @@ static void bpy_init_modules( void )
PyModule_AddObject( mod, "data", BPY_rna_module() );
/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
PyModule_AddObject( mod, "types", BPY_rna_types() );
- PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "ops", BPY_operator_module() );
- PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
+ PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
/* add the module so we can import it */
PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
Py_DECREF(mod);
-
-
- /* stand alone utility modules not related to blender directly */
- Geometry_Init("Geometry");
- Mathutils_Init("Mathutils");
- BGL_Init("BGL");
}
#if (PY_VERSION_HEX < 0x02050000)
@@ -115,7 +100,6 @@ static PyObject *CreateGlobalDictionary( bContext *C )
{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
- {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
{NULL, NULL, 0, NULL}
};
@@ -132,81 +116,13 @@ static PyObject *CreateGlobalDictionary( bContext *C )
return dict;
}
-/* Use this so we can include our own python bundle */
-#if 0
-wchar_t* Py_GetPath(void)
-{
- int i;
- static wchar_t py_path[FILE_MAXDIR] = L"";
- char *dirname= BLI_gethome_folder("python");
- if(dirname) {
- i= mbstowcs(py_path, dirname, FILE_MAXDIR);
- printf("py path %s, %d\n", dirname, i);
- }
- return py_path;
-}
-#endif
-
-
-/* must be called before Py_Initialize */
-void BPY_start_python_path(void)
-{
- char *py_path_bundle= BLI_gethome_folder("python");
-
- if(py_path_bundle==NULL)
- return;
-
- /* set the environment path */
- printf("found bundled python: %s\n", py_path_bundle);
-
-#if (defined(WIN32) || defined(WIN64))
-#if defined(FREE_WINDOWS)
- {
- char py_path[FILE_MAXDIR + 11] = "";
- sprintf(py_path, "PYTHONPATH=%s", py_path_bundle);
- putenv(py_path);
- }
-#else
- _putenv_s("PYTHONPATH", py_path_bundle);
-#endif
-#else
-#ifdef __sgi
- {
- char py_path[FILE_MAXDIR + 11] = "";
- sprintf(py_path, "PYTHONPATH=%s", py_path_bundle);
- putenv(py_path);
- }
-#else
- setenv("PYTHONPATH", py_path_bundle, 1);
-#endif
-#endif
-
-}
-
-
void BPY_start_python( int argc, char **argv )
{
PyThreadState *py_tstate = NULL;
- BPY_start_python_path(); /* allow to use our own included python */
-
Py_Initialize( );
-#if (PY_VERSION_HEX < 0x03000000)
- PySys_SetArgv( argc, argv);
-#else
- /* sigh, why do python guys not have a char** version anymore? :( */
- {
- int i;
- PyObject *py_argv= PyList_New(argc);
-
- for (i=0; i<argc; i++)
- PyList_SET_ITEM(py_argv, i, PyUnicode_FromString(argv[i]));
-
- PySys_SetObject("argv", py_argv);
- Py_DECREF(py_argv);
- }
-#endif
+ //PySys_SetArgv( argc_copy, argv_copy );
/* Initialize thread support (also acquires lock) */
PyEval_InitThreads();
@@ -215,17 +131,10 @@ void BPY_start_python( int argc, char **argv )
/* bpy.* and lets us import it */
bpy_init_modules();
- { /* our own import and reload functions */
- PyObject *item;
- //PyObject *m = PyImport_AddModule("__builtin__");
- //PyObject *d = PyModule_GetDict(m);
- PyObject *d = PyEval_GetBuiltins( );
- PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL)); Py_DECREF(item);
- PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item);
- }
py_tstate = PyGILState_GetThisThreadState();
PyEval_ReleaseThread(py_tstate);
+
}
void BPY_end_python( void )
@@ -241,7 +150,7 @@ void BPY_end_python( void )
}
/* Can run a file or text block */
-int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
+int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
{
PyObject *py_dict, *py_result;
PyGILState_STATE gilstate;
@@ -255,7 +164,6 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
gilstate = PyGILState_Ensure();
BPY_update_modules(); /* can give really bad results if this isnt here */
- bpy_import_main_set(CTX_data_main(C));
py_dict = CreateGlobalDictionary(C);
@@ -270,7 +178,7 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
MEM_freeN( buf );
if( PyErr_Occurred( ) ) {
- BPy_errors_to_report(reports);
+ PyErr_Print(); PyErr_Clear();
BPY_free_compiled_text( text );
PyGILState_Release(gilstate);
return 0;
@@ -286,14 +194,13 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
}
if (!py_result) {
- BPy_errors_to_report(reports);
+ PyErr_Print(); PyErr_Clear();
} else {
Py_DECREF( py_result );
}
Py_DECREF(py_dict);
PyGILState_Release(gilstate);
- bpy_import_main_set(NULL);
//BPY_end_python();
return py_result ? 1:0;
@@ -314,7 +221,7 @@ static void exit_pydraw( SpaceScript * sc, short err )
script = sc->script;
if( err ) {
- BPy_errors_to_report(NULL); // TODO, reports
+ PyErr_Print(); PyErr_Clear();
script->flags = 0; /* mark script struct for deletion */
SCRIPT_SET_NULL(script);
script->scriptname[0] = '\0';
@@ -343,7 +250,7 @@ static int bpy_run_script_init(bContext *C, SpaceScript * sc)
return 0;
if (sc->script->py_draw==NULL && sc->script->scriptname[0] != '\0')
- BPY_run_python_script(C, sc->script->scriptname, NULL, NULL);
+ BPY_run_python_script(C, sc->script->scriptname, NULL);
if (sc->script->py_draw==NULL)
return 0;
@@ -351,9 +258,9 @@ static int bpy_run_script_init(bContext *C, SpaceScript * sc)
return 1;
}
-int BPY_run_script_space_draw(const struct bContext *C, SpaceScript * sc)
+int BPY_run_script_space_draw(struct bContext *C, SpaceScript * sc)
{
- if (bpy_run_script_init( (bContext *)C, sc)) {
+ if (bpy_run_script_init(C, sc)) {
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL );
@@ -422,7 +329,7 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
}
if (!py_result) {
- BPy_errors_to_report(NULL); // TODO - reports
+ PyErr_Print(); PyErr_Clear();
} else
Py_DECREF( py_result );
@@ -450,72 +357,69 @@ void BPY_run_ui_scripts(bContext *C, int reload)
DIR *dir;
struct dirent *de;
char *file_extension;
- char *dirname;
char path[FILE_MAX];
- char *dirs[] = {"io", "ui", NULL};
- int a;
+ char *dirname= BLI_gethome_folder("ui");
+ int filelen; /* filename length */
PyGILState_STATE gilstate;
PyObject *mod;
- PyObject *sys_path;
+ PyObject *sys_path_orig;
+ PyObject *sys_path_new;
+
+ if(!dirname)
+ return;
+
+ dir = opendir(dirname);
+ if(!dir)
+ return;
+
gilstate = PyGILState_Ensure();
+ /* backup sys.path */
+ sys_path_orig= PySys_GetObject("path");
+ Py_INCREF(sys_path_orig); /* dont free it */
+
+ sys_path_new= PyList_New(1);
+ PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
+ PySys_SetObject("path", sys_path_new);
+ Py_DECREF(sys_path_new);
+
// XXX - evil, need to access context
BPy_SetContext(C);
- bpy_import_main_set(CTX_data_main(C));
-
-
- sys_path= PySys_GetObject("path"); /* borrow */
- PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
-
- for(a=0; dirs[a]; a++) {
- dirname= BLI_gethome_folder(dirs[a]);
-
- if(!dirname)
- continue;
-
- dir = opendir(dirname);
-
- if(!dir)
- continue;
+
+ while((de = readdir(dir)) != NULL) {
+ /* We could stat the file but easier just to let python
+ * import it and complain if theres a problem */
- /* set the first dir in the sys.path for fast importing of modules */
- PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */
-
- while((de = readdir(dir)) != NULL) {
- /* We could stat the file but easier just to let python
- * import it and complain if theres a problem */
-
- file_extension = strstr(de->d_name, ".py");
+ file_extension = strstr(de->d_name, ".py");
+
+ if(file_extension && *(file_extension + 3) == '\0') {
+ filelen = strlen(de->d_name);
+ BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
- if(file_extension && file_extension[3] == '\0') {
- BLI_strncpy(path, de->d_name, (file_extension - de->d_name) + 1); /* cut off the .py on copy */
- mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
- if (mod) {
- if (reload) {
- PyObject *mod_orig= mod;
- mod= PyImport_ReloadModule(mod);
- Py_DECREF(mod_orig);
- }
- }
-
- if(mod) {
- Py_DECREF(mod); /* could be NULL from reloading */
- } else {
- BPy_errors_to_report(NULL);
- fprintf(stderr, "unable to import \"%s\" %s/%s\n", path, dirname, de->d_name);
+ mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
+ if (mod) {
+ if (reload) {
+ PyObject *mod_orig= mod;
+ mod= PyImport_ReloadModule(mod);
+ Py_DECREF(mod_orig);
}
-
+ }
+
+ if(mod) {
+ Py_DECREF(mod); /* could be NULL from reloading */
+ } else {
+ PyErr_Print(); PyErr_Clear();
+ fprintf(stderr, "unable to import \"%s\" %s/%s\n", path, dirname, de->d_name);
}
}
-
- closedir(dir);
}
-
- PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
- bpy_import_main_set(NULL);
+ closedir(dir);
+
+ PySys_SetObject("path", sys_path_orig);
+ Py_DECREF(sys_path_orig);
PyGILState_Release(gilstate);
#ifdef TIME_REGISTRATION
@@ -626,7 +530,7 @@ static float pydriver_error(ChannelDriver *driver)
driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression);
- BPy_errors_to_report(NULL); // TODO - reports
+ PyErr_Print(); PyErr_Clear();
return 0.0f;
}
@@ -685,7 +589,7 @@ float BPY_pydriver_eval (ChannelDriver *driver)
}
fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add variable '%s' to namespace \n", dtar->name);
- BPy_errors_to_report(NULL); // TODO - reports
+ PyErr_Print(); PyErr_Clear();
}
}
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index b57ef54304b..004cf2fb7c7 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -68,7 +68,7 @@ static PyObject *pyop_base_call( PyObject * self, PyObject * args, PyObject * k
return NULL;
}
- ot= WM_operatortype_find(opname, 1);
+ ot= WM_operatortype_find(opname);
if (ot == NULL) {
PyErr_Format( PyExc_SystemError, "Operator \"%s\"could not be found", opname);
return NULL;
@@ -130,18 +130,11 @@ static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname )
PyObject *ret;
wmOperatorType *ot;
- /* First look for the operator, then our own methods if that fails.
- * when methods are searched first, PyObject_GenericGetAttr will raise an error
- * each time we want to call an operator, we could clear the error but I prefer
- * not to since calling operators is a lot more common then adding and removing. - Campbell */
-
- if ((ot= WM_operatortype_find(name, 1))) {
+ if ((ot= WM_operatortype_find(name))) {
ret = PyCFunction_New( pyop_base_call_meth, pyname); /* set the name string as self, PyCFunction_New incref's self */
}
else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) {
- /* do nothing, this accounts for methoddef's add and remove
- * An exception is raised when PyObject_GenericGetAttr fails
- * but its ok because its overwritten below */
+ /* do nothing, this accounts for methoddef's add and remove */
}
else {
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name);
@@ -177,7 +170,7 @@ static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
char *name = _PyUnicode_AsString(pyname);
wmOperatorType *ot;
- if ((ot= WM_operatortype_find(name, 1))) {
+ if ((ot= WM_operatortype_find(name))) {
BPy_StructRNA *pyrna;
PointerRNA ptr;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index f8567414717..6ab990acdf5 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -40,13 +40,116 @@
#include "bpy_compat.h"
#include "bpy_util.h"
-#include "../generic/bpy_internal_import.h" // our own imports
-
#define PYOP_ATTR_PROP "__props__"
#define PYOP_ATTR_UINAME "__label__"
#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */
#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */
+static PyObject *pyop_dict_from_event(wmEvent *event)
+{
+ PyObject *dict= PyDict_New();
+ PyObject *item;
+ char *cstring, ascii[2];
+
+ /* type */
+ item= PyUnicode_FromString(WM_key_event_string(event->type));
+ PyDict_SetItemString(dict, "type", item); Py_DECREF(item);
+
+ /* val */
+ switch(event->val) {
+ case KM_ANY:
+ cstring = "ANY";
+ break;
+ case KM_RELEASE:
+ cstring = "RELEASE";
+ break;
+ case KM_PRESS:
+ cstring = "PRESS";
+ break;
+ default:
+ cstring = "UNKNOWN";
+ break;
+ }
+
+ item= PyUnicode_FromString(cstring);
+ PyDict_SetItemString(dict, "val", item); Py_DECREF(item);
+
+ /* x, y (mouse) */
+ item= PyLong_FromLong(event->x);
+ PyDict_SetItemString(dict, "x", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->y);
+ PyDict_SetItemString(dict, "y", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->prevx);
+ PyDict_SetItemString(dict, "prevx", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->prevy);
+ PyDict_SetItemString(dict, "prevy", item); Py_DECREF(item);
+
+ /* ascii */
+ ascii[0]= event->ascii;
+ ascii[1]= '\0';
+ item= PyUnicode_FromString(ascii);
+ PyDict_SetItemString(dict, "ascii", item); Py_DECREF(item);
+
+ /* modifier keys */
+ item= PyLong_FromLong(event->shift);
+ PyDict_SetItemString(dict, "shift", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->ctrl);
+ PyDict_SetItemString(dict, "ctrl", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->alt);
+ PyDict_SetItemString(dict, "alt", item); Py_DECREF(item);
+
+ item= PyLong_FromLong(event->oskey);
+ PyDict_SetItemString(dict, "oskey", item); Py_DECREF(item);
+
+
+
+ /* modifier */
+#if 0
+ item= PyTuple_New(0);
+ if(event->keymodifier & KM_SHIFT) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT"));
+ size++;
+ }
+ if(event->keymodifier & KM_CTRL) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL"));
+ size++;
+ }
+ if(event->keymodifier & KM_ALT) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT"));
+ size++;
+ }
+ if(event->keymodifier & KM_OSKEY) {
+ _PyTuple_Resize(&item, size+1);
+ PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY"));
+ size++;
+ }
+ PyDict_SetItemString(dict, "keymodifier", item); Py_DECREF(item);
+#endif
+
+ return dict;
+}
+
+/* TODO - a whole traceback would be ideal */
+static void pyop_error_report(ReportList *reports)
+{
+ PyObject *exception, *v, *tb;
+ PyErr_Fetch(&exception, &v, &tb);
+ if (exception == NULL)
+ return;
+ /* Now we know v != NULL too */
+ BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(v));
+
+ PyErr_Print();
+}
+
static struct BPY_flag_def pyop_ret_flags[] = {
{"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
{"CANCELLED", OPERATOR_CANCELLED},
@@ -87,13 +190,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PyObject *ret= NULL, *py_class_instance, *item= NULL;
int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
PointerRNA ptr_context;
- PointerRNA ptr_operator;
- PointerRNA ptr_event;
- PyObject *py_operator;
+ PyObject *py_context;
PyGILState_STATE gilstate = PyGILState_Ensure();
-
- bpy_import_main_set(CTX_data_main(C));
BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
@@ -107,9 +206,15 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
/* Assign instance attributes from operator properties */
{
+ PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
const char *arg_name;
- RNA_STRUCT_BEGIN(op->ptr, prop) {
+ iterprop= RNA_struct_iterator_property(op->ptr->type);
+ RNA_property_collection_begin(op->ptr, iterprop, &iter);
+
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
@@ -118,33 +223,23 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PyObject_SetAttrString(py_class_instance, arg_name, item);
Py_DECREF(item);
}
- RNA_STRUCT_END;
- }
-
- /* set operator pointer RNA as instance "__operator__" attribute */
- RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
- py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
- PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
- Py_DECREF(py_operator);
- RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
+ RNA_property_collection_end(&iter);
+ }
+
if (mode==PYOP_INVOKE) {
item= PyObject_GetAttrString(py_class, "invoke");
- args = PyTuple_New(3);
-
- RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event);
-
- // PyTuple_SET_ITEM "steals" object reference, it is
- // an object passed shouldn't be DECREF'ed
- PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
- PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event));
+ args = PyTuple_New(2);
+ PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
}
else if (mode==PYOP_EXEC) {
- item= PyObject_GetAttrString(py_class, "execute");
+ item= PyObject_GetAttrString(py_class, "exec");
args = PyTuple_New(2);
- PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
+ RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
+ py_context = pyrna_struct_CreatePyObject(&ptr_context);
+ PyTuple_SET_ITEM(args, 1, py_context);
}
else if (mode==PYOP_POLL) {
item= PyObject_GetAttrString(py_class, "poll");
@@ -161,13 +256,13 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
}
if (ret == NULL) { /* covers py_class_instance failing too */
- BPy_errors_to_report(op->reports);
+ pyop_error_report(op->reports);
}
else {
if (mode==PYOP_POLL) {
if (PyBool_Check(ret) == 0) {
PyErr_SetString(PyExc_ValueError, "Python poll function return value ");
- BPy_errors_to_report(op->reports);
+ pyop_error_report(op->reports);
}
else {
ret_flag= ret==Py_True ? 1:0;
@@ -175,9 +270,8 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
/* the returned value could not be converted into a flag */
- BPy_errors_to_report(op->reports);
-
- ret_flag = OPERATOR_CANCELLED;
+ pyop_error_report(op->reports);
+
}
/* there is no need to copy the py keyword dict modified by
* pyot->py_invoke(), back to the operator props since they are just
@@ -190,34 +284,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
Py_DECREF(ret);
}
- /* print operator return value */
- if (mode != PYOP_POLL) {
- char flag_str[100];
- char class_name[100];
- BPY_flag_def *flag_def = pyop_ret_flags;
-
- strcpy(flag_str, "");
-
- while(flag_def->name) {
- if (ret_flag & flag_def->flag) {
- if(flag_str[1])
- sprintf(flag_str, "%s | %s", flag_str, flag_def->name);
- else
- strcpy(flag_str, flag_def->name);
- }
- flag_def++;
- }
-
- /* get class name */
- item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
- Py_DECREF(item);
- strcpy(class_name, _PyUnicode_AsString(item));
-
- fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str);
- }
-
PyGILState_Release(gilstate);
- bpy_import_main_set(NULL);
return ret_flag;
}
@@ -267,7 +334,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
/* api callbacks, detailed checks dont on adding */
if (PyObject_HasAttrString(py_class, "invoke"))
ot->invoke= PYTHON_OT_invoke;
- if (PyObject_HasAttrString(py_class, "execute"))
+ if (PyObject_HasAttrString(py_class, "exec"))
ot->exec= PYTHON_OT_exec;
if (PyObject_HasAttrString(py_class, "poll"))
ot->poll= PYTHON_OT_poll;
@@ -320,7 +387,6 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
{
PyObject *base_class, *item;
- wmOperatorType *ot;
char *idname= NULL;
@@ -331,8 +397,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
{PYOP_ATTR_UINAME, 's', 0, BPY_CLASS_ATTR_OPTIONAL},
{PYOP_ATTR_PROP, 'l', 0, BPY_CLASS_ATTR_OPTIONAL},
{PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
- {"execute", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
- {"invoke", 'f', 3, BPY_CLASS_ATTR_OPTIONAL},
+ {"exec", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
+ {"invoke", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{"poll", 'f', 2, BPY_CLASS_ATTR_OPTIONAL},
{NULL, 0, 0, 0}
};
@@ -351,12 +417,9 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
Py_DECREF(item);
idname = _PyUnicode_AsString(item);
- /* remove if it already exists */
- if ((ot=WM_operatortype_exists(idname))) {
- if(ot->pyop_data) {
- Py_XDECREF((PyObject*)ot->pyop_data);
- }
- WM_operatortype_remove(idname);
+ if (WM_operatortype_find(idname)) {
+ PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname);
+ return NULL;
}
/* If we have properties set, check its a list of dicts */
@@ -403,7 +466,7 @@ PyObject *PYOP_wrap_remove(PyObject *self, PyObject *value)
return NULL;
}
- if (!(ot= WM_operatortype_exists(idname))) {
+ if (!(ot= WM_operatortype_find(idname))) {
PyErr_Format( PyExc_AttributeError, "Operator \"%s\" does not exists, cant remove", idname);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 9ce9ec8e838..9fa7d1b6693 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -35,102 +35,16 @@
#include "RNA_define.h" /* for defining our own rna */
#include "MEM_guardedalloc.h"
-#include "BKE_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h" /* evil G.* */
#include "BKE_report.h"
-/* only for keyframing */
-#include "DNA_scene_types.h"
-#include "ED_keyframing.h"
-
-#define USE_MATHUTILS
-
-#ifdef USE_MATHUTILS
-#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
-
-/* bpyrna vector/euler/quat callbacks */
-static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_rna_generic_check(BPy_PropertyRNA *self)
-{
- return self->prop?1:0;
-}
-
-static int mathutils_rna_vector_get(BPy_PropertyRNA *self, int subtype, float *vec_from)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_get_array(&self->ptr, self->prop, vec_from);
- return 1;
-}
-
-static int mathutils_rna_vector_set(BPy_PropertyRNA *self, int subtype, float *vec_to)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_array(&self->ptr, self->prop, vec_to);
- return 1;
-}
-
-static int mathutils_rna_vector_get_index(BPy_PropertyRNA *self, int subtype, float *vec_from, int index)
-{
- if(self->prop==NULL)
- return 0;
-
- vec_from[index]= RNA_property_float_get_index(&self->ptr, self->prop, index);
- return 1;
-}
-
-static int mathutils_rna_vector_set_index(BPy_PropertyRNA *self, int subtype, float *vec_to, int index)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_index(&self->ptr, self->prop, index, vec_to[index]);
- return 1;
-}
-
-Mathutils_Callback mathutils_rna_array_cb = {
- (BaseMathCheckFunc) mathutils_rna_generic_check,
- (BaseMathGetFunc) mathutils_rna_vector_get,
- (BaseMathSetFunc) mathutils_rna_vector_set,
- (BaseMathGetIndexFunc) mathutils_rna_vector_get_index,
- (BaseMathSetIndexFunc) mathutils_rna_vector_set_index
-};
-
-
-/* bpyrna matrix callbacks */
-static int mathutils_rna_matrix_cb_index= -1; /* index for our callbacks */
-
-static int mathutils_rna_matrix_get(BPy_PropertyRNA *self, int subtype, float *mat_from)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_get_array(&self->ptr, self->prop, mat_from);
- return 1;
-}
-
-static int mathutils_rna_matrix_set(BPy_PropertyRNA *self, int subtype, float *mat_to)
-{
- if(self->prop==NULL)
- return 0;
-
- RNA_property_float_set_array(&self->ptr, self->prop, mat_to);
- return 1;
-}
-
-Mathutils_Callback mathutils_rna_matrix_cb = {
- (BaseMathCheckFunc) mathutils_rna_generic_check,
- (BaseMathGetFunc) mathutils_rna_matrix_get,
- (BaseMathSetFunc) mathutils_rna_matrix_set,
- (BaseMathGetIndexFunc) NULL,
- (BaseMathSetIndexFunc) NULL
-};
-
+#if 0
+#define bpy_PyObject_New(type, typeobj) \
+( (type *) PyObject_Init( \
+ (PyObject *) MEM_callocN( _PyObject_SIZE(typeobj), "python memory from bpy_rna.c" ), (typeobj)) )
+#else
+#define bpy_PyObject_New(type, typeobj) PyObject_New(type, typeobj)
#endif
static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b )
@@ -167,39 +81,39 @@ static PyObject *pyrna_prop_richcmp(BPy_PropertyRNA * a, BPy_PropertyRNA * b, in
/*----------------------repr--------------------------------------------*/
static PyObject *pyrna_struct_repr( BPy_StructRNA * self )
{
- PyObject *pyob;
- char *name;
+ PropertyRNA *prop;
+ char str[512];
/* print name if available */
- name= RNA_struct_name_get_alloc(&self->ptr, NULL, 0);
- if(name) {
- pyob= PyUnicode_FromFormat( "[BPy_StructRNA \"%.200s\" -> \"%.200s\"]", RNA_struct_identifier(self->ptr.type), name);
- MEM_freeN(name);
- return pyob;
+ prop= RNA_struct_name_property(self->ptr.type);
+ if(prop) {
+ RNA_property_string_get(&self->ptr, prop, str);
+ return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), str);
}
- return PyUnicode_FromFormat( "[BPy_StructRNA \"%.200s\"]", RNA_struct_identifier(self->ptr.type));
+ return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\"]", RNA_struct_identifier(self->ptr.type));
}
static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self )
{
- PyObject *pyob;
+ PropertyRNA *prop;
PointerRNA ptr;
- char *name;
+ char str[512];
/* if a pointer, try to print name of pointer target too */
if(RNA_property_type(self->prop) == PROP_POINTER) {
ptr= RNA_property_pointer_get(&self->ptr, self->prop);
- name= RNA_struct_name_get_alloc(&ptr, NULL, 0);
- if(name) {
- pyob= PyUnicode_FromFormat( "[BPy_PropertyRNA \"%.200s\" -> \"%.200s\" -> \"%.200s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), name);
- MEM_freeN(name);
- return pyob;
+ if(ptr.data) {
+ prop= RNA_struct_name_property(ptr.type);
+ if(prop) {
+ RNA_property_string_get(&ptr, prop, str);
+ return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), str);
+ }
}
}
- return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%.200s\" -> \"%.200s\"]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop));
+ return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop));
}
static long pyrna_struct_hash( BPy_StructRNA * self )
@@ -210,35 +124,24 @@ static long pyrna_struct_hash( BPy_StructRNA * self )
/* use our own dealloc so we can free a property if we use one */
static void pyrna_struct_dealloc( BPy_StructRNA * self )
{
+ /* Note!! for some weired reason calling PyObject_DEL() directly crashes blender! */
if (self->freeptr && self->ptr.data) {
IDP_FreeProperty(self->ptr.data);
MEM_freeN(self->ptr.data);
self->ptr.data= NULL;
}
- /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */
Py_TYPE(self)->tp_free(self);
return;
}
static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
{
- EnumPropertyItem *item;
- char *result;
- int free= 0;
-
- RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free);
- if(item) {
- result= (char*)BPy_enum_as_string(item);
- }
- else {
- result= "";
- }
-
- if(free)
- MEM_freeN(item);
+ const EnumPropertyItem *item;
+ int totitem;
- return result;
+ RNA_property_enum_items(ptr, prop, &item, &totitem);
+ return (char*)BPy_enum_as_string((EnumPropertyItem*)item);
}
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
@@ -249,52 +152,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
if (len > 0) {
/* resolve the array from a new pytype */
- PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop);
-
-#ifdef USE_MATHUTILS
-
- /* return a mathutils vector where possible */
- if(RNA_property_type(prop)==PROP_FLOAT) {
- switch(RNA_property_subtype(prop)) {
- case PROP_VECTOR:
- if(len>=2 && len <= 4) {
- PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the vector owns now */
- ret= vec_cb; /* return the vector instead */
- }
- break;
- case PROP_MATRIX:
- if(len==16) {
- PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= mat_cb; /* return the matrix instead */
- }
- else if (len==9) {
- PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= mat_cb; /* return the matrix instead */
- }
- break;
- case PROP_ROTATION:
- if(len==3) { /* euler */
- PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= eul_cb; /* return the matrix instead */
- }
- else if (len==4) {
- PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, 0);
- Py_DECREF(ret); /* the matrix owns now */
- ret= quat_cb; /* return the matrix instead */
- }
- break;
- default:
- break;
- }
- }
-
-#endif
-
- return ret;
+ return pyrna_prop_CreatePyObject(ptr, prop);
}
/* see if we can coorce into a python type - PropertyType */
@@ -321,32 +179,11 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
const char *identifier;
int val = RNA_property_enum_get(ptr, prop);
- if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) {
+ if (RNA_property_enum_identifier(ptr, prop, val, &identifier)) {
ret = PyUnicode_FromString( identifier );
} else {
- EnumPropertyItem *item;
- int free= 0;
-
- /* don't throw error here, can't trust blender 100% to give the
- * right values, python code should not generate error for that */
- RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free);
- if(item && item->identifier) {
- ret = PyUnicode_FromString( item->identifier );
- }
- else {
- /* prefer not fail silently incase of api errors, maybe disable it later */
- char error_str[128];
- sprintf(error_str, "RNA Warning: Current value \"%d\" matches no enum", val);
- PyErr_Warn(PyExc_RuntimeWarning, error_str);
-
- ret = PyUnicode_FromString( "" );
- }
-
- if(free)
- MEM_freeN(item);
-
- /*PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
- ret = NULL;*/
+ PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
+ ret = NULL;
}
break;
@@ -384,15 +221,23 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
const char *arg_name= NULL;
PyObject *item;
+ PropertyRNA *prop, *iterprop;
+ CollectionPropertyIterator iter;
+
+ iterprop= RNA_struct_iterator_property(ptr->type);
+ RNA_property_collection_begin(ptr, iterprop, &iter);
+
totkw = kw ? PyDict_Size(kw):0;
- RNA_STRUCT_BEGIN(ptr, prop) {
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ prop= iter.ptr.data;
+
arg_name= RNA_property_identifier(prop);
if (strcmp(arg_name, "rna_type")==0) continue;
if (kw==NULL) {
- PyErr_Format( PyExc_AttributeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
+ PyErr_Format( PyExc_AttributeError, "%s: no keywords, expected \"%s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
error_val= -1;
break;
}
@@ -400,7 +245,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
item= PyDict_GetItemString(kw, arg_name);
if (item == NULL) {
- PyErr_Format( PyExc_AttributeError, "%.200s: keyword \"%.200s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
+ PyErr_Format( PyExc_AttributeError, "%s: keyword \"%s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
error_val = -1; /* pyrna_py_to_prop sets the error */
break;
}
@@ -412,7 +257,8 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
totkw--;
}
- RNA_STRUCT_END;
+
+ RNA_property_collection_end(&iter);
if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */
PyObject *key, *value;
@@ -424,7 +270,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
arg_name= NULL;
}
- PyErr_Format( PyExc_AttributeError, "%.200s: keyword \"%.200s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
+ PyErr_Format( PyExc_AttributeError, "%s: keyword \"%s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>");
error_val = -1;
}
@@ -433,15 +279,12 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi
static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw);
-PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func)
+PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func)
{
static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"};
PyObject *self= PyTuple_New(2);
PyObject *ret;
-
- PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna);
- Py_INCREF(pyrna);
-
+ PyTuple_SET_ITEM(self, 0, pyrna_struct_CreatePyObject(ptr));
PyTuple_SET_ITEM(self, 1, PyCObject_FromVoidPtr((void *)func, NULL));
ret= PyCFunction_New(&func_meth, self);
@@ -459,30 +302,15 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if (len > 0) {
PyObject *item;
- int py_len = -1;
int i;
-
-#ifdef USE_MATHUTILS
- if(MatrixObject_Check(value)) {
- MatrixObject *mat = (MatrixObject*)value;
- if(!BaseMath_ReadCallback(mat))
- return -1;
-
- py_len = mat->rowSize * mat->colSize;
- } else /* continue... */
-#endif
- if (PySequence_Check(value)) {
- py_len= (int)PySequence_Length(value);
- }
- else {
- PyErr_Format(PyExc_TypeError, "RNA array assignment expected a sequence instead of %.200s instance.", Py_TYPE(value)->tp_name);
+ if (!PySequence_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array.");
return -1;
}
- /* done getting the length */
- if (py_len != len) {
- PyErr_Format(PyExc_AttributeError, "python sequence length %d did not match the RNA array length %d.", py_len, len);
+ if ((int)PySequence_Length(value) != len) {
+ PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array.");
return -1;
}
@@ -548,21 +376,14 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
else param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array");
-#ifdef USE_MATHUTILS
- if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) {
- MatrixObject *mat = (MatrixObject*)value;
- memcpy(param_arr, mat->contigPtr, sizeof(float) * len);
- } else /* continue... */
-#endif
- {
- /* collect the variables */
- for (i=0; i<len; i++) {
- item = PySequence_GetItem(value, i);
- param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
- Py_DECREF(item);
- }
+
+ /* collect the variables */
+ for (i=0; i<len; i++) {
+ item = PySequence_GetItem(value, i);
+ param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
+ Py_DECREF(item);
}
-
+
if (PyErr_Occurred()) {
if(data==NULL)
MEM_freeN(param_arr);
@@ -637,17 +458,17 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if (param==NULL) {
char *enum_str= pyrna_enum_as_string(ptr, prop);
- PyErr_Format(PyExc_TypeError, "expected a string enum type in (%.200s)", enum_str);
+ PyErr_Format(PyExc_TypeError, "expected a string enum type in (%s)", enum_str);
MEM_freeN(enum_str);
return -1;
} else {
int val;
- if (RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, &val)) {
+ if (RNA_property_enum_value(ptr, prop, param, &val)) {
if(data) *((int*)data)= val;
else RNA_property_enum_set(ptr, prop, val);
} else {
char *enum_str= pyrna_enum_as_string(ptr, prop);
- PyErr_Format(PyExc_AttributeError, "enum \"%.200s\" not found in (%.200s)", param, enum_str);
+ PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found in (%s)", param, enum_str);
MEM_freeN(enum_str);
return -1;
}
@@ -662,15 +483,13 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if(!BPy_StructRNA_Check(value) && value != Py_None) {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %.200s type", RNA_struct_identifier(tmp.type));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
} else {
BPy_StructRNA *param= (BPy_StructRNA*)value;
int raise_error= 0;
if(data) {
- int flag = RNA_property_flag(prop);
-
- if(flag & PROP_RNAPTR) {
+ if(ptype == &RNA_AnyType) {
if(value == Py_None)
memset(data, 0, sizeof(PointerRNA));
else
@@ -699,7 +518,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
else {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %.200s type", RNA_struct_identifier(tmp.type));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
}
}
@@ -707,7 +526,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
if(raise_error) {
PointerRNA tmp;
RNA_pointer_create(NULL, ptype, NULL, &tmp);
- PyErr_Format(PyExc_TypeError, "expected a %.200s type", RNA_struct_identifier(tmp.type));
+ PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(tmp.type));
return -1;
}
}
@@ -718,10 +537,6 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
int seq_len, i;
PyObject *item;
PointerRNA itemptr;
- ListBase *lb;
- CollectionPointerLink *link;
-
- lb= (data)? (ListBase*)data: NULL;
/* convert a sequence of dict's into a collection */
if(!PySequence_Check(value)) {
@@ -737,15 +552,8 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
Py_XDECREF(item);
return -1;
}
-
- if(lb) {
- link= MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink");
- link->ptr= itemptr;
- BLI_addtail(lb, link);
- }
- else
- RNA_property_collection_add(ptr, prop, &itemptr);
-
+
+ RNA_property_collection_add(ptr, prop, &itemptr);
if(pyrna_pydict_to_props(&itemptr, item, "Converting a python list to an RNA collection")==-1) {
Py_DECREF(item);
return -1;
@@ -859,317 +667,117 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
return len;
}
-/* internal use only */
-static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynum)
-{
- PointerRNA newptr;
-
- if(keynum < 0) keynum += RNA_property_collection_length(&self->ptr, self->prop);
-
- if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr))
- return pyrna_struct_CreatePyObject(&newptr);
-
- PyErr_Format(PyExc_IndexError, "index %d out of range", keynum);
- return NULL;
-}
-static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum)
-{
- int len= RNA_property_array_length(self->prop);
-
- if(keynum < 0) keynum += len;
-
- if(keynum >= 0 && keynum < len)
- return pyrna_prop_to_py_index(&self->ptr, self->prop, keynum);
-
- PyErr_Format(PyExc_IndexError, "index %d out of range", keynum);
- return NULL;
-}
-
-static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *keyname)
-{
- PointerRNA newptr;
- if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr))
- return pyrna_struct_CreatePyObject(&newptr);
-
- PyErr_Format(PyExc_KeyError, "key \"%.200s\" not found", keyname);
- return NULL;
-}
-/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA * self, char *keyname) */
-
-
-
-
-#if PY_VERSION_HEX >= 0x03000000
-static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int start, int stop)
+static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
{
+ PyObject *ret;
PointerRNA newptr;
- PyObject *list = PyList_New(stop - start);
- int count;
-
- start = MIN2(start,stop); /* values are clamped from */
-
- for(count = start; count < stop; count++) {
- if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) {
- PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr));
- }
- else {
- Py_DECREF(list);
-
- PyErr_SetString(PyExc_RuntimeError, "error getting an rna struct from a collection");
- return NULL;
- }
- }
-
- return list;
-}
-static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, int stop)
-{
- PyObject *list = PyList_New(stop - start);
- int count;
-
- start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */
-
- for(count = start; count < stop; count++)
- PyList_SetItem(list, count - start, pyrna_prop_to_py_index(&self->ptr, self->prop, count));
-
- return list;
-}
-#endif
-
-static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key)
-{
+ int keynum = 0;
+ char *keyname = NULL;
+
if (PyUnicode_Check(key)) {
- return prop_subscript_collection_str(self, _PyUnicode_AsString(key));
- }
- else if (PyIndex_Check(key)) {
- Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
-
- return prop_subscript_collection_int(self, i);
- }
-#if PY_VERSION_HEX >= 0x03000000
- else if (PySlice_Check(key)) {
- int len= RNA_property_collection_length(&self->ptr, self->prop);
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
- return NULL;
-
- if (slicelength <= 0) {
- return PyList_New(0);
- }
- else if (step == 1) {
- return prop_subscript_collection_slice(self, start, stop);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
- return NULL;
- }
- }
-#endif
- else {
- PyErr_Format(PyExc_TypeError, "invalid rna key, key must be a string or an int instead of %.200s instance.", Py_TYPE(key)->tp_name);
- return NULL;
- }
-}
-
-static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key)
-{
- /*if (PyUnicode_Check(key)) {
- return prop_subscript_array_str(self, _PyUnicode_AsString(key));
- } else*/
- if (PyIndex_Check(key)) {
- Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- return prop_subscript_array_int(self, PyLong_AsSsize_t(key));
- }
-#if PY_VERSION_HEX >= 0x03000000
- else if (PySlice_Check(key)) {
- int len= RNA_property_array_length(self->prop);
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
- return NULL;
-
- if (slicelength <= 0) {
- return PyList_New(0);
- }
- else if (step == 1) {
- return prop_subscript_array_slice(self, start, stop);
- }
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
- return NULL;
- }
- }
-#endif
- else {
- PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
+ keyname = _PyUnicode_AsString(key);
+ } else if (PyLong_Check(key)) {
+ keynum = PyLong_AsSsize_t(key);
+ } else {
+ PyErr_SetString(PyExc_AttributeError, "invalid key, key must be a string or an int");
return NULL;
}
-}
-
-static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
-{
+
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
- return prop_subscript_collection(self, key);
- } else if (RNA_property_array_length(self->prop)) { /* arrays are currently fixed length, zero length means its not an array */
- return prop_subscript_array(self, key);
+ int ok;
+ if (keyname) ok = RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr);
+ else ok = RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr);
+
+ if (ok) {
+ ret = pyrna_struct_CreatePyObject(&newptr);
+ } else {
+ PyErr_SetString(PyExc_AttributeError, "out of range");
+ ret = NULL;
+ }
+
+ } else if (keyname) {
+ PyErr_SetString(PyExc_AttributeError, "string keys are only supported for collections");
+ ret = NULL;
} else {
- PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection");
- return NULL;
- }
-
-}
-
-#if PY_VERSION_HEX >= 0x03000000
-static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value)
-{
- int count;
-
- /* values are clamped from */
- begin = MIN2(begin,end);
-
- for(count = begin; count < end; count++) {
- if(pyrna_py_to_prop_index(&self->ptr, self->prop, count - begin, value) == -1) {
- /* TODO - this is wrong since some values have been assigned... will need to fix that */
- return -1; /* pyrna_struct_CreatePyObject should set the error */
+ int len = RNA_property_array_length(self->prop);
+
+ if (len==0) { /* not an array*/
+ PyErr_Format(PyExc_AttributeError, "not an array or collection %d", keynum);
+ ret = NULL;
+ }
+
+ if (keynum >= len){
+ PyErr_SetString(PyExc_AttributeError, "index out of range");
+ ret = NULL;
+ } else { /* not an array*/
+ ret = pyrna_prop_to_py_index(&self->ptr, self->prop, keynum);
}
}
-
- return 0;
+
+ return ret;
}
-#endif
-
-static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value)
-{
-
- int len= RNA_property_array_length(self->prop);
-
- if(keynum < 0) keynum += len;
- if(keynum >= 0 && keynum < len)
- return pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value);
- PyErr_SetString(PyExc_IndexError, "out of range");
- return -1;
-}
-
-static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value )
+static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value )
{
- /* char *keyname = NULL; */ /* not supported yet */
+ int ret = 0;
+ int keynum = 0;
+ char *keyname = NULL;
if (!RNA_property_editable(&self->ptr, self->prop)) {
- PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
+ PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
- /* maybe one day we can support this... */
- if (RNA_property_type(self->prop) == PROP_COLLECTION) {
- PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%.200s\" from \"%.200s\" is a collection, assignment not supported", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
+ if (PyUnicode_Check(key)) {
+ keyname = _PyUnicode_AsString(key);
+ } else if (PyLong_Check(key)) {
+ keynum = PyLong_AsSsize_t(key);
+ } else {
+ PyErr_SetString(PyExc_AttributeError, "PropertyRNA - invalid key, key must be a string or an int");
return -1;
}
-
- if (PyIndex_Check(key)) {
- Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
-
- return prop_subscript_ass_array_int(self, i, value);
- }
-#if PY_VERSION_HEX >= 0x03000000
- else if (PySlice_Check(key)) {
- int len= RNA_property_array_length(self->prop);
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
- return -1;
-
- if (slicelength <= 0) {
- return 0;
- }
- else if (step == 1) {
- return prop_subscript_ass_array_slice(self, start, stop, value);
+
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
+ PyErr_SetString(PyExc_AttributeError, "PropertyRNA - assignment is not supported for collections (yet)");
+ ret = -1;
+ } else if (keyname) {
+ PyErr_SetString(PyExc_AttributeError, "PropertyRNA - string keys are only supported for collections");
+ ret = -1;
+ } else {
+ int len = RNA_property_array_length(self->prop);
+
+ if (len==0) { /* not an array*/
+ PyErr_Format(PyExc_AttributeError, "PropertyRNA - not an array or collection %d", keynum);
+ ret = -1;
}
- else {
- PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
- return -1;
+
+ if (keynum >= len){
+ PyErr_SetString(PyExc_AttributeError, "PropertyRNA - index out of range");
+ ret = -1;
+ } else {
+ ret = pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value);
}
}
-#endif
- else {
- PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
- return -1;
- }
+
+ return ret;
}
+
static PyMappingMethods pyrna_prop_as_mapping = {
( lenfunc ) pyrna_prop_len, /* mp_length */
( binaryfunc ) pyrna_prop_subscript, /* mp_subscript */
- ( objobjargproc ) pyrna_prop_ass_subscript, /* mp_ass_subscript */
+ ( objobjargproc ) pyrna_prop_assign_subscript, /* mp_ass_subscript */
};
-static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value)
-{
- PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */
- char *keyname = _PyUnicode_AsString(value);
-
- if(keyname==NULL) {
- PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, key must be a string type");
- return -1;
- }
-
- if (RNA_property_type(self->prop) != PROP_COLLECTION) {
- PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, is only valid for collection types");
- return -1;
- }
-
-
- if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr))
- return 1;
-
- return 0;
-}
-
-static PySequenceMethods pyrna_prop_as_sequence = {
- NULL, /* Cant set the len otherwise it can evaluate as false */
- NULL, /* sq_concat */
- NULL, /* sq_repeat */
- NULL, /* sq_item */
- NULL, /* sq_slice */
- NULL, /* sq_ass_item */
- NULL, /* sq_ass_slice */
- (objobjproc)pyrna_prop_contains, /* sq_contains */
-};
-
-
-static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA * self, PyObject *args)
-{
- char *path;
- int index= 0;
- float cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
-
- if(!RNA_struct_is_ID(self->ptr.type)) {
- PyErr_SetString( PyExc_TypeError, "StructRNA - keyframe_insert only for ID type");
- return NULL;
- }
-
- if (!PyArg_ParseTuple(args, "s|if:keyframe_insert", &path, &index, &cfra))
- return NULL;
-
- return PyBool_FromLong( insert_keyframe((ID *)self->ptr.data, NULL, NULL, path, index, cfra, 0));
-}
-
-
static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
{
PyObject *ret, *dict;
PyObject *pystring;
/* for looping over attrs and funcs */
+ CollectionPropertyIterator iter;
PropertyRNA *iterprop;
/* Include this incase this instance is a subtype of a python class
@@ -1198,23 +806,26 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
/*
* Collect RNA attributes
*/
+ PropertyRNA *nameprop;
char name[256], *nameptr;
iterprop= RNA_struct_iterator_property(self->ptr.type);
+ RNA_property_collection_begin(&self->ptr, iterprop, &iter);
- RNA_PROP_BEGIN(&self->ptr, itemptr, iterprop) {
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
-
- if(nameptr) {
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
+
pystring = PyUnicode_FromString(nameptr);
PyList_Append(ret, pystring);
Py_DECREF(pystring);
- if(name != nameptr)
+ if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
+
}
@@ -1227,25 +838,15 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
RNA_pointer_create(NULL, &RNA_Struct, self->ptr.type, &tptr);
iterprop= RNA_struct_find_property(&tptr, "functions");
- RNA_PROP_BEGIN(&tptr, itemptr, iterprop) {
- pystring = PyUnicode_FromString(RNA_function_identifier(itemptr.data));
- PyList_Append(ret, pystring);
- Py_DECREF(pystring);
- }
- RNA_PROP_END;
- }
-
- if(self->ptr.type == &RNA_Context) {
- ListBase lb = CTX_data_dir_get(self->ptr.data);
- LinkData *link;
+ RNA_property_collection_begin(&tptr, iterprop, &iter);
- for(link=lb.first; link; link=link->next) {
- pystring = PyUnicode_FromString(link->data);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ pystring = PyUnicode_FromString(RNA_function_identifier(iter.ptr.data));
PyList_Append(ret, pystring);
Py_DECREF(pystring);
}
- BLI_freelistN(&lb);
+ RNA_property_collection_end(&iter);
}
return ret;
@@ -1274,7 +875,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
ret = pyrna_prop_to_py(&self->ptr, prop);
}
else if ((func = RNA_struct_find_function(&self->ptr, name))) {
- ret = pyrna_func_to_py(self, func);
+ ret = pyrna_func_to_py(&self->ptr, func);
}
else if (self->ptr.type == &RNA_Context) {
PointerRNA newptr;
@@ -1305,7 +906,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
BLI_freelistN(&newlb);
}
else {
- PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
+ PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%s\" not found", name);
ret = NULL;
}
@@ -1323,13 +924,13 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
return 0;
}
else {
- PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
+ PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%s\" not found", name);
return -1;
}
}
if (!RNA_property_editable(&self->ptr, prop)) {
- PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type) );
+ PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
@@ -1337,7 +938,7 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje
return pyrna_py_to_prop(&self->ptr, prop, NULL, value);
}
-static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
+PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
{
PyObject *ret;
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
@@ -1345,31 +946,34 @@ static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self)
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *nameprop;
char name[256], *nameptr;
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
-
- if(nameptr) {
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
+
/* add to python list */
item = PyUnicode_FromString( nameptr );
PyList_Append(ret, item);
Py_DECREF(item);
/* done */
- if(name != nameptr)
+ if ((char *)&name != nameptr)
MEM_freeN(nameptr);
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
}
return ret;
}
-static PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
+PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
{
PyObject *ret;
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
@@ -1377,315 +981,60 @@ static PyObject *pyrna_prop_items(BPy_PropertyRNA *self)
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *nameprop;
char name[256], *nameptr;
- int i= 0;
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- if(itemptr.data) {
- /* add to python list */
- item= PyTuple_New(2);
- nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name));
- if(nameptr) {
- PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr ));
- if(name != nameptr)
- MEM_freeN(nameptr);
- }
- else {
- PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */
- }
- PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr));
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
+ /* add to python list */
+ item = Py_BuildValue("(NN)", PyUnicode_FromString( nameptr ), pyrna_struct_CreatePyObject(&iter.ptr));
PyList_Append(ret, item);
Py_DECREF(item);
+ /* done */
- i++;
+ if ((char *)&name != nameptr)
+ MEM_freeN(nameptr);
}
}
- RNA_PROP_END;
+ RNA_property_collection_end(&iter);
}
return ret;
}
-static PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
+PyObject *pyrna_prop_values(BPy_PropertyRNA *self)
{
PyObject *ret;
-
if (RNA_property_type(self->prop) != PROP_COLLECTION) {
PyErr_SetString( PyExc_TypeError, "values() is only valid for collection types" );
ret = NULL;
} else {
PyObject *item;
+ CollectionPropertyIterator iter;
+ PropertyRNA *nameprop;
+
ret = PyList_New(0);
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- item = pyrna_struct_CreatePyObject(&itemptr);
- PyList_Append(ret, item);
- Py_DECREF(item);
- }
- RNA_PROP_END;
- }
-
- return ret;
-}
-
-static PyObject *pyrna_prop_get(BPy_PropertyRNA *self, PyObject *args)
-{
- PointerRNA newptr;
-
- char *key;
- PyObject* def = Py_None;
-
- if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
- return NULL;
-
- if(RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr))
- return pyrna_struct_CreatePyObject(&newptr);
-
- Py_INCREF(def);
- return def;
-}
-
-
-#if (PY_VERSION_HEX >= 0x03000000) /* foreach needs py3 */
-static void foreach_attr_type( BPy_PropertyRNA *self, char *attr,
- /* values to assign */
- RawPropertyType *raw_type, int *attr_tot, int *attr_signed )
-{
- PropertyRNA *prop;
- *raw_type= -1;
- *attr_tot= 0;
- *attr_signed= 0;
-
- RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
- prop = RNA_struct_find_property(&itemptr, attr);
- *raw_type= RNA_property_raw_type(prop);
- *attr_tot = RNA_property_array_length(prop);
- *attr_signed= (RNA_property_subtype(prop)==PROP_UNSIGNED) ? 0:1;
- break;
- }
- RNA_PROP_END;
-}
-
-/* pyrna_prop_foreach_get/set both use this */
-static int foreach_parse_args(
- BPy_PropertyRNA *self, PyObject *args,
-
- /*values to assign */
- char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed)
-{
-#if 0
- int array_tot;
- int target_tot;
-#endif
-
- *size= *raw_type= *attr_tot= *attr_signed= 0;
-
- if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) {
- PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" );
- return -1;
- }
-
- *tot= PySequence_Length(*seq); // TODO - buffer may not be a sequence! array.array() is tho.
-
- if(*tot>0) {
- foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed);
- *size= RNA_raw_type_sizeof(*raw_type);
-
-#if 0 // works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks
- if((*attr_tot) < 1)
- *attr_tot= 1;
-
- if (RNA_property_type(self->prop) == PROP_COLLECTION)
- array_tot = RNA_property_collection_length(&self->ptr, self->prop);
- else
- array_tot = RNA_property_array_length(self->prop);
-
-
- target_tot= array_tot * (*attr_tot);
-
- /* rna_access.c - rna_raw_access(...) uses this same method */
- if(target_tot != (*tot)) {
- PyErr_Format( PyExc_TypeError, "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", *tot, target_tot);
- return -1;
- }
-#endif
- }
-
- return 0;
-}
-
-static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format)
-{
- char f = format ? *format:'B'; /* B is assumed when not set */
-
- switch(raw_type) {
- case PROP_RAW_CHAR:
- if (attr_signed) return (f=='b') ? 1:0;
- else return (f=='B') ? 1:0;
- case PROP_RAW_SHORT:
- if (attr_signed) return (f=='h') ? 1:0;
- else return (f=='H') ? 1:0;
- case PROP_RAW_INT:
- if (attr_signed) return (f=='i') ? 1:0;
- else return (f=='I') ? 1:0;
- case PROP_RAW_FLOAT:
- return (f=='f') ? 1:0;
- case PROP_RAW_DOUBLE:
- return (f=='d') ? 1:0;
- }
-
- return 0;
-}
-
-static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
-{
- PyObject *item;
- int i=0, ok, buffer_is_compat;
- void *array= NULL;
-
- /* get/set both take the same args currently */
- char *attr;
- PyObject *seq;
- int tot, size, attr_tot, attr_signed;
- RawPropertyType raw_type;
-
- if(foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) < 0)
- return NULL;
-
- if(tot==0)
- Py_RETURN_NONE;
-
-
-
- if(set) { /* get the array from python */
- buffer_is_compat = 0;
- if(PyObject_CheckBuffer(seq)) {
- Py_buffer buf;
- PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
-
- /* check if the buffer matches */
-
- buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);
-
- if(buffer_is_compat) {
- ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot);
- }
-
- PyBuffer_Release(&buf);
- }
-
- /* could not use the buffer, fallback to sequence */
- if(!buffer_is_compat) {
- array= PyMem_Malloc(size * tot);
-
- for( ; i<tot; i++) {
- item= PySequence_GetItem(seq, i);
- switch(raw_type) {
- case PROP_RAW_CHAR:
- ((char *)array)[i]= (char)PyLong_AsSsize_t(item);
- break;
- case PROP_RAW_SHORT:
- ((short *)array)[i]= (short)PyLong_AsSsize_t(item);
- break;
- case PROP_RAW_INT:
- ((int *)array)[i]= (int)PyLong_AsSsize_t(item);
- break;
- case PROP_RAW_FLOAT:
- ((float *)array)[i]= (float)PyFloat_AsDouble(item);
- break;
- case PROP_RAW_DOUBLE:
- ((double *)array)[i]= (double)PyFloat_AsDouble(item);
- break;
- }
-
- Py_DECREF(item);
- }
-
- ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, array, raw_type, tot);
- }
- }
- else {
- buffer_is_compat = 0;
- if(PyObject_CheckBuffer(seq)) {
- Py_buffer buf;
- PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
-
- /* check if the buffer matches, TODO - signed/unsigned types */
-
- buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);
-
- if(buffer_is_compat) {
- ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot);
- }
-
- PyBuffer_Release(&buf);
- }
-
- /* could not use the buffer, fallback to sequence */
- if(!buffer_is_compat) {
- array= PyMem_Malloc(size * tot);
-
- ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, array, raw_type, tot);
-
- if(!ok) i= tot; /* skip the loop */
-
- for( ; i<tot; i++) {
-
- switch(raw_type) {
- case PROP_RAW_CHAR:
- item= PyLong_FromSsize_t( (Py_ssize_t) ((char *)array)[i] );
- break;
- case PROP_RAW_SHORT:
- item= PyLong_FromSsize_t( (Py_ssize_t) ((short *)array)[i] );
- break;
- case PROP_RAW_INT:
- item= PyLong_FromSsize_t( (Py_ssize_t) ((int *)array)[i] );
- break;
- case PROP_RAW_FLOAT:
- item= PyFloat_FromDouble( (double) ((float *)array)[i] );
- break;
- case PROP_RAW_DOUBLE:
- item= PyFloat_FromDouble( (double) ((double *)array)[i] );
- break;
- }
-
- PySequence_SetItem(seq, i, item);
+ RNA_property_collection_begin(&self->ptr, self->prop, &iter);
+ for(; iter.valid; RNA_property_collection_next(&iter)) {
+ if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
+ item = pyrna_struct_CreatePyObject(&iter.ptr);
+ PyList_Append(ret, item);
Py_DECREF(item);
}
}
+ RNA_property_collection_end(&iter);
}
-
- if(PyErr_Occurred()) {
- /* Maybe we could make our own error */
- PyErr_Print();
- PyErr_SetString(PyExc_SystemError, "could not access the py sequence");
- return NULL;
- }
- if (!ok) {
- PyErr_SetString(PyExc_SystemError, "internal error setting the array");
- return NULL;
- }
-
- if(array)
- PyMem_Free(array);
-
- Py_RETURN_NONE;
-}
-
-static PyObject *pyrna_prop_foreach_get(BPy_PropertyRNA *self, PyObject *args)
-{
- return foreach_getset(self, args, 0);
-}
-
-static PyObject *pyrna_prop_foreach_set(BPy_PropertyRNA *self, PyObject *args)
-{
- return foreach_getset(self, args, 1);
+
+ return ret;
}
-#endif /* #if (PY_VERSION_HEX >= 0x03000000) */
/* A bit of a kludge, make a list out of a collection or array,
* then return the lists iter function, not especially fast but convenient for now */
@@ -1721,26 +1070,14 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
}
static struct PyMethodDef pyrna_struct_methods[] = {
-
- /* maybe this become and ID function */
- {"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS, NULL},
-
- {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
+ {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, ""},
{NULL, NULL, 0, NULL}
};
static struct PyMethodDef pyrna_prop_methods[] = {
- {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, NULL},
- {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS,NULL},
- {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, NULL},
-
- {"get", (PyCFunction)pyrna_prop_get, METH_VARARGS, NULL},
-
-#if (PY_VERSION_HEX >= 0x03000000)
- /* array accessor function */
- {"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL},
- {"foreach_set", (PyCFunction)pyrna_prop_foreach_set, METH_VARARGS, NULL},
-#endif
+ {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, ""},
+ {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS, ""},
+ {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, ""},
{NULL, NULL, 0, NULL}
};
@@ -1834,17 +1171,11 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
const char *identifier;
int val = *(int*)data;
- if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) {
+ if (RNA_property_enum_identifier(ptr, prop, val, &identifier)) {
ret = PyUnicode_FromString( identifier );
} else {
- /* prefer not fail silently incase of api errors, maybe disable it later */
- char error_str[128];
- sprintf(error_str, "RNA Warning: Current value \"%d\" matches no enum", val);
- PyErr_Warn(PyExc_RuntimeWarning, error_str);
-
- ret = PyUnicode_FromString( "" );
- /*PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
- ret = NULL;*/
+ PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
+ ret = NULL;
}
break;
@@ -1853,9 +1184,8 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
{
PointerRNA newptr;
StructRNA *type= RNA_property_pointer_type(ptr, prop);
- int flag = RNA_property_flag(prop);
- if(flag & PROP_RNAPTR) {
+ if(type == &RNA_AnyType) {
/* in this case we get the full ptr */
newptr= *(PointerRNA*)data;
}
@@ -1873,21 +1203,10 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
break;
}
case PROP_COLLECTION:
- {
- ListBase *lb= (ListBase*)data;
- CollectionPointerLink *link;
- PyObject *linkptr;
-
- ret = PyList_New(0);
-
- for(link=lb->first; link; link=link->next) {
- linkptr= pyrna_struct_CreatePyObject(&link->ptr);
- PyList_Append(ret, linkptr);
- Py_DECREF(linkptr);
- }
-
+ /* XXX not supported yet
+ * ret = pyrna_prop_CreatePyObject(ptr, prop); */
+ ret = NULL;
break;
- }
default:
PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type);
ret = NULL;
@@ -1946,7 +1265,7 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
tid= RNA_struct_identifier(self_ptr->type);
fid= RNA_function_identifier(self_func);
- PyErr_Format(PyExc_AttributeError, "%.200s.%.200s(): required parameter \"%.200s\" not specified", tid, fid, pid);
+ PyErr_Format(PyExc_AttributeError, "%s.%s(): required parameter \"%s\" not specified", tid, fid, pid);
err= -1;
break;
}
@@ -1963,19 +1282,11 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw)
ret= NULL;
if (err==0) {
/* call function */
- ReportList reports;
- bContext *C= BPy_GetContext();
-
- BKE_reports_init(&reports, RPT_STORE);
- RNA_function_call(C, &reports, self_ptr, self_func, parms);
-
- err= (BPy_reports_to_error(&reports))? -1: 0;
- BKE_reports_clear(&reports);
+ RNA_function_call(self_ptr, self_func, parms);
/* return value */
- if(err==0)
- if(pret)
- ret= pyrna_param_to_py(&funcptr, pret, retdata);
+ if(pret)
+ ret= pyrna_param_to_py(&funcptr, pret, retdata);
}
/* cleanup */
@@ -2064,7 +1375,7 @@ PyTypeObject pyrna_struct_Type = {
NULL, /* allocfunc tp_alloc; */
pyrna_struct_new, /* newfunc tp_new; */
/* Low-level free-memory routine */
- NULL, /* freefunc tp_free; */
+ NULL, //MEM_freeN, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
@@ -2090,7 +1401,7 @@ PyTypeObject pyrna_prop_Type = {
sizeof( BPy_PropertyRNA ), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
+ NULL, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
@@ -2100,7 +1411,7 @@ PyTypeObject pyrna_prop_Type = {
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
- &pyrna_prop_as_sequence, /* PySequenceMethods *tp_as_sequence; */
+ NULL, /* PySequenceMethods *tp_as_sequence; */
&pyrna_prop_as_mapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
@@ -2150,7 +1461,7 @@ PyTypeObject pyrna_prop_Type = {
NULL, /* allocfunc tp_alloc; */
pyrna_prop_new, /* newfunc tp_new; */
/* Low-level free-memory routine */
- NULL, /* freefunc tp_free; */
+ NULL, //MEM_freeN, /* freefunc tp_free; */
/* For PyObject_IS_GC */
NULL, /* inquiry tp_is_gc; */
NULL, /* PyObject *tp_bases; */
@@ -2185,52 +1496,43 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
/* done with rna instance */
}
-PyObject* pyrna_srna_Subtype(StructRNA *srna)
+PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
{
PyObject *newclass = NULL;
+ PropertyRNA *nameprop;
- if (srna == NULL) {
+ if (ptr->type==NULL) {
newclass= NULL; /* Nothing to do */
- } else if ((newclass= RNA_struct_py_type_get(srna))) {
+ } else if ((newclass= RNA_struct_py_type_get(ptr->data))) {
Py_INCREF(newclass);
- } else {
- StructRNA *base;
-
+ } else if ((nameprop = RNA_struct_name_property(ptr->type))) {
/* for now, return the base RNA type rather then a real module */
- /* Assume RNA_struct_py_type_get(srna) was alredy checked */
+ /* Assume RNA_struct_py_type_get(ptr->data) was alredy checked */
/* subclass equivelents
- class myClass(myBase):
some='value' # or ...
- - myClass = type(name='myClass', bases=(myBase,), dict={'__module__':'bpy.types'})
+ - myClass = type(name='myClass', bases=(myBase,), dict={'some':'value'})
*/
- const char *descr= RNA_struct_ui_description(srna);
+ char name[256], *nameptr;
+ const char *descr= RNA_struct_ui_description(ptr->type);
PyObject *args = PyTuple_New(3);
PyObject *bases = PyTuple_New(1);
- PyObject *py_base= NULL;
PyObject *dict = PyDict_New();
PyObject *item;
-
+
+
+ nameptr= RNA_property_string_get_alloc(ptr, nameprop, name, sizeof(name));
// arg 1
//PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(tp_name));
- PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(RNA_struct_identifier(srna)));
+ PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(nameptr));
// arg 2
- base= RNA_struct_base(srna);
- if(base && base != srna) {
- /*/printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */
- py_base= pyrna_srna_Subtype(base);
- }
-
- if(py_base==NULL) {
- py_base= (PyObject *)&pyrna_struct_Type;
- Py_INCREF(py_base);
- }
-
- PyTuple_SET_ITEM(bases, 0, py_base);
+ PyTuple_SET_ITEM(bases, 0, (PyObject *)&pyrna_struct_Type);
+ Py_INCREF(&pyrna_struct_Type);
PyTuple_SET_ITEM(args, 1, bases);
@@ -2241,13 +1543,6 @@ PyObject* pyrna_srna_Subtype(StructRNA *srna)
Py_DECREF(item);
}
- /* this isnt needed however its confusing if we get python script names in blender types,
- * because the __module__ is used when printing the class */
- item= PyUnicode_FromString("bpy.types"); /* just to know its an internal type */
- PyDict_SetItemString(dict, "__module__", item);
- Py_DECREF(item);
-
-
PyTuple_SET_ITEM(args, 2, dict); // fill with useful subclass things!
if (PyErr_Occurred()) {
@@ -2258,25 +1553,16 @@ PyObject* pyrna_srna_Subtype(StructRNA *srna)
newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
Py_DECREF(args);
- if (newclass) {
- pyrna_subtype_set_rna(newclass, srna);
- // PyObSpit("NewStructRNA Type: ", (PyObject *)newclass);
- }
- else {
- /* this should not happen */
- PyErr_Print();
- PyErr_Clear();
- }
+ if (newclass)
+ pyrna_subtype_set_rna(newclass, ptr->data);
+
+ if (name != nameptr)
+ MEM_freeN(nameptr);
}
return newclass;
}
-PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
-{
- return pyrna_srna_Subtype((ptr->type == &RNA_Struct) ? ptr->data : ptr->type);
-}
-
/*-----------------------CreatePyObject---------------------------------*/
PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
{
@@ -2285,7 +1571,8 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
if (ptr->data==NULL && ptr->type==NULL) { /* Operator RNA has NULL data */
Py_RETURN_NONE;
}
- else {
+
+ if (ptr->type == &RNA_Struct) { /* always return a python subtype from rna struct types */
PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr);
if (tp) {
@@ -2293,10 +1580,13 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
}
else {
fprintf(stderr, "Could not make type\n");
- pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
+ pyrna = ( BPy_StructRNA * ) bpy_PyObject_New( BPy_StructRNA, &pyrna_struct_Type );
}
}
-
+ else {
+ pyrna = ( BPy_StructRNA * ) bpy_PyObject_New( BPy_StructRNA, &pyrna_struct_Type );
+ }
+
if( !pyrna ) {
PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_StructRNA object" );
return NULL;
@@ -2304,9 +1594,6 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
pyrna->ptr= *ptr;
pyrna->freeptr= 0;
-
- // PyObSpit("NewStructRNA: ", (PyObject *)pyrna);
-
return ( PyObject * ) pyrna;
}
@@ -2314,7 +1601,7 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop )
{
BPy_PropertyRNA *pyrna;
- pyrna = ( BPy_PropertyRNA * ) PyObject_NEW( BPy_PropertyRNA, &pyrna_prop_Type );
+ pyrna = ( BPy_PropertyRNA * ) bpy_PyObject_New( BPy_PropertyRNA, &pyrna_prop_Type );
if( !pyrna ) {
PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_rna object" );
@@ -2331,11 +1618,6 @@ PyObject *BPY_rna_module( void )
{
PointerRNA ptr;
-#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once.
- mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb);
- mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb);
-#endif
-
/* This can't be set in the pytype struct because some compilers complain */
pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr;
pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr;
@@ -2382,12 +1664,12 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyna
if (RNA_property_collection_lookup_string(&self->ptr, self->prop, _PyUnicode_AsString(pyname), &newptr)) {
ret= pyrna_struct_Subtype(&newptr);
if (ret==NULL) {
- PyErr_Format(PyExc_SystemError, "bpy.types.%.200s subtype could not be generated, this is a bug!", _PyUnicode_AsString(pyname));
+ PyErr_Format(PyExc_SystemError, "bpy.types.%s subtype could not be generated, this is a bug!", _PyUnicode_AsString(pyname));
}
return ret;
}
else { /* Override the error */
- PyErr_Format(PyExc_AttributeError, "bpy.types.%.200s not a valid RNA_Struct", _PyUnicode_AsString(pyname));
+ PyErr_Format(PyExc_AttributeError, "bpy.types.%s not a valid RNA_Struct", _PyUnicode_AsString(pyname));
return NULL;
}
}
@@ -2428,12 +1710,13 @@ PyObject *BPY_rna_types(void)
pyrna_basetype_Type.tp_getattro = ( getattrofunc )pyrna_basetype_getattro;
pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT;
pyrna_basetype_Type.tp_methods = pyrna_basetype_methods;
+ //pyrna_basetype_Type.tp_free = MEM_freeN;
if( PyType_Ready( &pyrna_basetype_Type ) < 0 )
return NULL;
}
- self= (BPy_BaseTypeRNA *)PyObject_NEW( BPy_BaseTypeRNA, &pyrna_basetype_Type );
+ self= (BPy_BaseTypeRNA *)bpy_PyObject_New( BPy_BaseTypeRNA, &pyrna_basetype_Type );
/* avoid doing this lookup for every getattr */
RNA_blender_rna_pointer_create(&self->ptr);
@@ -2442,44 +1725,7 @@ PyObject *BPY_rna_types(void)
return (PyObject *)self;
}
-static struct PyMethodDef props_methods[] = {
- {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
- {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
- {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
- {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
- {NULL, NULL, 0, NULL}
-};
-#if PY_VERSION_HEX >= 0x03000000
-static struct PyModuleDef props_module = {
- PyModuleDef_HEAD_INIT,
- "bpyprops",
- "",
- -1,/* multiple "initialization" just copies the module dict. */
- props_methods,
- NULL, NULL, NULL, NULL
-};
-#endif
-
-PyObject *BPY_rna_props( void )
-{
- PyObject *submodule, *mod;
-#if PY_VERSION_HEX >= 0x03000000
- submodule= PyModule_Create(&props_module);
-#else /* Py2.x */
- submodule= Py_InitModule3( "bpy.props", props_methods, "" );
-#endif
-
- mod = PyModule_New("props");
- PyModule_AddObject( submodule, "props", mod );
-
- /* INCREF since its its assumed that all these functions return the
- * module with a new ref like PyDict_New, since they are passed to
- * PyModule_AddObject which steals a ref */
- Py_INCREF(submodule);
-
- return submodule;
-}
/* Orphan functions, not sure where they should go */
@@ -2499,7 +1745,7 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
- if (self && PyCObject_Check(self)) {
+ if (self) {
StructRNA *srna = PyCObject_AsVoidPtr(self);
RNA_def_float(srna, id, def, min, max, name, description, soft_min, soft_max);
Py_RETURN_NONE;
@@ -2526,7 +1772,7 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
- if (self && PyCObject_Check(self)) {
+ if (self) {
StructRNA *srna = PyCObject_AsVoidPtr(self);
RNA_def_int(srna, id, def, min, max, name, description, soft_min, soft_max);
Py_RETURN_NONE;
@@ -2545,7 +1791,7 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
char *id, *name="", *description="";
int def=0;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def))
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:IntProperty", kwlist, &id, &name, &description, &def))
return NULL;
if (PyTuple_Size(args) > 0) {
@@ -2553,40 +1799,13 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
- if (self && PyCObject_Check(self)) {
+ if (self) {
StructRNA *srna = PyCObject_AsVoidPtr(self);
RNA_def_boolean(srna, id, def, name, description);
Py_RETURN_NONE;
} else {
PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_BoolProperty, NULL));
- PyTuple_SET_ITEM(ret, 1, kw);
- Py_INCREF(kw);
- return ret;
- }
-}
-
-PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
-{
- static char *kwlist[] = {"attr", "name", "description", "maxlen", "default", NULL};
- char *id, *name="", *description="", *def="";
- int maxlen=0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssis:StringProperty", kwlist, &id, &name, &description, &maxlen, &def))
- return NULL;
-
- if (PyTuple_Size(args) > 0) {
- PyErr_SetString(PyExc_ValueError, "all args must be keywors"); // TODO - py3 can enforce this.
- return NULL;
- }
-
- if (self && PyCObject_Check(self)) {
- StructRNA *srna = PyCObject_AsVoidPtr(self);
- RNA_def_string(srna, id, def, maxlen, name, description);
- Py_RETURN_NONE;
- } else {
- PyObject *ret = PyTuple_New(2);
- PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_StringProperty, NULL));
+ PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_IntProperty, NULL));
PyTuple_SET_ITEM(ret, 1, kw);
Py_INCREF(kw);
return ret;
@@ -2629,7 +1848,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
if (base_class) {
if (!PyObject_IsSubclass(py_class, base_class)) {
PyObject *name= PyObject_GetAttrString(base_class, "__name__");
- PyErr_Format( PyExc_AttributeError, "expected %.200s subclass of class \"%.200s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
+ PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
Py_XDECREF(name);
return -1;
}
@@ -2652,7 +1871,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
if (item==NULL) {
if ((flag & FUNC_REGISTER_OPTIONAL)==0) {
- PyErr_Format( PyExc_AttributeError, "expected %.200s class to have an \"%.200s\" attribute", class_type, RNA_function_identifier(func));
+ PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, RNA_function_identifier(func));
return -1;
}
@@ -2667,7 +1886,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
fitem= item; /* py 3.x */
if (PyFunction_Check(fitem)==0) {
- PyErr_Format( PyExc_AttributeError, "expected %.200s class \"%.200s\" attribute to be a function", class_type, RNA_function_identifier(func));
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, RNA_function_identifier(func));
return -1;
}
@@ -2679,7 +1898,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
Py_DECREF(py_arg_count);
if (arg_count != func_arg_count) {
- PyErr_Format( PyExc_AttributeError, "expected %.200s class \"%.200s\" function to have %d args", class_type, RNA_function_identifier(func), func_arg_count);
+ PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, RNA_function_identifier(func), func_arg_count);
return -1;
}
}
@@ -2711,7 +1930,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
}
if (item==NULL && (flag & PROP_REGISTER_OPTIONAL)==0) {
- PyErr_Format( PyExc_AttributeError, "expected %.200s class to have an \"%.200s\" attribute", class_type, identifier);
+ PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, identifier);
return -1;
}
@@ -2795,12 +2014,12 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
}
else {
Py_DECREF(py_class_instance);
- PyErr_Format(PyExc_AttributeError, "could not find function %.200s in %.200s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type));
+ PyErr_Format(PyExc_AttributeError, "could not find function %s in %s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type));
err= -1;
}
}
else {
- PyErr_Format(PyExc_AttributeError, "could not create instance of %.200s to call callback function %.200s.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func));
+ PyErr_Format(PyExc_AttributeError, "could not create instance of %s to call callback function %s.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func));
err= -1;
}
@@ -2875,7 +2094,7 @@ PyObject *pyrna_basetype_register(PyObject *self, PyObject *args)
C= BPy_GetContext();
/* call the register callback */
- BKE_reports_init(&reports, RPT_STORE);
+ BKE_reports_init(&reports, RPT_PRINT);
srna= reg(C, &reports, py_class, bpy_class_validate, bpy_class_call, bpy_class_free);
if(!srna) {
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index d2f01b06336..a2a3015912b 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -63,7 +63,6 @@ typedef struct {
PyObject *BPY_rna_module( void );
/*PyObject *BPY_rna_doc( void );*/
PyObject *BPY_rna_types( void );
-PyObject *BPY_rna_props( void );
PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr );
PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop );
@@ -77,7 +76,6 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw);
-PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw);
/* function for registering types */
PyObject *pyrna_basetype_register(PyObject *self, PyObject *args);
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
index 088fe436c69..c15315ca350 100644
--- a/source/blender/python/intern/bpy_ui.c
+++ b/source/blender/python/intern/bpy_ui.c
@@ -373,7 +373,7 @@ static struct PyMethodDef ui_methods[] = {
#if PY_VERSION_HEX >= 0x03000000
static struct PyModuleDef ui_module = {
PyModuleDef_HEAD_INIT,
- "bpy.ui",
+ "bpyui",
"",
-1,/* multiple "initialization" just copies the module dict. */
ui_methods,
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index b451923e780..c447e7de982 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -81,7 +81,6 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
char *cstring;
PyObject *item;
BPY_flag_def *fd;
- *flag = 0;
if (PySequence_Check(seq)) {
i= PySequence_Length(seq);
@@ -109,9 +108,6 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
error_val= 1;
}
- if (*flag == 0)
- error_val = 1;
-
if (error_val) {
char *buf = bpy_flag_error_str(flagdef);
PyErr_SetString(PyExc_AttributeError, buf);
@@ -171,13 +167,7 @@ void PyObSpit(char *name, PyObject *var) {
else {
PyObject_Print(var, stderr, 0);
fprintf(stderr, " ref:%d ", var->ob_refcnt);
- fprintf(stderr, " ptr:%p", (void *)var);
-
- fprintf(stderr, " type:");
- if(Py_TYPE(var))
- fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
- else
- fprintf(stderr, "<NIL>");
+ fprintf(stderr, " ptr:%ld", (long)var);
}
fprintf(stderr, "\n");
}
@@ -339,81 +329,6 @@ int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_c
return 0;
}
-
-
-/* returns the exception string as a new PyUnicode object, depends on external StringIO module */
-PyObject *BPY_exception_buffer(void)
-{
- PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
- PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
- PyObject *string_io = NULL;
- PyObject *string_io_buf = NULL;
- PyObject *string_io_mod= NULL;
- PyObject *string_io_getvalue= NULL;
-
- PyObject *error_type, *error_value, *error_traceback;
-
- if (!PyErr_Occurred())
- return NULL;
-
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- PyErr_Clear();
-
- /* import StringIO / io
- * string_io = StringIO.StringIO()
- */
-
-#if PY_VERSION_HEX < 0x03000000
- if(! (string_io_mod= PyImport_ImportModule("StringIO")) ) {
-#else
- if(! (string_io_mod= PyImport_ImportModule("io")) ) {
-#endif
- goto error_cleanup;
- } else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
- goto error_cleanup;
- } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
- goto error_cleanup;
- }
-
- Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
- Py_INCREF(stderr_backup);
-
- PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
- PySys_SetObject("stderr", string_io);
-
- PyErr_Restore(error_type, error_value, error_traceback);
- PyErr_Print(); /* print the error */
- PyErr_Clear();
-
- string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
-
- PySys_SetObject("stdout", stdout_backup);
- PySys_SetObject("stderr", stderr_backup);
-
- Py_DECREF(stdout_backup); /* now sys owns the ref again */
- Py_DECREF(stderr_backup);
-
- Py_DECREF(string_io_mod);
- Py_DECREF(string_io_getvalue);
- Py_DECREF(string_io); /* free the original reference */
-
- PyErr_Clear();
- return string_io_buf;
-
-
-error_cleanup:
- /* could not import the module so print the error and close */
- Py_XDECREF(string_io_mod);
- Py_XDECREF(string_io);
-
- PyErr_Restore(error_type, error_value, error_traceback);
- PyErr_Print(); /* print the error */
- PyErr_Clear();
-
- return NULL;
-}
-
char *BPy_enum_as_string(EnumPropertyItem *item)
{
DynStr *dynstr= BLI_dynstr_new();
@@ -421,8 +336,7 @@ char *BPy_enum_as_string(EnumPropertyItem *item)
char *cstring;
for (e= item; item->identifier; item++) {
- if(item->identifier[0])
- BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
+ BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
}
cstring = BLI_dynstr_get_cstring(dynstr);
@@ -444,33 +358,3 @@ int BPy_reports_to_error(ReportList *reports)
return (report_str != NULL);
}
-
-int BPy_errors_to_report(ReportList *reports)
-{
- PyObject *pystring;
- char *cstring;
-
- if (!PyErr_Occurred())
- return 1;
-
- /* less hassle if we allow NULL */
- if(reports==NULL) {
- PyErr_Print();
- PyErr_Clear();
- return 1;
- }
-
- pystring= BPY_exception_buffer();
-
- if(pystring==NULL) {
- BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
- return 0;
- }
-
- cstring= _PyUnicode_AsString(pystring);
-
- BKE_report(reports, RPT_ERROR, cstring);
- fprintf(stderr, "%s\n", cstring); // not exactly needed. just for testing
- Py_DECREF(pystring);
- return 1;
-}
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index 6429af67eb0..49f48802249 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -47,8 +47,6 @@ void PyObSpit(char *name, PyObject *var);
void PyLineSpit(void);
void BPY_getFileAndNum(char **filename, int *lineno);
-PyObject *BPY_exception_buffer(void);
-
/* own python like utility function */
PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
@@ -75,7 +73,6 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item);
/* error reporting */
int BPy_reports_to_error(struct ReportList *reports);
-int BPy_errors_to_report(struct ReportList *reports);
/* TODO - find a better solution! */
struct bContext *BPy_GetContext(void);
diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c
index 40a991ad702..496ac529406 100644
--- a/source/blender/readblenfile/intern/BLO_readblenfile.c
+++ b/source/blender/readblenfile/intern/BLO_readblenfile.c
@@ -170,4 +170,3 @@ cleanup:
return bfd;
}
-
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 65942a14be9..a047dc63829 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1439,7 +1439,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
if(sd->uvco && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
for(i=0; i<sd->totuv; i++) {
if(num != DMCACHE_NOTFOUND) {
- MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+ MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
mtface += num;
@@ -1456,7 +1456,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
if(sd->mcol && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
for(i=0; i<sd->totcol; i++) {
if(num != DMCACHE_NOTFOUND) {
- MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+ MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
mc += num * 4;
@@ -1671,8 +1671,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(ma->amb != 0.0f)
dosurfacecache= 1;
- totface= psmd->dm->getNumFaces(psmd->dm);
- origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
+ totface= psmd->dm->getNumTessFaces(psmd->dm);
+ origindex= psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX);
if(origindex) {
for(a=0; a<totface; a++)
strandbuf->totbound= MAX2(strandbuf->totbound, origindex[a]);
@@ -1732,7 +1732,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
num= pa->num_dmcache;
if(num == DMCACHE_NOTFOUND)
- if(pa->num < psmd->dm->getNumFaces(psmd->dm))
+ if(pa->num < psmd->dm->getNumTessFaces(psmd->dm))
num= pa->num;
get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
@@ -1807,7 +1807,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
num = parent->num_dmcache;
if(num == DMCACHE_NOTFOUND)
- if(parent->num < psmd->dm->getNumFaces(psmd->dm))
+ if(parent->num < psmd->dm->getNumTessFaces(psmd->dm))
num = parent->num;
get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
@@ -2889,10 +2889,10 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
unsigned int *mcol=NULL;
int a, totedge=0, totface;
- mface= dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
- tface= dm->getFaceDataArray(dm, CD_MTFACE);
- mcol= dm->getFaceDataArray(dm, CD_MCOL);
+ mface= dm->getTessFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
+ tface= dm->getTessFaceDataArray(dm, CD_MTFACE);
+ mcol= dm->getTessFaceDataArray(dm, CD_MCOL);
if(mcol==NULL && tface==NULL) return NULL;
@@ -3068,7 +3068,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
totvert= dm->getNumVerts(dm);
/* attempt to autsmooth on original mesh, only without subsurf */
- if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumFaces(dm))
+ if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumTessFaces(dm))
use_original_normals= 1;
ms = (totvert==me->totvert)?me->msticky:NULL;
@@ -3129,8 +3129,8 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
}
if(ok) {
- end= dm->getNumFaces(dm);
- mface= dm->getFaceArray(dm);
+ end= dm->getNumTessFaces(dm);
+ mface= dm->getTessFaceArray(dm);
for(a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 130cda9f107..f67826a9806 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -377,25 +377,6 @@ void renderspothalo(ShadeInput *shi, float *col, float alpha)
/* ---------------- shaders ----------------------- */
-static double Normalize_d(double *n)
-{
- double d;
-
- d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
-
- if(d>0.00000000000000001) {
- d= sqrt(d);
-
- n[0]/=d;
- n[1]/=d;
- n[2]/=d;
- } else {
- n[0]=n[1]=n[2]= 0.0;
- d= 0.0;
- }
- return d;
-}
-
/* mix of 'real' fresnel and allowing control. grad defines blending gradient */
float fresnel_fac(float *view, float *vn, float grad, float fac)
{
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 3c8c1640b75..fc52f0fc9f4 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -943,7 +943,7 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm,
int a, totvert, totface;
totvert= dm->getNumVerts(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(mesh=re->strandsurface.first; mesh; mesh=mesh->next)
if(mesh->obr.ob == obr->ob && mesh->obr.par == obr->par
@@ -975,7 +975,7 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm,
Mat4MulVecfl(mat, co[a]);
}
- mface= dm->getFaceArray(dm);
+ mface= dm->getTessFaceArray(dm);
for(a=0; a<mesh->totface; a++, mface++) {
mesh->face[a][0]= mface->v1;
mesh->face[a][1]= mface->v2;
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 177f261e40b..084e3472ebd 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -736,16 +736,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
- MFace *mface = dm->getFaceArray(dm);
- MTFace *tface = static_cast<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE));
- MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL));
+ MFace *mface = dm->getTessFaceArray(dm);
+ MTFace *tface = static_cast<MTFace*>(dm->getTessFaceDataArray(dm, CD_MTFACE));
+ MCol *mcol = static_cast<MCol*>(dm->getTessFaceDataArray(dm, CD_MCOL));
float (*tangent)[3] = NULL;
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
const char *tfaceName = "";
if(tface) {
DM_add_tangent_layer(dm);
- tangent = (float(*)[3])dm->getFaceDataArray(dm, CD_TANGENT);
+ tangent = (float(*)[3])dm->getTessFaceDataArray(dm, CD_TANGENT);
}
// Determine if we need to make a skinned mesh
diff --git a/source/gameengine/PyDoc/Makefile b/source/gameengine/PyDoc/Makefile
new file mode 100644
index 00000000000..7861894ddec
--- /dev/null
+++ b/source/gameengine/PyDoc/Makefile
@@ -0,0 +1,13 @@
+
+
+SOURCES=$(shell ls *.py)
+TARGETS:=$(SOURCES:.py=.html)
+PYDOC=/usr/lib/python2.2/pydoc.py
+
+all: $(SOURCES)
+ epydoc -o BPY_GE_236 --url "http://www.blender.org" -t GameLogic.py \
+ -n "Blender GameEngine" --no-private --no-frames \
+ $(shell ls *.py )
+
+clean:
+ rm *.html
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h
new file mode 100644
index 00000000000..a2f27ce3361
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/ARB_multitexture.h
@@ -0,0 +1,150 @@
+#ifndef __ARB_MULTITEXTURE_H__
+#define __ARB_MULTITEXTURE_H__
+
+/*
+*/
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_multitexture
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_multitexture
+ #define GL_TEXTURE0_ARB 0x84C0
+ #define GL_TEXTURE1_ARB 0x84C1
+ #define GL_TEXTURE2_ARB 0x84C2
+ #define GL_TEXTURE3_ARB 0x84C3
+ #define GL_TEXTURE4_ARB 0x84C4
+ #define GL_TEXTURE5_ARB 0x84C5
+ #define GL_TEXTURE6_ARB 0x84C6
+ #define GL_TEXTURE7_ARB 0x84C7
+ #define GL_TEXTURE8_ARB 0x84C8
+ #define GL_TEXTURE9_ARB 0x84C9
+ #define GL_TEXTURE10_ARB 0x84CA
+ #define GL_ACTIVE_TEXTURE_ARB 0x84E0
+ #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+ #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+#endif
+
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_texture_env_combine
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_texture_env_combine
+ #define GL_COMBINE_ARB 0x8570
+ #define GL_COMBINE_RGB_ARB 0x8571
+ #define GL_COMBINE_ALPHA_ARB 0x8572
+ #define GL_SOURCE0_RGB_ARB 0x8580
+ #define GL_SOURCE1_RGB_ARB 0x8581
+ #define GL_SOURCE2_RGB_ARB 0x8582
+ #define GL_SOURCE0_ALPHA_ARB 0x8588
+ #define GL_SOURCE1_ALPHA_ARB 0x8589
+ #define GL_SOURCE2_ALPHA_ARB 0x858A
+ #define GL_OPERAND0_RGB_ARB 0x8590
+ #define GL_OPERAND1_RGB_ARB 0x8591
+ #define GL_OPERAND2_RGB_ARB 0x8592
+ #define GL_OPERAND0_ALPHA_ARB 0x8598
+ #define GL_OPERAND1_ALPHA_ARB 0x8599
+ #define GL_OPERAND2_ALPHA_ARB 0x859A
+ #define GL_RGB_SCALE_ARB 0x8573
+ #define GL_ADD_SIGNED_ARB 0x8574
+ #define GL_INTERPOLATE_ARB 0x8575
+ #define GL_SUBTRACT_ARB 0x84E7
+ #define GL_CONSTANT_ARB 0x8576
+ #define GL_PRIMARY_COLOR_ARB 0x8577
+ #define GL_PREVIOUS_ARB 0x8578
+#endif
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_texture_cube_map
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_texture_cube_map
+ #define GL_NORMAL_MAP_ARB 0x8511
+ #define GL_REFLECTION_MAP_ARB 0x8512
+ #define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+ #define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+ #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+ #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+ #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+ #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+ #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+ #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+ #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+ #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_shader_objects
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_shader_objects
+ #define GL_PROGRAM_OBJECT_ARB 0x8B40
+ #define GL_SHADER_OBJECT_ARB 0x8B48
+ #define GL_OBJECT_TYPE_ARB 0x8B4E
+ #define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+ #define GL_FLOAT_VEC2_ARB 0x8B50
+ #define GL_FLOAT_VEC3_ARB 0x8B51
+ #define GL_FLOAT_VEC4_ARB 0x8B52
+ #define GL_INT_VEC2_ARB 0x8B53
+ #define GL_INT_VEC3_ARB 0x8B54
+ #define GL_INT_VEC4_ARB 0x8B55
+ #define GL_BOOL_ARB 0x8B56
+ #define GL_BOOL_VEC2_ARB 0x8B57
+ #define GL_BOOL_VEC3_ARB 0x8B58
+ #define GL_BOOL_VEC4_ARB 0x8B59
+ #define GL_FLOAT_MAT2_ARB 0x8B5A
+ #define GL_FLOAT_MAT3_ARB 0x8B5B
+ #define GL_FLOAT_MAT4_ARB 0x8B5C
+ #define GL_SAMPLER_1D_ARB 0x8B5D
+ #define GL_SAMPLER_2D_ARB 0x8B5E
+ #define GL_SAMPLER_3D_ARB 0x8B5F
+ #define GL_SAMPLER_CUBE_ARB 0x8B60
+ #define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+ #define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+ #define GL_SAMPLER_2D_RECT_ARB 0x8B63
+ #define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+ #define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+ #define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+ #define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+ #define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+ #define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+ #define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+ #define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+ #define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+ #define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#endif
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_vertex_shader
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_vertex_shader
+ #define GL_VERTEX_SHADER_ARB 0x8B31
+ #define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+ #define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+ #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+ #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+ #define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+ #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#endif
+
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_fragment_shader
+---------------------------------------------------------------------------- */
+#ifdef GL_ARB_fragment_shader
+ #define GL_FRAGMENT_SHADER_ARB 0x8B30
+ #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+ #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif
+
+
+/* ----------------------------------------------------------------------------
+ GL_ARB_depth_texture
+---------------------------------------------------------------------------- */
+#ifndef GL_ARB_depth_texture
+ #define GL_DEPTH_COMPONENT16_ARB 0x81A5
+ #define GL_DEPTH_COMPONENT24_ARB 0x81A6
+ #define GL_DEPTH_COMPONENT32_ARB 0x81A7
+ #define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+ #define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif
+
+
+#endif//__ARB_MULTITEXTURE_H__
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/EXT_separate_specular_color.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/EXT_separate_specular_color.h
new file mode 100644
index 00000000000..5a9d8f32a87
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/EXT_separate_specular_color.h
@@ -0,0 +1,12 @@
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#endif
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/glext.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/glext.h
new file mode 100644
index 00000000000..7bb8e6e7cc7
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/glext.h
@@ -0,0 +1,6495 @@
+#ifndef __glext_h_
+#define __glext_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: This software was created using the
+** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
+** not been independently verified as being compliant with the OpenGL(R)
+** version 1.2.1 Specification.
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+/*************************************************************/
+
+/* Header file version number, required by OpenGL ABI for Linux */
+/* glext.h last updated 2005/06/20 */
+/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */
+#define GL_GLEXT_VERSION 29
+
+#ifndef GL_VERSION_1_2
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#endif
+
+#ifndef GL_ARB_imaging
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+#define GL_FUNC_ADD 0x8006
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BLEND_EQUATION 0x8009
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD GL_FOG_COORDINATE
+#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC0_RGB GL_SOURCE0_RGB
+#define GL_SRC1_RGB GL_SOURCE1_RGB
+#define GL_SRC2_RGB GL_SOURCE2_RGB
+#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
+#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif
+
+#ifndef GL_ARB_window_pos
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_HALF_FLOAT_ARB 0x140B
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_ABGR_EXT 0x8000
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_FILTER4_SGIS 0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+#endif
+
+#ifndef GL_EXT_subtexture
+#endif
+
+#ifndef GL_EXT_copy_texture
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+#define GL_TABLE_TOO_LARGE_EXT 0x8031
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+#endif
+
+#ifndef GL_SGI_color_matrix
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_PIXEL_TEXTURE_SGIS 0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define GL_TEXTURE_4D_SGIS 0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS 0x814F
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS 0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_RESCALE_NORMAL_EXT 0x803A
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_BLEND_EQUATION_EXT 0x8009
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_INTERLACE_SGIX 0x8094
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#endif
+
+#ifndef GL_SGIS_texture_select
+#define GL_DUAL_ALPHA4_SGIS 0x8110
+#define GL_DUAL_ALPHA8_SGIS 0x8111
+#define GL_DUAL_ALPHA12_SGIS 0x8112
+#define GL_DUAL_ALPHA16_SGIS 0x8113
+#define GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define GL_DUAL_INTENSITY4_SGIS 0x8118
+#define GL_DUAL_INTENSITY8_SGIS 0x8119
+#define GL_DUAL_INTENSITY12_SGIS 0x811A
+#define GL_DUAL_INTENSITY16_SGIS 0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define GL_QUAD_ALPHA4_SGIS 0x811E
+#define GL_QUAD_ALPHA8_SGIS 0x811F
+#define GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define GL_QUAD_INTENSITY4_SGIS 0x8122
+#define GL_QUAD_INTENSITY8_SGIS 0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SPRITE_SGIX 0x8148
+#define GL_SPRITE_MODE_SGIX 0x8149
+#define GL_SPRITE_AXIS_SGIX 0x814A
+#define GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define GL_SPRITE_AXIAL_SGIX 0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_POINT_SIZE_MIN_SGIS 0x8126
+#define GL_POINT_SIZE_MAX_SGIS 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS 0x8129
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_FRAMEZOOM_SGIX 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#endif
+
+#ifndef GL_FfdMaskSGIX
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_REFERENCE_PLANE_SGIX 0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_FOG_FUNC_SGIS 0x812A
+#define GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_IMAGE_SCALE_X_HP 0x8155
+#define GL_IMAGE_SCALE_Y_HP 0x8156
+#define GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define GL_IMAGE_MAG_FILTER_HP 0x815C
+#define GL_IMAGE_MIN_FILTER_HP 0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define GL_CUBIC_HP 0x815F
+#define GL_AVERAGE_HP 0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_IGNORE_BORDER_HP 0x8150
+#define GL_CONSTANT_BORDER_HP 0x8151
+#define GL_REPLICATE_BORDER_HP 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#endif
+
+#ifndef GL_INGR_palette_buffer
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#endif
+
+#ifndef GL_EXT_color_subtable
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define GL_CLIP_FAR_HINT_PGI 0x1A221
+#define GL_WIDE_LINE_HINT_PGI 0x1A222
+#define GL_BACK_NORMALS_HINT_PGI 0x1A223
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_LIST_PRIORITY_SGIX 0x8182
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_IR_INSTRUMENT1_SGIX 0x817F
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+#endif
+
+#ifndef GL_EXT_index_texture
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_INDEX_MATERIAL_EXT 0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_INDEX_TEST_EXT 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define GL_INDEX_TEST_REF_EXT 0x81B7
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_IUI_V2F_EXT 0x81AD
+#define GL_IUI_V3F_EXT 0x81AE
+#define GL_IUI_N3F_V2F_EXT 0x81AF
+#define GL_IUI_N3F_V3F_EXT 0x81B0
+#define GL_T2F_IUI_V2F_EXT 0x81B1
+#define GL_T2F_IUI_V3F_EXT 0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_YCRCB_422_SGIX 0x81BB
+#define GL_YCRCB_444_SGIX 0x81BC
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX 0x8413
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+/* reuse GL_FRAGMENT_DEPTH_EXT */
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+#endif
+
+#ifndef GL_SGIX_impact_pixel_texture
+#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184
+#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185
+#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186
+#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187
+#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188
+#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189
+#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_ASYNC_MARKER_SGIX 0x8329
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#endif
+
+#ifndef GL_INTEL_texture_scissor
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_FOG_SCALE_SGIX 0x81FC
+#define GL_FOG_SCALE_VALUE_SGIX 0x81FD
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_RESTART_SUN 0x0001
+#define GL_REPLACE_MIDDLE_SUN 0x0002
+#define GL_REPLACE_OLDEST_SUN 0x0003
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+#endif
+
+#ifndef GL_SUN_vertex
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INTERLACE_READ_INGR 0x8568
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+#endif
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_WRAP_BORDER_SUN 0x81D4
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW0_EXT GL_MODELVIEW
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+/* reuse GL_TEXTURE0_ARB */
+/* reuse GL_TEXTURE1_ARB */
+/* reuse GL_ZERO */
+/* reuse GL_NONE */
+/* reuse GL_FOG */
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+/* reuse GL_EYE_PLANE */
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+#endif
+
+#ifndef GL_NV_blend_square
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#endif
+
+#ifndef GL_MESA_window_pos
+#endif
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_CULL_VERTEX_IBM 103050
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_YCRCB_SGIX 0x8318
+#define GL_YCRCBA_SGIX 0x8319
+#endif
+
+#ifndef GL_SGI_depth_pass_instrument
+#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310
+#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311
+#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_PACK_RESAMPLE_SGIX 0x842C
+#define GL_UNPACK_RESAMPLE_SGIX 0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#endif
+
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SCALEBIAS_HINT_SGIX 0x8322
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#endif
+
+#ifndef GL_OML_resample
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_REG_6_ATI 0x8927
+#define GL_REG_7_ATI 0x8928
+#define GL_REG_8_ATI 0x8929
+#define GL_REG_9_ATI 0x892A
+#define GL_REG_10_ATI 0x892B
+#define GL_REG_11_ATI 0x892C
+#define GL_REG_12_ATI 0x892D
+#define GL_REG_13_ATI 0x892E
+#define GL_REG_14_ATI 0x892F
+#define GL_REG_15_ATI 0x8930
+#define GL_REG_16_ATI 0x8931
+#define GL_REG_17_ATI 0x8932
+#define GL_REG_18_ATI 0x8933
+#define GL_REG_19_ATI 0x8934
+#define GL_REG_20_ATI 0x8935
+#define GL_REG_21_ATI 0x8936
+#define GL_REG_22_ATI 0x8937
+#define GL_REG_23_ATI 0x8938
+#define GL_REG_24_ATI 0x8939
+#define GL_REG_25_ATI 0x893A
+#define GL_REG_26_ATI 0x893B
+#define GL_REG_27_ATI 0x893C
+#define GL_REG_28_ATI 0x893D
+#define GL_REG_29_ATI 0x893E
+#define GL_REG_30_ATI 0x893F
+#define GL_REG_31_ATI 0x8940
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_CON_8_ATI 0x8949
+#define GL_CON_9_ATI 0x894A
+#define GL_CON_10_ATI 0x894B
+#define GL_CON_11_ATI 0x894C
+#define GL_CON_12_ATI 0x894D
+#define GL_CON_13_ATI 0x894E
+#define GL_CON_14_ATI 0x894F
+#define GL_CON_15_ATI 0x8950
+#define GL_CON_16_ATI 0x8951
+#define GL_CON_17_ATI 0x8952
+#define GL_CON_18_ATI 0x8953
+#define GL_CON_19_ATI 0x8954
+#define GL_CON_20_ATI 0x8955
+#define GL_CON_21_ATI 0x8956
+#define GL_CON_22_ATI 0x8957
+#define GL_CON_23_ATI 0x8958
+#define GL_CON_24_ATI 0x8959
+#define GL_CON_25_ATI 0x895A
+#define GL_CON_26_ATI 0x895B
+#define GL_CON_27_ATI 0x895C
+#define GL_CON_28_ATI 0x895D
+#define GL_CON_29_ATI 0x895E
+#define GL_CON_30_ATI 0x895F
+#define GL_CON_31_ATI 0x8960
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_STREAM0_ATI 0x876C
+#define GL_VERTEX_STREAM1_ATI 0x876D
+#define GL_VERTEX_STREAM2_ATI 0x876E
+#define GL_VERTEX_STREAM3_ATI 0x876F
+#define GL_VERTEX_STREAM4_ATI 0x8770
+#define GL_VERTEX_STREAM5_ATI 0x8771
+#define GL_VERTEX_STREAM6_ATI 0x8772
+#define GL_VERTEX_STREAM7_ATI 0x8773
+#define GL_VERTEX_SOURCE_ATI 0x8774
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SLICE_ACCUM_SUN 0x85CC
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_DEPTH_CLAMP_NV 0x864F
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_ELEMENT_ARRAY_APPLE 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_YCBCR_422_APPLE 0x85B9
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_TYPE_RGBA_FLOAT_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_HALF_FLOAT_NV 0x140B
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif
+
+#ifndef GL_NV_vertex_program2
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_BLEND_EQUATION_RGB_EXT GL_BLEND_EQUATION
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_PACK_INVERT_MESA 0x8758
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
+/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */
+#endif
+
+#ifndef GL_NV_vertex_program3
+/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#endif
+
+
+/*************************************************************/
+
+#include <stddef.h>
+#ifndef GL_VERSION_2_0
+/* GL type for program/shader text */
+typedef char GLchar; /* native character */
+#endif
+
+#ifndef GL_VERSION_1_5
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+/* GL types for handling large vertex buffer objects */
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+#endif
+
+#ifndef GL_ARB_shader_objects
+/* GL types for handling shader object handles and program/shader text */
+typedef char GLcharARB; /* native character */
+typedef unsigned int GLhandleARB; /* shader object handle */
+#endif
+
+/* GL types for "half" precision (s10e5) float data in host memory */
+#ifndef GL_ARB_half_float_pixel
+typedef unsigned short GLhalfARB;
+#endif
+
+#ifndef GL_NV_half_float
+typedef unsigned short GLhalfNV;
+#endif
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf);
+GLAPI void APIENTRY glBlendEquation (GLenum);
+GLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);
+GLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean);
+GLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean);
+GLAPI void APIENTRY glResetHistogram (GLenum);
+GLAPI void APIENTRY glResetMinmax (GLenum);
+GLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum);
+GLAPI void APIENTRY glClientActiveTexture (GLenum);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *);
+GLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glFogCoordf (GLfloat);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *);
+GLAPI void APIENTRY glFogCoordd (GLdouble);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *);
+GLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+GLAPI void APIENTRY glPointParameterf (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *);
+GLAPI void APIENTRY glPointParameteri (GLenum, GLint);
+GLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *);
+GLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2i (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *);
+GLAPI void APIENTRY glWindowPos2s (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *);
+GLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *);
+GLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint);
+GLAPI void APIENTRY glBeginQuery (GLenum, GLuint);
+GLAPI void APIENTRY glEndQuery (GLenum);
+GLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *);
+GLAPI void APIENTRY glBindBuffer (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint);
+GLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum);
+GLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *);
+GLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *);
+GLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum);
+GLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint);
+GLAPI void APIENTRY glAttachShader (GLuint, GLuint);
+GLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *);
+GLAPI void APIENTRY glCompileShader (GLuint);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum);
+GLAPI void APIENTRY glDeleteProgram (GLuint);
+GLAPI void APIENTRY glDeleteShader (GLuint);
+GLAPI void APIENTRY glDetachShader (GLuint, GLuint);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+GLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *);
+GLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *);
+GLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint);
+GLAPI GLboolean APIENTRY glIsShader (GLuint);
+GLAPI void APIENTRY glLinkProgram (GLuint);
+GLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *);
+GLAPI void APIENTRY glUseProgram (GLuint);
+GLAPI void APIENTRY glUniform1f (GLint, GLfloat);
+GLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform1i (GLint, GLint);
+GLAPI void APIENTRY glUniform2i (GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glValidateProgram (GLuint);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#endif
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#endif
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+#endif
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#endif
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img);
+#endif
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#endif
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *);
+GLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *);
+GLAPI void APIENTRY glWeightivARB (GLint, const GLint *);
+GLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *);
+GLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *);
+GLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *);
+GLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *);
+GLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *);
+GLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexBlendARB (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#endif
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#endif
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#endif
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#endif
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#endif
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#endif
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#endif
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2iARB (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint);
+GLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glBindProgramARB (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *);
+GLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#endif
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */
+#endif
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint);
+GLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);
+GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
+typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);
+#endif
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint);
+GLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint);
+GLAPI void APIENTRY glEndQueryARB (GLenum);
+GLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB);
+GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat);
+GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glUniform1iARB (GLint, GLint);
+GLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#endif
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#endif
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#endif
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#endif
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#endif
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#endif
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+#endif
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#endif
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#endif
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#endif
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+#endif
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#endif
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#endif
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean);
+GLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column);
+#endif
+
+#ifndef GL_EXT_color_matrix
+#define GL_EXT_color_matrix 1
+#endif
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#endif
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels);
+#endif
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#endif
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#endif
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *);
+GLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#endif
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#endif
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#endif
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#endif
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint);
+GLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *);
+GLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#endif
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#endif
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#endif
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#endif
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#endif
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#endif
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#endif
+
+#ifndef GL_SGIX_texture_select
+#define GL_SGIX_texture_select 1
+#endif
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#endif
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#endif
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#endif
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#endif
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#endif
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#endif
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#endif
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#endif
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#endif
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#endif
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#endif
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#endif
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#endif
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#endif
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#endif
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#endif
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#endif
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#endif
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#endif
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#endif
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#endif
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#endif
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#endif
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#endif
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#endif
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+#endif
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#endif
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#endif
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum);
+GLAPI void APIENTRY glTextureLightEXT (GLenum);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#endif
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#endif
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#endif
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#endif
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#endif
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#endif
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *);
+GLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#endif
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+#endif
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#endif
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#endif
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#endif
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *);
+GLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *);
+GLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#endif
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#endif
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#endif
+
+#ifndef GL_SGIX_fog_scale
+#define GL_SGIX_fog_scale 1
+#endif
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#endif
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#endif
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer);
+#endif
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#endif
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#endif
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#endif
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#endif
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#endif
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#endif
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#endif
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#endif
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer);
+#endif
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint);
+GLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#endif
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#endif
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#endif
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#endif
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#endif
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#endif
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride);
+#endif
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride);
+#endif
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#endif
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#endif
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#endif
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#endif
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#endif
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#endif
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#endif
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#endif
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#endif
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#endif
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params);
+#endif
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#endif
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#endif
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint);
+GLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glFinishFenceNV (GLuint);
+GLAPI void APIENTRY glSetFenceNV (GLuint, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *);
+GLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#endif
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#endif
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#endif
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#endif
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#endif
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#endif
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *);
+GLAPI void APIENTRY glBindProgramNV (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint);
+GLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#endif
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#endif
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#endif
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#endif
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#endif
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#endif
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#endif
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum);
+GLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#endif
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint);
+GLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *);
+GLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *);
+GLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *);
+GLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *);
+GLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *);
+GLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *);
+GLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *);
+GLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *);
+GLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#endif
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#endif
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#endif
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#endif
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#endif
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#endif
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum, GLint);
+GLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#endif
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#endif
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#endif
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#endif
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#endif
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#endif
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, const GLuint *);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#endif
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#endif
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#endif
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#endif
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+/* This is really a WGL extension, but defines some associated GL enums.
+ * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string.
+ */
+#endif
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#endif
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#endif
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#endif
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#endif
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#endif
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#endif
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#endif
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#endif
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#endif
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#endif
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#endif
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#endif
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#endif
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#endif
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#endif
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei, GLuint *);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum, GLenum, GLsizei, GLsizei);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum, GLenum, GLint *);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum, GLuint);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei, const GLuint *);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum, GLenum, GLenum, GLuint, GLint);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum, GLenum, GLenum, GLuint, GLint);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLint);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum, GLenum, GLenum, GLuint);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum, GLenum, GLenum, GLint *);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#endif
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/mkglext.py b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/mkglext.py
new file mode 100644
index 00000000000..80247e93fe9
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/mkglext.py
@@ -0,0 +1,630 @@
+#!/usr/bin/python
+#
+# $Id: mkglext.py 2638 2004-06-07 11:01:31Z kester $
+# ***** BEGIN GPL/BL DUAL 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. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+#
+# mkglext.py generates code for linking extensions.
+#
+# It reads the glext.h header from stdin and writes code to stdout.
+#
+# Usage: mkglext.py < glext.h > tmp
+# Code can be copied & pasted from tmp to GL_ExtensionManager.cpp.
+#
+# glext.h is available here: http://oss.sgi.com/projects/ogl-sample/ABI/glext.h
+#
+
+from sys import stdin
+import string, re
+
+glext_h = string.split(stdin.read(), '\n')
+
+# These extensions have been incorporated into the core GL or been superceded.
+# Code will not be generated for these extensions
+blacklist = [
+ "GL_EXT_multisample",
+ "GL_INGR_blend_func_separate",
+ "GL_SGIX_fragment_lighting",
+ "GL_SGIX_polynomial_ffd",
+ "GL_SGIS_point_parameters",
+ "GL_EXT_texture_object",
+ "GL_EXT_subtexture",
+ "GL_EXT_copy_texture",
+ "GL_EXT_vertex_array",
+ "GL_EXT_point_parameters",
+ "GL_EXT_blend_color",
+ "GL_EXT_polygon_offset",
+ "GL_EXT_texture"]
+
+# Only code for these extensions will be generated. Extensions on both the
+# blacklist & whitelist will not have code generated.
+# This list is from http://oss.sgi.com/projects/ogl-sample/registry/ at 14-Mar-04
+whitelist = [
+ # ARB Extensions
+ "GL_ARB_multitexture",
+ "GLX_ARB_get_proc_address",
+ "GL_ARB_transpose_matrix",
+ "WGL_ARB_buffer_region",
+ "GL_ARB_multisample",
+ "GL_ARB_texture_env_add",
+ "GL_ARB_texture_cube_map",
+ "WGL_ARB_extensions_string",
+ "WGL_ARB_pixel_format",
+ "WGL_ARB_make_current_read",
+ "WGL_ARB_pbuffer",
+ "GL_ARB_texture_compression",
+ "GL_ARB_texture_border_clamp",
+ "GL_ARB_point_parameters",
+ "GL_ARB_vertex_blend",
+ "GL_ARB_matrix_palette",
+ "GL_ARB_texture_env_combine",
+ "GL_ARB_texture_env_crossbar",
+ "GL_ARB_texture_env_dot3",
+ "WGL_ARB_render_texture",
+ "GL_ARB_texture_mirrored_repeat",
+ "GL_ARB_depth_texture",
+ "GL_ARB_shadow",
+ "GL_ARB_shadow_ambient",
+ "GL_ARB_window_pos",
+ "GL_ARB_vertex_program",
+ "GL_ARB_fragment_program",
+ "GL_ARB_vertex_buffer_object",
+ "GL_ARB_occlusion_query",
+ "GL_ARB_shader_objects",
+ "GL_ARB_vertex_shader",
+ "GL_ARB_fragment_shader",
+ "GL_ARB_shading_language_100",
+ "GL_ARB_texture_non_power_of_two",
+ "GL_ARB_point_sprite",
+ "GL_ARB_fragment_program_shadow",
+
+ # Non ARB Extensions
+ "GL_EXT_abgr",
+ "GL_EXT_blend_color",
+ "GL_EXT_polygon_offset",
+ "GL_EXT_texture",
+ "GL_EXT_texture3D",
+ "GL_SGIS_texture_filter4",
+ "GL_EXT_subtexture",
+ "GL_EXT_copy_texture",
+ "GL_EXT_histogram",
+ "GL_EXT_convolution",
+ "GL_SGI_color_matrix",
+ "GL_SGI_color_table",
+ "GL_SGIS_pixel_texture",
+ "GL_SGIS_texture4D",
+ "GL_SGI_texture_color_table",
+ "GL_EXT_cmyka",
+ "GL_EXT_texture_object",
+ "GL_SGIS_detail_texture",
+ "GL_SGIS_sharpen_texture",
+ "GL_EXT_packed_pixels",
+ "GL_SGIS_texture_lod",
+ "GL_SGIS_multisample",
+ "GL_EXT_rescale_normal",
+ "GLX_EXT_visual_info",
+ "GL_EXT_vertex_array",
+ "GL_EXT_misc_attribute",
+ "GL_SGIS_generate_mipmap",
+ "GL_SGIX_clipmap",
+ "GL_SGIX_shadow",
+ "GL_SGIS_texture_edge_clamp",
+ "GL_SGIS_texture_border_clamp",
+ "GL_EXT_blend_minmax",
+ "GL_EXT_blend_subtract",
+ "GL_EXT_blend_logic_op",
+ "GLX_SGI_swap_control",
+ "GLX_SGI_video_sync",
+ "GLX_SGI_make_current_read",
+ "GLX_SGIX_video_source",
+ "GLX_EXT_visual_rating",
+ "GL_SGIX_interlace",
+ "GLX_EXT_import_context",
+ "GLX_SGIX_fbconfig",
+ "GLX_SGIX_pbuffer",
+ "GL_SGIS_texture_select",
+ "GL_SGIX_sprite",
+ "GL_SGIX_texture_multi_buffer",
+ "GL_EXT_point_parameters",
+ "GL_SGIX_instruments",
+ "GL_SGIX_texture_scale_bias",
+ "GL_SGIX_framezoom",
+ "GL_SGIX_tag_sample_buffer",
+ "GL_SGIX_reference_plane",
+ "GL_SGIX_flush_raster",
+ "GLX_SGI_cushion",
+ "GL_SGIX_depth_texture",
+ "GL_SGIS_fog_function",
+ "GL_SGIX_fog_offset",
+ "GL_HP_image_transform",
+ "GL_HP_convolution_border_modes",
+ "GL_SGIX_texture_add_env",
+ "GL_EXT_color_subtable",
+ "GLU_EXT_object_space_tess",
+ "GL_PGI_vertex_hints",
+ "GL_PGI_misc_hints",
+ "GL_EXT_paletted_texture",
+ "GL_EXT_clip_volume_hint",
+ "GL_SGIX_list_priority",
+ "GL_SGIX_ir_instrument1",
+ "GLX_SGIX_video_resize",
+ "GL_SGIX_texture_lod_bias",
+ "GLU_SGI_filter4_parameters",
+ "GLX_SGIX_dm_buffer",
+ "GL_SGIX_shadow_ambient",
+ "GLX_SGIX_swap_group",
+ "GLX_SGIX_swap_barrier",
+ "GL_EXT_index_texture",
+ "GL_EXT_index_material",
+ "GL_EXT_index_func",
+ "GL_EXT_index_array_formats",
+ "GL_EXT_compiled_vertex_array",
+ "GL_EXT_cull_vertex",
+ "GLU_EXT_nurbs_tessellator",
+ "GL_SGIX_ycrcb",
+ "GL_EXT_fragment_lighting",
+ "GL_IBM_rasterpos_clip",
+ "GL_HP_texture_lighting",
+ "GL_EXT_draw_range_elements",
+ "GL_WIN_phong_shading",
+ "GL_WIN_specular_fog",
+ "GLX_SGIS_color_range",
+ "GL_EXT_light_texture",
+ "GL_SGIX_blend_alpha_minmax",
+ "GL_EXT_scene_marker",
+ "GL_SGIX_pixel_texture_bits",
+ "GL_EXT_bgra",
+ "GL_SGIX_async",
+ "GL_SGIX_async_pixel",
+ "GL_SGIX_async_histogram",
+ "GL_INTEL_texture_scissor",
+ "GL_INTEL_parallel_arrays",
+ "GL_HP_occlusion_test",
+ "GL_EXT_pixel_transform",
+ "GL_EXT_pixel_transform_color_table",
+ "GL_EXT_shared_texture_palette",
+ "GLX_SGIS_blended_overlay",
+ "GL_EXT_separate_specular_color",
+ "GL_EXT_secondary_color",
+ "GL_EXT_texture_env",
+ "GL_EXT_texture_perturb_normal",
+ "GL_EXT_multi_draw_arrays",
+ "GL_EXT_fog_coord",
+ "GL_REND_screen_coordinates",
+ "GL_EXT_coordinate_frame",
+ "GL_EXT_texture_env_combine",
+ "GL_APPLE_specular_vector",
+ "GL_SGIX_pixel_texture",
+ "GL_APPLE_transform_hint",
+ "GL_SUNX_constant_data",
+ "GL_SUN_global_alpha",
+ "GL_SUN_triangle_list",
+ "GL_SUN_vertex",
+ "WGL_EXT_display_color_table",
+ "WGL_EXT_extensions_string",
+ "WGL_EXT_make_current_read",
+ "WGL_EXT_pixel_format",
+ "WGL_EXT_pbuffer",
+ "WGL_EXT_swap_control",
+ "GL_EXT_blend_func_separate",
+ "GL_INGR_color_clamp",
+ "GL_INGR_interlace_read",
+ "GL_EXT_stencil_wrap",
+ "WGL_EXT_depth_float",
+ "GL_EXT_422_pixels",
+ "GL_NV_texgen_reflection",
+ "GL_SGIX_texture_range",
+ "GL_SUN_convolution_border_modes",
+ "GLX_SUN_get_transparent_index",
+ "GL_EXT_texture_env_add",
+ "GL_EXT_texture_lod_bias",
+ "GL_EXT_texture_filter_anisotropic",
+ "GL_EXT_vertex_weighting",
+ "GL_NV_light_max_exponent",
+ "GL_NV_vertex_array_range",
+ "GL_NV_register_combiners",
+ "GL_NV_fog_distance",
+ "GL_NV_texgen_emboss",
+ "GL_NV_blend_square",
+ "GL_NV_texture_env_combine4",
+ "GL_MESA_resize_buffers",
+ "GL_MESA_window_pos",
+ "GL_EXT_texture_compression_s3tc",
+ "GL_IBM_cull_vertex",
+ "GL_IBM_multimode_draw_arrays",
+ "GL_IBM_vertex_array_lists",
+ "GL_3DFX_texture_compression_FXT1",
+ "GL_3DFX_multisample",
+ "GL_3DFX_tbuffer",
+ "WGL_EXT_multisample",
+ "GL_SGIX_vertex_preclip",
+ "GL_SGIX_resample",
+ "GL_SGIS_texture_color_mask",
+ "GLX_MESA_copy_sub_buffer",
+ "GLX_MESA_pixmap_colormap",
+ "GLX_MESA_release_buffers",
+ "GLX_MESA_set_3dfx_mode",
+ "GL_EXT_texture_env_dot3",
+ "GL_ATI_texture_mirror_once",
+ "GL_NV_fence",
+ "GL_IBM_static_data",
+ "GL_IBM_texture_mirrored_repeat",
+ "GL_NV_evaluators",
+ "GL_NV_packed_depth_stencil",
+ "GL_NV_register_combiners2",
+ "GL_NV_texture_compression_vtc",
+ "GL_NV_texture_rectangle",
+ "GL_NV_texture_shader",
+ "GL_NV_texture_shader2",
+ "GL_NV_vertex_array_range2",
+ "GL_NV_vertex_program",
+ "GLX_SGIX_visual_select_group",
+ "GL_SGIX_texture_coordinate_clamp",
+ "GLX_OML_swap_method",
+ "GLX_OML_sync_control",
+ "GL_OML_interlace",
+ "GL_OML_subsample",
+ "GL_OML_resample",
+ "WGL_OML_sync_control",
+ "GL_NV_copy_depth_to_color",
+ "GL_ATI_envmap_bumpmap",
+ "GL_ATI_fragment_shader",
+ "GL_ATI_pn_triangles",
+ "GL_ATI_vertex_array_object",
+ "GL_EXT_vertex_shader",
+ "GL_ATI_vertex_streams",
+ "WGL_I3D_digital_video_control",
+ "WGL_I3D_gamma",
+ "WGL_I3D_genlock",
+ "WGL_I3D_image_buffer",
+ "WGL_I3D_swap_frame_lock",
+ "WGL_I3D_swap_frame_usage",
+ "GL_ATI_element_array",
+ "GL_SUN_mesh_array",
+ "GL_SUN_slice_accum",
+ "GL_NV_multisample_filter_hint",
+ "GL_NV_depth_clamp",
+ "GL_NV_occlusion_query",
+ "GL_NV_point_sprite",
+ "WGL_NV_render_depth_texture",
+ "WGL_NV_render_texture_rectangle",
+ "GL_NV_texture_shader3",
+ "GL_NV_vertex_program1_1",
+ "GL_EXT_shadow_funcs",
+ "GL_EXT_stencil_two_side",
+ "GL_ATI_text_fragment_shader",
+ "GL_APPLE_client_storage",
+ "GL_APPLE_element_array",
+ "GL_APPLE_fence",
+ "GL_APPLE_vertex_array_object",
+ "GL_APPLE_vertex_array_range",
+ "GL_APPLE_ycbcr_422",
+ "GL_S3_s3tc",
+ "GL_ATI_draw_buffers",
+ "WGL_ATI_pixel_format_float",
+ "GL_ATI_texture_env_combine3",
+ "GL_ATI_texture_float",
+ "GL_NV_float_buffer",
+ "GL_NV_fragment_program",
+ "GL_NV_half_float",
+ "GL_NV_pixel_data_range",
+ "GL_NV_primitive_restart",
+ "GL_NV_texture_expand_normal",
+ "GL_NV_vertex_program2",
+ "GL_ATI_map_object_buffer",
+ "GL_ATI_separate_stencil",
+ "GL_ATI_vertex_attrib_array_object",
+ "GL_OES_byte_coordinates",
+ "GL_OES_fixed_point",
+ "GL_OES_single_precision",
+ "GL_OES_compressed_paletted_texture",
+ "GL_OES_read_format",
+ "GL_OES_query_matrix",
+ "GL_EXT_depth_bounds_test",
+ "GL_EXT_texture_mirror_clamp",
+ "GL_EXT_blend_equation_separate",
+ "GL_MESA_pack_invert",
+ "GL_MESA_ycbcr_texture"]
+
+"""
+Example code output:
+#ifdef GL_EXT_compiled_vertex_array
+ if (QueryExtension("GL_EXT_compiled_vertex_array"))
+ {
+ glUnlockArraysEXT = reinterpret_cast<PFNGLUNLOCKARRAYSEXTPROC>(bglGetProcAddress((const GLubyte *) "glUnlockArraysEXT"));
+ glLockArraysEXT = reinterpret_cast<PFNGLLOCKARRAYSEXTPROC>(bglGetProcAddress((const GLubyte *) "glLockArraysEXT"));
+ if (glUnlockArraysEXT && glLockArraysEXT)
+ {
+ EnableExtension(_GL_EXT_compiled_vertex_array);
+ if (doDebugMessages)
+ std::cout << "Detected GL_EXT_compiled_vertex_array" << std::endl;
+ } else {
+ std::cout << "ERROR: GL_EXT_compiled_vertex_array implementation is broken!" << std::endl;
+ }
+ }
+#endif
+"""
+def writeext(ext, fnlist):
+ if (find(blacklist, ext)):
+ return
+ if (len(fnlist) == 0):
+ # This extension has no functions to detect - don't need to wrap in
+ # #ifdef GL_extension names
+ print "\tif (QueryExtension(\"" + ext + "\"))"
+ print "\t{"
+ print "\t\tEnableExtension(_" + ext + ");"
+ print "\t\tif (doDebugMessages)"
+ print "\t\t\tstd::cout << \"Detected " + ext + "\" << std::endl;"
+ print "\t}"
+ print
+ return
+ print "#if defined(" + ext + ")"
+ print "\tif (QueryExtension(\"" + ext + "\"))"
+ print "\t{"
+ for fn in fnlist:
+ print "\t\t" + fn[0] + " = reinterpret_cast<" + fn[1] + ">(bglGetProcAddress((const GLubyte *) \"" + fn[0] + "\"));"
+ errcheck = ""
+ for fn in fnlist:
+ if (errcheck == ""):
+ errcheck = fn[0]
+ else:
+ errcheck = errcheck + " && " + fn[0]
+ print "\t\tif (" + errcheck + ") {"
+ print "\t\t\tEnableExtension(_" + ext + ");"
+ print "\t\t\tif (doDebugMessages)"
+ print "\t\t\t\tstd::cout << \"Enabled " + ext + "\" << std::endl;"
+ print "\t\t} else {"
+ print "\t\t\tstd::cout << \"ERROR: " + ext + " implementation is broken!\" << std::endl;"
+ print "\t\t}"
+ print "\t}"
+ print "#endif"
+ print
+
+"""
+Example Output:
+#if defined(GL_EXT_compiled_vertex_array)
+PFNGLLOCKARRAYSEXTPROC glLockArraysEXT;
+PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
+#endif
+"""
+def writeproto(ext, fnlist):
+ if (find(blacklist, ext) or not find(whitelist, ext)):
+ return
+ print "#if defined(" + ext + ")"
+ for fn in fnlist:
+ print fn[1] + " " + fn[0] + ";"
+ print "#endif"
+ print
+
+"""
+#ifdef GL_EXT_compiled_vertex_array
+extern PFNGLLOCKARRAYSEXTPROC glLockArraysEXT;
+extern PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
+#endif
+"""
+def writeheader(ext, fnlisti):
+ if (find(blacklist, ext) or not find(whitelist, ext)):
+ return
+ print "#if defined(" + ext + ")"
+ for fn in fnlist:
+ print "extern " + fn[1] + " " + fn[0] + ";"
+ print "#endif"
+ print
+
+def find(l, x):
+ for i in l:
+ if (i == x):
+ return 1
+ return 0
+
+
+# Write Prototypes
+ext = ""
+fns = []
+fnlist = []
+ifdef = 0
+for i in glext_h:
+ line = re.search('^#ifn?def', i)
+ if (line):
+ ifdef = ifdef + 1
+
+ line = re.search('^#ifndef (GL_.*)', i)
+ if (line):
+ if (not re.search('GL_VERSION.*', line.group(1)) and find(whitelist, line.group(1))):
+ ext = line.group(1)
+
+ line = re.search('^#endif', i)
+ if (line):
+ ifdef = ifdef - 1
+ if (ifdef == 0 and ext != ""):
+ writeproto(ext, fnlist)
+ ext = ""
+ fns = []
+ fnlist = []
+ if (ext != ""):
+ line = re.search('.* (gl.*) \(.*\);', i)
+ if (line):
+ fns += [line.group(1)]
+ line = re.search('.*PFN(.*)PROC.*', i)
+ if (line):
+ for j in fns:
+ if (string.lower(line.group(1)) == string.lower(j)):
+ fnlist += [(j, "PFN" + line.group(1) + "PROC")]
+
+# Write link code
+ext = ""
+fns = []
+fnlist = []
+ifdef = 0
+for i in glext_h:
+ line = re.search('^#ifn?def', i)
+ if (line):
+ ifdef = ifdef + 1
+
+ line = re.search('^#ifndef (GL_.*)', i)
+ if (line):
+ if (not re.search('GL_VERSION.*', line.group(1)) and find(whitelist, line.group(1))):
+ ext = line.group(1)
+
+ line = re.search('^#endif', i)
+ if (line):
+ ifdef = ifdef - 1
+ if (ifdef == 0 and ext != ""):
+ writeext(ext, fnlist)
+ ext = ""
+ fns = []
+ fnlist = []
+ if (ext != ""):
+ line = re.search('.* (gl.*) \(.*\);', i)
+ if (line):
+ fns += [line.group(1)]
+ line = re.search('.*PFN(.*)PROC.*', i)
+ if (line):
+ for j in fns:
+ if (string.lower(line.group(1)) == string.lower(j)):
+ fnlist += [(j, "PFN" + line.group(1) + "PROC")]
+
+# Write header code
+ext = ""
+fns = []
+fnlist = []
+ifdef = 0
+for i in glext_h:
+ line = re.search('^#ifn?def', i)
+ if (line):
+ ifdef = ifdef + 1
+
+ line = re.search('^#ifndef (GL_.*)', i)
+ if (line):
+ if (not re.search('GL_VERSION.*', line.group(1)) and find(whitelist, line.group(1))):
+ ext = line.group(1)
+
+ line = re.search('^#endif', i)
+ if (line):
+ ifdef = ifdef - 1
+ if (ifdef == 0 and ext != ""):
+ writeheader(ext, fnlist)
+ ext = ""
+ fns = []
+ fnlist = []
+ if (ext != ""):
+ line = re.search('.* (gl.*) \(.*\);', i)
+ if (line):
+ fns += [line.group(1)]
+ line = re.search('.*PFN(.*)PROC.*', i)
+ if (line):
+ for j in fns:
+ if (string.lower(line.group(1)) == string.lower(j)):
+ fnlist += [(j, "PFN" + line.group(1) + "PROC")]
+
+# Write Python link code
+ext = ""
+extensions = []
+fns = []
+defines = []
+ifdef = 0
+for i in glext_h:
+ line = re.search('^#ifn?def', i)
+ if (line):
+ ifdef = ifdef + 1
+
+ line = re.search('^#ifndef (GL_.*)', i)
+ if (line):
+ if (not re.search('GL_VERSION.*', line.group(1)) and find(whitelist, line.group(1))):
+ ext = line.group(1)
+
+ line = re.search('^#endif', i)
+ if (line):
+ ifdef = ifdef - 1
+ if (ifdef == 0 and ext != ""):
+ done = 0
+ for e in range(len(extensions)):
+ if extensions[e][0] == ext:
+ extensions[e] = (ext, defines + extensions[e][1], fns + extensions[e][2])
+ done = 1
+ if not done:
+ extensions = extensions + [(ext, defines, fns)]
+ ext = ""
+ fns = []
+ defines = []
+ if (ext != ""):
+ line = re.search('#define +(GL.*) +(0x.*)', i) # #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+ if (line):
+ defines += [(line.group(1), line.group(2))]
+
+ line = re.search('(.* )(gl.*)(\(.*\));', i) # GLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat);
+ if (line):
+ fns += [(line.group(1), line.group(2), line.group(3))]
+
+for ext in extensions:
+ if (find(blacklist, ext[0]) or not find(whitelist, ext[0])):
+ continue
+ print "#if defined(" + ext[0] + ")"
+ for fn in ext[2]:
+ line = re.search('gl(.*)', fn[1])
+ # BGL_Wrap(2, RasterPos2f, void, (GLfloat, GLfloat))
+ rtype = ""
+ for r in string.split(fn[0]):
+ if r != "GLAPI" and r != "APIENTRY":
+ rtype = rtype + " " + r
+ params = ""
+ for p in string.split(fn[2], ','):
+ pline = re.search('(.*) \*', p)
+ if (pline):
+ p = pline.group(1) + "P"
+ if params == "":
+ params = p
+ else:
+ params = params + "," + p
+ if not params[-1] == ")":
+ params = params + ")"
+ print "BGL_Wrap(" + str(len(string.split(fn[2], ','))) + ", " + line.group(1) + ",\t" + rtype + ",\t" + params + ")"
+ print "#endif"
+ print
+
+for ext in extensions:
+ if (find(blacklist, ext[0]) or not find(whitelist, ext[0])):
+ continue
+ print 'PyDict_SetItemString(dict, "' + ext[0] + '", PyInt_FromLong(_' + ext[0] + '))'
+ print "#if defined(" + ext[0] + ")"
+ print "if (bglQueryExtension(_" + ext[0] + ")) {"
+ if len(ext[2]) > 0:
+ for fn in ext[2]:
+ line = re.search('gl(.*)', fn[1])
+ # MethodDef(Vertex3iv),
+ print " BGL_AddMethod(" + line.group(1) + ");"
+ print
+
+ for define in ext[1]:
+ print " BGL_AddConst(" + define[0] + ");"
+ print
+
+ print "}"
+ print "#endif"
+ print
diff --git a/tools/Blender.py b/tools/Blender.py
index 164a9d097e6..306bce91bc8 100644
--- a/tools/Blender.py
+++ b/tools/Blender.py
@@ -14,7 +14,6 @@ to kill any code duplication
"""
-import os
import os.path
import string
import glob
@@ -101,7 +100,9 @@ def create_blender_liblist(lenv = None, libtype = None):
sortlist.sort()
for sk in sortlist:
v = curlib[sk]
- target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
+ target = root_build_dir + 'lib/'+lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX']
+ if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
+ target = '#'+target
lst.append(target)
return lst
@@ -145,7 +146,7 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
- if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'):
libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
return statlibs, libincs
@@ -160,10 +161,12 @@ def setup_syslibs(lenv):
syslibs += Split(lenv['BF_FREETYPE_LIB'])
if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
- if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
- syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
- else:
- syslibs.append(lenv['BF_PYTHON_LIB'])
+ #if not lenv['BF_NO_PYDEBUG'] and lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc'):
+ # print "using debug py"
+ # syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
+ #else:
+ #print "not using debug py"
+ syslibs.append(lenv['BF_PYTHON_LIB'])
if lenv['WITH_BF_INTERNATIONAL']:
syslibs += Split(lenv['BF_GETTEXT_LIB'])
if lenv['WITH_BF_OPENAL']:
@@ -187,7 +190,7 @@ def setup_syslibs(lenv):
syslibs += Split(lenv['BF_SDL_LIB'])
if not lenv['WITH_BF_STATICOPENGL']:
syslibs += Split(lenv['BF_OPENGL_LIB'])
- if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
+ if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'):
syslibs += Split(lenv['BF_PTHREADS_LIB'])
if lenv['WITH_BF_LCMS']:
syslibs.append(lenv['BF_LCMS_LIB'])
@@ -396,7 +399,7 @@ class BlenderEnvironment(SConsEnvironment):
if not self or not libname or not source:
print bc.FAIL+'Cannot continue. Missing argument for BlenderRes '+libname+bc.ENDC
self.Exit()
- if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
+ if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross'):
print bc.FAIL+'BlenderRes is for windows only!'+bc.END
self.Exit()
@@ -474,7 +477,7 @@ class BlenderEnvironment(SConsEnvironment):
global vcp
print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
lenv = self.Clone()
- if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
+ if lenv['OURPLATFORM'] in ['win32-vc', 'cygwin']:
lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
if lenv['BF_DEBUG']:
lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb'])
@@ -504,7 +507,10 @@ class BlenderEnvironment(SConsEnvironment):
lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
- if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
+ #needed for incremental linking
+ if lenv['OURPLATFORM'] == 'win32-vc': prog = lenv.Precious(prog)
+
+ if lenv['BF_DEBUG'] and lenv['OURPLATFORM']=='win32-vc' and lenv['BF_BSC']:
f = lenv.File(progname + '.bsc', builddir)
brs = lenv.Command(f, prog, [bsc])
SConsEnvironment.Default(self, brs)
diff --git a/tools/btools.py b/tools/btools.py
index 9603022deaa..ea0b09a9634 100755
--- a/tools/btools.py
+++ b/tools/btools.py
@@ -27,7 +27,7 @@ def print_arguments(args, bc):
def validate_arguments(args, bc):
opts_list = [
- 'WITH_BF_PYTHON', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC',
+ 'BF_NO_PYDEBUG', 'WITH_BF_PYTHON', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC',
'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC',
'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH',
'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH',
@@ -80,7 +80,7 @@ def validate_arguments(args, bc):
]
- arg_list = ['BF_DEBUG', 'BF_QUIET', 'BF_CROSS', 'BF_UPDATE',
+ arg_list = ['BF_NO_PYDEBUG', 'BF_DEBUG', 'BF_QUIET', 'BF_CROSS', 'BF_UPDATE',
'BF_INSTALLDIR', 'BF_TOOLSET', 'BF_BINNAME',
'BF_BUILDDIR', 'BF_FANCY', 'BF_QUICK', 'BF_PROFILE',
'BF_BSC', 'BF_CONFIG',
@@ -146,6 +146,7 @@ def read_opts(cfg, args):
localopts.AddVariables(
('LCGDIR', 'location of cvs lib dir'),
(BoolVariable('WITH_BF_PYTHON', 'Compile with python', True)),
+ (BoolVariable('BF_NO_PYDEBUG', 'don\'t use debug python, only valid on win32/msvc', False)),
('BF_PYTHON', 'base path for python', ''),
('BF_PYTHON_VERSION', 'Python version to use', ''),
('BF_PYTHON_INC', 'include path for Python headers', ''),