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.py5
-rw-r--r--intern/SoundSystem/CMakeLists.txt42
-rw-r--r--intern/SoundSystem/Makefile70
-rw-r--r--intern/SoundSystem/SConscript20
-rw-r--r--intern/SoundSystem/SND_C-api.h354
-rw-r--r--intern/SoundSystem/SND_CDObject.h83
-rw-r--r--intern/SoundSystem/SND_DependKludge.h50
-rw-r--r--intern/SoundSystem/SND_DeviceManager.h79
-rw-r--r--intern/SoundSystem/SND_IAudioDevice.h343
-rw-r--r--intern/SoundSystem/SND_Object.h54
-rw-r--r--intern/SoundSystem/SND_Scene.h104
-rw-r--r--intern/SoundSystem/SND_SoundListener.h82
-rw-r--r--intern/SoundSystem/SND_SoundObject.h159
-rw-r--r--intern/SoundSystem/SND_Utils.h111
-rw-r--r--intern/SoundSystem/SND_WaveCache.h66
-rw-r--r--intern/SoundSystem/SND_WaveSlot.h92
-rw-r--r--intern/SoundSystem/SND_test/Makefile48
-rw-r--r--intern/SoundSystem/SND_test/SND_test.c154
-rw-r--r--intern/SoundSystem/SoundDefines.h107
-rw-r--r--intern/SoundSystem/dummy/Makefile42
-rw-r--r--intern/SoundSystem/dummy/SND_DummyDevice.cpp (renamed from source/blender/render/intern/include/raycounter.h)43
-rw-r--r--intern/SoundSystem/dummy/SND_DummyDevice.h93
-rw-r--r--intern/SoundSystem/intern/Makefile44
-rw-r--r--intern/SoundSystem/intern/SND_AudioDevice.cpp242
-rw-r--r--intern/SoundSystem/intern/SND_AudioDevice.h115
-rw-r--r--intern/SoundSystem/intern/SND_C-api.cpp392
-rw-r--r--intern/SoundSystem/intern/SND_CDObject.cpp182
-rw-r--r--intern/SoundSystem/intern/SND_DeviceManager.cpp126
-rw-r--r--intern/SoundSystem/intern/SND_IdObject.cpp76
-rw-r--r--intern/SoundSystem/intern/SND_IdObject.h58
-rw-r--r--intern/SoundSystem/intern/SND_Scene.cpp544
-rw-r--r--intern/SoundSystem/intern/SND_SoundListener.cpp185
-rw-r--r--intern/SoundSystem/intern/SND_SoundObject.cpp508
-rw-r--r--intern/SoundSystem/intern/SND_Utils.cpp424
-rw-r--r--intern/SoundSystem/intern/SND_WaveCache.cpp138
-rw-r--r--intern/SoundSystem/intern/SND_WaveSlot.cpp180
-rw-r--r--intern/SoundSystem/make/msvc_6_0/SoundSystem.dsp206
-rw-r--r--intern/SoundSystem/make/msvc_6_0/dummy/DummySoundSystem.dsp103
-rw-r--r--intern/SoundSystem/make/msvc_6_0/openal/OpenALSoundSystem.dsp106
-rw-r--r--intern/SoundSystem/make/msvc_7_0/SoundSystem.vcproj339
-rw-r--r--intern/SoundSystem/make/msvc_7_0/dummy/DummySoundSystem.vcproj243
-rw-r--r--intern/SoundSystem/make/msvc_7_0/openal/OpenALSoundSystem.vcproj249
-rw-r--r--intern/SoundSystem/make/msvc_9_0/SoundSystem.vcproj447
-rw-r--r--intern/SoundSystem/make/msvc_9_0/dummy/DummySoundSystem.vcproj343
-rw-r--r--intern/SoundSystem/make/msvc_9_0/openal/OpenALSoundSystem.vcproj351
-rw-r--r--intern/SoundSystem/openal/Makefile44
-rw-r--r--intern/SoundSystem/openal/SND_OpenALDevice.cpp854
-rw-r--r--intern/SoundSystem/openal/SND_OpenALDevice.h107
-rw-r--r--intern/SoundSystem/openal/pthread_cancel.cpp67
-rw-r--r--intern/SoundSystem/sdl/Makefile43
-rw-r--r--intern/SoundSystem/sdl/SND_SDLCDDevice.cpp171
-rw-r--r--intern/SoundSystem/sdl/SND_SDLCDDevice.h58
-rw-r--r--intern/elbeem/intern/elbeem.h262
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCocoa.mm336
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm2790
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm2056
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h44
-rw-r--r--intern/guardedalloc/Makefile15
-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--intern/guardedalloc/make/msvc_9_0/guardedalloc.vcproj1
-rw-r--r--projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj355
-rw-r--r--projectfiles_vc9/blender/BPY_python/BPY_python.vcproj2
-rw-r--r--projectfiles_vc9/blender/blender.sln39
-rw-r--r--projectfiles_vc9/blender/blender.vcproj6
-rw-r--r--projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj22
-rw-r--r--projectfiles_vc9/blender/blenlib/BLI_blenlib.vcproj14
-rw-r--r--projectfiles_vc9/blender/editors/ED_editors.vcproj26
-rw-r--r--projectfiles_vc9/blender/makesdna/DNA_makesdna.vcproj6
-rw-r--r--[-rwxr-xr-x]release/irix-6.2-mips/specific.sh0
-rw-r--r--release/scripts/export_cal3d.py1112
-rw-r--r--release/scripts/io/add_mesh_torus.py98
-rw-r--r--release/scripts/io/engine_render_pov.py18
-rw-r--r--release/scripts/io/export_3ds.py17
-rw-r--r--release/scripts/io/export_fbx.py18
-rw-r--r--release/scripts/io/export_mdd.py184
-rw-r--r--release/scripts/io/export_obj.py20
-rw-r--r--release/scripts/io/export_ply.py6
-rw-r--r--release/scripts/io/export_x3d.py19
-rw-r--r--release/scripts/io/import_3ds.py19
-rw-r--r--release/scripts/io/import_obj.py25
-rw-r--r--release/scripts/io/mesh_skin.py647
-rw-r--r--release/scripts/io/netrender/client.py146
-rw-r--r--release/scripts/io/netrender/master.py42
-rw-r--r--release/scripts/io/netrender/master_html.py13
-rw-r--r--release/scripts/io/netrender/model.py24
-rw-r--r--release/scripts/io/netrender/operators.py42
-rw-r--r--release/scripts/io/netrender/slave.py71
-rw-r--r--release/scripts/io/netrender/ui.py86
-rw-r--r--release/scripts/io/netrender/utils.py2
-rw-r--r--release/scripts/modules/bpy_ops.py129
-rw-r--r--release/scripts/modules/dynamic_menu.py95
-rw-r--r--release/scripts/ui/buttons_data_armature.py2
-rw-r--r--release/scripts/ui/buttons_data_bone.py210
-rw-r--r--release/scripts/ui/buttons_data_lamp.py10
-rw-r--r--release/scripts/ui/buttons_data_mesh.py23
-rw-r--r--release/scripts/ui/buttons_material.py82
-rw-r--r--release/scripts/ui/buttons_object.py4
-rw-r--r--release/scripts/ui/buttons_object_constraint.py217
-rw-r--r--release/scripts/ui/buttons_particle.py126
-rw-r--r--release/scripts/ui/buttons_physics_common.py5
-rw-r--r--release/scripts/ui/buttons_physics_field.py41
-rw-r--r--release/scripts/ui/buttons_physics_smoke.py16
-rw-r--r--release/scripts/ui/buttons_render.py454
-rw-r--r--release/scripts/ui/buttons_scene.py491
-rw-r--r--release/scripts/ui/buttons_texture.py161
-rw-r--r--release/scripts/ui/buttons_world.py3
-rw-r--r--release/scripts/ui/space_buttons.py1
-rw-r--r--release/scripts/ui/space_console.py2
-rw-r--r--release/scripts/ui/space_filebrowser.py14
-rw-r--r--release/scripts/ui/space_image.py10
-rw-r--r--release/scripts/ui/space_info.py108
-rw-r--r--release/scripts/ui/space_node.py3
-rw-r--r--release/scripts/ui/space_outliner.py1
-rw-r--r--release/scripts/ui/space_sequencer.py6
-rw-r--r--release/scripts/ui/space_text.py7
-rw-r--r--release/scripts/ui/space_time.py6
-rw-r--r--release/scripts/ui/space_userpref.py381
-rw-r--r--release/scripts/ui/space_view3d.py234
-rw-r--r--release/scripts/ui/space_view3d_toolbar.py52
-rw-r--r--release/scripts/uv_from_adjacent.py129
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h191
-rw-r--r--source/blender/blenkernel/BKE_blender.h1
-rw-r--r--source/blender/blenkernel/BKE_bmesh.h3
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h43
-rw-r--r--source/blender/blenkernel/BKE_customdata.h48
-rw-r--r--source/blender/blenkernel/BKE_mesh.h23
-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.h58
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h56
-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/BME_tools.c1
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c486
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h209
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c501
-rw-r--r--source/blender/blenkernel/intern/anim.c27
-rw-r--r--source/blender/blenkernel/intern/armature.c1
-rw-r--r--source/blender/blenkernel/intern/blender.c18
-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.c719
-rw-r--r--source/blender/blenkernel/intern/cloth.c11
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/customdata.c385
-rw-r--r--source/blender/blenkernel/intern/deform.c1
-rw-r--r--source/blender/blenkernel/intern/displist.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedbmesh.c1694
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/exotic.c4
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c17
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c2
-rw-r--r--source/blender/blenkernel/intern/key.c1
-rw-r--r--source/blender/blenkernel/intern/lattice.c1
-rw-r--r--source/blender/blenkernel/intern/library.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c414
-rw-r--r--source/blender/blenkernel/intern/modifier.c1725
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c728
-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.c45
-rw-r--r--source/blender/blenkernel/intern/particle_system.c30
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c9
-rw-r--r--source/blender/blenkernel/intern/smoke.c14
-rw-r--r--source/blender/blenkernel/intern/softbody.c11
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2066
-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.h2
-rw-r--r--source/blender/blenlib/BLI_arithb.h3
-rw-r--r--source/blender/blenlib/BLI_array.h91
-rw-r--r--source/blender/blenlib/BLI_cellalloc.h49
-rw-r--r--source/blender/blenlib/BLI_edgehash.h106
-rw-r--r--source/blender/blenlib/BLI_editVert.h3
-rw-r--r--source/blender/blenlib/BLI_ghash.h163
-rw-r--r--source/blender/blenlib/intern/BLI_cellalloc.c174
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c134
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c18
-rw-r--r--source/blender/blenlib/intern/arithb.c51
-rw-r--r--source/blender/blenlib/intern/edgehash.c124
-rw-r--r--source/blender/blenlib/intern/scanfill.c47
-rw-r--r--source/blender/blenloader/intern/readfile.c174
-rw-r--r--source/blender/blenloader/intern/writefile.c2
-rw-r--r--source/blender/blenpluginapi/SConscript2
-rw-r--r--source/blender/bmesh/CMakeLists.txt8
-rw-r--r--source/blender/bmesh/SConscript38
-rw-r--r--source/blender/bmesh/bmesh.h362
-rw-r--r--source/blender/bmesh/bmesh_error.h55
-rw-r--r--source/blender/bmesh/bmesh_filters.h4
-rw-r--r--source/blender/bmesh/bmesh_iterators.h78
-rw-r--r--source/blender/bmesh/bmesh_marking.h52
-rw-r--r--source/blender/bmesh/bmesh_operator_api.h452
-rw-r--r--source/blender/bmesh/bmesh_operators.h93
-rw-r--r--source/blender/bmesh/bmesh_queries.h89
-rw-r--r--source/blender/bmesh/bmesh_walkers.h73
-rw-r--r--source/blender/bmesh/editmesh_tools.c7244
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c601
-rw-r--r--source/blender/bmesh/intern/bmesh_eulers.c1204
-rw-r--r--source/blender/bmesh/intern/bmesh_filters.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c267
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c438
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c710
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c304
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c465
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c894
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c1309
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h65
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c912
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h84
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c562
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c780
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h100
-rw-r--r--source/blender/bmesh/intern/bmesh_to_editmesh.c316
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c917
-rw-r--r--source/blender/bmesh/intern/editmesh_to_bmesh.c474
-rw-r--r--source/blender/bmesh/intern/in-progress/BME_conversions.c478
-rw-r--r--source/blender/bmesh/operators/bmesh_dupeops.c572
-rw-r--r--source/blender/bmesh/operators/connectops.c127
-rw-r--r--source/blender/bmesh/operators/createops.c596
-rw-r--r--source/blender/bmesh/operators/dissolveops.c431
-rw-r--r--source/blender/bmesh/operators/edgesplitop.c357
-rw-r--r--source/blender/bmesh/operators/extrudeops.c310
-rw-r--r--source/blender/bmesh/operators/mesh_conv.c463
-rw-r--r--source/blender/bmesh/operators/mirror.c123
-rw-r--r--source/blender/bmesh/operators/removedoubles.c607
-rw-r--r--source/blender/bmesh/operators/subdivideop.c1043
-rw-r--r--source/blender/bmesh/operators/subdivideop.h38
-rw-r--r--source/blender/bmesh/operators/triangulateop.c56
-rw-r--r--source/blender/bmesh/operators/utils.c1300
-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/CMakeLists.txt54
-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.h129
-rw-r--r--source/blender/editors/include/ED_uvedit.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h14
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/interface/resources.c7
-rw-r--r--source/blender/editors/mesh/SConscript1
-rw-r--r--source/blender/editors/mesh/bmesh_select.c1772
-rw-r--r--source/blender/editors/mesh/bmesh_selecthistory.c126
-rw-r--r--source/blender/editors/mesh/bmesh_tools.c3364
-rw-r--r--source/blender/editors/mesh/bmeshutils.c784
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.c288
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.h15
-rw-r--r--source/blender/editors/mesh/editface.c6
-rw-r--r--source/blender/editors/mesh/editmesh.c378
-rw-r--r--source/blender/editors/mesh/editmesh_add.c255
-rw-r--r--source/blender/editors/mesh/editmesh_lib.c143
-rw-r--r--source/blender/editors/mesh/editmesh_loop.c242
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c2196
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c1742
-rw-r--r--source/blender/editors/mesh/loopcut.c218
-rw-r--r--source/blender/editors/mesh/mesh_data.c78
-rw-r--r--source/blender/editors/mesh/mesh_intern.h78
-rw-r--r--source/blender/editors/mesh/mesh_ops.c55
-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.c48
-rw-r--r--source/blender/editors/object/object_vgroup.c95
-rw-r--r--source/blender/editors/physics/particle_edit.c4
-rw-r--r--source/blender/editors/physics/particle_object.c2
-rw-r--r--source/blender/editors/render/SConscript2
-rw-r--r--source/blender/editors/render/render_shading.c16
-rw-r--r--source/blender/editors/screen/Makefile1
-rw-r--r--source/blender/editors/screen/SConscript2
-rw-r--r--source/blender/editors/screen/screen_ops.c36
-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/paint_vertex.c428
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c6
-rw-r--r--source/blender/editors/space_buttons/SConscript2
-rw-r--r--source/blender/editors/space_image/Makefile1
-rw-r--r--source/blender/editors/space_image/SConscript2
-rw-r--r--source/blender/editors/space_image/image_header.c1
-rw-r--r--source/blender/editors/space_image/space_image.c27
-rw-r--r--source/blender/editors/space_info/Makefile1
-rw-r--r--source/blender/editors/space_info/SConscript2
-rw-r--r--source/blender/editors/space_info/info_stats.c27
-rw-r--r--source/blender/editors/space_node/SConscript2
-rw-r--r--source/blender/editors/space_view3d/SConscript2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c70
-rw-r--r--source/blender/editors/space_view3d/drawobject.c597
-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_select.c173
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c109
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
-rw-r--r--source/blender/editors/transform/SConscript2
-rw-r--r--source/blender/editors/transform/transform.c9
-rw-r--r--source/blender/editors/transform/transform_conversions.c260
-rw-r--r--source/blender/editors/transform/transform_generics.c544
-rw-r--r--source/blender/editors/transform/transform_manipulator.c17
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c139
-rw-r--r--source/blender/editors/transform/transform_snap.c77
-rw-r--r--source/blender/editors/util/ed_util.c8
-rw-r--r--source/blender/editors/uvedit/SConscript2
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c476
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h32
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2121
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h2
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c592
-rw-r--r--source/blender/gpu/gpu_buffers.h2
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c41
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c8
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp35
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h19
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h33
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h38
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/intern/SConscript10
-rw-r--r--source/blender/makesrna/SConscript2
-rw-r--r--source/blender/makesrna/intern/Makefile1
-rw-r--r--source/blender/makesrna/intern/SConscript4
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c319
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_nla.c2
-rw-r--r--source/blender/makesrna/intern/rna_object.c6
-rw-r--r--source/blender/makesrna/intern/rna_pose_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c10
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c2
-rw-r--r--source/blender/python/BPY_menus.c1118
-rw-r--r--source/blender/python/BPY_menus.h128
-rw-r--r--source/blender/python/Makefile2
-rw-r--r--source/blender/python/generic/BGL.c2
-rw-r--r--source/blender/python/generic/BGL.h2
-rw-r--r--source/blender/python/generic/Geometry.c2
-rw-r--r--source/blender/python/generic/Geometry.h2
-rw-r--r--source/blender/python/generic/Mathutils.c2
-rw-r--r--source/blender/python/generic/Mathutils.h2
-rw-r--r--source/blender/python/generic/bpy_internal_import.c2
-rw-r--r--source/blender/python/generic/bpy_internal_import.h2
-rw-r--r--source/blender/python/generic/euler.c2
-rw-r--r--source/blender/python/generic/euler.h2
-rw-r--r--source/blender/python/generic/matrix.c2
-rw-r--r--source/blender/python/generic/matrix.h2
-rw-r--r--source/blender/python/generic/quat.c2
-rw-r--r--source/blender/python/generic/quat.h2
-rw-r--r--source/blender/python/generic/vector.c2
-rw-r--r--source/blender/python/generic/vector.h2
-rw-r--r--source/blender/python/intern/bpy_interface.c3
-rw-r--r--source/blender/python/intern/bpy_operator.h2
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h2
-rw-r--r--source/blender/python/intern/bpy_ui.h2
-rw-r--r--source/blender/readblenfile/intern/BLO_readblenfile.c1
-rw-r--r--source/blender/render/intern/include/rayobject.h208
-rw-r--r--source/blender/render/intern/source/convertblender.c26
-rw-r--r--source/blender/render/intern/source/rayobject_blibvh.c169
-rw-r--r--source/blender/render/intern/source/rayobject_instance.c200
-rw-r--r--source/blender/render/intern/source/rayobject_octree.c1080
-rw-r--r--source/blender/render/intern/source/rayobject_raycounter.c87
-rw-r--r--source/blender/render/intern/source/shadeoutput.c19
-rw-r--r--source/blender/render/intern/source/strand.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c8
-rw-r--r--source/creator/CMakeLists.txt222
-rw-r--r--source/creator/creator.c34
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureActuator.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureChannel.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp2
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.h2
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp10
-rw-r--r--source/gameengine/GameLogic/SCA_BasicEventManager.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_BasicEventManager.h2
-rw-r--r--source/gameengine/Ketsji/KX_ArmatureSensor.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ArmatureSensor.h2
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp14
-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/RAS_OpenGLRasterizer.cpp2
-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.py20
-rwxr-xr-xtools/btools.py3
398 files changed, 75740 insertions, 18485 deletions
diff --git a/SConstruct b/SConstruct
index 6d18000a984..1385e3e7128 100644
--- a/SConstruct
+++ b/SConstruct
@@ -578,7 +578,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc'):
else:
dllsources.append('${BF_SDL_LIBPATH}/SDL.dll')
if env['WITH_BF_PYTHON']:
- if env['BF_DEBUG']:
+ if env['BF_DEBUG'] and not env["BF_NO_PYDEBUG"]:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll')
else:
dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}.dll')
diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py
index 291aa023ec8..bfb8930553d 100644
--- a/config/win32-vc-config.py
+++ b/config/win32-vc-config.py
@@ -149,6 +149,7 @@ CC = 'cl.exe'
CXX = 'cl.exe'
CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267']
+#CCFLAGS += ['/GL']
CXXFLAGS = ['/EHsc']
BGE_CXXFLAGS = ['/O2', '/EHsc', '/GR', '/fp:fast', '/arch:SSE']
@@ -165,8 +166,8 @@ CXX_WARN = []
LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid']
-PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/INCREMENTAL:NO','/NODEFAULTLIB:"msvcprt.lib"','/NODEFAULTLIB:"msvcprtd.lib"','/NODEFAULTLIB:"glut32.lib"','/NODEFAULTLIB:"libc.lib"','/NODEFAULTLIB:"libcd.lib"','/NODEFAULTLIB:"libcpd.lib"','/NODEFAULTLIB:"libcp.lib"','/NODEFAULTLIB:"msvcrt.lib"', '/NODEFAULTLIB:"msvcrtd.lib"', '/NODEFAULTLIB:"msvcmrt.lib"', '/NODEFAULTLIB:"msvcurt.lib"', '/LARGEADDRESSAWARE']
-
+PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/INCREMENTAL:YES','/NODEFAULTLIB:"msvcprt.lib"','/NODEFAULTLIB:"msvcprtd.lib"','/NODEFAULTLIB:"glut32.lib"','/NODEFAULTLIB:"libc.lib"','/NODEFAULTLIB:"libcd.lib"','/NODEFAULTLIB:"libcpd.lib"','/NODEFAULTLIB:"libcp.lib"','/NODEFAULTLIB:"msvcrt.lib"', '/NODEFAULTLIB:"msvcrtd.lib"', '/NODEFAULTLIB:"msvcmrt.lib"', '/NODEFAULTLIB:"msvcurt.lib"', '/LARGEADDRESSAWARE']
+#PLATFORM_LINKFLAGS += ['/LTCG']
# # Todo
# BF_PROFILE_CCFLAGS = ['-pg', '-g ']
# BF_PROFILE_LINKFLAGS = ['-pg']
diff --git a/intern/SoundSystem/CMakeLists.txt b/intern/SoundSystem/CMakeLists.txt
new file mode 100644
index 00000000000..9a370af2268
--- /dev/null
+++ b/intern/SoundSystem/CMakeLists.txt
@@ -0,0 +1,42 @@
+# $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) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+SET(INC . intern ../moto/include ../string dummy openal sdl)
+
+IF(WITH_OPENAL)
+ FILE(GLOB SRC dummy/*.cpp intern/*.cpp openal/*.cpp sdl/*.cpp)
+ INCLUDE_DIRECTORIES(${OPENAL_INC} ${SDL_INC})
+ STRING(REGEX MATCH ".*ramework.*" FRAMEWORK ${OPENAL_INC})
+ IF(FRAMEWORK)
+ ADD_DEFINITIONS(-DAPPLE_FRAMEWORK_FIX)
+ ENDIF(FRAMEWORK)
+ELSE(WITH_OPENAL)
+ FILE(GLOB SRC dummy/*.cpp intern/*.cpp)
+ ADD_DEFINITIONS(-DNO_SOUND)
+ENDIF(WITH_OPENAL)
+
+BLENDERLIB(bf_soundsystem "${SRC}" "${INC}")
+#, libtype=['core','player'], priority = [20,140] )
diff --git a/intern/SoundSystem/Makefile b/intern/SoundSystem/Makefile
new file mode 100644
index 00000000000..4d346f65138
--- /dev/null
+++ b/intern/SoundSystem/Makefile
@@ -0,0 +1,70 @@
+# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# vim: tabstop=8
+#
+# $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): GSR
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+include nan_definitions.mk
+
+LIBNAME = SoundSystem
+SOURCEDIR = intern/SoundSystem
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+DIRS += dummy
+
+ifneq ($(NAN_NO_OPENAL),true)
+ ifeq ($(OS),windows)
+ DIRS += openal sdl
+ endif
+ ifeq ($(OS),darwin)
+ DIRS += openal
+ endif
+ ifeq ($(OS),$(findstring $(OS), "linux freebsd solaris"))
+ DIRS += openal sdl
+ endif
+ ifeq ($(OS), irix)
+ DIRS += sdl
+ endif
+else
+ export CPPFLAGS += -DNO_SOUND
+endif
+
+include nan_subdirs.mk
+
+install: $(ALL_OR_DEBUG)
+ @[ -d $(NAN_SOUNDSYSTEM) ] || mkdir $(NAN_SOUNDSYSTEM)
+ @[ -d $(NAN_SOUNDSYSTEM)/include ] || mkdir $(NAN_SOUNDSYSTEM)/include
+ @[ -d $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR) ] || mkdir $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR)
+ @../tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)libSoundSystem.a $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR)
+ifeq ($(OS),darwin)
+ ranlib $(NAN_SOUNDSYSTEM)/lib/$(DEBUG_DIR)libSoundSystem.a
+endif
+ @../tools/cpifdiff.sh *.h $(NAN_SOUNDSYSTEM)/include/
+
+
diff --git a/intern/SoundSystem/SConscript b/intern/SoundSystem/SConscript
new file mode 100644
index 00000000000..256b7904a0f
--- /dev/null
+++ b/intern/SoundSystem/SConscript
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+
+Import ('env')
+
+sources = env.Glob('dummy/*.cpp') + env.Glob('intern/*.cpp')
+
+incs = '. intern ../moto/include ../string dummy openal sdl'
+defs = ''
+if env['WITH_BF_OPENAL']:
+ sources += env.Glob('openal/*.cpp') + env.Glob('sdl/*.cpp')
+ incs += ' ' + env['BF_OPENAL_INC']
+ incs += ' ' + env['BF_SDL_INC']
+ defs = 'USE_OPENAL'
+else:
+ defs = 'NO_SOUND'
+
+if not env['WITH_BF_SDL']:
+ defs += ' DISABLE_SDL'
+
+env.BlenderLib ('bf_soundsystem', sources, Split(incs), Split(defs), libtype=['intern','player'], priority = [25,135] )
diff --git a/intern/SoundSystem/SND_C-api.h b/intern/SoundSystem/SND_C-api.h
new file mode 100644
index 00000000000..f8e439a9c26
--- /dev/null
+++ b/intern/SoundSystem/SND_C-api.h
@@ -0,0 +1,354 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_BLENDER_H
+#define SND_BLENDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "SoundDefines.h"
+
+#define SND_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+SND_DECLARE_HANDLE(SND_AudioDeviceInterfaceHandle);
+SND_DECLARE_HANDLE(SND_SceneHandle);
+SND_DECLARE_HANDLE(SND_ObjectHandle);
+SND_DECLARE_HANDLE(SND_ListenerHandle);
+
+/**
+ * set the specified type
+ */
+extern void SND_SetDeviceType(int device_type);
+
+/**
+ * get an audiodevice
+ */
+extern SND_AudioDeviceInterfaceHandle SND_GetAudioDevice(void);
+
+/**
+ * and let go of it
+ */
+extern void SND_ReleaseDevice(void);
+
+/**
+ * check if playback is desired
+ */
+extern int SND_IsPlaybackWanted(SND_SceneHandle scene);
+
+/**
+ * add memlocation to cache
+ */
+extern int SND_AddSample(SND_SceneHandle scene,
+ const char* filename,
+ void* memlocation,
+ int size);
+
+/**
+ * remove all samples
+ */
+extern void SND_RemoveAllSamples(SND_SceneHandle scene);
+
+/**
+ * forces the object to check its buffer, and fix it if it's wrong
+ */
+extern int SND_CheckBuffer(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Creates a scene, initializes it and returns a handle to that scene.
+ *
+ * @param audiodevice: handle to the audiodevice.
+ */
+extern SND_SceneHandle SND_CreateScene(SND_AudioDeviceInterfaceHandle audiodevice);
+
+/**
+ * Stops all sounds, suspends the scene (so all resources will be freed) and deletes the scene.
+ *
+ * @param scene: handle to the soundscene.
+ */
+extern void SND_DeleteScene(SND_SceneHandle scene);
+
+/**
+ * Adds a soundobject to the scene, gets the buffer the sample is loaded into.
+ *
+ * @param scene: handle to the soundscene.
+ * @param object: handle to soundobject.
+ */
+extern void SND_AddSound(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Removes a soundobject from the scene.
+ *
+ * @param scene: handle to the soundscene.
+ * @param object: handle to soundobject.
+ */
+extern void SND_RemoveSound(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Removes all soundobjects from the scene.
+ *
+ * @param scene: handle to the soundscene.
+ */
+extern void SND_RemoveAllSounds(SND_SceneHandle scene);
+
+/**
+ * Stopss all soundobjects in the scene.
+ *
+ * @param scene: handle to the soundscene.
+ */
+extern void SND_StopAllSounds(SND_SceneHandle scene);
+
+/**
+ * Updates the listener, checks the status of all soundobjects, builds a list of all active
+ * objects, updates the active objects.
+ *
+ * @param audiodevice: handle to the audiodevice.
+ * @param scene: handle to the soundscene.
+ */
+extern void SND_Proceed(SND_AudioDeviceInterfaceHandle audiodevice, SND_SceneHandle scene);
+
+/**
+ * Returns a handle to the listener.
+ *
+ * @param scene: handle to the soundscene.
+ */
+extern SND_ListenerHandle SND_GetListener(SND_SceneHandle scene);
+
+/**
+ * Sets the gain of the listener.
+ *
+ * @param scene: handle to the soundscene.
+ * @param gain: factor the gain gets multiplied with.
+ */
+extern void SND_SetListenerGain(SND_SceneHandle scene, double gain);
+
+/**
+ * Sets a scaling to exaggerate or deemphasize the Doppler (pitch) shift resulting from the
+ * calculation.
+ * @attention $f' = dopplerfactor * f * frac{dopplervelocity - listener_velocity}{dopplervelocity + object_velocity}$
+ * @attention f: frequency in sample (soundobject)
+ * @attention f': effective Doppler shifted frequency
+ *
+ * @param object: handle to soundobject.
+ * @param dopplerfactor: the dopplerfactor.
+ */
+extern void SND_SetDopplerFactor(SND_SceneHandle scene, double dopplerfactor);
+
+/**
+ * Sets the value of the propagation speed relative to which the source velocities are interpreted.
+ * @attention $f' = dopplerfactor * f * frac{dopplervelocity - listener_velocity}{dopplervelocity + object_velocity}$
+ * @attention f: frequency in sample (soundobject)
+ * @attention f': effective Doppler shifted frequency
+ *
+ * @param object: handle to soundobject.
+ * @param dopplervelocity: the dopplervelocity.
+ */
+extern void SND_SetDopplerVelocity(SND_SceneHandle scene, double dopplervelocity);
+
+/**
+ * Creates a new soundobject and returns a handle to it.
+ */
+extern SND_ObjectHandle SND_CreateSound(void);
+
+/**
+ * Deletes a soundobject.
+ *
+ * @param object: handle to soundobject.
+ */
+extern void SND_DeleteSound(SND_ObjectHandle object);
+
+/**
+ * Sets a soundobject to SND_MUST_PLAY, so with the next proceed it will be updated and played.
+ *
+ * @param object: handle to soundobject.
+ */
+extern void SND_StartSound(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Sets a soundobject to SND_MUST_STOP, so with the next proceed it will be stopped.
+ *
+ * @param object: handle to soundobject.
+ */
+extern void SND_StopSound(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Sets a soundobject to SND_MUST_PAUSE, so with the next proceed it will be paused.
+ *
+ * @param object: handle to soundobject.
+ */
+extern void SND_PauseSound(SND_SceneHandle scene, SND_ObjectHandle object);
+
+/**
+ * Sets the name of the sample to reference the soundobject to it.
+ *
+ * @param object: handle to soundobject.
+ * @param samplename: the name of the sample
+ */
+extern void SND_SetSampleName(SND_ObjectHandle object, char* samplename);
+
+/**
+ * Sets the gain of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param gain: factor the gain gets multiplied with.
+ */
+extern void SND_SetGain(SND_ObjectHandle object, double gain);
+
+/**
+ * Sets the minimum gain of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param minimumgain: lower threshold for the gain.
+ */
+extern void SND_SetMinimumGain(SND_ObjectHandle object, double minimumgain);
+
+/**
+ * Sets the maximum gain of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param maximumgain: upper threshold for the gain.
+ */
+extern void SND_SetMaximumGain(SND_ObjectHandle object, double maximumgain);
+
+/**
+ * Sets the rollofffactor. The rollofffactor is a per-Source parameter the application
+ * can use to increase or decrease the range of a source by decreasing or increasing the
+ * attenuation, respectively. The default value is 1. The implementation is free to optimize
+ * for a rollofffactor value of 0, which indicates that the application does not wish any
+ * distance attenuation on the respective Source.
+ *
+ * @param object: handle to soundobject.
+ * @param rollofffactor: the rollofffactor.
+ */
+extern void SND_SetRollOffFactor(SND_ObjectHandle object, double rollofffactor);
+
+/**
+ * Sets the referencedistance at which the listener will experience gain.
+ * @attention G_dB = gain - 20 * log10(1 + rollofffactor * (dist - referencedistance)/referencedistance);
+ *
+ * @param object: handle to soundobject.
+ * @param distance: the reference distance.
+ */
+extern void SND_SetReferenceDistance(SND_ObjectHandle object, double referencedistance);
+
+/**
+ * Sets the pitch of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param pitch: pitchingfactor: 2.0 for doubling the frequency, 0.5 for half the frequency.
+ */
+extern void SND_SetPitch(SND_ObjectHandle object, double pitch);
+
+/**
+ * Sets the position a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param position: position[3].
+ */
+extern void SND_SetPosition(SND_ObjectHandle object, double* position);
+
+/**
+ * Sets the velocity of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param velocity: velocity[3].
+ */
+extern void SND_SetVelocity(SND_ObjectHandle object, double* velocity);
+
+/**
+ * Sets the orientation of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param orientation: orientation[9].
+ */
+extern void SND_SetOrientation(SND_ObjectHandle object, double* orientation);
+
+/**
+ * Sets the loopmode of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param loopmode type of the loop (SND_LOOP_OFF, SND_LOOP_NORMAL, SND_LOOP_BIDIRECTIONAL);
+ */
+extern void SND_SetLoopMode(SND_ObjectHandle object, int loopmode);
+
+/**
+ * Sets the looppoints of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ * @param loopstart startpoint of the loop
+ * @param loopend endpoint of the loop
+ */
+extern void SND_SetLoopPoints(SND_ObjectHandle object, unsigned int loopstart, unsigned int loopend);
+
+/**
+ * Gets the gain of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ */
+extern float SND_GetGain(SND_ObjectHandle object);
+
+/**
+ * Gets the pitch of a soundobject.
+ *
+ * @param object: handle to soundobject.
+ */
+extern float SND_GetPitch(SND_ObjectHandle object);
+
+/**
+ * Gets the looping of a soundobject.
+ * 0: SND_LOOP_OFF
+ * 1: SND_LOOP_NORMAL
+ * 2: SND_LOOP_BIDIRECTIONAL
+ *
+ * @param object: handle to soundobject.
+ */
+extern int SND_GetLoopMode(SND_ObjectHandle object);
+
+/**
+ * Gets the playstate of a soundobject.
+ * SND_UNKNOWN = -1
+ * SND_INITIAL
+ * SND_MUST_PLAY
+ * SND_PLAYING
+ * SND_MUST_STOP
+ * SND_STOPPED
+ * SND_MUST_PAUSE
+ * SND_PAUSED
+ * SND_MUST_BE_DELETED
+ *
+ * @param object: handle to soundobject.
+ */
+extern int SND_GetPlaystate(SND_ObjectHandle object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/intern/SoundSystem/SND_CDObject.h b/intern/SoundSystem/SND_CDObject.h
new file mode 100644
index 00000000000..c79f62d9862
--- /dev/null
+++ b/intern/SoundSystem/SND_CDObject.h
@@ -0,0 +1,83 @@
+/*
+ * SND_CDObject.h
+ *
+ * Implementation for CD playback
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_CDOBJECT_H
+#define __SND_CDOBJECT_H
+
+#include "SND_Object.h"
+
+class SND_CDObject : public SND_Object
+{
+private:
+
+ /**
+ * Private to enforce singleton
+ */
+ SND_CDObject();
+ SND_CDObject(const SND_CDObject&);
+
+ static SND_CDObject* m_instance;
+ MT_Scalar m_gain; /* the gain of the object */
+ int m_playmode; /* the way CD is played back (all, random, track, trackloop) */
+ int m_track; /* the track for 'track' and 'trackloop' */
+ int m_playstate; /* flag for current state of object */
+ bool m_modified;
+ bool m_used; /* flag for checking if we used the cd, if not don't
+ call the stop cd at the end */
+
+public:
+ static bool CreateSystem();
+ static bool DisposeSystem();
+ static SND_CDObject* Instance();
+
+ ~SND_CDObject();
+
+ void SetGain(MT_Scalar gain);
+ void SetPlaymode(int playmode);
+ void SetTrack(int track);
+ void SetPlaystate(int playstate);
+ void SetModified(bool modified);
+ void SetUsed();
+ bool GetUsed();
+
+ bool IsModified() const;
+
+ int GetTrack() const;
+ MT_Scalar GetGain() const;
+ int GetPlaymode() const;
+ int GetPlaystate() const;
+
+};
+
+#endif //__SND_CDOBJECT_H
+
diff --git a/intern/SoundSystem/SND_DependKludge.h b/intern/SoundSystem/SND_DependKludge.h
new file mode 100644
index 00000000000..06d4ec9c0c9
--- /dev/null
+++ b/intern/SoundSystem/SND_DependKludge.h
@@ -0,0 +1,50 @@
+/*
+ * SND_DependKludge.h
+ *
+ * who needs what?
+ *
+ * $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 *****
+ */
+
+#ifndef HAVE_CONFIG_H
+
+#ifndef NO_SOUND
+
+#if defined (_WIN32) && !defined(FREE_WINDOWS)
+# define USE_OPENAL
+#elif defined (__linux__) || (__FreeBSD__) || defined(__APPLE__) || defined(__sun)
+# define USE_OPENAL
+#else
+# ifdef USE_OPENAL
+# undef USE_OPENAL
+# endif
+#endif
+
+#endif /* NO_SOUND */
+
+#endif /* HAVE_CONFIG_H */
diff --git a/intern/SoundSystem/SND_DeviceManager.h b/intern/SoundSystem/SND_DeviceManager.h
new file mode 100644
index 00000000000..708db030519
--- /dev/null
+++ b/intern/SoundSystem/SND_DeviceManager.h
@@ -0,0 +1,79 @@
+/*
+ * SND_DeviceManager.h
+ *
+ * singleton for creating, switching and deleting audiodevices
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_DEVICEMANAGER_H
+#define __SND_DEVICEMANAGER_H
+
+#include "SND_IAudioDevice.h"
+
+class SND_DeviceManager
+{
+public :
+
+ /**
+ * a subscription is needed before instances are given away
+ * applications must call subscribe first, get an instance, and
+ * when they are finished with sound, unsubscribe
+ */
+ static void Subscribe();
+ static void Unsubscribe();
+
+ static SND_IAudioDevice* Instance();
+ static void SetDeviceType(int device_type);
+
+private :
+
+ /**
+ * Private to enforce singleton
+ */
+ SND_DeviceManager();
+ SND_DeviceManager(const SND_DeviceManager&);
+ ~SND_DeviceManager();
+
+ static SND_IAudioDevice* m_instance;
+
+ /**
+ * The type of device to be created on a call
+ * to Instance().
+ */
+ static int m_device_type;
+
+ /**
+ * Remember the number of subscriptions.
+ * if 0, delete the device
+ */
+ static int m_subscriptions;
+};
+
+#endif //__SND_DEVICEMANAGER_H
+
diff --git a/intern/SoundSystem/SND_IAudioDevice.h b/intern/SoundSystem/SND_IAudioDevice.h
new file mode 100644
index 00000000000..d6b3936e6ef
--- /dev/null
+++ b/intern/SoundSystem/SND_IAudioDevice.h
@@ -0,0 +1,343 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_IAUDIODEVICE
+#define SND_IAUDIODEVICE
+
+#include "SND_SoundObject.h"
+#include "SND_CDObject.h"
+#include "SND_WaveCache.h"
+#include "SND_WaveSlot.h"
+#include "MT_Matrix3x3.h"
+
+class SND_IAudioDevice
+{
+public:
+
+ /**
+ * constructor
+ */
+ SND_IAudioDevice() {};
+
+ /**
+ * destructor
+ */
+ virtual ~SND_IAudioDevice() {};
+
+ /**
+ * check to see if initialization was successfull
+ *
+ * @return indication of succes
+ */
+ virtual bool IsInitialized()=0;
+
+ /**
+ * get the wavecache (which does sample (un)loading)
+ *
+ * @return pointer to the wavecache
+ */
+ virtual SND_WaveCache* GetWaveCache() const =0;
+
+ /**
+ * loads a sample into the device
+ *
+ * @param samplename the name of the sample
+ * @param memlocation pointer where the sample is stored
+ * @param size size of the sample in memory
+ *
+ * @return pointer to the slot with sample data
+ */
+ virtual SND_WaveSlot* LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size)=0;
+
+ /**
+ * remove a sample from the wavecache
+ *
+ * @param filename pointer to filename
+ */
+// virtual void RemoveSample(const char* filename)=0;
+
+ /**
+ * remove all samples from the wavecache
+ */
+ virtual void RemoveAllSamples()=0;
+
+ /**
+ * get a new id from the device
+ *
+ * @param pObject pointer to soundobject
+ *
+ * @return indication of success
+ */
+ virtual bool GetNewId(SND_SoundObject* pObject)=0;
+
+ /**
+ * clear an id
+ *
+ * @param pObject pointer to soundobject
+ */
+ virtual void ClearId(SND_SoundObject* pObject)=0;
+
+ /**
+ * initialize the listener
+ */
+ virtual void InitListener()=0;
+
+ /**
+ * set the value of the propagation speed relative to which the
+ * source velocities are interpreted.
+ * f' = DOPPLER_FACTOR * f * (DOPPLER_VELOCITY - Vl) / (DOPPLER_VELOCITY + Vo)
+ * f: frequency in sample (soundobject)
+ * f': effective Doppler shifted frequency
+ * Vl: velocity listener
+ * Vo: velocity soundobject
+ *
+ * @param dopplervelocity scaling factor for doppler effect
+ */
+ virtual void SetDopplerVelocity(MT_Scalar dopplervelocity) const =0;
+
+ /**
+ * set a scaling to exaggerate or deemphasize the Doppler (pitch)
+ * shift resulting from the calculation.
+ * f' = DOPPLER_FACTOR * f * (DOPPLER_VELOCITY - Listener_velocity )/(DOPPLER_VELOCITY + object_velocity )
+ *
+ * @param dopplerfactor scaling factor for doppler effect
+ */
+ virtual void SetDopplerFactor(MT_Scalar dopplerfactor) const =0;
+
+ /**
+ * set the roll-off factor
+ *
+ * @param rollofffactor a global volume scaling factor
+ */
+ virtual void SetListenerRollOffFactor(MT_Scalar rollofffactor) const =0;
+
+ /**
+ * make the context the current one
+ */
+ virtual void MakeCurrent() const =0;
+
+ /**
+ * update the device
+ */
+ virtual void NextFrame() const =0;
+
+ /**
+ * set the volume of the listener.
+ *
+ * @param gain the mastergain
+ */
+ virtual void SetListenerGain(float gain) const =0;
+
+ /**
+ * connect the buffer with the source
+ *
+ * @param id the id of the object
+ * @param buffer the buffer the sample is stored in
+ */
+ virtual void SetObjectBuffer(int id, unsigned int buffer)=0;
+
+ /**
+ * pause playback of the cd
+ * @param id the id of the object
+ *
+ * @return the state the object is in
+ */
+ virtual int GetPlayState(int id) =0;
+
+ /**
+ * play a sound belonging to an object.
+ *
+ * @param id the id of the object
+ */
+ virtual void PlayObject(int id) =0;
+
+ /**
+ * stop a sound belonging to an object.
+ *
+ * @param id the id of the object
+ */
+ virtual void StopObject(int id) const =0;
+
+ /**
+ * stop all sounds.
+ */
+ virtual void StopAllObjects()=0;
+
+ /**
+ * pause the sound belonging to an object.
+ *
+ * @param id the id of the object
+ */
+ virtual void PauseObject(int id) const =0;
+
+ /**
+ * set the sound to looping or non-looping.
+ *
+ * @param id the id of the object
+ * @param loopmode type of looping (no loop, normal, bidirectional)
+ */
+ virtual void SetObjectLoop(int id, unsigned int loopmode) const =0;
+
+ /**
+ * set the looppoints of a sound
+ *
+ * @param id the id of the object
+ * @param loopstart the startpoint of the loop (in samples)
+ * @param loopend the endpoint of the loop (in samples)
+ */
+ virtual void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const =0;
+
+ /**
+ * set the pitch of the sound.
+ *
+ * @param id the id of the object
+ * @param pitch the pitch
+ */
+ virtual void SetObjectPitch(int id, MT_Scalar pitch) const =0;
+
+ /**
+ * set the gain of the sound.
+ *
+ * @param id the id of the object
+ * @param gain the gain
+ */
+ virtual void SetObjectGain(int id, MT_Scalar gain) const =0;
+
+ /**
+ * ROLLOFF_FACTOR is per-Source parameter the application can use to increase or decrease
+ * the range of a source by decreasing or increasing the attenuation, respectively. The
+ * default value is 1. The implementation is free to optimize for a ROLLOFF_FACTOR value
+ * of 0, which indicates that the application does not wish any distance attenuation on
+ * the respective Source.
+ *
+ * @param id the id of the object
+ * @param rolloff a per-source volume scaling factor
+ */
+ virtual void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const =0;
+
+ /**
+ * min_gain indicates the minimal gain which is always guaranteed for this sound
+ *
+ * @param id the id of the object
+ * @param mingain the minimum gain of the object
+ */
+ virtual void SetObjectMinGain(int id, MT_Scalar mingain) const =0;
+
+ /**
+ * max_gain indicates the maximal gain which is always guaranteed for this sound
+ *
+ * @param id the id of the object
+ * @param maxgain the maximum gain of the object
+ */
+ virtual void SetObjectMaxGain(int id, MT_Scalar maxgain) const =0;
+ /**
+ * set the distance at which the Listener will experience gain.
+ * G_dB = GAIN - 20*log10(1 + ROLLOFF_FACTOR*(dist-REFERENCE_DISTANCE)/REFERENCE_DISTANCE );
+ *
+ * @param id the id of the object
+ * @param referencedistance the distance at which the listener will start hearing
+ */
+ virtual void SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const =0;
+
+ /**
+ * set the position, velocity and orientation of a sound.
+ *
+ * @param id the id of the object
+ * @param position the position of the object
+ * @param velocity the velocity of the object
+ * @param orientation the orientation of the object
+ * @param lisposition the position of the listener
+ * @param rollofffactor the rollofffactor of the object
+ */
+ virtual void SetObjectTransform(int id,
+ const MT_Vector3& position,
+ const MT_Vector3& velocity,
+ const MT_Matrix3x3& orientation,
+ const MT_Vector3& lisposition,
+ const MT_Scalar& rollofffactor) const =0;
+
+ /**
+ * make a sound 2D
+ *
+ * @param id the id of the object
+ */
+ virtual void ObjectIs2D(int id) const =0;
+
+ /**
+ * tell the device we want cd suppport
+ */
+ virtual void UseCD() const =0;
+
+ /**
+ * start playback of the cd
+ *
+ * @param track the tracknumber to start playback from
+ */
+ virtual void PlayCD(int track) const =0;
+
+ /**
+ * pause playback of the cd (true == pause, false == resume)
+ */
+ virtual void PauseCD(bool pause) const =0;
+
+ /**
+ * stop playback of the cd
+ */
+ virtual void StopCD() const =0;
+
+ /**
+ * set the playbackmode of the cd
+ * SND_CD_ALL play all tracks
+ * SND_CD_TRACK play one track
+ * SND_CD_TRACKLOOP play one track looped
+ * SND_CD_RANDOM play all tracks in random order
+ *
+ * @param playmode playmode
+ */
+ virtual void SetCDPlaymode(int playmode) const =0;
+
+ /**
+ * set the volume playback of the cd
+ *
+ * @param gain the gain
+ */
+ virtual void SetCDGain(MT_Scalar gain) const =0;
+
+ virtual void StartUsingDSP() =0;
+ virtual float* GetSpectrum() =0;
+ virtual void StopUsingDSP() =0;
+
+protected:
+
+ virtual void RevokeSoundObject(SND_SoundObject* pObject)=0;
+};
+
+#endif //SND_IAUDIODEVICE
+
diff --git a/intern/SoundSystem/SND_Object.h b/intern/SoundSystem/SND_Object.h
new file mode 100644
index 00000000000..f23827974e3
--- /dev/null
+++ b/intern/SoundSystem/SND_Object.h
@@ -0,0 +1,54 @@
+/*
+ * SND_Object.h
+ *
+ * Abstract sound object
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_OBJECT_H
+#define __SND_OBJECT_H
+
+#include "GEN_List.h"
+#include "MT_Matrix3x3.h"
+#include "SoundDefines.h"
+
+/**
+ * SND_Object is an interface class for soundobjects, listeners and other
+ * kinds of sound related thingies.
+ */
+
+class SND_Object : public GEN_Link
+{
+public:
+ SND_Object() {};
+ virtual ~SND_Object() {};
+};
+
+#endif //__SND_OBJECT_H
+
diff --git a/intern/SoundSystem/SND_Scene.h b/intern/SoundSystem/SND_Scene.h
new file mode 100644
index 00000000000..bb3ff932bce
--- /dev/null
+++ b/intern/SoundSystem/SND_Scene.h
@@ -0,0 +1,104 @@
+/*
+ * SND_Scene.h
+ *
+ * The scene for sounds.
+ *
+ * $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 *****
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#ifndef __SND_SCENE_H
+#define __SND_SCENE_H
+
+#include "SoundDefines.h"
+#include "SND_SoundObject.h"
+#include "SND_CDObject.h"
+#include "SND_SoundListener.h"
+#include "SND_WaveSlot.h"
+
+#include "MT_Vector3.h"
+#include "MT_Matrix3x3.h"
+#include "STR_String.h"
+
+#include <set>
+
+
+class SND_Scene
+{
+ std::set<class SND_SoundObject*> m_soundobjects;
+
+ GEN_List m_activeobjects;
+ class SND_IAudioDevice* m_audiodevice;
+ class SND_WaveCache* m_wavecache;
+ class SND_SoundListener m_listener;
+ bool m_audio; // to check if audio works
+ bool m_audioplayback; // to check if audioplayback is wanted
+
+ void UpdateListener();
+ void BuildActiveList(MT_Scalar curtime);
+ void UpdateActiveObects();
+ void UpdateCD();
+
+public:
+ SND_Scene(SND_IAudioDevice* adi);
+ ~SND_Scene();
+
+ bool IsPlaybackWanted();
+
+ void AddActiveObject(SND_SoundObject* pObject, MT_Scalar curtime);
+ void RemoveActiveObject(SND_SoundObject* pObject);
+ void DeleteObjectWhenFinished(SND_SoundObject* pObject);
+
+ void Proceed();
+
+ int LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size);
+ void RemoveAllSamples();
+ bool CheckBuffer(SND_SoundObject* pObject);
+ bool IsSampleLoaded(STR_String& samplename);
+
+ void AddObject(SND_SoundObject* pObject);
+ bool SetCDObject(SND_CDObject* cdobject);
+ void DeleteObject(SND_SoundObject* pObject);
+ void RemoveAllObjects();
+ void StopAllObjects();
+ int GetObjectStatus(SND_SoundObject* pObject) const;
+
+ void SetListenerTransform(const MT_Vector3& pos,
+ const MT_Vector3& vel,
+ const MT_Matrix3x3& mat);
+
+ SND_SoundListener* GetListener();
+};
+
+#endif //__SND_SCENE_H
+
diff --git a/intern/SoundSystem/SND_SoundListener.h b/intern/SoundSystem/SND_SoundListener.h
new file mode 100644
index 00000000000..2f6a6e8cddd
--- /dev/null
+++ b/intern/SoundSystem/SND_SoundListener.h
@@ -0,0 +1,82 @@
+/*
+ * SND_SoundListener.h
+ *
+ * A SoundListener is for sound what a camera is for vision.
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_SOUNDLISTENER_H
+#define __SND_SOUNDLISTENER_H
+
+#include "SND_Object.h"
+
+class SND_SoundListener : public SND_Object
+{
+public:
+ SND_SoundListener();
+ virtual ~SND_SoundListener();
+
+ void SetStateFlag(unsigned int stateflags);
+ void SetGain(MT_Scalar gain);
+ void SetPosition(const MT_Vector3& pos);
+ void SetVelocity(const MT_Vector3& vel);
+ void SetOrientation(const MT_Matrix3x3& ori);
+ void SetDopplerFactor(MT_Scalar dopplerfactor);
+ void SetDopplerVelocity(MT_Scalar dopplervelocity);
+ void SetScale(MT_Scalar scale);
+
+ void SetModified(bool modified);
+ bool IsModified() const;
+
+ unsigned int GetStateFlags() const;
+ MT_Scalar GetGain() const;
+ MT_Vector3 GetPosition() const;
+ MT_Vector3 GetVelocity() const;
+ MT_Matrix3x3 GetOrientation();
+
+ MT_Scalar GetDopplerFactor() const;
+ MT_Scalar GetDopplerVelocity() const;
+ MT_Scalar GetScale() const;
+
+private:
+ void* m_listener;
+ bool m_modified;
+
+ MT_Scalar m_gain; /* overall gain */
+ MT_Vector3 m_position; /* position; left/right, up/down, in/out */
+ MT_Vector3 m_velocity; /* velocity of the listener */
+ MT_Matrix3x3 m_orientation; /* orientation of the listener */
+
+ MT_Scalar m_dopplerfactor; /* scaling factor for the Doppler (pitch) shift */
+ MT_Scalar m_dopplervelocity; /* factor for the reference velocity (for Dopplereffect) */
+ MT_Scalar m_scale;
+};
+
+#endif //__SND_SOUNDLISTENER_H
+
diff --git a/intern/SoundSystem/SND_SoundObject.h b/intern/SoundSystem/SND_SoundObject.h
new file mode 100644
index 00000000000..7bd43fb4e66
--- /dev/null
+++ b/intern/SoundSystem/SND_SoundObject.h
@@ -0,0 +1,159 @@
+/*
+ * SND_SoundObject.h
+ *
+ * Implementation of the abstract sound object
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_SOUNDOBJECT_H
+#define __SND_SOUNDOBJECT_H
+
+#include "SND_Object.h"
+#include "STR_String.h"
+
+/**
+ * SND_SoundObject is a class for api independent sounddata storage conected to an actuator
+ */
+
+class SND_SoundObject : public SND_Object
+{
+private:
+ STR_String m_samplename; /* name of the sample */
+ STR_String m_objectname; /* name of the object */
+ unsigned int m_buffer;
+
+ bool m_active; /* is the object active or not? */
+ int m_id;
+ MT_Scalar m_lifespan; /* the lifespan of the sound seconds */
+ MT_Scalar m_timestamp;
+
+ MT_Scalar m_length; /* length of the sample in seconds */
+
+ MT_Scalar m_gain; /* the gain of the object */
+ MT_Scalar m_rollofffactor; /* the scaling factor to increase or decrease the range
+ of a source by decreasing or increasing the
+ attenuation, respectively */
+ MT_Scalar m_referencedistance;/* the distance at which the listener will experience
+ gain */
+ MT_Scalar m_mingain; /* indicates the minimal gain which is always guaranteed
+ for this source */
+ MT_Scalar m_maxgain; /* indicates the maximal gain which is always guaranteed
+ for this source */
+
+ MT_Scalar m_pitch; /* the pitch of the object */
+ MT_Vector3 m_position; /* position; left/right, up/down, in/out */
+ MT_Vector3 m_velocity; /* velocity of the object */
+ MT_Matrix3x3 m_orientation; /* orientation of the object */
+ unsigned int m_loopmode; /* loop normal or bidirectional? */
+ unsigned int m_loopstart; /* start of looppoint in samples! */
+ unsigned int m_loopend; /* end of looppoint in samples! */
+ bool m_is3d; /* is the object 3D or 2D? */
+ int m_playstate; /* flag for current state of object */
+ bool m_modified;
+ unsigned int m_running;
+ bool m_highpriority; /* may the sound be ditched when we run out of voices? */
+
+public:
+
+ SND_SoundObject();
+ ~SND_SoundObject();
+
+ void SetBuffer(unsigned int buffer);
+ void SetActive(bool active);
+
+ void StartSound();
+ void StopSound();
+ void PauseSound();
+ void DeleteWhenFinished();
+
+ void SetObjectName(STR_String objectname);
+ void SetSampleName(STR_String samplename);
+ void SetLength(MT_Scalar length);
+
+ void SetPitch(MT_Scalar pitch);
+ void SetGain(MT_Scalar gain);
+ void SetMinGain(MT_Scalar mingain);
+ void SetMaxGain(MT_Scalar maxgain);
+ void SetRollOffFactor(MT_Scalar rollofffactor);
+ void SetReferenceDistance(MT_Scalar distance);
+ void SetPosition(const MT_Vector3& pos);
+ void SetVelocity(const MT_Vector3& vel);
+ void SetOrientation(const MT_Matrix3x3& orient);
+ void SetLoopMode(unsigned int loopmode);
+ void SetLoopStart(unsigned int loopstart);
+ void SetLoopEnd(unsigned int loopend);
+ void Set3D(bool threedee);
+ void SetPlaystate(int playstate);
+ void SetHighPriority(bool priority);
+
+ void SetId(int id);
+ void SetLifeSpan();
+ void SetTimeStamp(MT_Scalar timestamp);
+
+ void SetModified(bool modified);
+
+ bool IsLifeSpanOver(MT_Scalar curtime) const;
+ bool IsActive() const;
+ bool IsModified() const;
+ bool IsHighPriority() const;
+
+ void InitRunning();
+ bool IsRunning() const;
+ void AddRunning();
+
+ int GetId() const;
+ MT_Scalar GetLifeSpan() const;
+ MT_Scalar GetTimestamp() const;
+
+ unsigned int GetBuffer();
+ const STR_String& GetSampleName();
+ const STR_String& GetObjectName();
+
+ MT_Scalar GetLength() const;
+ MT_Scalar GetGain() const;
+ MT_Scalar GetPitch() const;
+
+ MT_Scalar GetMinGain() const;
+ MT_Scalar GetMaxGain() const;
+ MT_Scalar GetRollOffFactor() const;
+ MT_Scalar GetReferenceDistance() const;
+
+ MT_Vector3 GetPosition() const;
+ MT_Vector3 GetVelocity() const;
+ MT_Matrix3x3 GetOrientation() const;
+ unsigned int GetLoopMode() const;
+ unsigned int GetLoopStart() const;
+ unsigned int GetLoopEnd() const;
+ bool Is3D() const;
+ int GetPlaystate() const;
+
+};
+
+#endif //__SND_SOUNDOBJECT_H
+
diff --git a/intern/SoundSystem/SND_Utils.h b/intern/SoundSystem/SND_Utils.h
new file mode 100644
index 00000000000..82b7c69a595
--- /dev/null
+++ b/intern/SoundSystem/SND_Utils.h
@@ -0,0 +1,111 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_UTILS_H
+#define SND_UTILS_H
+
+#include "SND_WaveSlot.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct
+{
+ unsigned char riff[4];
+ signed int size;
+ unsigned char type[4];
+} WavFileHeader;
+
+typedef struct
+{
+ unsigned short format;
+ unsigned short numberofchannels;
+ unsigned int samplerate;
+ unsigned int bytespersec;
+ unsigned short blockalignment;
+ unsigned short bitrate;
+} WavFmtHeader;
+
+typedef struct
+{
+ unsigned short size;
+ unsigned short samplesperblock;
+} WavFmtExHeader;
+
+typedef struct
+{
+ unsigned int Manufacturer;
+ unsigned int Product;
+ unsigned int SamplePeriod;
+ unsigned int Note;
+ unsigned int FineTune;
+ unsigned int SMPTEFormat;
+ unsigned int SMPTEOffest;
+ unsigned int loops;
+ unsigned int SamplerData;
+ struct
+ {
+ unsigned int Identifier;
+ unsigned int Type;
+ unsigned int Start;
+ unsigned int End;
+ unsigned int Fraction;
+ unsigned int Count;
+ } Loop[1];
+} WavSampleHeader;
+
+typedef struct
+{
+ unsigned char id[4];
+ unsigned int size;
+} WavChunkHeader;
+
+/**
+ * loads a sample and returns a pointer
+ */
+extern void* SND_LoadSample(char *filename);
+
+extern bool SND_IsSampleValid(const STR_String& name, void* memlocation);
+extern unsigned int SND_GetSampleFormat(void* sample);
+extern unsigned int SND_GetNumberOfChannels(void* sample);
+extern unsigned int SND_GetSampleRate(void* sample);
+extern unsigned int SND_GetBitRate(void* sample);
+extern unsigned int SND_GetNumberOfSamples(void* sample, unsigned int sample_length);
+extern unsigned int SND_GetHeaderSize(void* sample, unsigned int sample_length);
+extern unsigned int SND_GetExtraChunk(void* sample);
+
+extern void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/intern/SoundSystem/SND_WaveCache.h b/intern/SoundSystem/SND_WaveCache.h
new file mode 100644
index 00000000000..2c457797768
--- /dev/null
+++ b/intern/SoundSystem/SND_WaveCache.h
@@ -0,0 +1,66 @@
+/*
+ * SND_WaveCache.h
+ *
+ * abstract wavecache, a way to organize samples
+ *
+ * $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 *****
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#ifndef __SND_WAVECACHE_H
+#define __SND_WAVECACHE_H
+
+#include "SND_WaveSlot.h"
+#include "SoundDefines.h"
+#include "SND_SoundObject.h"
+#include <map>
+
+class SND_WaveCache
+{
+public:
+ SND_WaveCache();
+ virtual ~SND_WaveCache();
+
+ SND_WaveSlot* GetWaveSlot(const STR_String& samplename);
+
+ void RemoveAllSamples();
+ void RemoveSample(const STR_String& samplename, int buffer);
+
+private:
+ std::map<STR_String, SND_WaveSlot*> m_samplecache;
+
+ SND_WaveSlot* m_bufferList[NUM_BUFFERS];
+
+ void FreeSamples();
+};
+
+#endif //__SND_WAVECACHE_H
+
diff --git a/intern/SoundSystem/SND_WaveSlot.h b/intern/SoundSystem/SND_WaveSlot.h
new file mode 100644
index 00000000000..75cddfa36d8
--- /dev/null
+++ b/intern/SoundSystem/SND_WaveSlot.h
@@ -0,0 +1,92 @@
+/*
+ * SND_WaveSlot.cpp
+ *
+ * class for storing sample related information
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_WAVESLOT_H
+#define __SND_WAVESLOT_H
+
+#include "STR_String.h"
+
+class SND_WaveSlot
+{
+ STR_String m_samplename;
+ bool m_loaded;
+ void* m_data;
+ unsigned int m_buffer;
+ unsigned int m_sampleformat;
+ unsigned int m_numberofchannels;
+ unsigned int m_samplerate;
+ unsigned int m_bitrate;
+ unsigned int m_numberofsamples;
+ unsigned int m_filesize;
+
+public:
+
+ SND_WaveSlot(): m_loaded(false),
+ m_data(NULL),
+ m_buffer(0),
+ m_sampleformat(0),
+ m_numberofchannels(0),
+ m_samplerate(0),
+ m_bitrate(0),
+ m_numberofsamples(0),
+ m_filesize(0)
+ {};
+ ~SND_WaveSlot();
+
+ void SetSampleName(STR_String samplename);
+ void SetLoaded(bool loaded);
+ void SetData(void* data);
+ void SetBuffer(unsigned int buffer);
+ void SetSampleFormat(unsigned int sampleformat);
+ void SetNumberOfChannels(unsigned int numberofchannels);
+ void SetSampleRate(unsigned int samplerate);
+ void SetBitRate(unsigned int bitrate);
+ void SetNumberOfSamples(unsigned int numberofsamples);
+ void SetFileSize(unsigned int filesize);
+
+
+ const STR_String& GetSampleName();
+ bool IsLoaded() const;
+ void* GetData();
+ unsigned int GetBuffer() const;
+ unsigned int GetSampleFormat() const;
+ unsigned int GetNumberOfChannels() const;
+ unsigned int GetSampleRate() const;
+ unsigned int GetBitRate() const;
+ unsigned int GetNumberOfSamples() const;
+ unsigned int GetFileSize() const;
+
+};
+
+#endif //__SND_WAVESLOT_H
+
diff --git a/intern/SoundSystem/SND_test/Makefile b/intern/SoundSystem/SND_test/Makefile
new file mode 100644
index 00000000000..279eeace0d8
--- /dev/null
+++ b/intern/SoundSystem/SND_test/Makefile
@@ -0,0 +1,48 @@
+#
+# $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 = soundsystem
+DIR = $(OCGDIR)/intern/SoundSystem
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)SoundSystem
+
+include nan_compile.mk
+
+CPPFLAGS += $(NAN_LEVEL_1_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I.. -I../SND_BlenderWaveCache -I../SND_OpenAL
+
+TESTLIB = $(OCGDIR)/gameengine/OpenALSoundSystem/$(DEBUG_DIR)libOpenALSoundSystem.a
+TESTLIB += $(OCGDIR)/gameengine/BlenderWaveCache/$(DEBUG_DIR)libBlenderWaveCache.a
+TESTLIB += $(OCGDIR)/intern/SoundSystem/$(DEBUG_DIR)libsoundsystem.a
+TESTLIB += $(NAN_OPENAL)/lib/libopenal.a
+
+$(DIR)/$(DEBUG_DIR)SoundSystem: $(OBJS) $(TESTLIB)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(TESTLIB) -lm -pthread -ldl -lstdc++
diff --git a/intern/SoundSystem/SND_test/SND_test.c b/intern/SoundSystem/SND_test/SND_test.c
new file mode 100644
index 00000000000..0d19dc2e131
--- /dev/null
+++ b/intern/SoundSystem/SND_test/SND_test.c
@@ -0,0 +1,154 @@
+/* SND_test.c nov 2000
+*
+* testfile for the SND module
+*
+* janco verduin
+*
+* $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 *****
+*/
+
+#include "SND_C-api.h"
+#include "BlenderWaveCacheCApi.h"
+#include "OpenALC-Api.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+static int buf[3];
+
+float oPos[3]={3.0, 0.0,-1.0};
+float oVel[3]={0.0, 0.0, 1.0};
+float oOri[6]={0.0, 0.0, 1.0, 0.0, 1.0, 0.0};
+
+void* ReadFile(char *filename)
+{
+ int file, filelen;
+ void *data = NULL;
+
+#if defined(WIN32)
+ file = open(filename, O_BINARY|O_RDONLY);
+#else
+ file = open(filename, 0|O_RDONLY);
+#endif
+
+ if (file == -1) {
+ printf("can't open file.\n");
+ printf("press q for quit.\n");
+
+ }
+ else {
+ filelen = lseek(file, 0, SEEK_END);
+ lseek(file, 0, SEEK_SET);
+
+ if (filelen != 0){
+ data = malloc(filelen);
+ if (read(file, data, filelen) != filelen) {
+ free(data);
+ data = NULL;
+ }
+ }
+ close(file);
+
+ }
+ return (data);
+}
+
+int main(int argc, char* argv[])
+{
+ int ch;
+ char* samplename = NULL;
+ void* sampleinmemory = NULL;
+ SND_CacheHandle wavecache = NULL;
+ SND_SceneHandle scene = NULL;
+ SND_ObjectHandle object = NULL;
+
+ wavecache = SND_GetWaveCache();
+ scene = SND_CreateOpenALScene(wavecache);
+
+ samplename = "2.wav";
+ sampleinmemory = ReadFile(samplename);
+
+ if (sampleinmemory) {
+
+ object = SND_CreateObject();
+ SND_AddMemoryLocation(samplename, sampleinmemory);
+ SND_SetSampleName(object, samplename);
+ SND_AddObject(scene, object);
+ printf("go your gang...\n");
+ printf("1: play\n");
+ printf("2: stop\n");
+ printf("q: quit\n");
+ }
+ do
+ {
+ ch = getchar();
+ ch = toupper(ch);
+ switch (ch)
+ {
+ case '1':
+ {
+ SND_SetPitch(object, 1.0);
+ SND_SetGain(object, 1.0);
+ SND_StartSound(object);
+ break;
+ }
+ case '2':
+ {
+ SND_StopSound(object);
+ break;
+ }
+ default:
+ break;
+ }
+
+ SND_Proceed(scene);
+
+ } while (ch != 'Q');
+
+ if (object) {
+
+ SND_RemoveObject(scene, object);
+ SND_DeleteObject(object);
+ }
+
+ SND_DeleteScene(scene);
+ SND_DeleteCache();
+
+ return 0;
+
+}
diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h
new file mode 100644
index 00000000000..5238507c866
--- /dev/null
+++ b/intern/SoundSystem/SoundDefines.h
@@ -0,0 +1,107 @@
+/*
+ * SoundDefines.h
+ *
+ * this is where all kinds of defines are stored
+ *
+ * $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 *****
+ */
+
+#ifndef __SOUNDDEFINES_H
+#define __SOUNDDEFINES_H
+
+/* the types of devices */
+enum
+{
+ snd_e_dummydevice = 0,
+ snd_e_openaldevice
+};
+
+/* general stuff */
+#define NUM_BUFFERS 128
+#define NUM_SOURCES 24 /* 24 is the limit for openal on windows, was 16 in 2.47 and previous */
+
+/* openal related stuff */
+#define AL_LOOPING 0x1007
+
+/* activelist defines */
+enum
+{
+ SND_REMOVE_ACTIVE_OBJECT = 0,
+ SND_ADD_ACTIVE_OBJECT,
+ SND_DO_NOTHING
+};
+
+/* playstate flags */
+enum
+{
+ SND_UNKNOWN = -1,
+ SND_INITIAL,
+ SND_MUST_PLAY,
+ SND_PLAYING,
+ SND_MUST_STOP,
+ SND_STOPPED,
+ SND_MUST_PAUSE,
+ SND_PAUSED,
+ SND_MUST_RESUME,
+ SND_MUST_STOP_WHEN_FINISHED,
+ SND_MUST_BE_DELETED
+};
+
+/* loopmodes */
+enum
+{
+ SND_LOOP_OFF = 0,
+ SND_LOOP_NORMAL,
+ SND_LOOP_BIDIRECTIONAL
+};
+
+
+/* cd playstate flags */
+enum
+{
+ SND_CD_ALL = 0,
+ SND_CD_TRACK,
+ SND_CD_TRACKLOOP
+};
+
+/* sample types */
+enum
+{
+ SND_WAVE_FORMAT_UNKNOWN = 0,
+ SND_WAVE_FORMAT_PCM,
+ SND_WAVE_FORMAT_ADPCM,
+ SND_WAVE_FORMAT_ALAW = 6,
+ SND_WAVE_FORMAT_MULAW,
+ SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 17,
+ SND_WAVE_FORMAT_CONTROL_RES_VQLPC = 34,
+ SND_WAVE_FORMAT_GSM_610 = 49,
+ SND_WAVE_FORMAT_MPEG3 = 85
+};
+
+#endif //__SOUNDDEFINES_H
+
diff --git a/intern/SoundSystem/dummy/Makefile b/intern/SoundSystem/dummy/Makefile
new file mode 100644
index 00000000000..829135dde98
--- /dev/null
+++ b/intern/SoundSystem/dummy/Makefile
@@ -0,0 +1,42 @@
+#
+# $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 = DummySoundSystem
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/source/blender/render/intern/include/raycounter.h b/intern/SoundSystem/dummy/SND_DummyDevice.cpp
index dea6d63d001..672c73e9c52 100644
--- a/source/blender/render/intern/include/raycounter.h
+++ b/intern/SoundSystem/dummy/SND_DummyDevice.cpp
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -6,7 +6,7 @@
* 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.
+ * 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
@@ -17,39 +17,36 @@
* 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.
+ * 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): André Pinto.
+ * Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
+ * SND_DummyDevice derived from SND_IAudioDevice
*/
-#ifndef RE_RAYCOUNTER_H
-#define RE_RAYCOUNTER_H
-#include "RE_raytrace.h"
-
-
-#ifdef RE_RAYCOUNTER
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
-/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */
-#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter)
-void RE_RC_INFO (RayCounter *rc);
-void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp);
-#define RE_RC_COUNT(var) (var)++
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
-extern RayCounter re_rc_counter[];
+#include "SND_DummyDevice.h"
-#else
+SND_DummyDevice::SND_DummyDevice()
+{
+}
-# define RE_RC_INIT(isec,shi)
-# define RE_RC_INFO(rc)
-# define RE_RC_MERGE(dest,src)
-# define RE_RC_COUNT(var)
-
+SND_DummyDevice::~SND_DummyDevice()
+{
+#ifdef ONTKEVER
+ printf("SND_DummyDevice destructor");
#endif
+}
-#endif
diff --git a/intern/SoundSystem/dummy/SND_DummyDevice.h b/intern/SoundSystem/dummy/SND_DummyDevice.h
new file mode 100644
index 00000000000..988f731d1bf
--- /dev/null
+++ b/intern/SoundSystem/dummy/SND_DummyDevice.h
@@ -0,0 +1,93 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_DUMMYDEVICE
+#define SND_DUMMYDEVICE
+
+#include "SND_AudioDevice.h"
+
+class SND_DummyDevice : public SND_AudioDevice
+{
+public:
+ SND_DummyDevice();
+ ~SND_DummyDevice();
+
+ bool Init() { return false; }
+
+ SND_WaveSlot* LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size) { return NULL; }
+
+ void InitListener() {};
+ void SetListenerGain(float gain) const {};
+ void SetDopplerVelocity(MT_Scalar dopplervelocity) const {};
+ void SetDopplerFactor(MT_Scalar dopplerfactor) const {};
+ void SetListenerRollOffFactor(MT_Scalar rollofffactor) const {};
+
+ void MakeCurrent() const {};
+
+ void NextFrame() const {};
+
+ void SetObjectBuffer(int id, unsigned int buffer) {};
+
+ int GetPlayState(int id) { return SND_UNKNOWN; }
+ void PlayObject(int id) {};
+ void StopObject(int id) const {};
+ void StopAllObjects() {};
+ void PauseObject(int id) const {};
+
+ void SetObjectLoop(int id, unsigned int loopmode) const {};
+ void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const {};
+ void SetObjectPitch(int id, MT_Scalar pitch) const {};
+ void SetObjectGain(int id, MT_Scalar gain) const {};
+ void SetObjectMinGain(int id, MT_Scalar mingain) const {};
+ void SetObjectMaxGain(int id, MT_Scalar maxgain) const {};
+ void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const {};
+ void SetObjectReferenceDistance(int id, MT_Scalar distance) const {};
+
+ void SetObjectTransform(int id,
+ const MT_Vector3& position,
+ const MT_Vector3& velocity,
+ const MT_Matrix3x3& orientation,
+ const MT_Vector3& lisposition,
+ const MT_Scalar& rollofffactor) const {};
+ void ObjectIs2D(int id) const {};
+
+ void PlayCD(int track) const {};
+ void PauseCD(bool pause) const {};
+ void StopCD() const {};
+ void SetCDPlaymode(int playmode) const {};
+ void SetCDGain(MT_Scalar gain) const {};
+
+ void StartUsingDSP() {};
+ float* GetSpectrum() { return NULL; }
+ void StopUsingDSP() {};
+};
+
+#endif //SND_DUMMYDEVICE
+
diff --git a/intern/SoundSystem/intern/Makefile b/intern/SoundSystem/intern/Makefile
new file mode 100644
index 00000000000..7684b6b0bca
--- /dev/null
+++ b/intern/SoundSystem/intern/Makefile
@@ -0,0 +1,44 @@
+#
+# $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 = SoundSystem
+DIR = $(OCGDIR)/intern/SoundSystem
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../source/blender/include
+CPPFLAGS += -I../dummy
+CPPFLAGS += -I../openal
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/intern/SoundSystem/intern/SND_AudioDevice.cpp b/intern/SoundSystem/intern/SND_AudioDevice.cpp
new file mode 100644
index 00000000000..4a5c0e2c498
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_AudioDevice.cpp
@@ -0,0 +1,242 @@
+/**
+ * $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 *****
+ */
+
+#include "SND_AudioDevice.h"
+#include "SND_SoundObject.h"
+
+#ifdef WIN32
+// This warning tells us about truncation of __long__ stl-generated names.
+// It can occasionally cause DevStudio to have internal compiler warnings.
+#pragma warning( disable : 4786 )
+#endif
+
+
+SND_AudioDevice::SND_AudioDevice()
+{
+ m_wavecache = NULL;
+ m_audio = false;
+
+ for (int i = 0; i < NUM_SOURCES; i++)
+ {
+ m_idObjectArray[i] = new SND_IdObject();
+ m_idObjectArray[i]->SetId(i);
+ m_idObjectArray[i]->SetSoundObject(NULL);
+ m_idObjectList.addTail(m_idObjectArray[i]);
+ }
+}
+
+
+
+SND_AudioDevice::~SND_AudioDevice()
+{
+ for (int i = 0; i < NUM_SOURCES; i++)
+ {
+ delete m_idObjectArray[i];
+ m_idObjectArray[i] = NULL;
+ }
+
+ if (m_wavecache)
+ {
+ delete m_wavecache;
+ m_wavecache = NULL;
+ }
+}
+
+
+
+bool SND_AudioDevice::IsInitialized()
+{
+ return m_audio;
+}
+
+
+
+SND_WaveCache* SND_AudioDevice::GetWaveCache() const
+{
+ return m_wavecache;
+}
+
+
+
+/* seeks an unused id and returns it */
+bool SND_AudioDevice::GetNewId(SND_SoundObject* pObject)
+{
+#ifdef ONTKEVER
+ printf("SND_AudioDevice::GetNewId\n");
+#endif
+
+ bool result = false;
+
+ // first, get the oldest (the first) idobject
+ SND_IdObject* pIdObject = (SND_IdObject*)m_idObjectList.getHead();
+
+ if (pIdObject->isTail())
+ {
+ }
+ else
+ {
+ // find the first id object which doesn't have a high priority soundobject
+ bool ThisSoundMustStay = false;
+ bool OutOfIds = false;
+
+ do
+ {
+ // if no soundobject present, it's seat may be taken
+ if (pIdObject->GetSoundObject())
+ {
+ // and also if it ain't highprio
+ if (pIdObject->GetSoundObject()->IsHighPriority())
+ {
+ ThisSoundMustStay = true;
+ pIdObject = (SND_IdObject*)pIdObject->getNext();
+
+ // if the last one is a priority sound too, then there are no id's left
+ // and we won't add any new sounds
+ if (pIdObject->isTail())
+ OutOfIds = true;
+ }
+ else
+ {
+ ThisSoundMustStay = false;
+ }
+ }
+ else
+ {
+ ThisSoundMustStay = false;
+ }
+
+ } while (ThisSoundMustStay && !OutOfIds);
+
+ if (!OutOfIds)
+ {
+ SND_SoundObject* oldobject = pIdObject->GetSoundObject();
+
+ // revoke the old object if present
+ if (oldobject)
+ {
+#ifdef ONTKEVER
+ printf("oldobject: %x\n", oldobject);
+#endif
+ RevokeSoundObject(oldobject);
+ }
+
+ // set the new soundobject into the idobject
+ pIdObject->SetSoundObject(pObject);
+
+ // set the id into the soundobject
+ int id = pIdObject->GetId();
+ pObject->SetId(id);
+
+ // connect the new id to the buffer the sample is stored in
+ SetObjectBuffer(id, pObject->GetBuffer());
+
+ // remove the idobject from the list and add it in the back again
+ pIdObject->remove();
+ m_idObjectList.addTail(pIdObject);
+
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+
+
+void SND_AudioDevice::ClearId(SND_SoundObject* pObject)
+{
+#ifdef ONTKEVER
+ printf("SND_AudioDevice::ClearId\n");
+#endif
+
+ if (pObject)
+ {
+ int id = pObject->GetId();
+
+ if (id != -1)
+ {
+ // lets get the idobject belonging to the soundobject
+ SND_IdObject* pIdObject = m_idObjectArray[id];
+ SND_SoundObject* oldobject = pIdObject->GetSoundObject();
+
+ if (oldobject)
+ {
+ RevokeSoundObject(oldobject);
+
+ // clear the idobject from the soundobject
+ pIdObject->SetSoundObject(NULL);
+ }
+
+ // remove the idobject and place it in front
+ pIdObject->remove();
+ m_idObjectList.addHead(pIdObject);
+ }
+ }
+}
+
+
+
+void SND_AudioDevice::RevokeSoundObject(SND_SoundObject* pObject)
+{
+#ifdef ONTKEVER
+ printf("SND_AudioDevice::RevokeSoundObject\n");
+#endif
+
+ // stop the soundobject
+ int id = pObject->GetId();
+
+ if (id >= 0 && id < NUM_SOURCES)
+ {
+ StopObject(id);
+
+ // remove the object from the 'activelist'
+ pObject->SetActive(false);
+
+#ifdef ONTKEVER
+ printf("pObject->remove();\n");
+#endif
+ }
+
+ // make sure its id is invalid
+ pObject->SetId(-1);
+}
+
+/*
+void SND_AudioDevice::RemoveSample(const char* filename)
+{
+ if (m_wavecache)
+ m_wavecache->RemoveSample(filename);
+}
+*/
+
+void SND_AudioDevice::RemoveAllSamples()
+{
+ if (m_wavecache)
+ m_wavecache->RemoveAllSamples();
+}
+
diff --git a/intern/SoundSystem/intern/SND_AudioDevice.h b/intern/SoundSystem/intern/SND_AudioDevice.h
new file mode 100644
index 00000000000..54e8feea90e
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_AudioDevice.h
@@ -0,0 +1,115 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_AUDIODEVICE
+#define SND_AUDIODEVICE
+
+#include "SND_IAudioDevice.h"
+#include "SoundDefines.h"
+#include "SND_IdObject.h"
+
+class SND_AudioDevice : public SND_IAudioDevice
+{
+public:
+ SND_AudioDevice();
+ virtual ~SND_AudioDevice();
+
+ virtual bool IsInitialized();
+
+ SND_WaveCache* GetWaveCache() const;
+
+ bool GetNewId(SND_SoundObject* pObject);
+ void ClearId(SND_SoundObject* pObject);
+
+ void UseCD() const {};
+
+ /* to be implemented in derived class
+
+ virtual SND_WaveSlot* LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size) =0;
+ */
+// void RemoveSample(const char* filename);
+ void RemoveAllSamples();
+
+ /* to be implemented in derived class
+
+ virtual void InitListener()=0;
+ virtual void SetListenerGain(float gain) const =0;
+ virtual void SetDopplerVelocity(MT_Scalar dopplervelocity) const =0;
+ virtual void SetDopplerFactor(MT_Scalar dopplerfactor) const =0;
+ virtual void SetListenerRollOffFactor(MT_Scalar rollofffactor) const =0;
+
+ virtual void MakeCurrent() const =0;
+
+ virtual void UpdateDevice() const =0;
+
+ virtual void SetObjectBuffer(int id, unsigned int buffer)=0;
+ virtual int GetPlayState(int id)=0;
+ virtual void PlayObject(int id)=0;
+ virtual void StopObject(int id) const =0;
+ virtual void StopAllObjects()=0;
+ virtual void PauseObject(int id) const =0;
+
+ virtual void SetObjectLoop(int id, bool loop) const =0;
+ virtual void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const =0;
+ virtual void SetObjectPitch(int id, MT_Scalar pitch) const =0;
+ virtual void SetObjectGain(int id, MT_Scalar gain) const =0;
+ virtual void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const =0;
+ virtual void SetObjectMinGain(int id, MT_Scalar mingain) const =0;
+ virtual void SetObjectMaxGain(int id, MT_Scalar maxgain) const =0;
+ virtual void SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const =0;
+
+ virtual void SetObjectTransform(int id,
+ const MT_Vector3& position,
+ const MT_Vector3& velocity,
+ const MT_Matrix3x3& orientation,
+ const MT_Vector3& lisposition,
+ const MT_Scalar& rollofffactor) const =0;
+ virtual void ObjectIs2D(int id) const =0;
+
+ virtual void PlayCD(int track) const =0;
+ virtual void PauseCD(bool pause) const =0;
+ virtual void StopCD() const =0;
+ virtual void SetCDPlaymode(int playmode) const =0;
+ virtual void SetCDGain(MT_Scalar gain) const =0;
+ virtual float* GetSpectrum() =0;
+ */
+
+protected:
+ bool m_audio;
+ GEN_List m_idObjectList;
+ SND_IdObject* m_idObjectArray[NUM_SOURCES];
+ SND_WaveCache* m_wavecache;
+
+private:
+ void RevokeSoundObject(SND_SoundObject* pObject);
+};
+
+#endif //SND_AUDIODEVICE
+
diff --git a/intern/SoundSystem/intern/SND_C-api.cpp b/intern/SoundSystem/intern/SND_C-api.cpp
new file mode 100644
index 00000000000..09846269dcc
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_C-api.cpp
@@ -0,0 +1,392 @@
+/*
+ * SND_C-Api.cpp
+ *
+ * C Api for soundmodule
+ *
+ * $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 *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SND_C-api.h"
+#include "SND_DeviceManager.h"
+#include "SND_Scene.h"
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+
+
+void SND_SetDeviceType(int device_type)
+{
+ SND_DeviceManager::SetDeviceType(device_type);
+}
+
+
+
+SND_AudioDeviceInterfaceHandle SND_GetAudioDevice()
+{
+ SND_IAudioDevice* audiodevice = NULL;
+
+ SND_DeviceManager::Subscribe();
+ audiodevice = SND_DeviceManager::Instance();
+
+ if (!audiodevice->IsInitialized())
+ {
+ SND_DeviceManager::SetDeviceType(snd_e_dummydevice);
+ audiodevice = SND_DeviceManager::Instance();
+ }
+
+ return (SND_AudioDeviceInterfaceHandle)audiodevice;
+}
+
+
+
+void SND_ReleaseDevice()
+{
+ SND_DeviceManager::Unsubscribe();
+}
+
+
+
+int SND_IsPlaybackWanted(SND_SceneHandle scene)
+{
+ assert(scene);
+ bool result = ((SND_Scene*)scene)->IsPlaybackWanted();
+
+ return (int)result;
+}
+
+
+
+// create a scene
+SND_SceneHandle SND_CreateScene(SND_AudioDeviceInterfaceHandle audiodevice)
+{
+ // initialize sound scene and object
+ SND_Scene* scene = new SND_Scene((SND_IAudioDevice*)audiodevice);
+
+ return (SND_SceneHandle)scene;
+}
+
+
+
+void SND_DeleteScene(SND_SceneHandle scene)
+{
+ assert(scene);
+ delete (SND_Scene*)scene;
+}
+
+
+
+int SND_AddSample(SND_SceneHandle scene,
+ const char* filename,
+ void* memlocation,
+ int size)
+{
+ assert(scene);
+ assert(memlocation);
+ int buffer = ((SND_Scene*)scene)->LoadSample(filename, memlocation, size);
+
+ return buffer;
+}
+
+
+
+void SND_RemoveAllSamples(SND_SceneHandle scene)
+{
+ assert(scene);
+ ((SND_Scene*)scene)->RemoveAllSamples();
+}
+
+
+
+int SND_CheckBuffer(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ int result = (int)((SND_Scene*)scene)->CheckBuffer((SND_SoundObject*)object);
+
+ return result;
+}
+
+
+
+void SND_AddSound(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((SND_Scene*)scene)->AddObject((SND_SoundObject *)object);
+}
+
+
+
+void SND_RemoveSound(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((SND_Scene*)scene)->DeleteObject((SND_SoundObject *)object);
+}
+
+
+
+void SND_RemoveAllSounds(SND_SceneHandle scene)
+{
+ assert(scene);
+ ((SND_Scene*)scene)->RemoveAllObjects();
+}
+
+
+
+void SND_StopAllSounds(SND_SceneHandle scene)
+{
+ assert(scene);
+ ((SND_Scene*)scene)->StopAllObjects();
+}
+
+
+
+void SND_Proceed(SND_AudioDeviceInterfaceHandle audiodevice, SND_SceneHandle scene)
+{
+ assert(scene);
+ ((SND_Scene*)scene)->Proceed();
+ ((SND_IAudioDevice*)audiodevice)->NextFrame();
+}
+
+
+
+SND_ListenerHandle SND_GetListener(SND_SceneHandle scene)
+{
+ assert(scene);
+ return (SND_ListenerHandle)((SND_Scene*)scene)->GetListener();
+}
+
+
+
+void SND_SetListenerGain(SND_SceneHandle scene, double gain)
+{
+ assert(scene);
+ SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener();
+ listener->SetGain((MT_Scalar)gain);
+}
+
+
+
+void SND_SetDopplerFactor(SND_SceneHandle scene, double dopplerfactor)
+{
+ assert(scene);
+ SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener();
+ listener->SetDopplerFactor(dopplerfactor);
+}
+
+
+
+void SND_SetDopplerVelocity(SND_SceneHandle scene, double dopplervelocity)
+{
+ assert(scene);
+ SND_SoundListener* listener = ((SND_Scene*)scene)->GetListener();
+ listener->SetDopplerVelocity(dopplervelocity);
+}
+
+
+
+// Object instantiation
+SND_ObjectHandle SND_CreateSound()
+{
+ return (SND_ObjectHandle)new SND_SoundObject();
+}
+
+
+
+void SND_DeleteSound(SND_ObjectHandle object)
+{
+ assert(object);
+ delete (SND_SoundObject*)object;
+}
+
+
+
+// Object control
+void SND_StartSound(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((SND_Scene*)scene)->AddActiveObject((SND_SoundObject*)object, 0);
+}
+
+
+
+void SND_StopSound(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((SND_Scene*)scene)->RemoveActiveObject((SND_SoundObject*)object);
+}
+
+
+
+void SND_PauseSound(SND_SceneHandle scene, SND_ObjectHandle object)
+{
+ assert(scene);
+ assert(object);
+ ((SND_Scene*)scene)->RemoveActiveObject((SND_SoundObject*)object);
+}
+
+
+
+void SND_SetSampleName(SND_ObjectHandle object, char* samplename)
+{
+ assert(object);
+ STR_String name = samplename;
+ ((SND_SoundObject*)object)->SetSampleName(name);
+}
+
+
+
+void SND_SetGain(SND_ObjectHandle object, double gain)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetGain(gain);
+}
+
+
+
+void SND_SetMinimumGain(SND_ObjectHandle object, double minimumgain)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetMinGain(minimumgain);
+}
+
+
+
+void SND_SetMaximumGain(SND_ObjectHandle object, double maximumgain)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetMaxGain(maximumgain);
+}
+
+
+
+void SND_SetRollOffFactor(SND_ObjectHandle object, double rollofffactor)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetRollOffFactor(rollofffactor);
+}
+
+
+
+void SND_SetReferenceDistance(SND_ObjectHandle object, double referencedistance)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetReferenceDistance(referencedistance);
+}
+
+
+
+void SND_SetPitch(SND_ObjectHandle object, double pitch)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetPitch(pitch);
+}
+
+
+
+void SND_SetPosition(SND_ObjectHandle object, double* position)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetPosition(position);
+}
+
+
+
+void SND_SetVelocity(SND_ObjectHandle object, double* velocity)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetVelocity(velocity);
+}
+
+
+
+void SND_SetOrientation(SND_ObjectHandle object, double* orientation)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetOrientation(orientation);
+}
+
+
+
+void SND_SetLoopMode(SND_ObjectHandle object, int loopmode)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetLoopMode(loopmode);
+}
+
+
+
+void SND_SetLoopPoints(SND_ObjectHandle object, unsigned int loopstart, unsigned int loopend)
+{
+ assert(object);
+ ((SND_SoundObject*)object)->SetLoopStart(loopstart);
+ ((SND_SoundObject*)object)->SetLoopEnd(loopend);
+}
+
+
+
+float SND_GetGain(SND_ObjectHandle object)
+{
+ assert(object);
+ MT_Scalar gain = ((SND_SoundObject*)object)->GetGain();
+ return (float) gain;
+}
+
+
+
+float SND_GetPitch(SND_ObjectHandle object)
+{
+ assert(object);
+ MT_Scalar pitch = ((SND_SoundObject*)object)->GetPitch();
+ return (float) pitch;
+}
+
+
+
+int SND_GetLoopMode(SND_ObjectHandle object)
+{
+ assert(object);
+ return ((SND_SoundObject*)object)->GetLoopMode();
+}
+
+
+
+int SND_GetPlaystate(SND_ObjectHandle object)
+{
+ assert(object);
+ return ((SND_SoundObject*)object)->GetPlaystate();
+}
diff --git a/intern/SoundSystem/intern/SND_CDObject.cpp b/intern/SoundSystem/intern/SND_CDObject.cpp
new file mode 100644
index 00000000000..089e0d554e4
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_CDObject.cpp
@@ -0,0 +1,182 @@
+/*
+ * SND_CDObject.cpp
+ *
+ * Implementation for CD playback
+ *
+ * $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 *****
+ */
+
+#include "SND_CDObject.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SND_CDObject* SND_CDObject::m_instance = NULL;
+
+bool SND_CDObject::CreateSystem()
+{
+ bool result = false;
+
+ if (!m_instance)
+ {
+ m_instance = new SND_CDObject();
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+bool SND_CDObject::DisposeSystem()
+{
+ bool result = false;
+
+ if (m_instance)
+ {
+ delete m_instance;
+ m_instance = NULL;
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+SND_CDObject* SND_CDObject::Instance()
+{
+ return m_instance;
+}
+
+
+
+SND_CDObject::SND_CDObject()
+{
+ m_gain = 1;
+ m_playmode = SND_CD_ALL;
+ m_track = 1;
+ m_playstate = SND_STOPPED;
+ m_used = false;
+
+ // don't set the cd standard on modified:
+ // if not used, we don't wanna touch it (performance)
+ m_modified = false;
+}
+
+
+
+SND_CDObject::~SND_CDObject()
+{
+}
+
+
+
+void SND_CDObject::SetGain(MT_Scalar gain)
+{
+ m_gain = gain;
+ m_modified = true;
+}
+
+
+
+void SND_CDObject::SetPlaymode(int playmode)
+{
+ m_playmode = playmode;
+}
+
+
+
+void SND_CDObject::SetPlaystate(int playstate)
+{
+ m_playstate = playstate;
+}
+
+
+
+void SND_CDObject::SetTrack(int track)
+{
+ m_track = track;
+}
+
+
+
+int SND_CDObject::GetTrack() const
+{
+ return m_track;
+}
+
+
+
+MT_Scalar SND_CDObject::GetGain() const
+{
+ return m_gain;
+}
+
+
+int SND_CDObject::GetPlaystate() const
+{
+ return m_playstate;
+}
+
+
+
+bool SND_CDObject::IsModified() const
+{
+ return m_modified;
+}
+
+
+
+void SND_CDObject::SetModified(bool modified)
+{
+ m_modified = modified;
+}
+
+
+
+int SND_CDObject::GetPlaymode() const
+{
+ return m_playmode;
+}
+
+
+
+void SND_CDObject::SetUsed()
+{
+ m_used = true;
+}
+
+
+
+bool SND_CDObject::GetUsed()
+{
+ return m_used;
+}
+
diff --git a/intern/SoundSystem/intern/SND_DeviceManager.cpp b/intern/SoundSystem/intern/SND_DeviceManager.cpp
new file mode 100644
index 00000000000..c4bc887dffe
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_DeviceManager.cpp
@@ -0,0 +1,126 @@
+/*
+ * SND_DeviceManager.h
+ *
+ * singleton for creating, switching and deleting audiodevices
+ *
+ * $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 *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SND_DeviceManager.h"
+#include "SND_DependKludge.h"
+#include "SND_DummyDevice.h"
+#ifdef USE_OPENAL
+#include "SND_OpenALDevice.h"
+#endif
+
+SND_IAudioDevice* SND_DeviceManager::m_instance = NULL;
+int SND_DeviceManager::m_subscriptions = 0;
+
+#ifdef USE_OPENAL
+int SND_DeviceManager::m_device_type = snd_e_openaldevice;
+#else
+int SND_DeviceManager::m_device_type = snd_e_dummydevice;
+#endif
+
+void SND_DeviceManager::Subscribe()
+{
+ ++m_subscriptions;
+}
+
+
+
+void SND_DeviceManager::Unsubscribe()
+{
+ --m_subscriptions;
+
+ // only release memory if there is a m_instance but no subscriptions left
+ if (m_subscriptions == 0 && m_instance)
+ {
+ delete m_instance;
+ m_instance = NULL;
+ }
+
+ if (m_subscriptions < 0)
+ m_subscriptions = 0;
+}
+
+
+
+SND_IAudioDevice* SND_DeviceManager::Instance()
+{
+ // only give away an instance if there are subscriptions
+ if (m_subscriptions)
+ {
+ // if there's no instance yet, set and create a new one
+ if (m_instance == NULL)
+ {
+ SetDeviceType(m_device_type);
+ }
+
+ return m_instance;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+
+void SND_DeviceManager::SetDeviceType(int device_type)
+{
+ // if we want to change devicetype, first delete the old one
+ if (m_instance)
+ {
+ delete m_instance;
+ m_instance = NULL;
+ }
+
+ // let's create the chosen device
+ switch (device_type)
+ {
+#ifdef USE_OPENAL
+ case snd_e_openaldevice:
+ {
+ m_instance = new SND_OpenALDevice();
+ m_device_type = device_type;
+ break;
+ }
+#endif
+ default:
+ {
+ m_instance = new SND_DummyDevice();
+ m_device_type = device_type;
+ break;
+ }
+ }
+}
diff --git a/intern/SoundSystem/intern/SND_IdObject.cpp b/intern/SoundSystem/intern/SND_IdObject.cpp
new file mode 100644
index 00000000000..b261442db0a
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_IdObject.cpp
@@ -0,0 +1,76 @@
+/*
+ * SND_IdObject.cpp
+ *
+ * Object for storing runtime data, like id's, soundobjects etc
+ *
+ * $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 *****
+ */
+
+#include "SND_IdObject.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SND_IdObject::SND_IdObject()
+{
+}
+
+
+
+SND_IdObject::~SND_IdObject()
+{
+}
+
+
+
+SND_SoundObject* SND_IdObject::GetSoundObject()
+{
+ return m_soundObject;
+}
+
+
+
+void SND_IdObject::SetSoundObject(SND_SoundObject* pObject)
+{
+ m_soundObject = pObject;
+}
+
+
+
+int SND_IdObject::GetId()
+{
+ return m_id;
+}
+
+
+
+void SND_IdObject::SetId(int id)
+{
+ m_id = id;
+}
diff --git a/intern/SoundSystem/intern/SND_IdObject.h b/intern/SoundSystem/intern/SND_IdObject.h
new file mode 100644
index 00000000000..86611b026f0
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_IdObject.h
@@ -0,0 +1,58 @@
+/*
+ * SND_IdObject.h
+ *
+ * Object for storing runtime data, like id's, soundobjects etc
+ *
+ * $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 *****
+ */
+
+#ifndef __SND_IDOBJECT_H
+#define __SND_IDOBJECT_H
+
+#include "SND_SoundObject.h"
+#include "GEN_List.h"
+#include "SoundDefines.h"
+
+class SND_IdObject : public GEN_Link
+{
+ SND_SoundObject* m_soundObject;
+ int m_id;
+
+public:
+ SND_IdObject();
+ virtual ~SND_IdObject();
+
+ SND_SoundObject* GetSoundObject();
+ void SetSoundObject(SND_SoundObject* pObject);
+
+ int GetId();
+ void SetId(int id);
+};
+
+#endif //__SND_OBJECT_H
+
diff --git a/intern/SoundSystem/intern/SND_Scene.cpp b/intern/SoundSystem/intern/SND_Scene.cpp
new file mode 100644
index 00000000000..af1b43a08aa
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_Scene.cpp
@@ -0,0 +1,544 @@
+/*
+* SND_Scene.cpp
+*
+* The scene for sounds.
+*
+* $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 *****
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#pragma warning (disable:4786) // Get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_Scene.h"
+#include "SND_DependKludge.h"
+#include "SND_IAudioDevice.h"
+
+#include <stdlib.h>
+#include <iostream>
+
+//static unsigned int tijd = 0;
+
+SND_Scene::SND_Scene(SND_IAudioDevice* audiodevice)
+ : m_audiodevice(audiodevice)
+{
+ if (m_audiodevice)
+ m_wavecache = m_audiodevice->GetWaveCache();
+
+ if (!m_wavecache || !audiodevice)
+ {
+ m_audio = false;
+ }
+ else
+ {
+ //if so, go ahead!
+ m_audio = true;
+#ifdef ONTKEVER
+ printf("SND_Scene::SND_Scene() m_audio == true\n");
+#endif
+ m_audiodevice->InitListener();
+ }
+
+ IsPlaybackWanted();
+}
+
+
+
+SND_Scene::~SND_Scene()
+{
+ StopAllObjects();
+}
+
+
+
+// check if audioplayback is wanted
+bool SND_Scene::IsPlaybackWanted()
+{
+ /* Removed the functionality for checking if noaudio was provided on */
+ /* the commandline. */
+ if (m_audiodevice && m_wavecache)
+ {
+ m_audioplayback = true;
+ }
+ else
+ {
+ StopAllObjects();
+ m_audioplayback = false;
+ }
+
+ return m_audioplayback;
+}
+
+
+
+int SND_Scene::LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size)
+{
+ int result = -1;
+
+ if (m_audiodevice)
+ {
+ SND_WaveSlot* waveslot = m_audiodevice->LoadSample(samplename, memlocation, size);
+
+ if (waveslot)
+ result = waveslot->GetBuffer();
+ }
+
+ return result;
+}
+
+
+
+void SND_Scene::RemoveAllSamples()
+{
+ if (m_audio && m_audiodevice)
+ m_audiodevice->RemoveAllSamples();
+}
+
+
+
+bool SND_Scene::CheckBuffer(SND_SoundObject* pObject)
+{
+ bool result = false;
+
+ if (pObject && m_wavecache)
+ {
+ SND_WaveSlot* waveslot = m_wavecache->GetWaveSlot(pObject->GetSampleName());
+
+ if (waveslot)
+ {
+ pObject->SetBuffer(waveslot->GetBuffer());
+
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+
+
+bool SND_Scene::IsSampleLoaded(STR_String& samplename)
+{
+ bool result = false;
+
+ if (samplename && m_wavecache)
+ {
+ SND_WaveSlot* waveslot = m_wavecache->GetWaveSlot(samplename);
+
+ if (waveslot && waveslot->IsLoaded())
+ result = true;
+ }
+
+ return result;
+}
+
+
+
+void SND_Scene::AddObject(SND_SoundObject* pObject)
+{
+ if (m_audio)
+ {
+ STR_String samplename = pObject->GetSampleName();
+ SND_WaveSlot* slot = NULL;
+
+ // don't add the object if no valid sample is referenced
+ if (samplename != "")
+ {
+ // check if the sample is already loaded
+ slot = m_wavecache->GetWaveSlot(samplename);
+ }
+
+ if (slot)
+ {
+ pObject->SetBuffer(slot->GetBuffer());
+
+ // needed for expected lifespan of the sample, but ain't necesary anymore i think
+ MT_Scalar samplelength = slot->GetNumberOfSamples();
+ MT_Scalar samplerate = slot->GetSampleRate();
+ MT_Scalar soundlength = samplelength/samplerate;
+ pObject->SetLength(soundlength);
+
+ // add the object to the list
+ m_soundobjects.insert((SND_SoundObject*)pObject);
+ }
+ }
+}
+
+
+
+void SND_Scene::SetListenerTransform(const MT_Vector3& pos,
+ const MT_Vector3& vel,
+ const MT_Matrix3x3& ori)
+{
+ if (m_audio)
+ {
+ GetListener()->SetPosition(pos);
+ GetListener()->SetVelocity(vel);
+ GetListener()->SetOrientation(ori);
+ }
+}
+
+
+
+void SND_Scene::UpdateListener()
+{
+ // process the listener if modified
+ if (m_listener.IsModified())
+ {
+ m_audiodevice->SetListenerGain(m_listener.GetGain());
+ m_audiodevice->SetDopplerVelocity(m_listener.GetDopplerVelocity());
+ m_audiodevice->SetDopplerFactor(m_listener.GetDopplerFactor());
+ m_listener.SetModified(false);
+ }
+}
+
+
+
+void SND_Scene::AddActiveObject(SND_SoundObject* pObject, MT_Scalar curtime)
+{
+ if (m_audio)
+ {
+ if (pObject)
+ {
+#ifdef ONTKEVER
+ printf("SND_Scene::AddActiveObject\n");
+#endif
+
+ // first check if the object is already on the list
+ if (pObject->IsActive())
+ {
+ pObject->SetTimeStamp(curtime);
+ pObject->StartSound();
+ }
+ else
+ {
+ pObject->SetTimeStamp(curtime);
+
+ // compute the expected lifespan
+ pObject->SetLifeSpan();
+
+ // lets give the new active-to-be object an id
+ if (m_audiodevice->GetNewId(pObject))
+ {
+ // and add the object
+ m_activeobjects.addTail(pObject);
+ pObject->StartSound();
+ pObject->SetActive(true);
+ }
+ }
+ }
+ }
+}
+
+
+
+void SND_Scene::RemoveActiveObject(SND_SoundObject* pObject)
+{
+ if (m_audio)
+ {
+ if (pObject)
+ {
+#ifdef ONTKEVER
+ printf("SND_Scene::RemoveActiveObject\n");
+#endif
+ // if inactive, remove it from the list
+ if (pObject->IsActive())
+ {
+ // first make sure it is stopped
+ m_audiodevice->ClearId(pObject);
+ }
+ }
+ }
+}
+
+
+
+void SND_Scene::UpdateActiveObects()
+{
+// ++tijd;
+
+ SND_SoundObject* pObject;
+ // update only the objects that need to be updated
+ for (pObject = (SND_SoundObject*)m_activeobjects.getHead();
+ !pObject->isTail();
+ pObject = (SND_SoundObject*)pObject->getNext())
+ {
+ int id = pObject->GetId();
+
+ if (id >= 0)
+ {
+ if (pObject->Is3D())
+ {
+ // Get the global positions and velocity vectors
+ // of the listener and soundobject
+ MT_Vector3 op = pObject->GetPosition();
+ MT_Vector3 lp = m_listener.GetPosition();
+ MT_Vector3 position = op - lp;
+
+ // Calculate relative velocity in global coordinates
+ // of the sound with respect to the listener.
+ MT_Vector3 ov = pObject->GetVelocity();
+ MT_Vector3 lv = m_listener.GetVelocity();
+ MT_Vector3 velocity = ov - lv;
+
+ // Now map the object position and velocity into
+ // the local coordinates of the listener.
+ MT_Matrix3x3 lo = m_listener.GetOrientation();
+
+ MT_Vector3 local_sound_pos = position * lo;
+ MT_Vector3 local_sound_vel = velocity * lo;
+
+ m_audiodevice->SetObjectTransform(
+ id,
+ local_sound_pos,
+ local_sound_vel,
+ pObject->GetOrientation(), // make relative to listener!
+ lp,
+ pObject->GetRollOffFactor());
+ }
+ else
+ {
+ m_audiodevice->ObjectIs2D(id);
+ }
+
+ // update the situation
+ if (pObject->IsModified())
+ {
+ m_audiodevice->SetObjectPitch(id, pObject->GetPitch());
+ m_audiodevice->SetObjectGain(id, pObject->GetGain());
+ m_audiodevice->SetObjectMinGain(id, pObject->GetMinGain());
+ m_audiodevice->SetObjectMaxGain(id, pObject->GetMaxGain());
+ m_audiodevice->SetObjectReferenceDistance(id, pObject->GetReferenceDistance());
+ m_audiodevice->SetObjectRollOffFactor(id, pObject->GetRollOffFactor());
+ m_audiodevice->SetObjectLoop(id, pObject->GetLoopMode());
+ m_audiodevice->SetObjectLoopPoints(id, pObject->GetLoopStart(), pObject->GetLoopEnd());
+ pObject->SetModified(false);
+ }
+
+ pObject->AddRunning();
+
+#ifdef ONTKEVER
+ STR_String naam = pObject->GetObjectName();
+ STR_String sample = pObject->GetSampleName();
+
+ int id = pObject->GetId();
+ int buffer = pObject->GetBuffer();
+
+ float gain = pObject->GetGain();
+ float pitch = pObject->GetPitch();
+ float timestamp = pObject->GetTimestamp();
+
+ printf("naam: %s, sample: %s \n", naam.Ptr(), sample.Ptr());
+ printf("id: %d, buffer: %d \n", id, buffer);
+ printf("gain: %f, pitch: %f, ts: %f \n\n", gain, pitch, timestamp);
+#endif
+#ifdef USE_OPENAL
+ // ok, properties Set. now see if it must play
+ switch (pObject->GetPlaystate()){
+ case SND_MUST_PLAY:
+ m_audiodevice->PlayObject(id);
+ pObject->SetPlaystate(SND_PLAYING);
+ break;
+ case SND_MUST_STOP:
+ RemoveActiveObject(pObject);
+ break;
+ case SND_MUST_PAUSE:
+ m_audiodevice->PauseObject(id);
+ pObject->SetPlaystate(SND_PAUSED);
+ break;
+ }
+#endif
+
+ // check to see if the sound is still playing
+ // if not: release its id
+ int playstate = m_audiodevice->GetPlayState(id);
+#ifdef ONTKEVER
+ if (playstate != 2)
+ printf("%d - ",playstate);
+#endif
+
+ if ((playstate == SND_STOPPED) && !pObject->GetLoopMode())
+ {
+ RemoveActiveObject(pObject);
+ }
+ }
+ }
+}
+
+
+
+void SND_Scene::UpdateCD()
+{
+ if (m_audiodevice)
+ {
+ SND_CDObject* pCD = SND_CDObject::Instance();
+
+ if (pCD)
+ {
+ int playstate = pCD->GetPlaystate();
+
+ switch (playstate)
+ {
+ case SND_MUST_PLAY:
+ {
+ // initialize the cd only when you need it
+ m_audiodevice->SetCDGain(pCD->GetGain());
+ m_audiodevice->SetCDPlaymode(pCD->GetPlaymode());
+ m_audiodevice->PlayCD(pCD->GetTrack());
+ pCD->SetPlaystate(SND_PLAYING);
+ pCD->SetUsed();
+ break;
+ }
+ case SND_MUST_PAUSE:
+ {
+ m_audiodevice->PauseCD(true);
+ pCD->SetPlaystate(SND_PAUSED);
+ break;
+ }
+ case SND_MUST_RESUME:
+ {
+ m_audiodevice->PauseCD(false);
+ pCD->SetPlaystate(SND_PLAYING);
+ break;
+ }
+ case SND_MUST_STOP:
+ {
+ m_audiodevice->StopCD();
+ pCD->SetPlaystate(SND_STOPPED);
+ break;
+ }
+ default:
+ {
+ }
+ }
+
+ // this one is only for realtime modifying settings
+ if (pCD->IsModified())
+ {
+ m_audiodevice->SetCDGain(pCD->GetGain());
+ pCD->SetModified(false);
+ }
+ }
+ }
+}
+
+
+
+void SND_Scene::Proceed()
+{
+ if (m_audio && m_audioplayback)
+ {
+ m_audiodevice->MakeCurrent();
+
+ UpdateListener();
+ UpdateActiveObects();
+ UpdateCD();
+
+// m_audiodevice->UpdateDevice();
+ }
+}
+
+
+void SND_Scene::DeleteObject(SND_SoundObject* pObject)
+{
+#ifdef ONTKEVER
+ printf("SND_Scene::DeleteObject\n");
+#endif
+
+ if (pObject)
+ {
+ if (m_audiodevice)
+ m_audiodevice->ClearId(pObject);
+
+ // must remove object from m_activeList
+ std::set<SND_SoundObject*>::iterator set_it;
+ set_it = m_soundobjects.find(pObject);
+
+ if (set_it != m_soundobjects.end())
+ m_soundobjects.erase(set_it);
+
+ // release the memory
+ delete pObject;
+ pObject = NULL;
+ }
+}
+
+
+
+void SND_Scene::RemoveAllObjects()
+{
+#ifdef ONTKEVER
+ printf("SND_Scene::RemoveAllObjects\n");
+#endif
+
+ StopAllObjects();
+
+ std::set<SND_SoundObject*>::iterator it = m_soundobjects.begin();
+
+ while (it != m_soundobjects.end())
+ {
+ delete (*it);
+ it++;
+ }
+
+ m_soundobjects.clear();
+}
+
+
+
+void SND_Scene::StopAllObjects()
+{
+ if (m_audio)
+ {
+#ifdef ONTKEVER
+ printf("SND_Scene::StopAllObjects\n");
+#endif
+
+ SND_SoundObject* pObject;
+
+ for (pObject = (SND_SoundObject*)m_activeobjects.getHead();
+ !pObject->isTail();
+ pObject = (SND_SoundObject*)pObject->getNext())
+ {
+ m_audiodevice->ClearId(pObject);
+ }
+ }
+}
+
+
+
+SND_SoundListener* SND_Scene::GetListener()
+{
+ return &m_listener;
+}
diff --git a/intern/SoundSystem/intern/SND_SoundListener.cpp b/intern/SoundSystem/intern/SND_SoundListener.cpp
new file mode 100644
index 00000000000..26163e87765
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_SoundListener.cpp
@@ -0,0 +1,185 @@
+/*
+ * SND_SoundListener.cpp
+ *
+ * A SoundListener is for sound what a camera is for vision.
+ *
+ * $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 *****
+ */
+
+#include "SND_SoundListener.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SND_SoundListener::SND_SoundListener()
+{
+ m_modified = true;
+ m_gain = 1.0;
+ m_dopplerfactor = 1.0;
+ m_dopplervelocity = 1.0;
+ m_scale = 1.0;
+ m_position[0] = 0.0;
+ m_position[1] = 0.0;
+ m_position[2] = 0.0;
+ m_velocity[0] = 0.0;
+ m_velocity[1] = 0.0;
+ m_velocity[2] = 0.0;
+ m_orientation[0][0] = 1.0;
+ m_orientation[0][1] = 0.0;
+ m_orientation[0][2] = 0.0;
+ m_orientation[1][0] = 0.0;
+ m_orientation[1][1] = 1.0;
+ m_orientation[1][2] = 0.0;
+ m_orientation[2][0] = 0.0;
+ m_orientation[2][1] = 0.0;
+ m_orientation[2][2] = 1.0;
+}
+
+
+SND_SoundListener::~SND_SoundListener()
+{
+ ; /* intentionally empty */
+
+}
+
+
+
+void SND_SoundListener::SetGain(MT_Scalar gain)
+{
+ m_gain = gain;
+ m_modified = true;
+}
+
+
+
+void SND_SoundListener::SetPosition (const MT_Vector3& pos)
+{
+ m_position = pos;
+}
+
+
+
+void SND_SoundListener::SetVelocity(const MT_Vector3& vel)
+{
+ m_velocity = vel;
+}
+
+
+
+void SND_SoundListener::SetOrientation(const MT_Matrix3x3& ori)
+{
+ m_orientation = ori;
+}
+
+
+
+void SND_SoundListener::SetDopplerFactor(MT_Scalar dopplerfactor)
+{
+ m_dopplerfactor = dopplerfactor;
+ m_modified = true;
+}
+
+
+
+void SND_SoundListener::SetDopplerVelocity(MT_Scalar dopplervelocity)
+{
+ m_dopplervelocity = dopplervelocity;
+ m_modified = true;
+}
+
+
+
+void SND_SoundListener::SetScale(MT_Scalar scale)
+{
+ m_scale = scale;
+ m_modified = true;
+}
+
+
+
+MT_Scalar SND_SoundListener::GetGain() const
+{
+ return m_gain;
+}
+
+
+
+MT_Vector3 SND_SoundListener::GetPosition() const
+{
+ return m_position;
+}
+
+
+
+MT_Vector3 SND_SoundListener::GetVelocity() const
+{
+ return m_velocity;
+}
+
+
+
+MT_Matrix3x3 SND_SoundListener::GetOrientation()
+{
+ return m_orientation;
+}
+
+
+
+MT_Scalar SND_SoundListener::GetDopplerFactor() const
+{
+ return m_dopplerfactor;
+}
+
+
+
+MT_Scalar SND_SoundListener::GetDopplerVelocity() const
+{
+ return m_dopplervelocity;
+}
+
+
+
+MT_Scalar SND_SoundListener::GetScale() const
+{
+ return m_scale;
+}
+
+
+
+bool SND_SoundListener::IsModified() const
+{
+ return m_modified;
+}
+
+
+
+void SND_SoundListener::SetModified(bool modified)
+{
+ m_modified = modified;
+}
diff --git a/intern/SoundSystem/intern/SND_SoundObject.cpp b/intern/SoundSystem/intern/SND_SoundObject.cpp
new file mode 100644
index 00000000000..7a244b5090d
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_SoundObject.cpp
@@ -0,0 +1,508 @@
+/*
+ * SND_SoundObject.cpp
+ *
+ * Implementation of the abstract sound object
+ *
+ * $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 *****
+ */
+
+#include "SND_SoundObject.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SND_SoundObject::SND_SoundObject()// : m_modified(true)
+{
+ m_samplename = "";
+ m_length = 0;
+ m_buffer = 0;
+
+ m_gain = 0.0;
+ m_pitch = 1.0;
+
+ m_mingain = 0.0;
+ m_maxgain = 1.0;
+ m_rollofffactor = 1.0;
+ m_referencedistance = 1.0;
+
+ m_position[0] = 0.0;
+ m_position[1] = 0.0;
+ m_position[2] = 0.0;
+ m_velocity[0] = 0.0;
+ m_velocity[1] = 0.0;
+ m_velocity[2] = 0.0;
+ m_orientation[0][0] = 1.0;
+ m_orientation[0][1] = 0.0;
+ m_orientation[0][2] = 0.0;
+ m_orientation[1][0] = 0.0;
+ m_orientation[1][1] = 1.0;
+ m_orientation[1][2] = 0.0;
+ m_orientation[2][0] = 0.0;
+ m_orientation[2][1] = 0.0;
+ m_orientation[2][2] = 1.0;
+
+ m_loopstart = 0;
+ m_loopend = 0;
+ m_loopmode = SND_LOOP_NORMAL;
+ m_is3d = true;
+ m_playstate = SND_INITIAL;
+ m_active = false;
+ m_id = -1;
+ m_lifespan = 0;
+ m_timestamp = 0;
+ m_modified = true;
+ m_running = 0;
+ m_highpriority = false;
+}
+
+
+
+SND_SoundObject::~SND_SoundObject()
+{
+}
+
+
+
+void SND_SoundObject::StartSound()
+{
+ if (m_id >= 0)
+ m_playstate = SND_MUST_PLAY;
+}
+
+
+
+void SND_SoundObject::StopSound()
+{
+ if (m_id >= 0)
+ m_playstate = SND_MUST_STOP;
+}
+
+
+
+void SND_SoundObject::PauseSound()
+{
+ if (m_id >= 0)
+ m_playstate = SND_MUST_PAUSE;
+}
+
+
+
+void SND_SoundObject::DeleteWhenFinished()
+{
+ m_playstate = SND_MUST_BE_DELETED;
+}
+
+
+
+void SND_SoundObject::SetGain(MT_Scalar gain)
+{
+ m_gain = gain;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetMinGain(MT_Scalar mingain)
+{
+ m_mingain = mingain;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetMaxGain(MT_Scalar maxgain)
+{
+ m_maxgain = maxgain;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetRollOffFactor(MT_Scalar rollofffactor)
+{
+ m_rollofffactor = rollofffactor;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetReferenceDistance(MT_Scalar referencedistance)
+{
+ m_referencedistance = referencedistance;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetPitch(MT_Scalar pitch)
+{
+ m_pitch = pitch;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetLoopMode(unsigned int loopmode)
+{
+ m_loopmode = loopmode;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetLoopStart(unsigned int loopstart)
+{
+ m_loopstart = loopstart;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::SetLoopEnd(unsigned int loopend)
+{
+ m_loopend = loopend;
+ m_modified = true;
+}
+
+
+
+void SND_SoundObject::Set3D(bool threedee)
+{
+ m_is3d = threedee;
+}
+
+
+
+void SND_SoundObject::SetLifeSpan()
+{
+ m_lifespan = m_length / m_pitch;
+}
+
+
+
+bool SND_SoundObject::IsLifeSpanOver(MT_Scalar curtime) const
+{
+ bool result = false;
+
+ if ((curtime - m_timestamp) > m_lifespan)
+ result = true;
+
+ return result;
+}
+
+
+
+void SND_SoundObject::SetActive(bool active)
+{
+ m_active = active;
+
+ if (!active)
+ {
+ m_playstate = SND_STOPPED;
+ (this)->remove();
+ }
+}
+
+
+
+void SND_SoundObject::SetBuffer(unsigned int buffer)
+{
+ m_buffer = buffer;
+}
+
+
+
+void SND_SoundObject::SetObjectName(STR_String objectname)
+{
+ m_objectname = objectname;
+}
+
+
+
+void SND_SoundObject::SetSampleName(STR_String samplename)
+{
+ m_samplename = samplename;
+}
+
+
+
+void SND_SoundObject::SetLength(MT_Scalar length)
+{
+ m_length = length;
+}
+
+
+
+void SND_SoundObject::SetPosition(const MT_Vector3& pos)
+{
+ m_position = pos;
+}
+
+
+
+void SND_SoundObject::SetVelocity(const MT_Vector3& vel)
+{
+ m_velocity = vel;
+}
+
+
+
+void SND_SoundObject::SetOrientation(const MT_Matrix3x3& orient)
+{
+ m_orientation = orient;
+}
+
+
+
+void SND_SoundObject::SetPlaystate(int playstate)
+{
+ m_playstate = playstate;
+}
+
+
+
+void SND_SoundObject::SetId(int id)
+{
+ m_id = id;
+}
+
+
+
+void SND_SoundObject::SetTimeStamp(MT_Scalar timestamp)
+{
+ m_timestamp = timestamp;
+}
+
+
+
+void SND_SoundObject::SetHighPriority(bool priority)
+{
+ m_highpriority = priority;
+}
+
+
+
+bool SND_SoundObject::IsHighPriority() const
+{
+ return m_highpriority;
+}
+
+
+
+bool SND_SoundObject::IsActive()const
+{
+ return m_active;
+}
+
+
+
+int SND_SoundObject::GetId()const
+{
+ return m_id;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetLifeSpan()const
+{
+ return m_lifespan;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetTimestamp()const
+{
+ return m_timestamp;
+}
+
+
+
+unsigned int SND_SoundObject::GetBuffer()
+{
+ return m_buffer;
+}
+
+
+
+const STR_String& SND_SoundObject::GetSampleName()
+{
+ return m_samplename;
+}
+
+
+
+const STR_String& SND_SoundObject::GetObjectName()
+{
+ return m_objectname;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetLength() const
+{
+ return m_length;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetGain() const
+{
+ return m_gain;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetPitch() const
+{
+ return m_pitch;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetMinGain() const
+{
+ return m_mingain;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetMaxGain() const
+{
+ return m_maxgain;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetRollOffFactor() const
+{
+ return m_rollofffactor;
+}
+
+
+
+MT_Scalar SND_SoundObject::GetReferenceDistance() const
+{
+ return m_referencedistance;
+}
+
+
+
+MT_Vector3 SND_SoundObject::GetPosition() const
+{
+ return m_position;
+}
+
+
+
+MT_Vector3 SND_SoundObject::GetVelocity() const
+{
+ return m_velocity;
+}
+
+
+
+MT_Matrix3x3 SND_SoundObject::GetOrientation() const
+{
+ return m_orientation;
+}
+
+
+
+unsigned int SND_SoundObject::GetLoopMode() const
+{
+ return m_loopmode;
+}
+
+
+
+unsigned int SND_SoundObject::GetLoopStart() const
+{
+ return m_loopstart;
+}
+
+
+
+unsigned int SND_SoundObject::GetLoopEnd() const
+{
+ return m_loopend;
+}
+
+
+
+bool SND_SoundObject::Is3D() const
+{
+ return m_is3d;
+}
+
+
+
+int SND_SoundObject::GetPlaystate() const
+{
+ return m_playstate;
+}
+
+
+
+bool SND_SoundObject::IsModified() const
+{
+ return m_modified;
+}
+
+
+
+void SND_SoundObject::SetModified(bool modified)
+{
+ m_modified = modified;
+}
+
+
+
+void SND_SoundObject::InitRunning()
+{
+ m_running = 0;
+}
+
+
+
+bool SND_SoundObject::IsRunning() const
+{
+ bool result = false;
+
+ if (m_running > 100)
+ result = true;
+
+ return result;
+}
+
+
+
+void SND_SoundObject::AddRunning()
+{
+ ++m_running;
+}
diff --git a/intern/SoundSystem/intern/SND_Utils.cpp b/intern/SoundSystem/intern/SND_Utils.cpp
new file mode 100644
index 00000000000..dbc3135b35c
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_Utils.cpp
@@ -0,0 +1,424 @@
+/*
+ * SND_Utils.cpp
+ *
+ * Util functions for soundthingies
+ *
+ * $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 *****
+ */
+
+#include "SND_Utils.h"
+#include "SoundDefines.h"
+#include "SND_DependKludge.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include <string.h>
+
+#if defined(_WIN32)
+#include <io.h>
+#define open _open
+#define read _read
+#define close _close
+#define write _write
+#define lseek _lseek
+#else
+#include <unistd.h>
+#endif
+
+#define BUFFERSIZE 32
+
+
+/*****************************************************************************
+ * Begin of temporary Endian stuff.
+ * I think there should be a central place to handle endian conversion but for
+ * the time being it suffices. Note that the defines come from the Blender
+ * source.
+ *****************************************************************************/
+typedef enum
+{
+ SND_endianBig = 0,
+ SND_endianLittle
+} SND_TEndian;
+
+#if defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__)
+const SND_TEndian SND_fEndian = SND_endianBig;
+#else
+const SND_TEndian SND_fEndian = SND_endianLittle;
+#endif
+
+/* This one swaps the bytes in a short */
+#define SWITCH_SHORT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; \
+ p_i[0] = p_i[1]; \
+ p_i[1] = s_i; }
+
+/* This one rotates the bytes in an int */
+#define SWITCH_INT(a) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+/*****************************************************************************
+ * End of temporary Endian stuff.
+ *****************************************************************************/
+
+
+/* loads a file */
+void* SND_LoadSample(char *filename)
+{
+ int file, filelen, buffersize = BUFFERSIZE;
+ void* data = NULL;
+
+#if defined(WIN32)
+ file = open(filename, O_BINARY|O_RDONLY);
+#else
+ file = open(filename, 0|O_RDONLY);
+#endif
+
+ if (file == -1)
+ {
+ //printf("can't open file.\n");
+ //printf("press q for quit.\n");
+ }
+ else
+ {
+ filelen = lseek(file, 0, SEEK_END);
+ lseek(file, 0, SEEK_SET);
+
+ if (filelen != 0)
+ {
+ data = malloc(buffersize);
+
+ if (read(file, data, buffersize) != buffersize)
+ {
+ free(data);
+ data = NULL;
+ }
+ }
+ close(file);
+
+ }
+ return (data);
+}
+
+
+
+bool SND_IsSampleValid(const STR_String& name, void* memlocation)
+{
+ bool result = false;
+ bool loadedsample = false;
+ char buffer[BUFFERSIZE];
+
+ if (!memlocation)
+ {
+ STR_String samplename = name;
+ memlocation = SND_LoadSample(samplename.Ptr());
+
+ if (memlocation)
+ loadedsample = true;
+ }
+
+ if (memlocation)
+ {
+ memcpy(&buffer, memlocation, BUFFERSIZE);
+
+ if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
+ {
+ /* This was endian unsafe. See top of the file for the define. */
+ short shortbuf = *((short *) &buffer[20]);
+ if (SND_fEndian == SND_endianBig) SWITCH_SHORT(shortbuf);
+
+ if (shortbuf == SND_WAVE_FORMAT_PCM)
+ result = true;
+ }
+ }
+ if (loadedsample)
+ {
+ free(memlocation);
+ memlocation = NULL;
+ }
+
+ return result;
+}
+
+
+
+/* checks if the passed pointer is a valid sample */
+static bool CheckSample(void* sample)
+{
+ bool valid = false;
+ char buffer[32];
+
+ memcpy(buffer, sample, 16);
+
+ if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
+ {
+ valid = true;
+ }
+
+ return valid;
+}
+
+
+
+/* gets the type of the sample (0 == unknown, 1 == PCM etc */
+unsigned int SND_GetSampleFormat(void* sample)
+{
+ short sampletype = 0;
+
+ if (CheckSample(sample))
+ {
+ memcpy(&sampletype, ((char*)sample) + 20, 2);
+ }
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig) SWITCH_SHORT(sampletype);
+
+ return (unsigned int)sampletype;
+}
+
+
+
+/* gets the number of channels in a sample */
+unsigned int SND_GetNumberOfChannels(void* sample)
+{
+ short numberofchannels = 0;
+
+ if (CheckSample(sample))
+ {
+ memcpy(&numberofchannels, ((char*)sample) + 22, 2);
+ }
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig) SWITCH_SHORT(numberofchannels);
+
+ return (unsigned int)numberofchannels;
+}
+
+
+
+/* gets the samplerate of a sample */
+unsigned int SND_GetSampleRate(void* sample)
+{
+ unsigned int samplerate = 0;
+
+ if (CheckSample(sample))
+ {
+ memcpy(&samplerate, ((char*)sample) + 24, 4);
+ }
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig) SWITCH_INT(samplerate);
+
+ return samplerate;
+}
+
+
+
+/* gets the bitrate of a sample */
+unsigned int SND_GetBitRate(void* sample)
+{
+ short bitrate = 0;
+
+ if (CheckSample(sample))
+ {
+ memcpy(&bitrate, ((char*)sample) + 34, 2);
+ }
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig) SWITCH_SHORT(bitrate);
+
+ return (unsigned int)bitrate;
+}
+
+
+
+/* gets the length of the actual sample data (without the header) */
+unsigned int SND_GetNumberOfSamples(void* sample, unsigned int sample_length)
+{
+ unsigned int chunklength, length = 0, offset;
+ unsigned short block_align;
+ if (CheckSample(sample))
+ {
+ memcpy(&chunklength, ((char*)sample) + 16, 4);
+ memcpy(&block_align, ((char*)sample) + 32, 2); /* always 2 or 4 it seems */
+
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig)
+ {
+ SWITCH_INT(chunklength);
+ SWITCH_SHORT(block_align);
+ }
+
+ offset = 16 + chunklength + 4;
+
+ /* This seems very unsafe, what if data is never found (f.i. corrupt file)... */
+ // lets find "data"
+ while (memcmp(((char*)sample) + offset, "data", 4))
+ {
+ offset += block_align;
+
+ if (offset+block_align > sample_length) /* save us from crashing */
+ return 0;
+ }
+ offset += 4;
+ memcpy(&length, ((char*)sample) + offset, 4);
+
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig) SWITCH_INT(length);
+ }
+
+ return length;
+}
+
+
+
+/* gets the size of the entire header (file - sampledata) */
+unsigned int SND_GetHeaderSize(void* sample, unsigned int sample_length)
+{
+ unsigned int chunklength, headersize = 0, offset = 16;
+ unsigned short block_align;
+ if (CheckSample(sample))
+ {
+ memcpy(&chunklength, ((char*)sample) + offset, 4);
+ memcpy(&block_align, ((char*)sample) + 32, 2); /* always 2 or 4 it seems */
+
+ /* This was endian unsafe. See top of the file for the define. */
+ if (SND_fEndian == SND_endianBig)
+ {
+ SWITCH_INT(chunklength);
+ SWITCH_SHORT(block_align);
+ }
+ offset = offset + chunklength + 4;
+
+ // lets find "data"
+ while (memcmp(((char*)sample) + offset, "data", 4))
+ {
+ offset += block_align;
+
+ if (offset+block_align > sample_length) /* save us from crashing */
+ return 0;
+ }
+ headersize = offset + 8;
+ }
+
+ return headersize;
+}
+
+
+unsigned int SND_GetExtraChunk(void* sample)
+{
+ unsigned int extrachunk = 0, chunklength, offset = 16;
+ char data[4];
+
+ if (CheckSample(sample))
+ {
+ memcpy(&chunklength, ((char*)sample) + offset, 4);
+ offset = offset + chunklength + 4;
+ memcpy(data, ((char*)sample) + offset, 4);
+
+ // lets find "cue"
+ while (memcmp(data, "cue", 3))
+ {
+ offset += 4;
+ memcpy(data, ((char*)sample) + offset, 4);
+ }
+ }
+
+ return extrachunk;
+}
+
+
+
+void SND_GetSampleInfo(signed char* sample, SND_WaveSlot* waveslot)
+{
+ WavFileHeader fileheader;
+ WavFmtHeader fmtheader;
+ WavFmtExHeader fmtexheader;
+ WavSampleHeader sampleheader;
+ WavChunkHeader chunkheader;
+
+ if (CheckSample(sample))
+ {
+ memcpy(&fileheader, sample, sizeof(WavFileHeader));
+ fileheader.size = SND_GetHeaderSize(sample, waveslot->GetFileSize());
+ if (fileheader.size) { /* this may fail for corrupt files */
+ sample += sizeof(WavFileHeader);
+ fileheader.size = ((fileheader.size+1) & ~1) - 4;
+
+ while ((fileheader.size > 0) && (memcpy(&chunkheader, sample, sizeof(WavChunkHeader))))
+ {
+ sample += sizeof(WavChunkHeader);
+ if (!memcmp(chunkheader.id, "fmt ", 4))
+ {
+ memcpy(&fmtheader, sample, sizeof(WavFmtHeader));
+ waveslot->SetSampleFormat(fmtheader.format);
+
+ if (fmtheader.format == 0x0001)
+ {
+ waveslot->SetNumberOfChannels(fmtheader.numberofchannels);
+ waveslot->SetBitRate(fmtheader.bitrate);
+ waveslot->SetSampleRate(fmtheader.samplerate);
+ sample += chunkheader.size;
+ }
+ else
+ {
+ memcpy(&fmtexheader, sample, sizeof(WavFmtExHeader));
+ sample += chunkheader.size;
+ }
+ }
+ else if (!memcmp(chunkheader.id, "data", 4))
+ {
+ if (fmtheader.format == 0x0001)
+ {
+ waveslot->SetNumberOfSamples(chunkheader.size);
+ sample += chunkheader.size;
+ }
+ else if (fmtheader.format == 0x0011)
+ {
+ //IMA ADPCM
+ }
+ else if (fmtheader.format == 0x0055)
+ {
+ //MP3 WAVE
+ }
+ }
+ else if (!memcmp(chunkheader.id, "smpl", 4))
+ {
+ memcpy(&sampleheader, sample, sizeof(WavSampleHeader));
+ //loop = sampleheader.loops;
+ sample += chunkheader.size;
+ }
+ else
+ sample += chunkheader.size;
+
+ sample += chunkheader.size & 1;
+ fileheader.size -= (((chunkheader.size + 1) & ~1) + 8);
+ }
+ }
+ }
+}
diff --git a/intern/SoundSystem/intern/SND_WaveCache.cpp b/intern/SoundSystem/intern/SND_WaveCache.cpp
new file mode 100644
index 00000000000..a678bd554bb
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_WaveCache.cpp
@@ -0,0 +1,138 @@
+/*
+ * SND_WaveCache.cpp
+ *
+ * abstract wavecache, a way to organize samples
+ *
+ * $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 *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#pragma warning (disable:4786) // Get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_WaveCache.h"
+#include <stdio.h>
+
+#ifdef __APPLE__
+# include <sys/malloc.h>
+#else
+# ifdef __FreeBSD__
+# include <stdlib.h>
+# else
+# include <malloc.h>
+# endif
+#endif
+
+SND_WaveCache::SND_WaveCache()
+{
+ // do the buffer administration
+ for (int i = 0; i < NUM_BUFFERS; i++)
+ m_bufferList[i] = NULL;
+}
+
+
+
+SND_WaveCache::~SND_WaveCache()
+{
+ // clean up the mess
+ FreeSamples();
+ RemoveAllSamples();
+}
+
+
+
+SND_WaveSlot* SND_WaveCache::GetWaveSlot(const STR_String& samplename)
+{
+ SND_WaveSlot* waveslot = NULL;
+
+ std::map<STR_String, SND_WaveSlot*>::iterator find_result = m_samplecache.find(samplename);
+
+ // let's see if we have already loaded this sample
+ if (find_result != m_samplecache.end())
+ {
+ waveslot = (*find_result).second;
+ }
+ else
+ {
+ // so the sample wasn't loaded, so do it here
+ for (int bufnum = 0; bufnum < NUM_BUFFERS; bufnum++)
+ {
+ // find an empty buffer
+ if (m_bufferList[bufnum] == NULL)
+ {
+ waveslot = new SND_WaveSlot();
+ waveslot->SetSampleName(samplename);
+ waveslot->SetBuffer(bufnum);
+ m_bufferList[bufnum] = waveslot;
+ break;
+ }
+ }
+ m_samplecache.insert(std::pair<STR_String, SND_WaveSlot*>(samplename, waveslot));
+ }
+
+ return waveslot;
+}
+
+
+
+void SND_WaveCache::RemoveAllSamples()
+{
+ // remove all samples
+ m_samplecache.clear();
+
+ // reset the list of buffers
+ for (int i = 0; i < NUM_BUFFERS; i++)
+ m_bufferList[i] = NULL;
+}
+
+
+
+void SND_WaveCache::RemoveSample(const STR_String& samplename, int buffer)
+{
+ m_samplecache.erase(samplename);
+ m_bufferList[buffer] = NULL;
+}
+
+
+
+void SND_WaveCache::FreeSamples()
+{
+ // iterate through the bufferlist and delete the waveslot if present
+ for (int i = 0; i < NUM_BUFFERS; i++)
+ {
+ if (m_bufferList[i])
+ {
+ delete m_bufferList[i];
+ m_bufferList[i] = NULL;
+ }
+ }
+}
diff --git a/intern/SoundSystem/intern/SND_WaveSlot.cpp b/intern/SoundSystem/intern/SND_WaveSlot.cpp
new file mode 100644
index 00000000000..43b2bb55892
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_WaveSlot.cpp
@@ -0,0 +1,180 @@
+/**
+ * $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 *****
+ */
+
+#include "SND_WaveSlot.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+SND_WaveSlot::~SND_WaveSlot()
+{
+#ifdef ONTKEVER
+ printf("neeeeeee...\n");
+#endif
+}
+
+
+
+void SND_WaveSlot::SetSampleName(STR_String samplename)
+{
+ m_samplename = samplename;
+}
+
+
+
+void SND_WaveSlot::SetLoaded(bool loaded)
+{
+ m_loaded = loaded;
+}
+
+
+
+void SND_WaveSlot::SetData(void* data)
+{
+ m_data = data;
+}
+
+
+
+void SND_WaveSlot::SetBuffer(unsigned int buffer)
+{
+ m_buffer = buffer;
+}
+
+
+
+void SND_WaveSlot::SetSampleFormat(unsigned int sampleformat)
+{
+ m_sampleformat = sampleformat;
+}
+
+
+
+void SND_WaveSlot::SetNumberOfChannels(unsigned int numberofchannels)
+{
+ m_numberofchannels = numberofchannels;
+}
+
+
+
+void SND_WaveSlot::SetSampleRate(unsigned int samplerate)
+{
+ m_samplerate = samplerate;
+}
+
+
+
+void SND_WaveSlot::SetBitRate(unsigned int bitrate)
+{
+ m_bitrate = bitrate;
+}
+
+
+
+void SND_WaveSlot::SetNumberOfSamples(unsigned int numberofsamples)
+{
+ m_numberofsamples = numberofsamples;
+}
+
+
+
+void SND_WaveSlot::SetFileSize(unsigned int filesize)
+{
+ m_filesize = filesize;
+}
+
+
+
+const STR_String& SND_WaveSlot::GetSampleName()
+{
+ return m_samplename;
+}
+
+
+
+bool SND_WaveSlot::IsLoaded() const
+{
+ return m_loaded;
+}
+
+
+
+void* SND_WaveSlot::GetData()
+{
+ return m_data;
+}
+
+
+
+unsigned int SND_WaveSlot::GetBuffer() const
+{
+ return m_buffer;
+}
+
+
+
+unsigned int SND_WaveSlot::GetSampleFormat() const
+{
+ return m_sampleformat;
+}
+
+
+
+unsigned int SND_WaveSlot::GetNumberOfChannels() const
+{
+ return m_numberofchannels;
+}
+
+
+
+unsigned int SND_WaveSlot::GetSampleRate() const
+{
+ return m_samplerate;
+}
+
+
+
+unsigned int SND_WaveSlot::GetBitRate() const
+{
+ return m_bitrate;
+}
+
+
+
+unsigned int SND_WaveSlot::GetNumberOfSamples() const
+{
+ return m_numberofsamples;
+}
+
+
+
+unsigned int SND_WaveSlot::GetFileSize() const
+{
+ return m_filesize;
+}
diff --git a/intern/SoundSystem/make/msvc_6_0/SoundSystem.dsp b/intern/SoundSystem/make/msvc_6_0/SoundSystem.dsp
new file mode 100644
index 00000000000..1bd973dfb6c
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_6_0/SoundSystem.dsp
@@ -0,0 +1,206 @@
+# Microsoft Developer Studio Project File - Name="SoundSystem" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=SoundSystem - Win32 Release
+!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 "SoundSystem.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 "SoundSystem.mak" CFG="SoundSystem - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SoundSystem - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "SoundSystem - 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)" == "SoundSystem - 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\soundsystem"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\soundsystem"
+# 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 /MT /W3 /GX /O2 /I "../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/moto/include" /I "../../dummy" /I "../../openal" /I "..\..\..\string" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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\soundsystem\libSoundSystem.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\SoundSystem\include\*.h ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\soundsystem\*.lib ..\..\..\..\..\lib\windows\SoundSystem\lib\*.a ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "SoundSystem - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "SoundSystem___Win32_Debug"
+# PROP BASE Intermediate_Dir "SoundSystem___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\obj\windows\intern\soundsystem\debug"
+# PROP Intermediate_Dir "..\..\..\..\obj\windows\intern\soundsystem\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 /MTd /W3 /Gm /GX /Zi /Od /I "../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/moto/include" /I "../../dummy" /I "../../openal" /I "..\..\..\string" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /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\soundsystem\debug\libSoundSystem.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files XCOPY /Y ..\..\*.h ..\..\..\..\..\lib\windows\SoundSystem\include\*.h ECHO Copying lib XCOPY /Y ..\..\..\..\obj\windows\intern\soundsystem\debug\*.lib ..\..\..\..\..\lib\windows\SoundSystem\lib\debug\*.a ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "SoundSystem - Win32 Release"
+# Name "SoundSystem - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\SND_AudioDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\intern\SND_C-api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_CDObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_DeviceManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_IdObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_Scene.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_SoundListener.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_SoundObject.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_Utils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_WaveCache.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_WaveSlot.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\intern\SND_AudioDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\SND_C-api.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_CDObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_DependKludge.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_DeviceManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_IAudioDevice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\SND_IdObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_Object.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_Scene.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_SoundListener.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_SoundObject.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_Utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_WaveCache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SND_WaveSlot.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\SoundDefines.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/SoundSystem/make/msvc_6_0/dummy/DummySoundSystem.dsp b/intern/SoundSystem/make/msvc_6_0/dummy/DummySoundSystem.dsp
new file mode 100644
index 00000000000..2bf372d0382
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_6_0/dummy/DummySoundSystem.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="DummySoundSystem" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=DummySoundSystem - Win32 Release
+!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 "DummySoundSystem.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 "DummySoundSystem.mak" CFG="DummySoundSystem - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "DummySoundSystem - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "DummySoundSystem - 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)" == "DummySoundSystem - 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\soundsystem\dummy"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\intern\soundsystem\dummy"
+# 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 /MT /W3 /GX /O2 /I "..\..\..\intern" /I "..\..\..\..\SoundSystem" /I "..\..\..\..\moto\include" /I "..\..\..\..\string" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /J /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\soundsystem\dummy\libDummySoundSystem.lib"
+
+!ELSEIF "$(CFG)" == "DummySoundSystem - 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\soundsystem\dummy\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\intern\soundsystem\dummy\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 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\intern" /I "..\..\..\..\SoundSystem" /I "..\..\..\..\moto\include" /I "..\..\..\..\string" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /J /FD /c
+# SUBTRACT CPP /Fr
+# 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\soundsystem\dummy\debug\libDummySoundSystem.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "DummySoundSystem - Win32 Release"
+# Name "DummySoundSystem - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\dummy\SND_DummyDevice.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\dummy\SND_DummyDevice.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/SoundSystem/make/msvc_6_0/openal/OpenALSoundSystem.dsp b/intern/SoundSystem/make/msvc_6_0/openal/OpenALSoundSystem.dsp
new file mode 100644
index 00000000000..ef0c10e8eff
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_6_0/openal/OpenALSoundSystem.dsp
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="OpenALSoundSystem" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=OpenALSoundSystem - Win32 Release
+!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 "OpenALSoundSystem.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 "OpenALSoundSystem.mak" CFG="OpenALSoundSystem - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "OpenALSoundSystem - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "OpenALSoundSystem - 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)" == "OpenALSoundSystem - 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\soundsystem\openal"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\intern\soundsystem\openal"
+# 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 /MT /W3 /GX /O2 /I "..\..\..\intern" /I "..\..\..\..\SoundSystem" /I "..\..\..\..\SoundSystem\sdl" /I "..\..\..\..\moto\include" /I "..\..\..\..\string" /I "..\..\..\..\..\..\lib\windows\openal\include" /I "..\..\..\..\..\..\lib\windows\sdl\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /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\soundsystem\openal\libOpenALSoundSystem.lib"
+
+!ELSEIF "$(CFG)" == "OpenALSoundSystem - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "OpenALSoundSystem___Win32_Debug"
+# PROP BASE Intermediate_Dir "OpenALSoundSystem___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\..\..\..\obj\windows\intern\soundsystem\openal\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\windows\intern\soundsystem\openal\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 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\intern" /I "..\..\..\..\SoundSystem" /I "..\..\..\..\SoundSystem\sdl" /I "..\..\..\..\moto\include" /I "..\..\..\..\string" /I "..\..\..\..\..\..\lib\windows\sdl\include" /I "..\..\..\..\..\..\lib\windows\openal\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /J /FD /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\soundsystem\openal\debug\libOpenALSoundSystem.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "OpenALSoundSystem - Win32 Release"
+# Name "OpenALSoundSystem - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\openal\SND_OpenALDevice.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\sdl\SND_SDLCDDevice.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\..\openal\SND_OpenALDevice.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/SoundSystem/make/msvc_7_0/SoundSystem.vcproj b/intern/SoundSystem/make/msvc_7_0/SoundSystem.vcproj
new file mode 100644
index 00000000000..f0952c582b7
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_7_0/SoundSystem.vcproj
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="SoundSystem"
+ ProjectGUID="{98330220-47A6-42E0-9DE4-AD0FF5D204D6}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\intern\soundsystem\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\intern\debug\libSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\intern\soundsystem\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\intern\soundsystem\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\intern\libSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\intern\mtdll\libSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_7\intern\soundsystem\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_7\libs\intern\mtdll\debug\libSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_7\intern\SoundSystem\include
+ECHO Done
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\intern\SND_AudioDevice.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_C-api.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_CDObject.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_DeviceManager.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_IdObject.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_Scene.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_SoundListener.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_SoundObject.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_Utils.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_WaveCache.cpp">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_WaveSlot.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\intern\SND_AudioDevice.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_C-api.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_CDObject.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_DependKludge.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_DeviceManager.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_IAudioDevice.h">
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_IdObject.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_Object.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_Scene.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_SoundListener.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_SoundObject.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_Utils.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_WaveCache.h">
+ </File>
+ <File
+ RelativePath="..\..\SND_WaveSlot.h">
+ </File>
+ <File
+ RelativePath="..\..\SoundDefines.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/make/msvc_7_0/dummy/DummySoundSystem.vcproj b/intern/SoundSystem/make/msvc_7_0/dummy/DummySoundSystem.vcproj
new file mode 100644
index 00000000000..103b589e732
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_7_0/dummy/DummySoundSystem.vcproj
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="DummySoundSystem"
+ ProjectGUID="{FAF46346-65CC-4DB2-85C4-B99826F79D0C}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="WIN32,NDEBUG,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\libDummySoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\debug\libDummySoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="WIN32,NDEBUG,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\mtdll\libDummySoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_7\intern\string\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\dummy\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\mtdll\debug\libDummySoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\..\dummy\SND_DummyDevice.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\..\dummy\SND_DummyDevice.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/make/msvc_7_0/openal/OpenALSoundSystem.vcproj b/intern/SoundSystem/make/msvc_7_0/openal/OpenALSoundSystem.vcproj
new file mode 100644
index 00000000000..8ce971ac1aa
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_7_0/openal/OpenALSoundSystem.vcproj
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="OpenALSoundSystem"
+ ProjectGUID="{213356A9-3A1F-41DA-9819-1297BCD17DEE}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\intern\string\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\debug\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\intern\string\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\intern\string\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\mtdll\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_7\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_7\intern\moto\include;..\..\..\..\..\..\build\msvc_7\intern\string\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_7\intern\soundsystem\openal\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_7\libs\intern\mtdll\debug\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\..\..\openal\SND_OpenALDevice.cpp">
+ </File>
+ <File
+ RelativePath="..\..\..\sdl\SND_SDLCDDevice.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\..\..\openal\SND_OpenALDevice.h">
+ </File>
+ <File
+ RelativePath="..\..\..\sdl\SND_SDLCDDevice.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/make/msvc_9_0/SoundSystem.vcproj b/intern/SoundSystem/make/msvc_9_0/SoundSystem.vcproj
new file mode 100644
index 00000000000..bd75fe88d43
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_9_0/SoundSystem.vcproj
@@ -0,0 +1,447 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="INT_SoundSystem"
+ ProjectGUID="{98330220-47A6-42E0-9DE4-AD0FF5D204D6}"
+ RootNamespace="SoundSystem"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\intern\soundsystem\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\intern\debug\libSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\intern\soundsystem\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\intern\soundsystem\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\intern\libSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\intern\mtdll\libSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..;..\..\dummy;..\..\openal;..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug\SoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\build\msvc_9\intern\soundsystem\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\build\msvc_9\libs\intern\mtdll\debug\libSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copying SND SoundSystem files library (debug target) to lib tree."
+ CommandLine="ECHO Copying header files&#x0D;&#x0A;IF NOT EXIST ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include MKDIR ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;XCOPY /Y ..\..\*.h ..\..\..\..\..\build\msvc_9\intern\SoundSystem\include&#x0D;&#x0A;ECHO Done&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\intern\SND_AudioDevice.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_C-api.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_CDObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_DeviceManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_IdObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_Scene.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_SoundListener.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_SoundObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_Utils.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_WaveCache.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_WaveSlot.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\intern\SND_AudioDevice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_C-api.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_CDObject.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_DependKludge.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_DeviceManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_IAudioDevice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\intern\SND_IdObject.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_Object.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_Scene.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_SoundListener.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_SoundObject.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_Utils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_WaveCache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SND_WaveSlot.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\SoundDefines.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/make/msvc_9_0/dummy/DummySoundSystem.vcproj b/intern/SoundSystem/make/msvc_9_0/dummy/DummySoundSystem.vcproj
new file mode 100644
index 00000000000..2109d92d430
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_9_0/dummy/DummySoundSystem.vcproj
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="INT_DummySoundSystem"
+ ProjectGUID="{FAF46346-65CC-4DB2-85C4-B99826F79D0C}"
+ RootNamespace="DummySoundSystem"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="WIN32,NDEBUG,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\libDummySoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\debug\libDummySoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="WIN32,NDEBUG,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\mtdll\libDummySoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\intern;..\..\..\..\..\..\build\msvc_9\intern\string\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug\DummySoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\dummy\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\mtdll\debug\libDummySoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\..\dummy\SND_DummyDevice.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\..\dummy\SND_DummyDevice.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/make/msvc_9_0/openal/OpenALSoundSystem.vcproj b/intern/SoundSystem/make/msvc_9_0/openal/OpenALSoundSystem.vcproj
new file mode 100644
index 00000000000..5593f00cb2b
--- /dev/null
+++ b/intern/SoundSystem/make/msvc_9_0/openal/OpenALSoundSystem.vcproj
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="INT_OpenALSoundSystem"
+ ProjectGUID="{213356A9-3A1F-41DA-9819-1297BCD17DEE}"
+ RootNamespace="OpenALSoundSystem"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Blender Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\debug\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Blender Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Release|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include"
+ PreprocessorDefinitions="NDEBUG,WIN32,_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\mtdll\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="3DPlugin Debug|Win32"
+ OutputDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug"
+ IntermediateDirectory="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\sdl;..\..\..\intern;..\..\..\..\..\..\lib\windows\sdl\include;..\..\..\..\..\..\lib\windows\openal\include;..\..\..\..\..\..\build\msvc_9\intern\soundsystem\include;..\..\..\..\..\..\build\msvc_9\intern\moto\include;..\..\..\..\..\..\build\msvc_9\intern\string\include"
+ PreprocessorDefinitions="_DEBUG,WIN32,_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ DefaultCharIsUnsigned="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug\OpenALSoundSystem.pch"
+ AssemblerListingLocation="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug\"
+ ObjectFile="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug\"
+ ProgramDataBaseFileName="..\..\..\..\..\..\build\msvc_9\intern\soundsystem\openal\mtdll\debug\"
+ WarningLevel="2"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\..\build\msvc_9\libs\intern\mtdll\debug\libOpenALSoundSystem.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\..\..\openal\SND_OpenALDevice.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\sdl\SND_SDLCDDevice.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\..\..\openal\SND_OpenALDevice.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\sdl\SND_SDLCDDevice.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/intern/SoundSystem/openal/Makefile b/intern/SoundSystem/openal/Makefile
new file mode 100644
index 00000000000..b28ab628d4c
--- /dev/null
+++ b/intern/SoundSystem/openal/Makefile
@@ -0,0 +1,44 @@
+#
+# $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 = OpenALSoundSystem
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_OPENAL)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
+CPPFLAGS += -I../sdl
diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp
new file mode 100644
index 00000000000..480f4ff6d74
--- /dev/null
+++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp
@@ -0,0 +1,854 @@
+/*
+ * $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 *****
+ * SND_OpenALDevice derived from SND_IAudioDevice
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_OpenALDevice.h"
+#ifndef __APPLE__
+#include "SND_SDLCDDevice.h"
+#endif
+#include "SoundDefines.h"
+
+#include "SND_Utils.h"
+
+#ifdef APPLE_FRAMEWORK_FIX
+#include <al.h>
+#include <alc.h>
+#else
+#include <AL/al.h>
+#include <AL/alc.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+#include <signal.h>
+
+/*************************** ALUT replacement *****************************/
+
+/* instead of relying on alut, we just implement our own
+ * WAV loading functions, hopefully more reliable */
+
+#include <stdlib.h>
+
+typedef struct /* WAV File-header */
+{
+ ALubyte Id[4];
+ ALsizei Size;
+ ALubyte Type[4];
+} WAVFileHdr_Struct;
+
+typedef struct /* WAV Fmt-header */
+{
+ ALushort Format;
+ ALushort Channels;
+ ALuint SamplesPerSec;
+ ALuint BytesPerSec;
+ ALushort BlockAlign;
+ ALushort BitsPerSample;
+} WAVFmtHdr_Struct;
+
+typedef struct /* WAV FmtEx-header */
+{
+ ALushort Size;
+ ALushort SamplesPerBlock;
+} WAVFmtExHdr_Struct;
+
+typedef struct /* WAV Smpl-header */
+{
+ ALuint Manufacturer;
+ ALuint Product;
+ ALuint SamplePeriod;
+ ALuint Note;
+ ALuint FineTune;
+ ALuint SMPTEFormat;
+ ALuint SMPTEOffest;
+ ALuint Loops;
+ ALuint SamplerData;
+ struct
+ {
+ ALuint Identifier;
+ ALuint Type;
+ ALuint Start;
+ ALuint End;
+ ALuint Fraction;
+ ALuint Count;
+ } Loop[1];
+} WAVSmplHdr_Struct;
+
+typedef struct /* WAV Chunk-header */
+{
+ ALubyte Id[4];
+ ALuint Size;
+} WAVChunkHdr_Struct;
+
+static void *SND_loadFileIntoMemory(const char *filename, int *len_r)
+{
+ FILE *fp= fopen(filename, "rb");
+ void *data;
+
+ if (!fp) {
+ *len_r= -1;
+ return NULL;
+ }
+
+ fseek(fp, 0L, SEEK_END);
+ *len_r= ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ data= malloc(*len_r);
+ if (!data) {
+ *len_r= -1;
+ return NULL;
+ }
+
+ if (fread(data, *len_r, 1, fp)!=1) {
+ *len_r= -1;
+ free(data);
+ return NULL;
+ }
+
+ return data;
+}
+
+#define TEST_SWITCH_INT(a) if(big_endian) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+ s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+
+#define TEST_SWITCH_SHORT(a) if(big_endian) { \
+ char s_i, *p_i; \
+ p_i= (char *)&(a); \
+ s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
+
+static int stream_read(void *out, ALbyte **stream, ALsizei size, ALsizei *memsize)
+{
+ if(size <= *memsize) {
+ memcpy(out, *stream, size);
+ return 1;
+ }
+ else {
+ memset(out, 0, size);
+ return 0;
+ }
+}
+
+static int stream_skip(ALbyte **stream, ALsizei size, ALsizei *memsize)
+{
+ if(size <= *memsize) {
+ *stream += size;
+ *memsize -= size;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+ALvoid SND_alutLoadWAVMemory(ALbyte *memory,ALsizei memsize,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop)
+{
+ WAVChunkHdr_Struct ChunkHdr;
+ WAVFmtExHdr_Struct FmtExHdr;
+ WAVFileHdr_Struct FileHdr;
+ WAVSmplHdr_Struct SmplHdr;
+ WAVFmtHdr_Struct FmtHdr;
+ ALbyte *Stream= memory;
+ int test_endian= 1;
+ int big_endian= !((char*)&test_endian)[0];
+
+ *format=AL_FORMAT_MONO16;
+ *data=NULL;
+ *size=0;
+ *freq=22050;
+ *loop=AL_FALSE;
+
+ if(!Stream)
+ return;
+
+ stream_read(&FileHdr,&Stream,sizeof(WAVFileHdr_Struct),&memsize);
+ stream_skip(&Stream,sizeof(WAVFileHdr_Struct),&memsize);
+
+ TEST_SWITCH_INT(FileHdr.Size);
+ FileHdr.Size=((FileHdr.Size+1)&~1)-4;
+
+ while((FileHdr.Size!=0) && stream_read(&ChunkHdr,&Stream,sizeof(WAVChunkHdr_Struct),&memsize))
+ {
+ TEST_SWITCH_INT(ChunkHdr.Size);
+ stream_skip(&Stream,sizeof(WAVChunkHdr_Struct),&memsize);
+
+ if (!memcmp(ChunkHdr.Id,"fmt ",4))
+ {
+ stream_read(&FmtHdr,&Stream,sizeof(WAVFmtHdr_Struct),&memsize);
+
+ TEST_SWITCH_SHORT(FmtHdr.Format);
+ TEST_SWITCH_SHORT(FmtHdr.Channels);
+ TEST_SWITCH_INT(FmtHdr.SamplesPerSec);
+ TEST_SWITCH_INT(FmtHdr.BytesPerSec);
+ TEST_SWITCH_SHORT(FmtHdr.BlockAlign);
+ TEST_SWITCH_SHORT(FmtHdr.BitsPerSample);
+
+ if (FmtHdr.Format==0x0001)
+ {
+ *format=(FmtHdr.Channels==1?
+ (FmtHdr.BitsPerSample==8?AL_FORMAT_MONO8:AL_FORMAT_MONO16):
+ (FmtHdr.BitsPerSample==8?AL_FORMAT_STEREO8:AL_FORMAT_STEREO16));
+ *freq=FmtHdr.SamplesPerSec;
+ }
+ else
+ {
+ stream_read(&FmtExHdr,&Stream,sizeof(WAVFmtExHdr_Struct),&memsize);
+ TEST_SWITCH_SHORT(FmtExHdr.Size);
+ TEST_SWITCH_SHORT(FmtExHdr.SamplesPerBlock);
+ }
+ }
+ else if (!memcmp(ChunkHdr.Id,"data",4))
+ {
+ if (FmtHdr.Format==0x0001)
+ {
+ if((ALsizei)ChunkHdr.Size <= memsize)
+ {
+ *size=ChunkHdr.Size;
+ *data=malloc(ChunkHdr.Size+31);
+
+ if (*data) {
+ stream_read(*data,&Stream,ChunkHdr.Size,&memsize);
+ memset(((char *)*data)+ChunkHdr.Size,0,31);
+
+ if(FmtHdr.BitsPerSample == 16 && big_endian) {
+ int a, len= *size/2;
+ short *samples= (short*)*data;
+
+ for(a=0; a<len; a++) {
+ TEST_SWITCH_SHORT(samples[a])
+ }
+ }
+ }
+ }
+ }
+ else if (FmtHdr.Format==0x0011)
+ {
+ //IMA ADPCM
+ }
+ else if (FmtHdr.Format==0x0055)
+ {
+ //MP3 WAVE
+ }
+ }
+ else if (!memcmp(ChunkHdr.Id,"smpl",4))
+ {
+ stream_read(&SmplHdr,&Stream,sizeof(WAVSmplHdr_Struct),&memsize);
+
+ TEST_SWITCH_INT(SmplHdr.Manufacturer);
+ TEST_SWITCH_INT(SmplHdr.Product);
+ TEST_SWITCH_INT(SmplHdr.SamplePeriod);
+ TEST_SWITCH_INT(SmplHdr.Note);
+ TEST_SWITCH_INT(SmplHdr.FineTune);
+ TEST_SWITCH_INT(SmplHdr.SMPTEFormat);
+ TEST_SWITCH_INT(SmplHdr.SMPTEOffest);
+ TEST_SWITCH_INT(SmplHdr.Loops);
+ TEST_SWITCH_INT(SmplHdr.SamplerData);
+
+ *loop = (SmplHdr.Loops ? AL_TRUE : AL_FALSE);
+ }
+
+ if(!stream_skip(&Stream, ChunkHdr.Size + (ChunkHdr.Size&1), &memsize))
+ break;
+
+ FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8);
+ }
+}
+
+ALvoid SND_alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
+{
+ if (data)
+ free(data);
+}
+
+/************************ Device Implementation ****************************/
+
+SND_OpenALDevice::SND_OpenALDevice()
+ : SND_AudioDevice(),
+ m_context(NULL),
+ m_device(NULL)
+{
+ /* Removed the functionality for checking if noaudio was provided on */
+ /* the commandline. */
+ m_audio = true;
+ m_context = NULL;
+ m_buffersinitialized = false;
+ m_sourcesinitialized = false;
+
+ // let's check if we can get openal to initialize...
+ if (m_audio)
+ {
+ m_audio = false;
+
+ ALCdevice *dev = alcOpenDevice(NULL);
+ if (dev) {
+ m_context = alcCreateContext(dev, NULL);
+
+ if (m_context) {
+#ifdef AL_VERSION_1_1
+ alcMakeContextCurrent((ALCcontext*)m_context);
+#else
+ alcMakeContextCurrent(m_context);
+#endif
+ m_audio = true;
+ m_device = dev;
+#ifdef __linux__
+ /*
+ * SIGHUP Hack:
+ *
+ * On Linux, alcDestroyContext generates a SIGHUP (Hangup) when killing the OpenAL
+ * mixer thread, which kills Blender.
+ *
+ * So we set the signal to ignore....
+ *
+ * TODO: check if this applies to other platforms.
+ *
+ */
+ signal(SIGHUP, SIG_IGN);
+#endif
+ }
+ }
+
+ }
+
+ // then try to generate some buffers
+ if (m_audio)
+ {
+ // let openal generate its buffers
+ alGenBuffers(NUM_BUFFERS, m_buffers);
+ m_buffersinitialized = true;
+
+ for (int i = 0; i < NUM_BUFFERS; i++)
+ {
+ if (!alIsBuffer(m_buffers[i]))
+ {
+ //printf("\n\n WARNING: OpenAL returned with an error. Continuing without audio.\n\n");
+ m_audio = false;
+ break;
+ }
+ }
+ }
+
+ // next: the sources
+ if (m_audio)
+ {
+#ifdef __APPLE__
+ ALenum alc_error = ALC_NO_ERROR; // openal_2.12
+#else
+ ALenum alc_error = alcGetError(NULL); // openal_2.14+
+#endif
+
+ // let openal generate its sources
+ if (alc_error == ALC_NO_ERROR)
+ {
+ int i;
+
+ for (i=0;i<NUM_SOURCES;i++)
+ m_sources[i] = 0;
+ alGenSources(NUM_SOURCES, m_sources);
+ m_sourcesinitialized = true;
+ }
+ }
+
+ // let's get us a wavecache
+ if (m_audio)
+ {
+ m_wavecache = new SND_WaveCache();
+ }
+#ifndef __APPLE__
+ m_cdrom = new SND_SDLCDDevice();
+#endif
+}
+
+void SND_OpenALDevice::UseCD(void) const
+{
+ // we use SDL for CD, so we create the system
+ SND_CDObject::CreateSystem();
+
+}
+
+void SND_OpenALDevice::MakeCurrent() const
+{
+}
+
+
+
+SND_OpenALDevice::~SND_OpenALDevice()
+{
+ MakeCurrent();
+
+ if (m_sourcesinitialized)
+ {
+ for (int i = 0; i < NUM_SOURCES; i++)
+ alSourceStop(m_sources[i]);
+
+ alDeleteSources(NUM_SOURCES, m_sources);
+ m_sourcesinitialized = false;
+ }
+
+ if (m_buffersinitialized)
+ {
+ alDeleteBuffers(NUM_BUFFERS, m_buffers);
+ m_buffersinitialized = false;
+ }
+
+ if (m_context) {
+ MakeCurrent();
+#ifdef AL_VERSION_1_1
+ alcDestroyContext((ALCcontext*)m_context);
+#else
+ alcDestroyContext(m_context);
+#endif
+ m_context = NULL;
+ }
+
+#ifdef __linux__
+ // restore the signal state above.
+ signal(SIGHUP, SIG_DFL);
+#endif
+ // let's see if we used the cd. if not, just leave it alone
+ SND_CDObject* pCD = SND_CDObject::Instance();
+
+ if (pCD)
+ {
+ this->StopCD();
+ SND_CDObject::DisposeSystem();
+ }
+#ifndef __APPLE__
+ if (m_cdrom)
+ delete m_cdrom;
+#endif
+ if (m_device)
+ alcCloseDevice((ALCdevice*) m_device);
+}
+
+
+SND_WaveSlot* SND_OpenALDevice::LoadSample(const STR_String& name,
+ void* memlocation,
+ int size)
+{
+ SND_WaveSlot* waveslot = NULL;
+ STR_String samplename = name;
+
+ if (m_audio)
+ {
+ /* create the waveslot */
+ waveslot = m_wavecache->GetWaveSlot(samplename);
+
+ /* do we support this sample? */
+ if (SND_IsSampleValid(name, memlocation))
+ {
+ if (waveslot)
+ {
+ bool freemem = false;
+ int buffer = waveslot->GetBuffer();
+ void* data = NULL;
+ char loop = 'a';
+ int sampleformat, bitrate, numberofchannels;
+ ALenum al_error = alGetError();
+ ALsizei samplerate, numberofsamples; // openal_2.14+
+
+ /* Give them some safe defaults just incase */
+ bitrate = numberofchannels = 0;
+
+ if (!(size && memlocation)) {
+ memlocation = SND_loadFileIntoMemory(samplename.Ptr(), &size);
+ freemem = true;
+ }
+
+ /* load the sample from memory? */
+ if (size && memlocation)
+ {
+ waveslot->SetFileSize(size);
+
+ /* what was (our) buffer? */
+ int buffer = waveslot->GetBuffer();
+
+ /* get some info out of the sample */
+ SND_GetSampleInfo((signed char*)memlocation, waveslot);
+ numberofchannels = SND_GetNumberOfChannels(memlocation);
+ bitrate = SND_GetBitRate(memlocation);
+
+ /* load the sample into openal */
+ SND_alutLoadWAVMemory((ALbyte*)memlocation, size, &sampleformat, &data, &numberofsamples, &samplerate, &loop);
+ /* put it in the buffer */
+ alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate);
+ }
+
+ if(freemem)
+ free(memlocation);
+
+ /* fill the waveslot with info */
+ al_error = alGetError();
+ if (al_error == AL_NO_ERROR && m_buffers[buffer])
+ {
+ waveslot->SetData(data);
+ waveslot->SetSampleFormat(sampleformat);
+ waveslot->SetNumberOfChannels(numberofchannels);
+ waveslot->SetSampleRate(samplerate);
+ waveslot->SetBitRate(bitrate);
+ waveslot->SetNumberOfSamples(numberofsamples);
+
+ /* if the loading succeeded, mark the waveslot */
+ waveslot->SetLoaded(true);
+ }
+ else
+ {
+ /* or when it failed, free the waveslot */
+ m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
+ waveslot = NULL;
+ }
+
+ /* and free the original stuff (copy was made in openal) */
+ SND_alutUnloadWAV(sampleformat, data, numberofsamples, samplerate);
+ }
+ }
+ else
+ {
+ /* sample not supported, remove waveslot */
+ m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
+ waveslot = NULL;
+ }
+ }
+ return waveslot;
+}
+
+
+
+// listener's and general stuff //////////////////////////////////////////////////////
+
+
+
+/* sets the global dopplervelocity */
+void SND_OpenALDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const
+{
+ alDopplerVelocity ((float)dopplervelocity);
+}
+
+
+
+/* sets the global dopplerfactor */
+void SND_OpenALDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const
+{
+ alDopplerFactor ((float)dopplerfactor);
+}
+
+
+
+/* sets the global rolloff factor */
+void SND_OpenALDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const
+{
+ // not implemented in openal
+}
+
+
+
+void SND_OpenALDevice::NextFrame() const
+{
+ // CD
+#ifndef __APPLE__
+ m_cdrom->NextFrame();
+#endif
+ // not needed by openal
+}
+
+
+
+// set the gain for the listener
+void SND_OpenALDevice::SetListenerGain(float gain) const
+{
+ alListenerf (AL_GAIN, gain);
+}
+
+
+
+void SND_OpenALDevice::InitListener()
+{
+ // initialize the listener with these values that won't change
+ // (as long as we can have only one listener)
+ // now we can superimpose all listeners on each other (for they
+ // have the same settings)
+ float lispos[3] = {0,0,0};
+ float lisvel[3] = {0,0,0};
+ float lisori[6] = {0,0,1,0,-1,0};
+
+ alListenerfv(AL_POSITION, lispos);
+ alListenerfv(AL_VELOCITY, lisvel);
+ alListenerfv(AL_ORIENTATION, lisori);
+}
+
+
+
+// source playstate stuff ////////////////////////////////////////////////////////////
+
+
+
+/* sets the buffer */
+void SND_OpenALDevice::SetObjectBuffer(int id, unsigned int buffer)
+{
+ alSourcei (m_sources[id], AL_BUFFER, m_buffers[buffer]);
+}
+
+
+
+// check if the sound's still playing
+int SND_OpenALDevice::GetPlayState(int id)
+{
+ int alstate = 0;
+ int result = 0;
+
+#ifdef __APPLE__
+ alGetSourcei(m_sources[id], AL_SOURCE_STATE, &alstate);
+#else
+ alGetSourceiv(m_sources[id], AL_SOURCE_STATE, &alstate);
+#endif
+
+ switch(alstate)
+ {
+ case AL_INITIAL:
+ {
+ result = SND_INITIAL;
+ break;
+ }
+ case AL_PLAYING:
+ {
+ result = SND_PLAYING;
+ break;
+ }
+ case AL_PAUSED:
+ {
+ result = SND_PAUSED;
+ break;
+ }
+ case AL_STOPPED:
+ {
+ result = SND_STOPPED;
+ break;
+ }
+ default:
+ result = SND_UNKNOWN;
+ }
+
+ return result;
+}
+
+
+
+// make the source play
+void SND_OpenALDevice::PlayObject(int id)
+{
+ alSourcePlay(m_sources[id]);
+}
+
+
+
+// make the source stop
+void SND_OpenALDevice::StopObject(int id) const
+{
+ float obpos[3] = {0,0,0};
+ float obvel[3] = {0,0,0};
+
+ alSourcefv(m_sources[id], AL_POSITION, obpos);
+ alSourcefv(m_sources[id], AL_VELOCITY, obvel);
+
+ alSourcef(m_sources[id], AL_GAIN, 1.0);
+ alSourcef(m_sources[id], AL_PITCH, 1.0);
+ alSourcei(m_sources[id], AL_LOOPING, AL_FALSE);
+ alSourceStop(m_sources[id]);
+}
+
+
+
+// stop all sources
+void SND_OpenALDevice::StopAllObjects()
+{
+ alSourceStopv(NUM_SOURCES, m_sources);
+}
+
+
+
+// pause the source
+void SND_OpenALDevice::PauseObject(int id) const
+{
+ alSourcePause(m_sources[id]);
+}
+
+
+
+// source properties stuff ////////////////////////////////////////////////////////////
+
+
+
+// give openal the object's pitch
+void SND_OpenALDevice::SetObjectPitch(int id, MT_Scalar pitch) const
+{
+ alSourcef (m_sources[id], AL_PITCH, (float)pitch);
+}
+
+
+
+// give openal the object's gain
+void SND_OpenALDevice::SetObjectGain(int id, MT_Scalar gain) const
+{
+ alSourcef (m_sources[id], AL_GAIN, (float)gain);
+}
+
+
+
+// give openal the object's looping
+void SND_OpenALDevice::SetObjectLoop(int id, unsigned int loopmode) const
+{
+ if (loopmode == SND_LOOP_OFF)
+ {
+ //printf("%d - ", id);
+ alSourcei (m_sources[id], AL_LOOPING, AL_FALSE);
+ }
+ else
+ alSourcei (m_sources[id], AL_LOOPING, AL_TRUE);
+}
+
+void SND_OpenALDevice::SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const
+{
+
+
+}
+
+
+void SND_OpenALDevice::SetObjectMinGain(int id, MT_Scalar mingain) const
+{
+ alSourcef (m_sources[id], AL_MIN_GAIN, (float)mingain);
+}
+
+
+
+void SND_OpenALDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const
+{
+ alSourcef (m_sources[id], AL_MAX_GAIN, (float)maxgain);
+}
+
+
+
+void SND_OpenALDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const
+{
+ alSourcef (m_sources[id], AL_ROLLOFF_FACTOR, (float)rollofffactor);
+}
+
+
+
+void SND_OpenALDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const
+{
+ alSourcef (m_sources[id], AL_REFERENCE_DISTANCE, (float)referencedistance);
+}
+
+
+
+// give openal the object's position
+void SND_OpenALDevice::ObjectIs2D(int id) const
+{
+ float obpos[3] = {0,0,0};
+ float obvel[3] = {0,0,0};
+
+ alSourcefv(m_sources[id], AL_POSITION, obpos);
+ alSourcefv(m_sources[id], AL_VELOCITY, obvel);
+}
+
+
+
+void SND_OpenALDevice::SetObjectTransform(int id,
+ const MT_Vector3& position,
+ const MT_Vector3& velocity,
+ const MT_Matrix3x3& orientation,
+ const MT_Vector3& lisposition,
+ const MT_Scalar& rollofffactor) const
+{
+ float obpos[3];
+ float obvel[3];
+
+ obpos[0] = (float)position[0] * (float)rollofffactor; //x (l/r)
+ obpos[1] = (float)position[1] * (float)rollofffactor;
+ obpos[2] = (float)position[2] * (float)rollofffactor;
+
+ alSourcefv(m_sources[id], AL_POSITION, obpos);
+
+ velocity.getValue(obvel);
+ alSourcefv(m_sources[id], AL_VELOCITY, obvel);
+}
+
+void SND_OpenALDevice::PlayCD(int track) const
+{
+#ifndef __APPLE__
+ m_cdrom->PlayCD(track);
+#endif
+}
+
+
+void SND_OpenALDevice::PauseCD(bool pause) const
+{
+#ifndef __APPLE__
+ m_cdrom->PauseCD(pause);
+#endif
+}
+
+void SND_OpenALDevice::StopCD() const
+{
+#ifndef __APPLE__
+ SND_CDObject* pCD = SND_CDObject::Instance();
+
+ if (pCD && pCD->GetUsed())
+ {
+ m_cdrom->StopCD();
+ }
+#endif
+}
+
+void SND_OpenALDevice::SetCDPlaymode(int playmode) const
+{
+#ifndef __APPLE__
+ m_cdrom->SetCDPlaymode(playmode);
+#endif
+}
+
+void SND_OpenALDevice::SetCDGain(MT_Scalar gain) const
+{
+#ifndef __APPLE__
+ m_cdrom->SetCDGain(gain);
+#endif
+}
diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.h b/intern/SoundSystem/openal/SND_OpenALDevice.h
new file mode 100644
index 00000000000..a7b97cc314f
--- /dev/null
+++ b/intern/SoundSystem/openal/SND_OpenALDevice.h
@@ -0,0 +1,107 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_OPENALDEVICE
+#define SND_OPENALDEVICE
+
+#include "SND_AudioDevice.h"
+#include "SoundDefines.h"
+
+struct SDL_CD;
+
+class SND_OpenALDevice : public SND_AudioDevice
+{
+public:
+ SND_OpenALDevice();
+ virtual ~SND_OpenALDevice();
+
+ SND_WaveSlot* LoadSample(const STR_String& samplename,
+ void* memlocation,
+ int size);
+
+ void InitListener();
+ void SetListenerGain(float gain) const;
+ void SetDopplerVelocity(MT_Scalar dopplervelocity) const;
+ void SetDopplerFactor(MT_Scalar dopplerfactor) const;
+ void SetListenerRollOffFactor(MT_Scalar rollofffactor) const;
+
+ void MakeCurrent() const;
+
+ void NextFrame() const;
+ void UseCD() const;
+
+ void SetObjectBuffer(int id, unsigned int buffer);
+
+ int GetPlayState(int id);
+ void PlayObject(int id);
+ void StopObject(int id) const;
+ void StopAllObjects();
+ void PauseObject(int id) const;
+
+ void SetObjectLoop(int id, unsigned int loopmode) const;
+ void SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const;
+ void SetObjectPitch(int id, MT_Scalar pitch) const;
+ void SetObjectGain(int id, MT_Scalar gain) const;
+ void SetObjectMinGain(int id, MT_Scalar mingain) const;
+ void SetObjectMaxGain(int id, MT_Scalar maxgain) const;
+ void SetObjectRollOffFactor(int id, MT_Scalar rolloff) const;
+ void SetObjectReferenceDistance(int id, MT_Scalar distance) const;
+
+ void SetObjectTransform(int id,
+ const MT_Vector3& position,
+ const MT_Vector3& velocity,
+ const MT_Matrix3x3& orientation,
+ const MT_Vector3& lisposition,
+ const MT_Scalar& rollofffactor) const;
+ void ObjectIs2D(int id) const;
+
+ void PlayCD(int track) const;
+ void PauseCD(bool pause) const;
+ void StopCD() const;
+ void SetCDPlaymode(int playmode) const;
+ void SetCDGain(MT_Scalar gain) const;
+
+ void StartUsingDSP() {};
+ float* GetSpectrum() { return NULL; }
+ void StopUsingDSP() {};
+
+private:
+ void* m_context;
+ void* m_device;
+
+ unsigned int m_buffers[NUM_BUFFERS];
+ unsigned int m_sources[NUM_SOURCES];
+ bool m_buffersinitialized;
+ bool m_sourcesinitialized;
+#ifndef __APPLE__
+ class SND_SDLCDDevice* m_cdrom;
+#endif
+};
+
+#endif //SND_OPENALDEVICE
+
diff --git a/intern/SoundSystem/openal/pthread_cancel.cpp b/intern/SoundSystem/openal/pthread_cancel.cpp
new file mode 100644
index 00000000000..bb36d1dd136
--- /dev/null
+++ b/intern/SoundSystem/openal/pthread_cancel.cpp
@@ -0,0 +1,67 @@
+/* $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 *****
+ * FreeBSD 3.4 does not yet have pthread_cancel (3.5 and above do)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef __FreeBSD__
+
+#include <osreldate.h>
+
+#if (__FreeBSD_version < 350000)
+#include <pthread.h>
+
+#define FD_READ 0x1
+#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
+#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
+
+int pthread_cancel(pthread_t pthread) {
+ pthread_exit(NULL);
+ return 0;
+}
+
+long fpathconf(int fd, int name)
+{
+ long ret;
+
+ if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
+ ret = _thread_sys_fpathconf(fd, name);
+ _FD_UNLOCK(fd, FD_READ);
+ }
+ return ret;
+}
+
+#endif
+
+int pthread_atfork(void *a, void *b, void *c) {
+ return 0;
+}
+
+#endif
diff --git a/intern/SoundSystem/sdl/Makefile b/intern/SoundSystem/sdl/Makefile
new file mode 100644
index 00000000000..669d7110797
--- /dev/null
+++ b/intern/SoundSystem/sdl/Makefile
@@ -0,0 +1,43 @@
+#
+# $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 = SDLSoundSystem
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += $(NAN_SDLCFLAGS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/intern/SoundSystem/sdl/SND_SDLCDDevice.cpp b/intern/SoundSystem/sdl/SND_SDLCDDevice.cpp
new file mode 100644
index 00000000000..5054c39e8a1
--- /dev/null
+++ b/intern/SoundSystem/sdl/SND_SDLCDDevice.cpp
@@ -0,0 +1,171 @@
+/*
+ * $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 *****
+ * SND_SDLCDDevice
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "MT_Scalar.h"
+
+#include "SND_SDLCDDevice.h"
+#include "SoundDefines.h"
+
+#ifndef DISABLE_SDL
+#include <SDL.h>
+#else
+#include <stdio.h>
+#endif
+
+SND_SDLCDDevice::SND_SDLCDDevice() :
+ m_cdrom(NULL),
+ m_cdplaying(false),
+ m_cdtrack(0),
+ m_cdplaymode(SND_CD_TRACK),
+ m_frame(0)
+{
+ init();
+}
+
+void SND_SDLCDDevice::init()
+{
+#ifdef DISABLE_SDL
+ fprintf(stderr, "Blender compiled without SDL, no CDROM support\n");
+ return;
+#else
+ if (SDL_InitSubSystem(SDL_INIT_CDROM))
+ {
+ fprintf(stderr, "Error initializing CDROM\n");
+ return;
+ }
+
+ /* Check for CD drives */
+ if(!SDL_CDNumDrives())
+ {
+ /* None found */
+ fprintf(stderr, "No CDROM devices available\n");
+ return;
+ }
+
+ /* Open the default drive */
+ m_cdrom = SDL_CDOpen(0);
+
+ /* Did if open? Check if cdrom is NULL */
+ if(!m_cdrom)
+ {
+ fprintf(stderr, "Couldn't open drive: %s\n", SDL_GetError());
+ return;
+ }
+#endif
+}
+
+SND_SDLCDDevice::~SND_SDLCDDevice()
+{
+#ifndef DISABLE_SDL
+ StopCD();
+ SDL_CDClose(m_cdrom);
+#endif
+}
+
+void SND_SDLCDDevice::NextFrame()
+{
+#ifndef DISABLE_SDL
+ m_frame++;
+ m_frame &= 127;
+
+ if (!m_frame && m_cdrom && m_cdplaying && SDL_CDStatus(m_cdrom) == CD_STOPPED)
+ {
+ switch (m_cdplaymode)
+ {
+ case SND_CD_ALL:
+ if (m_cdtrack < m_cdrom->numtracks)
+ PlayCD(m_cdtrack + 1);
+ else
+ m_cdplaying = false;
+ break;
+ default:
+ case SND_CD_TRACK:
+ m_cdplaying = false;
+ break;
+ case SND_CD_TRACKLOOP:
+ PlayCD(m_cdtrack);
+ break;
+ }
+
+ }
+#endif
+}
+
+void SND_SDLCDDevice::PlayCD(int track)
+{
+#ifndef DISABLE_SDL
+ if ( m_cdrom && CD_INDRIVE(SDL_CDStatus(m_cdrom)) ) {
+ SDL_CDPlayTracks(m_cdrom, track-1, 0, track, 0);
+ m_cdplaying = true;
+ m_cdtrack = track;
+ }
+#endif
+}
+
+
+void SND_SDLCDDevice::PauseCD(bool pause)
+{
+#ifndef DISABLE_SDL
+ if (!m_cdrom)
+ return;
+
+ if (pause)
+ SDL_CDPause(m_cdrom);
+ else
+ SDL_CDResume(m_cdrom);
+#endif
+}
+
+void SND_SDLCDDevice::StopCD()
+{
+#ifndef DISABLE_SDL
+ if (m_cdrom)
+ SDL_CDStop(m_cdrom);
+ m_cdplaying = false;
+#endif
+}
+
+void SND_SDLCDDevice::SetCDPlaymode(int playmode)
+{
+ m_cdplaymode = playmode;
+}
+
+void SND_SDLCDDevice::SetCDGain(MT_Scalar gain)
+{
+
+}
diff --git a/intern/SoundSystem/sdl/SND_SDLCDDevice.h b/intern/SoundSystem/sdl/SND_SDLCDDevice.h
new file mode 100644
index 00000000000..96600d53630
--- /dev/null
+++ b/intern/SoundSystem/sdl/SND_SDLCDDevice.h
@@ -0,0 +1,58 @@
+/**
+ * $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 *****
+ */
+#ifndef SND_SDLCDDEVICE
+#define SND_SDLCDDEVICE
+
+struct SDL_CD;
+
+class SND_SDLCDDevice
+{
+public:
+ SND_SDLCDDevice();
+ ~SND_SDLCDDevice();
+
+ void NextFrame();
+
+ void PlayCD(int track);
+ void PauseCD(bool pause);
+ void StopCD();
+ void SetCDPlaymode(int playmode);
+ void SetCDGain(MT_Scalar gain);
+
+private:
+ void init();
+ /* CD Audio */
+ SDL_CD* m_cdrom;
+ bool m_cdplaying;
+ int m_cdtrack;
+ unsigned char m_cdplaymode;
+ unsigned char m_frame;
+};
+
+#endif
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/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
index 153ee401011..0ce5e08b4f6 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: GHOST_DisplayManagerCocoa.h 23603 2009-10-02 07:20:33Z damien78 $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
index f105928c9a3..5be49851bcb 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
@@ -1,168 +1,168 @@
-/**
- * $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): Maarten Gribnau 09/2001
- Damien Plisson 10/2009
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <Cocoa/Cocoa.h>
-
-#include "GHOST_DisplayManagerCocoa.h"
-#include "GHOST_Debug.h"
-
-// We do not support multiple monitors at the moment
-
-
-GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void)
-{
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8& numDisplays) const
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- numDisplays = (GHOST_TUns8) [[NSScreen screens] count];
-
- [pool drain];
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
-{
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getNumDisplaySettings(): only main display is supported");
-
- numSettings = (GHOST_TInt32)3; //Width, Height, BitsPerPixel
-
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
-{
- //Note that only current display setting is available
- NSScreen *askedDisplay;
-
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getDisplaySetting(): only main display is supported");
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- if (display == kMainDisplay) //Screen #0 may not be the main one
- askedDisplay = [NSScreen mainScreen];
- else
- askedDisplay = [[NSScreen screens] objectAtIndex:display];
-
- if(askedDisplay == nil) {
- [pool drain];
- return GHOST_kFailure;
- }
-
- NSRect frame = [askedDisplay visibleFrame];
- setting.xPixels = frame.size.width;
- setting.yPixels = frame.size.height;
-
- setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
-
- setting.frequency = 0; //No more CRT display...
-
-#ifdef GHOST_DEBUG
- printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
-#endif // GHOST_DEBUG
-
- [pool drain];
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
-{
- NSScreen *askedDisplay;
-
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported");
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- if (display == kMainDisplay) //Screen #0 may not be the main one
- askedDisplay = [NSScreen mainScreen];
- else
- askedDisplay = [[NSScreen screens] objectAtIndex:display];
-
- if(askedDisplay == nil) {
- [pool drain];
- return GHOST_kFailure;
- }
-
- NSRect frame = [askedDisplay visibleFrame];
- setting.xPixels = frame.size.width;
- setting.yPixels = frame.size.height;
-
- setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
-
- setting.frequency = 0; //No more CRT display...
-
-#ifdef GHOST_DEBUG
- printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
-#endif // GHOST_DEBUG
-
- [pool drain];
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
-{
- GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): only main display is supported");
-
-#ifdef GHOST_DEBUG
- printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): requested settings:\n");
- printf(" setting.xPixels=%d\n", setting.xPixels);
- printf(" setting.yPixels=%d\n", setting.yPixels);
- printf(" setting.bpp=%d\n", setting.bpp);
- printf(" setting.frequency=%d\n", setting.frequency);
-#endif // GHOST_DEBUG
-
- //Display configuration is no more available in 10.6
-
-/* CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate(
- m_displayIDs[display],
- (size_t)setting.bpp,
- (size_t)setting.xPixels,
- (size_t)setting.yPixels,
- (CGRefreshRate)setting.frequency,
- NULL);*/
-
-#ifdef GHOST_DEBUG
- printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): switching to:\n");
- printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth));
- printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight));
- printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel));
- printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate));
-#endif // GHOST_DEBUG
-
- //CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
-
- return /*err == CGDisplayNoErr ? GHOST_kSuccess :*/ GHOST_kFailure;
-}
+/**
+ * $Id: GHOST_DisplayManagerCocoa.mm 23603 2009-10-02 07:20:33Z damien78 $
+ * ***** 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): Maarten Gribnau 09/2001
+ Damien Plisson 10/2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <Cocoa/Cocoa.h>
+
+#include "GHOST_DisplayManagerCocoa.h"
+#include "GHOST_Debug.h"
+
+// We do not support multiple monitors at the moment
+
+
+GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void)
+{
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8& numDisplays) const
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ numDisplays = (GHOST_TUns8) [[NSScreen screens] count];
+
+ [pool drain];
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getNumDisplaySettings(): only main display is supported");
+
+ numSettings = (GHOST_TInt32)3; //Width, Height, BitsPerPixel
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
+{
+ //Note that only current display setting is available
+ NSScreen *askedDisplay;
+
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getDisplaySetting(): only main display is supported");
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (display == kMainDisplay) //Screen #0 may not be the main one
+ askedDisplay = [NSScreen mainScreen];
+ else
+ askedDisplay = [[NSScreen screens] objectAtIndex:display];
+
+ if(askedDisplay == nil) {
+ [pool drain];
+ return GHOST_kFailure;
+ }
+
+ NSRect frame = [askedDisplay visibleFrame];
+ setting.xPixels = frame.size.width;
+ setting.yPixels = frame.size.height;
+
+ setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
+
+ setting.frequency = 0; //No more CRT display...
+
+#ifdef GHOST_DEBUG
+ printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
+#endif // GHOST_DEBUG
+
+ [pool drain];
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
+{
+ NSScreen *askedDisplay;
+
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported");
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (display == kMainDisplay) //Screen #0 may not be the main one
+ askedDisplay = [NSScreen mainScreen];
+ else
+ askedDisplay = [[NSScreen screens] objectAtIndex:display];
+
+ if(askedDisplay == nil) {
+ [pool drain];
+ return GHOST_kFailure;
+ }
+
+ NSRect frame = [askedDisplay visibleFrame];
+ setting.xPixels = frame.size.width;
+ setting.yPixels = frame.size.height;
+
+ setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
+
+ setting.frequency = 0; //No more CRT display...
+
+#ifdef GHOST_DEBUG
+ printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
+#endif // GHOST_DEBUG
+
+ [pool drain];
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): only main display is supported");
+
+#ifdef GHOST_DEBUG
+ printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): requested settings:\n");
+ printf(" setting.xPixels=%d\n", setting.xPixels);
+ printf(" setting.yPixels=%d\n", setting.yPixels);
+ printf(" setting.bpp=%d\n", setting.bpp);
+ printf(" setting.frequency=%d\n", setting.frequency);
+#endif // GHOST_DEBUG
+
+ //Display configuration is no more available in 10.6
+
+/* CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate(
+ m_displayIDs[display],
+ (size_t)setting.bpp,
+ (size_t)setting.xPixels,
+ (size_t)setting.yPixels,
+ (CGRefreshRate)setting.frequency,
+ NULL);*/
+
+#ifdef GHOST_DEBUG
+ printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): switching to:\n");
+ printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth));
+ printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight));
+ printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel));
+ printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate));
+#endif // GHOST_DEBUG
+
+ //CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
+
+ return /*err == CGDisplayNoErr ? GHOST_kSuccess :*/ GHOST_kFailure;
+}
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index ee7f9d8ed37..002089e4185 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: GHOST_SystemCocoa.h 23737 2009-10-09 12:48:28Z damien78 $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 62f0c538e7e..b924adeebde 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1,1396 +1,1396 @@
-/**
- * $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): Maarten Gribnau 05/2001
- * Damien Plisson 09/2009
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#import <Cocoa/Cocoa.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-#include "GHOST_SystemCocoa.h"
-
-#include "GHOST_DisplayManagerCocoa.h"
-#include "GHOST_EventKey.h"
-#include "GHOST_EventButton.h"
-#include "GHOST_EventCursor.h"
-#include "GHOST_EventWheel.h"
-#include "GHOST_EventNDOF.h"
-
-#include "GHOST_TimerManager.h"
-#include "GHOST_TimerTask.h"
-#include "GHOST_WindowManager.h"
-#include "GHOST_WindowCocoa.h"
-#include "GHOST_NDOFManager.h"
-#include "AssertMacros.h"
-
-#pragma mark KeyMap, mouse converters
-
-
-/* Keycodes from Carbon include file */
-/*
- * Summary:
- * Virtual keycodes
- *
- * Discussion:
- * These constants are the virtual keycodes defined originally in
- * Inside Mac Volume V, pg. V-191. They identify physical keys on a
- * keyboard. Those constants with "ANSI" in the name are labeled
- * according to the key position on an ANSI-standard US keyboard.
- * For example, kVK_ANSI_A indicates the virtual keycode for the key
- * with the letter 'A' in the US keyboard layout. Other keyboard
- * layouts may have the 'A' key label on a different physical key;
- * in this case, pressing 'A' will generate a different virtual
- * keycode.
- */
-enum {
- kVK_ANSI_A = 0x00,
- kVK_ANSI_S = 0x01,
- kVK_ANSI_D = 0x02,
- kVK_ANSI_F = 0x03,
- kVK_ANSI_H = 0x04,
- kVK_ANSI_G = 0x05,
- kVK_ANSI_Z = 0x06,
- kVK_ANSI_X = 0x07,
- kVK_ANSI_C = 0x08,
- kVK_ANSI_V = 0x09,
- kVK_ANSI_B = 0x0B,
- kVK_ANSI_Q = 0x0C,
- kVK_ANSI_W = 0x0D,
- kVK_ANSI_E = 0x0E,
- kVK_ANSI_R = 0x0F,
- kVK_ANSI_Y = 0x10,
- kVK_ANSI_T = 0x11,
- kVK_ANSI_1 = 0x12,
- kVK_ANSI_2 = 0x13,
- kVK_ANSI_3 = 0x14,
- kVK_ANSI_4 = 0x15,
- kVK_ANSI_6 = 0x16,
- kVK_ANSI_5 = 0x17,
- kVK_ANSI_Equal = 0x18,
- kVK_ANSI_9 = 0x19,
- kVK_ANSI_7 = 0x1A,
- kVK_ANSI_Minus = 0x1B,
- kVK_ANSI_8 = 0x1C,
- kVK_ANSI_0 = 0x1D,
- kVK_ANSI_RightBracket = 0x1E,
- kVK_ANSI_O = 0x1F,
- kVK_ANSI_U = 0x20,
- kVK_ANSI_LeftBracket = 0x21,
- kVK_ANSI_I = 0x22,
- kVK_ANSI_P = 0x23,
- kVK_ANSI_L = 0x25,
- kVK_ANSI_J = 0x26,
- kVK_ANSI_Quote = 0x27,
- kVK_ANSI_K = 0x28,
- kVK_ANSI_Semicolon = 0x29,
- kVK_ANSI_Backslash = 0x2A,
- kVK_ANSI_Comma = 0x2B,
- kVK_ANSI_Slash = 0x2C,
- kVK_ANSI_N = 0x2D,
- kVK_ANSI_M = 0x2E,
- kVK_ANSI_Period = 0x2F,
- kVK_ANSI_Grave = 0x32,
- kVK_ANSI_KeypadDecimal = 0x41,
- kVK_ANSI_KeypadMultiply = 0x43,
- kVK_ANSI_KeypadPlus = 0x45,
- kVK_ANSI_KeypadClear = 0x47,
- kVK_ANSI_KeypadDivide = 0x4B,
- kVK_ANSI_KeypadEnter = 0x4C,
- kVK_ANSI_KeypadMinus = 0x4E,
- kVK_ANSI_KeypadEquals = 0x51,
- kVK_ANSI_Keypad0 = 0x52,
- kVK_ANSI_Keypad1 = 0x53,
- kVK_ANSI_Keypad2 = 0x54,
- kVK_ANSI_Keypad3 = 0x55,
- kVK_ANSI_Keypad4 = 0x56,
- kVK_ANSI_Keypad5 = 0x57,
- kVK_ANSI_Keypad6 = 0x58,
- kVK_ANSI_Keypad7 = 0x59,
- kVK_ANSI_Keypad8 = 0x5B,
- kVK_ANSI_Keypad9 = 0x5C
-};
-
-/* keycodes for keys that are independent of keyboard layout*/
-enum {
- kVK_Return = 0x24,
- kVK_Tab = 0x30,
- kVK_Space = 0x31,
- kVK_Delete = 0x33,
- kVK_Escape = 0x35,
- kVK_Command = 0x37,
- kVK_Shift = 0x38,
- kVK_CapsLock = 0x39,
- kVK_Option = 0x3A,
- kVK_Control = 0x3B,
- kVK_RightShift = 0x3C,
- kVK_RightOption = 0x3D,
- kVK_RightControl = 0x3E,
- kVK_Function = 0x3F,
- kVK_F17 = 0x40,
- kVK_VolumeUp = 0x48,
- kVK_VolumeDown = 0x49,
- kVK_Mute = 0x4A,
- kVK_F18 = 0x4F,
- kVK_F19 = 0x50,
- kVK_F20 = 0x5A,
- kVK_F5 = 0x60,
- kVK_F6 = 0x61,
- kVK_F7 = 0x62,
- kVK_F3 = 0x63,
- kVK_F8 = 0x64,
- kVK_F9 = 0x65,
- kVK_F11 = 0x67,
- kVK_F13 = 0x69,
- kVK_F16 = 0x6A,
- kVK_F14 = 0x6B,
- kVK_F10 = 0x6D,
- kVK_F12 = 0x6F,
- kVK_F15 = 0x71,
- kVK_Help = 0x72,
- kVK_Home = 0x73,
- kVK_PageUp = 0x74,
- kVK_ForwardDelete = 0x75,
- kVK_F4 = 0x76,
- kVK_End = 0x77,
- kVK_F2 = 0x78,
- kVK_PageDown = 0x79,
- kVK_F1 = 0x7A,
- kVK_LeftArrow = 0x7B,
- kVK_RightArrow = 0x7C,
- kVK_DownArrow = 0x7D,
- kVK_UpArrow = 0x7E
-};
-
-/* ISO keyboards only*/
-enum {
- kVK_ISO_Section = 0x0A
-};
-
-/* JIS keyboards only*/
-enum {
- kVK_JIS_Yen = 0x5D,
- kVK_JIS_Underscore = 0x5E,
- kVK_JIS_KeypadComma = 0x5F,
- kVK_JIS_Eisu = 0x66,
- kVK_JIS_Kana = 0x68
-};
-
-
-static GHOST_TButtonMask convertButton(int button)
-{
- switch (button) {
- case 0:
- return GHOST_kButtonMaskLeft;
- case 1:
- return GHOST_kButtonMaskRight;
- case 2:
- return GHOST_kButtonMaskMiddle;
- case 3:
- return GHOST_kButtonMaskButton4;
- case 4:
- return GHOST_kButtonMaskButton5;
- default:
- return GHOST_kButtonMaskLeft;
- }
-}
-
-/**
- * Converts Mac rawkey codes (same for Cocoa & Carbon)
- * into GHOST key codes
- * @param rawCode The raw physical key code
- * @param recvChar the character ignoring modifiers (except for shift)
- * @return Ghost key code
- */
-static GHOST_TKey convertKey(int rawCode, unichar recvChar)
-{
-
- //printf("\nrecvchar %c 0x%x",recvChar,recvChar);
- switch (rawCode) {
- /*Physical keycodes not used due to map changes in int'l keyboards
- case kVK_ANSI_A: return GHOST_kKeyA;
- case kVK_ANSI_B: return GHOST_kKeyB;
- case kVK_ANSI_C: return GHOST_kKeyC;
- case kVK_ANSI_D: return GHOST_kKeyD;
- case kVK_ANSI_E: return GHOST_kKeyE;
- case kVK_ANSI_F: return GHOST_kKeyF;
- case kVK_ANSI_G: return GHOST_kKeyG;
- case kVK_ANSI_H: return GHOST_kKeyH;
- case kVK_ANSI_I: return GHOST_kKeyI;
- case kVK_ANSI_J: return GHOST_kKeyJ;
- case kVK_ANSI_K: return GHOST_kKeyK;
- case kVK_ANSI_L: return GHOST_kKeyL;
- case kVK_ANSI_M: return GHOST_kKeyM;
- case kVK_ANSI_N: return GHOST_kKeyN;
- case kVK_ANSI_O: return GHOST_kKeyO;
- case kVK_ANSI_P: return GHOST_kKeyP;
- case kVK_ANSI_Q: return GHOST_kKeyQ;
- case kVK_ANSI_R: return GHOST_kKeyR;
- case kVK_ANSI_S: return GHOST_kKeyS;
- case kVK_ANSI_T: return GHOST_kKeyT;
- case kVK_ANSI_U: return GHOST_kKeyU;
- case kVK_ANSI_V: return GHOST_kKeyV;
- case kVK_ANSI_W: return GHOST_kKeyW;
- case kVK_ANSI_X: return GHOST_kKeyX;
- case kVK_ANSI_Y: return GHOST_kKeyY;
- case kVK_ANSI_Z: return GHOST_kKeyZ;*/
-
- /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/
- case kVK_ISO_Section: return GHOST_kKeyUnknown;
- case kVK_ANSI_1: return GHOST_kKey1;
- case kVK_ANSI_2: return GHOST_kKey2;
- case kVK_ANSI_3: return GHOST_kKey3;
- case kVK_ANSI_4: return GHOST_kKey4;
- case kVK_ANSI_5: return GHOST_kKey5;
- case kVK_ANSI_6: return GHOST_kKey6;
- case kVK_ANSI_7: return GHOST_kKey7;
- case kVK_ANSI_8: return GHOST_kKey8;
- case kVK_ANSI_9: return GHOST_kKey9;
- case kVK_ANSI_0: return GHOST_kKey0;
-
- case kVK_ANSI_Keypad0: return GHOST_kKeyNumpad0;
- case kVK_ANSI_Keypad1: return GHOST_kKeyNumpad1;
- case kVK_ANSI_Keypad2: return GHOST_kKeyNumpad2;
- case kVK_ANSI_Keypad3: return GHOST_kKeyNumpad3;
- case kVK_ANSI_Keypad4: return GHOST_kKeyNumpad4;
- case kVK_ANSI_Keypad5: return GHOST_kKeyNumpad5;
- case kVK_ANSI_Keypad6: return GHOST_kKeyNumpad6;
- case kVK_ANSI_Keypad7: return GHOST_kKeyNumpad7;
- case kVK_ANSI_Keypad8: return GHOST_kKeyNumpad8;
- case kVK_ANSI_Keypad9: return GHOST_kKeyNumpad9;
- case kVK_ANSI_KeypadDecimal: return GHOST_kKeyNumpadPeriod;
- case kVK_ANSI_KeypadEnter: return GHOST_kKeyNumpadEnter;
- case kVK_ANSI_KeypadPlus: return GHOST_kKeyNumpadPlus;
- case kVK_ANSI_KeypadMinus: return GHOST_kKeyNumpadMinus;
- case kVK_ANSI_KeypadMultiply: return GHOST_kKeyNumpadAsterisk;
- case kVK_ANSI_KeypadDivide: return GHOST_kKeyNumpadSlash;
- case kVK_ANSI_KeypadClear: return GHOST_kKeyUnknown;
-
- case kVK_F1: return GHOST_kKeyF1;
- case kVK_F2: return GHOST_kKeyF2;
- case kVK_F3: return GHOST_kKeyF3;
- case kVK_F4: return GHOST_kKeyF4;
- case kVK_F5: return GHOST_kKeyF5;
- case kVK_F6: return GHOST_kKeyF6;
- case kVK_F7: return GHOST_kKeyF7;
- case kVK_F8: return GHOST_kKeyF8;
- case kVK_F9: return GHOST_kKeyF9;
- case kVK_F10: return GHOST_kKeyF10;
- case kVK_F11: return GHOST_kKeyF11;
- case kVK_F12: return GHOST_kKeyF12;
- case kVK_F13: return GHOST_kKeyF13;
- case kVK_F14: return GHOST_kKeyF14;
- case kVK_F15: return GHOST_kKeyF15;
- case kVK_F16: return GHOST_kKeyF16;
- case kVK_F17: return GHOST_kKeyF17;
- case kVK_F18: return GHOST_kKeyF18;
- case kVK_F19: return GHOST_kKeyF19;
- case kVK_F20: return GHOST_kKeyF20;
-
- case kVK_UpArrow: return GHOST_kKeyUpArrow;
- case kVK_DownArrow: return GHOST_kKeyDownArrow;
- case kVK_LeftArrow: return GHOST_kKeyLeftArrow;
- case kVK_RightArrow: return GHOST_kKeyRightArrow;
-
- case kVK_Return: return GHOST_kKeyEnter;
- case kVK_Delete: return GHOST_kKeyBackSpace;
- case kVK_ForwardDelete: return GHOST_kKeyDelete;
- case kVK_Escape: return GHOST_kKeyEsc;
- case kVK_Tab: return GHOST_kKeyTab;
- case kVK_Space: return GHOST_kKeySpace;
-
- case kVK_Home: return GHOST_kKeyHome;
- case kVK_End: return GHOST_kKeyEnd;
- case kVK_PageUp: return GHOST_kKeyUpPage;
- case kVK_PageDown: return GHOST_kKeyDownPage;
-
- /*case kVK_ANSI_Minus: return GHOST_kKeyMinus;
- case kVK_ANSI_Equal: return GHOST_kKeyEqual;
- case kVK_ANSI_Comma: return GHOST_kKeyComma;
- case kVK_ANSI_Period: return GHOST_kKeyPeriod;
- case kVK_ANSI_Slash: return GHOST_kKeySlash;
- case kVK_ANSI_Semicolon: return GHOST_kKeySemicolon;
- case kVK_ANSI_Quote: return GHOST_kKeyQuote;
- case kVK_ANSI_Backslash: return GHOST_kKeyBackslash;
- case kVK_ANSI_LeftBracket: return GHOST_kKeyLeftBracket;
- case kVK_ANSI_RightBracket: return GHOST_kKeyRightBracket;
- case kVK_ANSI_Grave: return GHOST_kKeyAccentGrave;*/
-
- case kVK_VolumeUp:
- case kVK_VolumeDown:
- case kVK_Mute:
- return GHOST_kKeyUnknown;
-
- default:
- /*Then detect on character value for "remappable" keys in int'l keyboards*/
- if ((recvChar >= 'A') && (recvChar <= 'Z')) {
- return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
- } else if ((recvChar >= 'a') && (recvChar <= 'z')) {
- return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
- } else
- switch (recvChar) {
- case '-': return GHOST_kKeyMinus;
- case '=': return GHOST_kKeyEqual;
- case ',': return GHOST_kKeyComma;
- case '.': return GHOST_kKeyPeriod;
- case '/': return GHOST_kKeySlash;
- case ';': return GHOST_kKeySemicolon;
- case '\'': return GHOST_kKeyQuote;
- case '\\': return GHOST_kKeyBackslash;
- case '[': return GHOST_kKeyLeftBracket;
- case ']': return GHOST_kKeyRightBracket;
- case '`': return GHOST_kKeyAccentGrave;
- default:
- return GHOST_kKeyUnknown;
- }
- }
- return GHOST_kKeyUnknown;
-}
-
-/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes
- * as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html
- * I am not sure how international this works...
- * For cross-platform convention, we'll use the Latin ascii set instead.
- * As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html
- *
- */
-static unsigned char convertRomanToLatin(unsigned char ascii)
-{
-
- if(ascii<128) return ascii;
-
- switch(ascii) {
- case 128: return 142;
- case 129: return 143;
- case 130: return 128;
- case 131: return 201;
- case 132: return 209;
- case 133: return 214;
- case 134: return 220;
- case 135: return 225;
- case 136: return 224;
- case 137: return 226;
- case 138: return 228;
- case 139: return 227;
- case 140: return 229;
- case 141: return 231;
- case 142: return 233;
- case 143: return 232;
- case 144: return 234;
- case 145: return 235;
- case 146: return 237;
- case 147: return 236;
- case 148: return 238;
- case 149: return 239;
- case 150: return 241;
- case 151: return 243;
- case 152: return 242;
- case 153: return 244;
- case 154: return 246;
- case 155: return 245;
- case 156: return 250;
- case 157: return 249;
- case 158: return 251;
- case 159: return 252;
- case 160: return 0;
- case 161: return 176;
- case 162: return 162;
- case 163: return 163;
- case 164: return 167;
- case 165: return 183;
- case 166: return 182;
- case 167: return 223;
- case 168: return 174;
- case 169: return 169;
- case 170: return 174;
- case 171: return 180;
- case 172: return 168;
- case 173: return 0;
- case 174: return 198;
- case 175: return 216;
- case 176: return 0;
- case 177: return 177;
- case 178: return 0;
- case 179: return 0;
- case 180: return 165;
- case 181: return 181;
- case 182: return 0;
- case 183: return 0;
- case 184: return 215;
- case 185: return 0;
- case 186: return 0;
- case 187: return 170;
- case 188: return 186;
- case 189: return 0;
- case 190: return 230;
- case 191: return 248;
- case 192: return 191;
- case 193: return 161;
- case 194: return 172;
- case 195: return 0;
- case 196: return 0;
- case 197: return 0;
- case 198: return 0;
- case 199: return 171;
- case 200: return 187;
- case 201: return 201;
- case 202: return 0;
- case 203: return 192;
- case 204: return 195;
- case 205: return 213;
- case 206: return 0;
- case 207: return 0;
- case 208: return 0;
- case 209: return 0;
- case 210: return 0;
-
- case 214: return 247;
-
- case 229: return 194;
- case 230: return 202;
- case 231: return 193;
- case 232: return 203;
- case 233: return 200;
- case 234: return 205;
- case 235: return 206;
- case 236: return 207;
- case 237: return 204;
- case 238: return 211;
- case 239: return 212;
- case 240: return 0;
- case 241: return 210;
- case 242: return 218;
- case 243: return 219;
- case 244: return 217;
- case 245: return 0;
- case 246: return 0;
- case 247: return 0;
- case 248: return 0;
- case 249: return 0;
- case 250: return 0;
-
-
- default: return 0;
- }
-
-}
-
-#define FIRSTFILEBUFLG 512
-static bool g_hasFirstFile = false;
-static char g_firstFileBuf[512];
-
-//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
-extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
- if (g_hasFirstFile) {
- strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
- buf[FIRSTFILEBUFLG - 1] = '\0';
- return 1;
- } else {
- return 0;
- }
-}
-
-
-#pragma mark Cocoa objects
-
-/**
- * CocoaAppDelegate
- * ObjC object to capture applicationShouldTerminate, and send quit event
- **/
-@interface CocoaAppDelegate : NSObject {
- GHOST_SystemCocoa *systemCocoa;
-}
--(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa;
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-- (void)applicationWillTerminate:(NSNotification *)aNotification;
-@end
-
-@implementation CocoaAppDelegate : NSObject
--(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
-{
- systemCocoa = sysCocoa;
-}
-
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
-{
- //TODO: implement graceful termination through Cocoa mechanism to avoid session log off to be cancelled
- //Note that Cmd+Q is already handled by keyhandler
- if (systemCocoa->handleQuitRequest() == GHOST_kExitNow)
- return NSTerminateCancel;//NSTerminateNow;
- else
- return NSTerminateCancel;
-}
-
-// To avoid cancelling a log off process, we must use Cocoa termination process
-// And this function is the only chance to perform clean up
-// So WM_exit needs to be called directly, as the event loop will never run before termination
-- (void)applicationWillTerminate:(NSNotification *)aNotification
-{
- /*G.afbreek = 0; //Let Cocoa perform the termination at the end
- WM_exit(C);*/
-}
-@end
-
-
-
-#pragma mark initialization/finalization
-
-
-GHOST_SystemCocoa::GHOST_SystemCocoa()
-{
- m_modifierMask =0;
- m_pressedMouseButtons =0;
- m_displayManager = new GHOST_DisplayManagerCocoa ();
- GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n");
- m_displayManager->initialize();
-
- //NSEvent timeStamp is given in system uptime, state start date is boot time
- //FIXME : replace by Cocoa equivalent
- int mib[2];
- struct timeval boottime;
- size_t len;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_BOOTTIME;
- len = sizeof(struct timeval);
-
- sysctl(mib, 2, &boottime, &len, NULL, 0);
- m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
-
- m_ignoreWindowSizedMessages = false;
-}
-
-GHOST_SystemCocoa::~GHOST_SystemCocoa()
-{
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::init()
-{
-
- GHOST_TSuccess success = GHOST_System::init();
- if (success) {
- //ProcessSerialNumber psn;
-
- //Carbon stuff to move window & menu to foreground
- /*if (!GetCurrentProcess(&psn)) {
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- SetFrontProcess(&psn);
- }*/
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- if (NSApp == nil) {
- [NSApplication sharedApplication];
-
- if ([NSApp mainMenu] == nil) {
- NSMenu *mainMenubar = [[NSMenu alloc] init];
- NSMenuItem *menuItem;
- NSMenu *windowMenu;
- NSMenu *appMenu;
-
- //Create the application menu
- appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
-
- [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"];
- [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-
- menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
- [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
-
- [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
-
- menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"];
- [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-
- menuItem = [[NSMenuItem alloc] init];
- [menuItem setSubmenu:appMenu];
-
- [mainMenubar addItem:menuItem];
- [menuItem release];
- [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5
- [appMenu release];
-
- //Create the window menu
- windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-
- menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
- [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
-
- [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
-
- menuItem = [[NSMenuItem alloc] init];
- [menuItem setSubmenu:windowMenu];
-
- [mainMenubar addItem:menuItem];
- [menuItem release];
-
- [NSApp setMainMenu:mainMenubar];
- [NSApp setWindowsMenu:windowMenu];
- [windowMenu release];
- }
- [NSApp finishLaunching];
- }
- if ([NSApp delegate] == nil) {
- CocoaAppDelegate *appDelegate = [[CocoaAppDelegate alloc] init];
- [appDelegate setSystemCocoa:this];
- [NSApp setDelegate:appDelegate];
- }
-
- [pool drain];
- }
- return success;
-}
-
-
-#pragma mark window management
-
-GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
-{
- //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
- int mib[2];
- struct timeval boottime;
- size_t len;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_BOOTTIME;
- len = sizeof(struct timeval);
-
- sysctl(mib, 2, &boottime, &len, NULL, 0);
-
- return ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
-}
-
-
-GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
-{
- //Note that OS X supports monitor hot plug
- // We do not support multiple monitors at the moment
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- GHOST_TUns8 count = [[NSScreen screens] count];
-
- [pool drain];
- return count;
-}
-
-
-void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- //Get visible frame, that is frame excluding dock and top menu bar
- NSRect frame = [[NSScreen mainScreen] visibleFrame];
-
- //Returns max window contents (excluding title bar...)
- NSRect contentRect = [NSWindow contentRectForFrameRect:frame
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
-
- width = contentRect.size.width;
- height = contentRect.size.height;
-
- [pool drain];
-}
-
-
-GHOST_IWindow* GHOST_SystemCocoa::createWindow(
- const STR_String& title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
- GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- bool stereoVisual,
- const GHOST_TEmbedderWindowID parentWindow
-)
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- GHOST_IWindow* window = 0;
-
- //Get the available rect for including window contents
- NSRect frame = [[NSScreen mainScreen] visibleFrame];
- NSRect contentRect = [NSWindow contentRectForFrameRect:frame
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
-
- //Ensures window top left is inside this available rect
- left = left > contentRect.origin.x ? left : contentRect.origin.x;
- top = top > contentRect.origin.y ? top : contentRect.origin.y;
-
- window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type);
-
- if (window) {
- if (window->getValid()) {
- // Store the pointer to the window
- GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
- //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
-
- }
- else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
- delete window;
- window = 0;
- }
- }
- else {
- GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
- }
- [pool drain];
- return window;
-}
-
-GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
-{
- GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
-
- *window = currentWindow;
-
- return currentWindow->setState(GHOST_kWindowStateFullScreen);
-}
-
-GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
-{
- GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
-
- return currentWindow->setState(GHOST_kWindowStateNormal);
-}
-
-
-
-
-GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
-{
- NSPoint mouseLoc = [NSEvent mouseLocation];
-
- // Returns the mouse location in screen coordinates
- x = (GHOST_TInt32)mouseLoc.x;
- y = (GHOST_TInt32)mouseLoc.y;
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
-{
- float xf=(float)x, yf=(float)y;
-
- //Quartz Display Services uses the old coordinates (top left origin)
- yf = [[NSScreen mainScreen] frame].size.height -yf;
-
- //CGAssociateMouseAndMouseCursorPosition(false);
- CGWarpMouseCursorPosition(CGPointMake(xf, yf));
- //CGAssociateMouseAndMouseCursorPosition(true);
-
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
-{
- unsigned int modifiers = [[NSApp currentEvent] modifierFlags];
- //Direct query to modifierFlags can be used in 10.6
-
- keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & NSAlternateKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftShift, (modifiers & NSShiftKeyMask) ? true : false);
- keys.set(GHOST_kModifierKeyLeftControl, (modifiers & NSControlKeyMask) ? true : false);
-
- return GHOST_kSuccess;
-}
-
-GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
-{
- buttons.clear();
- buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
- buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);
- buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);
- buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);
- buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);
- return GHOST_kSuccess;
-}
-
-
-
-#pragma mark Event handlers
-
-/**
- * The event queue polling function
- */
-bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
-{
- bool anyProcessed = false;
- NSEvent *event;
-
- // SetMouseCoalescingEnabled(false, NULL);
- //TODO : implement timer ??
-
- /*do {
- GHOST_TimerManager* timerMgr = getTimerManager();
-
- if (waitForEvent) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
- double timeOut;
-
- if (next == GHOST_kFireTimeNever) {
- timeOut = kEventDurationForever;
- } else {
- timeOut = (double)(next - getMilliSeconds())/1000.0;
- if (timeOut < 0.0)
- timeOut = 0.0;
- }
-
- ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
- }
-
- if (timerMgr->fireTimers(getMilliSeconds())) {
- anyProcessed = true;
- }
-
- if (getFullScreen()) {
- // Check if the full-screen window is dirty
- GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
- if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) {
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
- anyProcessed = true;
- }
- }*/
-
- do {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantPast]
- inMode:NSDefaultRunLoopMode
- dequeue:YES];
- if (event==nil) {
- [pool drain];
- break;
- }
-
- anyProcessed = true;
-
- switch ([event type]) {
- case NSKeyDown:
- case NSKeyUp:
- case NSFlagsChanged:
- handleKeyEvent(event);
-
- /* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
- /* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
- [NSApp sendEvent:event];
- }*/
- break;
-
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSMouseMoved:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSScrollWheel:
- case NSOtherMouseDown:
- case NSOtherMouseUp:
- case NSOtherMouseDragged:
- handleMouseEvent(event);
- break;
-
- case NSTabletPoint:
- case NSTabletProximity:
- handleTabletEvent(event,[event type]);
- break;
-
- /* Trackpad features, will need OS X 10.6 for implementation
- case NSEventTypeGesture:
- case NSEventTypeMagnify:
- case NSEventTypeSwipe:
- case NSEventTypeRotate:
- case NSEventTypeBeginGesture:
- case NSEventTypeEndGesture:
- break; */
-
- /*Unused events
- NSMouseEntered = 8,
- NSMouseExited = 9,
- NSAppKitDefined = 13,
- NSSystemDefined = 14,
- NSApplicationDefined = 15,
- NSPeriodic = 16,
- NSCursorUpdate = 17,*/
-
- default:
- break;
- }
- //Resend event to NSApp to ensure Mac wide events are handled
- [NSApp sendEvent:event];
- [pool drain];
- } while (event!= nil);
- //} while (waitForEvent && !anyProcessed); Needed only for timer implementation
-
-
-
- return anyProcessed;
-}
-
-//Note: called from NSWindow delegate
-GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
-{
- if (!validWindow(window)) {
- return GHOST_kFailure;
- }
- switch(eventType)
- {
- case GHOST_kEventWindowClose:
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
- break;
- case GHOST_kEventWindowActivate:
- m_windowManager->setActiveWindow(window);
- window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
- break;
- case GHOST_kEventWindowDeactivate:
- m_windowManager->setWindowInactive(window);
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
- break;
- case GHOST_kEventWindowUpdate:
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
- break;
- case GHOST_kEventWindowSize:
- if (!m_ignoreWindowSizedMessages)
- {
- window->updateDrawingContext();
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
- }
- break;
- default:
- return GHOST_kFailure;
- break;
- }
- return GHOST_kSuccess;
-}
-
-GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
-{
- //Check open windows if some changes are not saved
- if (m_windowManager->getAnyModifiedState())
- {
- int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?",
- @"Cancel", @"Quit anyway", nil);
- if (shouldQuit == NSAlertAlternateReturn)
- {
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
- return GHOST_kExitNow;
- }
- }
- else {
- pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
- return GHOST_kExitNow;
- }
-
- return GHOST_kExitCancel;
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
-{
- NSEvent *event = (NSEvent *)eventPtr;
- GHOST_IWindow* window = m_windowManager->getActiveWindow();
- GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
-
- switch (eventType) {
- case NSTabletPoint:
- ct.Pressure = [event tangentialPressure];
- ct.Xtilt = [event tilt].x;
- ct.Ytilt = [event tilt].y;
- break;
-
- case NSTabletProximity:
- ct.Pressure = 0;
- ct.Xtilt = 0;
- ct.Ytilt = 0;
- if ([event isEnteringProximity])
- {
- //pointer is entering tablet area proximity
- switch ([event pointingDeviceType]) {
- case NSPenPointingDevice:
- ct.Active = GHOST_kTabletModeStylus;
- break;
- case NSEraserPointingDevice:
- ct.Active = GHOST_kTabletModeEraser;
- break;
- case NSCursorPointingDevice:
- case NSUnknownPointingDevice:
- default:
- ct.Active = GHOST_kTabletModeNone;
- break;
- }
- } else {
- // pointer is leaving - return to mouse
- ct.Active = GHOST_kTabletModeNone;
- }
- break;
-
- default:
- GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received");
- return GHOST_kFailure;
- break;
- }
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
-{
- NSEvent *event = (NSEvent *)eventPtr;
- GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
-
- if (!window) {
- return GHOST_kFailure;
- }
-
- switch ([event type])
- {
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
- //Handle tablet events combined with mouse events
- switch ([event subtype]) {
- case NX_SUBTYPE_TABLET_POINT:
- handleTabletEvent(eventPtr, NSTabletPoint);
- break;
- case NX_SUBTYPE_TABLET_PROXIMITY:
- handleTabletEvent(eventPtr, NSTabletProximity);
- break;
- default:
- //No tablet event included : do nothing
- break;
- }
- break;
-
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
- pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
- //Handle tablet events combined with mouse events
- switch ([event subtype]) {
- case NX_SUBTYPE_TABLET_POINT:
- handleTabletEvent(eventPtr, NSTabletPoint);
- break;
- case NX_SUBTYPE_TABLET_PROXIMITY:
- handleTabletEvent(eventPtr, NSTabletProximity);
- break;
- default:
- //No tablet event included : do nothing
- break;
- }
- break;
-
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- //Handle tablet events combined with mouse events
- switch ([event subtype]) {
- case NX_SUBTYPE_TABLET_POINT:
- handleTabletEvent(eventPtr, NSTabletPoint);
- break;
- case NX_SUBTYPE_TABLET_PROXIMITY:
- handleTabletEvent(eventPtr, NSTabletProximity);
- break;
- default:
- //No tablet event included : do nothing
- break;
- }
- case NSMouseMoved:
- {
- if(window->getCursorWarp()) {
- GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
-
- window->getCursorWarpPos(x_warp, y_warp);
-
- window->getCursorWarpAccum(x_accum, y_accum);
- x_accum += [event deltaX];
- y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
- window->setCursorWarpAccum(x_accum, y_accum);
-
- pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
- }
- else { //Normal cursor operation: send mouse position in window
- NSPoint mousePos = [event locationInWindow];
- pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
- window->setCursorWarpAccum(0, 0); //Mouse motion occured between two cursor warps, so we can reset the delta counter
- }
- break;
- }
-
- case NSScrollWheel:
- {
- GHOST_TInt32 delta;
-
- double deltaF = [event deltaY];
- if (deltaF == 0.0) break; //discard trackpad delta=0 events
-
- delta = deltaF > 0.0 ? 1 : -1;
- pushEvent(new GHOST_EventWheel([event timestamp], window, delta));
- }
- break;
-
- default:
- return GHOST_kFailure;
- break;
- }
-
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
-{
- NSEvent *event = (NSEvent *)eventPtr;
- GHOST_IWindow* window = m_windowManager->getActiveWindow();
- unsigned int modifiers;
- NSString *characters;
- GHOST_TKey keyCode;
- unsigned char ascii;
-
- /* Can happen, very rarely - seems to only be when command-H makes
- * the window go away and we still get an HKey up.
- */
- if (!window) {
- printf("\nW failure");
- return GHOST_kFailure;
- }
-
- switch ([event type]) {
- case NSKeyDown:
- case NSKeyUp:
- characters = [event characters];
- if ([characters length]) { //Check for dead keys
- keyCode = convertKey([event keyCode],
- [[event charactersIgnoringModifiers] characterAtIndex:0]);
- ascii= convertRomanToLatin((char)[characters characterAtIndex:0]);
- } else {
- keyCode = convertKey([event keyCode],0);
- ascii= 0;
- }
-
-
- if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
- break; //Cmd-Q is directly handled by Cocoa
-
- if ([event type] == NSKeyDown) {
- pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyDown, window, keyCode, ascii) );
- //printf("\nKey pressed keyCode=%u ascii=%i %c",keyCode,ascii,ascii);
- } else {
- pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyUp, window, keyCode, ascii) );
- }
- break;
-
- case NSFlagsChanged:
- modifiers = [event modifierFlags];
- if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
- pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
- }
- if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
- pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
- }
- if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
- pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
- }
- if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
- pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
- }
-
- m_modifierMask = modifiers;
- break;
-
- default:
- return GHOST_kFailure;
- break;
- }
-
- return GHOST_kSuccess;
-}
-
-
-
-#pragma mark Clipboard get/set
-
-GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
-{
- GHOST_TUns8 * temp_buff;
- size_t pastedTextSize;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-
- if (pasteBoard == nil) {
- [pool drain];
- return NULL;
- }
-
- NSArray *supportedTypes =
- [NSArray arrayWithObjects: @"public.utf8-plain-text", nil];
-
- NSString *bestType = [[NSPasteboard generalPasteboard]
- availableTypeFromArray:supportedTypes];
-
- if (bestType == nil) {
- [pool drain];
- return NULL;
- }
-
- NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"];
-
- if (textPasted == nil) {
- [pool drain];
- return NULL;
- }
-
- pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-
- temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
-
- if (temp_buff == NULL) {
- [pool drain];
- return NULL;
- }
-
- strncpy((char*)temp_buff, [textPasted UTF8String], pastedTextSize);
-
- temp_buff[pastedTextSize] = '\0';
-
- [pool drain];
-
- if(temp_buff) {
- return temp_buff;
- } else {
- return NULL;
- }
-}
-
-void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
-{
- NSString *textToCopy;
-
- if(selection) {return;} // for copying the selection, used on X11
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-
- if (pasteBoard == nil) {
- [pool drain];
- return;
- }
-
- NSArray *supportedTypes = [NSArray arrayWithObject:@"public.utf8-plain-text"];
-
- [pasteBoard declareTypes:supportedTypes owner:nil];
-
- textToCopy = [NSString stringWithUTF8String:buffer];
-
- [pasteBoard setString:textToCopy forType:@"public.utf8-plain-text"];
-
- [pool drain];
-}
-
-#pragma mark Carbon stuff to remove
-
-#ifdef WITH_CARBON
-
-
-OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
- //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-
- return noErr;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
- //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
- AEDescList docs;
- SInt32 ndocs;
- OSErr err;
-
- err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs);
- if (err != noErr) return err;
-
- err = AECountItems(&docs, &ndocs);
- if (err==noErr) {
- int i;
-
- for (i=0; i<ndocs; i++) {
- FSSpec fss;
- AEKeyword kwd;
- DescType actType;
- Size actSize;
-
- err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize);
- if (err!=noErr)
- break;
-
- if (i==0) {
- FSRef fsref;
-
- if (FSpMakeFSRef(&fss, &fsref)!=noErr)
- break;
- if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr)
- break;
-
- g_hasFirstFile = true;
- }
- }
- }
-
- AEDisposeDesc(&docs);
-
- return err;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
- //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-
- return noErr;
-}
-
-OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
-{
- GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
-
- sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) );
-
- return noErr;
-}
+/**
+ * $Id: GHOST_SystemCocoa.mm 23854 2009-10-15 08:27:31Z damien78 $
+ * ***** 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): Maarten Gribnau 05/2001
+ * Damien Plisson 09/2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include "GHOST_SystemCocoa.h"
+
+#include "GHOST_DisplayManagerCocoa.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_EventWheel.h"
+#include "GHOST_EventNDOF.h"
+
+#include "GHOST_TimerManager.h"
+#include "GHOST_TimerTask.h"
+#include "GHOST_WindowManager.h"
+#include "GHOST_WindowCocoa.h"
+#include "GHOST_NDOFManager.h"
+#include "AssertMacros.h"
+
+#pragma mark KeyMap, mouse converters
+
+
+/* Keycodes from Carbon include file */
+/*
+ * Summary:
+ * Virtual keycodes
+ *
+ * Discussion:
+ * These constants are the virtual keycodes defined originally in
+ * Inside Mac Volume V, pg. V-191. They identify physical keys on a
+ * keyboard. Those constants with "ANSI" in the name are labeled
+ * according to the key position on an ANSI-standard US keyboard.
+ * For example, kVK_ANSI_A indicates the virtual keycode for the key
+ * with the letter 'A' in the US keyboard layout. Other keyboard
+ * layouts may have the 'A' key label on a different physical key;
+ * in this case, pressing 'A' will generate a different virtual
+ * keycode.
+ */
+enum {
+ kVK_ANSI_A = 0x00,
+ kVK_ANSI_S = 0x01,
+ kVK_ANSI_D = 0x02,
+ kVK_ANSI_F = 0x03,
+ kVK_ANSI_H = 0x04,
+ kVK_ANSI_G = 0x05,
+ kVK_ANSI_Z = 0x06,
+ kVK_ANSI_X = 0x07,
+ kVK_ANSI_C = 0x08,
+ kVK_ANSI_V = 0x09,
+ kVK_ANSI_B = 0x0B,
+ kVK_ANSI_Q = 0x0C,
+ kVK_ANSI_W = 0x0D,
+ kVK_ANSI_E = 0x0E,
+ kVK_ANSI_R = 0x0F,
+ kVK_ANSI_Y = 0x10,
+ kVK_ANSI_T = 0x11,
+ kVK_ANSI_1 = 0x12,
+ kVK_ANSI_2 = 0x13,
+ kVK_ANSI_3 = 0x14,
+ kVK_ANSI_4 = 0x15,
+ kVK_ANSI_6 = 0x16,
+ kVK_ANSI_5 = 0x17,
+ kVK_ANSI_Equal = 0x18,
+ kVK_ANSI_9 = 0x19,
+ kVK_ANSI_7 = 0x1A,
+ kVK_ANSI_Minus = 0x1B,
+ kVK_ANSI_8 = 0x1C,
+ kVK_ANSI_0 = 0x1D,
+ kVK_ANSI_RightBracket = 0x1E,
+ kVK_ANSI_O = 0x1F,
+ kVK_ANSI_U = 0x20,
+ kVK_ANSI_LeftBracket = 0x21,
+ kVK_ANSI_I = 0x22,
+ kVK_ANSI_P = 0x23,
+ kVK_ANSI_L = 0x25,
+ kVK_ANSI_J = 0x26,
+ kVK_ANSI_Quote = 0x27,
+ kVK_ANSI_K = 0x28,
+ kVK_ANSI_Semicolon = 0x29,
+ kVK_ANSI_Backslash = 0x2A,
+ kVK_ANSI_Comma = 0x2B,
+ kVK_ANSI_Slash = 0x2C,
+ kVK_ANSI_N = 0x2D,
+ kVK_ANSI_M = 0x2E,
+ kVK_ANSI_Period = 0x2F,
+ kVK_ANSI_Grave = 0x32,
+ kVK_ANSI_KeypadDecimal = 0x41,
+ kVK_ANSI_KeypadMultiply = 0x43,
+ kVK_ANSI_KeypadPlus = 0x45,
+ kVK_ANSI_KeypadClear = 0x47,
+ kVK_ANSI_KeypadDivide = 0x4B,
+ kVK_ANSI_KeypadEnter = 0x4C,
+ kVK_ANSI_KeypadMinus = 0x4E,
+ kVK_ANSI_KeypadEquals = 0x51,
+ kVK_ANSI_Keypad0 = 0x52,
+ kVK_ANSI_Keypad1 = 0x53,
+ kVK_ANSI_Keypad2 = 0x54,
+ kVK_ANSI_Keypad3 = 0x55,
+ kVK_ANSI_Keypad4 = 0x56,
+ kVK_ANSI_Keypad5 = 0x57,
+ kVK_ANSI_Keypad6 = 0x58,
+ kVK_ANSI_Keypad7 = 0x59,
+ kVK_ANSI_Keypad8 = 0x5B,
+ kVK_ANSI_Keypad9 = 0x5C
+};
+
+/* keycodes for keys that are independent of keyboard layout*/
+enum {
+ kVK_Return = 0x24,
+ kVK_Tab = 0x30,
+ kVK_Space = 0x31,
+ kVK_Delete = 0x33,
+ kVK_Escape = 0x35,
+ kVK_Command = 0x37,
+ kVK_Shift = 0x38,
+ kVK_CapsLock = 0x39,
+ kVK_Option = 0x3A,
+ kVK_Control = 0x3B,
+ kVK_RightShift = 0x3C,
+ kVK_RightOption = 0x3D,
+ kVK_RightControl = 0x3E,
+ kVK_Function = 0x3F,
+ kVK_F17 = 0x40,
+ kVK_VolumeUp = 0x48,
+ kVK_VolumeDown = 0x49,
+ kVK_Mute = 0x4A,
+ kVK_F18 = 0x4F,
+ kVK_F19 = 0x50,
+ kVK_F20 = 0x5A,
+ kVK_F5 = 0x60,
+ kVK_F6 = 0x61,
+ kVK_F7 = 0x62,
+ kVK_F3 = 0x63,
+ kVK_F8 = 0x64,
+ kVK_F9 = 0x65,
+ kVK_F11 = 0x67,
+ kVK_F13 = 0x69,
+ kVK_F16 = 0x6A,
+ kVK_F14 = 0x6B,
+ kVK_F10 = 0x6D,
+ kVK_F12 = 0x6F,
+ kVK_F15 = 0x71,
+ kVK_Help = 0x72,
+ kVK_Home = 0x73,
+ kVK_PageUp = 0x74,
+ kVK_ForwardDelete = 0x75,
+ kVK_F4 = 0x76,
+ kVK_End = 0x77,
+ kVK_F2 = 0x78,
+ kVK_PageDown = 0x79,
+ kVK_F1 = 0x7A,
+ kVK_LeftArrow = 0x7B,
+ kVK_RightArrow = 0x7C,
+ kVK_DownArrow = 0x7D,
+ kVK_UpArrow = 0x7E
+};
+
+/* ISO keyboards only*/
+enum {
+ kVK_ISO_Section = 0x0A
+};
+
+/* JIS keyboards only*/
+enum {
+ kVK_JIS_Yen = 0x5D,
+ kVK_JIS_Underscore = 0x5E,
+ kVK_JIS_KeypadComma = 0x5F,
+ kVK_JIS_Eisu = 0x66,
+ kVK_JIS_Kana = 0x68
+};
+
+
+static GHOST_TButtonMask convertButton(int button)
+{
+ switch (button) {
+ case 0:
+ return GHOST_kButtonMaskLeft;
+ case 1:
+ return GHOST_kButtonMaskRight;
+ case 2:
+ return GHOST_kButtonMaskMiddle;
+ case 3:
+ return GHOST_kButtonMaskButton4;
+ case 4:
+ return GHOST_kButtonMaskButton5;
+ default:
+ return GHOST_kButtonMaskLeft;
+ }
+}
+
+/**
+ * Converts Mac rawkey codes (same for Cocoa & Carbon)
+ * into GHOST key codes
+ * @param rawCode The raw physical key code
+ * @param recvChar the character ignoring modifiers (except for shift)
+ * @return Ghost key code
+ */
+static GHOST_TKey convertKey(int rawCode, unichar recvChar)
+{
+
+ //printf("\nrecvchar %c 0x%x",recvChar,recvChar);
+ switch (rawCode) {
+ /*Physical keycodes not used due to map changes in int'l keyboards
+ case kVK_ANSI_A: return GHOST_kKeyA;
+ case kVK_ANSI_B: return GHOST_kKeyB;
+ case kVK_ANSI_C: return GHOST_kKeyC;
+ case kVK_ANSI_D: return GHOST_kKeyD;
+ case kVK_ANSI_E: return GHOST_kKeyE;
+ case kVK_ANSI_F: return GHOST_kKeyF;
+ case kVK_ANSI_G: return GHOST_kKeyG;
+ case kVK_ANSI_H: return GHOST_kKeyH;
+ case kVK_ANSI_I: return GHOST_kKeyI;
+ case kVK_ANSI_J: return GHOST_kKeyJ;
+ case kVK_ANSI_K: return GHOST_kKeyK;
+ case kVK_ANSI_L: return GHOST_kKeyL;
+ case kVK_ANSI_M: return GHOST_kKeyM;
+ case kVK_ANSI_N: return GHOST_kKeyN;
+ case kVK_ANSI_O: return GHOST_kKeyO;
+ case kVK_ANSI_P: return GHOST_kKeyP;
+ case kVK_ANSI_Q: return GHOST_kKeyQ;
+ case kVK_ANSI_R: return GHOST_kKeyR;
+ case kVK_ANSI_S: return GHOST_kKeyS;
+ case kVK_ANSI_T: return GHOST_kKeyT;
+ case kVK_ANSI_U: return GHOST_kKeyU;
+ case kVK_ANSI_V: return GHOST_kKeyV;
+ case kVK_ANSI_W: return GHOST_kKeyW;
+ case kVK_ANSI_X: return GHOST_kKeyX;
+ case kVK_ANSI_Y: return GHOST_kKeyY;
+ case kVK_ANSI_Z: return GHOST_kKeyZ;*/
+
+ /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/
+ case kVK_ISO_Section: return GHOST_kKeyUnknown;
+ case kVK_ANSI_1: return GHOST_kKey1;
+ case kVK_ANSI_2: return GHOST_kKey2;
+ case kVK_ANSI_3: return GHOST_kKey3;
+ case kVK_ANSI_4: return GHOST_kKey4;
+ case kVK_ANSI_5: return GHOST_kKey5;
+ case kVK_ANSI_6: return GHOST_kKey6;
+ case kVK_ANSI_7: return GHOST_kKey7;
+ case kVK_ANSI_8: return GHOST_kKey8;
+ case kVK_ANSI_9: return GHOST_kKey9;
+ case kVK_ANSI_0: return GHOST_kKey0;
+
+ case kVK_ANSI_Keypad0: return GHOST_kKeyNumpad0;
+ case kVK_ANSI_Keypad1: return GHOST_kKeyNumpad1;
+ case kVK_ANSI_Keypad2: return GHOST_kKeyNumpad2;
+ case kVK_ANSI_Keypad3: return GHOST_kKeyNumpad3;
+ case kVK_ANSI_Keypad4: return GHOST_kKeyNumpad4;
+ case kVK_ANSI_Keypad5: return GHOST_kKeyNumpad5;
+ case kVK_ANSI_Keypad6: return GHOST_kKeyNumpad6;
+ case kVK_ANSI_Keypad7: return GHOST_kKeyNumpad7;
+ case kVK_ANSI_Keypad8: return GHOST_kKeyNumpad8;
+ case kVK_ANSI_Keypad9: return GHOST_kKeyNumpad9;
+ case kVK_ANSI_KeypadDecimal: return GHOST_kKeyNumpadPeriod;
+ case kVK_ANSI_KeypadEnter: return GHOST_kKeyNumpadEnter;
+ case kVK_ANSI_KeypadPlus: return GHOST_kKeyNumpadPlus;
+ case kVK_ANSI_KeypadMinus: return GHOST_kKeyNumpadMinus;
+ case kVK_ANSI_KeypadMultiply: return GHOST_kKeyNumpadAsterisk;
+ case kVK_ANSI_KeypadDivide: return GHOST_kKeyNumpadSlash;
+ case kVK_ANSI_KeypadClear: return GHOST_kKeyUnknown;
+
+ case kVK_F1: return GHOST_kKeyF1;
+ case kVK_F2: return GHOST_kKeyF2;
+ case kVK_F3: return GHOST_kKeyF3;
+ case kVK_F4: return GHOST_kKeyF4;
+ case kVK_F5: return GHOST_kKeyF5;
+ case kVK_F6: return GHOST_kKeyF6;
+ case kVK_F7: return GHOST_kKeyF7;
+ case kVK_F8: return GHOST_kKeyF8;
+ case kVK_F9: return GHOST_kKeyF9;
+ case kVK_F10: return GHOST_kKeyF10;
+ case kVK_F11: return GHOST_kKeyF11;
+ case kVK_F12: return GHOST_kKeyF12;
+ case kVK_F13: return GHOST_kKeyF13;
+ case kVK_F14: return GHOST_kKeyF14;
+ case kVK_F15: return GHOST_kKeyF15;
+ case kVK_F16: return GHOST_kKeyF16;
+ case kVK_F17: return GHOST_kKeyF17;
+ case kVK_F18: return GHOST_kKeyF18;
+ case kVK_F19: return GHOST_kKeyF19;
+ case kVK_F20: return GHOST_kKeyF20;
+
+ case kVK_UpArrow: return GHOST_kKeyUpArrow;
+ case kVK_DownArrow: return GHOST_kKeyDownArrow;
+ case kVK_LeftArrow: return GHOST_kKeyLeftArrow;
+ case kVK_RightArrow: return GHOST_kKeyRightArrow;
+
+ case kVK_Return: return GHOST_kKeyEnter;
+ case kVK_Delete: return GHOST_kKeyBackSpace;
+ case kVK_ForwardDelete: return GHOST_kKeyDelete;
+ case kVK_Escape: return GHOST_kKeyEsc;
+ case kVK_Tab: return GHOST_kKeyTab;
+ case kVK_Space: return GHOST_kKeySpace;
+
+ case kVK_Home: return GHOST_kKeyHome;
+ case kVK_End: return GHOST_kKeyEnd;
+ case kVK_PageUp: return GHOST_kKeyUpPage;
+ case kVK_PageDown: return GHOST_kKeyDownPage;
+
+ /*case kVK_ANSI_Minus: return GHOST_kKeyMinus;
+ case kVK_ANSI_Equal: return GHOST_kKeyEqual;
+ case kVK_ANSI_Comma: return GHOST_kKeyComma;
+ case kVK_ANSI_Period: return GHOST_kKeyPeriod;
+ case kVK_ANSI_Slash: return GHOST_kKeySlash;
+ case kVK_ANSI_Semicolon: return GHOST_kKeySemicolon;
+ case kVK_ANSI_Quote: return GHOST_kKeyQuote;
+ case kVK_ANSI_Backslash: return GHOST_kKeyBackslash;
+ case kVK_ANSI_LeftBracket: return GHOST_kKeyLeftBracket;
+ case kVK_ANSI_RightBracket: return GHOST_kKeyRightBracket;
+ case kVK_ANSI_Grave: return GHOST_kKeyAccentGrave;*/
+
+ case kVK_VolumeUp:
+ case kVK_VolumeDown:
+ case kVK_Mute:
+ return GHOST_kKeyUnknown;
+
+ default:
+ /*Then detect on character value for "remappable" keys in int'l keyboards*/
+ if ((recvChar >= 'A') && (recvChar <= 'Z')) {
+ return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
+ } else if ((recvChar >= 'a') && (recvChar <= 'z')) {
+ return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
+ } else
+ switch (recvChar) {
+ case '-': return GHOST_kKeyMinus;
+ case '=': return GHOST_kKeyEqual;
+ case ',': return GHOST_kKeyComma;
+ case '.': return GHOST_kKeyPeriod;
+ case '/': return GHOST_kKeySlash;
+ case ';': return GHOST_kKeySemicolon;
+ case '\'': return GHOST_kKeyQuote;
+ case '\\': return GHOST_kKeyBackslash;
+ case '[': return GHOST_kKeyLeftBracket;
+ case ']': return GHOST_kKeyRightBracket;
+ case '`': return GHOST_kKeyAccentGrave;
+ default:
+ return GHOST_kKeyUnknown;
+ }
+ }
+ return GHOST_kKeyUnknown;
+}
+
+/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes
+ * as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html
+ * I am not sure how international this works...
+ * For cross-platform convention, we'll use the Latin ascii set instead.
+ * As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html
+ *
+ */
+static unsigned char convertRomanToLatin(unsigned char ascii)
+{
+
+ if(ascii<128) return ascii;
+
+ switch(ascii) {
+ case 128: return 142;
+ case 129: return 143;
+ case 130: return 128;
+ case 131: return 201;
+ case 132: return 209;
+ case 133: return 214;
+ case 134: return 220;
+ case 135: return 225;
+ case 136: return 224;
+ case 137: return 226;
+ case 138: return 228;
+ case 139: return 227;
+ case 140: return 229;
+ case 141: return 231;
+ case 142: return 233;
+ case 143: return 232;
+ case 144: return 234;
+ case 145: return 235;
+ case 146: return 237;
+ case 147: return 236;
+ case 148: return 238;
+ case 149: return 239;
+ case 150: return 241;
+ case 151: return 243;
+ case 152: return 242;
+ case 153: return 244;
+ case 154: return 246;
+ case 155: return 245;
+ case 156: return 250;
+ case 157: return 249;
+ case 158: return 251;
+ case 159: return 252;
+ case 160: return 0;
+ case 161: return 176;
+ case 162: return 162;
+ case 163: return 163;
+ case 164: return 167;
+ case 165: return 183;
+ case 166: return 182;
+ case 167: return 223;
+ case 168: return 174;
+ case 169: return 169;
+ case 170: return 174;
+ case 171: return 180;
+ case 172: return 168;
+ case 173: return 0;
+ case 174: return 198;
+ case 175: return 216;
+ case 176: return 0;
+ case 177: return 177;
+ case 178: return 0;
+ case 179: return 0;
+ case 180: return 165;
+ case 181: return 181;
+ case 182: return 0;
+ case 183: return 0;
+ case 184: return 215;
+ case 185: return 0;
+ case 186: return 0;
+ case 187: return 170;
+ case 188: return 186;
+ case 189: return 0;
+ case 190: return 230;
+ case 191: return 248;
+ case 192: return 191;
+ case 193: return 161;
+ case 194: return 172;
+ case 195: return 0;
+ case 196: return 0;
+ case 197: return 0;
+ case 198: return 0;
+ case 199: return 171;
+ case 200: return 187;
+ case 201: return 201;
+ case 202: return 0;
+ case 203: return 192;
+ case 204: return 195;
+ case 205: return 213;
+ case 206: return 0;
+ case 207: return 0;
+ case 208: return 0;
+ case 209: return 0;
+ case 210: return 0;
+
+ case 214: return 247;
+
+ case 229: return 194;
+ case 230: return 202;
+ case 231: return 193;
+ case 232: return 203;
+ case 233: return 200;
+ case 234: return 205;
+ case 235: return 206;
+ case 236: return 207;
+ case 237: return 204;
+ case 238: return 211;
+ case 239: return 212;
+ case 240: return 0;
+ case 241: return 210;
+ case 242: return 218;
+ case 243: return 219;
+ case 244: return 217;
+ case 245: return 0;
+ case 246: return 0;
+ case 247: return 0;
+ case 248: return 0;
+ case 249: return 0;
+ case 250: return 0;
+
+
+ default: return 0;
+ }
+
+}
+
+#define FIRSTFILEBUFLG 512
+static bool g_hasFirstFile = false;
+static char g_firstFileBuf[512];
+
+//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
+extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
+ if (g_hasFirstFile) {
+ strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
+ buf[FIRSTFILEBUFLG - 1] = '\0';
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+#pragma mark Cocoa objects
+
+/**
+ * CocoaAppDelegate
+ * ObjC object to capture applicationShouldTerminate, and send quit event
+ **/
+@interface CocoaAppDelegate : NSObject {
+ GHOST_SystemCocoa *systemCocoa;
+}
+-(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa;
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
+- (void)applicationWillTerminate:(NSNotification *)aNotification;
+@end
+
+@implementation CocoaAppDelegate : NSObject
+-(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
+{
+ systemCocoa = sysCocoa;
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ //TODO: implement graceful termination through Cocoa mechanism to avoid session log off to be cancelled
+ //Note that Cmd+Q is already handled by keyhandler
+ if (systemCocoa->handleQuitRequest() == GHOST_kExitNow)
+ return NSTerminateCancel;//NSTerminateNow;
+ else
+ return NSTerminateCancel;
+}
+
+// To avoid cancelling a log off process, we must use Cocoa termination process
+// And this function is the only chance to perform clean up
+// So WM_exit needs to be called directly, as the event loop will never run before termination
+- (void)applicationWillTerminate:(NSNotification *)aNotification
+{
+ /*G.afbreek = 0; //Let Cocoa perform the termination at the end
+ WM_exit(C);*/
+}
+@end
+
+
+
+#pragma mark initialization/finalization
+
+
+GHOST_SystemCocoa::GHOST_SystemCocoa()
+{
+ m_modifierMask =0;
+ m_pressedMouseButtons =0;
+ m_displayManager = new GHOST_DisplayManagerCocoa ();
+ GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n");
+ m_displayManager->initialize();
+
+ //NSEvent timeStamp is given in system uptime, state start date is boot time
+ //FIXME : replace by Cocoa equivalent
+ int mib[2];
+ struct timeval boottime;
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ len = sizeof(struct timeval);
+
+ sysctl(mib, 2, &boottime, &len, NULL, 0);
+ m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
+
+ m_ignoreWindowSizedMessages = false;
+}
+
+GHOST_SystemCocoa::~GHOST_SystemCocoa()
+{
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::init()
+{
+
+ GHOST_TSuccess success = GHOST_System::init();
+ if (success) {
+ //ProcessSerialNumber psn;
+
+ //Carbon stuff to move window & menu to foreground
+ /*if (!GetCurrentProcess(&psn)) {
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ SetFrontProcess(&psn);
+ }*/
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ if (NSApp == nil) {
+ [NSApplication sharedApplication];
+
+ if ([NSApp mainMenu] == nil) {
+ NSMenu *mainMenubar = [[NSMenu alloc] init];
+ NSMenuItem *menuItem;
+ NSMenu *windowMenu;
+ NSMenu *appMenu;
+
+ //Create the application menu
+ appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
+
+ [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+
+ menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"];
+ [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
+
+ menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+ [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
+
+ [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+
+ menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"];
+ [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
+
+ menuItem = [[NSMenuItem alloc] init];
+ [menuItem setSubmenu:appMenu];
+
+ [mainMenubar addItem:menuItem];
+ [menuItem release];
+ [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5
+ [appMenu release];
+
+ //Create the window menu
+ windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+
+ menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+ [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
+
+ [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
+
+ menuItem = [[NSMenuItem alloc] init];
+ [menuItem setSubmenu:windowMenu];
+
+ [mainMenubar addItem:menuItem];
+ [menuItem release];
+
+ [NSApp setMainMenu:mainMenubar];
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenu release];
+ }
+ [NSApp finishLaunching];
+ }
+ if ([NSApp delegate] == nil) {
+ CocoaAppDelegate *appDelegate = [[CocoaAppDelegate alloc] init];
+ [appDelegate setSystemCocoa:this];
+ [NSApp setDelegate:appDelegate];
+ }
+
+ [pool drain];
+ }
+ return success;
+}
+
+
+#pragma mark window management
+
+GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
+{
+ //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
+ int mib[2];
+ struct timeval boottime;
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ len = sizeof(struct timeval);
+
+ sysctl(mib, 2, &boottime, &len, NULL, 0);
+
+ return ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
+}
+
+
+GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
+{
+ //Note that OS X supports monitor hot plug
+ // We do not support multiple monitors at the moment
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ GHOST_TUns8 count = [[NSScreen screens] count];
+
+ [pool drain];
+ return count;
+}
+
+
+void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ //Get visible frame, that is frame excluding dock and top menu bar
+ NSRect frame = [[NSScreen mainScreen] visibleFrame];
+
+ //Returns max window contents (excluding title bar...)
+ NSRect contentRect = [NSWindow contentRectForFrameRect:frame
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
+
+ width = contentRect.size.width;
+ height = contentRect.size.height;
+
+ [pool drain];
+}
+
+
+GHOST_IWindow* GHOST_SystemCocoa::createWindow(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ bool stereoVisual,
+ const GHOST_TEmbedderWindowID parentWindow
+)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ GHOST_IWindow* window = 0;
+
+ //Get the available rect for including window contents
+ NSRect frame = [[NSScreen mainScreen] visibleFrame];
+ NSRect contentRect = [NSWindow contentRectForFrameRect:frame
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
+
+ //Ensures window top left is inside this available rect
+ left = left > contentRect.origin.x ? left : contentRect.origin.x;
+ top = top > contentRect.origin.y ? top : contentRect.origin.y;
+
+ window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type);
+
+ if (window) {
+ if (window->getValid()) {
+ // Store the pointer to the window
+ GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
+ //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
+
+ }
+ else {
+ GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
+ }
+ }
+ else {
+ GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
+ }
+ [pool drain];
+ return window;
+}
+
+GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
+{
+ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
+
+ *window = currentWindow;
+
+ return currentWindow->setState(GHOST_kWindowStateFullScreen);
+}
+
+GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
+{
+ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
+
+ return currentWindow->setState(GHOST_kWindowStateNormal);
+}
+
+
+
+
+GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
+{
+ NSPoint mouseLoc = [NSEvent mouseLocation];
+
+ // Returns the mouse location in screen coordinates
+ x = (GHOST_TInt32)mouseLoc.x;
+ y = (GHOST_TInt32)mouseLoc.y;
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
+{
+ float xf=(float)x, yf=(float)y;
+
+ //Quartz Display Services uses the old coordinates (top left origin)
+ yf = [[NSScreen mainScreen] frame].size.height -yf;
+
+ //CGAssociateMouseAndMouseCursorPosition(false);
+ CGWarpMouseCursorPosition(CGPointMake(xf, yf));
+ //CGAssociateMouseAndMouseCursorPosition(true);
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
+{
+ unsigned int modifiers = [[NSApp currentEvent] modifierFlags];
+ //Direct query to modifierFlags can be used in 10.6
+
+ keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & NSAlternateKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftShift, (modifiers & NSShiftKeyMask) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftControl, (modifiers & NSControlKeyMask) ? true : false);
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
+{
+ buttons.clear();
+ buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
+ buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);
+ buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);
+ buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);
+ buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);
+ return GHOST_kSuccess;
+}
+
+
+
+#pragma mark Event handlers
+
+/**
+ * The event queue polling function
+ */
+bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
+{
+ bool anyProcessed = false;
+ NSEvent *event;
+
+ // SetMouseCoalescingEnabled(false, NULL);
+ //TODO : implement timer ??
+
+ /*do {
+ GHOST_TimerManager* timerMgr = getTimerManager();
+
+ if (waitForEvent) {
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+ double timeOut;
+
+ if (next == GHOST_kFireTimeNever) {
+ timeOut = kEventDurationForever;
+ } else {
+ timeOut = (double)(next - getMilliSeconds())/1000.0;
+ if (timeOut < 0.0)
+ timeOut = 0.0;
+ }
+
+ ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
+ }
+
+ if (timerMgr->fireTimers(getMilliSeconds())) {
+ anyProcessed = true;
+ }
+
+ if (getFullScreen()) {
+ // Check if the full-screen window is dirty
+ GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
+ if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) {
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+ anyProcessed = true;
+ }
+ }*/
+
+ do {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event==nil) {
+ [pool drain];
+ break;
+ }
+
+ anyProcessed = true;
+
+ switch ([event type]) {
+ case NSKeyDown:
+ case NSKeyUp:
+ case NSFlagsChanged:
+ handleKeyEvent(event);
+
+ /* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
+ /* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
+ [NSApp sendEvent:event];
+ }*/
+ break;
+
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSMouseMoved:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSScrollWheel:
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ handleMouseEvent(event);
+ break;
+
+ case NSTabletPoint:
+ case NSTabletProximity:
+ handleTabletEvent(event,[event type]);
+ break;
+
+ /* Trackpad features, will need OS X 10.6 for implementation
+ case NSEventTypeGesture:
+ case NSEventTypeMagnify:
+ case NSEventTypeSwipe:
+ case NSEventTypeRotate:
+ case NSEventTypeBeginGesture:
+ case NSEventTypeEndGesture:
+ break; */
+
+ /*Unused events
+ NSMouseEntered = 8,
+ NSMouseExited = 9,
+ NSAppKitDefined = 13,
+ NSSystemDefined = 14,
+ NSApplicationDefined = 15,
+ NSPeriodic = 16,
+ NSCursorUpdate = 17,*/
+
+ default:
+ break;
+ }
+ //Resend event to NSApp to ensure Mac wide events are handled
+ [NSApp sendEvent:event];
+ [pool drain];
+ } while (event!= nil);
+ //} while (waitForEvent && !anyProcessed); Needed only for timer implementation
+
+
+
+ return anyProcessed;
+}
+
+//Note: called from NSWindow delegate
+GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
+{
+ if (!validWindow(window)) {
+ return GHOST_kFailure;
+ }
+ switch(eventType)
+ {
+ case GHOST_kEventWindowClose:
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
+ break;
+ case GHOST_kEventWindowActivate:
+ m_windowManager->setActiveWindow(window);
+ window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
+ break;
+ case GHOST_kEventWindowDeactivate:
+ m_windowManager->setWindowInactive(window);
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
+ break;
+ case GHOST_kEventWindowUpdate:
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+ break;
+ case GHOST_kEventWindowSize:
+ if (!m_ignoreWindowSizedMessages)
+ {
+ window->updateDrawingContext();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ }
+ break;
+ default:
+ return GHOST_kFailure;
+ break;
+ }
+ return GHOST_kSuccess;
+}
+
+GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
+{
+ //Check open windows if some changes are not saved
+ if (m_windowManager->getAnyModifiedState())
+ {
+ int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?",
+ @"Cancel", @"Quit anyway", nil);
+ if (shouldQuit == NSAlertAlternateReturn)
+ {
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
+ return GHOST_kExitNow;
+ }
+ }
+ else {
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
+ return GHOST_kExitNow;
+ }
+
+ return GHOST_kExitCancel;
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
+{
+ NSEvent *event = (NSEvent *)eventPtr;
+ GHOST_IWindow* window = m_windowManager->getActiveWindow();
+ GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
+
+ switch (eventType) {
+ case NSTabletPoint:
+ ct.Pressure = [event tangentialPressure];
+ ct.Xtilt = [event tilt].x;
+ ct.Ytilt = [event tilt].y;
+ break;
+
+ case NSTabletProximity:
+ ct.Pressure = 0;
+ ct.Xtilt = 0;
+ ct.Ytilt = 0;
+ if ([event isEnteringProximity])
+ {
+ //pointer is entering tablet area proximity
+ switch ([event pointingDeviceType]) {
+ case NSPenPointingDevice:
+ ct.Active = GHOST_kTabletModeStylus;
+ break;
+ case NSEraserPointingDevice:
+ ct.Active = GHOST_kTabletModeEraser;
+ break;
+ case NSCursorPointingDevice:
+ case NSUnknownPointingDevice:
+ default:
+ ct.Active = GHOST_kTabletModeNone;
+ break;
+ }
+ } else {
+ // pointer is leaving - return to mouse
+ ct.Active = GHOST_kTabletModeNone;
+ }
+ break;
+
+ default:
+ GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received");
+ return GHOST_kFailure;
+ break;
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
+{
+ NSEvent *event = (NSEvent *)eventPtr;
+ GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
+
+ if (!window) {
+ return GHOST_kFailure;
+ }
+
+ switch ([event type])
+ {
+ case NSLeftMouseDown:
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
+ //Handle tablet events combined with mouse events
+ switch ([event subtype]) {
+ case NX_SUBTYPE_TABLET_POINT:
+ handleTabletEvent(eventPtr, NSTabletPoint);
+ break;
+ case NX_SUBTYPE_TABLET_PROXIMITY:
+ handleTabletEvent(eventPtr, NSTabletProximity);
+ break;
+ default:
+ //No tablet event included : do nothing
+ break;
+ }
+ break;
+
+ case NSLeftMouseUp:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
+ //Handle tablet events combined with mouse events
+ switch ([event subtype]) {
+ case NX_SUBTYPE_TABLET_POINT:
+ handleTabletEvent(eventPtr, NSTabletPoint);
+ break;
+ case NX_SUBTYPE_TABLET_PROXIMITY:
+ handleTabletEvent(eventPtr, NSTabletProximity);
+ break;
+ default:
+ //No tablet event included : do nothing
+ break;
+ }
+ break;
+
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ //Handle tablet events combined with mouse events
+ switch ([event subtype]) {
+ case NX_SUBTYPE_TABLET_POINT:
+ handleTabletEvent(eventPtr, NSTabletPoint);
+ break;
+ case NX_SUBTYPE_TABLET_PROXIMITY:
+ handleTabletEvent(eventPtr, NSTabletProximity);
+ break;
+ default:
+ //No tablet event included : do nothing
+ break;
+ }
+ case NSMouseMoved:
+ {
+ if(window->getCursorWarp()) {
+ GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
+
+ window->getCursorWarpPos(x_warp, y_warp);
+
+ window->getCursorWarpAccum(x_accum, y_accum);
+ x_accum += [event deltaX];
+ y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
+ window->setCursorWarpAccum(x_accum, y_accum);
+
+ pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
+ }
+ else { //Normal cursor operation: send mouse position in window
+ NSPoint mousePos = [event locationInWindow];
+ pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
+ window->setCursorWarpAccum(0, 0); //Mouse motion occured between two cursor warps, so we can reset the delta counter
+ }
+ break;
+ }
+
+ case NSScrollWheel:
+ {
+ GHOST_TInt32 delta;
+
+ double deltaF = [event deltaY];
+ if (deltaF == 0.0) break; //discard trackpad delta=0 events
+
+ delta = deltaF > 0.0 ? 1 : -1;
+ pushEvent(new GHOST_EventWheel([event timestamp], window, delta));
+ }
+ break;
+
+ default:
+ return GHOST_kFailure;
+ break;
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
+{
+ NSEvent *event = (NSEvent *)eventPtr;
+ GHOST_IWindow* window = m_windowManager->getActiveWindow();
+ unsigned int modifiers;
+ NSString *characters;
+ GHOST_TKey keyCode;
+ unsigned char ascii;
+
+ /* Can happen, very rarely - seems to only be when command-H makes
+ * the window go away and we still get an HKey up.
+ */
+ if (!window) {
+ printf("\nW failure");
+ return GHOST_kFailure;
+ }
+
+ switch ([event type]) {
+ case NSKeyDown:
+ case NSKeyUp:
+ characters = [event characters];
+ if ([characters length]) { //Check for dead keys
+ keyCode = convertKey([event keyCode],
+ [[event charactersIgnoringModifiers] characterAtIndex:0]);
+ ascii= convertRomanToLatin((char)[characters characterAtIndex:0]);
+ } else {
+ keyCode = convertKey([event keyCode],0);
+ ascii= 0;
+ }
+
+
+ if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
+ break; //Cmd-Q is directly handled by Cocoa
+
+ if ([event type] == NSKeyDown) {
+ pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyDown, window, keyCode, ascii) );
+ //printf("\nKey pressed keyCode=%u ascii=%i %c",keyCode,ascii,ascii);
+ } else {
+ pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyUp, window, keyCode, ascii) );
+ }
+ break;
+
+ case NSFlagsChanged:
+ modifiers = [event modifierFlags];
+ if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
+ pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
+ }
+ if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
+ pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
+ }
+ if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
+ pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
+ }
+ if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
+ pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
+ }
+
+ m_modifierMask = modifiers;
+ break;
+
+ default:
+ return GHOST_kFailure;
+ break;
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+
+#pragma mark Clipboard get/set
+
+GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
+{
+ GHOST_TUns8 * temp_buff;
+ size_t pastedTextSize;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
+
+ if (pasteBoard == nil) {
+ [pool drain];
+ return NULL;
+ }
+
+ NSArray *supportedTypes =
+ [NSArray arrayWithObjects: @"public.utf8-plain-text", nil];
+
+ NSString *bestType = [[NSPasteboard generalPasteboard]
+ availableTypeFromArray:supportedTypes];
+
+ if (bestType == nil) {
+ [pool drain];
+ return NULL;
+ }
+
+ NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"];
+
+ if (textPasted == nil) {
+ [pool drain];
+ return NULL;
+ }
+
+ pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+
+ temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
+
+ if (temp_buff == NULL) {
+ [pool drain];
+ return NULL;
+ }
+
+ strncpy((char*)temp_buff, [textPasted UTF8String], pastedTextSize);
+
+ temp_buff[pastedTextSize] = '\0';
+
+ [pool drain];
+
+ if(temp_buff) {
+ return temp_buff;
+ } else {
+ return NULL;
+ }
+}
+
+void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+{
+ NSString *textToCopy;
+
+ if(selection) {return;} // for copying the selection, used on X11
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
+
+ if (pasteBoard == nil) {
+ [pool drain];
+ return;
+ }
+
+ NSArray *supportedTypes = [NSArray arrayWithObject:@"public.utf8-plain-text"];
+
+ [pasteBoard declareTypes:supportedTypes owner:nil];
+
+ textToCopy = [NSString stringWithUTF8String:buffer];
+
+ [pasteBoard setString:textToCopy forType:@"public.utf8-plain-text"];
+
+ [pool drain];
+}
+
+#pragma mark Carbon stuff to remove
+
+#ifdef WITH_CARBON
+
+
+OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
+{
+ //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
+
+ return noErr;
+}
+
+OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
+{
+ //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
+ AEDescList docs;
+ SInt32 ndocs;
+ OSErr err;
+
+ err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs);
+ if (err != noErr) return err;
+
+ err = AECountItems(&docs, &ndocs);
+ if (err==noErr) {
+ int i;
+
+ for (i=0; i<ndocs; i++) {
+ FSSpec fss;
+ AEKeyword kwd;
+ DescType actType;
+ Size actSize;
+
+ err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize);
+ if (err!=noErr)
+ break;
+
+ if (i==0) {
+ FSRef fsref;
+
+ if (FSpMakeFSRef(&fss, &fsref)!=noErr)
+ break;
+ if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr)
+ break;
+
+ g_hasFirstFile = true;
+ }
+ }
+ }
+
+ AEDisposeDesc(&docs);
+
+ return err;
+}
+
+OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
+{
+ //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
+
+ return noErr;
+}
+
+OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
+{
+ GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
+
+ sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) );
+
+ return noErr;
+}
#endif \ No newline at end of file
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index d6c154535a9..4037ebafc64 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: GHOST_WindowCocoa.h 23789 2009-10-12 16:51:36Z damien78 $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index e41c773a4c3..a2b146c1e33 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -1,1028 +1,1028 @@
-/**
- * $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): Maarten Gribnau 05/2001
- Damien Plisson 10/2009
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <Cocoa/Cocoa.h>
-
-#ifndef MAC_OS_X_VERSION_10_6
-//Use of the SetSystemUIMode function (64bit compatible)
-#include <Carbon/Carbon.h>
-#endif
-
-#include "GHOST_WindowCocoa.h"
-#include "GHOST_SystemCocoa.h"
-#include "GHOST_Debug.h"
-
-
-// Pixel Format Attributes for the windowed NSOpenGLContext
-static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
-{
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFAAccelerated,
- //NSOpenGLPFAAllowOfflineRenderers, // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
- NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 32,
- (NSOpenGLPixelFormatAttribute) 0
-};
-
-#pragma mark Cocoa window delegate object
-
-@interface CocoaWindowDelegate : NSObject
-{
- GHOST_SystemCocoa *systemCocoa;
- GHOST_WindowCocoa *associatedWindow;
-}
-
-- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
-- (void)windowWillClose:(NSNotification *)notification;
-- (void)windowDidBecomeKey:(NSNotification *)notification;
-- (void)windowDidResignKey:(NSNotification *)notification;
-- (void)windowDidUpdate:(NSNotification *)notification;
-- (void)windowDidResize:(NSNotification *)notification;
-@end
-
-@implementation CocoaWindowDelegate : NSObject
-- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
-{
- systemCocoa = sysCocoa;
- associatedWindow = winCocoa;
-}
-
-- (void)windowWillClose:(NSNotification *)notification
-{
- systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
-}
-
-- (void)windowDidBecomeKey:(NSNotification *)notification
-{
- systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
-}
-
-- (void)windowDidResignKey:(NSNotification *)notification
-{
- //The window is no more key when its own view becomes fullscreen
- //but ghost doesn't know the view/window difference, so hide this fact
- if (associatedWindow->getState() != GHOST_kWindowStateFullScreen)
- systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
-}
-
-- (void)windowDidUpdate:(NSNotification *)notification
-{
- systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
-}
-
-- (void)windowDidResize:(NSNotification *)notification
-{
- systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
-}
-@end
-
-#pragma mark NSWindow subclass
-//We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events)
-@interface CocoaWindow: NSWindow
-{
-
-}
--(BOOL)canBecomeKeyWindow;
-
-@end
-@implementation CocoaWindow
-
--(BOOL)canBecomeKeyWindow
-{
- return YES;
-}
-
-@end
-
-
-
-#pragma mark NSOpenGLView subclass
-//We need to subclass it in order to give Cocoa the feeling key events are trapped
-@interface CocoaOpenGLView : NSOpenGLView
-{
-
-}
-@end
-@implementation CocoaOpenGLView
-
-- (BOOL)acceptsFirstResponder
-{
- return YES;
-}
-
-//The trick to prevent Cocoa from complaining (beeping)
-- (void)keyDown:(NSEvent *)theEvent
-{}
-
-- (BOOL)isOpaque
-{
- return YES;
-}
-
-@end
-
-
-#pragma mark initialization / finalization
-
-NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
-
-GHOST_WindowCocoa::GHOST_WindowCocoa(
- GHOST_SystemCocoa *systemCocoa,
- const STR_String& title,
- GHOST_TInt32 left,
- GHOST_TInt32 top,
- GHOST_TUns32 width,
- GHOST_TUns32 height,
- GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
- const bool stereoVisual
-) :
- GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
- m_customCursor(0)
-{
- m_systemCocoa = systemCocoa;
- m_fullScreen = false;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-
- //Creates the window
- NSRect rect;
-
- rect.origin.x = left;
- rect.origin.y = top;
- rect.size.width = width;
- rect.size.height = height;
-
- m_window = [[CocoaWindow alloc] initWithContentRect:rect
- styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
- backing:NSBackingStoreBuffered defer:NO];
- if (m_window == nil) {
- [pool drain];
- return;
- }
-
- setTitle(title);
-
-
- //Creates the OpenGL View inside the window
- NSOpenGLPixelFormat *pixelFormat =
- [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
-
- m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
- pixelFormat:pixelFormat];
-
- [pixelFormat release];
-
- m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
-
- [m_window setContentView:m_openGLView];
- [m_window setInitialFirstResponder:m_openGLView];
-
- [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
-
- [m_window makeKeyAndOrderFront:nil];
-
- setDrawingContextType(type);
- updateDrawingContext();
- activateDrawingContext();
-
- m_tablet.Active = GHOST_kTabletModeNone;
-
- CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
- [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
- [m_window setDelegate:windowDelegate];
-
- [m_window setAcceptsMouseMovedEvents:YES];
-
- if (state == GHOST_kWindowStateFullScreen)
- setState(GHOST_kWindowStateFullScreen);
-
- [pool drain];
-}
-
-
-GHOST_WindowCocoa::~GHOST_WindowCocoa()
-{
- if (m_customCursor) delete m_customCursor;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLView release];
-
- if (m_window) {
- [m_window close];
- [[m_window delegate] release];
- [m_window release];
- m_window = nil;
- }
-
- //Check for other blender opened windows and make the frontmost key
- NSArray *windowsList = [NSApp orderedWindows];
- if ([windowsList count]) {
- [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
- }
- [pool drain];
-}
-
-#pragma mark accessors
-
-bool GHOST_WindowCocoa::getValid() const
-{
- bool valid;
- if (!m_fullScreen) {
- valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef);
- }
- else {
- valid = true;
- }
- return valid;
-}
-
-
-void GHOST_WindowCocoa::setTitle(const STR_String& title)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];
-
- //Set associated file if applicable
- if ([windowTitle hasPrefix:@"Blender"])
- {
- NSRange fileStrRange;
- NSString *associatedFileName;
- int len;
-
- fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;
- len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;
-
- if (len >0)
- {
- fileStrRange.length = len;
- associatedFileName = [windowTitle substringWithRange:fileStrRange];
- @try {
- [m_window setRepresentedFilename:associatedFileName];
- }
- @catch (NSException * e) {
- printf("\nInvalid file path given in window title");
- }
- [m_window setTitle:[associatedFileName lastPathComponent]];
- }
- else {
- [m_window setTitle:windowTitle];
- [m_window setRepresentedFilename:@""];
- }
-
- } else {
- [m_window setTitle:windowTitle];
- [m_window setRepresentedFilename:@""];
- }
-
-
- [windowTitle release];
- [pool drain];
-}
-
-
-void GHOST_WindowCocoa::getTitle(STR_String& title) const
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *windowTitle = [m_window title];
-
- if (windowTitle != nil) {
- title = [windowTitle UTF8String];
- }
-
- [pool drain];
-}
-
-
-void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
-{
- NSRect rect;
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSRect screenSize = [[m_window screen] visibleFrame];
-
- rect = [m_window frame];
-
- bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);
- bounds.m_l = rect.origin.x -screenSize.origin.x;
- bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;
- bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);
-
- [pool drain];
-}
-
-
-void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
-{
- NSRect rect;
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- if (!m_fullScreen)
- {
- NSRect screenSize = [[m_window screen] visibleFrame];
-
- //Max window contents as screen size (excluding title bar...)
- NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
-
- rect = [m_window contentRectForFrameRect:[m_window frame]];
-
- bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);
- bounds.m_l = rect.origin.x -contentRect.origin.x;
- bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;
- bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);
- }
- else {
- NSRect screenSize = [[m_window screen] frame];
-
- bounds.m_b = screenSize.origin.y + screenSize.size.height;
- bounds.m_l = screenSize.origin.x;
- bounds.m_r = screenSize.origin.x + screenSize.size.width;
- bounds.m_t = screenSize.origin.y;
- }
- [pool drain];
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
- GHOST_Rect cBnds, wBnds;
- getClientBounds(cBnds);
- if (((GHOST_TUns32)cBnds.getWidth()) != width) {
- NSSize size;
- size.width=width;
- size.height=cBnds.getHeight();
- [m_window setContentSize:size];
- }
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
- GHOST_Rect cBnds, wBnds;
- getClientBounds(cBnds);
- if (((GHOST_TUns32)cBnds.getHeight()) != height) {
- NSSize size;
- size.width=cBnds.getWidth();
- size.height=height;
- [m_window setContentSize:size];
- }
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
- GHOST_Rect cBnds, wBnds;
- getClientBounds(cBnds);
- if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
- (((GHOST_TUns32)cBnds.getHeight()) != height)) {
- NSSize size;
- size.width=width;
- size.height=height;
- [m_window setContentSize:size];
- }
- return GHOST_kSuccess;
-}
-
-
-GHOST_TWindowState GHOST_WindowCocoa::getState() const
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- GHOST_TWindowState state;
- if (m_fullScreen) {
- state = GHOST_kWindowStateFullScreen;
- }
- else if ([m_window isMiniaturized]) {
- state = GHOST_kWindowStateMinimized;
- }
- else if ([m_window isZoomed]) {
- state = GHOST_kWindowStateMaximized;
- }
- else {
- state = GHOST_kWindowStateNormal;
- }
- [pool drain];
- return state;
-}
-
-
-void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
-
- NSPoint screenCoord;
- NSPoint baseCoord;
-
- screenCoord.x = inX;
- screenCoord.y = inY;
-
- baseCoord = [m_window convertScreenToBase:screenCoord];
-
- outX = baseCoord.x;
- outY = baseCoord.y;
-}
-
-
-void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
-
- NSPoint screenCoord;
- NSPoint baseCoord;
-
- baseCoord.x = inX;
- baseCoord.y = inY;
-
- screenCoord = [m_window convertBaseToScreen:baseCoord];
-
- outX = screenCoord.x;
- outY = screenCoord.y;
-}
-
-/**
- * @note Fullscreen switch is not actual fullscreen with display capture. As this capture removes all OS X window manager features.
- * Instead, the menu bar and the dock are hidden, and the window is made borderless and enlarged.
- * Thus, process switch, exposé, spaces, ... still work in fullscreen mode
- */
-GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
- switch (state) {
- case GHOST_kWindowStateMinimized:
- [m_window miniaturize:nil];
- break;
- case GHOST_kWindowStateMaximized:
- [m_window zoom:nil];
- break;
-
- case GHOST_kWindowStateFullScreen:
- if (!m_fullScreen)
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- //This status change needs to be done before Cocoa call to enter fullscreen mode
- //to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference
- m_fullScreen = true;
-
-#ifdef MAC_OS_X_VERSION_10_6
- //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style
- //Hide menu & dock if needed
- if ([[m_window screen] isEqual:[NSScreen mainScreen]])
- {
- [NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
- }
- //Make window borderless and enlarge it
- [m_window setStyleMask:NSBorderlessWindowMask];
- [m_window setFrame:[[m_window screen] frame] display:YES];
-#else
- //With 10.5, we need to create a new window to change its style to borderless
- //Hide menu & dock if needed
- if ([[m_window screen] isEqual:[NSScreen mainScreen]])
- {
- //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:NO];
- //One of the very few 64bit compatible Carbon function
- SetSystemUIMode(kUIModeAllHidden,kUIOptionAutoShowMenuBar);
- }
- //Create a fullscreen borderless window
- CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:YES];
- //Copy current window parameters
- [tmpWindow setTitle:[m_window title]];
- [tmpWindow setRepresentedFilename:[m_window representedFilename]];
- [tmpWindow setReleasedWhenClosed:NO];
- [tmpWindow setAcceptsMouseMovedEvents:YES];
- [tmpWindow setDelegate:[m_window delegate]];
-
- //Assign the openGL view to the new window
- [tmpWindow setContentView:m_openGLView];
-
- //Show the new window
- [tmpWindow makeKeyAndOrderFront:nil];
- //Close and release old window
- [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
- [m_window close];
- [m_window release];
- m_window = tmpWindow;
-#endif
-
- //Tell WM of view new size
- m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
-
- [pool drain];
- }
- break;
- case GHOST_kWindowStateNormal:
- default:
- if (m_fullScreen)
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- m_fullScreen = false;
-
- //Exit fullscreen
-#ifdef MAC_OS_X_VERSION_10_6
- //Show again menu & dock if needed
- if ([[m_window screen] isEqual:[NSScreen mainScreen]])
- {
- [NSApp setPresentationOptions:NSApplicationPresentationDefault];
- }
- //Make window normal and resize it
- [m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
- [m_window setFrame:[[m_window screen] visibleFrame] display:YES];
-#else
- //With 10.5, we need to create a new window to change its style to borderless
- //Show menu & dock if needed
- if ([[m_window screen] isEqual:[NSScreen mainScreen]])
- {
- //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:YES];
- SetSystemUIMode(kUIModeNormal, 0); //One of the very few 64bit compatible Carbon function
- }
- //Create a fullscreen borderless window
- CocoaWindow *tmpWindow = [[CocoaWindow alloc]
- initWithContentRect:[[m_window screen] frame]
- styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
- backing:NSBackingStoreBuffered
- defer:YES];
- //Copy current window parameters
- [tmpWindow setTitle:[m_window title]];
- [tmpWindow setRepresentedFilename:[m_window representedFilename]];
- [tmpWindow setReleasedWhenClosed:NO];
- [tmpWindow setAcceptsMouseMovedEvents:YES];
- [tmpWindow setDelegate:[m_window delegate]];
-
- //Assign the openGL view to the new window
- [tmpWindow setContentView:m_openGLView];
-
- //Show the new window
- [tmpWindow makeKeyAndOrderFront:nil];
- //Close and release old window
- [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
- [m_window close];
- [m_window release];
- m_window = tmpWindow;
-#endif
-
- //Tell WM of view new size
- m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
-
- [pool drain];
- }
- else if ([m_window isMiniaturized])
- [m_window deminiaturize:nil];
- else if ([m_window isZoomed])
- [m_window zoom:nil];
- break;
- }
- return GHOST_kSuccess;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [m_window setDocumentEdited:isUnsavedChanges];
-
- [pool drain];
- return GHOST_Window::setModifiedState(isUnsavedChanges);
-}
-
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
- if (order == GHOST_kWindowOrderTop) {
- [m_window orderFront:nil];
- }
- else {
- [m_window orderBack:nil];
- }
- return GHOST_kSuccess;
-}
-
-#pragma mark Drawing context
-
-/*#define WAIT_FOR_VSYNC 1*/
-
-GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext flushBuffer];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext update];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
-{
- if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
- if (m_openGLContext != nil) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLContext makeCurrentContext];
- [pool drain];
- return GHOST_kSuccess;
- }
- }
- return GHOST_kFailure;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
-{
- GHOST_TSuccess success = GHOST_kFailure;
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSOpenGLPixelFormat *pixelFormat;
- NSOpenGLContext *tmpOpenGLContext;
-
- switch (type) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (!getValid()) break;
-
- pixelFormat = [m_openGLView pixelFormat];
- tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
- shareContext:s_firstOpenGLcontext];
- if (tmpOpenGLContext == nil) {
- success = GHOST_kFailure;
- break;
- }
-
- if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
-#ifdef WAIT_FOR_VSYNC
- /* wait for vsync, to avoid tearing artifacts */
- [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval];
-#endif
- [m_openGLView setOpenGLContext:tmpOpenGLContext];
- [tmpOpenGLContext setView:m_openGLView];
-
- m_openGLContext = tmpOpenGLContext;
- break;
-
- case GHOST_kDrawingContextTypeNone:
- success = GHOST_kSuccess;
- break;
-
- default:
- break;
- }
- [pool drain];
- return success;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- switch (m_drawingContextType) {
- case GHOST_kDrawingContextTypeOpenGL:
- if (m_openGLContext)
- {
- [m_openGLView clearGLContext];
- if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil;
- m_openGLContext = nil;
- }
- [pool drain];
- return GHOST_kSuccess;
- case GHOST_kDrawingContextTypeNone:
- [pool drain];
- return GHOST_kSuccess;
- break;
- default:
- [pool drain];
- return GHOST_kFailure;
- }
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::invalidate()
-{
- GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLView setNeedsDisplay:YES];
- [pool drain];
- return GHOST_kSuccess;
-}
-
-#pragma mark Cursor handling
-
-void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
-{
- static bool systemCursorVisible = true;
-
- NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
-
- NSCursor *tmpCursor =nil;
-
- if (visible != systemCursorVisible) {
- if (visible) {
- [NSCursor unhide];
- systemCursorVisible = true;
- }
- else {
- [NSCursor hide];
- systemCursorVisible = false;
- }
- }
-
- if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
- tmpCursor = m_customCursor;
- } else {
- switch (cursor) {
- case GHOST_kStandardCursorDestroy:
- tmpCursor = [NSCursor disappearingItemCursor];
- break;
- case GHOST_kStandardCursorText:
- tmpCursor = [NSCursor IBeamCursor];
- break;
- case GHOST_kStandardCursorCrosshair:
- tmpCursor = [NSCursor crosshairCursor];
- break;
- case GHOST_kStandardCursorUpDown:
- tmpCursor = [NSCursor resizeUpDownCursor];
- break;
- case GHOST_kStandardCursorLeftRight:
- tmpCursor = [NSCursor resizeLeftRightCursor];
- break;
- case GHOST_kStandardCursorTopSide:
- tmpCursor = [NSCursor resizeUpCursor];
- break;
- case GHOST_kStandardCursorBottomSide:
- tmpCursor = [NSCursor resizeDownCursor];
- break;
- case GHOST_kStandardCursorLeftSide:
- tmpCursor = [NSCursor resizeLeftCursor];
- break;
- case GHOST_kStandardCursorRightSide:
- tmpCursor = [NSCursor resizeRightCursor];
- break;
- case GHOST_kStandardCursorRightArrow:
- case GHOST_kStandardCursorInfo:
- case GHOST_kStandardCursorLeftArrow:
- case GHOST_kStandardCursorHelp:
- case GHOST_kStandardCursorCycle:
- case GHOST_kStandardCursorSpray:
- case GHOST_kStandardCursorWait:
- case GHOST_kStandardCursorTopLeftCorner:
- case GHOST_kStandardCursorTopRightCorner:
- case GHOST_kStandardCursorBottomRightCorner:
- case GHOST_kStandardCursorBottomLeftCorner:
- case GHOST_kStandardCursorDefault:
- default:
- tmpCursor = [NSCursor arrowCursor];
- break;
- };
- }
- [tmpCursor set];
- [pool drain];
-}
-
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
-{
- if ([m_window isVisible]) {
- loadCursor(visible, getCursorShape());
- }
-
- return GHOST_kSuccess;
-}
-
-
-//Override this method to provide set feature even if not in warp
-inline bool GHOST_WindowCocoa::setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y)
-{
- m_cursorWarpAccumPos[0]= x;
- m_cursorWarpAccumPos[1]= y;
-
- return GHOST_kSuccess;
-}
-
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
-{
- if (grab)
- {
- //No need to perform grab without warp as it is always on in OS X
- if(warp) {
- GHOST_TInt32 x_old,y_old;
-
- m_cursorWarp= true;
- m_systemCocoa->getCursorPosition(x_old,y_old);
- screenToClient(x_old, y_old, m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
- //Warp position is stored in client (window base) coordinates
- setWindowCursorVisibility(false);
- return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
- }
- }
- else {
- if(m_cursorWarp)
- {/* are we exiting warp */
- setWindowCursorVisibility(true);
- /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
- if(restore) {
- GHOST_Rect bounds;
- GHOST_TInt32 x_new, y_new, x_cur, y_cur;
-
- getClientBounds(bounds);
- x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
- y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
-
- if(x_new < 0) x_new = 0;
- if(y_new < 0) y_new = 0;
- if(x_new > bounds.getWidth()) x_new = bounds.getWidth();
- if(y_new > bounds.getHeight()) y_new = bounds.getHeight();
-
- //get/set cursor position works in screen coordinates
- clientToScreen(x_new, y_new, x_cur, y_cur);
- m_systemCocoa->setCursorPosition(x_cur, y_cur);
-
- //As Cocoa will give as first deltaX,deltaY this change in cursor position, we need to compensate for it
- //Issue appearing in case of two transform operations conducted w/o mouse motion in between
- x_new=m_cursorWarpAccumPos[0];
- y_new=m_cursorWarpAccumPos[1];
- setCursorWarpAccum(-x_new, -y_new);
- }
- else {
- GHOST_TInt32 x_new, y_new;
- //get/set cursor position works in screen coordinates
- clientToScreen(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1], x_new, y_new);
- m_systemCocoa->setCursorPosition(x_new, y_new);
- setCursorWarpAccum(0, 0);
- }
-
- m_cursorWarp= false;
- return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
- }
- }
- return GHOST_kSuccess;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
-{
- if (m_customCursor) {
- [m_customCursor release];
- m_customCursor = nil;
- }
-
- if ([m_window isVisible]) {
- loadCursor(getCursorVisibility(), shape);
- }
-
- return GHOST_kSuccess;
-}
-
-/** Reverse the bits in a GHOST_TUns8
-static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
-{
- ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
- ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC);
- ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
- return ch;
-}
-*/
-
-
-/** Reverse the bits in a GHOST_TUns16 */
-static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
-{
- shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA);
- shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC);
- shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0);
- shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00);
- return shrt;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
- int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
-{
- int y,nbUns16;
- NSPoint hotSpotPoint;
- NSBitmapImageRep *cursorImageRep;
- NSImage *cursorImage;
- NSSize imSize;
- GHOST_TUns16 *cursorBitmap;
-
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- if (m_customCursor) {
- [m_customCursor release];
- m_customCursor = nil;
- }
-
-
- cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
- pixelsWide:sizex
- pixelsHigh:sizey
- bitsPerSample:1
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:YES
- colorSpaceName:NSDeviceBlackColorSpace
- bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
- bitsPerPixel:1];
-
-
- cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
- nbUns16 = [cursorImageRep bytesPerPlane]/2;
-
- for (y=0; y<nbUns16; y++) {
-#if !defined(__LITTLE_ENDIAN__)
- cursorBitmap[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
- cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
-#else
- cursorBitmap[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
- cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
-#endif
-
- }
-
-
- imSize.width = sizex;
- imSize.height= sizey;
- cursorImage = [[NSImage alloc] initWithSize:imSize];
- [cursorImage addRepresentation:cursorImageRep];
-
- hotSpotPoint.x = hotX;
- hotSpotPoint.y = hotY;
-
- //foreground and background color parameter is not handled for now (10.6)
- m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
- hotSpot:hotSpotPoint];
-
- [cursorImageRep release];
- [cursorImage release];
-
- if ([m_window isVisible]) {
- loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
- }
- [pool drain];
- return GHOST_kSuccess;
-}
-
-GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
- GHOST_TUns8 mask[16][2], int hotX, int hotY)
-{
- return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
-}
+/**
+ * $Id: GHOST_WindowCocoa.mm 23873 2009-10-15 20:09:50Z damien78 $
+ * ***** 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): Maarten Gribnau 05/2001
+ Damien Plisson 10/2009
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <Cocoa/Cocoa.h>
+
+#ifndef MAC_OS_X_VERSION_10_6
+//Use of the SetSystemUIMode function (64bit compatible)
+#include <Carbon/Carbon.h>
+#endif
+
+#include "GHOST_WindowCocoa.h"
+#include "GHOST_SystemCocoa.h"
+#include "GHOST_Debug.h"
+
+
+// Pixel Format Attributes for the windowed NSOpenGLContext
+static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
+{
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAAccelerated,
+ //NSOpenGLPFAAllowOfflineRenderers, // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
+ NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 32,
+ (NSOpenGLPixelFormatAttribute) 0
+};
+
+#pragma mark Cocoa window delegate object
+
+@interface CocoaWindowDelegate : NSObject
+{
+ GHOST_SystemCocoa *systemCocoa;
+ GHOST_WindowCocoa *associatedWindow;
+}
+
+- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
+- (void)windowWillClose:(NSNotification *)notification;
+- (void)windowDidBecomeKey:(NSNotification *)notification;
+- (void)windowDidResignKey:(NSNotification *)notification;
+- (void)windowDidUpdate:(NSNotification *)notification;
+- (void)windowDidResize:(NSNotification *)notification;
+@end
+
+@implementation CocoaWindowDelegate : NSObject
+- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
+{
+ systemCocoa = sysCocoa;
+ associatedWindow = winCocoa;
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)notification
+{
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
+}
+
+- (void)windowDidResignKey:(NSNotification *)notification
+{
+ //The window is no more key when its own view becomes fullscreen
+ //but ghost doesn't know the view/window difference, so hide this fact
+ if (associatedWindow->getState() != GHOST_kWindowStateFullScreen)
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
+}
+
+- (void)windowDidUpdate:(NSNotification *)notification
+{
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
+}
+@end
+
+#pragma mark NSWindow subclass
+//We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events)
+@interface CocoaWindow: NSWindow
+{
+
+}
+-(BOOL)canBecomeKeyWindow;
+
+@end
+@implementation CocoaWindow
+
+-(BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
+
+@end
+
+
+
+#pragma mark NSOpenGLView subclass
+//We need to subclass it in order to give Cocoa the feeling key events are trapped
+@interface CocoaOpenGLView : NSOpenGLView
+{
+
+}
+@end
+@implementation CocoaOpenGLView
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+//The trick to prevent Cocoa from complaining (beeping)
+- (void)keyDown:(NSEvent *)theEvent
+{}
+
+- (BOOL)isOpaque
+{
+ return YES;
+}
+
+@end
+
+
+#pragma mark initialization / finalization
+
+NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
+
+GHOST_WindowCocoa::GHOST_WindowCocoa(
+ GHOST_SystemCocoa *systemCocoa,
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ const bool stereoVisual
+) :
+ GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
+ m_customCursor(0)
+{
+ m_systemCocoa = systemCocoa;
+ m_fullScreen = false;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+
+ //Creates the window
+ NSRect rect;
+
+ rect.origin.x = left;
+ rect.origin.y = top;
+ rect.size.width = width;
+ rect.size.height = height;
+
+ m_window = [[CocoaWindow alloc] initWithContentRect:rect
+ styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
+ backing:NSBackingStoreBuffered defer:NO];
+ if (m_window == nil) {
+ [pool drain];
+ return;
+ }
+
+ setTitle(title);
+
+
+ //Creates the OpenGL View inside the window
+ NSOpenGLPixelFormat *pixelFormat =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+
+ m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
+ pixelFormat:pixelFormat];
+
+ [pixelFormat release];
+
+ m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
+
+ [m_window setContentView:m_openGLView];
+ [m_window setInitialFirstResponder:m_openGLView];
+
+ [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
+
+ [m_window makeKeyAndOrderFront:nil];
+
+ setDrawingContextType(type);
+ updateDrawingContext();
+ activateDrawingContext();
+
+ m_tablet.Active = GHOST_kTabletModeNone;
+
+ CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
+ [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
+ [m_window setDelegate:windowDelegate];
+
+ [m_window setAcceptsMouseMovedEvents:YES];
+
+ if (state == GHOST_kWindowStateFullScreen)
+ setState(GHOST_kWindowStateFullScreen);
+
+ [pool drain];
+}
+
+
+GHOST_WindowCocoa::~GHOST_WindowCocoa()
+{
+ if (m_customCursor) delete m_customCursor;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLView release];
+
+ if (m_window) {
+ [m_window close];
+ [[m_window delegate] release];
+ [m_window release];
+ m_window = nil;
+ }
+
+ //Check for other blender opened windows and make the frontmost key
+ NSArray *windowsList = [NSApp orderedWindows];
+ if ([windowsList count]) {
+ [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+ }
+ [pool drain];
+}
+
+#pragma mark accessors
+
+bool GHOST_WindowCocoa::getValid() const
+{
+ bool valid;
+ if (!m_fullScreen) {
+ valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef);
+ }
+ else {
+ valid = true;
+ }
+ return valid;
+}
+
+
+void GHOST_WindowCocoa::setTitle(const STR_String& title)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];
+
+ //Set associated file if applicable
+ if ([windowTitle hasPrefix:@"Blender"])
+ {
+ NSRange fileStrRange;
+ NSString *associatedFileName;
+ int len;
+
+ fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;
+ len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;
+
+ if (len >0)
+ {
+ fileStrRange.length = len;
+ associatedFileName = [windowTitle substringWithRange:fileStrRange];
+ @try {
+ [m_window setRepresentedFilename:associatedFileName];
+ }
+ @catch (NSException * e) {
+ printf("\nInvalid file path given in window title");
+ }
+ [m_window setTitle:[associatedFileName lastPathComponent]];
+ }
+ else {
+ [m_window setTitle:windowTitle];
+ [m_window setRepresentedFilename:@""];
+ }
+
+ } else {
+ [m_window setTitle:windowTitle];
+ [m_window setRepresentedFilename:@""];
+ }
+
+
+ [windowTitle release];
+ [pool drain];
+}
+
+
+void GHOST_WindowCocoa::getTitle(STR_String& title) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSString *windowTitle = [m_window title];
+
+ if (windowTitle != nil) {
+ title = [windowTitle UTF8String];
+ }
+
+ [pool drain];
+}
+
+
+void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
+{
+ NSRect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSRect screenSize = [[m_window screen] visibleFrame];
+
+ rect = [m_window frame];
+
+ bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);
+ bounds.m_l = rect.origin.x -screenSize.origin.x;
+ bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;
+ bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);
+
+ [pool drain];
+}
+
+
+void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
+{
+ NSRect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (!m_fullScreen)
+ {
+ NSRect screenSize = [[m_window screen] visibleFrame];
+
+ //Max window contents as screen size (excluding title bar...)
+ NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
+
+ rect = [m_window contentRectForFrameRect:[m_window frame]];
+
+ bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);
+ bounds.m_l = rect.origin.x -contentRect.origin.x;
+ bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;
+ bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);
+ }
+ else {
+ NSRect screenSize = [[m_window screen] frame];
+
+ bounds.m_b = screenSize.origin.y + screenSize.size.height;
+ bounds.m_l = screenSize.origin.x;
+ bounds.m_r = screenSize.origin.x + screenSize.size.width;
+ bounds.m_t = screenSize.origin.y;
+ }
+ [pool drain];
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (((GHOST_TUns32)cBnds.getWidth()) != width) {
+ NSSize size;
+ size.width=width;
+ size.height=cBnds.getHeight();
+ [m_window setContentSize:size];
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (((GHOST_TUns32)cBnds.getHeight()) != height) {
+ NSSize size;
+ size.width=cBnds.getWidth();
+ size.height=height;
+ [m_window setContentSize:size];
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
+ (((GHOST_TUns32)cBnds.getHeight()) != height)) {
+ NSSize size;
+ size.width=width;
+ size.height=height;
+ [m_window setContentSize:size];
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TWindowState GHOST_WindowCocoa::getState() const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ GHOST_TWindowState state;
+ if (m_fullScreen) {
+ state = GHOST_kWindowStateFullScreen;
+ }
+ else if ([m_window isMiniaturized]) {
+ state = GHOST_kWindowStateMinimized;
+ }
+ else if ([m_window isZoomed]) {
+ state = GHOST_kWindowStateMaximized;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
+ [pool drain];
+ return state;
+}
+
+
+void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
+
+ NSPoint screenCoord;
+ NSPoint baseCoord;
+
+ screenCoord.x = inX;
+ screenCoord.y = inY;
+
+ baseCoord = [m_window convertScreenToBase:screenCoord];
+
+ outX = baseCoord.x;
+ outY = baseCoord.y;
+}
+
+
+void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
+
+ NSPoint screenCoord;
+ NSPoint baseCoord;
+
+ baseCoord.x = inX;
+ baseCoord.y = inY;
+
+ screenCoord = [m_window convertBaseToScreen:baseCoord];
+
+ outX = screenCoord.x;
+ outY = screenCoord.y;
+}
+
+/**
+ * @note Fullscreen switch is not actual fullscreen with display capture. As this capture removes all OS X window manager features.
+ * Instead, the menu bar and the dock are hidden, and the window is made borderless and enlarged.
+ * Thus, process switch, exposé, spaces, ... still work in fullscreen mode
+ */
+GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
+ switch (state) {
+ case GHOST_kWindowStateMinimized:
+ [m_window miniaturize:nil];
+ break;
+ case GHOST_kWindowStateMaximized:
+ [m_window zoom:nil];
+ break;
+
+ case GHOST_kWindowStateFullScreen:
+ if (!m_fullScreen)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ //This status change needs to be done before Cocoa call to enter fullscreen mode
+ //to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference
+ m_fullScreen = true;
+
+#ifdef MAC_OS_X_VERSION_10_6
+ //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style
+ //Hide menu & dock if needed
+ if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+ {
+ [NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
+ }
+ //Make window borderless and enlarge it
+ [m_window setStyleMask:NSBorderlessWindowMask];
+ [m_window setFrame:[[m_window screen] frame] display:YES];
+#else
+ //With 10.5, we need to create a new window to change its style to borderless
+ //Hide menu & dock if needed
+ if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+ {
+ //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:NO];
+ //One of the very few 64bit compatible Carbon function
+ SetSystemUIMode(kUIModeAllHidden,kUIOptionAutoShowMenuBar);
+ }
+ //Create a fullscreen borderless window
+ CocoaWindow *tmpWindow = [[CocoaWindow alloc]
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ //Copy current window parameters
+ [tmpWindow setTitle:[m_window title]];
+ [tmpWindow setRepresentedFilename:[m_window representedFilename]];
+ [tmpWindow setReleasedWhenClosed:NO];
+ [tmpWindow setAcceptsMouseMovedEvents:YES];
+ [tmpWindow setDelegate:[m_window delegate]];
+
+ //Assign the openGL view to the new window
+ [tmpWindow setContentView:m_openGLView];
+
+ //Show the new window
+ [tmpWindow makeKeyAndOrderFront:nil];
+ //Close and release old window
+ [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
+ [m_window close];
+ [m_window release];
+ m_window = tmpWindow;
+#endif
+
+ //Tell WM of view new size
+ m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
+
+ [pool drain];
+ }
+ break;
+ case GHOST_kWindowStateNormal:
+ default:
+ if (m_fullScreen)
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ m_fullScreen = false;
+
+ //Exit fullscreen
+#ifdef MAC_OS_X_VERSION_10_6
+ //Show again menu & dock if needed
+ if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+ {
+ [NSApp setPresentationOptions:NSApplicationPresentationDefault];
+ }
+ //Make window normal and resize it
+ [m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
+ [m_window setFrame:[[m_window screen] visibleFrame] display:YES];
+#else
+ //With 10.5, we need to create a new window to change its style to borderless
+ //Show menu & dock if needed
+ if ([[m_window screen] isEqual:[NSScreen mainScreen]])
+ {
+ //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:YES];
+ SetSystemUIMode(kUIModeNormal, 0); //One of the very few 64bit compatible Carbon function
+ }
+ //Create a fullscreen borderless window
+ CocoaWindow *tmpWindow = [[CocoaWindow alloc]
+ initWithContentRect:[[m_window screen] frame]
+ styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ //Copy current window parameters
+ [tmpWindow setTitle:[m_window title]];
+ [tmpWindow setRepresentedFilename:[m_window representedFilename]];
+ [tmpWindow setReleasedWhenClosed:NO];
+ [tmpWindow setAcceptsMouseMovedEvents:YES];
+ [tmpWindow setDelegate:[m_window delegate]];
+
+ //Assign the openGL view to the new window
+ [tmpWindow setContentView:m_openGLView];
+
+ //Show the new window
+ [tmpWindow makeKeyAndOrderFront:nil];
+ //Close and release old window
+ [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
+ [m_window close];
+ [m_window release];
+ m_window = tmpWindow;
+#endif
+
+ //Tell WM of view new size
+ m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
+
+ [pool drain];
+ }
+ else if ([m_window isMiniaturized])
+ [m_window deminiaturize:nil];
+ else if ([m_window isZoomed])
+ [m_window zoom:nil];
+ break;
+ }
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [m_window setDocumentEdited:isUnsavedChanges];
+
+ [pool drain];
+ return GHOST_Window::setModifiedState(isUnsavedChanges);
+}
+
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
+ if (order == GHOST_kWindowOrderTop) {
+ [m_window orderFront:nil];
+ }
+ else {
+ [m_window orderBack:nil];
+ }
+ return GHOST_kSuccess;
+}
+
+#pragma mark Drawing context
+
+/*#define WAIT_FOR_VSYNC 1*/
+
+GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
+{
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext flushBuffer];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ }
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
+{
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext update];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ }
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
+{
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLContext makeCurrentContext];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ }
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSOpenGLPixelFormat *pixelFormat;
+ NSOpenGLContext *tmpOpenGLContext;
+
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ if (!getValid()) break;
+
+ pixelFormat = [m_openGLView pixelFormat];
+ tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+ shareContext:s_firstOpenGLcontext];
+ if (tmpOpenGLContext == nil) {
+ success = GHOST_kFailure;
+ break;
+ }
+
+ if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
+#ifdef WAIT_FOR_VSYNC
+ /* wait for vsync, to avoid tearing artifacts */
+ [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval];
+#endif
+ [m_openGLView setOpenGLContext:tmpOpenGLContext];
+ [tmpOpenGLContext setView:m_openGLView];
+
+ m_openGLContext = tmpOpenGLContext;
+ break;
+
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+
+ default:
+ break;
+ }
+ [pool drain];
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ switch (m_drawingContextType) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ if (m_openGLContext)
+ {
+ [m_openGLView clearGLContext];
+ if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil;
+ m_openGLContext = nil;
+ }
+ [pool drain];
+ return GHOST_kSuccess;
+ case GHOST_kDrawingContextTypeNone:
+ [pool drain];
+ return GHOST_kSuccess;
+ break;
+ default:
+ [pool drain];
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::invalidate()
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [m_openGLView setNeedsDisplay:YES];
+ [pool drain];
+ return GHOST_kSuccess;
+}
+
+#pragma mark Cursor handling
+
+void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
+{
+ static bool systemCursorVisible = true;
+
+ NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
+
+ NSCursor *tmpCursor =nil;
+
+ if (visible != systemCursorVisible) {
+ if (visible) {
+ [NSCursor unhide];
+ systemCursorVisible = true;
+ }
+ else {
+ [NSCursor hide];
+ systemCursorVisible = false;
+ }
+ }
+
+ if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
+ tmpCursor = m_customCursor;
+ } else {
+ switch (cursor) {
+ case GHOST_kStandardCursorDestroy:
+ tmpCursor = [NSCursor disappearingItemCursor];
+ break;
+ case GHOST_kStandardCursorText:
+ tmpCursor = [NSCursor IBeamCursor];
+ break;
+ case GHOST_kStandardCursorCrosshair:
+ tmpCursor = [NSCursor crosshairCursor];
+ break;
+ case GHOST_kStandardCursorUpDown:
+ tmpCursor = [NSCursor resizeUpDownCursor];
+ break;
+ case GHOST_kStandardCursorLeftRight:
+ tmpCursor = [NSCursor resizeLeftRightCursor];
+ break;
+ case GHOST_kStandardCursorTopSide:
+ tmpCursor = [NSCursor resizeUpCursor];
+ break;
+ case GHOST_kStandardCursorBottomSide:
+ tmpCursor = [NSCursor resizeDownCursor];
+ break;
+ case GHOST_kStandardCursorLeftSide:
+ tmpCursor = [NSCursor resizeLeftCursor];
+ break;
+ case GHOST_kStandardCursorRightSide:
+ tmpCursor = [NSCursor resizeRightCursor];
+ break;
+ case GHOST_kStandardCursorRightArrow:
+ case GHOST_kStandardCursorInfo:
+ case GHOST_kStandardCursorLeftArrow:
+ case GHOST_kStandardCursorHelp:
+ case GHOST_kStandardCursorCycle:
+ case GHOST_kStandardCursorSpray:
+ case GHOST_kStandardCursorWait:
+ case GHOST_kStandardCursorTopLeftCorner:
+ case GHOST_kStandardCursorTopRightCorner:
+ case GHOST_kStandardCursorBottomRightCorner:
+ case GHOST_kStandardCursorBottomLeftCorner:
+ case GHOST_kStandardCursorDefault:
+ default:
+ tmpCursor = [NSCursor arrowCursor];
+ break;
+ };
+ }
+ [tmpCursor set];
+ [pool drain];
+}
+
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
+{
+ if ([m_window isVisible]) {
+ loadCursor(visible, getCursorShape());
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+//Override this method to provide set feature even if not in warp
+inline bool GHOST_WindowCocoa::setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y)
+{
+ m_cursorWarpAccumPos[0]= x;
+ m_cursorWarpAccumPos[1]= y;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
+{
+ if (grab)
+ {
+ //No need to perform grab without warp as it is always on in OS X
+ if(warp) {
+ GHOST_TInt32 x_old,y_old;
+
+ m_cursorWarp= true;
+ m_systemCocoa->getCursorPosition(x_old,y_old);
+ screenToClient(x_old, y_old, m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+ //Warp position is stored in client (window base) coordinates
+ setWindowCursorVisibility(false);
+ return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ }
+ else {
+ if(m_cursorWarp)
+ {/* are we exiting warp */
+ setWindowCursorVisibility(true);
+ /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
+ if(restore) {
+ GHOST_Rect bounds;
+ GHOST_TInt32 x_new, y_new, x_cur, y_cur;
+
+ getClientBounds(bounds);
+ x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
+ y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
+
+ if(x_new < 0) x_new = 0;
+ if(y_new < 0) y_new = 0;
+ if(x_new > bounds.getWidth()) x_new = bounds.getWidth();
+ if(y_new > bounds.getHeight()) y_new = bounds.getHeight();
+
+ //get/set cursor position works in screen coordinates
+ clientToScreen(x_new, y_new, x_cur, y_cur);
+ m_systemCocoa->setCursorPosition(x_cur, y_cur);
+
+ //As Cocoa will give as first deltaX,deltaY this change in cursor position, we need to compensate for it
+ //Issue appearing in case of two transform operations conducted w/o mouse motion in between
+ x_new=m_cursorWarpAccumPos[0];
+ y_new=m_cursorWarpAccumPos[1];
+ setCursorWarpAccum(-x_new, -y_new);
+ }
+ else {
+ GHOST_TInt32 x_new, y_new;
+ //get/set cursor position works in screen coordinates
+ clientToScreen(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1], x_new, y_new);
+ m_systemCocoa->setCursorPosition(x_new, y_new);
+ setCursorWarpAccum(0, 0);
+ }
+
+ m_cursorWarp= false;
+ return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ }
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
+{
+ if (m_customCursor) {
+ [m_customCursor release];
+ m_customCursor = nil;
+ }
+
+ if ([m_window isVisible]) {
+ loadCursor(getCursorVisibility(), shape);
+ }
+
+ return GHOST_kSuccess;
+}
+
+/** Reverse the bits in a GHOST_TUns8
+static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
+{
+ ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
+ ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC);
+ ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
+ return ch;
+}
+*/
+
+
+/** Reverse the bits in a GHOST_TUns16 */
+static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
+{
+ shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA);
+ shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC);
+ shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0);
+ shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00);
+ return shrt;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
+ int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
+{
+ int y,nbUns16;
+ NSPoint hotSpotPoint;
+ NSBitmapImageRep *cursorImageRep;
+ NSImage *cursorImage;
+ NSSize imSize;
+ GHOST_TUns16 *cursorBitmap;
+
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (m_customCursor) {
+ [m_customCursor release];
+ m_customCursor = nil;
+ }
+
+
+ cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+ pixelsWide:sizex
+ pixelsHigh:sizey
+ bitsPerSample:1
+ samplesPerPixel:2
+ hasAlpha:YES
+ isPlanar:YES
+ colorSpaceName:NSDeviceBlackColorSpace
+ bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
+ bitsPerPixel:1];
+
+
+ cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
+ nbUns16 = [cursorImageRep bytesPerPlane]/2;
+
+ for (y=0; y<nbUns16; y++) {
+#if !defined(__LITTLE_ENDIAN__)
+ cursorBitmap[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
+ cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
+#else
+ cursorBitmap[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
+ cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
+#endif
+
+ }
+
+
+ imSize.width = sizex;
+ imSize.height= sizey;
+ cursorImage = [[NSImage alloc] initWithSize:imSize];
+ [cursorImage addRepresentation:cursorImageRep];
+
+ hotSpotPoint.x = hotX;
+ hotSpotPoint.y = hotY;
+
+ //foreground and background color parameter is not handled for now (10.6)
+ m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
+ hotSpot:hotSpotPoint];
+
+ [cursorImageRep release];
+ [cursorImage release];
+
+ if ([m_window isVisible]) {
+ loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
+ }
+ [pool drain];
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2], int hotX, int hotY)
+{
+ return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
+}
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 9e3927314d3..60e93ad4bee 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -72,7 +72,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. */
@@ -128,6 +132,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/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index ca7f2a4d506..fca87af5dc3 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/intern/guardedalloc/make/msvc_9_0/guardedalloc.vcproj b/intern/guardedalloc/make/msvc_9_0/guardedalloc.vcproj
index 16deb7b71fa..d59b80f7b62 100644
--- a/intern/guardedalloc/make/msvc_9_0/guardedalloc.vcproj
+++ b/intern/guardedalloc/make/msvc_9_0/guardedalloc.vcproj
@@ -42,7 +42,6 @@
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\.."
PreprocessorDefinitions="WIN32,NDEBUG,_LIB"
diff --git a/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj b/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj
new file mode 100644
index 00000000000..ce158680a25
--- /dev/null
+++ b/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="BL_bmesh"
+ ProjectGUID="{6A51010A-9393-4D77-84B4-5BBCDA6E7C25}"
+ RootNamespace="BL_bmesh"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\editors\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <ProjectReference
+ ReferencedProjectIdentifier="{31628053-825D-4C06-8A21-D13883489718}"
+ RelativePathToProject=".\blenlib\BLI_blenlib.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}"
+ RelativePathToProject=".\blenkernel\BKE_blenkernel.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{E013786A-9575-4F34-81B2-33290357EE87}"
+ RelativePathToProject=".\makesdna\DNA_makesdna.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{1CC733F1-6AB5-4904-8F63-C08C46B79DD9}"
+ RelativePathToProject="..\..\intern\guardedalloc\make\msvc_9_0\guardedalloc.vcproj"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_construct.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\bmesh_dupeops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_eulers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_filters.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_interp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_iterators.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_marking.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_mesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_mods.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_opdefines.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_polygon.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_queries.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_to_editmesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_walkers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\connectops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\createops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\dissolveops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\edgesplitop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\editmesh_to_bmesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\extrudeops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\mesh_conv.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\mirror.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\removedoubles.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\subdivideop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\triangulateop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\utils.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_error.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_filters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_iterators.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_marking.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_operator_api.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_operators.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_queries.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_walkers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\editmesh_tools.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
index 6137696fc59..9757c60f597 100644
--- a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
+++ b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="BPY_python"
ProjectGUID="{5A2EA6DC-1A53-4E87-9166-52870CE3B4EA}"
RootNamespace="BPY_python"
diff --git a/projectfiles_vc9/blender/blender.sln b/projectfiles_vc9/blender/blender.sln
index 936e444ed12..c85103c62ce 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
{02110D03-59DB-4571-8787-72B3C03B2F2D} = {02110D03-59DB-4571-8787-72B3C03B2F2D}
@@ -9,7 +9,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{FB88301F-F725-401B-ACD7-D2ABBF333B71} = {FB88301F-F725-401B-ACD7-D2ABBF333B71}
{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}
{79D0B232-208C-F208-DA71-79B4AC088602} = {79D0B232-208C-F208-DA71-79B4AC088602}
{E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}
@@ -298,6 +297,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
@@ -316,7 +343,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
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INT_itasc", "..\..\intern\itasc\make\msvc_9_0\itasc.vcproj", "{59567A5B-F63A-4A5C-B33A-0A45C300F4DC}"
EndProject
diff --git a/projectfiles_vc9/blender/blender.vcproj b/projectfiles_vc9/blender/blender.vcproj
index d6f29788f9d..f508909c751 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"
@@ -260,6 +260,10 @@
Filter="h;hpp;hxx;hm;inl"
>
</Filter>
+ <Filter
+ Name="Source Files"
+ >
+ </Filter>
</Files>
<Globals>
</Globals>
diff --git a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
index 3f17da1ddab..f272a6711db 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"
@@ -468,6 +468,14 @@
</Configuration>
</Configurations>
<References>
+ <ProjectReference
+ ReferencedProjectIdentifier="{31628053-825D-4C06-8A21-D13883489718}"
+ RelativePathToProject=".\blenlib\BLI_blenlib.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{E013786A-9575-4F34-81B2-33290357EE87}"
+ RelativePathToProject=".\makesdna\DNA_makesdna.vcproj"
+ />
</References>
<Files>
<Filter
@@ -599,6 +607,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenkernel\intern\editderivedbmesh.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenkernel\intern\effect.c"
>
</File>
@@ -679,6 +691,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenkernel\intern\modifiers_bmesh.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenkernel\intern\multires.c"
>
</File>
@@ -1096,6 +1112,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/blenlib/BLI_blenlib.vcproj b/projectfiles_vc9/blender/blenlib/BLI_blenlib.vcproj
index b883d8bf2b2..0f4749d73ae 100644
--- a/projectfiles_vc9/blender/blenlib/BLI_blenlib.vcproj
+++ b/projectfiles_vc9/blender/blenlib/BLI_blenlib.vcproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="BLI_blenlib"
ProjectGUID="{31628053-825D-4C06-8A21-D13883489718}"
RootNamespace="BLI_blenlib"
@@ -484,6 +484,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenlib\intern\BLI_cellalloc.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenlib\intern\BLI_bfile.c"
>
</File>
@@ -625,6 +629,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenlib\BLI_array.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenlib\BLI_bfile.h"
>
</File>
@@ -645,6 +653,10 @@
>
</File>
<File
+ RelativePath="..\..\..\source\blender\blenlib\BLI_cellalloc.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenlib\BLI_dlrbTree.h"
>
</File>
diff --git a/projectfiles_vc9/blender/editors/ED_editors.vcproj b/projectfiles_vc9/blender/editors/ED_editors.vcproj
index c49e817196e..593a84ccad6 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"
@@ -1188,6 +1188,30 @@
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\editbmesh_bvh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_bvh.h"
+ >
+ </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 631c5dc2693..25e9a932d28 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"
@@ -707,6 +707,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/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/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/io/add_mesh_torus.py b/release/scripts/io/add_mesh_torus.py
deleted file mode 100644
index a0f41db15d6..00000000000
--- a/release/scripts/io/add_mesh_torus.py
+++ /dev/null
@@ -1,98 +0,0 @@
-
-import bpy, Mathutils
-from math import cos, sin, pi, radians
-
-
-def add_torus(PREF_MAJOR_RAD, PREF_MINOR_RAD, PREF_MAJOR_SEG, PREF_MINOR_SEG):
- Vector = Mathutils.Vector
- Quaternion = Mathutils.Quaternion
-
- PI_2= pi*2
- Z_AXIS = 0,0,1
-
- verts = []
- faces = []
- i1 = 0
- tot_verts = PREF_MAJOR_SEG * PREF_MINOR_SEG
- for major_index in range(PREF_MAJOR_SEG):
- verts_tmp = []
- quat = Quaternion( Z_AXIS, (major_index/PREF_MAJOR_SEG)*PI_2)
-
- for minor_index in range(PREF_MINOR_SEG):
- angle = 2*pi*minor_index/PREF_MINOR_SEG
-
- vec = Vector(PREF_MAJOR_RAD+(cos(angle)*PREF_MINOR_RAD), 0, (sin(angle)*PREF_MINOR_RAD)) * quat
- verts.extend([vec.x, vec.y, vec.z])
-
- if minor_index+1==PREF_MINOR_SEG:
- i2 = (major_index)*PREF_MINOR_SEG
- i3 = i1 + PREF_MINOR_SEG
- i4 = i2 + PREF_MINOR_SEG
-
- else:
- i2 = i1 + 1
- i3 = i1 + PREF_MINOR_SEG
- i4 = i3 + 1
-
- if i2>=tot_verts: i2 = i2-tot_verts
- if i3>=tot_verts: i3 = i3-tot_verts
- if i4>=tot_verts: i4 = i4-tot_verts
-
- # stupid eekadoodle
- if i2: faces.extend( [i1,i3,i4,i2] )
- else: faces.extend( [i2,i1,i3,i4] )
-
- i1+=1
-
- return verts, faces
-
-
-class MESH_OT_primitive_torus_add(bpy.types.Operator):
- '''Add a torus mesh.'''
- __idname__ = "mesh.primitive_torus_add"
- __label__ = "Add Torus"
- __register__ = True
- __undo__ = True
- __props__ = [
- bpy.props.FloatProperty(attr="major_radius", name="Major Radius", description="Number of segments for the main ring of the torus", default= 1.0, min= 0.01, max= 100.0),
- bpy.props.FloatProperty(attr="minor_radius", name="Minor Radius", description="Number of segments for the minor ring of the torus", default= 0.25, min= 0.01, max= 100.0),
- bpy.props.IntProperty(attr="major_segments", name="Major Segments", description="Number of segments for the main ring of the torus", default= 48, min= 3, max= 256),
- bpy.props.IntProperty(attr="minor_segments", name="Minor Segments", description="Number of segments for the minor ring of the torus", default= 16, min= 3, max= 256),
- ]
-
- def execute(self, context):
- verts_loc, faces = add_torus(self.major_radius, self.minor_radius, self.major_segments, self.minor_segments)
-
- me= bpy.data.add_mesh("Torus")
-
- me.add_geometry(int(len(verts_loc)/3), 0, int(len(faces)/4))
- me.verts.foreach_set("co", verts_loc)
- me.faces.foreach_set("verts_raw", faces)
-
- sce = context.scene
-
- # ugh
- for ob in sce.objects:
- ob.selected = False
-
- me.update()
- ob= bpy.data.add_object('MESH', "Torus")
- ob.data= me
- context.scene.add_object(ob)
- context.scene.active_object = ob
- ob.selected = True
-
- ob.location = tuple(context.scene.cursor_location)
-
- return ('FINISHED',)
-
-# Register the operator
-bpy.ops.add(MESH_OT_primitive_torus_add)
-
-# Add to a menu
-import dynamic_menu
-import space_info
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_mesh_add, (lambda self, context: self.layout.itemO("mesh.primitive_torus_add", text="Add Torus")) )
-
-if __name__ == "__main__":
- bpy.ops.mesh.primitive_torus_add() \ No newline at end of file
diff --git a/release/scripts/io/engine_render_pov.py b/release/scripts/io/engine_render_pov.py
index f69c8a267e0..f0247ce532a 100644
--- a/release/scripts/io/engine_render_pov.py
+++ b/release/scripts/io/engine_render_pov.py
@@ -826,12 +826,12 @@ class PovrayRender(bpy.types.RenderEngine):
bpy.types.register(PovrayRender)
# Use some of the existing buttons.
-import buttons_render
-buttons_render.RENDER_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
-buttons_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
-buttons_render.RENDER_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
-buttons_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
-del buttons_render
+import buttons_scene
+buttons_scene.SCENE_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
+buttons_scene.SCENE_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
+buttons_scene.SCENE_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
+buttons_scene.SCENE_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
+del buttons_scene
# Use only a subset of the world panels
import buttons_world
@@ -852,14 +852,14 @@ del buttons_material
class RenderButtonsPanel(bpy.types.Panel):
__space_type__ = 'PROPERTIES'
__region_type__ = 'WINDOW'
- __context__ = "render"
+ __context__ = "scene"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
rd = context.scene.render_data
return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
-class RENDER_PT_povray_radiosity(RenderButtonsPanel):
+class SCENE_PT_povray_radiosity(RenderButtonsPanel):
__label__ = "Radiosity"
COMPAT_ENGINES = set(['POVRAY_RENDER'])
@@ -909,4 +909,4 @@ class RENDER_PT_povray_radiosity(RenderButtonsPanel):
col = split.column()
col.itemR(scene, "pov_radio_always_sample")
-bpy.types.register(RENDER_PT_povray_radiosity)
+bpy.types.register(SCENE_PT_povray_radiosity)
diff --git a/release/scripts/io/export_3ds.py b/release/scripts/io/export_3ds.py
index 5ca7d5629d5..2c1999c3d45 100644
--- a/release/scripts/io/export_3ds.py
+++ b/release/scripts/io/export_3ds.py
@@ -1,4 +1,12 @@
+#!BPY
# coding: utf-8
+"""
+Name: '3D Studio (.3ds)...'
+Blender: 243
+Group: 'Export'
+Tooltip: 'Export to 3DS file format (.3ds).'
+"""
+
__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"]
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
__version__ = "0.90a"
@@ -1092,7 +1100,9 @@ def save_3ds(filename, context):
# # save_3ds('/test_b.3ds')
class EXPORT_OT_3ds(bpy.types.Operator):
- '''Export to 3DS file format (.3ds).'''
+ '''
+ 3DS Exporter
+ '''
__idname__ = "export.3ds"
__label__ = 'Export 3DS'
@@ -1118,8 +1128,3 @@ class EXPORT_OT_3ds(bpy.types.Operator):
return context.active_object != None
bpy.ops.add(EXPORT_OT_3ds)
-
-# Add to a menu
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.3ds", text="Autodesk 3DS...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
diff --git a/release/scripts/io/export_fbx.py b/release/scripts/io/export_fbx.py
index d159c6588e5..21b1388ebfe 100644
--- a/release/scripts/io/export_fbx.py
+++ b/release/scripts/io/export_fbx.py
@@ -1,3 +1,10 @@
+#!BPY
+"""
+Name: 'Autodesk FBX (.fbx)...'
+Blender: 249
+Group: 'Export'
+Tooltip: 'Selection to an ASCII Autodesk FBX '
+"""
__author__ = "Campbell Barton"
__url__ = ['www.blender.org', 'blenderartists.org']
__version__ = "1.2"
@@ -3334,7 +3341,9 @@ def write_ui():
# GLOBALS.clear()
class EXPORT_OT_fbx(bpy.types.Operator):
- '''Selection to an ASCII Autodesk FBX'''
+ '''
+ Operator documentation text, will be used for the operator tooltip and python docs.
+ '''
__idname__ = "export.fbx"
__label__ = "Export FBX"
@@ -3442,10 +3451,3 @@ bpy.ops.add(EXPORT_OT_fbx)
# SMALL or COSMETICAL
# - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
-
-
-# Add to a menu
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.fbx", text="Autodesk FBX...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
diff --git a/release/scripts/io/export_mdd.py b/release/scripts/io/export_mdd.py
deleted file mode 100644
index 1336660aefc..00000000000
--- a/release/scripts/io/export_mdd.py
+++ /dev/null
@@ -1,184 +0,0 @@
-
-__author__ = "Bill L.Nieuwendorp"
-__bpydoc__ = """\
-This script Exports Lightwaves MotionDesigner format.
-
-The .mdd format has become quite a popular Pipeline format<br>
-for moving animations from package to package.
-
-Be sure not to use modifiers that change the number or order of verts in the mesh
-"""
-#Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com
-#Bill Niewuendorp
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-import bpy
-import Mathutils
-import math
-import os
-
-#import Blender
-#from Blender import *
-#import BPyMessages
-try:
- from struct import pack
-except:
- pack = None
-
-def zero_file(filepath):
- '''
- If a file fails, this replaces it with 1 char, better not remove it?
- '''
- file = open(filepath, 'w')
- file.write('\n') # apparently macosx needs some data in a blank file?
- file.close()
-
-def check_vertcount(mesh,vertcount):
- '''
- check and make sure the vertcount is consistent throughout the frame range
- '''
- if len(mesh.verts) != vertcount:
- raise Exception('Error, number of verts has changed during animation, cannot export')
- f.close()
- zero_file(filepath)
- return
-
-
-def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
- if not pack:
- raise Exception('Error, this script requires the "pack" module')
-
- if ob.type != 'MESH':
- raise Exception('Error, active object is not a mesh')
- """
- Window.EditMode(0)
- Blender.Window.WaitCursor(1)
-
- mesh_orig = Mesh.New()
- mesh_orig.getFromObject(ob.name)
- """
- orig_frame = sce.current_frame
- sce.set_frame(PREF_STARTFRAME)
- me = ob.create_mesh(True, 'PREVIEW')
-
- #Flip y and z
- mat_flip= Mathutils.Matrix(\
- [1.0, 0.0, 0.0, 0.0],\
- [0.0, 0.0, 1.0, 0.0],\
- [0.0, 1.0, 0.0, 0.0],\
- [0.0, 0.0, 0.0, 1.0],\
- )
-
- numverts = len(me.verts)
-
- numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
- PREF_FPS= float(PREF_FPS)
- f = open(filename, 'wb') #no Errors yet:Safe to create file
-
- # Write the header
- f.write(pack(">2i", numframes, numverts))
-
- # Write the frame times (should we use the time IPO??)
- f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
-
- #rest frame needed to keep frames in sync
- """
- Blender.Set('curframe', PREF_STARTFRAME)
- me_tmp.getFromObject(ob.name)
- """
-
- check_vertcount(me,numverts)
- me.transform(mat_flip * ob.matrix)
- f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
-
- for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
- """
- Blender.Set('curframe', frame)
- me_tmp.getFromObject(ob.name)
- """
-
- sce.set_frame(frame)
- me = ob.create_mesh(True, 'PREVIEW')
- check_vertcount(me,numverts)
- me.transform(mat_flip * ob.matrix)
-
- # Write the vertex data
- f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
-
- """
- me_tmp.verts= None
- """
- f.close()
-
- print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
- """
- Blender.Window.WaitCursor(0)
- Blender.Set('curframe', orig_frame)
- """
- sce.set_frame(orig_frame)
-
-class EXPORT_OT_mdd(bpy.types.Operator):
- '''Animated mesh to MDD vertex keyframe file.'''
- __idname__ = "export.mdd"
- __label__ = "Export MDD"
-
- # get first scene to get min and max properties for frames, fps
-
- sce = bpy.data.scenes[bpy.data.scenes.keys()[0]]
- minframe = sce.rna_type.properties["current_frame"].soft_min
- maxframe = sce.rna_type.properties["current_frame"].soft_max
- minfps = sce.render_data.rna_type.properties["fps"].soft_min
- maxfps = sce.render_data.rna_type.properties["fps"].soft_max
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- __props__ = [
- bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd"),
- bpy.props.IntProperty(attr="fps", name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25),
- bpy.props.IntProperty(attr="start_frame", name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1),
- bpy.props.IntProperty(attr="end_frame", name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250),
- ]
-
- def poll(self, context):
- return context.active_object != None
-
- def execute(self, context):
- if not self.path:
- raise Exception("filename not set")
- write(self.path, context.scene, context.active_object,
- self.start_frame, self.end_frame, self.fps )
- return ('FINISHED',)
-
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self.__operator__)
- return ('RUNNING_MODAL',)
-
-bpy.ops.add(EXPORT_OT_mdd)
-
-# Add to a menu
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.mdd", text="Vertex Keyframe Animation (.mdd)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
-if __name__=='__main__':
- #if not pack:
-# Draw.PupMenu('Error%t|This script requires a full python install')
- #Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
- bpy.ops.EXPORT_OT_mdd(path="/tmp/test.mdd")
diff --git a/release/scripts/io/export_obj.py b/release/scripts/io/export_obj.py
index 1e8a152e91f..83b400816e3 100644
--- a/release/scripts/io/export_obj.py
+++ b/release/scripts/io/export_obj.py
@@ -906,16 +906,14 @@ def do_export(filename, context,
# orig_scene.makeCurrent()
# Window.WaitCursor(0)
-
-'''
-Currently the exporter lacks these features:
-* nurbs
-* multiple scene export (only active scene is written)
-* particles
-'''
+
class EXPORT_OT_obj(bpy.types.Operator):
- '''Save a Wavefront OBJ File'''
-
+ '''
+ Currently the exporter lacks these features:
+ * nurbs
+ * multiple scene export (only active scene is written)
+ * particles
+ '''
__idname__ = "export.obj"
__label__ = 'Export OBJ'
@@ -986,10 +984,6 @@ class EXPORT_OT_obj(bpy.types.Operator):
bpy.ops.add(EXPORT_OT_obj)
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.obj", text="Wavefront (.obj)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
if __name__ == "__main__":
bpy.ops.EXPORT_OT_obj(filename="/tmp/test.obj")
diff --git a/release/scripts/io/export_ply.py b/release/scripts/io/export_ply.py
index d74cc0e9d7e..8e79c3741bb 100644
--- a/release/scripts/io/export_ply.py
+++ b/release/scripts/io/export_ply.py
@@ -273,9 +273,7 @@ class EXPORT_OT_ply(bpy.types.Operator):
bpy.ops.add(EXPORT_OT_ply)
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.ply", text="Stanford (.ply)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
if __name__ == "__main__":
bpy.ops.EXPORT_OT_ply(path="/tmp/test.ply")
+
+
diff --git a/release/scripts/io/export_x3d.py b/release/scripts/io/export_x3d.py
index 2c6ca749757..db29afc7d6d 100644
--- a/release/scripts/io/export_x3d.py
+++ b/release/scripts/io/export_x3d.py
@@ -1,3 +1,10 @@
+#!BPY
+""" Registration info for Blender menus:
+Name: 'X3D Extensible 3D (.x3d)...'
+Blender: 245
+Group: 'Export'
+Tooltip: 'Export selection to Extensible 3D file (.x3d)'
+"""
__author__ = ("Bart", "Campbell Barton")
__email__ = ["Bart, bart:neeneenee*de"]
@@ -1197,7 +1204,9 @@ def x3d_export_ui(filename):
# Blender.Window.FileSelector(x3d_export_ui,"Export X3D", Blender.Get('filename').replace('.blend', '.x3d'))
class EXPORT_OT_x3d(bpy.types.Operator):
- '''Export selection to Extensible 3D file (.x3d)'''
+ '''
+ X3D Exporter
+ '''
__idname__ = "export.x3d"
__label__ = 'Export X3D'
@@ -1220,12 +1229,12 @@ class EXPORT_OT_x3d(bpy.types.Operator):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
+
+ def poll(self, context): # Poll isnt working yet
+ print("Poll")
+ return context.active_object != None
bpy.ops.add(EXPORT_OT_x3d)
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.x3d", text="X3D Extensible 3D (.x3d)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
# NOTES
# - blender version is hardcoded
diff --git a/release/scripts/io/import_3ds.py b/release/scripts/io/import_3ds.py
index cbd9d8948ab..339fac839ea 100644
--- a/release/scripts/io/import_3ds.py
+++ b/release/scripts/io/import_3ds.py
@@ -1,3 +1,10 @@
+#!BPY
+"""
+Name: '3D Studio (.3ds)...'
+Blender: 244
+Group: 'Import'
+Tooltip: 'Import from 3DS file format (.3ds)'
+"""
__author__= ['Bob Holcomb', 'Richard L?rk?ng', 'Damien McGinnes', 'Campbell Barton', 'Mario Lapin']
__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/")
@@ -1123,7 +1130,9 @@ else:
'''
class IMPORT_OT_3ds(bpy.types.Operator):
- '''Import from 3DS file format (.3ds)'''
+ '''
+ 3DS Importer
+ '''
__idname__ = "import.3ds"
__label__ = 'Import 3DS'
@@ -1146,13 +1155,13 @@ class IMPORT_OT_3ds(bpy.types.Operator):
wm = context.manager
wm.add_fileselect(self.__operator__)
return ('RUNNING_MODAL',)
+ '''
+ def poll(self, context):
+ print("Poll")
+ return context.active_object != None'''
bpy.ops.add(IMPORT_OT_3ds)
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("import.3ds", text="3D Studio (.3ds)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
-
# NOTES:
# why add 1 extra vertex? and remove it when done?
# disabled scaling to size, this requires exposing bb (easy) and understanding how it works (needs some time)
diff --git a/release/scripts/io/import_obj.py b/release/scripts/io/import_obj.py
index a557e4427d8..a762005ae7d 100644
--- a/release/scripts/io/import_obj.py
+++ b/release/scripts/io/import_obj.py
@@ -1,3 +1,11 @@
+#!BPY
+
+"""
+Name: 'Wavefront (.obj)...'
+Blender: 249
+Group: 'Import'
+Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.'
+"""
__author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone"
__url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org']
@@ -1552,9 +1560,15 @@ else:
print 'TOTAL TIME: %.6f' % (sys.time() - TIME)
'''
+#load_obj('/test.obj')
+#load_obj('/fe/obj/mba1.obj')
+
+
class IMPORT_OT_obj(bpy.types.Operator):
- '''Load a Wavefront OBJ File.'''
+ '''
+ Operator documentation text, will be used for the operator tooltip and python docs.
+ '''
__idname__ = "import.obj"
__label__ = "Import OBJ"
@@ -1579,6 +1593,10 @@ class IMPORT_OT_obj(bpy.types.Operator):
bpy.props.BoolProperty(attr="IMAGE_SEARCH", name="Image Search", description="Search subdirs for any assosiated images (Warning, may be slow)", default= True),
]
+ '''
+ def poll(self, context):
+ return True '''
+
def execute(self, context):
# print("Selected: " + context.active_object.name)
@@ -1606,11 +1624,6 @@ class IMPORT_OT_obj(bpy.types.Operator):
bpy.ops.add(IMPORT_OT_obj)
-import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("import.obj", text="Wavefront (.obj)...")
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
-
-
# NOTES (all line numbers refer to 2.4x import_obj.py, not this file)
# check later: line 489
# can convert now: edge flags, edges: lines 508-528
diff --git a/release/scripts/io/mesh_skin.py b/release/scripts/io/mesh_skin.py
deleted file mode 100644
index f6fafc41111..00000000000
--- a/release/scripts/io/mesh_skin.py
+++ /dev/null
@@ -1,647 +0,0 @@
-# import Blender
-import time, functools
-import bpy
-# from Blender import Window
-from Mathutils import MidpointVecs, Vector
-from Mathutils import AngleBetweenVecs as _AngleBetweenVecs_
-# import BPyMessages
-
-# from Blender.Draw import PupMenu
-
-BIG_NUM = 1<<30
-
-global CULL_METHOD
-CULL_METHOD = 0
-
-def AngleBetweenVecs(a1,a2):
- import math
- try:
- return math.degrees(_AngleBetweenVecs_(a1,a2))
- except:
- return 180.0
-
-class edge(object):
- __slots__ = 'v1', 'v2', 'co1', 'co2', 'length', 'removed', 'match', 'cent', 'angle', 'next', 'prev', 'normal', 'fake'
- def __init__(self, v1,v2):
- self.v1 = v1
- self.v2 = v2
- co1, co2= v1.co, v2.co
- self.co1= co1
- self.co2= co2
-
- # uv1 uv2 vcol1 vcol2 # Add later
- self.length = (co1 - co2).length
- self.removed = 0 # Have we been culled from the eloop
- self.match = None # The other edge were making a face with
-
- self.cent= MidpointVecs(co1, co2)
- self.angle= 0.0
- self.fake= False
-
-class edgeLoop(object):
- __slots__ = 'centre', 'edges', 'normal', 'closed', 'backup_edges'
- def __init__(self, loop, me, closed): # Vert loop
- # Use next and prev, nextDist, prevDist
-
- # Get Loops centre.
- fac= len(loop)
- verts = me.verts
- self.centre= functools.reduce(lambda a,b: a+verts[b].co/fac, loop, Vector())
-
- # Convert Vert loop to Edges.
- self.edges = [edge(verts[loop[vIdx-1]], verts[loop[vIdx]]) for vIdx in range(len(loop))]
-
- if not closed:
- self.edges[0].fake = True # fake edge option
-
- self.closed = closed
-
-
- # Assign linked list
- for eIdx in range(len(self.edges)-1):
- self.edges[eIdx].next = self.edges[eIdx+1]
- self.edges[eIdx].prev = self.edges[eIdx-1]
- # Now last
- self.edges[-1].next = self.edges[0]
- self.edges[-1].prev = self.edges[-2]
-
-
-
- # GENERATE AN AVERAGE NORMAL FOR THE WHOLE LOOP.
- self.normal = Vector()
- for e in self.edges:
- n = (self.centre-e.co1).cross(self.centre-e.co2)
- # Do we realy need tot normalize?
- n.normalize()
- self.normal += n
-
- # Generate the angle
- va= e.cent - e.prev.cent
- vb= e.next.cent - e.cent
-
- e.angle= AngleBetweenVecs(va, vb)
-
- # Blur the angles
- #for e in self.edges:
- # e.angle= (e.angle+e.next.angle)/2
-
- # Blur the angles
- #for e in self.edges:
- # e.angle= (e.angle+e.prev.angle)/2
-
- self.normal.normalize()
-
- # Generate a normal for each edge.
- for e in self.edges:
-
- n1 = e.co1
- n2 = e.co2
- n3 = e.prev.co1
-
- a = n1-n2
- b = n1-n3
- normal1 = a.cross(b)
- normal1.normalize()
-
- n1 = e.co2
- n3 = e.next.co2
- n2 = e.co1
-
- a = n1-n2
- b = n1-n3
-
- normal2 = a.cross(b)
- normal2.normalize()
-
- # Reuse normal1 var
- normal1 += normal1 + normal2
- normal1.normalize()
-
- e.normal = normal1
- #print e.normal
-
-
-
- def backup(self):
- # Keep a backup of the edges
- self.backup_edges = self.edges[:]
-
- def restore(self):
- self.edges = self.backup_edges[:]
- for e in self.edges:
- e.removed = 0
-
- def reverse(self):
- self.edges.reverse()
- self.normal.negate()
-
- for e in self.edges:
- e.normal.negate()
- e.v1, e.v2 = e.v2, e.v1
- e.co1, e.co2 = e.co2, e.co1
- e.next, e.prev = e.prev, e.next
-
-
- def removeSmallest(self, cullNum, otherLoopLen):
- '''
- Removes N Smallest edges and backs up the loop,
- this is so we can loop between 2 loops as if they are the same length,
- backing up and restoring incase the loop needs to be skinned with another loop of a different length.
- '''
- global CULL_METHOD
- if CULL_METHOD == 1: # Shortest edge
- eloopCopy = self.edges[:]
-
- # Length sort, smallest first
- try: eloopCopy.sort(key = lambda e1: e1.length)
- except: eloopCopy.sort(lambda e1, e2: cmp(e1.length, e2.length ))
-
- # Dont use atm
- #eloopCopy.sort(lambda e1, e2: cmp(e1.angle*e1.length, e2.angle*e2.length)) # Length sort, smallest first
- #eloopCopy.sort(lambda e1, e2: cmp(e1.angle, e2.angle)) # Length sort, smallest first
-
- remNum = 0
- for i, e in enumerate(eloopCopy):
- if not e.fake:
- e.removed = 1
- self.edges.remove( e ) # Remove from own list, still in linked list.
- remNum += 1
-
- if not remNum < cullNum:
- break
-
- else: # CULL METHOD is even
-
- culled = 0
-
- step = int(otherLoopLen / float(cullNum)) * 2
-
- currentEdge = self.edges[0]
- while culled < cullNum:
-
- # Get the shortest face in the next STEP
- step_count= 0
- bestAng= 360.0
- smallestEdge= None
- while step_count<=step or smallestEdge==None:
- step_count+=1
- if not currentEdge.removed: # 0 or -1 will not be accepted
- if currentEdge.angle<bestAng and not currentEdge.fake:
- smallestEdge= currentEdge
- bestAng= currentEdge.angle
-
- currentEdge = currentEdge.next
-
- # In that stepping length we have the smallest edge.remove it
- smallestEdge.removed = 1
- self.edges.remove(smallestEdge)
-
- # Start scanning from the edge we found? - result is over fanning- no good.
- #currentEdge= smallestEdge.next
-
- culled+=1
-
-
-# Returns face edges.
-# face must have edge data.
-
-# Utility funcs for 2.5, make into a module??
-def ord_ind(i1,i2):
- if i1<i2: return i1,i2
- return i2,i1
-
-def edge_key(ed):
- v1,v2 = tuple(ed.verts)
- return ord_ind(v1, v2)
-
-def face_edge_keys(f):
- verts = tuple(f.verts)
- if len(verts)==3:
- return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[0])
-
- return ord_ind(verts[0], verts[1]), ord_ind(verts[1], verts[2]), ord_ind(verts[2], verts[3]), ord_ind(verts[3], verts[0])
-
-def mesh_faces_extend(me, faces, mat_idx = 0):
- orig_facetot = len(me.faces)
- new_facetot = len(faces)
- me.add_geometry(0, 0, new_facetot)
- tot = orig_facetot+new_facetot
- me_faces = me.faces
- i= 0
- while i < new_facetot:
-
- f = [v.index for v in faces[i]]
- if len(f)==4 and f[3]==0:
- f = f[1], f[2], f[3], f[0]
-
- mf = me_faces[orig_facetot+i]
- mf.verts_raw = f
- mf.material_index = mat_idx
- i+=1
-# end utils
-
-
-def getSelectedEdges(context, me, ob):
- MESH_MODE= context.scene.tool_settings.mesh_selection_mode
-
- if MESH_MODE in ('EDGE', 'VERTEX'):
- context.scene.tool_settings.mesh_selection_mode = 'EDGE'
- edges= [ ed for ed in me.edges if ed.selected ]
- # print len(edges), len(me.edges)
- context.scene.tool_settings.mesh_selection_mode = MESH_MODE
- return edges
-
- if MESH_MODE == 'FACE':
- context.scene.tool_settings.mesh_selection_mode = 'EDGE'
- # value is [edge, face_sel_user_in]
- edge_dict= dict((edge_key(ed), [ed, 0]) for ed in me.edges)
-
- for f in me.faces:
- if f.sel:
- for edkey in face_edge_keys(f):
- edge_dict[edkey][1] += 1
-
- context.scene.tool_settings.mesh_selection_mode = MESH_MODE
- return [ ed_data[0] for ed_data in edge_dict.itervalues() if ed_data[1] == 1 ]
-
-
-
-def getVertLoops(selEdges, me):
- '''
- return a list of vert loops, closed and open [(loop, closed)...]
- '''
-
- mainVertLoops = []
- # second method
- tot = len(me.verts)
- vert_siblings = [[] for i in range(tot)]
- vert_used = [False] * tot
-
- for ed in selEdges:
- i1, i2 = edge_key(ed)
- vert_siblings[i1].append(i2)
- vert_siblings[i2].append(i1)
-
- # find the first used vert and keep looping.
- for i in range(tot):
- if vert_siblings[i] and not vert_used[i]:
- sbl = vert_siblings[i] # siblings
-
- if len(sbl) > 2:
- return None
-
- vert_used[i] = True
-
- # do an edgeloop seek
- if len(sbl) == 2:
- contextVertLoop= [sbl[0], i, sbl[1]] # start the vert loop
- vert_used[contextVertLoop[ 0]] = True
- vert_used[contextVertLoop[-1]] = True
- else:
- contextVertLoop= [i, sbl[0]]
- vert_used[contextVertLoop[ 1]] = True
-
- # Always seek up
- ok = True
- while ok:
- ok = False
- closed = False
- sbl = vert_siblings[contextVertLoop[-1]]
- if len(sbl) == 2:
- next = sbl[not sbl.index( contextVertLoop[-2] )]
- if vert_used[next]:
- closed = True
- # break
- else:
- contextVertLoop.append( next ) # get the vert that isnt the second last
- vert_used[next] = True
- ok = True
-
- # Seek down as long as the starting vert was not at the edge.
- if not closed and len(vert_siblings[i]) == 2:
-
- ok = True
- while ok:
- ok = False
- sbl = vert_siblings[contextVertLoop[0]]
- if len(sbl) == 2:
- next = sbl[not sbl.index( contextVertLoop[1] )]
- if vert_used[next]:
- closed = True
- else:
- contextVertLoop.insert(0, next) # get the vert that isnt the second last
- vert_used[next] = True
- ok = True
-
- mainVertLoops.append((contextVertLoop, closed))
-
-
- verts = me.verts
- # convert from indicies to verts
- # mainVertLoops = [([verts[i] for i in contextVertLoop], closed) for contextVertLoop, closed in mainVertLoops]
- # print len(mainVertLoops)
- return mainVertLoops
-
-
-
-def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
-
- new_faces= [] #
-
- # Make sure e1 loops is bigger then e2
- if len(eloop1.edges) != len(eloop2.edges):
- if len(eloop1.edges) < len(eloop2.edges):
- eloop1, eloop2 = eloop2, eloop1
-
- eloop1.backup() # were about to cull faces
- CULL_FACES = len(eloop1.edges) - len(eloop2.edges)
- eloop1.removeSmallest(CULL_FACES, len(eloop1.edges))
- else:
- CULL_FACES = 0
- # First make sure poly vert loops are in sync with eachother.
-
- # The vector allong which we are skinning.
- skinVector = eloop1.centre - eloop2.centre
-
- loopDist = skinVector.length
-
- # IS THE LOOP FLIPPED, IF SO FLIP BACK. we keep it flipped, its ok,
- if eloop1.closed or eloop2.closed:
- angleBetweenLoopNormals = AngleBetweenVecs(eloop1.normal, eloop2.normal)
- if angleBetweenLoopNormals > 90:
- eloop2.reverse()
-
-
- DIR= eloop1.centre - eloop2.centre
-
- # if eloop2.closed:
- bestEloopDist = BIG_NUM
- bestOffset = 0
- # Loop rotation offset to test.1
- eLoopIdxs = list(range(len(eloop1.edges)))
- for offset in range(len(eloop1.edges)):
- totEloopDist = 0 # Measure this total distance for thsi loop.
-
- offsetIndexLs = eLoopIdxs[offset:] + eLoopIdxs[:offset] # Make offset index list
-
-
- # e1Idx is always from 0uu to N, e2Idx is offset.
- for e1Idx, e2Idx in enumerate(offsetIndexLs):
- e1= eloop1.edges[e1Idx]
- e2= eloop2.edges[e2Idx]
-
-
- # Include fan connections in the measurement.
- OK= True
- while OK or e1.removed:
- OK= False
-
- # Measure the vloop distance ===============
- diff= ((e1.cent - e2.cent).length) #/ nangle1
-
- ed_dir= e1.cent-e2.cent
- a_diff= AngleBetweenVecs(DIR, ed_dir)/18 # 0 t0 18
-
- totEloopDist += (diff * (1+a_diff)) / (1+loopDist)
-
- # Premeture break if where no better off
- if totEloopDist > bestEloopDist:
- break
-
- e1=e1.next
-
- if totEloopDist < bestEloopDist:
- bestOffset = offset
- bestEloopDist = totEloopDist
-
- # Modify V2 LS for Best offset
- eloop2.edges = eloop2.edges[bestOffset:] + eloop2.edges[:bestOffset]
-
- else:
- # Both are open loops, easier to calculate.
-
-
- # Make sure the fake edges are at the start.
- for i, edloop in enumerate((eloop1, eloop2)):
- # print "LOOPO"
- if edloop.edges[0].fake:
- # alredy at the start
- #print "A"
- pass
- elif edloop.edges[-1].fake:
- # put the end at the start
- edloop.edges.insert(0, edloop.edges.pop())
- #print "B"
-
- else:
- for j, ed in enumerate(edloop.edges):
- if ed.fake:
- #print "C"
- edloop.edges = edloop.edges = edloop.edges[j:] + edloop.edges[:j]
- break
- # print "DONE"
- ed1, ed2 = eloop1.edges[0], eloop2.edges[0]
-
- if not ed1.fake or not ed2.fake:
- raise "Error"
-
- # Find the join that isnt flipped (juts like detecting a bow-tie face)
- a1 = (ed1.co1 - ed2.co1).length + (ed1.co2 - ed2.co2).length
- a2 = (ed1.co1 - ed2.co2).length + (ed1.co2 - ed2.co1).length
-
- if a1 > a2:
- eloop2.reverse()
- # make the first edge the start edge still
- eloop2.edges.insert(0, eloop2.edges.pop())
-
-
-
-
- for loopIdx in range(len(eloop2.edges)):
- e1 = eloop1.edges[loopIdx]
- e2 = eloop2.edges[loopIdx]
-
- # Remember the pairs for fan filling culled edges.
- e1.match = e2; e2.match = e1
-
- if not (e1.fake or e2.fake):
- new_faces.append([e1.v1, e1.v2, e2.v2, e2.v1])
-
- # FAN FILL MISSING FACES.
- if CULL_FACES:
- # Culled edges will be in eloop1.
- FAN_FILLED_FACES = 0
-
- contextEdge = eloop1.edges[0] # The larger of teh 2
- while FAN_FILLED_FACES < CULL_FACES:
- while contextEdge.next.removed == 0:
- contextEdge = contextEdge.next
-
- vertFanPivot = contextEdge.match.v2
-
- while contextEdge.next.removed == 1:
- #if not contextEdge.next.fake:
- new_faces.append([contextEdge.next.v1, contextEdge.next.v2, vertFanPivot])
-
- # Should we use another var?, this will work for now.
- contextEdge.next.removed = 1
-
- contextEdge = contextEdge.next
- FAN_FILLED_FACES += 1
-
- # may need to fan fill backwards 1 for non closed loops.
-
- eloop1.restore() # Add culled back into the list.
-
- return new_faces
-
-def main(context):
- global CULL_METHOD
-
- ob = context.object
-
- is_editmode = (ob.mode=='EDIT')
- if is_editmode: bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- if ob == None or ob.type != 'MESH':
- raise Exception("BPyMessages.Error_NoMeshActive()")
- return
-
- me = ob.data
-
- time1 = time.time()
- selEdges = getSelectedEdges(context, me, ob)
- vertLoops = getVertLoops(selEdges, me) # list of lists of edges.
- if vertLoops == None:
- raise Exception('Error%t|Selection includes verts that are a part of more then 1 loop')
- if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- return
- # print len(vertLoops)
-
-
- if len(vertLoops) > 2:
- choice = PupMenu('Loft '+str(len(vertLoops))+' edge loops%t|loop|segment')
- if choice == -1:
- if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- return
-
- elif len(vertLoops) < 2:
- raise Exception('Error%t|No Vertloops found!')
- if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- return
- else:
- choice = 2
-
-
- # The line below checks if any of the vert loops are differenyt in length.
- if False in [len(v[0]) == len(vertLoops[0][0]) for v in vertLoops]:
- CULL_METHOD = PupMenu('Small to large edge loop distrobution method%t|remove edges evenly|remove smallest edges')
- if CULL_METHOD == -1:
- if is_editmode: Window.EditMode(1)
- return
-
- if CULL_METHOD ==1: # RESET CULL_METHOD
- CULL_METHOD = 0 # shortest
- else:
- CULL_METHOD = 1 # even
-
-
- time1 = time.time()
- # Convert to special edge data.
- edgeLoops = []
- for vloop, closed in vertLoops:
- edgeLoops.append(edgeLoop(vloop, me, closed))
-
-
- # VERT LOOP ORDERING CODE
- # "Build a worm" list - grow from Both ends
- edgeOrderedList = [edgeLoops.pop()]
-
- # Find the closest.
- bestSoFar = BIG_NUM
- bestIdxSoFar = None
- for edLoopIdx, edLoop in enumerate(edgeLoops):
- l =(edgeOrderedList[-1].centre - edLoop.centre).length
- if l < bestSoFar:
- bestIdxSoFar = edLoopIdx
- bestSoFar = l
-
- edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )
-
- # Now we have the 2 closest, append to either end-
- # Find the closest.
- while edgeLoops:
- bestSoFar = BIG_NUM
- bestIdxSoFar = None
- first_or_last = 0 # Zero is first
- for edLoopIdx, edLoop in enumerate(edgeLoops):
- l1 =(edgeOrderedList[-1].centre - edLoop.centre).length
-
- if l1 < bestSoFar:
- bestIdxSoFar = edLoopIdx
- bestSoFar = l1
- first_or_last = 1 # last
-
- l2 =(edgeOrderedList[0].centre - edLoop.centre).length
- if l2 < bestSoFar:
- bestIdxSoFar = edLoopIdx
- bestSoFar = l2
- first_or_last = 0 # last
-
- if first_or_last: # add closest Last
- edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )
- else: # Add closest First
- edgeOrderedList.insert(0, edgeLoops.pop(bestIdxSoFar) ) # First
-
- faces = []
-
- for i in range(len(edgeOrderedList)-1):
- faces.extend( skin2EdgeLoops(edgeOrderedList[i], edgeOrderedList[i+1], me, ob, 0) )
- if choice == 1 and len(edgeOrderedList) > 2: # Loop
- faces.extend( skin2EdgeLoops(edgeOrderedList[0], edgeOrderedList[-1], me, ob, 0) )
-
- # REMOVE SELECTED FACES.
- MESH_MODE= ob.mode
- if MESH_MODE == 'EDGE' or MESH_MODE == 'VERTEX': pass
- elif MESH_MODE == 'FACE':
- try: me.faces.delete(1, [ f for f in me.faces if f.sel ])
- except: pass
-
- if 1: # 2.5
- mesh_faces_extend(me, faces, ob.active_material_index)
- me.update(calc_edges=True)
- else:
- me.faces.extend(faces, smooth = True)
-
- print('\nSkin done in %.4f sec.' % (time.time()-time1))
-
- if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
-
-class MESH_OT_skin(bpy.types.Operator):
- '''Bridge face loops.'''
-
- __idname__ = "mesh.skin"
- __label__ = "Add Torus"
- __register__ = True
- __undo__ = True
-
- '''
- __props__ = [
- bpy.props.EnumProperty(attr="loft_method", items=[(), ()], description="", default= True),
- ]
- '''
-
- def execute(self, context):
- main(context)
- return ('FINISHED',)
-
-
-# Register the operator
-bpy.ops.add(MESH_OT_skin)
-
-# Add to a menu
-import dynamic_menu
-menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_edit_mesh_faces, (lambda self, context: self.layout.itemO("mesh.skin", text="Bridge Faces")) )
-
-if __name__ == "__main__":
- bpy.ops.mesh.skin()
diff --git a/release/scripts/io/netrender/client.py b/release/scripts/io/netrender/client.py
index d4a7b242cab..65b2937867f 100644
--- a/release/scripts/io/netrender/client.py
+++ b/release/scripts/io/netrender/client.py
@@ -3,74 +3,12 @@ import sys, os, re
import http, http.client, http.server, urllib
import subprocess, shutil, time, hashlib
-import netrender.model
import netrender.slave as slave
import netrender.master as master
from netrender.utils import *
-def addFluidFiles(job, path):
- if os.path.exists(path):
- pattern = re.compile("fluidsurface_(final|preview)_([0-9]+)\.(bobj|bvel)\.gz")
- for fluid_file in sorted(os.listdir(path)):
- match = pattern.match(fluid_file)
-
- if match:
- current_frame = int(match.groups()[1])
- job.addFile(path + fluid_file, current_frame, current_frame)
-
-def addPointCache(job, ob, point_cache, default_path):
- if not point_cache.disk_cache:
- return
-
-
- name = point_cache.name
- if name == "":
- name = "".join(["%02X" % ord(c) for c in ob.name])
-
- cache_path = bpy.sys.expandpath(point_cache.filepath) if point_cache.external else default_path
-
- index = "%02i" % point_cache.index
-
- if os.path.exists(cache_path):
- pattern = re.compile(name + "_([0-9]+)_" + index + "\.bphys")
-
- cache_files = []
-
- for cache_file in sorted(os.listdir(cache_path)):
- match = pattern.match(cache_file)
-
- if match:
- cache_frame = int(match.groups()[0])
- cache_files.append((cache_frame, cache_file))
-
- cache_files.sort()
-
- if len(cache_files) == 1:
- cache_frame, cache_file = cache_files[0]
- job.addFile(cache_path + cache_file, cache_frame, cache_frame)
- else:
- for i in range(len(cache_files)):
- current_item = cache_files[i]
- next_item = cache_files[i+1] if i + 1 < len(cache_files) else None
- previous_item = cache_files[i - 1] if i > 0 else None
-
- current_frame, current_file = current_item
-
- if not next_item and not previous_item:
- job.addFile(cache_path + current_file, current_frame, current_frame)
- elif next_item and not previous_item:
- next_frame = next_item[0]
- job.addFile(cache_path + current_file, current_frame, next_frame - 1)
- elif not next_item and previous_item:
- previous_frame = previous_item[0]
- job.addFile(cache_path + current_file, previous_frame + 1, current_frame)
- else:
- next_frame = next_item[0]
- previous_frame = previous_item[0]
- job.addFile(cache_path + current_file, previous_frame + 1, next_frame - 1)
-
-def clientSendJob(conn, scene, anim = False):
+def clientSendJob(conn, scene, anim = False, chunks = 5):
netsettings = scene.network_render
job = netrender.model.RenderJob()
@@ -85,7 +23,6 @@ def clientSendJob(conn, scene, anim = False):
job_name = netsettings.job_name
path, name = os.path.split(filename)
- path += os.sep
if job_name == "[default]":
job_name = name
@@ -93,38 +30,67 @@ def clientSendJob(conn, scene, anim = False):
# LIBRARIES
###########################
for lib in bpy.data.libraries:
- job.addFile(bpy.sys.expandpath(lib_path))
+ lib_path = lib.filename
+ if lib_path.startswith("//"):
+ lib_path = path + os.sep + lib_path[2:]
+
+ job.addFile(lib_path)
+
###########################
- # IMAGES
+ # POINT CACHES
###########################
- for image in bpy.data.images:
- if image.source == "FILE" and not image.packed_file:
- job.addFile(bpy.sys.expandpath(image.filename))
+ root, ext = os.path.splitext(name)
+ cache_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
+
+ if os.path.exists(cache_path):
+ caches = {}
+ pattern = re.compile("([a-zA-Z0-9]+)_([0-9]+)_[0-9]+\.bphys")
+ for cache_file in sorted(os.listdir(cache_path)):
+ match = pattern.match(cache_file)
+
+ if match:
+ cache_id = match.groups()[0]
+ cache_frame = int(match.groups()[1])
+
+ cache_files = caches.get(cache_id, [])
+ cache_files.append((cache_frame, cache_file))
+ caches[cache_id] = cache_files
+
+ for cache in caches.values():
+ cache.sort()
+
+ if len(cache) == 1:
+ cache_frame, cache_file = cache[0]
+ job.addFile(cache_path + cache_file, cache_frame, cache_frame)
+ else:
+ for i in range(len(cache)):
+ current_item = cache[i]
+ next_item = cache[i+1] if i + 1 < len(cache) else None
+ previous_item = cache[i - 1] if i > 0 else None
+
+ current_frame, current_file = current_item
+
+ if not next_item and not previous_item:
+ job.addFile(cache_path + current_file, current_frame, current_frame)
+ elif next_item and not previous_item:
+ next_frame = next_item[0]
+ job.addFile(cache_path + current_file, current_frame, next_frame - 1)
+ elif not next_item and previous_item:
+ previous_frame = previous_item[0]
+ job.addFile(cache_path + current_file, previous_frame + 1, current_frame)
+ else:
+ next_frame = next_item[0]
+ previous_frame = previous_item[0]
+ job.addFile(cache_path + current_file, previous_frame + 1, next_frame - 1)
+
###########################
- # FLUID + POINT CACHE
+ # IMAGES
###########################
- root, ext = os.path.splitext(name)
- default_path = path + "blendcache_" + root + os.sep # need an API call for that
-
- for object in bpy.data.objects:
- for modifier in object.modifiers:
- if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
- addFluidFiles(job, bpy.sys.expandpath(modifier.settings.path))
- elif modifier.type == "CLOTH":
- addPointCache(job, object, modifier.point_cache, default_path)
- elif modifier.type == "SOFT_BODY":
- addPointCache(job, object, modifier.point_cache, default_path)
- elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
- addPointCache(job, object, modifier.domain_settings.point_cache_low, default_path)
- if modifier.domain_settings.highres:
- addPointCache(job, object, modifier.domain_settings.point_cache_high, default_path)
-
- # particles modifier are stupid and don't contain data
- # we have to go through the object property
- for psys in object.particle_systems:
- addPointCache(job, object, psys.point_cache, default_path)
+ for image in bpy.data.images:
+ if image.source == "FILE" and not image.packed_file:
+ job.addFile(image.filename)
# print(job.files)
diff --git a/release/scripts/io/netrender/master.py b/release/scripts/io/netrender/master.py
index 1c83e758ce5..a3e186a9cfd 100644
--- a/release/scripts/io/netrender/master.py
+++ b/release/scripts/io/netrender/master.py
@@ -42,10 +42,9 @@ class MRenderSlave(netrender.model.RenderSlave):
self.job = None
class MRenderJob(netrender.model.RenderJob):
- def __init__(self, job_id, job_type, name, files, chunks = 1, priority = 1, blacklist = []):
+ def __init__(self, job_id, name, files, chunks = 1, priority = 1, blacklist = []):
super().__init__()
self.id = job_id
- self.type = job_type
self.name = name
self.files = files
self.frames = []
@@ -54,10 +53,6 @@ class MRenderJob(netrender.model.RenderJob):
self.usage = 0.0
self.blacklist = blacklist
self.last_dispatched = time.time()
-
- # force one chunk for process jobs
- if self.type == netrender.model.JOB_PROCESS:
- self.chunks = 1
# special server properties
self.last_update = 0
@@ -98,8 +93,8 @@ class MRenderJob(netrender.model.RenderJob):
if frame:
frame.log_path = log_path
- def addFrame(self, frame_number, command):
- frame = MRenderFrame(frame_number, command)
+ def addFrame(self, frame_number):
+ frame = MRenderFrame(frame_number)
self.frames.append(frame)
return frame
@@ -119,14 +114,12 @@ class MRenderJob(netrender.model.RenderJob):
return frames
class MRenderFrame(netrender.model.RenderFrame):
- def __init__(self, frame, command):
+ def __init__(self, frame):
super().__init__()
self.number = frame
self.slave = None
self.time = 0
self.status = QUEUED
- self.command = command
-
self.log_path = None
def reset(self, all):
@@ -375,10 +368,10 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
job_id = self.server.nextJobID()
- job = MRenderJob(job_id, job_info.type, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
+ job = MRenderJob(job_id, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
for frame in job_info.frames:
- frame = job.addFrame(frame.number, frame.command)
+ frame = job.addFrame(frame.number)
self.server.addJob(job)
@@ -545,18 +538,17 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
frame = job[job_frame]
if frame:
- if job.type == netrender.model.JOB_BLENDER:
- if job_result == DONE:
- length = int(self.headers['content-length'])
- buf = self.rfile.read(length)
- f = open(job.save_path + "%04d" % job_frame + ".exr", 'wb')
- f.write(buf)
- f.close()
+ if job_result == DONE:
+ length = int(self.headers['content-length'])
+ buf = self.rfile.read(length)
+ f = open(job.save_path + "%04d" % job_frame + ".exr", 'wb')
+ f.write(buf)
+ f.close()
- del buf
- elif job_result == ERROR:
- # blacklist slave on this job on error
- job.blacklist.append(slave.id)
+ del buf
+ elif job_result == ERROR:
+ # blacklist slave on this job on error
+ job.blacklist.append(slave.id)
self.server.stats("", "Receiving result")
@@ -744,7 +736,7 @@ def runMaster(address, broadcast, path, update_stats, test_break):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- start_time = time.time()
+ start_time = time.time()
while not test_break():
httpd.handle_request()
diff --git a/release/scripts/io/netrender/master_html.py b/release/scripts/io/netrender/master_html.py
index 545659e8dc4..6a956a70e9f 100644
--- a/release/scripts/io/netrender/master_html.py
+++ b/release/scripts/io/netrender/master_html.py
@@ -32,8 +32,9 @@ def get(handler):
def endTable():
output("</table>")
+ handler.send_head(content = "text/html")
+
if handler.path == "/html" or handler.path == "/":
- handler.send_head(content = "text/html")
output("<html><head><title>NetRender</title></head><body>")
output("<h2>Master</h2>")
@@ -85,7 +86,6 @@ def get(handler):
output("</body></html>")
elif handler.path.startswith("/html/job"):
- handler.send_head(content = "text/html")
job_id = handler.path[9:]
output("<html><head><title>NetRender</title></head><body>")
@@ -108,9 +108,10 @@ def get(handler):
output("</body></html>")
elif handler.path.startswith("/html/log"):
- handler.send_head(content = "text/plain")
pattern = re.compile("([a-zA-Z0-9]+)_([0-9]+)")
+ output("<html><head><title>NetRender</title></head><body>")
+
match = pattern.match(handler.path[9:])
if match:
job_id = match.groups()[0]
@@ -124,8 +125,12 @@ def get(handler):
if frame:
f = open(frame.log_path, 'rb')
+ output("<pre>")
+
shutil.copyfileobj(f, handler.wfile)
+ output("</pre>")
+
f.close()
else:
output("no such frame")
@@ -133,3 +138,5 @@ def get(handler):
output("no such job")
else:
output("malformed url")
+
+ output("</body></html>")
diff --git a/release/scripts/io/netrender/model.py b/release/scripts/io/netrender/model.py
index bef6f0e68af..be97f8d0a81 100644
--- a/release/scripts/io/netrender/model.py
+++ b/release/scripts/io/netrender/model.py
@@ -72,18 +72,9 @@ class RenderSlave:
return slave
-JOB_BLENDER = 1
-JOB_PROCESS = 2
-
-JOB_TYPES = {
- JOB_BLENDER: "Blender",
- JOB_PROCESS: "Process"
- }
-
class RenderJob:
def __init__(self):
self.id = ""
- self.type = JOB_BLENDER
self.name = ""
self.files = []
self.frames = []
@@ -96,8 +87,8 @@ class RenderJob:
def addFile(self, file_path, start=-1, end=-1):
self.files.append((file_path, start, end))
- def addFrame(self, frame_number, command = ""):
- frame = RenderFrame(frame_number, command)
+ def addFrame(self, frame_number):
+ frame = RenderFrame(frame_number)
self.frames.append(frame)
return frame
@@ -147,9 +138,8 @@ class RenderJob:
max_frame = max((f.number for f in frames)) if frames else -1
return {
"id": self.id,
- "type": self.type,
"name": self.name,
- "files": [f for f in self.files if f[1] == -1 or not frames or (f[1] <= max_frame and f[2] >= min_frame)],
+ "files": [f for f in self.files if f[1] == -1 or not frames or (f[1] <= min_frame <= f[2] or f[1] <= max_frame <= f[2])],
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
"chunks": self.chunks,
"priority": self.priority,
@@ -165,7 +155,6 @@ class RenderJob:
job = RenderJob()
job.id = data["id"]
- job.type = data["type"]
job.name = data["name"]
job.files = data["files"]
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
@@ -178,12 +167,11 @@ class RenderJob:
return job
class RenderFrame:
- def __init__(self, number = 0, command = ""):
+ def __init__(self, number = 0):
self.number = number
self.time = 0
self.status = QUEUED
self.slave = None
- self.command = command
def statusText(self):
return STATUS_TEXT[self.status]
@@ -193,8 +181,7 @@ class RenderFrame:
"number": self.number,
"time": self.time,
"status": self.status,
- "slave": None if not self.slave else self.slave.serialize(),
- "command": self.command
+ "slave": None if not self.slave else self.slave.serialize()
}
@staticmethod
@@ -207,6 +194,5 @@ class RenderFrame:
frame.time = data["time"]
frame.status = data["status"]
frame.slave = RenderSlave.materialize(data["slave"])
- frame.command = data["command"]
return frame
diff --git a/release/scripts/io/netrender/operators.py b/release/scripts/io/netrender/operators.py
index e46b0c7b888..42d1f6a0b86 100644
--- a/release/scripts/io/netrender/operators.py
+++ b/release/scripts/io/netrender/operators.py
@@ -9,9 +9,11 @@ import netrender.model
@rnaOperator
class RENDER_OT_netclientanim(bpy.types.Operator):
- '''Start rendering an animation on network'''
+ '''
+ Operator documentation text, will be used for the operator tooltip and python docs.
+ '''
__idname__ = "render.netclientanim"
- __label__ = "Animation on network"
+ __label__ = "Net Render Client Anim"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -40,9 +42,11 @@ class RENDER_OT_netclientanim(bpy.types.Operator):
@rnaOperator
class RENDER_OT_netclientsend(bpy.types.Operator):
- '''Send Render Job to the Network'''
+ '''
+ Operator documentation text, will be used for the operator tooltip and python docs.
+ '''
__idname__ = "render.netclientsend"
- __label__ = "Send job"
+ __label__ = "Net Render Client Send"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -69,9 +73,9 @@ class RENDER_OT_netclientsend(bpy.types.Operator):
@rnaOperator
class RENDER_OT_netclientstatus(bpy.types.Operator):
- '''Refresh the status of the current jobs'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientstatus"
- __label__ = "Client Status"
+ __label__ = "Net Render Client Status"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -116,7 +120,7 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientblacklistslave"
- __label__ = "Client Blacklist Slave"
+ __label__ = "Net Render Client Blacklist Slave"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -151,7 +155,7 @@ class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientwhitelistslave"
- __label__ = "Client Whitelist Slave"
+ __label__ = "Net Render Client Whitelist Slave"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -185,9 +189,9 @@ class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
@rnaOperator
class RENDER_OT_netclientslaves(bpy.types.Operator):
- '''Refresh status about available Render slaves'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientslaves"
- __label__ = "Client Slaves"
+ __label__ = "Net Render Client Slaves"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -235,9 +239,9 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
@rnaOperator
class RENDER_OT_netclientcancel(bpy.types.Operator):
- '''Cancel the selected network rendering job.'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientcancel"
- __label__ = "Client Cancel"
+ __label__ = "Net Render Client Cancel"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -269,9 +273,9 @@ class RENDER_OT_netclientcancel(bpy.types.Operator):
@rnaOperator
class RENDER_OT_netclientcancelall(bpy.types.Operator):
- '''Cancel all running network rendering jobs.'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientcancelall"
- __label__ = "Client Cancel All"
+ __label__ = "Net Render Client Cancel All"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -301,9 +305,9 @@ class RENDER_OT_netclientcancelall(bpy.types.Operator):
@rnaOperator
class netclientdownload(bpy.types.Operator):
- '''Download render results from the network'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientdownload"
- __label__ = "Client Download"
+ __label__ = "Net Render Client Download"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -353,7 +357,7 @@ class netclientdownload(bpy.types.Operator):
class netclientscan(bpy.types.Operator):
'''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientscan"
- __label__ = "Client Scan"
+ __label__ = "Net Render Client Scan"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
@@ -389,9 +393,9 @@ class netclientscan(bpy.types.Operator):
@rnaOperator
class netclientweb(bpy.types.Operator):
- '''Open new window with information about running rendering jobs'''
+ '''Operator documentation text, will be used for the operator tooltip and python docs.'''
__idname__ = "render.netclientweb"
- __label__ = "Open Master Monitor"
+ __label__ = "Net Render Client Web"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
diff --git a/release/scripts/io/netrender/slave.py b/release/scripts/io/netrender/slave.py
index 15ca6faf297..657e31001e0 100644
--- a/release/scripts/io/netrender/slave.py
+++ b/release/scripts/io/netrender/slave.py
@@ -99,46 +99,37 @@ def render_slave(engine, scene):
if not os.path.exists(JOB_PREFIX):
os.mkdir(JOB_PREFIX)
+ job_path = job.files[0][0] # data in files have format (path, start, end)
+ main_path, main_file = os.path.split(job_path)
+
+ job_full_path = testFile(conn, job.id, slave_id, JOB_PREFIX, job_path)
+ print("Fullpath", job_full_path)
+ print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
+ engine.update_stats("", "Render File", main_file, "for job", job.id)
+
+ for file_path, start, end in job.files[1:]:
+ print("\t", file_path)
+ testFile(conn, job.id, slave_id, JOB_PREFIX, file_path, main_path)
+
+ frame_args = []
+
+ for frame in job.frames:
+ print("frame", frame.number)
+ frame_args += ["-f", str(frame.number)]
- if job.type == netrender.model.JOB_BLENDER:
- job_path = job.files[0][0] # data in files have format (path, start, end)
- main_path, main_file = os.path.split(job_path)
-
- job_full_path = testFile(conn, job.id, slave_id, JOB_PREFIX, job_path)
- print("Fullpath", job_full_path)
- print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
- engine.update_stats("", "Render File", main_file, "for job", job.id)
-
- for file_path, start, end in job.files[1:]:
- print("\t", file_path)
- testFile(conn, job.id, slave_id, JOB_PREFIX, file_path, main_path)
-
# announce log to master
logfile = netrender.model.LogFile(job.id, [frame.number for frame in job.frames])
conn.request("POST", "/log", bytes(repr(logfile.serialize()), encoding='utf8'), headers={"slave-id":slave_id})
response = conn.getresponse()
-
first_frame = job.frames[0].number
-
+
# start render
start_t = time.time()
-
- if job.type == netrender.model.JOB_BLENDER:
- frame_args = []
-
- for frame in job.frames:
- print("frame", frame.number)
- frame_args += ["-f", str(frame.number)]
-
- val = SetErrorMode()
- process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- RestoreErrorMode(val)
- elif job.type == netrender.model.JOB_PROCESS:
- command = job.frames[0].command
- val = SetErrorMode()
- process = subprocess.Popen(command.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- RestoreErrorMode(val)
+
+ val = SetErrorMode()
+ process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ RestoreErrorMode(val)
headers = {"job-id":job.id, "slave-id":slave_id}
@@ -164,9 +155,6 @@ def render_slave(engine, scene):
if testCancel(conn, job.id, first_frame):
cancelled = True
- # read leftovers if needed
- stdout += process.stdout.read()
-
if cancelled:
# kill process if needed
if process.poll() == None:
@@ -194,16 +182,11 @@ def render_slave(engine, scene):
headers["job-result"] = str(DONE)
for frame in job.frames:
headers["job-frame"] = str(frame.number)
-
- if job.type == netrender.model.JOB_BLENDER:
- # send image back to server
- f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
- conn.request("PUT", "/render", f, headers=headers)
- f.close()
- response = conn.getresponse()
- elif job.type == netrender.model.JOB_PROCESS:
- conn.request("PUT", "/render", headers=headers)
- response = conn.getresponse()
+ # send result back to server
+ f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
+ conn.request("PUT", "/render", f, headers=headers)
+ f.close()
+ response = conn.getresponse()
else:
headers["job-result"] = str(ERROR)
for frame in job.frames:
diff --git a/release/scripts/io/netrender/ui.py b/release/scripts/io/netrender/ui.py
index 7d7f3c29630..7681d4865e9 100644
--- a/release/scripts/io/netrender/ui.py
+++ b/release/scripts/io/netrender/ui.py
@@ -20,7 +20,7 @@ ERROR = 3
class RenderButtonsPanel(bpy.types.Panel):
__space_type__ = "PROPERTIES"
__region_type__ = "WINDOW"
- __context__ = "render"
+ __context__ = "scene"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
@@ -29,10 +29,14 @@ class RenderButtonsPanel(bpy.types.Panel):
# Setting panel, use in the scene for now.
@rnaType
-class RENDER_PT_network_settings(RenderButtonsPanel):
+class SCENE_PT_network_settings(RenderButtonsPanel):
__label__ = "Network Settings"
COMPAT_ENGINES = set(['NET_RENDER'])
+ def draw_header(self, context):
+ layout = self.layout
+ scene = context.scene
+
def draw(self, context):
layout = self.layout
@@ -44,6 +48,7 @@ class RENDER_PT_network_settings(RenderButtonsPanel):
split = layout.split()
col = split.column()
+
col.itemR(scene.network_render, "mode")
col.itemR(scene.network_render, "path")
col.itemR(scene.network_render, "server_address")
@@ -55,7 +60,7 @@ class RENDER_PT_network_settings(RenderButtonsPanel):
col.itemO("render.netclientscan", icon="ICON_FILE_REFRESH", text="")
@rnaType
-class RENDER_PT_network_job(RenderButtonsPanel):
+class SCENE_PT_network_job(RenderButtonsPanel):
__label__ = "Job Settings"
COMPAT_ENGINES = set(['NET_RENDER'])
@@ -74,16 +79,16 @@ class RENDER_PT_network_job(RenderButtonsPanel):
split = layout.split()
col = split.column()
- col.itemO("render.netclientanim", icon='ICON_RENDER_ANIMATION')
- col.itemO("render.netclientsend", icon="ICON_FILE_BLEND")
- col.itemO("render.netclientweb", icon="ICON_QUESTION")
+
+ col.itemO("render.netclientanim", icon='ICON_RENDER_ANIMATION', text="Animaton on network")
+ col.itemO("render.netclientsend", icon="ICON_FILE_BLEND", text="Send job")
+ col.itemO("render.netclientweb", icon="ICON_QUESTION", text="Open Master Monitor")
col.itemR(scene.network_render, "job_name")
- row = col.row()
- row.itemR(scene.network_render, "priority")
- row.itemR(scene.network_render, "chunks")
+ col.itemR(scene.network_render, "priority")
+ col.itemR(scene.network_render, "chunks")
@rnaType
-class RENDER_PT_network_slaves(RenderButtonsPanel):
+class SCENE_PT_network_slaves(RenderButtonsPanel):
__label__ = "Slaves Status"
COMPAT_ENGINES = set(['NET_RENDER'])
@@ -100,9 +105,11 @@ class RENDER_PT_network_slaves(RenderButtonsPanel):
row = layout.row()
row.template_list(netsettings, "slaves", netsettings, "active_slave_index", rows=2)
- sub = row.column(align=True)
- sub.itemO("render.netclientslaves", icon="ICON_FILE_REFRESH", text="")
- sub.itemO("render.netclientblacklistslave", icon="ICON_ZOOMOUT", text="")
+ col = row.column()
+
+ subcol = col.column(align=True)
+ subcol.itemO("render.netclientslaves", icon="ICON_FILE_REFRESH", text="")
+ subcol.itemO("render.netclientblacklistslave", icon="ICON_ZOOMOUT", text="")
if len(bpy.data.netrender_slaves) == 0 and len(netsettings.slaves) > 0:
while(len(netsettings.slaves) > 0):
@@ -119,7 +126,7 @@ class RENDER_PT_network_slaves(RenderButtonsPanel):
layout.itemL(text="Stats: " + slave.stats)
@rnaType
-class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel):
+class SCENE_PT_network_slaves_blacklist(RenderButtonsPanel):
__label__ = "Slaves Blacklist"
COMPAT_ENGINES = set(['NET_RENDER'])
@@ -136,8 +143,10 @@ class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel):
row = layout.row()
row.template_list(netsettings, "slaves_blacklist", netsettings, "active_blacklisted_slave_index", rows=2)
- sub = row.column(align=True)
- sub.itemO("render.netclientwhitelistslave", icon="ICON_ZOOMOUT", text="")
+ col = row.column()
+
+ subcol = col.column(align=True)
+ subcol.itemO("render.netclientwhitelistslave", icon="ICON_ZOOMOUT", text="")
if len(bpy.data.netrender_blacklist) == 0 and len(netsettings.slaves_blacklist) > 0:
while(len(netsettings.slaves_blacklist) > 0):
@@ -154,7 +163,7 @@ class RENDER_PT_network_slaves_blacklist(RenderButtonsPanel):
layout.itemL(text="Stats: " + time.ctime(slave.stats))
@rnaType
-class RENDER_PT_network_jobs(RenderButtonsPanel):
+class SCENE_PT_network_jobs(RenderButtonsPanel):
__label__ = "Jobs"
COMPAT_ENGINES = set(['NET_RENDER'])
@@ -171,11 +180,13 @@ class RENDER_PT_network_jobs(RenderButtonsPanel):
row = layout.row()
row.template_list(netsettings, "jobs", netsettings, "active_job_index", rows=2)
- sub = row.column(align=True)
- sub.itemO("render.netclientstatus", icon="ICON_FILE_REFRESH", text="")
- sub.itemO("render.netclientcancel", icon="ICON_ZOOMOUT", text="")
- sub.itemO("render.netclientcancelall", icon="ICON_PANEL_CLOSE", text="")
- sub.itemO("render.netclientdownload", icon='ICON_RENDER_ANIMATION', text="")
+ col = row.column()
+
+ subcol = col.column(align=True)
+ subcol.itemO("render.netclientstatus", icon="ICON_FILE_REFRESH", text="")
+ subcol.itemO("render.netclientcancel", icon="ICON_ZOOMOUT", text="")
+ subcol.itemO("render.netclientcancelall", icon="ICON_PANEL_CLOSE", text="")
+ subcol.itemO("render.netclientdownload", icon='ICON_RENDER_ANIMATION', text="")
if len(bpy.data.netrender_jobs) == 0 and len(netsettings.jobs) > 0:
while(len(netsettings.jobs) > 0):
@@ -223,21 +234,18 @@ NetRenderSettings.BoolProperty( attr="server_broadcast",
description="broadcast server address on local network",
default = True)
-default_path = os.environ.get("TEMP", None)
-
-if not default_path:
- if os.name == 'nt':
- default_path = "c:/tmp/"
- else:
- default_path = "/tmp/"
-elif not default_path.endswith(os.sep):
- default_path += os.sep
-
-NetRenderSettings.StringProperty( attr="path",
- name="Path",
- description="Path for temporary files",
- maxlen = 128,
- default = default_path)
+if os.name == 'nt':
+ NetRenderSettings.StringProperty( attr="path",
+ name="Path",
+ description="Path for temporary files",
+ maxlen = 128,
+ default = "C:/tmp/")
+else:
+ NetRenderSettings.StringProperty( attr="path",
+ name="Path",
+ description="Path for temporary files",
+ maxlen = 128,
+ default = "/tmp/")
NetRenderSettings.StringProperty( attr="job_name",
name="Job name",
@@ -292,8 +300,8 @@ NetRenderSettings.EnumProperty(attr="mode",
("RENDER_MASTER", "Master", "Act as render master"),
("RENDER_SLAVE", "Slave", "Act as render slave"),
),
- name="Network mode",
- description="Mode of operation of this instance",
+ name="network mode",
+ description="mode of operation of this instance",
default="RENDER_CLIENT")
NetRenderSettings.CollectionProperty(attr="slaves", type=NetRenderSlave, name="Slaves", description="")
diff --git a/release/scripts/io/netrender/utils.py b/release/scripts/io/netrender/utils.py
index b10648b8d62..06393a738a0 100644
--- a/release/scripts/io/netrender/utils.py
+++ b/release/scripts/io/netrender/utils.py
@@ -75,7 +75,7 @@ def prefixPath(prefix_directory, file_path, prefix_path):
if prefix_path and p.startswith(prefix_path):
directory = prefix_directory + p[len(prefix_path):]
- full_path = directory + os.sep + n
+ full_path = directory + n
if not os.path.exists(directory):
os.mkdir(directory)
else:
diff --git a/release/scripts/modules/bpy_ops.py b/release/scripts/modules/bpy_ops.py
index 6772a3771cb..83c2e82bf6c 100644
--- a/release/scripts/modules/bpy_ops.py
+++ b/release/scripts/modules/bpy_ops.py
@@ -139,132 +139,3 @@ class bpy_ops_submodule_op(object):
import bpy
bpy.ops = bpy_ops()
-
-# TODO, C macro's cant define settings :|
-
-class MESH_OT_delete_edgeloop(bpy.types.Operator):
- '''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
- __idname__ = "mesh.delete_edgeloop"
- __label__ = "Delete Edge Loop"
-
- def execute(self, context):
- bpy.ops.tfm.edge_slide(value=1.0)
- bpy.ops.mesh.select_more()
- bpy.ops.mesh.remove_doubles()
- return ('FINISHED',)
-
-rna_path_prop = bpy.props.StringProperty(attr="path", name="Context Attributes", description="rna context string", maxlen= 1024, default= "")
-
-class WM_OT_context_set_boolean(bpy.types.Operator):
- '''Set a context value.'''
- __idname__ = "wm.context_set_boolean"
- __label__ = "Context Set"
- __props__ = [rna_path_prop, bpy.props.BoolProperty(attr="value", name="Value", description="Assignment value", default= True)]
- def execute(self, context):
- exec("context.%s=%s" % (self.path, self.value)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_set_int(bpy.types.Operator): # same as enum
- '''Set a context value.'''
- __idname__ = "wm.context_set_int"
- __label__ = "Context Set"
- __props__ = [rna_path_prop, bpy.props.IntProperty(attr="value", name="Value", description="Assignment value", default= 0)]
- def execute(self, context):
- exec("context.%s=%d" % (self.path, self.value)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_set_float(bpy.types.Operator): # same as enum
- '''Set a context value.'''
- __idname__ = "wm.context_set_int"
- __label__ = "Context Set"
- __props__ = [rna_path_prop, bpy.props.FloatProperty(attr="value", name="Value", description="Assignment value", default= 0.0)]
- def execute(self, context):
- exec("context.%s=%f" % (self.path, self.value)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_set_string(bpy.types.Operator): # same as enum
- '''Set a context value.'''
- __idname__ = "wm.context_set_string"
- __label__ = "Context Set"
- __props__ = [rna_path_prop, bpy.props.StringProperty(attr="value", name="Value", description="Assignment value", maxlen= 1024, default= "")]
- def execute(self, context):
- exec("context.%s='%s'" % (self.path, self.value)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_set_enum(bpy.types.Operator):
- '''Set a context value.'''
- __idname__ = "wm.context_set_enum"
- __label__ = "Context Set"
- __props__ = [rna_path_prop, bpy.props.StringProperty(attr="value", name="Value", description="Assignment value (as a string)", maxlen= 1024, default= "")]
- def execute(self, context):
- exec("context.%s='%s'" % (self.path, self.value)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_toggle(bpy.types.Operator):
- '''Toggle a context value.'''
- __idname__ = "wm.context_toggle"
- __label__ = "Context Toggle"
- __props__ = [rna_path_prop]
- def execute(self, context):
- exec("context.%s=not (context.%s)" % (self.path, self.path)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_toggle_enum(bpy.types.Operator):
- '''Toggle a context value.'''
- __idname__ = "wm.context_toggle_enum"
- __label__ = "Context Toggle Values"
- __props__ = [
- rna_path_prop,
- bpy.props.StringProperty(attr="value_1", name="Value", description="Toggle enum", maxlen= 1024, default= ""),
- bpy.props.StringProperty(attr="value_2", name="Value", description="Toggle enum", maxlen= 1024, default= "")
- ]
- def execute(self, context):
- exec("context.%s = ['%s', '%s'][context.%s!='%s']" % (self.path, self.value_1, self.value_2, self.path, self.value_2)) # security nuts will complain.
- return ('FINISHED',)
-
-class WM_OT_context_cycle_enum(bpy.types.Operator):
- '''Toggle a context value.'''
- __idname__ = "wm.context_cycle_enum"
- __label__ = "Context Enum Cycle"
- __props__ = [rna_path_prop, bpy.props.BoolProperty(attr="reverse", name="Reverse", description="Cycle backwards", default= False)]
- def execute(self, context):
- orig_value = eval("context.%s" % self.path) # security nuts will complain.
-
- # Have to get rna enum values
- rna_struct_str, rna_prop_str = self.path.rsplit('.', 1)
- i = rna_prop_str.find('[')
- if i != -1: rna_prop_str = rna_prop_str[0:i] # just incse we get "context.foo.bar[0]"
-
- rna_struct = eval("context.%s.rna_type" % rna_struct_str)
-
- rna_prop = rna_struct.properties[rna_prop_str]
-
- if type(rna_prop) != bpy.types.EnumProperty:
- raise Exception("expected an enum property")
-
- enums = rna_struct.properties[rna_prop_str].items.keys()
- orig_index = enums.index(orig_value)
-
- # Have the info we need, advance to the next item
- if self.reverse:
- if orig_index==0: advance_enum = enums[-1]
- else: advance_enum = enums[orig_index-1]
- else:
- if orig_index==len(enums)-1: advance_enum = enums[0]
- else: advance_enum = enums[orig_index+1]
-
- # set the new value
- exec("context.%s=advance_enum" % self.path)
- return ('FINISHED',)
-
-bpy.ops.add(MESH_OT_delete_edgeloop)
-
-bpy.ops.add(WM_OT_context_set_boolean)
-bpy.ops.add(WM_OT_context_set_int)
-bpy.ops.add(WM_OT_context_set_float)
-bpy.ops.add(WM_OT_context_set_string)
-bpy.ops.add(WM_OT_context_set_enum)
-bpy.ops.add(WM_OT_context_toggle)
-bpy.ops.add(WM_OT_context_toggle_enum)
-bpy.ops.add(WM_OT_context_cycle_enum)
-
diff --git a/release/scripts/modules/dynamic_menu.py b/release/scripts/modules/dynamic_menu.py
deleted file mode 100644
index ce51dc9937b..00000000000
--- a/release/scripts/modules/dynamic_menu.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import bpy
-
-def collect_baseclasses(_class, bases):
-
- if _class is type or _class is object:
- return bases
-
- bases.append(_class)
- for _superclass in _class.__bases__:
- collect_baseclasses(_superclass, bases)
-
- return bases
-
-def collect_subclasses(_class, subs):
-
- if _class is type or _class is object:
- return subs
-
- subs.append(_class)
- for _subclass in _class.__subclasses__():
- collect_subclasses(_subclass, subs)
-
- return subs
-
-class DynMenu(bpy.types.Menu):
-
- def draw(self, context):
- '''
- This is a draw function that is used to call all subclasses draw functions
- starting from the registered classes draw function and working down.
-
- DynMenu.setup() must be called first.
-
- Sort/group classes could be nice
- '''
-
- subclass_ls = []
- collect_subclasses(self.__class__, subclass_ls)
- # print(subclass_ls)
-
- for subclass in subclass_ls:
- # print("drawwing", subclass) # , dir(subclass))
- subclass.internal_draw(self, context)
- # print("subclass.internal_draw", subclass.internal_draw)
-
-def setup(menu_class):
- '''
- Setup subclasses (not needed when self.add() is used)
- '''
- bases = collect_baseclasses(menu_class, [])
-
- # Incase 'DynMenu' isnt last
- while bases[-1] is not DynMenu:
- bases.pop()
- bases.pop() # remove 'DynMenu'
-
- root_class = bases[-1] # this is the registered class
-
- for subclass in collect_subclasses(root_class, []):
- #print(subclass)
-
- draw = getattr(subclass, 'draw', None)
- if draw and not hasattr(subclass, 'internal_draw'):
- # print("replace", subclass, draw)
- try:
- del subclass.draw
- except:
- pass
- subclass.internal_draw = draw
-
- root_class.draw = DynMenu.draw
-
-def add(menu_class, func):
- '''
- Add a single function directly without having to make a class
-
- important that the returned value should be stored in the module that called it.
- '''
-
- newclass = type('<menuclass>', (menu_class,), {})
- newclass.internal_draw = func
- setup(menu_class)
- return newclass
-
-'''
-# so we dont need to import this module
-DynMenu.setup = setup
-DynMenu.add = add
-
-# Only so we can access as bpy.types.
-# dont ever use this directly!
-bpy.types.register(DynMenu)
-'''
-
-
diff --git a/release/scripts/ui/buttons_data_armature.py b/release/scripts/ui/buttons_data_armature.py
index bbec295a165..9344294ff9e 100644
--- a/release/scripts/ui/buttons_data_armature.py
+++ b/release/scripts/ui/buttons_data_armature.py
@@ -88,7 +88,7 @@ class DATA_PT_bone_groups(DataButtonsPanel):
pose = ob.pose
row = layout.row()
- row.template_list(pose, "bone_groups", pose, "active_bone_group_index", rows=2)
+ row.template_list(pose, "bone_groups", pose, "active_bone_group_index")
col = row.column(align=True)
col.active = (ob.proxy == None)
diff --git a/release/scripts/ui/buttons_data_bone.py b/release/scripts/ui/buttons_data_bone.py
index e8041cc7393..5971e4492ce 100644
--- a/release/scripts/ui/buttons_data_bone.py
+++ b/release/scripts/ui/buttons_data_bone.py
@@ -48,7 +48,7 @@ class BONE_PT_transform(BoneButtonsPanel):
else:
pchan = ob.pose.pose_channels[context.bone.name]
-
+ layout.itemR(pchan, "rotation_mode")
row = layout.row()
col = row.column()
@@ -67,8 +67,6 @@ class BONE_PT_transform(BoneButtonsPanel):
col.itemR(pchan, "rotation_euler", text="Rotation")
row.column().itemR(pchan, "scale")
-
- layout.itemR(pchan, "rotation_mode")
class BONE_PT_transform_locks(BoneButtonsPanel):
__label__ = "Transform Locks"
@@ -100,8 +98,8 @@ class BONE_PT_transform_locks(BoneButtonsPanel):
row.column().itemR(pchan, "lock_scale")
-class BONE_PT_relations(BoneButtonsPanel):
- __label__ = "Relations"
+class BONE_PT_bone(BoneButtonsPanel):
+ __label__ = "Bone"
def draw(self, context):
layout = self.layout
@@ -117,17 +115,7 @@ class BONE_PT_relations(BoneButtonsPanel):
pchan = ob.pose.pose_channels[context.bone.name]
split = layout.split()
-
- col = split.column()
- col.itemL(text="Layers:")
- col.itemR(bone, "layer", text="")
-
- col.itemS()
-
- if ob and pchan:
- col.itemL(text="Bone Group:")
- col.item_pointerR(pchan, "bone_group", ob.pose, "bone_groups", text="")
-
+
col = split.column()
col.itemL(text="Parent:")
if context.bone:
@@ -135,46 +123,119 @@ class BONE_PT_relations(BoneButtonsPanel):
else:
col.item_pointerR(bone, "parent", arm, "edit_bones", text="")
- sub = col.column()
- sub.active = bone.parent != None
- sub.itemR(bone, "connected")
- sub.itemR(bone, "hinge", text="Inherit Rotation")
- sub.itemR(bone, "inherit_scale", text="Inherit Scale")
-
-
-class BONE_PT_display(BoneButtonsPanel):
- __label__ = "Display"
-
- def poll(self, context):
- return context.bone
-
- def draw(self, context):
- layout = self.layout
+ row = col.row()
+ row.active = bone.parent != None
+ row.itemR(bone, "connected")
- ob = context.object
- bone = context.bone
- arm = context.armature
+ col.itemL(text="Layers:")
+ col.itemR(bone, "layer", text="")
- if not bone:
- bone = context.edit_bone
- pchan = None
- else:
- pchan = ob.pose.pose_channels[context.bone.name]
+ col = split.column()
+ col.itemL(text="Inherit:")
+ col.itemR(bone, "hinge", text="Rotation")
+ col.itemR(bone, "inherit_scale", text="Scale")
+ col.itemL(text="Display:")
+ col.itemR(bone, "draw_wire", text="Wireframe")
+ col.itemR(bone, "hidden", text="Hide")
if ob and pchan:
-
split = layout.split()
-
- col = split.column()
-
- col.itemR(bone, "draw_wire", text="Wireframe")
- col.itemR(bone, "hidden", text="Hide")
col = split.column()
+ col.itemL(text="Bone Group:")
+ col.item_pointerR(pchan, "bone_group", ob.pose, "bone_groups", text="")
+ col = split.column()
col.itemL(text="Custom Shape:")
col.itemR(pchan, "custom_shape", text="")
+class BONE_PT_inverse_kinematics(BoneButtonsPanel):
+ __label__ = "Inverse Kinematics"
+ __default_closed__ = True
+
+ def poll(self, context):
+ ob = context.object
+ bone = context.bone
+
+ if ob and context.bone:
+ pchan = ob.pose.pose_channels[context.bone.name]
+ return pchan.has_ik
+
+ return False
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ bone = context.bone
+ pchan = ob.pose.pose_channels[context.bone.name]
+
+ row = layout.row()
+ row.itemR(ob.pose, "ik_solver")
+
+ split = layout.split(percentage=0.25)
+ split.itemR(pchan, "ik_dof_x", text="X")
+ row = split.row()
+ row.itemR(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
+ row.active = pchan.ik_dof_x
+
+ split = layout.split(percentage=0.25)
+ row = split.row()
+ row.itemR(pchan, "ik_limit_x", text="Limit")
+ row.active = pchan.ik_dof_x
+ row = split.row(align=True)
+ row.itemR(pchan, "ik_min_x", text="")
+ row.itemR(pchan, "ik_max_x", text="")
+ row.active = pchan.ik_dof_x and pchan.ik_limit_x
+
+ split = layout.split(percentage=0.25)
+ split.itemR(pchan, "ik_dof_y", text="Y")
+ row = split.row()
+ row.itemR(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
+ row.active = pchan.ik_dof_y
+
+ split = layout.split(percentage=0.25)
+ row = split.row()
+ row.itemR(pchan, "ik_limit_y", text="Limit")
+ row.active = pchan.ik_dof_y
+ row = split.row(align=True)
+ row.itemR(pchan, "ik_min_y", text="")
+ row.itemR(pchan, "ik_max_y", text="")
+ row.active = pchan.ik_dof_y and pchan.ik_limit_y
+
+ split = layout.split(percentage=0.25)
+ split.itemR(pchan, "ik_dof_z", text="Z")
+ row = split.row()
+ row.itemR(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
+ row.active = pchan.ik_dof_z
+
+ split = layout.split(percentage=0.25)
+ row = split.row()
+ row.itemR(pchan, "ik_limit_z", text="Limit")
+ row.active = pchan.ik_dof_z
+ row = split.row(align=True)
+ row.itemR(pchan, "ik_min_z", text="")
+ row.itemR(pchan, "ik_max_z", text="")
+ row.active = pchan.ik_dof_z and pchan.ik_limit_z
+ split = layout.split()
+ split.itemR(pchan, "ik_stretch", text="Stretch", slider=True)
+ split.itemL()
+
+ if ob.pose.ik_solver == "ITASC":
+ layout.itemL(text="Joint constraint:")
+ split = layout.split(percentage=0.3)
+ row = split.row()
+ row.itemR(pchan, "ik_rot_control", text="Rotation")
+ row = split.row()
+ row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True)
+ row.active = pchan.ik_rot_control
+ # not supported yet
+ #split = layout.split(percentage=0.3)
+ #row = split.row()
+ #row.itemR(pchan, "ik_lin_control", text="Size")
+ #row = split.row()
+ #row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True)
+ #row.active = pchan.ik_lin_control
class BONE_PT_deform(BoneButtonsPanel):
__label__ = "Deform"
@@ -224,10 +285,65 @@ class BONE_PT_deform(BoneButtonsPanel):
col.itemL(text="Offset:")
col.itemR(bone, "cyclic_offset")
+class BONE_PT_iksolver_itasc(BoneButtonsPanel):
+ __idname__ = "BONE_PT_iksolver_itasc"
+ __label__ = "iTaSC parameters"
+ __default_closed__ = True
+
+ def poll(self, context):
+ ob = context.object
+ bone = context.bone
+
+ if ob and context.bone:
+ pchan = ob.pose.pose_channels[context.bone.name]
+ return pchan.has_ik and ob.pose.ik_solver == "ITASC" and ob.pose.ik_param
+
+ return False
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ itasc = ob.pose.ik_param
+
+ layout.row().itemR(itasc, "simulation")
+ if itasc.simulation:
+ split = layout.split()
+ row = split.row()
+ row.itemR(itasc, "reiteration")
+ row = split.row()
+ if itasc.reiteration:
+ itasc.initial_reiteration = True
+ row.itemR(itasc, "initial_reiteration")
+ row.active = not itasc.reiteration
+
+ flow = layout.column_flow()
+ flow.itemR(itasc, "precision")
+ flow.itemR(itasc, "num_iter")
+ flow.active = not itasc.simulation or itasc.initial_reiteration or itasc.reiteration
+
+ if itasc.simulation:
+ layout.itemR(itasc, "auto_step")
+ row = layout.row()
+ if itasc.auto_step:
+ row.itemR(itasc, "min_step")
+ row.itemR(itasc, "max_step")
+ else:
+ row.itemR(itasc, "num_step")
+
+ layout.itemR(itasc, "solver")
+ if itasc.simulation:
+ layout.itemR(itasc, "feedback")
+ layout.itemR(itasc, "max_velocity")
+ if itasc.solver == "DLS":
+ row = layout.row()
+ row.itemR(itasc, "dampmax")
+ row.itemR(itasc, "dampeps")
bpy.types.register(BONE_PT_context_bone)
bpy.types.register(BONE_PT_transform)
bpy.types.register(BONE_PT_transform_locks)
-bpy.types.register(BONE_PT_relations)
-bpy.types.register(BONE_PT_display)
+bpy.types.register(BONE_PT_bone)
bpy.types.register(BONE_PT_deform)
+bpy.types.register(BONE_PT_inverse_kinematics)
+bpy.types.register(BONE_PT_iksolver_itasc)
diff --git a/release/scripts/ui/buttons_data_lamp.py b/release/scripts/ui/buttons_data_lamp.py
index 4e495d158eb..86ca5beb9b5 100644
--- a/release/scripts/ui/buttons_data_lamp.py
+++ b/release/scripts/ui/buttons_data_lamp.py
@@ -202,7 +202,7 @@ class DATA_PT_shadow(DataButtonsPanel):
col.itemL(text="Buffer Type:")
col.row().itemR(lamp, "shadow_buffer_type", expand=True)
- if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY', 'DEEP'):
+ if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY'):
split = layout.split()
col = split.column()
@@ -218,8 +218,6 @@ class DATA_PT_shadow(DataButtonsPanel):
sub = col.column(align=True)
sub.itemR(lamp, "shadow_buffer_size", text="Size")
sub.itemR(lamp, "shadow_buffer_samples", text="Samples")
- if lamp.shadow_buffer_type == 'DEEP':
- col.itemR(lamp, "compression_threshold")
elif lamp.shadow_buffer_type == 'IRREGULAR':
layout.itemR(lamp, "shadow_buffer_bias", text="Bias")
@@ -251,7 +249,7 @@ class DATA_PT_area(DataButtonsPanel):
split = layout.split()
col = split.column()
- col.row().itemR(lamp, "shape", expand=True)
+ col.itemR(lamp, "shape", text="")
sub = col.column(align=True)
if (lamp.shape == 'SQUARE'):
@@ -275,9 +273,9 @@ class DATA_PT_spot(DataButtonsPanel):
split = layout.split()
col = split.column()
- sub = col.column()
+ sub = col.column(align=True)
sub.itemR(lamp, "spot_size", text="Size")
- sub.itemR(lamp, "spot_blend", text="Blend", slider=True)
+ sub.itemR(lamp, "spot_blend", text="Blend")
col.itemR(lamp, "square")
col = split.column()
diff --git a/release/scripts/ui/buttons_data_mesh.py b/release/scripts/ui/buttons_data_mesh.py
index 8dc5af5cf4f..780ae3ac8f9 100644
--- a/release/scripts/ui/buttons_data_mesh.py
+++ b/release/scripts/ui/buttons_data_mesh.py
@@ -48,22 +48,6 @@ class DATA_PT_normals(DataButtonsPanel):
col.itemR(mesh, "vertex_normal_flip")
col.itemR(mesh, "double_sided")
-class DATA_PT_settings(DataButtonsPanel):
- __label__ = "Settings"
-
- def draw(self, context):
- layout = self.layout
-
- mesh = context.mesh
-
- split = layout.split()
-
- col = split.column()
- col.itemR(mesh, "texture_mesh")
-
- col = split.column()
- col.itemR(mesh, "use_mirror_x")
-
class DATA_PT_vertex_groups(DataButtonsPanel):
__label__ = "Vertex Groups"
@@ -82,9 +66,9 @@ class DATA_PT_vertex_groups(DataButtonsPanel):
col.itemO("object.vertex_group_add", icon='ICON_ZOOMIN', text="")
col.itemO("object.vertex_group_remove", icon='ICON_ZOOMOUT', text="")
- col.itemO("object.vertex_group_copy", icon='ICON_COPY_ID', text="")
+ col.itemO("object.vertex_group_copy", icon='ICON_COPYDOWN', text="")
if ob.data.users > 1:
- col.itemO("object.vertex_group_copy_to_linked", icon='ICON_LINK_AREA', text="")
+ col.itemO("object.vertex_group_copy_to_linked", icon='ICON_COPYDOWN', text="")
group = ob.active_vertex_group
if group:
@@ -131,7 +115,7 @@ class DATA_PT_shape_keys(DataButtonsPanel):
subcol = col.column(align=True)
subcol.itemR(ob, "shape_key_lock", icon='ICON_UNPINNED', text="")
- subcol.itemR(kb, "mute", icon='ICON_MUTE_IPO_OFF', text="")
+ subcol.itemR(kb, "mute", icon='ICON_MUTE_IPO_ON', text="")
if key.relative:
row = layout.row()
@@ -213,7 +197,6 @@ class DATA_PT_vertex_colors(DataButtonsPanel):
bpy.types.register(DATA_PT_context_mesh)
bpy.types.register(DATA_PT_normals)
-bpy.types.register(DATA_PT_settings)
bpy.types.register(DATA_PT_vertex_groups)
bpy.types.register(DATA_PT_shape_keys)
bpy.types.register(DATA_PT_uv_texture)
diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py
index e0e2fc736c0..ee7193da301 100644
--- a/release/scripts/ui/buttons_material.py
+++ b/release/scripts/ui/buttons_material.py
@@ -1,19 +1,6 @@
import bpy
-def active_node_mat(mat):
- # TODO, 2.4x has a pipeline section, for 2.5 we need to communicate
- # which settings from node-materials are used
- if mat:
- mat_node = mat.active_node_material
- if mat_node:
- return mat_node
- else:
- return mat
-
- return None
-
-
class MaterialButtonsPanel(bpy.types.Panel):
__space_type__ = 'PROPERTIES'
__region_type__ = 'WINDOW'
@@ -59,7 +46,6 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel):
col = row.column(align=True)
col.itemO("object.material_slot_add", icon='ICON_ZOOMIN', text="")
col.itemO("object.material_slot_remove", icon='ICON_ZOOMOUT', text="")
- col.itemO("object.material_slot_copy", icon='ICON_COPY_ID', text="")
if ob.mode == 'EDIT':
row = layout.row(align=True)
@@ -88,14 +74,14 @@ class MATERIAL_PT_shading(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
if mat.type in ('SURFACE', 'WIRE'):
split = layout.split()
@@ -131,7 +117,7 @@ class MATERIAL_PT_strand(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
- mat = context.material # dont use node material
+ mat = context.material
tan = mat.strand
split = layout.split()
@@ -166,7 +152,7 @@ class MATERIAL_PT_physics(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
- phys = context.material.physics # dont use node material
+ phys = context.material.physics
split = layout.split()
@@ -185,14 +171,14 @@ class MATERIAL_PT_options(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
split = layout.split()
@@ -225,14 +211,14 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
split = layout.split()
@@ -258,14 +244,14 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
split = layout.split()
@@ -306,22 +292,20 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel):
split = row.split(percentage=0.3)
split.itemL(text="Blend:")
split.itemR(mat, "diffuse_ramp_blend", text="")
- row = layout.row()
- row.itemR(mat, "diffuse_ramp_factor", text="Factor")
class MATERIAL_PT_specular(MaterialButtonsPanel):
__label__ = "Specular"
COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
layout.active = (not mat.shadeless)
@@ -360,8 +344,6 @@ class MATERIAL_PT_specular(MaterialButtonsPanel):
split = row.split(percentage=0.3)
split.itemL(text="Blend:")
split.itemR(mat, "specular_ramp_blend", text="")
- row = layout.row()
- row.itemR(mat, "specular_ramp_factor", text="Factor")
class MATERIAL_PT_sss(MaterialButtonsPanel):
__label__ = "Subsurface Scattering"
@@ -369,12 +351,12 @@ class MATERIAL_PT_sss(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw_header(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
sss = mat.subsurface_scattering
self.layout.active = (not mat.shadeless)
@@ -383,7 +365,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
sss = mat.subsurface_scattering
layout.active = sss.enabled
@@ -414,19 +396,19 @@ class MATERIAL_PT_mirror(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw_header(self, context):
- raym = active_node_mat(context.material).raytrace_mirror
+ raym = context.material.raytrace_mirror
self.layout.itemR(raym, "enabled", text="")
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
raym = mat.raytrace_mirror
layout.active = raym.enabled
@@ -469,19 +451,19 @@ class MATERIAL_PT_transp(MaterialButtonsPanel):
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render_data.engine
return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES)
def draw_header(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
self.layout.itemR(mat, "transparency", text="")
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ mat = context.material
rayt = mat.raytrace_transparency
row = layout.row()
@@ -535,7 +517,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
- mat = context.material # dont use node material
+ mat = context.material
halo = mat.halo
split = layout.split()
@@ -587,7 +569,7 @@ class MATERIAL_PT_flare(MaterialButtonsPanel):
def draw(self, context):
layout = self.layout
- mat = context.material # dont use node material
+ mat = context.material
halo = mat.halo
layout.active = halo.flare_mode
@@ -636,7 +618,8 @@ class MATERIAL_PT_volume_density(VolumeButtonsPanel):
def draw(self, context):
layout = self.layout
- vol = context.material.volume # dont use node material
+ mat = context.material
+ vol = context.material.volume
split = layout.split()
row = split.row()
@@ -652,7 +635,7 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel):
def draw(self, context):
layout = self.layout
- vol = context.material.volume # dont use node material
+ vol = context.material.volume
split = layout.split()
@@ -677,22 +660,21 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel):
def draw(self, context):
layout = self.layout
- vol = context.material.volume # dont use node material
+ vol = context.material.volume
split = layout.split()
col = split.column()
- col.itemR(vol, "lighting_mode", text="")
+ col.itemR(vol, "scattering_mode", text="")
col = split.column()
- if vol.lighting_mode == 'SHADED':
- col.itemR(vol, "external_shadows")
+ if vol.scattering_mode == 'SINGLE_SCATTERING':
col.itemR(vol, "light_cache")
sub = col.column()
sub.active = vol.light_cache
sub.itemR(vol, "cache_resolution")
- elif vol.lighting_mode in ('MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'):
+ elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'):
sub = col.column()
sub.enabled = True
sub.active = False
@@ -712,7 +694,7 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel):
def draw(self, context):
layout = self.layout
- mat = context.material # dont use node material
+ mat = context.material
layout.itemR(mat, "transparency_method", expand=True)
@@ -724,7 +706,7 @@ class MATERIAL_PT_volume_integration(VolumeButtonsPanel):
def draw(self, context):
layout = self.layout
- vol = context.material.volume # dont use node material
+ vol = context.material.volume
split = layout.split()
diff --git a/release/scripts/ui/buttons_object.py b/release/scripts/ui/buttons_object.py
index 98ac462f2d4..c069572aa28 100644
--- a/release/scripts/ui/buttons_object.py
+++ b/release/scripts/ui/buttons_object.py
@@ -26,6 +26,8 @@ class OBJECT_PT_transform(ObjectButtonsPanel):
ob = context.object
+ layout.itemR(ob, "rotation_mode")
+
row = layout.row()
row.column().itemR(ob, "location")
@@ -41,8 +43,6 @@ class OBJECT_PT_transform(ObjectButtonsPanel):
row.column().itemR(ob, "scale")
- layout.itemR(ob, "rotation_mode")
-
class OBJECT_PT_transform_locks(ObjectButtonsPanel):
__label__ = "Transform Locks"
__default_closed__ = True
diff --git a/release/scripts/ui/buttons_object_constraint.py b/release/scripts/ui/buttons_object_constraint.py
index 63fe27f2e4b..e089cff264f 100644
--- a/release/scripts/ui/buttons_object_constraint.py
+++ b/release/scripts/ui/buttons_object_constraint.py
@@ -50,7 +50,6 @@ class ConstraintButtonsPanel(bpy.types.Panel):
layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
def ik_template(self, layout, con):
- # only used for iTaSC
layout.itemR(con, "pole_target")
if con.pole_target and con.pole_target.type == 'ARMATURE':
@@ -61,14 +60,14 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row.itemL()
row.itemR(con, "pole_angle")
- split = layout.split(percentage=0.33)
+ split = layout.split()
col = split.column()
col.itemR(con, "tail")
col.itemR(con, "stretch")
col = split.column()
+ col.itemR(con, "iterations")
col.itemR(con, "chain_length")
- col.itemR(con, "targetless")
def CHILD_OF(self, context, layout, con):
self.target_template(layout, con)
@@ -116,74 +115,24 @@ class ConstraintButtonsPanel(bpy.types.Panel):
layout.itemR(con, "ik_type")
getattr(self, "IK_"+con.ik_type)(context, layout, con)
else:
- # Legacy IK constraint
- self.target_template(layout, con)
- layout.itemR(con, "pole_target")
-
- if con.pole_target and con.pole_target.type == 'ARMATURE':
- layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
-
- if con.pole_target:
- row = layout.row()
- row.itemL()
- row.itemR(con, "pole_angle")
-
- split = layout.split()
- col = split.column()
- col.itemR(con, "tail")
- col.itemR(con, "stretch")
-
- col = split.column()
- col.itemR(con, "iterations")
- col.itemR(con, "chain_length")
-
- split = layout.split()
- col = split.column()
- col.itemL()
- col.itemR(con, "targetless")
- col.itemR(con, "rotation")
-
- col = split.column()
- col.itemL(text="Weight:")
- col.itemR(con, "weight", text="Position", slider=True)
- sub = col.column()
- sub.active = con.rotation
- sub.itemR(con, "orient_weight", text="Rotation", slider=True)
+ self.IK_COPY_POSE(context, layout, con)
def IK_COPY_POSE(self, context, layout, con):
self.target_template(layout, con)
self.ik_template(layout, con)
-
- row = layout.row()
- row.itemL(text="Axis Ref:")
- row.itemR(con, "axis_reference", expand=True)
- split = layout.split(percentage=0.33)
- split.row().itemR(con, "position")
- row = split.row()
- row.itemR(con, "weight", text="Weight", slider=True)
- row.active = con.position
- split = layout.split(percentage=0.33)
- row = split.row()
- row.itemL(text="Lock:")
- row = split.row()
- row.itemR(con, "pos_lock_x", text="X")
- row.itemR(con, "pos_lock_y", text="Y")
- row.itemR(con, "pos_lock_z", text="Z")
- split.active = con.position
-
- split = layout.split(percentage=0.33)
- split.row().itemR(con, "rotation")
- row = split.row()
- row.itemR(con, "orient_weight", text="Weight", slider=True)
- row.active = con.rotation
- split = layout.split(percentage=0.33)
- row = split.row()
- row.itemL(text="Lock:")
- row = split.row()
- row.itemR(con, "rot_lock_x", text="X")
- row.itemR(con, "rot_lock_y", text="Y")
- row.itemR(con, "rot_lock_z", text="Z")
- split.active = con.rotation
+
+ split = layout.split()
+ col = split.column()
+ col.itemL()
+ col.itemR(con, "targetless")
+ col.itemR(con, "rotation")
+
+ col = split.column()
+ col.itemL(text="Weight:")
+ col.itemR(con, "weight", text="Position", slider=True)
+ sub = col.column()
+ sub.active = con.rotation
+ sub.itemR(con, "orient_weight", text="Rotation", slider=True)
def IK_DISTANCE(self, context, layout, con):
self.target_template(layout, con)
@@ -587,138 +536,6 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel):
for con in ob.constraints:
self.draw_constraint(context, con)
-class BONE_PT_inverse_kinematics(ConstraintButtonsPanel):
- __label__ = "Inverse Kinematics"
- __default_closed__ = True
- __context__ = "bone_constraint"
-
- def poll(self, context):
- ob = context.object
- bone = context.bone
-
- if ob and bone:
- pchan = ob.pose.pose_channels[bone.name]
- return pchan.has_ik
-
- return False
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
- bone = context.bone
- pchan = ob.pose.pose_channels[bone.name]
-
- row = layout.row()
- row.itemR(ob.pose, "ik_solver")
-
- split = layout.split(percentage=0.25)
- split.itemR(pchan, "ik_dof_x", text="X")
- row = split.row()
- row.itemR(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
- row.active = pchan.ik_dof_x
-
- split = layout.split(percentage=0.25)
- row = split.row()
- row.itemR(pchan, "ik_limit_x", text="Limit")
- row.active = pchan.ik_dof_x
- row = split.row(align=True)
- row.itemR(pchan, "ik_min_x", text="")
- row.itemR(pchan, "ik_max_x", text="")
- row.active = pchan.ik_dof_x and pchan.ik_limit_x
-
- split = layout.split(percentage=0.25)
- split.itemR(pchan, "ik_dof_y", text="Y")
- row = split.row()
- row.itemR(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
- row.active = pchan.ik_dof_y
-
- split = layout.split(percentage=0.25)
- row = split.row()
- row.itemR(pchan, "ik_limit_y", text="Limit")
- row.active = pchan.ik_dof_y
- row = split.row(align=True)
- row.itemR(pchan, "ik_min_y", text="")
- row.itemR(pchan, "ik_max_y", text="")
- row.active = pchan.ik_dof_y and pchan.ik_limit_y
-
- split = layout.split(percentage=0.25)
- split.itemR(pchan, "ik_dof_z", text="Z")
- row = split.row()
- row.itemR(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
- row.active = pchan.ik_dof_z
-
- split = layout.split(percentage=0.25)
- row = split.row()
- row.itemR(pchan, "ik_limit_z", text="Limit")
- row.active = pchan.ik_dof_z
- row = split.row(align=True)
- row.itemR(pchan, "ik_min_z", text="")
- row.itemR(pchan, "ik_max_z", text="")
- row.active = pchan.ik_dof_z and pchan.ik_limit_z
- split = layout.split()
- split.itemR(pchan, "ik_stretch", text="Stretch", slider=True)
- split.itemL()
-
- if ob.pose.ik_solver == "ITASC":
- row = layout.row()
- row.itemR(pchan, "ik_rot_control", text="Control Rotation")
- row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True)
- # not supported yet
- #row = layout.row()
- #row.itemR(pchan, "ik_lin_control", text="Joint Size")
- #row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True)
-
-class BONE_PT_iksolver_itasc(ConstraintButtonsPanel):
- __label__ = "iTaSC parameters"
- __default_closed__ = True
- __context__ = "bone_constraint"
-
- def poll(self, context):
- ob = context.object
- bone = context.bone
-
- if ob and bone:
- pchan = ob.pose.pose_channels[bone.name]
- return pchan.has_ik and ob.pose.ik_solver == "ITASC" and ob.pose.ik_param
-
- return False
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
- itasc = ob.pose.ik_param
-
- layout.itemR(itasc, "mode", expand=True)
- simulation = itasc.mode == "SIMULATION"
- if simulation:
- layout.itemL(text="Reiteration:")
- layout.itemR(itasc, "reiteration", expand=True)
-
- flow = layout.column_flow()
- flow.itemR(itasc, "precision", text="Prec")
- flow.itemR(itasc, "num_iter", text="Iter")
- flow.active = not simulation or itasc.reiteration != "NEVER"
-
- if simulation:
- layout.itemR(itasc, "auto_step")
- row = layout.row()
- if itasc.auto_step:
- row.itemR(itasc, "min_step", text="Min")
- row.itemR(itasc, "max_step", text="Max")
- else:
- row.itemR(itasc, "num_step")
-
- layout.itemR(itasc, "solver")
- if simulation:
- layout.itemR(itasc, "feedback")
- layout.itemR(itasc, "max_velocity")
- if itasc.solver == "DLS":
- row = layout.row()
- row.itemR(itasc, "dampmax", text="Damp", slider=True)
- row.itemR(itasc, "dampeps", text="Eps", slider=True)
-
class BONE_PT_constraints(ConstraintButtonsPanel):
__label__ = "Constraints"
__context__ = "bone_constraint"
@@ -741,6 +558,4 @@ class BONE_PT_constraints(ConstraintButtonsPanel):
self.draw_constraint(context, con)
bpy.types.register(OBJECT_PT_constraints)
-bpy.types.register(BONE_PT_iksolver_itasc)
-bpy.types.register(BONE_PT_inverse_kinematics)
bpy.types.register(BONE_PT_constraints)
diff --git a/release/scripts/ui/buttons_particle.py b/release/scripts/ui/buttons_particle.py
index b0be974727a..1a800fc4dfd 100644
--- a/release/scripts/ui/buttons_particle.py
+++ b/release/scripts/ui/buttons_particle.py
@@ -6,8 +6,8 @@ from buttons_physics_common import effector_weights_ui
from buttons_physics_common import basic_force_field_settings_ui
from buttons_physics_common import basic_force_field_falloff_ui
-def particle_panel_enabled(context, psys):
- return psys.point_cache.baked==False and psys.edited==False and (not context.particle_system_editable)
+def particle_panel_enabled(psys):
+ return psys.point_cache.baked==False and psys.edited==False
def particle_panel_poll(context):
psys = context.particle_system
@@ -78,7 +78,7 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
return
row=col.row()
- row.enabled = particle_panel_enabled(context, psys)
+ row.enabled = particle_panel_enabled(psys)
row.itemR(part, "type", text="")
row.itemR(psys, "seed")
@@ -89,7 +89,7 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
else:
split.itemL(text="")
row = split.row()
- row.enabled = particle_panel_enabled(context, psys)
+ row.enabled = particle_panel_enabled(psys)
row.itemR(part, "hair_step")
if psys.edited==True:
if psys.global_hair:
@@ -99,7 +99,7 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
layout.itemO("particle.disconnect_hair")
layout.itemL(text="")
elif part.type=='REACTOR':
- split.enabled = particle_panel_enabled(context, psys)
+ split.enabled = particle_panel_enabled(psys)
split.itemR(psys, "reactor_target_object")
split.itemR(psys, "reactor_target_particle_system", text="Particle System")
@@ -118,22 +118,20 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
psys = context.particle_system
part = psys.settings
- layout.enabled = particle_panel_enabled(context, psys) and not psys.multiple_caches
+ layout.enabled = particle_panel_enabled(psys) and not psys.multiple_caches
row = layout.row()
- row.active = part.distribution != 'GRID'
row.itemR(part, "amount")
- if part.type != 'HAIR':
- split = layout.split()
-
- col = split.column(align=True)
- col.itemR(part, "start")
- col.itemR(part, "end")
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.itemR(part, "start")
+ col.itemR(part, "end")
- col = split.column(align=True)
- col.itemR(part, "lifetime")
- col.itemR(part, "random_lifetime", slider=True)
+ col = split.column(align=True)
+ col.itemR(part, "lifetime")
+ col.itemR(part, "random_lifetime", slider=True)
layout.row().itemL(text="Emit From:")
@@ -221,9 +219,9 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
psys = context.particle_system
- point_cache_ui(self, psys.point_cache, particle_panel_enabled(context, psys), not psys.hair_dynamics, 0)
+ point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0)
-class PARTICLE_PT_velocity(ParticleButtonsPanel):
+class PARTICLE_PT_initial(ParticleButtonsPanel):
__label__ = "Velocity"
def poll(self, context):
@@ -239,67 +237,49 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel):
psys = context.particle_system
part = psys.settings
- layout.enabled = particle_panel_enabled(context, psys)
+ layout.enabled = particle_panel_enabled(psys)
+
+ layout.row().itemL(text="Direction:")
split = layout.split()
sub = split.column()
- sub.itemL(text="Emitter Geometry:")
sub.itemR(part, "normal_factor")
- subsub = sub.column(align=True)
- subsub.itemR(part, "tangent_factor")
- subsub.itemR(part, "tangent_phase", slider=True)
-
- sub = split.column()
- sub.itemL(text="Emitter Object")
- sub.itemR(part, "object_aligned_factor", text="")
-
- layout.row().itemL(text="Other:")
- split = layout.split()
- sub = split.column()
if part.emit_from=='PARTICLE':
sub.itemR(part, "particle_factor")
else:
sub.itemR(part, "object_factor", slider=True)
- sub = split.column()
sub.itemR(part, "random_factor")
+ sub.itemR(part, "tangent_factor")
+ sub.itemR(part, "tangent_phase", slider=True)
- #if part.type=='REACTOR':
- # sub.itemR(part, "reactor_factor")
- # sub.itemR(part, "reaction_shape", slider=True)
+ sub = split.column()
+ sub.itemL(text="TODO:")
+ sub.itemL(text="Object aligned")
+ sub.itemL(text="direction: X, Y, Z")
-class PARTICLE_PT_rotation(ParticleButtonsPanel):
- __label__ = "Rotation"
-
- def poll(self, context):
- if particle_panel_poll(context):
- psys = context.particle_system
- return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
+ if part.type=='REACTOR':
+ sub.itemR(part, "reactor_factor")
+ sub.itemR(part, "reaction_shape", slider=True)
else:
- return False
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = psys.settings
-
- layout.enabled = particle_panel_enabled(context, psys)
+ sub.itemL(text="")
- split = layout.split()
- split.itemL(text="Initial Rotation:")
- split.itemR(part, "rotation_dynamic")
+ layout.row().itemL(text="Rotation:")
split = layout.split()
- sub = split.column(align=True)
- sub.itemR(part, "rotation_mode", text="")
- sub.itemR(part, "random_rotation_factor", slider=True, text="Random")
+ sub = split.column()
+
+ sub.itemR(part, "rotation_mode", text="Axis")
+ split = layout.split()
- sub = split.column(align=True)
+ sub = split.column()
+ sub.itemR(part, "rotation_dynamic")
+ sub.itemR(part, "random_rotation_factor", slider=True)
+ sub = split.column()
sub.itemR(part, "phase_factor", slider=True)
sub.itemR(part, "random_phase_factor", text="Random", slider=True)
- layout.row().itemL(text="Angular Velocity:")
+ layout.row().itemL(text="Angular velocity:")
layout.row().itemR(part, "angular_velocity_mode", expand=True)
split = layout.split()
@@ -322,7 +302,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
psys = context.particle_system
part = psys.settings
- layout.enabled = particle_panel_enabled(context, psys)
+ layout.enabled = particle_panel_enabled(psys)
row = layout.row()
row.itemR(part, "physics_type", expand=True)
@@ -461,7 +441,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
boids = context.particle_system.settings.boids
layout = self.layout
- layout.enabled = particle_panel_enabled(context, context.particle_system)
+ layout.enabled = particle_panel_enabled(context.particle_system)
# Currently boids can only use the first state so these are commented out for now.
#row = layout.row()
@@ -627,37 +607,16 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
elif part.ren_as == 'OBJECT':
sub.itemR(part, "dupli_object")
- sub.itemR(part, "use_global_dupli")
elif part.ren_as == 'GROUP':
sub.itemR(part, "dupli_group")
split = layout.split()
sub = split.column()
sub.itemR(part, "whole_group")
- colsub = sub.column()
- colsub.active = part.whole_group == False
- colsub.itemR(part, "use_group_count")
-
sub = split.column()
colsub = sub.column()
colsub.active = part.whole_group == False
- colsub.itemR(part, "use_global_dupli")
colsub.itemR(part, "rand_group")
- if part.use_group_count and not part.whole_group:
- row = layout.row()
- row.template_list(part, "dupliweights", part, "active_dupliweight_index")
-
- col = row.column()
- subrow = col.row()
- subcol = subrow.column(align=True)
- subcol.itemO("particle.dupliob_move_up", icon='VICON_MOVE_UP', text="")
- subcol.itemO("particle.dupliob_move_down", icon='VICON_MOVE_DOWN', text="")
-
- weight = part.active_dupliweight
- if weight:
- row = layout.row()
- row.itemR(weight, "count")
-
elif part.ren_as == 'BILLBOARD':
sub.itemL(text="Align:")
@@ -939,8 +898,7 @@ bpy.types.register(PARTICLE_PT_particles)
bpy.types.register(PARTICLE_PT_hair_dynamics)
bpy.types.register(PARTICLE_PT_cache)
bpy.types.register(PARTICLE_PT_emission)
-bpy.types.register(PARTICLE_PT_velocity)
-bpy.types.register(PARTICLE_PT_rotation)
+bpy.types.register(PARTICLE_PT_initial)
bpy.types.register(PARTICLE_PT_physics)
bpy.types.register(PARTICLE_PT_boidbrain)
bpy.types.register(PARTICLE_PT_render)
diff --git a/release/scripts/ui/buttons_physics_common.py b/release/scripts/ui/buttons_physics_common.py
index 17ac1b2bbaa..b65d092fcfa 100644
--- a/release/scripts/ui/buttons_physics_common.py
+++ b/release/scripts/ui/buttons_physics_common.py
@@ -78,7 +78,7 @@ def effector_weights_ui(self, weights):
layout.itemS()
flow = layout.column_flow()
- flow.itemR(weights, "force", slider=True)
+ flow.itemR(weights, "spherical", slider=True)
flow.itemR(weights, "vortex", slider=True)
flow.itemR(weights, "magnetic", slider=True)
flow.itemR(weights, "wind", slider=True)
@@ -110,7 +110,7 @@ def basic_force_field_settings_ui(self, field):
col.itemR(field, "flow")
elif field.type == 'HARMONIC':
col.itemR(field, "harmonic_damping", text="Damping")
- elif field.type == 'VORTEX' and field.shape != 'POINT':
+ elif field.type == 'VORTEX' and field.shape == 'PLANE':
col.itemR(field, "inflow")
elif field.type == 'DRAG':
col.itemR(field, "quadratic_drag", text="Quadratic")
@@ -140,7 +140,6 @@ def basic_force_field_falloff_ui(self, field):
col.itemR(field, "z_direction", text="")
col.itemR(field, "use_min_distance", text="Use Minimum")
col.itemR(field, "use_max_distance", text="Use Maximum")
- col.itemR(field, "do_absorption")
col = split.column()
col.itemR(field, "falloff_power", text="Power")
diff --git a/release/scripts/ui/buttons_physics_field.py b/release/scripts/ui/buttons_physics_field.py
index 9aec0404ab1..24740acc68f 100644
--- a/release/scripts/ui/buttons_physics_field.py
+++ b/release/scripts/ui/buttons_physics_field.py
@@ -21,6 +21,8 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
ob = context.object
field = ob.field
+
+ #layout.active = field.enabled
split = layout.split(percentage=0.2)
split.itemL(text="Type:")
@@ -37,33 +39,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
if field.type == 'NONE':
return # nothing to draw
elif field.type == 'GUIDE':
- col = split.column()
- col.itemR(field, "guide_minimum")
- col.itemR(field, "guide_free")
- col.itemR(field, "falloff_power")
- col.itemR(field, "guide_path_add")
-
- col = split.column()
- col.itemL(text="Clumping:")
- col.itemR(field, "guide_clump_amount")
- col.itemR(field, "guide_clump_shape")
-
- row = layout.row()
- row.itemR(field, "use_max_distance")
- sub = row.row()
- sub.active = field.use_max_distance
- sub.itemR(field, "maximum_distance")
-
- layout.itemS()
-
- layout.itemR(field, "guide_kink_type")
- if (field.guide_kink_type != "NONE"):
- layout.itemR(field, "guide_kink_axis")
-
- flow = layout.column_flow()
- flow.itemR(field, "guide_kink_frequency")
- flow.itemR(field, "guide_kink_shape")
- flow.itemR(field, "guide_kink_amplitude")
+ layout.itemR(field, "guide_path_add")
elif field.type == 'TEXTURE':
col = split.column()
col.itemR(field, "strength")
@@ -126,6 +102,17 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
sub = col.column()
sub.active = field.use_radial_max
sub.itemR(field, "radial_maximum", text="Distance")
+
+ #if ob.type in 'CURVE':
+ #if field.type == 'GUIDE':
+ #colsub = col.column(align=True)
+
+ #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):
__label__ = "Collision"
diff --git a/release/scripts/ui/buttons_physics_smoke.py b/release/scripts/ui/buttons_physics_smoke.py
index b1523148a30..1541b0bae14 100644
--- a/release/scripts/ui/buttons_physics_smoke.py
+++ b/release/scripts/ui/buttons_physics_smoke.py
@@ -1,8 +1,7 @@
import bpy
-from buttons_physics_common import point_cache_ui
-from buttons_physics_common import effector_weights_ui
+from buttons_particle import point_cache_ui
class PhysicButtonsPanel(bpy.types.Panel):
__space_type__ = 'PROPERTIES'
@@ -172,21 +171,8 @@ class PHYSICS_PT_smoke_cache_highres(PhysicButtonsPanel):
cache = md.point_cache_high
point_cache_ui(self, cache, cache.baked==False, 0, 1)
-
-class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel):
- __label__ = "Smoke Field Weights"
- __default_closed__ = True
-
- def poll(self, context):
- smoke = context.smoke
- return (smoke and smoke.smoke_type == 'TYPE_DOMAIN')
-
- def draw(self, context):
- domain = context.smoke.domain_settings
- effector_weights_ui(self, domain.effector_weights)
bpy.types.register(PHYSICS_PT_smoke)
-bpy.types.register(PHYSICS_PT_smoke_field_weights)
bpy.types.register(PHYSICS_PT_smoke_cache)
bpy.types.register(PHYSICS_PT_smoke_highres)
bpy.types.register(PHYSICS_PT_smoke_groups)
diff --git a/release/scripts/ui/buttons_render.py b/release/scripts/ui/buttons_render.py
deleted file mode 100644
index 0826c766ce3..00000000000
--- a/release/scripts/ui/buttons_render.py
+++ /dev/null
@@ -1,454 +0,0 @@
-
-import bpy
-
-class RenderButtonsPanel(bpy.types.Panel):
- __space_type__ = 'PROPERTIES'
- __region_type__ = 'WINDOW'
- __context__ = "render"
- # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
-
- def poll(self, context):
- rd = context.scene.render_data
- return (context.scene and rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
-
-class RENDER_PT_render(RenderButtonsPanel):
- __label__ = "Render"
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- row = layout.row()
- row.itemO("screen.render", text="Image", icon='ICON_RENDER_STILL')
- row.item_booleanO("screen.render", "animation", True, text="Animation", icon='ICON_RENDER_ANIMATION')
-
- layout.itemR(rd, "display_mode", text="Display")
-
-class RENDER_PT_layers(RenderButtonsPanel):
- __label__ = "Layers"
- __default_closed__ = True
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render_data
-
- row = layout.row()
- row.template_list(rd, "layers", rd, "active_layer_index", rows=2)
-
- col = row.column(align=True)
- col.itemO("scene.render_layer_add", icon='ICON_ZOOMIN', text="")
- col.itemO("scene.render_layer_remove", icon='ICON_ZOOMOUT', text="")
-
- rl = rd.layers[rd.active_layer_index]
-
- if rl:
- layout.itemR(rl, "name")
-
- split = layout.split()
-
- col = split.column()
- col.itemR(scene, "visible_layers", text="Scene")
- col = split.column()
- col.itemR(rl, "visible_layers", text="Layer")
-
- layout.itemR(rl, "light_override", text="Light")
- layout.itemR(rl, "material_override", text="Material")
-
- layout.itemS()
- layout.itemL(text="Include:")
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rl, "zmask")
- row = col.row()
- row.itemR(rl, "zmask_negate", text="Negate")
- row.active = rl.zmask
- col.itemR(rl, "all_z")
-
- col = split.column()
- col.itemR(rl, "solid")
- col.itemR(rl, "halo")
- col.itemR(rl, "ztransp")
-
- col = split.column()
- col.itemR(rl, "sky")
- col.itemR(rl, "edge")
- col.itemR(rl, "strand")
-
- if rl.zmask:
- split = layout.split()
- split.itemL(text="Zmask Layers:")
- split.column().itemR(rl, "zmask_layers", text="")
-
- layout.itemS()
-
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Passes:")
- col.itemR(rl, "pass_combined")
- col.itemR(rl, "pass_z")
- col.itemR(rl, "pass_vector")
- col.itemR(rl, "pass_normal")
- col.itemR(rl, "pass_uv")
- col.itemR(rl, "pass_mist")
- col.itemR(rl, "pass_object_index")
-
- col = split.column()
- col.itemL()
- col.itemR(rl, "pass_color")
- col.itemR(rl, "pass_diffuse")
- row = col.row()
- row.itemR(rl, "pass_specular")
- row.itemR(rl, "pass_specular_exclude", text="", icon='ICON_X')
- row = col.row()
- row.itemR(rl, "pass_shadow")
- row.itemR(rl, "pass_shadow_exclude", text="", icon='ICON_X')
- row = col.row()
- row.itemR(rl, "pass_ao")
- row.itemR(rl, "pass_ao_exclude", text="", icon='ICON_X')
- row = col.row()
- row.itemR(rl, "pass_reflection")
- row.itemR(rl, "pass_reflection_exclude", text="", icon='ICON_X')
- row = col.row()
- row.itemR(rl, "pass_refraction")
- row.itemR(rl, "pass_refraction_exclude", text="", icon='ICON_X')
-
-class RENDER_PT_shading(RenderButtonsPanel):
- __label__ = "Shading"
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "render_textures", text="Textures")
- col.itemR(rd, "render_shadows", text="Shadows")
- col.itemR(rd, "render_sss", text="Subsurface Scattering")
- col.itemR(rd, "render_envmaps", text="Environment Map")
-
- col = split.column()
- col.itemR(rd, "render_raytracing", text="Ray Tracing")
- col.itemR(rd, "color_management")
- col.itemR(rd, "alpha_mode", text="Alpha")
-
-class RENDER_PT_performance(RenderButtonsPanel):
- __label__ = "Performance"
- __default_closed__ = True
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- split = layout.split()
-
- col = split.column(align=True)
- col.itemL(text="Threads:")
- col.row().itemR(rd, "threads_mode", expand=True)
- sub = col.column()
- sub.enabled = rd.threads_mode == 'THREADS_FIXED'
- sub.itemR(rd, "threads")
- col.itemL(text="Tiles:")
- col.itemR(rd, "parts_x", text="X")
- col.itemR(rd, "parts_y", text="Y")
-
- col = split.column()
- col.itemL(text="Memory:")
- sub = col.column()
- sub.itemR(rd, "save_buffers")
- sub.enabled = not rd.full_sample
- sub = col.column()
- sub.active = rd.use_compositing
- sub.itemR(rd, "free_image_textures")
- sub = col.column()
- sub.active = rd.render_raytracing
- sub.itemL(text="Acceleration structure:")
- sub.itemR(rd, "raytrace_structure", text="")
- if rd.raytrace_structure == "OCTREE":
- sub.itemR(rd, "octree_resolution", text="Resolution")
- else:
- sub.itemR(rd, "use_instances", text="Instances")
- sub.itemR(rd, "use_local_coords", text="Local Coordinates")
-
-class RENDER_PT_post_processing(RenderButtonsPanel):
- __label__ = "Post Processing"
- __default_closed__ = True
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "use_compositing")
- col.itemR(rd, "use_sequencer")
-
- col = split.column()
- col.itemR(rd, "dither_intensity", text="Dither", slider=True)
-
- layout.itemS()
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "fields", text="Fields")
- sub = col.column()
- sub.active = rd.fields
- sub.row().itemR(rd, "field_order", expand=True)
- sub.itemR(rd, "fields_still", text="Still")
-
- col = split.column()
- col.itemR(rd, "edge")
- sub = col.column()
- sub.active = rd.edge
- sub.itemR(rd, "edge_threshold", text="Threshold", slider=True)
- sub.itemR(rd, "edge_color", text="")
-
-class RENDER_PT_output(RenderButtonsPanel):
- __label__ = "Output"
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- layout.itemR(rd, "output_path", text="")
-
- split = layout.split()
- col = split.column()
- col.itemR(rd, "file_format", text="")
- col.row().itemR(rd, "color_mode", text="Color", expand=True)
-
- col = split.column()
- col.itemR(rd, "file_extensions")
- col.itemR(rd, "use_overwrite")
- col.itemR(rd, "use_placeholder")
-
- if rd.file_format in ('AVIJPEG', 'JPEG'):
- split = layout.split()
- split.itemR(rd, "quality", slider=True)
-
- elif rd.file_format == 'OPENEXR':
- split = layout.split()
-
- col = split.column()
- col.itemL(text="Codec:")
- col.itemR(rd, "exr_codec", text="")
-
- subsplit = split.split()
- col = subsplit.column()
- col.itemR(rd, "exr_half")
- col.itemR(rd, "exr_zbuf")
- col = subsplit.column()
- col.itemR(rd, "exr_preview")
-
- elif rd.file_format == 'JPEG2000':
- split = layout.split()
- col = split.column()
- col.itemL(text="Depth:")
- col.row().itemR(rd, "jpeg2k_depth", expand=True)
-
- col = split.column()
- col.itemR(rd, "jpeg2k_preset", text="")
- col.itemR(rd, "jpeg2k_ycc")
-
- elif rd.file_format in ('CINEON', 'DPX'):
- split = layout.split()
- col = split.column()
- col.itemR(rd, "cineon_log", text="Convert to Log")
-
- col = split.column(align=True)
- col.active = rd.cineon_log
- col.itemR(rd, "cineon_black", text="Black")
- col.itemR(rd, "cineon_white", text="White")
- col.itemR(rd, "cineon_gamma", text="Gamma")
-
- elif rd.file_format == 'TIFF':
- split = layout.split()
- split.itemR(rd, "tiff_bit")
-
-class RENDER_PT_encoding(RenderButtonsPanel):
- __label__ = "Encoding"
- __default_closed__ = True
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def poll(self, context):
- rd = context.scene.render_data
- return rd.file_format in ('FFMPEG', 'XVID', 'H264', 'THEORA')
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- split = layout.split()
-
- split.itemR(rd, "ffmpeg_format")
- if rd.ffmpeg_format in ('AVI', 'QUICKTIME', 'MKV', 'OGG'):
- split.itemR(rd, "ffmpeg_codec")
- else:
- split.itemL()
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "ffmpeg_video_bitrate")
- col.itemL(text="Rate:")
- col.itemR(rd, "ffmpeg_minrate", text="Minimum")
- col.itemR(rd, "ffmpeg_maxrate", text="Maximum")
- col.itemR(rd, "ffmpeg_buffersize", text="Buffer")
-
- col = split.column()
- col.itemR(rd, "ffmpeg_gopsize")
- col.itemR(rd, "ffmpeg_autosplit")
- col.itemL(text="Mux:")
- col.itemR(rd, "ffmpeg_muxrate", text="Rate")
- col.itemR(rd, "ffmpeg_packetsize", text="Packet Size")
-
- row = layout.row()
- row.itemL(text="Audio:")
- row = layout.row()
- row.itemR(rd, "ffmpeg_audio_codec")
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "ffmpeg_audio_bitrate")
- col.itemR(rd, "ffmpeg_audio_mixrate")
- col = split.column()
- col.itemR(rd, "ffmpeg_multiplex_audio")
- col.itemR(rd, "ffmpeg_audio_volume")
-
-class RENDER_PT_antialiasing(RenderButtonsPanel):
- __label__ = "Anti-Aliasing"
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw_header(self, context):
- rd = context.scene.render_data
-
- self.layout.itemR(rd, "antialiasing", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- layout.active = rd.antialiasing
-
- split = layout.split()
-
- col = split.column()
- col.row().itemR(rd, "antialiasing_samples", expand=True)
- col.itemR(rd, "full_sample")
-
- col = split.column()
- col.itemR(rd, "pixel_filter", text="")
- col.itemR(rd, "filter_size", text="Size", slider=True)
-
-class RENDER_PT_dimensions(RenderButtonsPanel):
- __label__ = "Dimensions"
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render_data
-
- split = layout.split()
-
- col = split.column()
- sub = col.column(align=True)
- sub.itemL(text="Resolution:")
- sub.itemR(rd, "resolution_x", text="X")
- sub.itemR(rd, "resolution_y", text="Y")
- sub.itemR(rd, "resolution_percentage", text="")
-
- sub.itemL(text="Aspect Ratio:")
- sub.itemR(rd, "pixel_aspect_x", text="X")
- sub.itemR(rd, "pixel_aspect_y", text="Y")
-
- row = col.row()
- row.itemR(rd, "use_border", text="Border")
- rowsub = row.row()
- rowsub.active = rd.use_border
- rowsub.itemR(rd, "crop_to_border", text="Crop")
-
- col = split.column(align=True)
- col.itemL(text="Frame Range:")
- col.itemR(scene, "start_frame", text="Start")
- col.itemR(scene, "end_frame", text="End")
- col.itemR(scene, "frame_step", text="Step")
-
- col.itemL(text="Frame Rate:")
- col.itemR(rd, "fps")
- col.itemR(rd, "fps_base",text="/")
-
-class RENDER_PT_stamp(RenderButtonsPanel):
- __label__ = "Stamp"
- __default_closed__ = True
- COMPAT_ENGINES = set(['BLENDER_RENDER'])
-
- def draw_header(self, context):
- rd = context.scene.render_data
-
- self.layout.itemR(rd, "render_stamp", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render_data
-
- layout.active = rd.render_stamp
-
- split = layout.split()
-
- col = split.column()
- col.itemR(rd, "stamp_time", text="Time")
- col.itemR(rd, "stamp_date", text="Date")
- col.itemR(rd, "stamp_render_time", text="RenderTime")
- col.itemR(rd, "stamp_frame", text="Frame")
- col.itemR(rd, "stamp_scene", text="Scene")
- col.itemR(rd, "stamp_camera", text="Camera")
- col.itemR(rd, "stamp_filename", text="Filename")
- col.itemR(rd, "stamp_marker", text="Marker")
- col.itemR(rd, "stamp_sequence_strip", text="Seq. Strip")
-
- col = split.column()
- col.active = rd.render_stamp
- col.itemR(rd, "stamp_foreground", slider=True)
- col.itemR(rd, "stamp_background", slider=True)
- col.itemR(rd, "stamp_font_size", text="Font Size")
-
- row = layout.split(percentage=0.2)
- row.itemR(rd, "stamp_note", text="Note")
- sub = row.row()
- sub.active = rd.stamp_note
- sub.itemR(rd, "stamp_note_text", text="")
-
-bpy.types.register(RENDER_PT_render)
-bpy.types.register(RENDER_PT_layers)
-bpy.types.register(RENDER_PT_dimensions)
-bpy.types.register(RENDER_PT_antialiasing)
-bpy.types.register(RENDER_PT_shading)
-bpy.types.register(RENDER_PT_output)
-bpy.types.register(RENDER_PT_encoding)
-bpy.types.register(RENDER_PT_performance)
-bpy.types.register(RENDER_PT_post_processing)
-bpy.types.register(RENDER_PT_stamp)
diff --git a/release/scripts/ui/buttons_scene.py b/release/scripts/ui/buttons_scene.py
index 54f47791d59..2fbd176e36a 100644
--- a/release/scripts/ui/buttons_scene.py
+++ b/release/scripts/ui/buttons_scene.py
@@ -1,120 +1,457 @@
import bpy
-class SceneButtonsPanel(bpy.types.Panel):
+class RenderButtonsPanel(bpy.types.Panel):
__space_type__ = 'PROPERTIES'
__region_type__ = 'WINDOW'
__context__ = "scene"
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
def poll(self, context):
- return context.scene
+ rd = context.scene.render_data
+ return (rd.use_game_engine==False) and (rd.engine in self.COMPAT_ENGINES)
-class SCENE_PT_scene(SceneButtonsPanel):
- __label__ = "Scene"
+class SCENE_PT_render(RenderButtonsPanel):
+ __label__ = "Render"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render_data
+ row = layout.row()
+ row.itemO("screen.render", text="Image", icon='ICON_RENDER_RESULT')
+ row.item_booleanO("screen.render", "animation", True, text="Animation", icon='ICON_RENDER_ANIMATION')
+
+ layout.itemR(rd, "display_mode", text="Display")
+
+class SCENE_PT_layers(RenderButtonsPanel):
+ __label__ = "Layers"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
def draw(self, context):
layout = self.layout
scene = context.scene
+ rd = scene.render_data
- layout.itemR(scene, "camera")
- layout.itemR(scene, "set", text="Background")
+ row = layout.row()
+ row.template_list(rd, "layers", rd, "active_layer_index", rows=2)
-class SCENE_PT_unit(SceneButtonsPanel):
- __label__ = "Units"
+ col = row.column(align=True)
+ col.itemO("scene.render_layer_add", icon='ICON_ZOOMIN', text="")
+ col.itemO("scene.render_layer_remove", icon='ICON_ZOOMOUT', text="")
+
+ rl = rd.layers[rd.active_layer_index]
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(scene, "visible_layers", text="Scene")
+ col = split.column()
+ col.itemR(rl, "visible_layers", text="Layer")
+
+ layout.itemR(rl, "light_override", text="Light")
+ layout.itemR(rl, "material_override", text="Material")
+
+ layout.itemS()
+ layout.itemL(text="Include:")
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(rl, "zmask")
+ row = col.row()
+ row.itemR(rl, "zmask_negate", text="Negate")
+ row.active = rl.zmask
+ col.itemR(rl, "all_z")
+
+ col = split.column()
+ col.itemR(rl, "solid")
+ col.itemR(rl, "halo")
+ col.itemR(rl, "ztransp")
+
+ col = split.column()
+ col.itemR(rl, "sky")
+ col.itemR(rl, "edge")
+ col.itemR(rl, "strand")
+
+ if rl.zmask:
+ split = layout.split()
+ split.itemL(text="Zmask Layers:")
+ split.column().itemR(rl, "zmask_layers", text="")
+
+ layout.itemS()
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemL(text="Passes:")
+ col.itemR(rl, "pass_combined")
+ col.itemR(rl, "pass_z")
+ col.itemR(rl, "pass_vector")
+ col.itemR(rl, "pass_normal")
+ col.itemR(rl, "pass_uv")
+ col.itemR(rl, "pass_mist")
+ col.itemR(rl, "pass_object_index")
+
+ col = split.column()
+ col.itemL()
+ col.itemR(rl, "pass_color")
+ col.itemR(rl, "pass_diffuse")
+ row = col.row()
+ row.itemR(rl, "pass_specular")
+ row.itemR(rl, "pass_specular_exclude", text="", icon='ICON_X')
+ row = col.row()
+ row.itemR(rl, "pass_shadow")
+ row.itemR(rl, "pass_shadow_exclude", text="", icon='ICON_X')
+ row = col.row()
+ row.itemR(rl, "pass_ao")
+ row.itemR(rl, "pass_ao_exclude", text="", icon='ICON_X')
+ row = col.row()
+ row.itemR(rl, "pass_reflection")
+ row.itemR(rl, "pass_reflection_exclude", text="", icon='ICON_X')
+ row = col.row()
+ row.itemR(rl, "pass_refraction")
+ row.itemR(rl, "pass_refraction_exclude", text="", icon='ICON_X')
+
+class SCENE_PT_shading(RenderButtonsPanel):
+ __label__ = "Shading"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
def draw(self, context):
layout = self.layout
- unit = context.scene.unit_settings
+ rd = context.scene.render_data
- col = layout.column()
- col.row().itemR(unit, "system", expand=True)
+ split = layout.split()
- row = layout.row()
- row.active = (unit.system != 'NONE')
- row.itemR(unit, "scale_length", text="Scale")
- row.itemR(unit, "use_separate")
+ col = split.column()
+ col.itemR(rd, "render_textures", text="Textures")
+ col.itemR(rd, "render_shadows", text="Shadows")
+ col.itemR(rd, "render_sss", text="Subsurface Scattering")
+ col.itemR(rd, "render_envmaps", text="Environment Map")
-class SCENE_PT_keying_sets(SceneButtonsPanel):
- __label__ = "Keying Sets"
-
+ col = split.column()
+ col.itemR(rd, "render_raytracing", text="Ray Tracing")
+ col.itemR(rd, "color_management")
+ col.itemR(rd, "alpha_mode", text="Alpha")
+
+class SCENE_PT_performance(RenderButtonsPanel):
+ __label__ = "Performance"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
def draw(self, context):
layout = self.layout
- scene = context.scene
+ rd = context.scene.render_data
+
+ split = layout.split()
- row = layout.row()
+ col = split.column(align=True)
+ col.itemL(text="Threads:")
+ col.row().itemR(rd, "threads_mode", expand=True)
+ sub = col.column()
+ sub.enabled = rd.threads_mode == 'THREADS_FIXED'
+ sub.itemR(rd, "threads")
+ col.itemL(text="Tiles:")
+ col.itemR(rd, "parts_x", text="X")
+ col.itemR(rd, "parts_y", text="Y")
+
+ col = split.column()
+ col.itemL(text="Memory:")
+ sub = col.column()
+ sub.itemR(rd, "save_buffers")
+ sub.enabled = not rd.full_sample
+ sub = col.column()
+ sub.active = rd.use_compositing
+ sub.itemR(rd, "free_image_textures")
+ sub = col.column()
+ sub.active = rd.render_raytracing
+ sub.itemL(text="Ray Tracing Octree:")
+ sub.itemR(rd, "octree_resolution", text="")
+
+class SCENE_PT_post_processing(RenderButtonsPanel):
+ __label__ = "Post Processing"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw(self, context):
+ layout = self.layout
- col = row.column()
- col.template_list(scene, "keying_sets", scene, "active_keying_set_index", rows=2)
+ rd = context.scene.render_data
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(rd, "use_compositing")
+ col.itemR(rd, "use_sequencer")
- col = row.column(align=True)
- col.itemO("anim.keying_set_add", icon='ICON_ZOOMIN', text="")
- col.itemO("anim.keying_set_remove", icon='ICON_ZOOMOUT', text="")
+ col = split.column()
+ col.itemR(rd, "dither_intensity", text="Dither", slider=True)
+
+ layout.itemS()
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(rd, "fields", text="Fields")
+ sub = col.column()
+ sub.active = rd.fields
+ sub.row().itemR(rd, "field_order", expand=True)
+ sub.itemR(rd, "fields_still", text="Still")
- ks = scene.active_keying_set
- if ks:
- row = layout.row()
+ col = split.column()
+ col.itemR(rd, "edge")
+ sub = col.column()
+ sub.active = rd.edge
+ sub.itemR(rd, "edge_threshold", text="Threshold", slider=True)
+ sub.itemR(rd, "edge_color", text="")
+
+class SCENE_PT_output(RenderButtonsPanel):
+ __label__ = "Output"
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render_data
+
+ layout.itemR(rd, "output_path", text="")
+
+ split = layout.split()
+ col = split.column()
+ col.itemR(rd, "file_format", text="")
+ col.row().itemR(rd, "color_mode", text="Color", expand=True)
+
+ col = split.column()
+ col.itemR(rd, "file_extensions")
+ col.itemR(rd, "use_overwrite")
+ col.itemR(rd, "use_placeholder")
+
+ if rd.file_format in ('AVIJPEG', 'JPEG'):
+ split = layout.split()
+ split.itemR(rd, "quality", slider=True)
+
+ elif rd.file_format == 'OPENEXR':
+ split = layout.split()
- col = row.column()
- col.itemR(ks, "name")
- col.itemR(ks, "absolute")
+ col = split.column()
+ col.itemL(text="Codec:")
+ col.itemR(rd, "exr_codec", text="")
+
+ subsplit = split.split()
+ col = subsplit.column()
+ col.itemR(rd, "exr_half")
+ col.itemR(rd, "exr_zbuf")
+ col = subsplit.column()
+ col.itemR(rd, "exr_preview")
+
+ elif rd.file_format == 'JPEG2000':
+ split = layout.split()
+ col = split.column()
+ col.itemL(text="Depth:")
+ col.row().itemR(rd, "jpeg2k_depth", expand=True)
+
+ col = split.column()
+ col.itemR(rd, "jpeg2k_preset", text="")
+ col.itemR(rd, "jpeg2k_ycc")
- col = row.column()
- col.itemL(text="Keyframing Settings:")
- col.itemR(ks, "insertkey_needed", text="Needed")
- col.itemR(ks, "insertkey_visual", text="Visual")
+ elif rd.file_format in ('CINEON', 'DPX'):
+ split = layout.split()
+ col = split.column()
+ col.itemR(rd, "cineon_log", text="Convert to Log")
+
+ col = split.column(align=True)
+ col.active = rd.cineon_log
+ col.itemR(rd, "cineon_black", text="Black")
+ col.itemR(rd, "cineon_white", text="White")
+ col.itemR(rd, "cineon_gamma", text="Gamma")
-class SCENE_PT_keying_set_paths(SceneButtonsPanel):
- __label__ = "Active Keying Set"
+ elif rd.file_format == 'TIFF':
+ split = layout.split()
+ split.itemR(rd, "tiff_bit")
+
+class SCENE_PT_encoding(RenderButtonsPanel):
+ __label__ = "Encoding"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
def poll(self, context):
- return (context.scene != None) and (context.scene.active_keying_set != None)
+ rd = context.scene.render_data
+ return rd.file_format in ('FFMPEG', 'XVID', 'H264', 'THEORA')
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render_data
+
+ split = layout.split()
+
+ split.itemR(rd, "ffmpeg_format")
+ if rd.ffmpeg_format in ('AVI', 'QUICKTIME', 'MKV', 'OGG'):
+ split.itemR(rd, "ffmpeg_codec")
+ else:
+ split.itemL()
+
+ split = layout.split()
+ col = split.column()
+ col.itemR(rd, "ffmpeg_video_bitrate")
+ col.itemL(text="Rate:")
+ col.itemR(rd, "ffmpeg_minrate", text="Minimum")
+ col.itemR(rd, "ffmpeg_maxrate", text="Maximum")
+ col.itemR(rd, "ffmpeg_buffersize", text="Buffer")
+
+ col = split.column()
+ col.itemR(rd, "ffmpeg_gopsize")
+ col.itemR(rd, "ffmpeg_autosplit")
+ col.itemL(text="Mux:")
+ col.itemR(rd, "ffmpeg_muxrate", text="Rate")
+ col.itemR(rd, "ffmpeg_packetsize", text="Packet Size")
+
+ row = layout.row()
+ row.itemL(text="Audio:")
+ row = layout.row()
+ row.itemR(rd, "ffmpeg_audio_codec")
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(rd, "ffmpeg_audio_bitrate")
+ col.itemR(rd, "ffmpeg_audio_mixrate")
+ col = split.column()
+ col.itemR(rd, "ffmpeg_multiplex_audio")
+ col.itemR(rd, "ffmpeg_audio_volume")
+
+class SCENE_PT_antialiasing(RenderButtonsPanel):
+ __label__ = "Anti-Aliasing"
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw_header(self, context):
+ rd = context.scene.render_data
+
+ self.layout.itemR(rd, "antialiasing", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render_data
+
+ layout.active = rd.antialiasing
+
+ split = layout.split()
+
+ col = split.column()
+ col.row().itemR(rd, "antialiasing_samples", expand=True)
+ col.itemR(rd, "full_sample")
+
+ col = split.column()
+ col.itemR(rd, "pixel_filter", text="")
+ col.itemR(rd, "filter_size", text="Size", slider=True)
+
+class SCENE_PT_dimensions(RenderButtonsPanel):
+ __label__ = "Dimensions"
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
def draw(self, context):
layout = self.layout
scene = context.scene
- ks = scene.active_keying_set
+ rd = scene.render_data
- row = layout.row()
- row.itemL(text="Paths:")
+ split = layout.split()
- row = layout.row()
+ col = split.column()
+ sub = col.column(align=True)
+ sub.itemL(text="Resolution:")
+ sub.itemR(rd, "resolution_x", text="X")
+ sub.itemR(rd, "resolution_y", text="Y")
+ sub.itemR(rd, "resolution_percentage", text="")
- col = row.column()
- col.template_list(ks, "paths", ks, "active_path_index", rows=2)
+ sub.itemL(text="Aspect Ratio:")
+ sub.itemR(rd, "pixel_aspect_x", text="X")
+ sub.itemR(rd, "pixel_aspect_y", text="Y")
+
+ row = col.row()
+ row.itemR(rd, "use_border", text="Border")
+ rowsub = row.row()
+ rowsub.active = rd.use_border
+ rowsub.itemR(rd, "crop_to_border", text="Crop")
- col = row.column(align=True)
- col.itemO("anim.keying_set_path_add", icon='ICON_ZOOMIN', text="")
- col.itemO("anim.keying_set_path_remove", icon='ICON_ZOOMOUT', text="")
-
- ksp = ks.active_path
- if ksp:
- col = layout.column()
- col.itemL(text="Target:")
- col.template_any_ID(ksp, "id", "id_type")
- col.template_path_builder(ksp, "rna_path", ksp.id)
-
-
- row = layout.row()
-
- col = row.column()
- col.itemL(text="Array Target:")
- col.itemR(ksp, "entire_array")
- if ksp.entire_array == False:
- col.itemR(ksp, "array_index")
-
- col = row.column()
- col.itemL(text="F-Curve Grouping:")
- col.itemR(ksp, "grouping")
- if ksp.grouping == 'NAMED':
- col.itemR(ksp, "group")
+ col = split.column(align=True)
+ col.itemL(text="Frame Range:")
+ col.itemR(scene, "start_frame", text="Start")
+ col.itemR(scene, "end_frame", text="End")
+ col.itemR(scene, "frame_step", text="Step")
+
+ col.itemL(text="Frame Rate:")
+ col.itemR(rd, "fps")
+ col.itemR(rd, "fps_base",text="/")
+
+class SCENE_PT_stamp(RenderButtonsPanel):
+ __label__ = "Stamp"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw_header(self, context):
+ rd = context.scene.render_data
+
+ self.layout.itemR(rd, "render_stamp", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render_data
+
+ layout.active = rd.render_stamp
+
+ split = layout.split()
+
+ col = split.column()
+ col.itemR(rd, "stamp_time", text="Time")
+ col.itemR(rd, "stamp_date", text="Date")
+ col.itemR(rd, "stamp_frame", text="Frame")
+ col.itemR(rd, "stamp_scene", text="Scene")
+ col.itemR(rd, "stamp_camera", text="Camera")
+ col.itemR(rd, "stamp_filename", text="Filename")
+ col.itemR(rd, "stamp_marker", text="Marker")
+ col.itemR(rd, "stamp_sequence_strip", text="Seq. Strip")
+
+ col = split.column()
+ col.active = rd.render_stamp
+ col.itemR(rd, "stamp_foreground", slider=True)
+ col.itemR(rd, "stamp_background", slider=True)
+ col.itemR(rd, "stamp_font_size", text="Font Size")
+
+ row = layout.split(percentage=0.2)
+ row.itemR(rd, "stamp_note", text="Note")
+ sub = row.row()
+ sub.active = rd.stamp_note
+ sub.itemR(rd, "stamp_note_text", text="")
-class SCENE_PT_physics(SceneButtonsPanel):
+class SCENE_PT_unit(RenderButtonsPanel):
+ __label__ = "Units"
+ __default_closed__ = True
+ COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+ def draw(self, context):
+ layout = self.layout
+
+ unit = context.scene.unit_settings
+
+ col = layout.column()
+ col.row().itemR(unit, "system", expand=True)
+
+ row = layout.row()
+ row.active = (unit.system != 'NONE')
+ row.itemR(unit, "scale_length", text="Scale")
+ row.itemR(unit, "use_separate")
+
+class SCENE_PT_physics(RenderButtonsPanel):
__label__ = "Gravity"
COMPAT_ENGINES = set(['BLENDER_RENDER'])
@@ -130,8 +467,16 @@ class SCENE_PT_physics(SceneButtonsPanel):
layout.itemR(scene, "gravity", text="")
-bpy.types.register(SCENE_PT_scene)
+
+bpy.types.register(SCENE_PT_render)
+bpy.types.register(SCENE_PT_layers)
+bpy.types.register(SCENE_PT_dimensions)
+bpy.types.register(SCENE_PT_antialiasing)
+bpy.types.register(SCENE_PT_shading)
+bpy.types.register(SCENE_PT_output)
+bpy.types.register(SCENE_PT_encoding)
+bpy.types.register(SCENE_PT_performance)
+bpy.types.register(SCENE_PT_post_processing)
+bpy.types.register(SCENE_PT_stamp)
bpy.types.register(SCENE_PT_unit)
-bpy.types.register(SCENE_PT_keying_sets)
-bpy.types.register(SCENE_PT_keying_set_paths)
bpy.types.register(SCENE_PT_physics)
diff --git a/release/scripts/ui/buttons_texture.py b/release/scripts/ui/buttons_texture.py
index 270ecaf19aa..9765aa93ca4 100644
--- a/release/scripts/ui/buttons_texture.py
+++ b/release/scripts/ui/buttons_texture.py
@@ -1,30 +1,6 @@
import bpy
-def active_node_mat(mat):
- if mat:
- mat_node = mat.active_node_material
- if mat_node:
- return mat_node
- else:
- return mat
-
- return None
-
-def context_tex_datablock(context):
-
- idblock = active_node_mat(context.material)
- if idblock: return idblock
-
- idblock = context.lamp
- if idblock: return idblock
-
- idblock = context.world
- if idblock: return idblock
-
- idblock = context.brush
- return idblock
-
class TextureButtonsPanel(bpy.types.Panel):
__space_type__ = 'PROPERTIES'
__region_type__ = 'WINDOW'
@@ -42,11 +18,19 @@ class TEXTURE_PT_preview(TextureButtonsPanel):
tex = context.texture
slot = context.texture_slot
-
- idblock = context_tex_datablock(context)
-
- if idblock:
- layout.template_preview(tex, parent=idblock, slot=slot)
+ ma = context.material
+ la = context.lamp
+ wo = context.world
+ br = context.brush
+
+ if ma:
+ layout.template_preview(tex, parent=ma, slot=slot)
+ elif la:
+ layout.template_preview(tex, parent=la, slot=slot)
+ elif wo:
+ layout.template_preview(tex, parent=wo, slot=slot)
+ elif br:
+ layout.template_preview(tex, parent=br, slot=slot)
else:
layout.template_preview(tex, slot=slot)
@@ -60,25 +44,22 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel):
layout = self.layout
tex = context.texture
-
- idblock = context_tex_datablock(context)
+
+ id = context.material
+ if not id: id = context.lamp
+ if not id: id = context.world
+ if not id: id = context.brush
space = context.space_data
- if idblock:
+ if id:
row = layout.row()
-
- row.template_list(idblock, "textures", idblock, "active_texture_index", rows=2)
-
- col = row.column(align=True)
- col.item_enumO("texture.slot_move", "type", 'UP', text="", icon='ICON_TRIA_UP')
- col.item_enumO("texture.slot_move", "type", 'DOWN', text="", icon='ICON_TRIA_DOWN')
-
+ row.template_list(id, "textures", id, "active_texture_index", rows=2)
split = layout.split(percentage=0.65)
- if idblock:
- split.template_ID(idblock, "active_texture", new="texture.new")
+ if id:
+ split.template_ID(id, "active_texture", new="texture.new")
elif tex:
split.template_ID(space, "pin_id")
@@ -94,13 +75,11 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel):
layout.itemR(tex, "use_nodes")
split = layout.split(percentage=0.2)
-
+
if tex.use_nodes:
slot = context.texture_slot
-
- if slot:
- split.itemL(text="Output:")
- split.itemR(slot, "output_node", text="")
+ split.itemL(text="Output:")
+ split.itemR(slot, "output_node", text="")
else:
split.itemL(text="Type:")
@@ -120,13 +99,8 @@ class TEXTURE_PT_colors(TextureButtonsPanel):
layout.template_color_ramp(tex, "color_ramp", expand=True)
split = layout.split()
-
- col = split.column()
- col.itemL(text="RGB Multiply:")
- sub = col.column(align=True)
- sub.itemR(tex, "factor_red", text="R")
- sub.itemR(tex, "factor_green", text="G")
- sub.itemR(tex, "factor_blue", text="B")
+
+ split.itemR(tex, "rgb_factor", text="Multiply RGB")
col = split.column()
col.itemL(text="Adjust:")
@@ -148,12 +122,14 @@ class TEXTURE_PT_mapping(TextureSlotPanel):
def draw(self, context):
layout = self.layout
- idblock = context_tex_datablock(context)
-
+ ma = context.material
+ la = context.lamp
+ wo = context.world
+ br = context.brush
tex = context.texture_slot
textype = context.texture
- if type(idblock) != bpy.types.Brush:
+ if not br:
split = layout.split(percentage=0.3)
col = split.column()
col.itemL(text="Coordinates:")
@@ -177,43 +153,41 @@ class TEXTURE_PT_mapping(TextureSlotPanel):
split.itemL(text="Object:")
split.itemR(tex, "object", text="")
- if type(idblock) == bpy.types.Brush:
- layout.itemR(tex, "map_mode", expand=True)
+ if ma:
+ split = layout.split(percentage=0.3)
+ split.itemL(text="Projection:")
+ split.itemR(tex, "mapping", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ if tex.texture_coordinates in ('ORCO', 'UV'):
+ col.itemR(tex, "from_dupli")
+ elif tex.texture_coordinates == 'OBJECT':
+ col.itemR(tex, "from_original")
+ else:
+ col.itemL()
+
+ col = split.column()
+ row = col.row()
+ row.itemR(tex, "x_mapping", text="")
+ row.itemR(tex, "y_mapping", text="")
+ row.itemR(tex, "z_mapping", text="")
+
+ if br:
+ layout.itemR(tex, "brush_map_mode", expand=True)
row = layout.row()
- row.active = tex.map_mode in ('FIXED', 'TILED')
+ row.active = tex.brush_map_mode in ('FIXED', 'TILED')
row.itemR(tex, "angle")
row = layout.row()
- row.active = tex.map_mode in ('TILED', '3D')
+ row.active = tex.brush_map_mode in ('TILED', '3D')
row.column().itemR(tex, "size")
else:
- if type(idblock) == bpy.types.Material:
- split = layout.split(percentage=0.3)
- split.itemL(text="Projection:")
- split.itemR(tex, "mapping", text="")
-
- split = layout.split()
-
- col = split.column()
- if tex.texture_coordinates in ('ORCO', 'UV'):
- col.itemR(tex, "from_dupli")
- elif tex.texture_coordinates == 'OBJECT':
- col.itemR(tex, "from_original")
- else:
- col.itemL()
-
- col = split.column()
- row = col.row()
- row.itemR(tex, "x_mapping", text="")
- row.itemR(tex, "y_mapping", text="")
- row.itemR(tex, "z_mapping", text="")
-
- # any non brush
row = layout.row()
row.column().itemR(tex, "offset")
row.column().itemR(tex, "size")
-
class TEXTURE_PT_influence(TextureSlotPanel):
__label__ = "Influence"
@@ -221,8 +195,10 @@ class TEXTURE_PT_influence(TextureSlotPanel):
def draw(self, context):
layout = self.layout
- idblock = context_tex_datablock(context)
-
+ ma = context.material
+ la = context.lamp
+ wo = context.world
+ br = context.brush
textype = context.texture
tex = context.texture_slot
@@ -233,8 +209,8 @@ class TEXTURE_PT_influence(TextureSlotPanel):
sub.active = active
sub.itemR(tex, factor, text=name, slider=True)
- if type(idblock) == bpy.types.Material:
- if idblock.type in ('SURFACE', 'HALO', 'WIRE'):
+ if ma:
+ if ma.type in ['SURFACE', 'HALO', 'WIRE']:
split = layout.split()
col = split.column()
@@ -264,7 +240,7 @@ class TEXTURE_PT_influence(TextureSlotPanel):
#sub = col.column()
#sub.active = tex.map_translucency or tex.map_emit or tex.map_alpha or tex.map_raymir or tex.map_hardness or tex.map_ambient or tex.map_specularity or tex.map_reflection or tex.map_mirror
#sub.itemR(tex, "default_value", text="Amount", slider=True)
- elif idblock.type == 'VOLUME':
+ elif ma.type == 'VOLUME':
split = layout.split()
col = split.column()
@@ -279,12 +255,11 @@ class TEXTURE_PT_influence(TextureSlotPanel):
factor_but(col, tex.map_colortransmission, "map_colortransmission", "colortransmission_factor", "Transmission Color")
factor_but(col, tex.map_colorreflection, "map_colorreflection", "colorreflection_factor", "Reflection Color")
- elif type(idblock) == bpy.types.Lamp:
+ elif la:
row = layout.row()
factor_but(row, tex.map_color, "map_color", "color_factor", "Color")
factor_but(row, tex.map_shadow, "map_shadow", "shadow_factor", "Shadow")
-
- elif type(idblock) == bpy.types.World:
+ elif wo:
split = layout.split()
col = split.column()
@@ -309,8 +284,7 @@ class TEXTURE_PT_influence(TextureSlotPanel):
col = split.column()
col.itemR(tex, "negate", text="Negative")
col.itemR(tex, "stencil")
-
- if type(idblock) in (bpy.types.Material, bpy.types.World):
+ if ma or wo:
col.itemR(tex, "default_value", text="DVar", slider=True)
# Texture Type Panels #
@@ -784,4 +758,3 @@ bpy.types.register(TEXTURE_PT_pointdensity_turbulence)
bpy.types.register(TEXTURE_PT_colors)
bpy.types.register(TEXTURE_PT_mapping)
bpy.types.register(TEXTURE_PT_influence)
-
diff --git a/release/scripts/ui/buttons_world.py b/release/scripts/ui/buttons_world.py
index b64efc1048d..3134c0ce46b 100644
--- a/release/scripts/ui/buttons_world.py
+++ b/release/scripts/ui/buttons_world.py
@@ -129,8 +129,7 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel):
col = split.column()
col.itemL(text="Attenuation:")
- if ao.gather_method == 'RAYTRACE':
- col.itemR(ao, "distance")
+ col.itemR(ao, "distance")
col.itemR(ao, "falloff")
sub = col.row()
sub.active = ao.falloff
diff --git a/release/scripts/ui/space_buttons.py b/release/scripts/ui/space_buttons.py
index 299e8bc9dae..aa89c06ea08 100644
--- a/release/scripts/ui/space_buttons.py
+++ b/release/scripts/ui/space_buttons.py
@@ -22,6 +22,7 @@ class Buttons_HT_header(bpy.types.Header):
row.itemR(scene, "current_frame")
class Buttons_MT_view(bpy.types.Menu):
+ __space_type__ = 'PROPERTIES'
__label__ = "View"
def draw(self, context):
diff --git a/release/scripts/ui/space_console.py b/release/scripts/ui/space_console.py
index 5bb211f7d98..a65d7577c7a 100644
--- a/release/scripts/ui/space_console.py
+++ b/release/scripts/ui/space_console.py
@@ -38,6 +38,7 @@ class CONSOLE_HT_header(bpy.types.Header):
row.itemO("console.autocomplete", text="Autocomplete")
class CONSOLE_MT_console(bpy.types.Menu):
+ __space_type__ = 'CONSOLE'
__label__ = "Console"
def draw(self, context):
@@ -50,6 +51,7 @@ class CONSOLE_MT_console(bpy.types.Menu):
layout.itemO("console.paste")
class CONSOLE_MT_report(bpy.types.Menu):
+ __space_type__ = 'CONSOLE'
__label__ = "Report"
def draw(self, context):
diff --git a/release/scripts/ui/space_filebrowser.py b/release/scripts/ui/space_filebrowser.py
index 5b0c189464f..f1ea5555787 100644
--- a/release/scripts/ui/space_filebrowser.py
+++ b/release/scripts/ui/space_filebrowser.py
@@ -12,17 +12,11 @@ class FILEBROWSER_HT_header(bpy.types.Header):
layout.template_header(menus=False)
- row = layout.row()
- row.itemS()
-
row = layout.row(align=True)
- row.itemO("file.previous", text="", icon='ICON_BACK')
- row.itemO("file.next", text="", icon='ICON_FORWARD')
row.itemO("file.parent", text="", icon='ICON_FILE_PARENT')
row.itemO("file.refresh", text="", icon='ICON_FILE_REFRESH')
-
- row = layout.row()
- row.itemS()
+ row.itemO("file.previous", text="", icon='ICON_PREV_KEYFRAME')
+ row.itemO("file.next", text="", icon='ICON_NEXT_KEYFRAME')
row = layout.row(align=True)
row.itemO("file.directory_new", text="", icon='ICON_NEWFOLDER')
@@ -30,8 +24,8 @@ class FILEBROWSER_HT_header(bpy.types.Header):
layout.itemR(params, "display", expand=True, text="")
layout.itemR(params, "sort", expand=True, text="")
- layout.itemR(params, "hide_dot", text="Hide Invisible")
- layout.itemR(params, "do_filter", text="", icon='ICON_FILTER')
+ layout.itemR(params, "hide_dot")
+ layout.itemR(params, "do_filter")
row = layout.row(align=True)
row.itemR(params, "filter_folder", text="");
diff --git a/release/scripts/ui/space_image.py b/release/scripts/ui/space_image.py
index 93d8043b61f..b14bec0e40e 100644
--- a/release/scripts/ui/space_image.py
+++ b/release/scripts/ui/space_image.py
@@ -2,6 +2,7 @@
import bpy
class IMAGE_MT_view(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "View"
def draw(self, context):
@@ -32,7 +33,7 @@ class IMAGE_MT_view(bpy.types.Menu):
for a, b in ratios:
text = "Zoom %d:%d" % (a, b)
- layout.item_floatO("image.view_zoom_ratio", "ratio", a/b, text=text)
+ layout.item_floatO("image.view_zoom_ratio", "ratio", a/float(b), text=text)
layout.itemS()
@@ -43,6 +44,7 @@ class IMAGE_MT_view(bpy.types.Menu):
layout.itemO("screen.screen_full_area")
class IMAGE_MT_select(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "Select"
def draw(self, context):
@@ -63,6 +65,7 @@ class IMAGE_MT_select(bpy.types.Menu):
layout.itemO("uv.select_linked")
class IMAGE_MT_image(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "Image"
def draw(self, context):
@@ -106,6 +109,7 @@ class IMAGE_MT_image(bpy.types.Menu):
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):
@@ -116,6 +120,7 @@ class IMAGE_MT_uvs_showhide(bpy.types.Menu):
layout.item_booleanO("uv.hide", "unselected", True)
class IMAGE_MT_uvs_transform(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "Transform"
def draw(self, context):
@@ -126,6 +131,7 @@ class IMAGE_MT_uvs_transform(bpy.types.Menu):
layout.itemO("tfm.resize")
class IMAGE_MT_uvs_mirror(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "Mirror"
def draw(self, context):
@@ -139,6 +145,7 @@ class IMAGE_MT_uvs_mirror(bpy.types.Menu):
props.constraint_axis[1]= True
class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "Weld/Align"
def draw(self, context):
@@ -148,6 +155,7 @@ class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
layout.items_enumO("uv.align", "axis") # W, 2/3/4
class IMAGE_MT_uvs(bpy.types.Menu):
+ __space_type__ = 'IMAGE_EDITOR'
__label__ = "UVs"
def draw(self, context):
diff --git a/release/scripts/ui/space_info.py b/release/scripts/ui/space_info.py
index 961329ea5d0..c1a2b1f4275 100644
--- a/release/scripts/ui/space_info.py
+++ b/release/scripts/ui/space_info.py
@@ -1,9 +1,6 @@
import bpy
-import dynamic_menu
-# reload(dynamic_menu)
-
class INFO_HT_header(bpy.types.Header):
__space_type__ = 'INFO'
@@ -39,28 +36,28 @@ class INFO_HT_header(bpy.types.Header):
layout.template_running_jobs()
layout.itemL(text=scene.statistics())
-
-
+
class INFO_MT_file(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "File"
def draw(self, context):
layout = self.layout
layout.operator_context = "EXEC_AREA"
- layout.itemO("wm.read_homefile", text="New", icon='ICON_NEW')
+ layout.itemO("wm.read_homefile", text="New")
layout.operator_context = "INVOKE_AREA"
- layout.itemO("wm.open_mainfile", text="Open...", icon='ICON_FILE_FOLDER')
+ layout.itemO("wm.open_mainfile", text="Open...")
layout.item_menu_enumO("wm.open_recentfile", "file", text="Open Recent")
layout.itemO("wm.recover_last_session")
layout.itemS()
layout.operator_context = "EXEC_AREA"
- layout.itemO("wm.save_mainfile", text="Save", icon='ICON_FILE_TICK')
+ layout.itemO("wm.save_mainfile", text="Save")
layout.operator_context = "INVOKE_AREA"
layout.itemO("wm.save_as_mainfile", text="Save As...")
- layout.itemO("screen.userpref_show", text="User Preferences...", icon='ICON_PREFERENCES')
+ layout.itemO("screen.userpref_show", text="User Preferences...")
layout.itemS()
layout.operator_context = "INVOKE_AREA"
@@ -78,35 +75,35 @@ class INFO_MT_file(bpy.types.Menu):
layout.itemS()
layout.operator_context = "EXEC_AREA"
- layout.itemO("wm.exit_blender", text="Quit", icon='ICON_QUIT')
+ layout.itemO("wm.exit_blender", text="Quit")
-
-# test for expanding menus
-'''
-class INFO_MT_file_more(INFO_MT_file):
- __label__ = "File"
+class INFO_MT_file_import(bpy.types.Menu):
+ __space_type__ = 'INFO'
+ __label__ = "Import"
def draw(self, context):
layout = self.layout
+
+ layout.itemO("import.3ds", text="3DS")
+ layout.itemO("import.obj", text="OBJ")
- layout.itemO("wm.read_homefile", text="TESTING ")
-
-dynamic_menu.setup(INFO_MT_file_more)
-'''
-class INFO_MT_file_import(dynamic_menu.DynMenu):
- __label__ = "Import"
+class INFO_MT_file_export(bpy.types.Menu):
+ __space_type__ = 'INFO'
+ __label__ = "Export"
def draw(self, context):
- pass # dynamic menu
+ layout = self.layout
-class INFO_MT_file_export(dynamic_menu.DynMenu):
- __label__ = "Export"
+ layout.itemO("export.3ds", text="3DS")
+ layout.itemO("export.fbx", text="FBX")
+ layout.itemO("export.obj", text="OBJ")
+ layout.itemO("export.ply", text="PLY")
+ layout.itemO("export.x3d", text="X3D")
- def draw(self, context):
- pass # dynamic menu
class INFO_MT_file_external_data(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "External Data"
def draw(self, context):
@@ -122,24 +119,8 @@ class INFO_MT_file_external_data(bpy.types.Menu):
layout.itemO("file.report_missing_files")
layout.itemO("file.find_missing_files")
-
-class INFO_MT_mesh_add(dynamic_menu.DynMenu):
- __label__ = "Add Mesh"
- def draw(self, context):
- layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
- layout.itemO("mesh.primitive_plane_add", icon='ICON_MESH_PLANE')
- layout.itemO("mesh.primitive_cube_add", icon='ICON_MESH_CUBE')
- layout.itemO("mesh.primitive_circle_add", icon='ICON_MESH_CIRCLE')
- layout.itemO("mesh.primitive_uv_sphere_add", icon='ICON_MESH_UVSPHERE')
- layout.itemO("mesh.primitive_ico_sphere_add", icon='ICON_MESH_ICOSPHERE')
- layout.itemO("mesh.primitive_cylinder_add", icon='ICON_MESH_TUBE')
- layout.itemO("mesh.primitive_cone_add", icon='ICON_MESH_CONE')
- layout.itemS()
- layout.itemO("mesh.primitive_grid_add", icon='ICON_MESH_GRID')
- layout.itemO("mesh.primitive_monkey_add", icon='ICON_MESH_MONKEY')
-
class INFO_MT_add(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "Add"
def draw(self, context):
@@ -147,9 +128,7 @@ class INFO_MT_add(bpy.types.Menu):
layout.operator_context = "EXEC_SCREEN"
- # layout.item_menu_enumO("object.mesh_add", "type", text="Mesh", icon='ICON_OUTLINER_OB_MESH')
- layout.itemM("INFO_MT_mesh_add", icon='ICON_OUTLINER_OB_MESH')
-
+ layout.item_menu_enumO("object.mesh_add", "type", text="Mesh", icon='ICON_OUTLINER_OB_MESH')
layout.item_menu_enumO("object.curve_add", "type", text="Curve", icon='ICON_OUTLINER_OB_CURVE')
layout.item_menu_enumO("object.surface_add", "type", text="Surface", icon='ICON_OUTLINER_OB_SURFACE')
layout.item_menu_enumO("object.metaball_add", "type", 'META', text="Metaball", icon='ICON_OUTLINER_OB_META')
@@ -165,16 +144,9 @@ class INFO_MT_add(bpy.types.Menu):
layout.item_enumO("object.add", "type", 'CAMERA', icon='ICON_OUTLINER_OB_CAMERA')
layout.item_menu_enumO("object.lamp_add", "type", 'LAMP', text="Lamp", icon='ICON_OUTLINER_OB_LAMP')
-
- layout.itemS()
-
- layout.item_menu_enumO("object.effector_add", "type", 'EMPTY', text="Force Field", icon='ICON_OUTLINER_OB_EMPTY')
-
- layout.itemS()
-
- layout.item_menu_enumO("object.group_instance_add", "type", text="Group Instance", icon='ICON_OUTLINER_OB_EMPTY')
class INFO_MT_game(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "Game"
def draw(self, context):
@@ -192,6 +164,7 @@ class INFO_MT_game(bpy.types.Menu):
layout.itemR(gs, "deprecation_warnings")
class INFO_MT_render(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "Render"
def draw(self, context):
@@ -199,30 +172,32 @@ class INFO_MT_render(bpy.types.Menu):
rd = context.scene.render_data
- layout.itemO("screen.render", text="Render Image", icon='ICON_RENDER_STILL')
- layout.item_booleanO("screen.render", "animation", True, text="Render Animation", icon='ICON_RENDER_ANIMATION')
+ layout.itemO("screen.render", text="Render Image")
+ layout.item_booleanO("screen.render", "animation", True, text="Render Animation")
layout.itemS()
layout.itemO("screen.render_view_show")
class INFO_MT_help(bpy.types.Menu):
+ __space_type__ = 'INFO'
__label__ = "Help"
def draw(self, context):
layout = self.layout
- layout.itemO("help.manual", icon='ICON_HELP')
- layout.itemO("help.release_logs", icon='ICON_URL')
+ layout.itemO("help.manual")
+ layout.itemO("help.release_logs")
layout.itemS()
- layout.itemO("help.blender_website", icon='ICON_URL')
- layout.itemO("help.blender_eshop", icon='ICON_URL')
- layout.itemO("help.developer_community", icon='ICON_URL')
- layout.itemO("help.user_community", icon='ICON_URL')
+ layout.itemO("help.blender_website")
+ layout.itemO("help.blender_eshop")
+ layout.itemO("help.developer_community")
+ layout.itemO("help.user_community")
layout.itemS()
layout.itemO("help.operator_cheat_sheet")
+
bpy.types.register(INFO_HT_header)
bpy.types.register(INFO_MT_file)
@@ -230,7 +205,6 @@ bpy.types.register(INFO_MT_file_import)
bpy.types.register(INFO_MT_file_export)
bpy.types.register(INFO_MT_file_external_data)
bpy.types.register(INFO_MT_add)
-bpy.types.register(INFO_MT_mesh_add)
bpy.types.register(INFO_MT_game)
bpy.types.register(INFO_MT_render)
bpy.types.register(INFO_MT_help)
@@ -250,37 +224,31 @@ class HelpOperator(bpy.types.Operator):
return ('FINISHED',)
class HELP_OT_manual(HelpOperator):
- '''The Blender Wiki manual'''
__idname__ = "help.manual"
__label__ = "Manual"
__URL__ = 'http://wiki.blender.org/index.php/Manual'
class HELP_OT_release_logs(HelpOperator):
- '''Information about the changes in this version of Blender'''
__idname__ = "help.release_logs"
__label__ = "Release Logs"
__URL__ = 'http://www.blender.org/development/release-logs/'
class HELP_OT_blender_website(HelpOperator):
- '''The official Blender website'''
__idname__ = "help.blender_website"
__label__ = "Blender Website"
__URL__ = 'http://www.blender.org/'
class HELP_OT_blender_eshop(HelpOperator):
- '''Buy official Blender resources and merchandise online'''
__idname__ = "help.blender_eshop"
__label__ = "Blender e-Shop"
__URL__ = 'http://www.blender3d.org/e-shop'
class HELP_OT_developer_community(HelpOperator):
- '''Get involved with Blender development'''
__idname__ = "help.developer_community"
__label__ = "Developer Community"
__URL__ = 'http://www.blender.org/community/get-involved/'
class HELP_OT_user_community(HelpOperator):
- '''Get involved with other Blender users'''
__idname__ = "help.user_community"
__label__ = "User Community"
__URL__ = 'http://www.blender.org/community/user-community/'
@@ -310,6 +278,7 @@ class HELP_OT_operator_cheat_sheet(bpy.types.Operator):
print("See OperatorList.txt textblock")
return ('FINISHED',)
+
bpy.ops.add(HELP_OT_manual)
bpy.ops.add(HELP_OT_release_logs)
bpy.ops.add(HELP_OT_blender_website)
@@ -317,3 +286,4 @@ bpy.ops.add(HELP_OT_blender_eshop)
bpy.ops.add(HELP_OT_developer_community)
bpy.ops.add(HELP_OT_user_community)
bpy.ops.add(HELP_OT_operator_cheat_sheet)
+
diff --git a/release/scripts/ui/space_node.py b/release/scripts/ui/space_node.py
index 5c5c49afbc7..b32e6a9f61a 100644
--- a/release/scripts/ui/space_node.py
+++ b/release/scripts/ui/space_node.py
@@ -48,6 +48,7 @@ class NODE_HT_header(bpy.types.Header):
layout.itemR(snode, "backdrop")
class NODE_MT_view(bpy.types.Menu):
+ __space_type__ = 'NODE_EDITOR'
__label__ = "View"
def draw(self, context):
@@ -65,6 +66,7 @@ class NODE_MT_view(bpy.types.Menu):
layout.itemO("screen.screen_full_area")
class NODE_MT_select(bpy.types.Menu):
+ __space_type__ = 'NODE_EDITOR'
__label__ = "Select"
def draw(self, context):
@@ -78,6 +80,7 @@ class NODE_MT_select(bpy.types.Menu):
layout.itemO("node.select_linked_to")
class NODE_MT_node(bpy.types.Menu):
+ __space_type__ = 'NODE_EDITOR'
__label__ = "Node"
def draw(self, context):
diff --git a/release/scripts/ui/space_outliner.py b/release/scripts/ui/space_outliner.py
index f3c45983d76..522b620e29d 100644
--- a/release/scripts/ui/space_outliner.py
+++ b/release/scripts/ui/space_outliner.py
@@ -36,6 +36,7 @@ class OUTLINER_HT_header(bpy.types.Header):
class OUTLINER_MT_view(bpy.types.Menu):
+ __space_type__ = 'OUTLINER'
__label__ = "View"
def draw(self, context):
diff --git a/release/scripts/ui/space_sequencer.py b/release/scripts/ui/space_sequencer.py
index 582481401a6..a804998cdaa 100644
--- a/release/scripts/ui/space_sequencer.py
+++ b/release/scripts/ui/space_sequencer.py
@@ -38,6 +38,7 @@ class SEQUENCER_HT_header(bpy.types.Header):
layout.itemR(st, "display_channel", text="Channel")
class SEQUENCER_MT_view(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "View"
def draw(self, context):
@@ -105,6 +106,7 @@ class SEQUENCER_MT_view(bpy.types.Menu):
"""
class SEQUENCER_MT_select(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "Select"
def draw(self, context):
@@ -125,6 +127,7 @@ class SEQUENCER_MT_select(bpy.types.Menu):
layout.itemO("sequencer.select_inverse")
class SEQUENCER_MT_marker(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "Marker (TODO)"
def draw(self, context):
@@ -143,6 +146,7 @@ class SEQUENCER_MT_marker(bpy.types.Menu):
#layout.itemO("sequencer.sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
class SEQUENCER_MT_add(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "Add"
def draw(self, context):
@@ -159,6 +163,7 @@ class SEQUENCER_MT_add(bpy.types.Menu):
layout.itemM("SEQUENCER_MT_add_effect")
class SEQUENCER_MT_add_effect(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "Effect Strip..."
def draw(self, context):
@@ -182,6 +187,7 @@ class SEQUENCER_MT_add_effect(bpy.types.Menu):
layout.item_enumO("sequencer.effect_strip_add", 'type', 'SPEED')
class SEQUENCER_MT_strip(bpy.types.Menu):
+ __space_type__ = 'SEQUENCE_EDITOR'
__label__ = "Strip"
def draw(self, context):
diff --git a/release/scripts/ui/space_text.py b/release/scripts/ui/space_text.py
index 4860767d69d..117033c50a1 100644
--- a/release/scripts/ui/space_text.py
+++ b/release/scripts/ui/space_text.py
@@ -98,6 +98,7 @@ class TEXT_PT_find(bpy.types.Panel):
row.itemR(st, "find_all", text="All")
class TEXT_MT_text(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Text"
def draw(self, context):
@@ -139,6 +140,7 @@ class TEXT_MT_text(bpy.types.Menu):
#endif
class TEXT_MT_edit_view(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "View"
def draw(self, context):
@@ -148,6 +150,7 @@ class TEXT_MT_edit_view(bpy.types.Menu):
layout.item_enumO("text.move", "type", 'FILE_BOTTOM', text="Bottom of File")
class TEXT_MT_edit_select(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Select"
def draw(self, context):
@@ -157,6 +160,7 @@ class TEXT_MT_edit_select(bpy.types.Menu):
layout.itemO("text.select_line")
class TEXT_MT_edit_markers(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Markers"
def draw(self, context):
@@ -167,6 +171,7 @@ class TEXT_MT_edit_markers(bpy.types.Menu):
layout.itemO("text.previous_marker")
class TEXT_MT_format(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Format"
def draw(self, context):
@@ -185,6 +190,7 @@ class TEXT_MT_format(bpy.types.Menu):
layout.item_menu_enumO("text.convert_whitespace", "type")
class TEXT_MT_edit_to3d(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Text To 3D Object"
def draw(self, context):
@@ -194,6 +200,7 @@ class TEXT_MT_edit_to3d(bpy.types.Menu):
layout.item_booleanO("text.to_3d_object", "split_lines", True, text="One Object Per Line");
class TEXT_MT_edit(bpy.types.Menu):
+ __space_type__ = 'TEXT_EDITOR'
__label__ = "Edit"
def poll(self, context):
diff --git a/release/scripts/ui/space_time.py b/release/scripts/ui/space_time.py
index 2ead4305960..696dcf18623 100644
--- a/release/scripts/ui/space_time.py
+++ b/release/scripts/ui/space_time.py
@@ -64,6 +64,7 @@ class TIME_HT_header(bpy.types.Header):
row.itemO("anim.delete_keyframe", text="", icon='ICON_KEY_DEHLT')
class TIME_MT_view(bpy.types.Menu):
+ __space_type__ = 'TIMELINE'
__label__ = "View"
def draw(self, context):
@@ -78,6 +79,7 @@ class TIME_MT_view(bpy.types.Menu):
layout.itemR(st, "only_selected")
class TIME_MT_frame(bpy.types.Menu):
+ __space_type__ = 'TIMELINE'
__label__ = "Frame"
def draw(self, context):
@@ -98,10 +100,11 @@ class TIME_MT_frame(bpy.types.Menu):
layout.itemS()
sub = layout.row()
- #sub.active = tools.enable_auto_key
+ sub.active = tools.enable_auto_key
sub.itemM("TIME_MT_autokey")
class TIME_MT_playback(bpy.types.Menu):
+ __space_type__ = 'TIMELINE'
__label__ = "Playback"
def draw(self, context):
@@ -129,6 +132,7 @@ class TIME_MT_playback(bpy.types.Menu):
layout.itemR(scene, "scrub_audio")
class TIME_MT_autokey(bpy.types.Menu):
+ __space_type__ = 'TIMELINE'
__label__ = "Auto-Keyframing Mode"
def draw(self, context):
diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py
index 46a56f7d133..9798e0ccab6 100644
--- a/release/scripts/ui/space_userpref.py
+++ b/release/scripts/ui/space_userpref.py
@@ -12,12 +12,9 @@ class USERPREF_HT_header(bpy.types.Header):
layout.operator_context = "EXEC_AREA"
layout.itemO("wm.save_homefile", text="Save As Default")
-
- if userpref.active_section == 'INPUT':
- layout.operator_context = "INVOKE_DEFAULT"
- layout.itemO("wm.keyconfig_save", "Save Key Configuration...")
class USERPREF_MT_view(bpy.types.Menu):
+ __space_type__ = 'USER_PREFERENCES'
__label__ = "View"
def draw(self, context):
@@ -34,14 +31,14 @@ class USERPREF_PT_tabs(bpy.types.Panel):
layout.itemR(userpref, "active_section", expand=True)
-class USERPREF_PT_interface(bpy.types.Panel):
+class USERPREF_PT_view(bpy.types.Panel):
__space_type__ = 'USER_PREFERENCES'
- __label__ = "Interface"
+ __label__ = "View"
__show_header__ = False
def poll(self, context):
userpref = context.user_preferences
- return (userpref.active_section == 'INTERFACE')
+ return (userpref.active_section == 'VIEW_CONTROLS')
def draw(self, context):
layout = self.layout
@@ -90,27 +87,37 @@ class USERPREF_PT_interface(bpy.types.Panel):
sub1.itemR(view, "perspective_orthographic_switch")
sub1.itemR(view, "smooth_view")
sub1.itemR(view, "rotation_angle")
+ sub1.itemS()
+ sub1.itemL(text="NDOF Device:")
+ sub1.itemR(view, "ndof_pan_speed", text="Pan Speed")
+ sub1.itemR(view, "ndof_rotate_speed", text="Orbit Speed")
col = split.column()
sub = col.split(percentage=0.85)
sub1 = sub.column()
+ sub1.itemL(text="Mouse Buttons:")
+
+ sub2 = sub1.column()
+ sub2.enabled = (view.select_mouse == 'RIGHT')
+ sub2.itemR(view, "emulate_3_button_mouse")
+ sub1.itemL(text="Select With:")
+ sub1.row().itemR(view, "select_mouse", expand=True)
+ sub1.itemL(text="Middle Mouse:")
+ sub1.row().itemR(view, "middle_mouse", expand=True)
+ sub1.itemR(view, "use_middle_mouse_paste")
+ sub1.itemL(text="Mouse Wheel:")
+ sub1.itemR(view, "wheel_invert_zoom", text="Invert Zoom")
+ sub1.itemR(view, "wheel_scroll_lines", text="Scroll Lines")
+ sub1.itemS()
+ sub1.itemS()
+ sub1.itemS()
sub1.itemL(text="Menus:")
sub1.itemR(view, "open_mouse_over")
sub1.itemL(text="Menu Open Delay:")
sub1.itemR(view, "open_toplevel_delay", text="Top Level")
sub1.itemR(view, "open_sublevel_delay", text="Sub Level")
- sub1.itemS()
- sub1.itemS()
- sub1.itemS()
-
- sub1.itemL(text="Toolbox:")
- sub1.itemR(view, "use_column_layout")
- sub1.itemL(text="Open Toolbox Delay:")
- sub1.itemR(view, "open_left_mouse_delay", text="Hold LMB")
- sub1.itemR(view, "open_right_mouse_delay", text="Hold RMB")
-
col = split.column()
sub = col.split(percentage=0.85)
@@ -122,6 +129,14 @@ class USERPREF_PT_interface(bpy.types.Panel):
sub2.itemR(view, "manipulator_size", text="Size")
sub2.itemR(view, "manipulator_handle_size", text="Handle Size")
sub2.itemR(view, "manipulator_hotspot", text="Hotspot")
+ sub1.itemS()
+ sub1.itemS()
+ sub1.itemS()
+ sub1.itemL(text="Toolbox:")
+ sub1.itemR(view, "use_column_layout")
+ sub1.itemL(text="Open Toolbox Delay:")
+ sub1.itemR(view, "open_left_mouse_delay", text="Hold LMB")
+ sub1.itemR(view, "open_right_mouse_delay", text="Hold RMB")
class USERPREF_PT_edit(bpy.types.Panel):
__space_type__ = 'USER_PREFERENCES'
@@ -130,7 +145,7 @@ class USERPREF_PT_edit(bpy.types.Panel):
def poll(self, context):
userpref = context.user_preferences
- return (userpref.active_section == 'EDITING')
+ return (userpref.active_section == 'EDIT_METHODS')
def draw(self, context):
layout = self.layout
@@ -184,16 +199,14 @@ class USERPREF_PT_edit(bpy.types.Panel):
sub1 = sub.column()
sub1.itemL(text="Keyframing:")
sub1.itemR(edit, "use_visual_keying")
- sub1.itemR(edit, "keyframe_insert_needed", text="Only Insert Needed")
- sub1.itemS()
- sub1.itemL(text="New F-Curve Defaults:")
- sub1.itemR(edit, "new_interpolation_type", text="Interpolation")
+ sub1.itemR(edit, "new_interpolation_type", text="New F-Curves")
sub1.itemS()
- sub1.itemR(edit, "auto_keying_enable", text="Auto Keyframing:")
+ sub1.itemR(edit, "auto_keying_enable", text="Auto Keyframing")
sub2 = sub1.column()
- sub2.active = edit.auto_keying_enable
- sub2.itemR(edit, "auto_keyframe_insert_keyingset", text="Only Insert for Keying Set")
+ sub2.enabled = edit.auto_keying_enable
+ sub2.row().itemR(edit, "auto_keying_mode", expand=True)
sub2.itemR(edit, "auto_keyframe_insert_available", text="Only Insert Available")
+ sub2.itemR(edit, "auto_keyframe_insert_needed", text="Only Insert Needed")
sub1.itemS()
sub1.itemS()
@@ -233,7 +246,7 @@ class USERPREF_PT_system(bpy.types.Panel):
def poll(self, context):
userpref = context.user_preferences
- return (userpref.active_section == 'SYSTEM')
+ return (userpref.active_section == 'SYSTEM_OPENGL')
def draw(self, context):
layout = self.layout
@@ -261,7 +274,7 @@ class USERPREF_PT_system(bpy.types.Panel):
sub1.itemL(text="Sound:")
sub1.row().itemR(system, "audio_device", expand=True)
sub2 = sub1.column()
- sub2.active = system.audio_device != 'NONE'
+ sub2.active = system.audio_device != 'AUDIO_DEVICE_NULL'
sub2.itemR(system, "enable_all_codecs")
sub2.itemR(system, "game_sound")
sub2.itemR(system, "audio_channels", text="Channels")
@@ -301,7 +314,6 @@ class USERPREF_PT_system(bpy.types.Panel):
sub1.itemL(text="OpenGL:")
sub1.itemR(system, "clip_alpha", slider=True)
sub1.itemR(system, "use_mipmaps")
- sub1.itemR(system, "use_vbos")
sub1.itemL(text="Window Draw Method:")
sub1.row().itemR(system, "window_draw_method", expand=True)
sub1.itemL(text="Textures:")
@@ -317,14 +329,14 @@ class USERPREF_PT_system(bpy.types.Panel):
sub1.itemR(system, "prefetch_frames")
sub1.itemR(system, "memory_cache_limit")
-class USERPREF_PT_file(bpy.types.Panel):
+class USERPREF_PT_filepaths(bpy.types.Panel):
__space_type__ = 'USER_PREFERENCES'
- __label__ = "Files"
+ __label__ = "File Paths"
__show_header__ = False
def poll(self, context):
userpref = context.user_preferences
- return (userpref.active_section == 'FILES')
+ return (userpref.active_section == 'FILE_PATHS')
def draw(self, context):
layout = self.layout
@@ -383,314 +395,11 @@ class USERPREF_PT_file(bpy.types.Panel):
sub3.enabled = paths.auto_save_temporary_files
sub3.itemR(paths, "auto_save_time", text="Timer (mins)")
-class USERPREF_PT_input(bpy.types.Panel):
- __space_type__ = 'USER_PREFERENCES'
- __label__ = "Input"
- __show_header__ = False
-
- def poll(self, context):
- userpref = context.user_preferences
- return (userpref.active_section == 'INPUT')
-
- def draw(self, context):
- layout = self.layout
-
- userpref = context.user_preferences
- wm = context.manager
- #input = userpref.input
- input = userpref
- view = userpref.view
-
- split = layout.split(percentage=0.25)
-
- # General settings
- row = split.row()
- col = row.column()
-
- sub = col.column()
- sub.itemL(text="Configuration:")
- sub.item_pointerR(wm, "active_keyconfig", wm, "keyconfigs", text="")
-
- col.itemS()
-
- sub = col.column()
- sub.itemL(text="Mouse:")
- sub1 = sub.column()
- sub1.enabled = (view.select_mouse == 'RIGHT')
- sub1.itemR(view, "emulate_3_button_mouse")
- sub.itemR(view, "continuous_mouse")
-
- sub.itemL(text="Select With:")
- sub.row().itemR(view, "select_mouse", expand=True)
- #sub.itemL(text="Middle Mouse:")
- #sub.row().itemR(view, "middle_mouse", expand=True)
- #sub.itemR(view, "use_middle_mouse_paste")
-
- #col.itemS()
-
- #sub = col.column()
- #sub.itemL(text="Mouse Wheel:")
- #sub.itemR(view, "wheel_invert_zoom", text="Invert Zoom")
- #sub.itemR(view, "wheel_scroll_lines", text="Scroll Lines")
-
- col.itemS()
-
- sub = col.column()
- sub.itemL(text="NDOF Device:")
- sub.itemR(view, "ndof_pan_speed", text="Pan Speed")
- sub.itemR(view, "ndof_rotate_speed", text="Orbit Speed")
-
- row.itemS()
-
- # Keymap Settings
- col = split.column()
-
- kc = wm.active_keyconfig
- defkc = wm.default_keyconfig
- km = wm.active_keymap
-
- subsplit = col.split()
- subsplit.item_pointerR(wm, "active_keymap", defkc, "keymaps", text="Map:")
- if km.user_defined:
- row = subsplit.row()
- row.itemO("WM_OT_keymap_restore", text="Restore")
- row.item_booleanO("WM_OT_keymap_restore", "all", True, text="Restore All")
- else:
- row = subsplit.row()
- row.itemO("WM_OT_keymap_edit", text="Edit")
- row.itemL()
-
- col.itemS()
-
- for kmi in km.items:
- subcol = col.column()
- subcol.set_context_pointer("keyitem", kmi)
-
- row = subcol.row()
-
- if kmi.expanded:
- row.itemR(kmi, "expanded", text="", icon="ICON_TRIA_RIGHT")
- else:
- row.itemR(kmi, "expanded", text="", icon="ICON_TRIA_RIGHT")
-
- itemrow = row.row()
- itemrow.enabled = km.user_defined
- itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_DEHLT")
-
- itemcol = itemrow.column()
- itemcol.active = kmi.active
- row = itemcol.row()
- row.itemR(kmi, "idname", text="")
-
- sub = row.row()
- sub.scale_x = 0.6
- sub.itemR(kmi, "map_type", text="")
-
- sub = row.row(align=True)
- if kmi.map_type == 'KEYBOARD':
- sub.itemR(kmi, "type", text="", full_event=True)
- elif kmi.map_type == 'MOUSE':
- sub.itemR(kmi, "type", text="", full_event=True)
- elif kmi.map_type == 'TWEAK':
- sub.scale_x = 0.5
- sub.itemR(kmi, "type", text="")
- sub.itemR(kmi, "value", text="")
- elif kmi.map_type == 'TIMER':
- sub.itemR(kmi, "type", text="")
- else:
- sub.itemL()
-
- if kmi.expanded:
- if kmi.map_type not in ('TEXTINPUT', 'TIMER'):
- sub = itemcol.row(align=True)
-
- if kmi.map_type == 'KEYBOARD':
- sub.itemR(kmi, "type", text="", event=True)
- sub.itemR(kmi, "value", text="")
- elif kmi.map_type == 'MOUSE':
- sub.itemR(kmi, "type", text="")
- sub.itemR(kmi, "value", text="")
- else:
- sub.itemL()
- sub.itemL()
-
- subrow = sub.row()
- subrow.scale_x = 0.75
- subrow.itemR(kmi, "shift")
- subrow.itemR(kmi, "ctrl")
- subrow.itemR(kmi, "alt")
- subrow.itemR(kmi, "oskey", text="Cmd")
- sub.itemR(kmi, "key_modifier", text="", event=True)
-
- flow = itemcol.column_flow(columns=2)
- props = kmi.properties
-
- if props != None:
- for pname in dir(props):
- if not props.is_property_hidden(pname):
- flow.itemR(props, pname)
-
- itemcol.itemS()
-
- itemrow.itemO("wm.keyitem_remove", text="", icon="ICON_ZOOMOUT")
-
- itemrow = col.row()
- itemrow.itemL()
- itemrow.itemO("wm.keyitem_add", text="", icon="ICON_ZOOMIN")
- itemrow.enabled = km.user_defined
-
bpy.types.register(USERPREF_HT_header)
bpy.types.register(USERPREF_MT_view)
bpy.types.register(USERPREF_PT_tabs)
-bpy.types.register(USERPREF_PT_interface)
+bpy.types.register(USERPREF_PT_view)
bpy.types.register(USERPREF_PT_edit)
bpy.types.register(USERPREF_PT_system)
-bpy.types.register(USERPREF_PT_file)
-bpy.types.register(USERPREF_PT_input)
-
-class WM_OT_keyconfig_save(bpy.types.Operator):
- "Save key configuration to a python script."
- __idname__ = "wm.keyconfig_save"
- __label__ = "Save Key Configuration..."
- __props__ = [
- bpy.props.StringProperty(attr="path", name="File Path", description="File path to write file to.")]
-
- def _string_value(self, value):
- result = ""
- if isinstance(value, str):
- if value != "":
- result = "\'%s\'" % value
- elif isinstance(value, bool):
- if value:
- result = "True"
- else:
- result = "False"
- elif isinstance(value, float):
- result = "%.10f" % value
- elif isinstance(value, int):
- result = "%d" % value
- elif getattr(value, '__len__', False):
- if len(value):
- result = "["
- for i in range(0, len(value)):
- result += self._string_value(value[i])
- if i != len(value)-1:
- result += ", "
- result += "]"
- else:
- print("Save key configuration: can't write ", value)
-
- return result
-
- def execute(self, context):
- if not self.path:
- raise Exception("File path not set.")
-
- f = open(self.path, "w")
- if not f:
- raise Exception("Could not open file.")
-
- wm = context.manager
- kc = wm.active_keyconfig
-
- f.write('# Configuration %s\n' % kc.name)
-
- f.write("wm = bpy.data.windowmanagers[0]\n");
- f.write("kc = wm.add_keyconfig(\'%s\')\n\n" % kc.name)
-
- for km in kc.keymaps:
- f.write("# Map %s\n" % km.name)
- f.write("km = kc.add_keymap(\'%s\', space_type=\'%s\', region_type=\'%s\')\n\n" % (km.name, km.space_type, km.region_type))
- for kmi in km.items:
- f.write("kmi = km.add_item(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value))
- if kmi.shift:
- f.write(", shift=True")
- if kmi.ctrl:
- f.write(", ctrl=True")
- if kmi.alt:
- f.write(", alt=True")
- if kmi.oskey:
- f.write(", oskey=True")
- if kmi.key_modifier and kmi.key_modifier != 'NONE':
- f.write(", key_modifier=\'%s\'" % kmi.key_modifier)
- f.write(")\n")
-
- props = kmi.properties
-
- if props != None:
- for pname in dir(props):
- if props.is_property_set(pname) and not props.is_property_hidden(pname):
- value = eval("props.%s" % pname)
- value = self._string_value(value)
- if value != "":
- f.write("kmi.properties.%s = %s\n" % (pname, value))
-
- f.write("\n")
-
- f.close()
-
- return ('FINISHED',)
-
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self.__operator__)
- return ('RUNNING_MODAL',)
-
-class WM_OT_keymap_edit(bpy.types.Operator):
- "Edit key map."
- __idname__ = "wm.keymap_edit"
- __label__ = "Edit Key Map"
-
- def execute(self, context):
- wm = context.manager
- km = wm.active_keymap
- km.copy_to_user()
- return ('FINISHED',)
-
-class WM_OT_keymap_restore(bpy.types.Operator):
- "Restore key map"
- __idname__ = "wm.keymap_restore"
- __label__ = "Restore Key Map"
- __props__ = [bpy.props.BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default.")]
-
- def execute(self, context):
- wm = context.manager
-
- if self.all:
- for km in wm.default_keyconfig.keymaps:
- km.restore_to_default()
- else:
- km = wm.active_keymap
- km.restore_to_default()
-
- return ('FINISHED',)
-
-class WM_OT_keyitem_add(bpy.types.Operator):
- "Add key map item."
- __idname__ = "wm.keyitem_add"
- __label__ = "Add Key Map Item"
-
- def execute(self, context):
- wm = context.manager
- km = wm.active_keymap
- kmi = km.add_item("", "A", "PRESS")
- return ('FINISHED',)
-
-class WM_OT_keyitem_remove(bpy.types.Operator):
- "Remove key map item."
- __idname__ = "wm.keyitem_remove"
- __label__ = "Remove Key Map Item"
-
- def execute(self, context):
- wm = context.manager
- kmi = context.keyitem
- km = wm.active_keymap
- km.remove_item(kmi)
- return ('FINISHED',)
-
-bpy.ops.add(WM_OT_keyconfig_save)
-bpy.ops.add(WM_OT_keymap_edit)
-bpy.ops.add(WM_OT_keymap_restore)
-bpy.ops.add(WM_OT_keyitem_add)
-bpy.ops.add(WM_OT_keyitem_remove)
+bpy.types.register(USERPREF_PT_filepaths)
diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py
index cac2b88f39e..a270e053126 100644
--- a/release/scripts/ui/space_view3d.py
+++ b/release/scripts/ui/space_view3d.py
@@ -1,8 +1,6 @@
import bpy
-import dynamic_menu
-
# ********** Header **********
class VIEW3D_HT_header(bpy.types.Header):
@@ -46,6 +44,7 @@ class VIEW3D_HT_header(bpy.types.Header):
# ********** Utilities **********
class VIEW3D_MT_showhide(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Show/Hide"
_operator_name = ""
@@ -57,6 +56,7 @@ class VIEW3D_MT_showhide(bpy.types.Menu):
layout.item_booleanO("%s.hide" % self._operator_name, "unselected", True, text="Hide Unselected")
class VIEW3D_MT_snap(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Snap"
def draw(self, context):
@@ -75,6 +75,7 @@ class VIEW3D_MT_snap(bpy.types.Menu):
# ********** View menus **********
class VIEW3D_MT_view(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "View"
def draw(self, context):
@@ -119,6 +120,7 @@ class VIEW3D_MT_view(bpy.types.Menu):
layout.itemO("screen.screen_full_area", text="Toggle Full Screen")
class VIEW3D_MT_view_navigation(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Navigation"
def draw(self, context):
@@ -140,6 +142,7 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu):
layout.itemO("view3d.fly")
class VIEW3D_MT_view_align(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Align View"
def draw(self, context):
@@ -148,16 +151,16 @@ class VIEW3D_MT_view_align(bpy.types.Menu):
layout.itemO("view3d.view_center")
class VIEW3D_MT_view_cameras(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Cameras"
def draw(self, context):
layout = self.layout
-
- layout.itemO("view3d.object_as_camera")
# ********** Select menus, suffix from context.mode **********
class VIEW3D_MT_select_object(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -172,11 +175,11 @@ class VIEW3D_MT_select_object(bpy.types.Menu):
layout.itemO("object.select_random", text="Random")
layout.itemO("object.select_mirror", text="Mirror")
layout.itemO("object.select_by_layer", text="Select All by Layer")
- layout.item_menu_enumO("object.select_by_type", "type", "", text="Select All by Type...")
- layout.item_menu_enumO("object.select_grouped", "type", text="Select Grouped...")
- layout.itemO("object.select_pattern", text="Select Pattern...")
+ layout.item_enumO("object.select_by_type", "type", "", text="Select All by Type...")
+ layout.itemO("object.select_grouped", text="Select Grouped...")
class VIEW3D_MT_select_pose(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -207,6 +210,7 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
props.direction = 'CHILD'
class VIEW3D_MT_select_particle(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -225,6 +229,7 @@ class VIEW3D_MT_select_particle(bpy.types.Menu):
layout.itemO("particle.select_less")
class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -268,6 +273,7 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
layout.itemO("mesh.region_to_loop")
class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -296,6 +302,7 @@ class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
layout.itemO("curve.select_less")
class VIEW3D_MT_select_edit_surface(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -321,6 +328,7 @@ class VIEW3D_MT_select_edit_surface(bpy.types.Menu):
layout.itemO("curve.select_less")
class VIEW3D_MT_select_edit_metaball(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -338,6 +346,7 @@ class VIEW3D_MT_select_edit_metaball(bpy.types.Menu):
layout.itemO("mball.select_random_metaelems")
class VIEW3D_MT_select_edit_lattice(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -350,6 +359,7 @@ class VIEW3D_MT_select_edit_lattice(bpy.types.Menu):
layout.itemO("lattice.select_all_toggle", text="Select/Deselect All")
class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -378,6 +388,7 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
props.direction = 'CHILD'
class VIEW3D_MT_select_face(bpy.types.Menu):# XXX no matching enum
+ __space_type__ = 'VIEW_3D'
__label__ = "Select"
def draw(self, context):
@@ -388,6 +399,7 @@ class VIEW3D_MT_select_face(bpy.types.Menu):# XXX no matching enum
# ********** Object menu **********
class VIEW3D_MT_object(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__context__ = "objectmode"
__label__ = "Object"
@@ -395,7 +407,6 @@ class VIEW3D_MT_object(bpy.types.Menu):
layout = self.layout
layout.itemM("VIEW3D_MT_object_clear")
- layout.itemM("VIEW3D_MT_object_apply")
layout.itemM("VIEW3D_MT_snap")
layout.itemS()
@@ -425,9 +436,8 @@ class VIEW3D_MT_object(bpy.types.Menu):
layout.itemM("VIEW3D_MT_object_showhide")
- layout.item_menu_enumO("object.convert", "target")
-
class VIEW3D_MT_object_clear(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Clear"
def draw(self, context):
@@ -438,19 +448,8 @@ class VIEW3D_MT_object_clear(bpy.types.Menu):
layout.itemO("object.scale_clear", text="Scale")
layout.itemO("object.origin_clear", text="Origin")
-class VIEW3D_MT_object_apply(bpy.types.Menu):
- __label__ = "Apply"
-
- def draw(self, context):
- layout = self.layout
-
- layout.itemO("object.location_apply", text="Location")
- layout.itemO("object.rotation_apply", text="Rotation")
- layout.itemO("object.scale_apply", text="Scale")
- layout.itemS()
- layout.itemO("object.visual_transform_apply", text="Visual Transform")
-
class VIEW3D_MT_object_parent(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Parent"
def draw(self, context):
@@ -460,6 +459,7 @@ class VIEW3D_MT_object_parent(bpy.types.Menu):
layout.itemO("object.parent_clear", text="Clear")
class VIEW3D_MT_object_track(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Track"
def draw(self, context):
@@ -469,6 +469,7 @@ class VIEW3D_MT_object_track(bpy.types.Menu):
layout.itemO("object.track_clear", text="Clear")
class VIEW3D_MT_object_group(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Group"
def draw(self, context):
@@ -483,6 +484,7 @@ class VIEW3D_MT_object_group(bpy.types.Menu):
layout.itemO("group.objects_remove_active")
class VIEW3D_MT_object_constraints(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Constraints"
def draw(self, context):
@@ -492,6 +494,7 @@ class VIEW3D_MT_object_constraints(bpy.types.Menu):
layout.itemO("object.constraints_clear")
class VIEW3D_MT_object_showhide(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Show/Hide"
def draw(self, context):
@@ -504,6 +507,7 @@ class VIEW3D_MT_object_showhide(bpy.types.Menu):
# ********** Vertex paint menu **********
class VIEW3D_MT_paint_vertex(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Paint"
def draw(self, context):
@@ -518,6 +522,7 @@ class VIEW3D_MT_paint_vertex(bpy.types.Menu):
# ********** Sculpt menu **********
class VIEW3D_MT_sculpt(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Sculpt"
def draw(self, context):
@@ -553,6 +558,7 @@ class VIEW3D_MT_sculpt(bpy.types.Menu):
# ********** Particle menu **********
class VIEW3D_MT_particle(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Particle"
def draw(self, context):
@@ -582,6 +588,7 @@ class VIEW3D_MT_particle_showhide(VIEW3D_MT_showhide):
# ********** Pose Menu **********
class VIEW3D_MT_pose(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Pose"
def draw(self, context):
@@ -641,6 +648,7 @@ class VIEW3D_MT_pose(bpy.types.Menu):
layout.item_menu_enumO("pose.flags_set", 'mode', text="Bone Settings")
class VIEW3D_MT_pose_transform(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Clear Transform"
def draw(self, context):
@@ -655,6 +663,7 @@ class VIEW3D_MT_pose_transform(bpy.types.Menu):
layout.itemL(text="Origin")
class VIEW3D_MT_pose_pose(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Pose Library"
def draw(self, context):
@@ -669,6 +678,7 @@ class VIEW3D_MT_pose_pose(bpy.types.Menu):
layout.itemO("poselib.pose_remove", text="Remove Pose...")
class VIEW3D_MT_pose_motion(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Motion Paths"
def draw(self, context):
@@ -678,6 +688,7 @@ class VIEW3D_MT_pose_motion(bpy.types.Menu):
layout.itemO("pose.paths_clear", text="Clear")
class VIEW3D_MT_pose_group(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Bone Groups"
def draw(self, context):
@@ -692,6 +703,7 @@ class VIEW3D_MT_pose_group(bpy.types.Menu):
class VIEW3D_MT_pose_ik(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Inverse Kinematics"
def draw(self, context):
@@ -701,6 +713,7 @@ class VIEW3D_MT_pose_ik(bpy.types.Menu):
layout.itemO("pose.ik_clear")
class VIEW3D_MT_pose_constraints(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Constraints"
def draw(self, context):
@@ -716,6 +729,7 @@ class VIEW3D_MT_pose_showhide(VIEW3D_MT_showhide):
# Edit MESH
class VIEW3D_MT_edit_mesh(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Mesh"
def draw(self, context):
@@ -750,44 +764,19 @@ class VIEW3D_MT_edit_mesh(bpy.types.Menu):
layout.itemS()
layout.itemR(settings, "automerge_editing")
- layout.item_menu_enumR(settings, "proportional_editing")
+ layout.itemR(settings, "proportional_editing")
layout.item_menu_enumR(settings, "proportional_editing_falloff")
layout.itemS()
layout.itemM("VIEW3D_MT_edit_mesh_showhide")
-# Only used by the menu
-class VIEW3D_MT_edit_mesh_specials(bpy.types.Menu):
- __label__ = "Specials"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.itemO("mesh.subdivide", text="Subdivide")
- layout.item_floatO("mesh.subdivide", "smoothness", 1.0, text="Subdivide Smooth")
- layout.itemO("mesh.merge", text="Merge...")
- layout.itemO("mesh.remove_doubles", text="Remove Doubles")
- layout.itemO("mesh.hide", text="Hide")
- layout.itemO("mesh.reveal", text="Reveal")
- layout.itemO("mesh.select_inverse", text="Select Inverse")
- layout.itemO("mesh.flip_normals")
- layout.itemO("mesh.vertices_smooth", text="Smooth")
- # layout.itemO("mesh.bevel", text="Bevel")
- layout.itemO("mesh.faces_shade_smooth")
- layout.itemO("mesh.faces_shade_flat")
- # layout.itemO("mesh.blend_from_shape", text="Blend From Shape")
- # layout.itemO("mesh.shape_propagate_to_all", text="Propagate to All Shapes")
- layout.itemO("mesh.select_vertex_path", text="Select Vertex Path")
-
class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Vertices"
def draw(self, context):
layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
layout.itemO("mesh.merge")
layout.itemO("mesh.rip")
@@ -798,19 +787,14 @@ class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
layout.itemO("mesh.vertices_smooth")
layout.itemO("mesh.remove_doubles")
-
- layout.itemO("mesh.select_vertex_path", text="Select Vertex Path")
-
- # uiItemO(layout, "Blend From Shape", 0, "mesh.blend_from_shape");
- # uiItemO(layout, "Propagate to All Shapes", 0, "mesh.shape_propagate_to_all");
class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Edges"
def draw(self, context):
layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
+
layout.itemO("mesh.edge_face_add")
layout.itemO("mesh.subdivide")
@@ -829,30 +813,13 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
layout.item_enumO("mesh.edge_rotate", "direction", 'CW', text="Rotate Edge CW")
layout.item_enumO("mesh.edge_rotate", "direction", 'CCW', text="Rotate Edge CCW")
- layout.itemS()
-
- layout.itemO("TFM_OT_edge_slide", text="Edge Slide")
- layout.itemO("mesh.loop_multi_select", text="Edge Loop")
-
- # uiItemO(layout, "Loopcut", 0, "mesh.loop_cut"); // CutEdgeloop(em, 1);
- # uiItemO(layout, "Edge Slide", 0, "mesh.edge_slide"); // EdgeSlide(em, 0,0.0);
-
- layout.item_booleanO("mesh.loop_multi_select", "ring", True, text="Edge Ring")
-
- layout.itemO("mesh.loop_to_region")
- layout.itemO("mesh.region_to_loop")
-
-
-class VIEW3D_MT_edit_mesh_faces(dynamic_menu.DynMenu):
+class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Faces"
def draw(self, context):
layout = self.layout
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.itemO("mesh.flip_normals")
- # layout.itemO("mesh.bevel")
- # layout.itemO("mesh.bevel")
+
layout.itemO("mesh.edge_face_add")
layout.itemO("mesh.fill")
layout.itemO("mesh.beauty_fill")
@@ -867,23 +834,9 @@ class VIEW3D_MT_edit_mesh_faces(dynamic_menu.DynMenu):
layout.itemO("mesh.faces_shade_smooth")
layout.itemO("mesh.faces_shade_flat")
-
- layout.itemS()
-
- # uiItemO(layout, NULL, 0, "mesh.face_mode"); // mesh_set_face_flags(em, 1);
- # uiItemBooleanO(layout, NULL, 0, "mesh.face_mode", "clear", 1); // mesh_set_face_flags(em, 0);
-
- layout.item_enumO("mesh.edge_rotate", "direction", 'CW', text="Rotate Edge CW")
-
- layout.itemS()
-
- layout.item_menu_enumO("mesh.uvs_rotate", "direction")
- layout.item_menu_enumO("mesh.uvs_mirror", "axis")
- layout.item_menu_enumO("mesh.colors_rotate", "direction")
- layout.item_menu_enumO("mesh.colors_mirror", "axis")
-
class VIEW3D_MT_edit_mesh_normals(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Normals"
def draw(self, context):
@@ -933,11 +886,13 @@ def draw_curve(self, context):
layout.itemM("VIEW3D_MT_edit_curve_showhide")
class VIEW3D_MT_edit_curve(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Curve"
draw = draw_curve
class VIEW3D_MT_edit_curve_ctrlpoints(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Control Points"
def draw(self, context):
@@ -955,6 +910,7 @@ class VIEW3D_MT_edit_curve_ctrlpoints(bpy.types.Menu):
layout.item_menu_enumO("curve.handle_type_set", "type")
class VIEW3D_MT_edit_curve_segments(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Segments"
def draw(self, context):
@@ -968,12 +924,14 @@ class VIEW3D_MT_edit_curve_showhide(VIEW3D_MT_showhide):
# Edit SURFACE
class VIEW3D_MT_edit_surface(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Surface"
draw = draw_curve
# Edit TEXT
class VIEW3D_MT_edit_text(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Text"
def draw(self, context):
@@ -986,6 +944,7 @@ class VIEW3D_MT_edit_text(bpy.types.Menu):
layout.itemm("view3d_mt_edit_text_chars")
class VIEW3D_MT_edit_text_chars(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Special Characters"
def draw(self, context):
@@ -1020,6 +979,7 @@ class VIEW3D_MT_edit_text_chars(bpy.types.Menu):
# Edit META
class VIEW3D_MT_edit_meta(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Metaball"
def draw(self, context):
@@ -1049,6 +1009,7 @@ class VIEW3D_MT_edit_meta(bpy.types.Menu):
layout.itemM("VIEW3D_MT_edit_meta_showhide")
class VIEW3D_MT_edit_meta_showhide(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Show/Hide"
def draw(self, context):
@@ -1060,6 +1021,7 @@ class VIEW3D_MT_edit_meta_showhide(bpy.types.Menu):
# Edit LATTICE
class VIEW3D_MT_edit_lattice(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Lattice"
def draw(self, context):
@@ -1080,6 +1042,7 @@ class VIEW3D_MT_edit_lattice(bpy.types.Menu):
# Edit ARMATURE
class VIEW3D_MT_edit_armature(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Armature"
def draw(self, context):
@@ -1136,6 +1099,7 @@ class VIEW3D_MT_edit_armature(bpy.types.Menu):
layout.item_menu_enumO("armature.flags_set", "mode", text="Bone Settings")
class VIEW3D_MT_edit_armature_parent(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Parent"
def draw(self, context):
@@ -1145,6 +1109,7 @@ class VIEW3D_MT_edit_armature_parent(bpy.types.Menu):
layout.itemO("armature.parent_clear", text="Clear")
class VIEW3D_MT_edit_armature_roll(bpy.types.Menu):
+ __space_type__ = 'VIEW_3D'
__label__ = "Bone Roll"
def draw(self, context):
@@ -1205,7 +1170,6 @@ class VIEW3D_PT_3dview_display(bpy.types.Panel):
def draw(self, context):
layout = self.layout
view = context.space_data
- gs = context.scene.game_data
col = layout.column()
col.itemR(view, "display_floor", text="Grid Floor")
@@ -1215,21 +1179,16 @@ class VIEW3D_PT_3dview_display(bpy.types.Panel):
col.itemR(view, "outline_selected")
col.itemR(view, "all_object_centers")
col.itemR(view, "relationship_lines")
+ col.itemR(view, "textured_solid")
+
+ layout.itemS()
+
+ layout.itemO("screen.region_foursplit", text="Toggle Quad View")
col = layout.column()
- col.itemL(text="Shading:")
- col.itemR(gs, "material_mode", text="")
- col.itemR(view, "textured_solid")
-
-
-# XXX - the Quad View options don't work yet
-# layout.itemS()
-#
-# layout.itemO("screen.region_foursplit", text="Toggle Quad View")
-# col = layout.column()
-# col.itemR(view, "lock_rotation")
-# col.itemR(view, "box_preview")
-# col.itemR(view, "box_clip")
+ col.itemR(view, "lock_rotation")
+ col.itemR(view, "box_preview")
+ col.itemR(view, "box_clip")
class VIEW3D_PT_3dview_meshdisplay(bpy.types.Panel):
__space_type__ = 'VIEW_3D'
@@ -1248,8 +1207,6 @@ class VIEW3D_PT_3dview_meshdisplay(bpy.types.Panel):
col = layout.column()
col.itemL(text="Overlays:")
col.itemR(mesh, "draw_edges", text="Edges")
- col.itemR(mesh, "all_edges")
- col.itemS()
col.itemR(mesh, "draw_faces", text="Faces")
col.itemR(mesh, "draw_creases", text="Creases")
col.itemR(mesh, "draw_bevel_weights", text="Bevel Weights")
@@ -1268,6 +1225,7 @@ class VIEW3D_PT_3dview_meshdisplay(bpy.types.Panel):
col.itemR(mesh, "draw_edge_angle")
col.itemR(mesh, "draw_face_area")
+
class VIEW3D_PT_3dview_curvedisplay(bpy.types.Panel):
__space_type__ = 'VIEW_3D'
__region_type__ = 'UI'
@@ -1287,7 +1245,8 @@ class VIEW3D_PT_3dview_curvedisplay(bpy.types.Panel):
col.itemR(curve, "draw_handles", text="Handles")
col.itemR(curve, "draw_normals", text="Normals")
col.itemR(context.scene.tool_settings, "normal_size", text="Normal Size")
-
+
+
class VIEW3D_PT_background_image(bpy.types.Panel):
__space_type__ = 'VIEW_3D'
__region_type__ = 'UI'
@@ -1342,54 +1301,10 @@ class VIEW3D_PT_transform_orientations(bpy.types.Panel):
view = context.space_data
col = layout.column()
-
- col.itemR(view, "transform_orientation")
- col.itemO("tfm.create_orientation", text="Create")
-
- orientation = view.current_orientation
-
- if orientation:
- col.itemR(orientation, "name")
- col.itemO("tfm.delete_orientation", text="Delete")
-
-# Operators
-
-class OBJECT_OT_select_pattern(bpy.types.Operator):
- '''Select object matching a naming pattern.'''
- __idname__ = "object.select_pattern"
- __label__ = "Select Pattern"
- __register__ = True
- __undo__ = True
- __props__ = [
- bpy.props.StringProperty(attr="pattern", name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen= 32, default= "*"),
- bpy.props.BoolProperty(attr="case_sensitive", name="Case Sensitive", description="Do a case sensitive compare", default= False),
- bpy.props.BoolProperty(attr="extend", name="Extend", description="Extend the existing selection", default= True),
- ]
-
- def execute(self, context):
-
- import fnmatch
- if self.case_sensitive: pattern_match = fnmatch.fnmatchcase
- else: pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
-
- for ob in context.visible_objects:
- if pattern_match(ob.name, self.pattern):
- ob.selected = True
- elif not self.extend:
- ob.selected = False
-
- return ('FINISHED',)
-
- # TODO - python cant do popups yet
- '''
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self.__operator__)
- return ('RUNNING_MODAL',)
- '''
-
-
-
+ col.itemO("TFM_OT_select_orientation", text="Select")
+ col.itemO("TFM_OT_create_orientation", text="Create")
+ col.itemO("TFM_OT_delete_orientation", text="Delete")
+
bpy.types.register(VIEW3D_HT_header) # Header
bpy.types.register(VIEW3D_MT_view) #View Menus
@@ -1409,7 +1324,6 @@ bpy.types.register(VIEW3D_MT_select_edit_armature)
bpy.types.register(VIEW3D_MT_select_face) # XXX todo
bpy.types.register(VIEW3D_MT_object) # Object Menu
-bpy.types.register(VIEW3D_MT_object_apply)
bpy.types.register(VIEW3D_MT_object_clear)
bpy.types.register(VIEW3D_MT_object_parent)
bpy.types.register(VIEW3D_MT_object_track)
@@ -1436,7 +1350,6 @@ bpy.types.register(VIEW3D_MT_pose_showhide)
bpy.types.register(VIEW3D_MT_snap) # Edit Menus
bpy.types.register(VIEW3D_MT_edit_mesh)
-bpy.types.register(VIEW3D_MT_edit_mesh_specials) # Only as a menu for keybindings
bpy.types.register(VIEW3D_MT_edit_mesh_vertices)
bpy.types.register(VIEW3D_MT_edit_mesh_edges)
bpy.types.register(VIEW3D_MT_edit_mesh_faces)
@@ -1467,7 +1380,4 @@ bpy.types.register(VIEW3D_PT_3dview_display)
bpy.types.register(VIEW3D_PT_3dview_meshdisplay)
bpy.types.register(VIEW3D_PT_3dview_curvedisplay)
bpy.types.register(VIEW3D_PT_background_image)
-bpy.types.register(VIEW3D_PT_transform_orientations)
-
-bpy.ops.add(OBJECT_OT_select_pattern)
-
+bpy.types.register(VIEW3D_PT_transform_orientations) \ No newline at end of file
diff --git a/release/scripts/ui/space_view3d_toolbar.py b/release/scripts/ui/space_view3d_toolbar.py
index d93a2d26040..4c1b54ea8e6 100644
--- a/release/scripts/ui/space_view3d_toolbar.py
+++ b/release/scripts/ui/space_view3d_toolbar.py
@@ -39,12 +39,6 @@ class VIEW3D_PT_tools_objectmode(View3DPanel):
col.itemO("anim.delete_keyframe_v3d", text="Remove")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -92,12 +86,6 @@ class VIEW3D_PT_tools_meshedit(View3DPanel):
col.itemO("mesh.uvs_mirror")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -139,12 +127,6 @@ class VIEW3D_PT_tools_curveedit(View3DPanel):
col.itemO("curve.subdivide")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -178,12 +160,6 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel):
col.itemO("curve.subdivide")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -241,12 +217,6 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel):
col.itemO("armature.extrude")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -268,12 +238,6 @@ class VIEW3D_PT_tools_mballedit(View3DPanel):
col.itemO("tfm.resize", text="Scale")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -295,12 +259,6 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel):
col.itemO("tfm.resize", text="Scale")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -345,12 +303,6 @@ class VIEW3D_PT_tools_posemode(View3DPanel):
col.itemO("pose.breakdown", text="Breakdowner")
col = layout.column(align=True)
- col.itemL(text="Grease Pencil:")
- col.item_enumO("gpencil.draw", "mode", 'DRAW', text="Draw Freehand")
- col.item_enumO("gpencil.draw", "mode", 'DRAW_STRAIGHT', text="Straight Line")
- col.item_enumO("gpencil.draw", "mode", 'ERASER', text="Eraser")
-
- col = layout.column(align=True)
col.itemL(text="Repeat:")
col.itemO("screen.repeat_last")
col.itemO("screen.repeat_history", text="History...")
@@ -724,7 +676,9 @@ class VIEW3D_PT_tools_particlemode(View3DPanel):
pe = context.tool_settings.particle_edit
ob = pe.object
- layout.itemR(pe, "type", text="")
+ row = layout.row()
+ row.itemL(text="Edit:")
+ row.itemR(pe, "type", text="")
if pe.type == 'PARTICLES':
if ob.particle_systems:
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/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 99297714fd2..025ffc49ab1 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -40,6 +40,7 @@ ADD_SUBDIRECTORY(makesrna)
ADD_SUBDIRECTORY(readblenfile)
ADD_SUBDIRECTORY(render)
ADD_SUBDIRECTORY(blenfont)
+ADD_SUBDIRECTORY(bmesh)
ADD_SUBDIRECTORY(ikplugin)
IF(WITH_OPENEXR)
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 3625678f610..71971e7c072 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 076747cb845..ec7998cc064 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -30,6 +30,45 @@
#ifndef BKE_DERIVEDMESH_H
#define BKE_DERIVEDMESH_H
+/*
+ Basic design of the DerivedMesh system:
+
+ DerivedMesh is a common set of interfaces for mesh systems.
+
+ There are three main mesh data structures in Blender: Mesh, CDDM, and BMesh.
+ These, and a few others, all implement DerivedMesh interfaces,
+ which contains unified drawing interfaces, a few utility interfaces,
+ and a bunch of read-only interfaces intended mostly for conversion from
+ one format to another.
+
+ All Mesh structures in blender make use of CustomData, which is used to store
+ per-element attributes and interpolate them (e.g. uvs, vcols, vgroups, etc).
+
+ Mesh is the "serialized" structure, used for storing object-mode mesh data
+ and also for saving stuff to disk. It's interfaces are also what DerivedMesh
+ uses to communicate with.
+
+ CDDM is a little mesh library, that uses Mesh data structures in the backend.
+ It's mostly used for modifiers, and has the advantages of not taking much
+ resources.
+
+ BMesh is a full-on brep, used for editmode, some modifiers, etc. It's much
+ more capable (if memory-intensive) then CDDM.
+
+ DerivedMesh is somewhat hackish. Many places assumes that a DerivedMesh is
+ a CDDM (most of the time by simply copying it and converting it to one).
+ CDDM is the original structure for modifiers, but has since been superseded
+ by BMesh, at least for the foreseeable future.
+*/
+
+/*
+ * Note: This sturcture is read-only, for all practical purposes.
+ * At some point in the future, we may want to consider
+ * creating a replacement structure that implements a proper
+ * abstract mesh kernel interface. Or, we can leave this
+ * as it is and stick with using BMesh and CDDM.
+ */
+
/* TODO (Probably)
*
* o Make drawMapped* functions take a predicate function that
@@ -43,6 +82,8 @@
*/
#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+
#include "BKE_customdata.h"
#include "BKE_bvhutils.h"
@@ -53,45 +94,103 @@ struct MTFace;
struct Object;
struct Scene;
struct Mesh;
-struct EditMesh;
+struct BMEditMesh;
struct ModifierData;
struct MCol;
struct ColorBand;
struct GPUVertexAttribs;
struct GPUDrawObject;
+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.
+ Also, the mface origindex layer indexes mpolys, not mfaces.
+*/
+
+/*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);
+
+/* derivedmesh 2.0 interface ideas (will likely never be implemented ;):
+ void (*interpLoopData)(void *self, void **src_blocks,
+ float *weights, float *sub_weights, int count);
+
+ //a generic handle for a loop
+ intptr_t lhandle;
+
+ inside DerivedMesh itself:
+ //
+ //void (*interpLoopData)(DerivedMesh *dm, DMLoopIter *destloop,
+ // intptr_t *loop_handles, int totloop);
+*/
+} 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;
struct GPUDrawObject *drawObject;
/* 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,
@@ -100,21 +199,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
@@ -122,7 +221,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
@@ -130,8 +229,21 @@ 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
* coordinate and normal. For historical reasons the normal can be
@@ -220,7 +332,7 @@ struct DerivedMesh {
*/
void (*drawFacesTex)(DerivedMesh *dm,
int (*setDrawOptions)(struct MTFace *tface,
- struct MCol *mcol, int matnr));
+ int has_vcol, int matnr));
/* Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
@@ -301,13 +413,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
@@ -333,6 +447,8 @@ void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
+void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
@@ -352,6 +468,7 @@ void *DM_get_face_data(struct DerivedMesh *dm, int index, int type);
*/
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
+void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_face_data_layer(struct DerivedMesh *dm, int type);
/* custom data setting functions
@@ -370,6 +487,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);
@@ -379,8 +500,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
@@ -410,12 +536,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);
@@ -436,6 +570,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 */
@@ -451,17 +588,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_blender.h b/source/blender/blenkernel/BKE_blender.h
index e91e434b97d..cbce20a4980 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -75,6 +75,7 @@ extern void BKE_undo_name(struct bContext *C, const char *name);
extern void BKE_reset_undo(void);
extern char *BKE_undo_menu_string(void);
extern void BKE_undo_number(struct bContext *C, int nr);
+void BKE_undo_save(char *fname);
extern void BKE_undo_save_quit(void);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h
index 957cd8ef9bd..fc43ae0f9a5 100644
--- a/source/blender/blenkernel/BKE_bmesh.h
+++ b/source/blender/blenkernel/BKE_bmesh.h
@@ -1,7 +1,7 @@
/**
* BKE_bmesh.h jan 2007
*
- * BMesh modeler structure and functions.
+ * (old) BMesh modeler structure and functions.
*
* $Id$
*
@@ -52,6 +52,7 @@ struct BME_Edge;
struct BME_Poly;
struct BME_Loop;
+/*NOTE: this is the bmesh 1.0 code. it's completely outdated.*/
/*Notes on further structure Cleanup:
-Remove the tflags, they belong in custom data layers
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index a570b4fe598..13219c8bb30 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -38,12 +38,17 @@
#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);
+
+/*tests if a given DerivedMesh is a CDDM*/
+int CDDM_Check(struct DerivedMesh *dm);
/* 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,17 +59,26 @@ 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.
*/
-struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
+struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm, int faces_from_tessfaces);
/* creates a CDDerivedMesh with the same layer stack configuration as the
* given DerivedMesh and containing the requested numbers of elements.
* 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
@@ -79,9 +93,14 @@ void CDDM_calc_normals(struct DerivedMesh *dm);
/* calculates edges for a CDDerivedMesh (from face data)
* this completely replaces the current edge data in the DerivedMesh
+ * builds edges from the tesselated face data.
*/
void CDDM_calc_edges(struct DerivedMesh *dm);
+/* same as CDDM_calc_edges only makes edges from ngon faces instead of tesselation
+ faces*/
+void CDDM_calc_edges_poly(struct DerivedMesh *dm);
+
/* lowers the number of vertices/edges/faces in a CDDerivedMesh
* the layer data stays the same size
*/
@@ -95,7 +114,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 +125,18 @@ 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);
+
+/*Assigns news m*** layers to the cddm. Note that you must handle
+ freeing the old ones yourself. Also you must ensure dm->num****Data
+ is correct.*/
+void CDDM_set_mvert(struct DerivedMesh *dm, struct MVert *mvert);
+void CDDM_set_medge(struct DerivedMesh *dm, struct MEdge *medge);
+void CDDM_set_mface(struct DerivedMesh *dm, struct MFace *mface);
+void CDDM_set_mloop(struct DerivedMesh *dm, struct MLoop *mloop);
+void CDDM_set_mpoly(struct DerivedMesh *dm, struct MPoly *mpoly);
+
#endif
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 95ee918a888..17513b1b7c3 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -32,10 +32,14 @@
#ifndef BKE_CUSTOMDATA_H
#define BKE_CUSTOMDATA_H
+struct BMesh;
struct CustomData;
struct CustomDataLayer;
typedef unsigned int CustomDataMask;
+/*a data type large enough to hold 1 element from any customdata layer type*/
+typedef struct {unsigned char data[64];} CDBlockBytes;
+
extern const CustomDataMask CD_MASK_BAREMESH;
extern const CustomDataMask CD_MASK_MESH;
extern const CustomDataMask CD_MASK_EDITMESH;
@@ -58,6 +62,25 @@ extern const CustomDataMask CD_MASK_FACECORNERS;
#define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source
has same number of elements */
+/* Checks if the layer at physical offset layern (in data->layers) support math
+ * the below operations.
+ */
+int CustomData_layer_has_math(struct CustomData *data, int layern);
+
+/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
+ another, while not overwriting anything else (e.g. flags). probably only
+ implemented for mloopuv/mloopcol, for now.*/
+void CustomData_data_copy_value(int type, void *source, void *dest);
+
+/* compares if data1 is equal to data2. type is a valid CustomData type
+ * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
+ * the data, if it exists, otherwise memcmp is used.*/
+int CustomData_data_equals(int type, void *data1, void *data2);
+void CustomData_data_initminmax(int type, void *min, void *max);
+void CustomData_data_dominmax(int type, void *data, void *min, void *max);
+void CustomData_data_multiply(int type, void *data, float fac);
+void CustomData_data_add(int type, void *data1, void *data2);
+
/* initialises a CustomData object with the same layer setup as source.
* mask is a bitfield where (mask & (1 << (layer type))) indicates
* if a layer should be copied or not. alloctype must be one of the above. */
@@ -69,6 +92,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)
*/
@@ -133,12 +162,13 @@ void CustomData_set_only_copy(const struct CustomData *data,
void CustomData_copy_data(const struct CustomData *source,
struct CustomData *dest, int source_index,
int dest_index, int count);
+void CustomData_copy_elements(int type, void *source, void *dest, int count);
void CustomData_em_copy_data(const struct CustomData *source,
struct CustomData *dest, void *src_block,
void **dest_block);
void CustomData_bmesh_copy_data(const struct CustomData *source,
- struct CustomData *dest,void *src_block,
- void **dest_block);
+ struct CustomData *dest, void *src_block,
+ void **dest_block);
/* frees data in a CustomData object
* return 1 on success, 0 on failure
@@ -179,11 +209,16 @@ 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);
void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n);
+/* gets the layer at physical index n, with no type checking.
+ */
+void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
+
/* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type
*/
@@ -191,7 +226,6 @@ void *CustomData_get_layer(const struct CustomData *data, int type);
void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
void *CustomData_get_layer_named(const struct CustomData *data, int type,
char *name);
-
int CustomData_get_layer_index(const struct CustomData *data, int type);
int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name);
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
@@ -219,6 +253,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type,
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n,
void *source);
+/*sets the data of the block at physical layer n. no real type checking
+ *is performed.
+ */
+void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n,
+ void *source);
/* set the pointer of to the first layer of type. the old data is not freed.
* returns the value of ptr if the layer is found, NULL otherwise
@@ -275,7 +314,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 d2f5e0faa0f..249da2478b7 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,12 +55,30 @@ 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);
+
+/*
+ this function recreates a tesselation.
+ returns number of tesselation faces.
+ */
+int mesh_recalcTesselation(struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, struct MVert *mvert, int totface,
+ int totloop, int totpoly);
+
+/*calculates a face normal.*/
+void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, float *no);
void unlink_mesh(struct Mesh *me);
-void free_mesh(struct Mesh *me);
+void free_mesh(struct Mesh *me, int unlink);
struct Mesh *add_mesh(char *name);
struct Mesh *copy_mesh(struct Mesh *me);
void mesh_update_customdata_pointers(struct Mesh *me);
+
+/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
+ mloopcol and mcol) have the same relative active/render/clone/mask indices.*/
+void mesh_update_linked_customdata(struct Mesh *me);
+
void make_local_tface(struct Mesh *me);
void make_local_mesh(struct Mesh *me);
void boundbox_mesh(struct Mesh *me, float *loc, float *size);
@@ -136,8 +155,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 9957ced9555..8a3c8c64575 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -44,6 +44,7 @@ struct ListBase;
struct LinkNode;
struct bArmature;
struct ModifierData;
+struct BMEditMesh;
typedef enum {
/* Should not be used, only for None modifier type */
@@ -138,13 +139,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 *********************/
@@ -182,7 +183,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 a331479cad1..d20a00cbfff 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -42,7 +42,8 @@ typedef struct MultiresSubsurf {
/* MultiresDM */
struct Object *MultiresDM_get_object(struct DerivedMesh *dm);
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..daad8665d1a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -0,0 +1,58 @@
+#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.
+*/
+
+/*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->edit_bmesh stores a pointer to this structure.*/
+typedef struct BMEditMesh {
+ struct BMesh *bm;
+
+ /*this is for undoing failed operations*/
+ struct BMEditMesh *emcopy;
+ int emcopyusers;
+
+ /*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 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);
+void BMEdit_UpdateLinkedCustomData(BMEditMesh *em);
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index c0ed8430177..1bf581b9435 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -114,6 +114,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 VECSUBFAC(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);}
@@ -201,54 +203,14 @@
#define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i))
#define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i))
-/*little 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
+/*little macro so inline keyword works*/
+#if defined(_MSC_VER)
+#define BM_INLINE static __forceinline
+#else
+#define BM_INLINE static inline __attribute((always_inline))
+#endif
-/*set the count of the array*/
-#define V_SETCOUNT(vec, count) _##vec##_count = (count)
+#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;}
#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 63631ddc40f..43e50bb4f1f 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 += ' #/intern/smoke/extern'
incs += ' #/intern/audaspace/intern'
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/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c
index 32065ea5151..15ef809158b 100644
--- a/source/blender/blenkernel/intern/BME_tools.c
+++ b/source/blender/blenkernel/intern/BME_tools.c
@@ -44,6 +44,7 @@
#include "BKE_bmesh.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
/*split this all into a seperate bevel.c file in src*/
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index cee032f364e..a3569298fde 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -31,7 +31,7 @@ typedef struct _EHash {
int numEntries, curSize, curSizeIdx;
CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator;
+ CCAllocHDL allocator;
} EHash;
#define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
@@ -39,7 +39,7 @@ typedef struct _EHash {
#define EHASH_hash(eh, item) (((uintptr_t) (item))%((unsigned int) (eh)->curSize))
-static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
+static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCAllocHDL allocator) {
EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh));
eh->allocatorIFC = *allocatorIFC;
eh->allocator = allocator;
@@ -175,13 +175,13 @@ static int _ehashIterator_isStopped(EHashIterator *ehi) {
/***/
-static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) {
+static void *_stdAllocator_alloc(CCAllocHDL a, int numBytes) {
return malloc(numBytes);
}
-static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
+static void *_stdAllocator_realloc(CCAllocHDL a, void *ptr, int newSize, int oldSize) {
return realloc(ptr, newSize);
}
-static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) {
+static void _stdAllocator_free(CCAllocHDL a, void *ptr) {
free(ptr);
}
@@ -218,7 +218,7 @@ static int VertDataEqual(float *a, float *b) {
#define NormAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; }
-static int _edge_isBoundary(CCGEdge *e);
+static int _edge_isBoundary(CCEdge *e);
/***/
@@ -229,53 +229,53 @@ enum {
} VertFlags;
enum {
Edge_eEffected= (1<<0),
-} CCGEdgeFlags;
+} CCEdgeFlags;
enum {
Face_eEffected= (1<<0),
} FaceFlags;
-struct _CCGVert {
- CCGVert *next; /* EHData.next */
- CCGVertHDL vHDL; /* EHData.key */
+struct _CCVert {
+ CCVert *next; /* EHData.next */
+ CCVertHDL vHDL; /* EHData.key */
short numEdges, numFaces, flags, pad;
- CCGEdge **edges;
- CCGFace **faces;
+ CCEdge **edges;
+ CCFace **faces;
// byte *levelData;
// byte *userData;
};
#define VERT_getLevelData(v) ((byte*) &(v)[1])
-struct _CCGEdge {
- CCGEdge *next; /* EHData.next */
- CCGEdgeHDL eHDL; /* EHData.key */
+struct _CCEdge {
+ CCEdge *next; /* EHData.next */
+ CCEdgeHDL eHDL; /* EHData.key */
short numFaces, flags;
float crease;
- CCGVert *v0,*v1;
- CCGFace **faces;
+ CCVert *v0,*v1;
+ CCFace **faces;
// byte *levelData;
// byte *userData;
};
#define EDGE_getLevelData(e) ((byte*) &(e)[1])
-struct _CCGFace {
- CCGFace *next; /* EHData.next */
- CCGFaceHDL fHDL; /* EHData.key */
+struct _CCFace {
+ CCFace *next; /* EHData.next */
+ CCFaceHDL fHDL; /* EHData.key */
short numVerts, flags, pad1, pad2;
-// CCGVert **verts;
-// CCGEdge **edges;
+// CCVert **verts;
+// CCEdge **edges;
// byte *centerData;
// byte **gridData;
// byte *userData;
};
-#define FACE_getVerts(f) ((CCGVert**) &(f)[1])
-#define FACE_getEdges(f) ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts]))
+#define FACE_getVerts(f) ((CCVert**) &(f)[1])
+#define FACE_getEdges(f) ((CCEdge**) &(FACE_getVerts(f)[(f)->numVerts]))
#define FACE_getCenterData(f) ((byte*) &(FACE_getEdges(f)[(f)->numVerts]))
typedef enum {
@@ -286,15 +286,15 @@ typedef enum {
eSyncState_Partial,
} SyncState;
-struct _CCGSubSurf {
- EHash *vMap; /* map of CCGVertHDL -> Vert */
- EHash *eMap; /* map of CCGEdgeHDL -> Edge */
- EHash *fMap; /* map of CCGFaceHDL -> Face */
+struct _CSubSurf {
+ EHash *vMap; /* map of CCVertHDL -> Vert */
+ EHash *eMap; /* map of CCEdgeHDL -> Edge */
+ EHash *fMap; /* map of CCFaceHDL -> Face */
CCGMeshIFC meshIFC;
CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator;
+ CCAllocHDL allocator;
int subdivLevels;
int numGrids;
@@ -320,8 +320,8 @@ struct _CCGSubSurf {
EHash *oldVMap, *oldEMap, *oldFMap;
int lenTempArrays;
- CCGVert **tempVerts;
- CCGEdge **tempEdges;
+ CCVert **tempVerts;
+ CCEdge **tempEdges;
};
#define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
@@ -330,8 +330,8 @@ struct _CCGSubSurf {
/***/
-static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss) {
- CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize);
+static CCVert *_vert_new(CCVertHDL vHDL, CSubSurf *ss) {
+ CCVert *v = CCGSUBSURF_alloc(ss, sizeof(CCVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize);
byte *userData;
v->vHDL = vHDL;
@@ -340,13 +340,13 @@ static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss) {
v->numEdges = v->numFaces = 0;
v->flags = 0;
- userData = ccgSubSurf_getVertUserData(ss, v);
+ userData = CCS_getVertUserData(ss, v);
memset(userData, 0, ss->meshIFC.vertUserSize);
if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
return v;
}
-static void _vert_remEdge(CCGVert *v, CCGEdge *e) {
+static void _vert_remEdge(CCVert *v, CCEdge *e) {
int i;
for (i=0; i<v->numEdges; i++) {
if (v->edges[i]==e) {
@@ -355,7 +355,7 @@ static void _vert_remEdge(CCGVert *v, CCGEdge *e) {
}
}
}
-static void _vert_remFace(CCGVert *v, CCGFace *f) {
+static void _vert_remFace(CCVert *v, CCFace *f) {
int i;
for (i=0; i<v->numFaces; i++) {
if (v->faces[i]==f) {
@@ -364,25 +364,25 @@ static void _vert_remFace(CCGVert *v, CCGFace *f) {
}
}
}
-static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
+static void _vert_addEdge(CCVert *v, CCEdge *e, CSubSurf *ss) {
v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges));
v->edges[v->numEdges++] = e;
}
-static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
+static void _vert_addFace(CCVert *v, CCFace *f, CSubSurf *ss) {
v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces));
v->faces[v->numFaces++] = f;
}
-static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
+static CCEdge *_vert_findEdgeTo(CCVert *v, CCVert *vQ) {
int i;
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
+ CCEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
if ( (e->v0==v && e->v1==vQ) ||
(e->v1==v && e->v0==vQ))
return e;
}
return 0;
}
-static int _vert_isBoundary(CCGVert *v) {
+static int _vert_isBoundary(CCVert *v) {
int i;
for (i=0; i<v->numEdges; i++)
if (_edge_isBoundary(v->edges[i]))
@@ -390,27 +390,27 @@ static int _vert_isBoundary(CCGVert *v) {
return 0;
}
-static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) {
+static void *_vert_getCo(CCVert *v, int lvl, int dataSize) {
return &VERT_getLevelData(v)[lvl*dataSize];
}
-static float *_vert_getNo(CCGVert *v, int lvl, int dataSize, int normalDataOffset) {
+static float *_vert_getNo(CCVert *v, int lvl, int dataSize, int normalDataOffset) {
return (float*) &VERT_getLevelData(v)[lvl*dataSize + normalDataOffset];
}
-static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
+static void _vert_free(CCVert *v, CSubSurf *ss) {
CCGSUBSURF_free(ss, v->edges);
CCGSUBSURF_free(ss, v->faces);
CCGSUBSURF_free(ss, v);
}
-static int VERT_seam(CCGVert *v) {
+static int VERT_seam(CCVert *v) {
return ((v->flags & Vert_eSeam) != 0);
}
/***/
-static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, CCGSubSurf *ss) {
- CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize);
+static CCEdge *_edge_new(CCEdgeHDL eHDL, CCVert *v0, CCVert *v1, float crease, CSubSurf *ss) {
+ CCEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize);
byte *userData;
e->eHDL = eHDL;
@@ -423,13 +423,13 @@ static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float creas
_vert_addEdge(v0, e, ss);
_vert_addEdge(v1, e, ss);
- userData = ccgSubSurf_getEdgeUserData(ss, e);
+ userData = CCS_getEdgeUserData(ss, e);
memset(userData, 0, ss->meshIFC.edgeUserSize);
if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
return e;
}
-static void _edge_remFace(CCGEdge *e, CCGFace *f) {
+static void _edge_remFace(CCEdge *e, CCFace *f) {
int i;
for (i=0; i<e->numFaces; i++) {
if (e->faces[i]==f) {
@@ -438,15 +438,15 @@ static void _edge_remFace(CCGEdge *e, CCGFace *f) {
}
}
}
-static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
+static void _edge_addFace(CCEdge *e, CCFace *f, CSubSurf *ss) {
e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces));
e->faces[e->numFaces++] = f;
}
-static int _edge_isBoundary(CCGEdge *e) {
+static int _edge_isBoundary(CCEdge *e) {
return e->numFaces<2;
}
-static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) {
+static CCVert *_edge_getOtherVert(CCEdge *e, CCVert *vQ) {
if (vQ==e->v0) {
return e->v1;
} else {
@@ -454,17 +454,17 @@ static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) {
}
}
-static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) {
+static void *_edge_getCo(CCEdge *e, int lvl, int x, int dataSize) {
int levelBase = lvl + (1<<lvl) - 1;
return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
}
#if 0
-static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
+static float *_edge_getNo(CCEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
int levelBase = lvl + (1<<lvl) - 1;
return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset];
}
#endif
-static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) {
+static void *_edge_getCoVert(CCEdge *e, CCVert *v, int lvl, int x, int dataSize) {
int levelBase = lvl + (1<<lvl) - 1;
if (v==e->v0) {
return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
@@ -473,11 +473,11 @@ static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSiz
}
}
-static void _edge_free(CCGEdge *e, CCGSubSurf *ss) {
+static void _edge_free(CCEdge *e, CSubSurf *ss) {
CCGSUBSURF_free(ss, e->faces);
CCGSUBSURF_free(ss, e);
}
-static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
+static void _edge_unlinkMarkAndFree(CCEdge *e, CSubSurf *ss) {
_vert_remEdge(e->v0, e);
_vert_remEdge(e->v1, e);
e->v0->flags |= Vert_eEffected;
@@ -485,7 +485,7 @@ static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
_edge_free(e, ss);
}
-static float EDGE_getSharpness(CCGEdge *e, int lvl) {
+static float EDGE_getSharpness(CCEdge *e, int lvl) {
if (!lvl)
return e->crease;
else if (!e->crease)
@@ -496,9 +496,9 @@ static float EDGE_getSharpness(CCGEdge *e, int lvl) {
return e->crease - lvl;
}
-static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, CCGSubSurf *ss) {
+static CCFace *_face_new(CCFaceHDL fHDL, CCVert **verts, CCEdge **edges, int numVerts, CSubSurf *ss) {
int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
- CCGFace *f = CCGSUBSURF_alloc(ss, sizeof(CCGFace) + sizeof(CCGVert*)*numVerts + sizeof(CCGEdge*)*numVerts + ss->meshIFC.vertDataSize *(1 + numVerts*maxGridSize + numVerts*maxGridSize*maxGridSize) + ss->meshIFC.faceUserSize);
+ CCFace *f = CCGSUBSURF_alloc(ss, sizeof(CCFace) + sizeof(CCVert*)*numVerts + sizeof(CCEdge*)*numVerts + ss->meshIFC.vertDataSize *(1 + numVerts*maxGridSize + numVerts*maxGridSize*maxGridSize) + ss->meshIFC.faceUserSize);
byte *userData;
int i;
@@ -513,39 +513,39 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int
_edge_addFace(edges[i], f, ss);
}
- userData = ccgSubSurf_getFaceUserData(ss, f);
+ userData = CCS_getFaceUserData(ss, f);
memset(userData, 0, ss->meshIFC.faceUserSize);
if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
return f;
}
-static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
+static void *_face_getIECo(CCFace *f, int lvl, int S, int x, int levels, int dataSize) {
int maxGridSize = 1 + (1<<(levels-1));
int spacing = 1<<(levels-lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
return &gridBase[dataSize*x*spacing];
}
-static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
+static void *_face_getIFCo(CCFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
int maxGridSize = 1 + (1<<(levels-1));
int spacing = 1<<(levels-lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
}
-static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
+static float *_face_getIFNo(CCFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
int maxGridSize = 1 + (1<<(levels-1));
int spacing = 1<<(levels-lvl);
byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset];
}
-static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
+static int _face_getVertIndex(CCFace *f, CCVert *v) {
int i;
for (i=0; i<f->numVerts; i++)
if (FACE_getVerts(f)[i]==v)
return i;
return -1;
}
-static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
+static void *_face_getIFCoEdge(CCFace *f, CCEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
int maxGridSize = 1 + (1<<(levels-1));
int spacing = 1<<(levels-lvl);
int S, x, y, cx, cy;
@@ -575,10 +575,10 @@ static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY,
}
return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize);
}
-static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
+static float *_face_getIFNoEdge(CCFace *f, CCEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
}
-void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
+void _face_calcIFNo(CCFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize);
float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize);
float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize);
@@ -604,10 +604,10 @@ void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int lev
}
}
-static void _face_free(CCGFace *f, CCGSubSurf *ss) {
+static void _face_free(CCFace *f, CSubSurf *ss) {
CCGSUBSURF_free(ss, f);
}
-static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
+static void _face_unlinkMarkAndFree(CCFace *f, CSubSurf *ss) {
int j;
for (j=0; j<f->numVerts; j++) {
_vert_remFace(FACE_getVerts(f)[j], f);
@@ -619,7 +619,7 @@ static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
/***/
-CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
+CSubSurf *CCS_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCAllocHDL allocator) {
if (!allocatorIFC) {
allocatorIFC = _getStandardAllocatorIFC();
allocator = NULL;
@@ -628,7 +628,7 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
if (subdivLevels<1) {
return NULL;
} else {
- CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
+ CSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
ss->allocatorIFC = *allocatorIFC;
ss->allocator = allocator;
@@ -667,9 +667,9 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
}
}
-void ccgSubSurf_free(CCGSubSurf *ss) {
+void CCS_free(CSubSurf *ss) {
CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
- CCGAllocatorHDL allocator = ss->allocator;
+ CCAllocHDL allocator = ss->allocator;
if (ss->syncState) {
_ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
@@ -695,7 +695,7 @@ void ccgSubSurf_free(CCGSubSurf *ss) {
}
}
-CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) {
+CCGError CCS_setAllowEdgeCreation(CSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) {
if (ss->defaultEdgeUserData) {
CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
}
@@ -712,7 +712,7 @@ CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation,
return eCCGError_None;
}
-void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) {
+void CCS_getAllowEdgeCreation(CSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) {
if (allowEdgeCreation_r) *allowEdgeCreation_r = ss->allowEdgeCreation;
if (ss->allowEdgeCreation) {
if (defaultCreaseValue_r) *defaultCreaseValue_r = ss->defaultCreaseValue;
@@ -720,7 +720,7 @@ void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, f
}
}
-CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) {
+CCGError CCS_setSubdivisionLevels(CSubSurf *ss, int subdivisionLevels) {
if (subdivisionLevels<=0) {
return eCCGError_InvalidValue;
} else if (subdivisionLevels!=ss->subdivLevels) {
@@ -737,7 +737,7 @@ CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels)
return eCCGError_None;
}
-void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r)
+void CCS_getUseAgeCounts(CSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r)
{
*useAgeCounts_r = ss->useAgeCounts;
@@ -746,7 +746,7 @@ void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUs
if (faceUserOffset_r) *faceUserOffset_r = ss->faceUserAgeOffset;
}
-CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
+CCGError CCS_setUseAgeCounts(CSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
if (useAgeCounts) {
if ( (vertUserOffset+4>ss->meshIFC.vertUserSize) ||
(edgeUserOffset+4>ss->meshIFC.edgeUserSize) ||
@@ -766,7 +766,7 @@ CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUs
return eCCGError_None;
}
-CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) {
+CCGError CCS_setCalcVertexNormals(CSubSurf *ss, int useVertNormals, int normalDataOffset) {
if (useVertNormals) {
if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) {
return eCCGError_InvalidValue;
@@ -784,7 +784,7 @@ CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int
/***/
-CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
+CCGError CCS_initFullSync(CSubSurf *ss) {
if (ss->syncState!=eSyncState_None) {
return eCCGError_InvalidSyncState;
}
@@ -810,7 +810,7 @@ CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
return eCCGError_None;
}
-CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
+CCGError CCS_initPartialSync(CSubSurf *ss) {
if (ss->syncState!=eSyncState_None) {
return eCCGError_InvalidSyncState;
}
@@ -822,12 +822,12 @@ CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
return eCCGError_None;
}
-CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
+CCGError CCS_syncVertDel(CSubSurf *ss, CCVertHDL vHDL) {
if (ss->syncState!=eSyncState_Partial) {
return eCCGError_InvalidSyncState;
} else {
void **prevp;
- CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
+ CCVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
if (!v || v->numFaces || v->numEdges) {
return eCCGError_InvalidValue;
@@ -840,12 +840,12 @@ CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
return eCCGError_None;
}
-CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
+CCGError CCS_syncEdgeDel(CSubSurf *ss, CCEdgeHDL eHDL) {
if (ss->syncState!=eSyncState_Partial) {
return eCCGError_InvalidSyncState;
} else {
void **prevp;
- CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
+ CCEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
if (!e || e->numFaces) {
return eCCGError_InvalidValue;
@@ -858,12 +858,12 @@ CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
return eCCGError_None;
}
-CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
+CCGError CCS_syncFaceDel(CSubSurf *ss, CCFaceHDL fHDL) {
if (ss->syncState!=eSyncState_Partial) {
return eCCGError_InvalidSyncState;
} else {
void **prevp;
- CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
+ CCFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
if (!f) {
return eCCGError_InvalidValue;
@@ -876,9 +876,9 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
return eCCGError_None;
}
-CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
+CCGError CCS_syncVert(CSubSurf *ss, CCVertHDL vHDL, void *vertData, int seam, CCVert **v_r) {
void **prevp;
- CCGVert *v = NULL;
+ CCVert *v = NULL;
short seamflag = (seam)? Vert_eSeam: 0;
if (ss->syncState==eSyncState_Partial) {
@@ -895,12 +895,12 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, in
v->flags = Vert_eEffected|seamflag;
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
e->v0->flags |= Vert_eEffected;
e->v1->flags |= Vert_eEffected;
}
for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
+ CCFace *f = v->faces[i];
for (j=0; j<f->numVerts; j++) {
FACE_getVerts(f)[j]->flags |= Vert_eEffected;
}
@@ -933,15 +933,15 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, in
return eCCGError_None;
}
-CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r) {
+CCGError CCS_syncEdge(CSubSurf *ss, CCEdgeHDL eHDL, CCVertHDL e_vHDL0, CCVertHDL e_vHDL1, float crease, CCEdge **e_r) {
void **prevp;
- CCGEdge *e = NULL, *eNew;
+ CCEdge *e = NULL, *eNew;
if (ss->syncState==eSyncState_Partial) {
e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) {
- CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
- CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
+ CCVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
+ CCVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
eNew = _edge_new(eHDL, v0, v1, crease, ss);
@@ -966,8 +966,8 @@ CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0
e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) {
- CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
- CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
+ CCVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
+ CCVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
e = _edge_new(eHDL, v0, v1, crease, ss);
_ehash_insert(ss->eMap, (EHEntry*) e);
e->v0->flags |= Vert_eEffected;
@@ -987,9 +987,9 @@ CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0
return eCCGError_None;
}
-CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r) {
+CCGError CCS_syncFace(CSubSurf *ss, CCFaceHDL fHDL, int numVerts, CCVertHDL *vHDLs, CCFace **f_r) {
void **prevp;
- CCGFace *f = NULL, *fNew;
+ CCFace *f = NULL, *fNew;
int j, k, topologyChanged = 0;
if (numVerts>ss->lenTempArrays) {
@@ -1054,12 +1054,12 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
if (!ss->tempEdges[k]) {
if (ss->allowEdgeCreation) {
- CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], ss->defaultCreaseValue, ss);
+ CCEdge *e = ss->tempEdges[k] = _edge_new((CCEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], ss->defaultCreaseValue, ss);
_ehash_insert(ss->eMap, (EHEntry*) e);
e->v0->flags |= Vert_eEffected;
e->v1->flags |= Vert_eEffected;
if (ss->meshIFC.edgeUserSize) {
- memcpy(ccgSubSurf_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
+ memcpy(CCS_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
}
} else {
return eCCGError_InvalidValue;
@@ -1101,12 +1101,12 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV
return eCCGError_None;
}
-static void ccgSubSurf__sync(CCGSubSurf *ss);
-CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
+static void CCS__sync(CSubSurf *ss);
+CCGError CCS_processSync(CSubSurf *ss) {
if (ss->syncState==eSyncState_Partial) {
ss->syncState = eSyncState_None;
- ccgSubSurf__sync(ss);
+ CCS__sync(ss);
} else if (ss->syncState) {
_ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
_ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
@@ -1122,7 +1122,7 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
ss->syncState = eSyncState_None;
- ccgSubSurf__sync(ss);
+ CCS__sync(ss);
} else {
return eCCGError_InvalidSyncState;
}
@@ -1130,10 +1130,10 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
return eCCGError_None;
}
-static void ccgSubSurf__sync(CCGSubSurf *ss) {
- CCGVert **effectedV;
- CCGEdge **effectedE;
- CCGFace **effectedF;
+static void CCS__sync(CSubSurf *ss) {
+ CCVert **effectedV;
+ CCEdge **effectedE;
+ CCFace **effectedF;
int numEffectedV, numEffectedE, numEffectedF;
int subdivLevels = ss->subdivLevels;
int vertDataSize = ss->meshIFC.vertDataSize;
@@ -1148,13 +1148,13 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
effectedF = CCGSUBSURF_alloc(ss, sizeof(*effectedF)*ss->fMap->numEntries);
numEffectedV = numEffectedE = numEffectedF = 0;
for (i=0; i<ss->vMap->curSize; i++) {
- CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
+ CCVert *v = (CCVert*) ss->vMap->buckets[i];
for (; v; v = v->next) {
if (v->flags&Vert_eEffected) {
effectedV[numEffectedV++] = v;
for (j=0; j<v->numEdges; j++) {
- CCGEdge *e = v->edges[j];
+ CCEdge *e = v->edges[j];
if (!(e->flags&Edge_eEffected)) {
effectedE[numEffectedE++] = e;
e->flags |= Edge_eEffected;
@@ -1162,7 +1162,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (j=0; j<v->numFaces; j++) {
- CCGFace *f = v->faces[j];
+ CCFace *f = v->faces[j];
if (!(f->flags&Face_eEffected)) {
effectedF[numEffectedF++] = f;
f->flags |= Face_eEffected;
@@ -1180,7 +1180,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
nextLvl = curLvl+1;
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = effectedF[ptrIdx];
+ CCFace *f = effectedF[ptrIdx];
void *co = FACE_getCenterData(f);
VertDataZero(co);
for (i=0; i<f->numVerts; i++) {
@@ -1191,7 +1191,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
f->flags = 0;
}
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = effectedE[ptrIdx];
+ CCEdge *e = effectedE[ptrIdx];
void *co = EDGE_getCo(e, nextLvl, 1);
float sharpness = EDGE_getSharpness(e, curLvl);
@@ -1204,7 +1204,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataCopy(q, VERT_getCo(e->v0, curLvl));
VertDataAdd(q, VERT_getCo(e->v1, curLvl));
for (i=0; i<e->numFaces; i++) {
- CCGFace *f = e->faces[i];
+ CCFace *f = e->faces[i];
VertDataAdd(q, FACE_getCenterData(f));
numFaces++;
}
@@ -1223,7 +1223,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
// edge flags cleared later
}
for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = effectedV[ptrIdx];
+ CCVert *v = effectedV[ptrIdx];
void *co = VERT_getCo(v, curLvl);
void *nCo = VERT_getCo(v, nextLvl);
int sharpCount = 0, allSharp = 1;
@@ -1231,7 +1231,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
int seam = VERT_seam(v), seamEdges = 0;
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl);
if (seam && _edge_isBoundary(e))
@@ -1262,7 +1262,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataZero(r);
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
if (_edge_isBoundary(e)) {
VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
numBoundary++;
@@ -1277,14 +1277,14 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataZero(q);
for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
+ CCFace *f = v->faces[i];
VertDataAdd(q, FACE_getCenterData(f));
numFaces++;
}
VertDataMulN(q, 1.0f/numFaces);
VertDataZero(r);
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
numEdges++;
}
@@ -1307,16 +1307,16 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl);
if (seam) {
if (_edge_isBoundary(e)) {
- CCGVert *oV = _edge_getOtherVert(e, v);
+ CCVert *oV = _edge_getOtherVert(e, v);
VertDataAdd(q, VERT_getCo(oV, curLvl));
}
} else if (sharpness != 0.0) {
- CCGVert *oV = _edge_getOtherVert(e, v);
+ CCVert *oV = _edge_getOtherVert(e, v);
VertDataAdd(q, VERT_getCo(oV, curLvl));
}
}
@@ -1348,34 +1348,34 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
if (ss->useAgeCounts) {
for (i=0; i<numEffectedV; i++) {
- CCGVert *v = effectedV[i];
- byte *userData = ccgSubSurf_getVertUserData(ss, v);
+ CCVert *v = effectedV[i];
+ byte *userData = CCS_getVertUserData(ss, v);
*((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
}
for (i=0; i<numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
- byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
+ CCEdge *e = effectedE[i];
+ byte *userData = CCS_getEdgeUserData(ss, e);
*((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
}
for (i=0; i<numEffectedF; i++) {
- CCGFace *f = effectedF[i];
- byte *userData = ccgSubSurf_getFaceUserData(ss, f);
+ CCFace *f = effectedF[i];
+ byte *userData = CCS_getFaceUserData(ss, f);
*((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
}
}
for (i=0; i<numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
+ CCEdge *e = effectedE[i];
VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl));
}
for (i=0; i<numEffectedF; i++) {
- CCGFace *f = effectedF[i];
+ CCFace *f = effectedF[i];
for (S=0; S<f->numVerts; S++) {
- CCGEdge *e = FACE_getEdges(f)[S];
- CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
+ CCEdge *e = FACE_getEdges(f)[S];
+ CCEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
@@ -1393,7 +1393,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
nextLvl = curLvl+1;
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
/* interior face midpoints
* o old interior face points
@@ -1472,7 +1472,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
* o new interior face midpoints
*/
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ CCEdge *e = (CCEdge*) effectedE[ptrIdx];
float sharpness = EDGE_getSharpness(e, curLvl);
if (_edge_isBoundary(e) || sharpness>1.0) {
@@ -1498,7 +1498,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataAdd(q, co1);
for (i=0; i<e->numFaces; i++) {
- CCGFace *f = e->faces[i];
+ CCFace *f = e->faces[i];
VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
numFaces++;
}
@@ -1523,7 +1523,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
* o new interior face midpoints
*/
for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert*) effectedV[ptrIdx];
+ CCVert *v = (CCVert*) effectedV[ptrIdx];
void *co = VERT_getCo(v, curLvl);
void *nCo = VERT_getCo(v, nextLvl);
int sharpCount = 0, allSharp = 1;
@@ -1531,7 +1531,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
int seam = VERT_seam(v), seamEdges = 0;
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl);
if (seam && _edge_isBoundary(e))
@@ -1562,7 +1562,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataZero(r);
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
if (_edge_isBoundary(e)) {
VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
numBoundary++;
@@ -1579,14 +1579,14 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataZero(q);
for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
+ CCFace *f = v->faces[i];
VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
numFaces++;
}
VertDataMulN(q, 1.0f/numFaces);
VertDataZero(r);
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
numEdges++;
}
@@ -1609,7 +1609,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
+ CCEdge *e = v->edges[i];
float sharpness = EDGE_getSharpness(e, curLvl);
if (seam) {
@@ -1649,7 +1649,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
* o new interior face midpoints
*/
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ CCEdge *e = (CCEdge*) effectedE[ptrIdx];
float sharpness = EDGE_getSharpness(e, curLvl);
int sharpCount = 0;
float avgSharpness = 0.0;
@@ -1691,7 +1691,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
for (i=0; i<e->numFaces; i++) {
- CCGFace *f = e->faces[i];
+ CCFace *f = e->faces[i];
VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
@@ -1723,7 +1723,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
/* interior center point shift
* o old face center point (shifting)
@@ -1809,15 +1809,15 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
gridSize = 1 + (1<<((nextLvl)-1));
cornerIdx = gridSize-1;
for (i=0; i<numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
+ CCEdge *e = effectedE[i];
VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
}
for (i=0; i<numEffectedF; i++) {
- CCGFace *f = effectedF[i];
+ CCFace *f = effectedF[i];
for (S=0; S<f->numVerts; S++) {
- CCGEdge *e = FACE_getEdges(f)[S];
- CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
+ CCEdge *e = FACE_getEdges(f)[S];
+ CCEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
@@ -1846,7 +1846,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
int normalDataOffset = ss->normalDataOffset;
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
int S, x, y;
for (S=0; S<f->numVerts; S++) {
@@ -1866,7 +1866,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
int S, x, y;
float no[3];
@@ -1922,13 +1922,13 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
// XXX can I reduce the number of normalisations here?
for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert*) effectedV[ptrIdx];
+ CCVert *v = (CCVert*) effectedV[ptrIdx];
float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
NormZero(no);
for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
+ CCFace *f = v->faces[i];
NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
}
@@ -1944,19 +1944,19 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
+ CCFace *f = v->faces[i];
NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
}
}
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ CCEdge *e = (CCEdge*) effectedE[ptrIdx];
if (e->numFaces) {
- CCGFace *fLast = e->faces[e->numFaces-1];
+ CCFace *fLast = e->faces[e->numFaces-1];
int x;
for (i=0; i<e->numFaces-1; i++) {
- CCGFace *f = e->faces[i];
+ CCFace *f = e->faces[i];
for (x=1; x<edgeSize-1; x++) {
NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
@@ -1965,7 +1965,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (i=0; i<e->numFaces-1; i++) {
- CCGFace *f = e->faces[i];
+ CCFace *f = e->faces[i];
for (x=1; x<edgeSize-1; x++) {
NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
@@ -1975,7 +1975,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
}
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
int S;
for (S=0; S<f->numVerts; S++) {
@@ -1984,7 +1984,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
}
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ CCFace *f = (CCFace*) effectedF[ptrIdx];
int S, x, y;
for (S=0; S<f->numVerts; S++) {
@@ -2009,11 +2009,11 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
#undef FACE_getIFNo
for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = effectedV[ptrIdx];
+ CCVert *v = effectedV[ptrIdx];
v->flags = 0;
}
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = effectedE[ptrIdx];
+ CCEdge *e = effectedE[ptrIdx];
e->flags = 0;
}
@@ -2029,43 +2029,43 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
/*** External API accessor functions ***/
-int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
+int CCS_getNumVerts(CSubSurf *ss) {
return ss->vMap->numEntries;
}
-int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
+int CCS_getNumEdges(CSubSurf *ss) {
return ss->eMap->numEntries;
}
-int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
+int CCS_getNumFaces(CSubSurf *ss) {
return ss->fMap->numEntries;
}
-CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
- return (CCGVert*) _ehash_lookup(ss->vMap, v);
+CCVert *CCS_getVert(CSubSurf *ss, CCVertHDL v) {
+ return (CCVert*) _ehash_lookup(ss->vMap, v);
}
-CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
- return (CCGEdge*) _ehash_lookup(ss->eMap, e);
+CCEdge *CCS_getEdge(CSubSurf *ss, CCEdgeHDL e) {
+ return (CCEdge*) _ehash_lookup(ss->eMap, e);
}
-CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
- return (CCGFace*) _ehash_lookup(ss->fMap, f);
+CCFace *CCS_getFace(CSubSurf *ss, CCFaceHDL f) {
+ return (CCFace*) _ehash_lookup(ss->fMap, f);
}
-int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
+int CCS_getSubdivisionLevels(CSubSurf *ss) {
return ss->subdivLevels;
}
-int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) {
- return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
+int CCS_getEdgeSize(CSubSurf *ss) {
+ return CCS_getEdgeLevelSize(ss, ss->subdivLevels);
}
-int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) {
+int CCS_getEdgeLevelSize(CSubSurf *ss, int level) {
if (level<1 || level>ss->subdivLevels) {
return -1;
} else {
return 1 + (1<<level);
}
}
-int ccgSubSurf_getGridSize(CCGSubSurf *ss) {
- return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
+int CCS_getGridSize(CSubSurf *ss) {
+ return CCS_getGridLevelSize(ss, ss->subdivLevels);
}
-int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
+int CCS_getGridLevelSize(CSubSurf *ss, int level) {
if (level<1 || level>ss->subdivLevels) {
return -1;
} else {
@@ -2075,44 +2075,44 @@ int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
/* Vert accessors */
-CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v) {
+CCVertHDL CCS_getVertVertHandle(CCVert *v) {
return v->vHDL;
}
-int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) {
+int CCS_getVertAge(CSubSurf *ss, CCVert *v) {
if (ss->useAgeCounts) {
- byte *userData = ccgSubSurf_getVertUserData(ss, v);
+ byte *userData = CCS_getVertUserData(ss, v);
return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]);
} else {
return 0;
}
}
-void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) {
+void *CCS_getVertUserData(CSubSurf *ss, CCVert *v) {
return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1);
}
-int ccgSubSurf_getVertNumFaces(CCGVert *v) {
+int CCS_getVertNumFaces(CCVert *v) {
return v->numFaces;
}
-CCGFace *ccgSubSurf_getVertFace(CCGVert *v, int index) {
+CCFace *CCS_getVertFace(CCVert *v, int index) {
if (index<0 || index>=v->numFaces) {
return NULL;
} else {
return v->faces[index];
}
}
-int ccgSubSurf_getVertNumEdges(CCGVert *v) {
+int CCS_getVertNumEdges(CCVert *v) {
return v->numEdges;
}
-CCGEdge *ccgSubSurf_getVertEdge(CCGVert *v, int index) {
+CCEdge *CCS_getVertEdge(CCVert *v, int index) {
if (index<0 || index>=v->numEdges) {
return NULL;
} else {
return v->edges[index];
}
}
-void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) {
- return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
+void *CCS_getVertData(CSubSurf *ss, CCVert *v) {
+ return CCS_getVertLevelData(ss, v, ss->subdivLevels);
}
-void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
+void *CCS_getVertLevelData(CSubSurf *ss, CCVert *v, int level) {
if (level<0 || level>ss->subdivLevels) {
return NULL;
} else {
@@ -2122,88 +2122,88 @@ void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
/* Edge accessors */
-CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGEdge *e) {
+CCEdgeHDL CCS_getEdgeEdgeHandle(CCEdge *e) {
return e->eHDL;
}
-int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) {
+int CCS_getEdgeAge(CSubSurf *ss, CCEdge *e) {
if (ss->useAgeCounts) {
- byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
+ byte *userData = CCS_getEdgeUserData(ss, e);
return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]);
} else {
return 0;
}
}
-void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) {
+void *CCS_getEdgeUserData(CSubSurf *ss, CCEdge *e) {
return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1);
}
-int ccgSubSurf_getEdgeNumFaces(CCGEdge *e) {
+int CCS_getEdgeNumFaces(CCEdge *e) {
return e->numFaces;
}
-CCGFace *ccgSubSurf_getEdgeFace(CCGEdge *e, int index) {
+CCFace *CCS_getEdgeFace(CCEdge *e, int index) {
if (index<0 || index>=e->numFaces) {
return NULL;
} else {
return e->faces[index];
}
}
-CCGVert *ccgSubSurf_getEdgeVert0(CCGEdge *e) {
+CCVert *CCS_getEdgeVert0(CCEdge *e) {
return e->v0;
}
-CCGVert *ccgSubSurf_getEdgeVert1(CCGEdge *e) {
+CCVert *CCS_getEdgeVert1(CCEdge *e) {
return e->v1;
}
-void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) {
- return ccgSubSurf_getEdgeData(ss, e, 0);
+void *CCS_getEdgeDataArray(CSubSurf *ss, CCEdge *e) {
+ return CCS_getEdgeData(ss, e, 0);
}
-void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) {
- return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
+void *CCS_getEdgeData(CSubSurf *ss, CCEdge *e, int x) {
+ return CCS_getEdgeLevelData(ss, e, x, ss->subdivLevels);
}
-void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) {
+void *CCS_getEdgeLevelData(CSubSurf *ss, CCEdge *e, int x, int level) {
if (level<0 || level>ss->subdivLevels) {
return NULL;
} else {
return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
}
}
-float ccgSubSurf_getEdgeCrease(CCGEdge *e) {
+float CCS_getEdgeCrease(CCEdge *e) {
return e->crease;
}
/* Face accessors */
-CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) {
+CCFaceHDL CCS_getFaceFaceHandle(CSubSurf *ss, CCFace *f) {
return f->fHDL;
}
-int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
+int CCS_getFaceAge(CSubSurf *ss, CCFace *f) {
if (ss->useAgeCounts) {
- byte *userData = ccgSubSurf_getFaceUserData(ss, f);
+ byte *userData = CCS_getFaceUserData(ss, f);
return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]);
} else {
return 0;
}
}
-void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
+void *CCS_getFaceUserData(CSubSurf *ss, CCFace *f) {
int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize);
}
-int ccgSubSurf_getFaceNumVerts(CCGFace *f) {
+int CCS_getFaceNumVerts(CCFace *f) {
return f->numVerts;
}
-CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) {
+CCVert *CCS_getFaceVert(CSubSurf *ss, CCFace *f, int index) {
if (index<0 || index>=f->numVerts) {
return NULL;
} else {
return FACE_getVerts(f)[index];
}
}
-CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) {
+CCEdge *CCS_getFaceEdge(CSubSurf *ss, CCFace *f, int index) {
if (index<0 || index>=f->numVerts) {
return NULL;
} else {
return FACE_getEdges(f)[index];
}
}
-int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e) {
+int CCS_getFaceEdgeIndex(CCFace *f, CCEdge *e) {
int i;
for (i=0; i<f->numVerts; i++)
@@ -2212,88 +2212,88 @@ int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e) {
return -1;
}
-void *ccgSubSurf_getFaceCenterData(CCGFace *f) {
+void *CCS_getFaceCenterData(CCFace *f) {
return FACE_getCenterData(f);
}
-void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
- return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
+void *CCS_getFaceGridEdgeDataArray(CSubSurf *ss, CCFace *f, int gridIndex) {
+ return CCS_getFaceGridEdgeData(ss, f, gridIndex, 0);
}
-void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) {
+void *CCS_getFaceGridEdgeData(CSubSurf *ss, CCFace *f, int gridIndex, int x) {
return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
}
-void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
- return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
+void *CCS_getFaceGridDataArray(CSubSurf *ss, CCFace *f, int gridIndex) {
+ return CCS_getFaceGridData(ss, f, gridIndex, 0, 0);
}
-void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) {
+void *CCS_getFaceGridData(CSubSurf *ss, CCFace *f, int gridIndex, int x, int y) {
return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
}
/*** External API iterator functions ***/
-CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) {
- return (CCGVertIterator*) _ehashIterator_new(ss->vMap);
+CCVertIterator *CCS_getVertIterator(CSubSurf *ss) {
+ return (CCVertIterator*) _ehashIterator_new(ss->vMap);
}
-CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) {
- return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap);
+CCEdgeIterator *CCS_getEdgeIterator(CSubSurf *ss) {
+ return (CCEdgeIterator*) _ehashIterator_new(ss->eMap);
}
-CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) {
- return (CCGFaceIterator*) _ehashIterator_new(ss->fMap);
+CCFaceIterator *CCS_getFaceIterator(CSubSurf *ss) {
+ return (CCFaceIterator*) _ehashIterator_new(ss->fMap);
}
-CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) {
- return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
+CCVert *CCVIter_getCurrent(CCVertIterator *vi) {
+ return (CCVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
}
-int ccgVertIterator_isStopped(CCGVertIterator *vi) {
+int CCVIter_isStopped(CCVertIterator *vi) {
return _ehashIterator_isStopped((EHashIterator*) vi);
}
-void ccgVertIterator_next(CCGVertIterator *vi) {
+void CCVIter_next(CCVertIterator *vi) {
_ehashIterator_next((EHashIterator*) vi);
}
-void ccgVertIterator_free(CCGVertIterator *vi) {
+void CCVIter_free(CCVertIterator *vi) {
_ehashIterator_free((EHashIterator*) vi);
}
-CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) {
- return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
+CCEdge *CCEIter_getCurrent(CCEdgeIterator *vi) {
+ return (CCEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
}
-int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) {
+int CCEIter_isStopped(CCEdgeIterator *vi) {
return _ehashIterator_isStopped((EHashIterator*) vi);
}
-void ccgEdgeIterator_next(CCGEdgeIterator *vi) {
+void CCEIter_next(CCEdgeIterator *vi) {
_ehashIterator_next((EHashIterator*) vi);
}
-void ccgEdgeIterator_free(CCGEdgeIterator *vi) {
+void CCEIter_free(CCEdgeIterator *vi) {
_ehashIterator_free((EHashIterator*) vi);
}
-CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) {
- return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
+CCFace *CCFIter_getCurrent(CCFaceIterator *vi) {
+ return (CCFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
}
-int ccgFaceIterator_isStopped(CCGFaceIterator *vi) {
+int CCFIter_isStopped(CCFaceIterator *vi) {
return _ehashIterator_isStopped((EHashIterator*) vi);
}
-void ccgFaceIterator_next(CCGFaceIterator *vi) {
+void CCFIter_next(CCFaceIterator *vi) {
_ehashIterator_next((EHashIterator*) vi);
}
-void ccgFaceIterator_free(CCGFaceIterator *vi) {
+void CCFIter_free(CCFaceIterator *vi) {
_ehashIterator_free((EHashIterator*) vi);
}
/*** Extern API final vert/edge/face interface ***/
-int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) {
+int CCS_getNumFinalVerts(CSubSurf *ss) {
int edgeSize = 1 + (1<<ss->subdivLevels);
int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
return numFinalVerts;
}
-int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) {
+int CCS_getNumFinalEdges(CSubSurf *ss) {
int edgeSize = 1 + (1<<ss->subdivLevels);
int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
return numFinalEdges;
}
-int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) {
+int CCS_getNumFinalFaces(CSubSurf *ss) {
int gridSize = 1 + (1<<(ss->subdivLevels-1));
int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
return numFinalFaces;
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index fbd0aecc0a5..2d4bef3d038 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -1,31 +1,30 @@
/* $Id$ */
typedef void* CCGMeshHDL;
-typedef void* CCGVertHDL;
-typedef void* CCGEdgeHDL;
-typedef void* CCGFaceHDL;
+typedef void* CCVertHDL;
+typedef void* CCEdgeHDL;
+typedef void* CCFaceHDL;
-typedef struct _CCGVert CCGVert;
-typedef struct _CCGEdge CCGEdge;
-typedef struct _CCGFace CCGFace;
+typedef struct _CCVert CCVert;
+typedef struct _CCEdge CCEdge;
+typedef struct _CCFace CCFace;
typedef struct _CCGMeshIFC CCGMeshIFC;
struct _CCGMeshIFC {
- int vertUserSize, edgeUserSize, faceUserSize;
-
- int vertDataSize;
+ int vertUserSize, edgeUserSize, faceUserSize;
+ int vertDataSize;
};
/***/
-typedef void* CCGAllocatorHDL;
+typedef void* CCAllocHDL;
typedef struct _CCGAllocatorIFC CCGAllocatorIFC;
struct _CCGAllocatorIFC {
- void* (*alloc) (CCGAllocatorHDL a, int numBytes);
- void* (*realloc) (CCGAllocatorHDL a, void *ptr, int newSize, int oldSize);
- void (*free) (CCGAllocatorHDL a, void *ptr);
- void (*release) (CCGAllocatorHDL a);
+ void* (*alloc) (CCAllocHDL a, int numBytes);
+ void* (*realloc) (CCAllocHDL a, void *ptr, int newSize, int oldSize);
+ void (*free) (CCAllocHDL a, void *ptr);
+ void (*release) (CCAllocHDL a);
};
/***/
@@ -39,114 +38,114 @@ typedef enum {
/***/
-typedef struct _CCGSubSurf CCGSubSurf;
+typedef struct _CSubSurf CSubSurf;
-CCGSubSurf* ccgSubSurf_new (CCGMeshIFC *ifc, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator);
-void ccgSubSurf_free (CCGSubSurf *ss);
+CSubSurf* CCS_new (CCGMeshIFC *ifc, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCAllocHDL allocator);
+void CCS_free (CSubSurf *ss);
-CCGError ccgSubSurf_sync (CCGSubSurf *ss);
+CCGError CCS_sync (CSubSurf *ss);
-CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
-CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
+CCGError CCS_initFullSync (CSubSurf *ss);
+CCGError CCS_initPartialSync (CSubSurf *ss);
-CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r);
-CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
-CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
+CCGError CCS_syncVert (CSubSurf *ss, CCVertHDL vHDL, void *vertData, int seam, CCVert **v_r);
+CCGError CCS_syncEdge (CSubSurf *ss, CCEdgeHDL eHDL, CCVertHDL e_vHDL0, CCVertHDL e_vHDL1, float crease, CCEdge **e_r);
+CCGError CCS_syncFace (CSubSurf *ss, CCFaceHDL fHDL, int numVerts, CCVertHDL *vHDLs, CCFace **f_r);
-CCGError ccgSubSurf_syncVertDel (CCGSubSurf *ss, CCGVertHDL vHDL);
-CCGError ccgSubSurf_syncEdgeDel (CCGSubSurf *ss, CCGEdgeHDL eHDL);
-CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL);
+CCGError CCS_syncVertDel (CSubSurf *ss, CCVertHDL vHDL);
+CCGError CCS_syncEdgeDel (CSubSurf *ss, CCEdgeHDL eHDL);
+CCGError CCS_syncFaceDel (CSubSurf *ss, CCFaceHDL fHDL);
-CCGError ccgSubSurf_processSync (CCGSubSurf *ss);
+CCGError CCS_processSync (CSubSurf *ss);
-CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels);
+CCGError CCS_setSubdivisionLevels(CSubSurf *ss, int subdivisionLevels);
-CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData);
-void ccgSubSurf_getAllowEdgeCreation (CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r);
+CCGError CCS_setAllowEdgeCreation(CSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData);
+void CCS_getAllowEdgeCreation(CSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r);
-void ccgSubSurf_getUseAgeCounts (CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r);
-CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
+void CCS_getUseAgeCounts (CSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r);
+CCGError CCS_setUseAgeCounts (CSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
-CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset);
+CCGError CCS_setCalcVertexNormals(CSubSurf *ss, int useVertNormals, int normalDataOffset);
/***/
-int ccgSubSurf_getNumVerts (CCGSubSurf *ss);
-int ccgSubSurf_getNumEdges (CCGSubSurf *ss);
-int ccgSubSurf_getNumFaces (CCGSubSurf *ss);
-
-int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss);
-int ccgSubSurf_getEdgeSize (CCGSubSurf *ss);
-int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level);
-int ccgSubSurf_getGridSize (CCGSubSurf *ss);
-int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level);
-
-CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v);
-CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v);
-int ccgSubSurf_getVertNumFaces (CCGVert *v);
-CCGFace* ccgSubSurf_getVertFace (CCGVert *v, int index);
-int ccgSubSurf_getVertNumEdges (CCGVert *v);
-CCGEdge* ccgSubSurf_getVertEdge (CCGVert *v, int index);
-
-int ccgSubSurf_getVertAge (CCGSubSurf *ss, CCGVert *v);
-void* ccgSubSurf_getVertUserData (CCGSubSurf *ss, CCGVert *v);
-void* ccgSubSurf_getVertData (CCGSubSurf *ss, CCGVert *v);
-void* ccgSubSurf_getVertLevelData (CCGSubSurf *ss, CCGVert *v, int level);
-
-CCGEdge* ccgSubSurf_getEdge (CCGSubSurf *ss, CCGEdgeHDL e);
-CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle (CCGEdge *e);
-int ccgSubSurf_getEdgeNumFaces (CCGEdge *e);
-CCGFace* ccgSubSurf_getEdgeFace (CCGEdge *e, int index);
-CCGVert* ccgSubSurf_getEdgeVert0 (CCGEdge *e);
-CCGVert* ccgSubSurf_getEdgeVert1 (CCGEdge *e);
-float ccgSubSurf_getEdgeCrease (CCGEdge *e);
-
-int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e);
-void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e);
-void* ccgSubSurf_getEdgeDataArray (CCGSubSurf *ss, CCGEdge *e);
-void* ccgSubSurf_getEdgeData (CCGSubSurf *ss, CCGEdge *e, int x);
-void* ccgSubSurf_getEdgeLevelData (CCGSubSurf *ss, CCGEdge *e, int x, int level);
-
-CCGFace* ccgSubSurf_getFace (CCGSubSurf *ss, CCGFaceHDL f);
-CCGFaceHDL ccgSubSurf_getFaceFaceHandle (CCGSubSurf *ss, CCGFace *f);
-int ccgSubSurf_getFaceNumVerts (CCGFace *f);
-CCGVert* ccgSubSurf_getFaceVert (CCGSubSurf *ss, CCGFace *f, int index);
-CCGEdge* ccgSubSurf_getFaceEdge (CCGSubSurf *ss, CCGFace *f, int index);
-int ccgSubSurf_getFaceEdgeIndex (CCGFace *f, CCGEdge *e);
-
-int ccgSubSurf_getFaceAge (CCGSubSurf *ss, CCGFace *f);
-void* ccgSubSurf_getFaceUserData (CCGSubSurf *ss, CCGFace *f);
-void* ccgSubSurf_getFaceCenterData (CCGFace *f);
-void* ccgSubSurf_getFaceGridEdgeDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
-void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x);
-void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex);
-void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y);
-
-int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss);
-int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss);
-int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss);
+int CCS_getNumVerts (CSubSurf *ss);
+int CCS_getNumEdges (CSubSurf *ss);
+int CCS_getNumFaces (CSubSurf *ss);
+
+int CCS_getSubdivisionLevels(CSubSurf *ss);
+int CCS_getEdgeSize (CSubSurf *ss);
+int CCS_getEdgeLevelSize (CSubSurf *ss, int level);
+int CCS_getGridSize (CSubSurf *ss);
+int CCS_getGridLevelSize (CSubSurf *ss, int level);
+
+CCVert* CCS_getVert (CSubSurf *ss, CCVertHDL v);
+CCVertHDL CCS_getVertVertHandle (CCVert *v);
+int CCS_getVertNumFaces (CCVert *v);
+CCFace* CCS_getVertFace (CCVert *v, int index);
+int CCS_getVertNumEdges (CCVert *v);
+CCEdge* CCS_getVertEdge (CCVert *v, int index);
+
+int CCS_getVertAge (CSubSurf *ss, CCVert *v);
+void* CCS_getVertUserData (CSubSurf *ss, CCVert *v);
+void* CCS_getVertData (CSubSurf *ss, CCVert *v);
+void* CCS_getVertLevelData (CSubSurf *ss, CCVert *v, int level);
+
+CCEdge* CCS_getEdge (CSubSurf *ss, CCEdgeHDL e);
+CCEdgeHDL CCS_getEdgeEdgeHandle (CCEdge *e);
+int CCS_getEdgeNumFaces (CCEdge *e);
+CCFace* CCS_getEdgeFace (CCEdge *e, int index);
+CCVert* CCS_getEdgeVert0 (CCEdge *e);
+CCVert* CCS_getEdgeVert1 (CCEdge *e);
+float CCS_getEdgeCrease (CCEdge *e);
+
+int CCS_getEdgeAge (CSubSurf *ss, CCEdge *e);
+void* CCS_getEdgeUserData (CSubSurf *ss, CCEdge *e);
+void* CCS_getEdgeDataArray (CSubSurf *ss, CCEdge *e);
+void* CCS_getEdgeData (CSubSurf *ss, CCEdge *e, int x);
+void* CCS_getEdgeLevelData (CSubSurf *ss, CCEdge *e, int x, int level);
+
+CCFace* CCS_getFace (CSubSurf *ss, CCFaceHDL f);
+CCFaceHDL CCS_getFaceFaceHandle (CSubSurf *ss, CCFace *f);
+int CCS_getFaceNumVerts (CCFace *f);
+CCVert* CCS_getFaceVert (CSubSurf *ss, CCFace *f, int index);
+CCEdge* CCS_getFaceEdge (CSubSurf *ss, CCFace *f, int index);
+int CCS_getFaceEdgeIndex (CCFace *f, CCEdge *e);
+
+int CCS_getFaceAge (CSubSurf *ss, CCFace *f);
+void* CCS_getFaceUserData (CSubSurf *ss, CCFace *f);
+void* CCS_getFaceCenterData (CCFace *f);
+void* CCS_getFaceGridEdgeDataArray (CSubSurf *ss, CCFace *f, int gridIndex);
+void* CCS_getFaceGridEdgeData (CSubSurf *ss, CCFace *f, int gridIndex, int x);
+void* CCS_getFaceGridDataArray (CSubSurf *ss, CCFace *f, int gridIndex);
+void* CCS_getFaceGridData (CSubSurf *ss, CCFace *f, int gridIndex, int x, int y);
+
+int CCS_getNumFinalVerts (CSubSurf *ss);
+int CCS_getNumFinalEdges (CSubSurf *ss);
+int CCS_getNumFinalFaces (CSubSurf *ss);
/***/
-typedef struct _CCGVertIterator CCGVertIterator;
-typedef struct _CCGEdgeIterator CCGEdgeIterator;
-typedef struct _CCGFaceIterator CCGFaceIterator;
+typedef struct _CCVertIterator CCVertIterator;
+typedef struct _CCEdgeIterator CCEdgeIterator;
+typedef struct _CCFaceIterator CCFaceIterator;
-CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss);
-CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss);
-CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss);
+CCVertIterator* CCS_getVertIterator (CSubSurf *ss);
+CCEdgeIterator* CCS_getEdgeIterator (CSubSurf *ss);
+CCFaceIterator* CCS_getFaceIterator (CSubSurf *ss);
-CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi);
-int ccgVertIterator_isStopped (CCGVertIterator *vi);
-void ccgVertIterator_next (CCGVertIterator *vi);
-void ccgVertIterator_free (CCGVertIterator *vi);
+CCVert* CCVIter_getCurrent (CCVertIterator *vi);
+int CCVIter_isStopped (CCVertIterator *vi);
+void CCVIter_next (CCVertIterator *vi);
+void CCVIter_free (CCVertIterator *vi);
-CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei);
-int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei);
-void ccgEdgeIterator_next (CCGEdgeIterator *ei);
-void ccgEdgeIterator_free (CCGEdgeIterator *ei);
+CCEdge* CCEIter_getCurrent (CCEdgeIterator *ei);
+int CCEIter_isStopped (CCEdgeIterator *ei);
+void CCEIter_next (CCEdgeIterator *ei);
+void CCEIter_free (CCEdgeIterator *ei);
-CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
-int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
-void ccgFaceIterator_next (CCGFaceIterator *fi);
-void ccgFaceIterator_free (CCGFaceIterator *fi);
+CCFace* CCFIter_getCurrent (CCFaceIterator *fi);
+int CCFIter_isStopped (CCFaceIterator *fi);
+void CCFIter_next (CCFaceIterator *fi);
+void CCFIter_free (CCFaceIterator *fi);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index a8ea83a45fc..91279597768 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -58,6 +58,7 @@
#include "BLI_editVert.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_array.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
@@ -77,6 +78,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
@@ -126,9 +128,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;
@@ -156,40 +158,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_tessface_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);
@@ -197,7 +232,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);
@@ -205,10 +241,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);
@@ -223,6 +265,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;
}
@@ -230,28 +274,139 @@ 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;
+ CustomData *oldata, *opdata;
+ MPoly *mpoly;
+ MLoop *mloop;
+ int p, l, i, j, lasttype;
+
+ oldata = dm->getLoopDataLayout(dm);
+ opdata = dm->getFaceDataLayout(dm);
+
+ CustomData_copy(oldata, ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, totloop);
+ CustomData_copy(opdata, pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, dm->getNumFaces(dm));
+
+ mloop = MEM_callocN(sizeof(MLoop)*totloop, "MLoop from dm_add_polys_from_iter");
+ CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
+ mpoly = MEM_callocN(sizeof(MPoly)*dm->getNumFaces(dm), "MPoly from dm_add_polys_from_iter");
+ CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, dm->getNumFaces(dm));
+
+ l = 0;
+ for (p=0; !iter->done; iter->step(iter), mpoly++, p++) {
+ mpoly->flag = iter->flags;
+ mpoly->loopstart = l;
+ mpoly->totloop = iter->len;
+ mpoly->mat_nr = iter->mat_nr;
+
+ j = 0;
+ lasttype = -1;
+ for (i=0; i<opdata->totlayer; i++) {
+ void *e1, *e2;
+
+ if (opdata->layers[i].type == lasttype)
+ j++;
+ else
+ j = 0;
+
+ if (opdata->layers[i].type == CD_MPOLY)
+ continue;
+
+ e1 = iter->getCDData(iter, opdata->layers[i].type, j);
+ e2 = (char*)CustomData_get_n(pdata, opdata->layers[i].type, p, j);
+
+ if (!e2)
+ continue;
+
+ CustomData_copy_elements(opdata->layers[i].type, e1, e2, 1);
+
+ lasttype = opdata->layers[i].type;
+ }
+
+ liter = iter->getLoopsIter(iter);
+ for (; !liter->done; liter->step(liter), mloop++, l++) {
+ mloop->v = liter->vindex;
+ mloop->e = liter->eindex;
+
+ j = 0;
+ lasttype = -1;
+ for (i=0; i<oldata->totlayer; i++) {
+ void *e1, *e2;
+
+ if (oldata->layers[i].type == CD_MLOOP)
+ continue;
+
+ if (oldata->layers[i].type == lasttype)
+ j++;
+ else
+ j = 0;
+
+ e1 = liter->getLoopCDData(liter, oldata->layers[i].type, j);
+ e2 = CustomData_get_n(ldata, oldata->layers[i].type, l, j);
+
+ if (!e2)
+ continue;
+
+ CustomData_copy_elements(oldata->layers[i].type, e1, e2, 1);
+ lasttype = oldata->layers[i].type;
+ }
+ }
+ }
+ iter->free(iter);
+}
+
+void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
+{
+ DMFaceIter *iter = source->newFaceIter(source);
+ DMLoopIter *liter;
+ int totloop = source->numLoopData;
+
+ dm_add_polys_from_iter(&target->loopData, &target->polyData, source, totloop);
+
+ target->numLoopData = totloop;
+ target->numPolyData = source->getNumFaces(source);
+}
+
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);
+
+ tmp.totloop = totloop;
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 */
@@ -260,13 +415,17 @@ 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.pdata, 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) {
@@ -294,11 +453,21 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
}
-void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
{
CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
}
+void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+ CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
+}
+
+void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+ CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
+}
+
void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
{
return CustomData_get(&dm->vertData, index, type);
@@ -324,11 +493,16 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
return CustomData_get_layer(&dm->edgeData, type);
}
-void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
{
return CustomData_get_layer(&dm->faceData, type);
}
+void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+{
+ return CustomData_get_layer(&dm->polyData, type);
+}
+
void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data)
{
CustomData_set(&dm->vertData, index, type, data);
@@ -358,13 +532,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);
@@ -375,11 +563,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)
@@ -397,7 +595,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)
@@ -406,13 +604,29 @@ 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])
{
DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -439,9 +653,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;
@@ -453,9 +667,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;
@@ -471,9 +685,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;
@@ -544,13 +758,13 @@ static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us
GPU_buffer_free( buffer, 0 );
}
}
-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;
@@ -584,9 +798,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;
@@ -635,9 +849,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];
@@ -653,9 +867,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;
@@ -834,12 +1048,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;
@@ -1002,21 +1216,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, int has_vcol, 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;
@@ -1162,15 +1376,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;
@@ -1186,28 +1400,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;
@@ -1225,7 +1439,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;
@@ -1260,7 +1474,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;
@@ -1302,7 +1516,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;
@@ -1320,7 +1534,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;
@@ -1348,7 +1562,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;
@@ -1373,16 +1587,16 @@ 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;
void *datalayer;
int index, offset, size;
- datalayer = DM_get_face_data_layer(dm, type);
+ datalayer = DM_get_tessface_data_layer(dm, type);
if(datalayer)
return datalayer;
@@ -1395,11 +1609,11 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
offset = em->fdata.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;
+ DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
+ 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);
+ data = datalayer = DM_get_tessface_data_layer(dm, type);
for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
emdata = CustomData_em_get(&em->fdata, efa->data, type);
memcpy(data, emdata, size);
@@ -1410,9 +1624,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) {
@@ -1431,21 +1645,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;
@@ -1555,37 +1770,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);
@@ -1599,7 +1813,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;
@@ -1615,7 +1829,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);
}
@@ -1700,15 +1914,21 @@ void vDM_ColorBand_store(ColorBand *coba)
static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
{
Mesh *me = ob->data;
- MFace *mf = me->mface;
+ MFace *mf = dm->getTessFaceArray(dm);
+ DMFaceIter *dfiter;
+ DMLoopIter *dliter;
ColorBand *coba= stored_cb; /* warning, not a local var */
unsigned char *wtcol;
- int i;
+ unsigned char(*wlcol)[4] = NULL;
+ BLI_array_declare(wlcol);
+ int i, totface=dm->getNumTessFaces(dm), totpoly=dm->getNumFaces, totloop;
+ int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX);
- wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
+ wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap");
- memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
- for (i=0; i<me->totface; i++, mf++) {
+ /*first add colors to the tesselation faces*/
+ memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4);
+ for (i=0; i<totface; i++, mf++) {
calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]);
@@ -1716,7 +1936,22 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]);
}
- CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
+ CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface);
+
+ /*now add to loops, so the data can be passed through the modifier stack*/
+ totloop = 0;
+ dfiter = dm->newFaceIter(dm);
+ for (; !dfiter->done; dfiter->step(dfiter)) {
+ dliter = dfiter->getLoopsIter(dfiter);
+ for (; !dliter->done; dliter->step(dliter), totloop++) {
+ BLI_array_growone(wlcol);
+ calc_weightpaint_vert_color(ob, coba, dliter->vindex, &wlcol[totloop]);
+ }
+ }
+
+ CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop);
+
+ dfiter->free(dfiter);
}
/* new value for useDeform -1 (hack for the gameengine):
@@ -1861,7 +2096,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* apply vertex coordinates or build a DerivedMesh as necessary */
if(dm) {
if(deformedVerts) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
dm->release(dm);
dm = tdm;
@@ -1903,7 +2138,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* add an origspace layer if needed */
if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
- DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
+ DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
ndm = mti->applyModifier(md, ob, dm, useRenderParams, !inputVertexCos);
@@ -1935,15 +2170,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
* DerivedMesh then we need to build one.
*/
if(dm && deformedVerts) {
- finaldm = CDDM_copy(dm);
+ finaldm = CDDM_copy(dm, 0);
dm->release(dm);
CDDM_apply_vert_coords(finaldm, deformedVerts);
CDDM_calc_normals(finaldm);
-
- if(dataMask & CD_MASK_WEIGHT_MCOL)
- add_weight_mcol_dm(ob, finaldm);
} else if(dm) {
finaldm = dm;
} else {
@@ -1977,21 +2209,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;
@@ -2005,7 +2240,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)
{
@@ -2020,7 +2255,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;
@@ -2037,7 +2272,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 */
@@ -2065,7 +2300,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);
}
}
@@ -2076,7 +2311,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
/* apply vertex coordinates or build a DerivedMesh as necessary */
if(dm) {
if(deformedVerts) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
if(!(cage_r && dm == *cage_r)) dm->release(dm);
dm = tdm;
@@ -2085,11 +2320,11 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
} else if(cage_r && dm == *cage_r) {
/* dm may be changed by this modifier, so we need to copy it
*/
- dm = CDDM_copy(dm);
+ dm = CDDM_copy(dm, 0);
}
} else {
- dm = CDDM_from_editmesh(em, ob->data);
+ dm = CDDM_from_BMEditMesh(em, ob->data);
if(deformedVerts) {
CDDM_apply_vert_coords(dm, deformedVerts);
@@ -2119,7 +2354,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
- DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
+ DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
ndm = mti->applyModifierEM(md, ob, em, dm);
@@ -2138,13 +2373,13 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
if(cage_r && i == cageIndex) {
if(dm && deformedVerts) {
- *cage_r = CDDM_copy(dm);
+ *cage_r = CDDM_copy(dm, 0);
CDDM_apply_vert_coords(*cage_r, deformedVerts);
} else if(dm) {
*cage_r = dm;
} else {
*cage_r =
- getEditMeshDerivedMesh(em, ob,
+ getEditDerivedBMesh(em, ob,
deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
@@ -2157,7 +2392,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
* then we need to build one.
*/
if(dm && deformedVerts) {
- *final_r = CDDM_copy(dm);
+ *final_r = CDDM_copy(dm, 0);
if(!(cage_r && dm == *cage_r)) dm->release(dm);
@@ -2168,7 +2403,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;
}
@@ -2238,7 +2473,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];
@@ -2257,7 +2492,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);
@@ -2272,10 +2507,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);
}
@@ -2365,7 +2600,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
@@ -2373,27 +2608,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);
}
@@ -2455,7 +2690,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;
@@ -2474,13 +2709,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++)
@@ -2495,7 +2730,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)
@@ -2527,11 +2762,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);
@@ -2540,8 +2775,8 @@ void DM_add_tangent_layer(DerivedMesh *dm)
}
/* create tangent layer */
- DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
- tangent= DM_get_face_data_layer(dm, CD_TANGENT);
+ DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+ tangent= DM_get_tessface_data_layer(dm, CD_TANGENT);
/* allocate some space */
arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index f119f52a47d..2007e35b131 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>
@@ -474,7 +475,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;
@@ -483,11 +484,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);
@@ -590,34 +590,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/armature.c b/source/blender/blenkernel/intern/armature.c
index 9894cc85784..afc5a972a65 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -38,6 +38,7 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 2df5b7c173c..9c1b93f2bf8 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -737,10 +737,18 @@ char *BKE_undo_menu_string(void)
/* saves quit.blend */
void BKE_undo_save_quit(void)
{
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ BLI_make_file_string("/", str, btempdir, "quit.blend");
+
+ BKE_undo_save(str);
+}
+
+void BKE_undo_save(char *fname)
+{
UndoElem *uel;
MemFileChunk *chunk;
int file;
- char str[FILE_MAXDIR+FILE_MAXFILE];
if( (U.uiflag & USER_GLOBALUNDO)==0) return;
@@ -753,9 +761,7 @@ void BKE_undo_save_quit(void)
/* no undo state to save */
if(undobase.first==undobase.last) return;
- BLI_make_file_string("/", str, btempdir, "quit.blend");
-
- file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
+ file = open(fname, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
if(file == -1) {
//XXX error("Unable to save %s, check you have permissions", str);
return;
@@ -769,7 +775,7 @@ void BKE_undo_save_quit(void)
close(file);
- if(chunk) ; //XXX error("Unable to save %s, internal error", str);
- else printf("Saved session recovery to %s\n", str);
+ if(chunk) ; //XXX error("Unable to save %s, internal error", fname);
+ else printf("Saved session recovery to %s\n", fname);
}
diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c
index 5f0697f06ce..76355045186 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 f2526231d50..c47bed65b69 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -558,7 +558,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;
}
@@ -575,9 +575,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)
{
@@ -623,7 +623,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 e38bb00fe8d..94f2fcae9fb 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -44,7 +44,10 @@
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
@@ -77,8 +80,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)
{
@@ -90,11 +97,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;
@@ -196,7 +208,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MFace *mf = cddm->mface;
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i;
if(mf) {
@@ -365,7 +377,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) { \
@@ -530,21 +542,21 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha
}
static void cdDM_drawFacesTex_common(DerivedMesh *dm,
- int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
+ int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
int (*drawParamsMapped)(void *userData, int index),
void *userData)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mv = cddm->mvert;
- MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
- MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
- int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
+ MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
int startFace = 0, lastFlag = 0xdeadbeef;
- MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
if( GPU_buffer_legacy(dm) ) {
DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
@@ -637,8 +649,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
if( col != 0 ) {*/
- unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
- for( i=0; i < dm->getNumFaces(dm); i++ ) {
+ unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
+ for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
for( j=0; j < 4; j++ ) {
colors[i*12+j*3] = col[i*4+j].r;
colors[i*12+j*3+1] = col[i*4+j].g;
@@ -704,7 +716,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
}
-static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
+static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
{
cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
}
@@ -715,15 +727,14 @@ 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);
- int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
+ int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
-
- mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
if(!mc)
- mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
if(!mc)
- mc = DM_get_face_data_layer(dm, CD_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_MCOL);
if( GPU_buffer_legacy(dm) ) {
DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
@@ -858,11 +869,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;
@@ -1256,37 +1267,52 @@ 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;
+ 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_recalcTesselation(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData,
+ &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, dm->numPolyData);
+
+ cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
}
static void cdDM_release(DerivedMesh *dm)
@@ -1297,6 +1323,11 @@ static void cdDM_release(DerivedMesh *dm)
MEM_freeN(cddm);
}
+int CDDM_Check(DerivedMesh *dm)
+{
+ return dm && dm->getMinMax == cdDM_getMinMax;
+}
+
/**************** CDDM interface functions ****************/
static CDDerivedMesh *cdDM_create(const char *desc)
{
@@ -1309,21 +1340,27 @@ 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_tessface_data_layer;
+
+ //doesn't work yet for all cases
+ //dm->recalcTesselation = cdDM_recalcTesselation;
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
@@ -1353,24 +1390,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;
}
@@ -1385,11 +1427,12 @@ 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;
@@ -1399,11 +1442,17 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
mesh->totedge);
- CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
+ CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, 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->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX);
@@ -1414,10 +1463,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
for(i = 0; i < mesh->totedge; ++i, ++index)
*index = i;
- index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
- for(i = 0; i < mesh->totface; ++i, ++index)
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ for(i = 0; i < mesh->totpoly; ++i, ++index)
*index = i;
+ if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
+ CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
+
return dm;
}
@@ -1425,7 +1477,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;
@@ -1443,6 +1495,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)
@@ -1499,7 +1553,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];
@@ -1520,16 +1574,341 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
return dm;
}
-DerivedMesh *CDDM_copy(DerivedMesh *source)
+
+static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
+ int cdindex, BMLoop *l3[3],
+ int numCol, int numTex)
+{
+ BMLoop *l;
+ BMFace *f = l3[0]->f;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
+
+ 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; j++) {
+ 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;
+ }
+ }
+
+ if (hasWCol) {
+ mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<3; j++) {
+ l = l3[j];
+ mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
+ 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 layers*/
+ CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, 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_LoopIter *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_LoopIter *iter = self;
+
+ if (layer == -1) return CustomData_get(&iter->cddm->dm.vertData,
+ iter->cddm->mloop[iter->head.vindex].v,
+ type);
+ else return CustomData_get_n(&iter->cddm->dm.vertData, type,
+ iter->cddm->mloop[iter->head.vindex].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, int faces_from_tessfaces)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
DerivedMesh *dm = &cddm->dm;
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);
@@ -1539,32 +1918,45 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
/* 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);
+
+ if (!faces_from_tessfaces)
+ DM_DupPolys(source, dm);
+ else
+ CDDM_tessfaces_to_faces(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;
}
@@ -1625,7 +2017,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];
@@ -1716,6 +2108,83 @@ void CDDM_calc_edges(DerivedMesh *dm)
BLI_edgehash_free(eh, NULL);
}
+
+void CDDM_calc_edges_poly(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData edgeData;
+ EdgeHashIterator *ehi;
+ MPoly *mp = cddm->mpoly;
+ MLoop *ml;
+ MEdge *med;
+ EdgeHash *eh = BLI_edgehash_new();
+ int v1, v2;
+ int *eindex;
+ int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
+
+ eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
+
+ med = cddm->medge;
+ if (med) {
+ for (i=0; i < numEdges; i++, med++) {
+ BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
+ }
+ }
+
+ for (i=0; i < maxFaces; i++, mp++) {
+ ml = cddm->mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v1 = ml->v;
+ v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
+ if (!BLI_edgehash_haskey(eh, v1, v2)) {
+ BLI_edgehash_insert(eh, v1, v2, NULL);
+ }
+ }
+ }
+
+ k = numEdges;
+ numEdges = BLI_edgehash_size(eh);
+
+ /* write new edges into a temporary CustomData */
+ memset(&edgeData, 0, sizeof(edgeData));
+ CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
+ CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
+
+ ehi = BLI_edgehashIterator_new(eh);
+ med = CustomData_get_layer(&edgeData, CD_MEDGE);
+ index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
+ for(i = 0; !BLI_edgehashIterator_isDone(ehi);
+ BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
+ BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
+ j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
+
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* free old CustomData and assign new one */
+ CustomData_free(&dm->edgeData, dm->numEdgeData);
+ dm->edgeData = edgeData;
+ dm->numEdgeData = numEdges;
+
+ cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
+
+ mp = cddm->mpoly;
+ for (i=0; i < maxFaces; i++, mp++) {
+ ml = cddm->mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v1 = ml->v;
+ v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
+ }
+ }
+
+ BLI_edgehash_free(eh, NULL);
+}
+
void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
{
if (numVerts < dm->numVertData)
@@ -1750,7 +2219,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];
}
@@ -1765,11 +2234,125 @@ 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;
+
+ /*ensure we have all the edges we need*/
+ CDDM_calc_edges(dm);
+
+ /*build edge hash*/
+ 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_ORIGINDEX, 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);
+}
+
+void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData_add_layer(&cddm->dm.vertData, CD_MVERT, CD_ASSIGN, mvert, cddm->dm.numVertData);
+ cddm->mvert = mvert;
+}
+
+void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData_add_layer(&cddm->dm.edgeData, CD_MEDGE, CD_ASSIGN, medge, cddm->dm.numEdgeData);
+ cddm->medge = medge;
+}
+
+void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData_add_layer(&cddm->dm.faceData, CD_MFACE, CD_ASSIGN, mface, cddm->dm.numFaceData);
+ cddm->mface = mface;
+}
+
+void CDDM_set_mloop(DerivedMesh *dm, MLoop *mloop)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, mloop, cddm->dm.numLoopData);
+ cddm->mloop = mloop;
+}
+
+void CDDM_set_mpoly(DerivedMesh *dm, MPoly *mpoly)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, mpoly, cddm->dm.numPolyData);
+ cddm->mpoly = mpoly;
+}
+
+
/* Multires DerivedMesh, extends CDDM */
typedef struct MultiresDM {
CDDerivedMesh cddm;
@@ -1830,7 +2413,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");
@@ -1849,7 +2434,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);
@@ -1863,7 +2449,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);
@@ -1974,3 +2560,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 74f88a77e63..8a9c88e2ce5 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -48,6 +48,7 @@
#include "BKE_pointcache.h"
#include "BLI_kdopbvh.h"
+#include "BLI_cellalloc.h"
#ifdef _WIN32
void tstart ( void )
@@ -438,7 +439,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
clmd->scene= scene; /* nice to pass on later :) */
framenr= (int)scene->r.cfra;
cache= clmd->point_cache;
- result = CDDM_copy(dm);
+ result = CDDM_copy(dm, 0);
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
@@ -933,8 +934,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. */
@@ -1046,9 +1047,9 @@ static 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 cf919f024b8..af8fed15efe 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -38,6 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
+#include "BLI_cellalloc.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -66,6 +67,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 28aaadea9c3..2d743a33106 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -38,6 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_mempool.h"
+#include "BLI_cellalloc.h"
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
@@ -45,6 +46,8 @@
#include "MEM_guardedalloc.h"
+#include "bmesh.h"
+
#include <math.h>
#include <string.h>
@@ -89,6 +92,14 @@ typedef struct LayerTypeInfo {
/* a function to set a layer's data to default values. if NULL, the
default is assumed to be all zeros */
void (*set_default)(void *data, int count);
+
+ /* functions necassary for geometry collapse*/
+ int (*equal)(void *data1, void *data2);
+ void (*multiply)(void *data, float fac);
+ void (*initminmax)(void *min, void *max);
+ void (*add)(void *data1, void *data2);
+ void (*dominmax)(void *data1, void *min, void *max);
+ void (*copyvalue)(void *source, void *dest);
} LayerTypeInfo;
static void layerCopy_mdeformvert(const void *source, void *dest,
@@ -102,7 +113,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest,
MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size);
if(dvert->totweight) {
- MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw),
+ MDeformWeight *dw = BLI_cellalloc_calloc(dvert->totweight * sizeof(*dw),
"layerCopy_mdeformvert dw");
memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
@@ -121,7 +132,7 @@ static void layerFree_mdeformvert(void *data, int count, int size)
MDeformVert *dvert = (MDeformVert *)((char *)data + i * size);
if(dvert->dw) {
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
dvert->dw = NULL;
dvert->totweight = 0;
}
@@ -163,7 +174,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
/* if this def_nr is not in the list, add it */
if(!node) {
- MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw),
+ MDeformWeight *tmp_dw = BLI_cellalloc_calloc(sizeof(*tmp_dw),
"layerInterp_mdeformvert tmp_dw");
tmp_dw->def_nr = dw->def_nr;
tmp_dw->weight = dw->weight * interp_weight;
@@ -174,10 +185,10 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
}
/* now we know how many unique deform weights there are, so realloc */
- if(dvert->dw) MEM_freeN(dvert->dw);
+ if(dvert->dw) BLI_cellalloc_free(dvert->dw);
if(totweight) {
- dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight,
+ dvert->dw = BLI_cellalloc_calloc(sizeof(*dvert->dw) * totweight,
"layerInterp_mdeformvert dvert->dw");
dvert->totweight = totweight;
@@ -257,6 +268,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];
@@ -531,12 +543,86 @@ static void layerFree_mdisps(void *data, int count, int size)
}
/* --------- */
+static void layerCopyValue_mloopcol(void *source, void *dest)
+{
+ MLoopCol *m1 = source, *m2 = dest;
+
+ m2->r = m1->r;
+ m2->g = m1->g;
+ m2->b = m1->b;
+ m2->a = m1->a;
+}
+
+static int layerEqual_mloopcol(void *data1, void *data2)
+{
+ MLoopCol *m1 = data1, *m2 = data2;
+ float r, g, b, a;
+
+ r = m1->r - m2->r;
+ g = m1->g - m2->g;
+ b = m1->b - m2->b;
+ a = m1->a - m2->a;
+
+ return r*r + g*g + b*b + a*a < 0.001;
+}
+
+static void layerMultiply_mloopcol(void *data, float fac)
+{
+ MLoopCol *m = data;
+
+ m->r = (float)m->r * fac;
+ m->g = (float)m->g * fac;
+ m->b = (float)m->b * fac;
+ m->a = (float)m->a * fac;
+}
+
+static void layerAdd_mloopcol(void *data1, void *data2)
+{
+ MLoopCol *m = data1, *m2 = data2;
+
+ m->r += m2->r;
+ m->g += m2->g;
+ m->b += m2->b;
+ m->a += m2->a;
+}
+
+static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax)
+{
+ MLoopCol *m = data;
+ MLoopCol *min = vmin, *max = vmax;
+
+ if (m->r < min->r) min->r = m->r;
+ if (m->g < min->g) min->g = m->g;
+ if (m->b < min->b) min->b = m->b;
+ if (m->a < min->a) min->a = m->a;
+
+ if (m->r > max->r) max->r = m->r;
+ if (m->g > max->g) max->g = m->g;
+ if (m->b > max->b) max->b = m->b;
+ if (m->a > max->a) max->a = m->a;
+}
+
+static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
+{
+ MLoopCol *min = vmin, *max = vmax;
+
+ min->r = 255;
+ min->g = 255;
+ min->b = 255;
+ min->a = 255;
+
+ max->r = 0;
+ max->g = 0;
+ max->b = 0;
+ max->a = 0;
+}
static void layerDefault_mloopcol(void *data, int count)
{
- static MLoopCol default_mloopcol = {255,255,255,255};
+ MLoopCol default_mloopcol = {255,255,255,255};
MLoopCol *mlcol = (MLoopCol*)data;
int i;
+
for(i = 0; i < count; i++)
mlcol[i] = default_mloopcol;
@@ -586,6 +672,56 @@ static void layerInterp_mloopcol(void **sources, float *weights,
mc->g = (int)col.g;
mc->b = (int)col.b;
}
+
+static void layerCopyValue_mloopuv(void *source, void *dest)
+{
+ MLoopUV *luv1 = source, *luv2 = dest;
+
+ luv2->uv[0] = luv1->uv[0];
+ luv2->uv[1] = luv1->uv[1];
+}
+
+static int layerEqual_mloopuv(void *data1, void *data2)
+{
+ MLoopUV *luv1 = data1, *luv2 = data2;
+ float u, v;
+
+ u = luv1->uv[0] - luv2->uv[0];
+ v = luv1->uv[1] - luv2->uv[1];
+
+ return u*u + v*v < 0.00001;
+}
+
+static void layerMultiply_mloopuv(void *data, float fac)
+{
+ MLoopUV *luv = data;
+
+ luv->uv[0] *= fac;
+ luv->uv[1] *= fac;
+}
+
+static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
+{
+ MLoopUV *min = vmin, *max = vmax;
+
+ INIT_MINMAX2(min->uv, max->uv);
+}
+
+static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax)
+{
+ MLoopUV *min = vmin, *max = vmax, *luv = data;
+
+ DO_MINMAX2(luv->uv, min->uv, max->uv);
+}
+
+static void layerAdd_mloopuv(void *data1, void *data2)
+{
+ MLoopUV *l1 = data1, *l2 = data2;
+
+ l1->uv[0] += l2->uv[0];
+ l1->uv[1] += l2->uv[1];
+}
+
static void layerInterp_mloopuv(void **sources, float *weights,
float *sub_weights, int count, void *dest)
{
@@ -719,16 +855,25 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
{sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
- {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
- {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
+ {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL,
+ layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
+ layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv},
+ {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL,
+ layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
{sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL},
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
- {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol,
+ {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL,
+ layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
+ {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
- {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol,
+ {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
};
@@ -739,25 +884,28 @@ 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_MLOOP | 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 |
+ CD_MASK_MTEXPOLY;
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_WEIGHT_MLOOPCOL |
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 |
CD_MASK_MLOOPCOL;
-
static const LayerTypeInfo *layerType_getInfo(int type)
{
if(type < 0 || type >= CD_NUMTYPES) return NULL;
@@ -778,13 +926,29 @@ static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type, int alloctype, void *layerdata, int totelem, const char *name);
+void customData_update_typemap(CustomData *data)
+{
+ int i, lasttype = -1;
+
+ for (i=0; i<CD_NUMTYPES; i++) {
+ data->typemap[i] = -1;
+ }
+
+ for (i=0; i<data->totlayer; i++) {
+ if (data->layers[i].type != lasttype) {
+ data->typemap[data->layers[i].type] = i;
+ }
+ lasttype = data->layers[i].type;
+ }
+}
+
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem)
{
const LayerTypeInfo *typeInfo;
CustomDataLayer *layer, *newlayer;
int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
-
+
for(i = 0; i < source->totlayer; ++i) {
layer = &source->layers[i];
typeInfo = layerType_getInfo(layer->type);
@@ -804,7 +968,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,
@@ -820,6 +984,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
newlayer->active_mask = lastmask;
}
}
+
+ customData_update_typemap(dest);
}
void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
@@ -897,11 +1063,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, char *nam
int CustomData_get_active_layer_index(const CustomData *data, int type)
{
- int i;
+ if (!data->totlayer)
+ return -1;
- for(i=0; i < data->totlayer; ++i)
- if(data->layers[i].type == type)
- return i + data->layers[i].active;
+ if (data->typemap[type] != -1) {
+ return data->typemap[type] + data->layers[data->typemap[type]].active;
+ }
return -1;
}
@@ -1163,6 +1330,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, typeInfo->defaultname);
+ customData_update_typemap(data);
if(layer)
return layer->data;
@@ -1178,6 +1346,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, name);
+ customData_update_typemap(data);
if(layer)
return layer->data;
@@ -1216,6 +1385,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
customData_resize(data, -CUSTOMDATA_GROW);
customData_update_offsets(data);
+ customData_update_typemap(data);
return 1;
}
@@ -1325,6 +1495,16 @@ void CustomData_set_only_copy(const struct CustomData *data,
data->layers[i].flag |= CD_FLAG_NOCOPY;
}
+void CustomData_copy_elements(int type, void *source, void *dest, int count)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->copy)
+ typeInfo->copy(source, dest, count);
+ else
+ memcpy(dest, source, typeInfo->size*count);
+}
+
void CustomData_copy_data(const CustomData *source, CustomData *dest,
int source_index, int dest_index, int count)
{
@@ -1484,6 +1664,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 = data->typemap[type];
+ if(layer_index < 0) return NULL;
+
+ offset = layerType_getInfo(type)->size * index;
+ return (char *)data->layers[layer_index+n].data + offset;
+}
+
void *CustomData_get_layer(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
@@ -1818,17 +2011,18 @@ 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){
int i;
@@ -1839,6 +2033,8 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
for(i=0; i < ldata->totlayer; i++){
if(ldata->layers[i].type == CD_MLOOPCOL)
CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total);
+ if (ldata->layers[i].type == CD_WEIGHT_MLOOPCOL)
+ CustomData_add_layer(fdata, CD_WEIGHT_MCOL, CD_CALLOC, &(ldata->layers[i].name), total);
}
}
@@ -1847,6 +2043,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 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, l->head.data, &tmp);
+ CustomData_bmesh_free_block(&destold, &l->head.data);
+ l->head.data = tmp;
+ }
+ }
+ }
+
+ if (destold.pool) BLI_mempool_destroy(destold.pool);
+}
+
void CustomData_bmesh_free_block(CustomData *data, void **block)
{
const LayerTypeInfo *typeInfo;
@@ -1948,6 +2192,82 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
return (char *)block + data->layers[layer_index+n].offset;
}
+/*gets from the layer at physical index n, note: doesn't check type.*/
+void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
+{
+ if(n < 0 || n >= data->totlayer) return NULL;
+
+ return (char *)block + data->layers[n].offset;
+}
+
+int CustomData_layer_has_math(struct CustomData *data, int layern)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type);
+
+ if (typeInfo->equal && typeInfo->add && typeInfo->multiply &&
+ typeInfo->initminmax && typeInfo->dominmax) return 1;
+
+ return 0;
+}
+
+/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
+ another, while not overwriting anything else (e.g. flags)*/
+void CustomData_data_copy_value(int type, void *source, void *dest)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if(!dest) return;
+
+ if(typeInfo->copyvalue)
+ typeInfo->copyvalue(source, dest);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
+int CustomData_data_equals(int type, void *data1, void *data2)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->equal)
+ return typeInfo->equal(data1, data2);
+ else return !memcmp(data1, data2, typeInfo->size);
+}
+
+void CustomData_data_initminmax(int type, void *min, void *max)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->initminmax)
+ typeInfo->initminmax(min, max);
+}
+
+
+void CustomData_data_dominmax(int type, void *data, void *min, void *max)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->dominmax)
+ typeInfo->dominmax(data, min, max);
+}
+
+
+void CustomData_data_multiply(int type, void *data, float fac)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->multiply)
+ typeInfo->multiply(data, fac);
+}
+
+
+void CustomData_data_add(int type, void *data1, void *data2)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->add)
+ typeInfo->add(data1, data2);
+}
+
void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
{
void *dest = CustomData_bmesh_get(data, block, type);
@@ -1974,6 +2294,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
memcpy(dest, source, typeInfo->size);
}
+void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source)
+{
+ void *dest = CustomData_bmesh_get_layer_n(data, block, n);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
+
+ if(!dest) return;
+
+ if(typeInfo->copy)
+ typeInfo->copy(source, dest, 1);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
float *sub_weights, int count, void *dest_block)
{
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 47736865273..9ad004cff5f 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -60,6 +60,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "BLI_cellalloc.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 266a528dc57..d8f466835b3 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -530,10 +530,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..6e8bfb9040f
--- /dev/null
+++ b/source/blender/blenkernel/intern/editderivedbmesh.c
@@ -0,0 +1,1694 @@
+/**
+ * $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 "BLI_array.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;
+ BLI_array_declare(looptris);
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l;
+ int i = 0, j, a, b;
+
+ if (tm->looptris) MEM_freeN(tm->looptris);
+
+#if 0 //simple quad/triangle code for performance testing purposes
+ looptris = MEM_callocN(sizeof(void*)*bm->totface*8, "looptris");
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for ( ; f; f=BMIter_Step(&iter)) {
+ EditVert *v, *lastv=NULL, *firstv=NULL;
+ EditEdge *e;
+ EditFace *efa;
+
+ /*don't consider two-edged faces*/
+ if (f->len < 3) continue;
+
+ //BLI_array_growone(looptris);
+ //BLI_array_growone(looptris);
+ //BLI_array_growone(looptris);
+
+ looptris[i*3] = f->loopbase;
+ looptris[i*3+1] = f->loopbase->head.next;
+ looptris[i*3+2] = f->loopbase->head.next->next;
+ i++;
+
+ if (f->len > 3) {
+ //BLI_array_growone(looptris);
+ //BLI_array_growone(looptris);
+ //BLI_array_growone(looptris);
+
+ looptris[i*3] = f->loopbase;
+ looptris[i*3+1] = f->loopbase->head.next->next;
+ looptris[i*3+2] = f->loopbase->head.next->next->next;
+ i++;
+ }
+
+ }
+
+ tm->tottri = i;
+ tm->looptris = looptris;
+ return;
+#endif
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for ( ; f; f=BMIter_Step(&iter)) {
+ EditVert *v, *lastv=NULL, *firstv=NULL;
+ EditEdge *e;
+ EditFace *efa;
+
+ /*don't consider two-edged faces*/
+ if (f->len < 3) continue;
+
+ /*scanfill time*/
+ 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) {
+ BMLoop *l1, *l2, *l3;
+
+ BLI_array_growone(looptris);
+ BLI_array_growone(looptris);
+ BLI_array_growone(looptris);
+
+ looptris[i*3] = l1 = efa->v1->tmp.p;
+ looptris[i*3+1] = l2 = efa->v2->tmp.p;
+ looptris[i*3+2] = l3 = efa->v3->tmp.p;
+
+ if (l1->head.eflag2 > l2->head.eflag2) {
+ SWAP(BMLoop*, l1, l2);
+ }
+ if (l2->head.eflag2 > l3->head.eflag2) {
+ SWAP(BMLoop*, l2, l3);
+ }
+ if (l1->head.eflag2 > l2->head.eflag2) {
+ SWAP(BMLoop*, l1, l2);
+ }
+
+ looptris[i*3] = l1;
+ looptris[i*3+1] = l2;
+ looptris[i*3+2] = l3;
+
+ 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);
+ }
+}
+
+void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+ int act;
+
+ if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
+ act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_mask_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_mask(&bm->ldata, CD_MLOOPUV, act);
+ }
+}
+
+/*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;
+
+ /*customdata layout of the tesselated faces*/
+ CustomData tessface_layout;
+} 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), 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)) {
+ 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 :/ */
+
+ if (vertexCos) {
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, vertexCos[BMINDEX_GET(l->v)]);
+ tot++;
+ }
+ } else {
+ 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), i++)
+ 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), i++)
+ 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;
+
+ 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(bmdm->faceNos[i]);
+ 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_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
+ int has_uv, int has_col)
+{
+ if (has_uv) {
+ luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+ luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+ luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+ }
+
+ if (has_col) {
+ lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
+ lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
+ lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
+ }
+
+
+}
+
+static void bmDM_drawFacesTex_common(DerivedMesh *dm,
+ int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
+ int (*drawParamsMapped)(void *userData, int index),
+ void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEditMesh *em = bmdm->tc;
+ BMesh *bm= bmdm->tc->bm;
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ BMFace *efa;
+ BMVert *eve;
+ BMIter iter;
+ MLoopUV *luv[3], dummyluv = {0};
+ MLoopCol *lcol[3], dummylcol = {0};
+ int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
+ int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
+
+ luv[0] = luv[1] = luv[2] = &dummyluv;
+ lcol[0] = lcol[1] = lcol[2] = &dummylcol;
+
+ dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+
+ i = 0;
+ BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL)
+ BMINDEX_SET(efa, i++);
+
+ if (vertexCos) {
+ i = 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BMINDEX_SET(eve, i++);
+
+ glBegin(GL_TRIANGLES);
+ for (i=0; i<em->tottri; i++) {
+ BMLoop **ls = em->looptris[i];
+ MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+ MTFace mtf = {0};
+ unsigned char *cp= NULL;
+ int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
+ int flag;
+
+ efa = ls[0]->f;
+
+ if (has_uv) {
+ mtf.flag = tp->flag;
+ mtf.tpage = tp->tpage;
+ mtf.transp = tp->transp;
+ mtf.mode = tp->mode;
+ mtf.tile = tp->tile;
+ mtf.unwrap = tp->unwrap;
+ }
+
+ if(drawParams)
+ flag= drawParams(&mtf, has_vcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, BMINDEX_GET(efa));
+ 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 (!has_vcol) {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ if (!drawSmooth) {
+ glNormal3fv(bmdm->faceNos[i]);
+
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ glTexCoord2fv(luv[0]->uv);
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
+
+ glTexCoord2fv(luv[1]->uv);
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
+
+ glTexCoord2fv(luv[2]->uv);
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
+ } else {
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ glTexCoord2fv(luv[0]->uv);
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ glNormal3fv(vertexNos[BMINDEX_GET(ls[0]->v)]);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
+
+ glTexCoord2fv(luv[1]->uv);
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ glNormal3fv(vertexNos[BMINDEX_GET(ls[1]->v)]);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
+
+ glTexCoord2fv(luv[2]->uv);
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ glNormal3fv(vertexNos[BMINDEX_GET(ls[2]->v)]);
+ glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
+ }
+ }
+ }
+ glEnd();
+ } else {
+ i = 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BMINDEX_SET(eve, i++);
+
+ for (i=0; i<em->tottri; i++) {
+ BMLoop **ls = em->looptris[i];
+ MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+ MTFace mtf = {0};
+ unsigned char *cp= NULL;
+ int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
+ int flag;
+
+ efa = ls[0]->f;
+
+ if (has_uv) {
+ mtf.flag = tp->flag;
+ mtf.tpage = tp->tpage;
+ mtf.transp = tp->transp;
+ mtf.mode = tp->mode;
+ mtf.tile = tp->tile;
+ mtf.unwrap = tp->unwrap;
+ }
+
+ if(drawParams)
+ flag= drawParams(&mtf, has_vcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, BMINDEX_GET(efa));
+ 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 (!has_vcol) {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ glBegin(GL_TRIANGLES);
+ if (!drawSmooth) {
+ glNormal3fv(efa->no);
+
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ if (luv[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (lcol[0])
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[0]->v->co);
+
+ if (luv[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (lcol[1])
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[1]->v->co);
+
+ if (luv[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (lcol[2])
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[2]->v->co);
+ } else {
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ if (luv[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (lcol[0])
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[0]->v->no);
+ glVertex3fv(ls[0]->v->co);
+
+ if (luv[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (lcol[1])
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[1]->v->no);
+ glVertex3fv(ls[1]->v->co);
+
+ if (luv[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (lcol[2])
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[2]->v->no);
+ glVertex3fv(ls[2]->v->co);
+ }
+ glEnd();
+ }
+ }
+ }
+}
+
+static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, 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_tessface_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_tessface_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_tessface_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->head.len = iter->f->len;
+
+ 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 = BMIter_Step(&iter->iter);
+ if (!iter->l) {
+ iter->head.done = 1;
+ return;
+ }
+
+ 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);
+}
+
+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->l = 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->l->v, &iter->head.v);
+ iter->head.vindex = BMINDEX_GET(iter->l->v);
+ iter->head.eindex = BMINDEX_GET(iter->l->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);
+ }
+
+ if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+ if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+ if (bmdm->vhash) 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);
+ }
+}
+
+CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->vdata;
+}
+
+CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->edata;
+}
+
+CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tessface_layout;
+}
+
+CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->ldata;
+}
+
+CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->pdata;
+}
+
+
+DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
+ float (*vertexCos)[3])
+{
+ EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
+ BMesh *bm = em->bm;
+ int i;
+
+ bmdm->tc = em;
+
+ DM_init((DerivedMesh*)bmdm, em->bm->totvert, em->bm->totedge, em->tottri,
+ em->bm->totloop, em->bm->totface);
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (bm->ldata.layers[i].type == CD_MLOOPCOL) {
+ CustomData_add_layer(&bmdm->tessface_layout, CD_MCOL, CD_ASSIGN, NULL, 0);
+ } else if (bm->ldata.layers[i].type == CD_MLOOPUV) {
+ CustomData_add_layer(&bmdm->tessface_layout, CD_MTFACE, CD_ASSIGN, NULL, 0);
+ }
+ }
+
+ bmdm->dm.numVertData = bm->totvert;
+ bmdm->dm.numEdgeData = bm->totedge;
+ bmdm->dm.numFaceData = em->tottri;
+ bmdm->dm.numLoopData = bm->totloop;
+ bmdm->dm.numPolyData = bm->totface;
+
+ bmdm->dm.getMinMax = bmDM_getMinMax;
+
+ bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
+ bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
+ bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
+ bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
+ bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
+
+ 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 = bmdm->tc->tottri;
+ 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/effect.c b/source/blender/blenkernel/intern/effect.c
index 9b648e2c05c..a6a99de462d 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -571,7 +571,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surfa
}
if(surface_vel) {
- MFace *mface = CDDM_get_face(surmd->dm, nearest.index);
+ MFace *mface = CDDM_get_tessface(surmd->dm, nearest.index);
VECCOPY(surface_vel, surmd->v[mface->v1].co);
VecAddf(surface_vel, surface_vel, surmd->v[mface->v2].co);
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index 8827897a509..3ea7bba9f5b 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 aa163b821c8..2233bbbf328 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -227,7 +227,7 @@ DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Ob
}
}
- result = CDDM_copy(dm);
+ result = CDDM_copy(dm, 0);
if(result)
{
@@ -299,7 +299,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)
{
@@ -356,7 +356,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];
@@ -392,6 +392,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;
@@ -459,12 +460,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;
@@ -618,9 +619,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
index 64558d0b456..5f6d7bd6272 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: fmodifier.c 21537 2009-07-11 22:22:53Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index b6e4ffd6cc3..2d3b84bbdb3 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -58,6 +58,7 @@
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
#ifdef HAVE_CONFIG_H
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index a957be4704c..0faff6d3354 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -40,6 +40,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "BLI_cellalloc.h"
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index a79c3472426..abd551f06c2 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -713,7 +713,7 @@ void free_libblock(ListBase *lb, void *idv)
free_object((Object *)id);
break;
case ID_ME:
- free_mesh((Mesh *)id);
+ free_mesh((Mesh *)id, 1);
break;
case ID_CU:
free_curve((Curve *)id);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 0065c348ad0..2725d1dc894 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -67,25 +67,104 @@
/* -- */
#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 "BLI_cellalloc.h"
+#include "BLI_array.h"
#include "BLI_edgehash.h"
+#include "bmesh.h"
EditMesh *BKE_mesh_get_editmesh(Mesh *me)
{
- return me->edit_mesh;
+ return bmesh_to_editmesh(me->edit_btmesh->bm);
}
+void free_editMesh(EditMesh *em);
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);
+ free_editMesh(em);
+ MEM_freeN(em);
}
+static void mesh_ensure_tesselation_customdata(Mesh *me)
+{
+ int tottex, totcol;
+
+ tottex = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ totcol = CustomData_number_of_layers(&me->fdata, CD_MCOL);
+
+ if (tottex != CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY) ||
+ totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL))
+ {
+ CustomData_free(&me->fdata, me->totface);
+
+ me->mface = NULL;
+ me->mtface = NULL;
+ me->mcol = NULL;
+ me->totface = 0;
+
+ memset(&me->fdata, 0, sizeof(&me->fdata));
+
+ CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
+ printf("Warning! Tesselation uvs or vcol data got out of sync, had to reset!\n");
+ }
+}
+
+/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
+ mloopcol and mcol) have the same relative active/render/clone/mask indices.*/
+void mesh_update_linked_customdata(Mesh *me)
+{
+ int act;
+
+ if (me->edit_btmesh)
+ BMEdit_UpdateLinkedCustomData(me->edit_btmesh);
+
+ mesh_ensure_tesselation_customdata(me);
+
+ if (CustomData_has_layer(&me->pdata, CD_MTEXPOLY)) {
+ act = CustomData_get_active_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_active(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_render_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_render(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_render(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_clone_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_clone(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_clone(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_mask_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_mask(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_mask(&me->fdata, CD_MTFACE, act);
+ }
+
+ if (CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) {
+ act = CustomData_get_active_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_render_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_render(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_clone_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_clone(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_mask_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_mask(&me->fdata, CD_MCOL, act);
+ }
+}
void mesh_update_customdata_pointers(Mesh *me)
{
+ mesh_update_linked_customdata(me);
+
me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY);
@@ -95,6 +174,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
@@ -125,9 +211,10 @@ void unlink_mesh(Mesh *me)
/* do not free mesh itself */
-void free_mesh(Mesh *me)
+void free_mesh(Mesh *me, int unlink)
{
- unlink_mesh(me);
+ if (unlink)
+ unlink_mesh(me);
if(me->pv) {
if(me->pv->vert_map) MEM_freeN(me->pv->vert_map);
@@ -143,12 +230,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)
@@ -163,7 +252,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
for (i=0; i<copycount; i++){
if (src[i].dw){
- dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
+ dst[i].dw = BLI_cellalloc_calloc (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight);
}
}
@@ -182,7 +271,7 @@ void free_dverts(MDeformVert *dvert, int totvert)
/* Free any special data from the verts */
for (i=0; i<totvert; i++){
- if (dvert[i].dw) MEM_freeN (dvert[i].dw);
+ if (dvert[i].dw) BLI_cellalloc_free (dvert[i].dw);
}
MEM_freeN (dvert);
}
@@ -207,6 +296,7 @@ Mesh *copy_mesh(Mesh *me)
{
Mesh *men;
MTFace *tface;
+ MTexPoly *txface;
int a, i;
men= copy_libblock(me);
@@ -220,6 +310,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 */
@@ -232,7 +324,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);
@@ -243,12 +345,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;
@@ -266,6 +399,7 @@ void make_local_tface(Mesh *me)
}
}
}
+
}
void make_local_mesh(Mesh *me)
@@ -985,10 +1119,10 @@ void mesh_to_curve(Scene *scene, Object *ob)
MVert *mverts= dm->getVertArray(dm);
MEdge *med, *medge= dm->getEdgeArray(dm);
- MFace *mf, *mface= dm->getFaceArray(dm);
+ MFace *mf, *mface= dm->getTessFaceArray(dm);
int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
int totedges = 0;
int i;
@@ -1461,3 +1595,265 @@ void mesh_pmv_off(Object *ob, Mesh *me)
me->pv= NULL;
}
}
+
+static void mesh_loops_to_corners(CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int lindex[3], int findex,
+ int polyindex, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, 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; j++) {
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], 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(fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+/*this function recreates a tesselation.
+
+ returns number of tesselation faces.*/
+int mesh_recalcTesselation(CustomData *fdata,
+ CustomData *ldata, CustomData *pdata,
+ MVert *mvert, int totface, int totloop,
+ int totpoly)
+{
+ MPoly *mp, *mpoly;
+ MLoop *ml, *mloop;
+ MFace *mf = NULL, *mface;
+ BLI_array_declare(mf);
+ EditVert *v, *lastv, *firstv;
+ EditFace *f;
+ BLI_array_declare(origIndex);
+ int i, j, k, lindex[3], *origIndex = NULL, *polyorigIndex;
+ int numTex, numCol;
+
+ mpoly = CustomData_get_layer(pdata, CD_MPOLY);
+ mloop = CustomData_get_layer(ldata, CD_MLOOP);
+
+ numTex = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ k = 0;
+ mp = mpoly;
+ polyorigIndex = CustomData_get_layer(pdata, CD_ORIGINDEX);
+ for (i=0; i<totpoly; i++, mp++) {
+ ml = mloop + mp->loopstart;
+ firstv = NULL;
+ lastv = NULL;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v = BLI_addfillvert(mvert[ml->v].co);
+ if (polyorigIndex)
+ v->tmp.l = polyorigIndex[i];
+ else
+ v->tmp.l = i;
+
+ v->keyindex = mp->loopstart + j;
+
+ if (lastv)
+ BLI_addfilledge(lastv, v);
+
+ if (!firstv)
+ firstv = v;
+ lastv = v;
+ }
+ BLI_addfilledge(lastv, firstv);
+
+ BLI_edgefill(0, 0);
+ for (f=fillfacebase.first; f; f=f->next) {
+ BLI_array_growone(mf);
+ BLI_array_growone(origIndex);
+
+ /*these are loop indices, they'll be transformed
+ into vert indices later.*/
+ mf[k].v1 = f->v1->keyindex;
+ mf[k].v2 = f->v2->keyindex;
+ mf[k].v3 = f->v3->keyindex;
+ origIndex[k] = f->v1->tmp.l;
+
+ k++;
+ }
+
+ BLI_end_edgefill();
+ }
+
+ CustomData_free(fdata, totface);
+ memset(fdata, 0, sizeof(CustomData));
+ totface = k;
+
+ CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mf, totface);
+ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, origIndex, totface);
+ CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+ mface = mf;
+ for (i=0; i<totface; i++, mf++) {
+ /*ensure winding is correct*/
+ if (mf->v1 > mf->v2) {
+ SWAP(int, mf->v1, mf->v2);
+ }
+ if (mf->v2 > mf->v3) {
+ SWAP(int, mf->v2, mf->v3);
+ }
+ if (mf->v1 > mf->v2) {
+ SWAP(int, mf->v1, mf->v2);
+ }
+
+ lindex[0] = mf->v1;
+ lindex[1] = mf->v2;
+ lindex[2] = mf->v3;
+
+ /*transform loop indices to vert indices*/
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+
+ mf->flag = mpoly[origIndex[i]].flag;
+ mf->mat_nr = mpoly[origIndex[i]].mat_nr;
+
+ mesh_loops_to_corners(fdata, ldata, pdata,
+ lindex, i, origIndex[i], numTex, numCol);
+ }
+
+ return totface;
+}
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+*/
+static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvert, float *normal)
+{
+
+ MVert *v1, *v2, *v3;
+ double u[3], v[3], w[3];
+ double n[3] = {0.0, 0.0, 0.0}, l;
+ int i, s=0;
+
+ for(i = 0; i < mpoly->totloop; i++){
+ v1 = mvert + loopstart[i].v;
+ v2 = mvert + loopstart[(i+1)%mpoly->totloop].v;
+ v3 = mvert + loopstart[(i+2)%mpoly->totloop].v;
+
+ VECCOPY(u, v1->co);
+ VECCOPY(v, v2->co);
+ VECCOPY(w, v3->co);
+
+ /*this fixes some weird numerical error*/
+ if (i==0) {
+ u[0] += 0.0001f;
+ u[1] += 0.0001f;
+ u[2] += 0.0001f;
+ }
+
+ /* 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 = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ l = sqrt(l);
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ } else l = 1.0f / l;
+
+ n[0] *= l;
+ n[1] *= l;
+ n[2] *= l;
+
+ normal[0] = (float) n[0];
+ normal[1] = (float) n[1];
+ normal[2] = (float) n[2];
+
+}
+
+void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float *no)
+{
+ if(mpoly->totloop > 4) {
+ mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
+ }
+ else if(mpoly->totloop == 3){
+ MVert *v1, *v2, *v3;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + loopstart->v;
+ CalcNormFloat(v1->co, v2->co, v3->co, no);
+ }
+ else if(mpoly->totloop == 4){
+ MVert *v1, *v2, *v3, *v4;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + (loopstart++)->v;
+ v4 = mvarray + loopstart->v;
+ CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, no);
+ }
+ else{ /*horrible, two sided face!*/
+ no[0] = 0.0;
+ no[1] = 0.0;
+ no[2] = 1.0;
+ }
+}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 532c3e5da73..a70d1a02bb4 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 *****
*
@@ -50,6 +51,9 @@
#include "BLI_edgehash.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
+#include "BLI_cellalloc.h"
+#include "BLI_mempool.h"
+#include "BLI_array.h"
#include "MEM_guardedalloc.h"
@@ -105,6 +109,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"
@@ -268,12 +273,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);
@@ -360,12 +365,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);
@@ -399,10 +404,10 @@ static void subsurfModifier_freeData(ModifierData *md)
SubsurfModifierData *smd = (SubsurfModifierData*) md;
if(smd->mCache) {
- ccgSubSurf_free(smd->mCache);
+ CCS_free(smd->mCache);
}
if(smd->emCache) {
- ccgSubSurf_free(smd->emCache);
+ CCS_free(smd->emCache);
}
}
@@ -421,7 +426,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;
@@ -489,7 +494,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;
@@ -502,7 +507,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 */
@@ -518,7 +523,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),
@@ -594,7 +599,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);
@@ -635,8 +640,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;
@@ -646,13 +651,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);
@@ -660,7 +666,7 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
MEM_freeN(vertMap);
MEM_freeN(edgeMap);
MEM_freeN(faceMap);
-
+
return result;
}
@@ -724,7 +730,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
@@ -918,7 +924,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)) &&
@@ -935,7 +941,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 */
@@ -989,8 +995,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;
@@ -1000,7 +1006,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));
@@ -1015,6 +1021,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;
}
@@ -1162,6 +1170,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)
@@ -1264,18 +1273,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) */
Mat4One(final_offset);
@@ -1426,15 +1435,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;
@@ -1470,7 +1479,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);
@@ -1503,10 +1512,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);
@@ -1565,9 +1574,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];
@@ -1604,10 +1613,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);
@@ -1666,9 +1675,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];
@@ -1699,6 +1708,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;
}
@@ -1719,11 +1730,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 */
@@ -1882,6 +1901,7 @@ static 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,
@@ -1894,7 +1914,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;
@@ -1905,7 +1925,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) {
@@ -2040,11 +2060,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++;
@@ -2057,10 +2077,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];
@@ -2070,7 +2090,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) {
@@ -2084,7 +2104,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++;
@@ -2099,9 +2119,17 @@ 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
+DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+ Object *ob,
+ DerivedMesh *dm,
+ int initFlags,
+ int axis);
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
Object *ob, DerivedMesh *dm,
int initFlags)
@@ -2142,7 +2170,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);
@@ -2152,1201 +2180,366 @@ static DerivedMesh *mirrorModifier_applyModifierEM(
/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
* or edge angle (can be used to achieve autosmoothing)
*/
-#if 0
-#define EDGESPLIT_DEBUG_3
-#define EDGESPLIT_DEBUG_2
-#define EDGESPLIT_DEBUG_1
-#define EDGESPLIT_DEBUG_0
-#endif
-static void edgesplitModifier_initData(ModifierData *md)
-{
- EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+/*new cddm-based edge split code*/
+typedef struct VertUser {
+ int ov, v, done;
+ ListBase users;
+} VertUser;
- /* default to 30-degree split angle, sharpness from both angle & flag
- */
- emd->split_angle = 30;
- emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
-}
+typedef struct EdgeNode {
+ struct EdgeNode *next, *prev;
+ struct EdgeData *edge;
+} EdgeNode;
-static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
-{
- EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
- EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
+typedef struct EdgeData {
+ EdgeNode v1node, v2node;
+ VertUser *v1user, *v2user;
+ float fno[3]; /*used to calculate face angles*/
+ int has_fno;
+ int tag;
+ int v1, v2;
+ int used;
+} EdgeData;
- temd->split_angle = emd->split_angle;
- temd->flags = emd->flags;
-}
+typedef struct MemBase {
+ BLI_mempool *vertuserpool;
+} MemBase;
-/* Mesh data for edgesplit operation */
-typedef struct SmoothVert {
- LinkNode *faces; /* all faces which use this vert */
- int oldIndex; /* the index of the original DerivedMesh vert */
- int newIndex; /* the index of the new DerivedMesh vert */
-} SmoothVert;
-
-#define SMOOTHEDGE_NUM_VERTS 2
-
-typedef struct SmoothEdge {
- SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
- LinkNode *faces; /* all faces which use this edge */
- int oldIndex; /* the index of the original DerivedMesh edge */
- int newIndex; /* the index of the new DerivedMesh edge */
- short flag; /* the flags from the original DerivedMesh edge */
-} SmoothEdge;
-
-#define SMOOTHFACE_MAX_EDGES 4
-
-typedef struct SmoothFace {
- SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
- int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
- float normal[3]; /* the normal of this face */
- int oldIndex; /* the index of the original DerivedMesh face */
- int newIndex; /* the index of the new DerivedMesh face */
-} SmoothFace;
-
-typedef struct SmoothMesh {
- SmoothVert *verts;
- SmoothEdge *edges;
- SmoothFace *faces;
- int num_verts, num_edges, num_faces;
- int max_verts, max_edges, max_faces;
- DerivedMesh *dm;
- float threshold; /* the cosine of the smoothing angle */
- int flags;
- MemArena *arena;
- ListBase propagatestack, reusestack;
-} SmoothMesh;
+BM_INLINE EdgeData *edge_get_next(EdgeData *e, int ov) {
+ if (ov == e->v1)
+ return e->v1node.next ? e->v1node.next->edge : NULL;
+ else return e->v2node.next ? e->v2node.next->edge : NULL;
+}
-static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
+BM_INLINE EdgeNode *edge_get_node(EdgeData *e, int ov)
{
- SmoothVert *copy = &mesh->verts[mesh->num_verts];
-
- if(mesh->num_verts >= mesh->max_verts) {
- printf("Attempted to add a SmoothMesh vert beyond end of array\n");
- return NULL;
- }
-
- *copy = *vert;
- copy->faces = NULL;
- copy->newIndex = mesh->num_verts;
- ++mesh->num_verts;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
-#endif
- return copy;
+ if (ov == e->v1)
+ return &e->v1node;
+ else return &e->v2node;
}
-static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
+BM_INLINE VertUser *edge_get_vuser(MemBase *b, EdgeData *edge, int ov)
{
- SmoothEdge *copy = &mesh->edges[mesh->num_edges];
-
- if(mesh->num_edges >= mesh->max_edges) {
- printf("Attempted to add a SmoothMesh edge beyond end of array\n");
+ if (ov == edge->v1)
+ return edge->v1user;
+ else if (ov == edge->v2)
+ return edge->v2user;
+ else {
+ printf("yeek!!\n");
return NULL;
}
-
- *copy = *edge;
- copy->faces = NULL;
- copy->newIndex = mesh->num_edges;
- ++mesh->num_edges;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
-#endif
- return copy;
-}
-
-static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- int i;
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
- if(edge->verts[i] == vert) return 1;
-
- return 0;
}
-static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
- int max_verts, int max_edges, int max_faces)
-{
- SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
- mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
- "SmoothMesh.verts");
- mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
- "SmoothMesh.edges");
- mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
- "SmoothMesh.faces");
-
- mesh->num_verts = num_verts;
- mesh->num_edges = num_edges;
- mesh->num_faces = num_faces;
+BM_INLINE void edge_set_vuser(MemBase *b, EdgeData *e, int ov, VertUser *vu)
- mesh->max_verts = max_verts;
- mesh->max_edges = max_edges;
- mesh->max_faces = max_faces;
-
- return mesh;
-}
-
-static void smoothmesh_free(SmoothMesh *mesh)
{
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i)
- BLI_linklist_free(mesh->verts[i].faces, NULL);
+ VertUser *olduser = edge_get_vuser(b, e, ov);
- for(i = 0; i < mesh->num_edges; ++i)
- BLI_linklist_free(mesh->edges[i].faces, NULL);
+ if (vu == olduser)
+ return;
- if(mesh->arena)
- BLI_memarena_free(mesh->arena);
+ if (olduser)
+ BLI_remlink(&olduser->users, ov==e->v1 ? &e->v1node : &e->v2node);
+ BLI_addtail(&vu->users, ov==e->v1 ? &e->v1node : &e->v2node);
- MEM_freeN(mesh->verts);
- MEM_freeN(mesh->edges);
- MEM_freeN(mesh->faces);
- MEM_freeN(mesh);
+ if (ov == e->v1)
+ e->v1user = vu;
+ else e->v2user = vu;
}
-static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
+BM_INLINE VertUser *new_vuser(MemBase *base)
{
- int i;
- SmoothVert *tmp;
-
- if(max_verts <= mesh->max_verts) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
-
- memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
-
- /* remap vert pointers in edges */
- for(i = 0; i < mesh->num_edges; ++i) {
- int j;
- SmoothEdge *edge = &mesh->edges[i];
+ VertUser *vusr = BLI_mempool_calloc(base->vertuserpool);
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
- /* pointer arithmetic to get vert array index */
- edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
- }
-
- MEM_freeN(mesh->verts);
- mesh->verts = tmp;
- mesh->max_verts = max_verts;
+ return vusr;
}
-static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
+BM_INLINE MemBase *new_membase(void)
{
- int i;
- SmoothEdge *tmp;
-
- if(max_edges <= mesh->max_edges) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
-
- memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
+ MemBase *b = MEM_callocN(sizeof(MemBase), "MemBase for edgesplit in modifier.c");
+ b->vertuserpool = BLI_mempool_create(sizeof(VertUser), 1, 2048);
- /* remap edge pointers in faces */
- for(i = 0; i < mesh->num_faces; ++i) {
- int j;
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
- if(face->edges[j])
- /* pointer arithmetic to get edge array index */
- face->edges[j] = &tmp[face->edges[j] - mesh->edges];
- }
-
- MEM_freeN(mesh->edges);
- mesh->edges = tmp;
- mesh->max_edges = max_edges;
+ return b;
}
-#ifdef EDGESPLIT_DEBUG_0
-static void smoothmesh_print(SmoothMesh *mesh)
+BM_INLINE void free_membase(MemBase *b)
{
- int i, j;
- DerivedMesh *dm = mesh->dm;
-
- printf("--- SmoothMesh ---\n");
- printf("--- Vertices ---\n");
- for(i = 0; i < mesh->num_verts; i++) {
- SmoothVert *vert = &mesh->verts[i];
- LinkNode *node;
- MVert mv;
-
- dm->getVert(dm, vert->oldIndex, &mv);
-
- printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
- i, vert->oldIndex, vert->newIndex,
- mv.co[0], mv.co[1], mv.co[2]);
- printf(", faces={");
- for(node = vert->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Edges ---\n");
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- LinkNode *node;
-
- printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
- i,
- edge->oldIndex, edge->newIndex,
- edge->verts[0]->newIndex, edge->verts[1]->newIndex);
- if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
- printf(", faces={");
- for(node = edge->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Faces ---\n");
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- printf("%4d: indices={%4d, %4d}, edges={", i,
- face->oldIndex, face->newIndex);
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- if(face->flip[j])
- printf(" -%-2d", face->edges[j]->newIndex);
- else
- printf(" %-2d", face->edges[j]->newIndex);
- }
- printf("}, verts={");
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
- }
- printf("}\n");
- }
+ BLI_mempool_destroy(b->vertuserpool);
+ MEM_freeN(b);
}
-#endif
-static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
+BM_INLINE EdgeData *edge_get_first(VertUser *vu)
{
- SmoothMesh *mesh;
- EdgeHash *edges = BLI_edgehash_new();
- int i;
- int totvert, totedge, totface;
-
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
-
- mesh = smoothmesh_new(totvert, totedge, totface,
- totvert, totedge, totface);
-
- mesh->dm = dm;
-
- for(i = 0; i < totvert; i++) {
- SmoothVert *vert = &mesh->verts[i];
-
- vert->oldIndex = vert->newIndex = i;
- }
-
- for(i = 0; i < totedge; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge med;
-
- dm->getEdge(dm, i, &med);
- edge->verts[0] = &mesh->verts[med.v1];
- edge->verts[1] = &mesh->verts[med.v2];
- edge->oldIndex = edge->newIndex = i;
- edge->flag = med.flag;
-
- BLI_edgehash_insert(edges, med.v1, med.v2, edge);
- }
-
- for(i = 0; i < totface; i++) {
- SmoothFace *face = &mesh->faces[i];
- MFace mf;
- MVert v1, v2, v3;
- int j;
-
- dm->getFace(dm, i, &mf);
-
- dm->getVert(dm, mf.v1, &v1);
- dm->getVert(dm, mf.v2, &v2);
- dm->getVert(dm, mf.v3, &v3);
- face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
- if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
- face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
- if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
- if(mf.v4) {
- MVert v4;
- dm->getVert(dm, mf.v4, &v4);
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
- if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
- CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
- } else {
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = NULL;
- CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
- }
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- BLI_linklist_prepend(&edge->faces, face);
- BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
- }
-
- face->oldIndex = face->newIndex = i;
- }
-
- BLI_edgehash_free(edges, NULL);
-
- return mesh;
+ return vu->users.first ? ((EdgeNode*)vu->users.first)->edge : NULL;
}
-static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
+DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd)
{
- DerivedMesh *result = CDDM_from_template(mesh->dm,
- mesh->num_verts,
- mesh->num_edges,
- mesh->num_faces);
- MVert *new_verts = CDDM_get_verts(result);
- MEdge *new_edges = CDDM_get_edges(result);
- MFace *new_faces = CDDM_get_faces(result);
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i) {
- SmoothVert *vert = &mesh->verts[i];
- MVert *newMV = &new_verts[vert->newIndex];
-
- DM_copy_vert_data(mesh->dm, result,
- vert->oldIndex, vert->newIndex, 1);
- mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
- }
-
- for(i = 0; i < mesh->num_edges; ++i) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge *newME = &new_edges[edge->newIndex];
-
- DM_copy_edge_data(mesh->dm, result,
- edge->oldIndex, edge->newIndex, 1);
- mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
- newME->v1 = edge->verts[0]->newIndex;
- newME->v2 = edge->verts[1]->newIndex;
- }
-
- for(i = 0; i < mesh->num_faces; ++i) {
- SmoothFace *face = &mesh->faces[i];
- MFace *newMF = &new_faces[face->newIndex];
-
- DM_copy_face_data(mesh->dm, result,
- face->oldIndex, face->newIndex, 1);
- mesh->dm->getFace(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;
- newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
-
- if(face->edges[3]) {
- newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
- } else {
- newMF->v4 = 0;
+ DerivedMesh *cddm = CDDM_copy(dm, 0);
+ MEdge *medge;
+ BLI_array_declare(medge);
+ MLoop *mloop, *ml, *prevl;
+ MPoly *mpoly, *mp;
+ MVert *mvert;
+ BLI_array_declare(mvert);
+ EdgeData *etags, *e, *enext;
+ BLI_array_declare(etags);
+ VertUser *vu, *vu2;
+ MemBase *membase;
+ CustomData edata, vdata;
+ int i, j, curv, cure;
+ float threshold = cos((emd->split_angle + 0.00001) * M_PI / 180.0);
+ float no[3], edge_angle_cos;
+
+ if (!cddm->numVertData || !cddm->numEdgeData)
+ return cddm;
+
+ membase = new_membase();
+
+ etags = MEM_callocN(sizeof(EdgeData)*cddm->numEdgeData, "edgedata tag thingies");
+ BLI_array_set_length(etags, cddm->numEdgeData);
+
+ mvert = cddm->getVertArray(cddm);
+ BLI_array_set_length(mvert, cddm->numVertData);
+ medge = cddm->getEdgeArray(cddm);
+ BLI_array_set_length(medge, cddm->numEdgeData);
+ mloop = CustomData_get_layer(&cddm->loopData, CD_MLOOP);
+ mpoly = CustomData_get_layer(&cddm->polyData, CD_MPOLY);
+
+ for (i=0; i<cddm->numEdgeData; i++) {
+ etags[i].v1 = medge[i].v1;
+ etags[i].v2 = medge[i].v2;
+
+ etags[i].tag = (medge[i].flag & ME_SHARP) != 0;
+
+ etags[i].v1node.edge = etags+i;
+ etags[i].v2node.edge = etags+i;
+ }
+
+ if (emd->flags & MOD_EDGESPLIT_FROMANGLE) {
+ mp = mpoly;
+ for (i=0; i<cddm->numPolyData; i++, mp++) {
+ mesh_calc_poly_normal(mp, mloop+mp->loopstart, mvert, no);
+
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ if (!etags[ml->e].has_fno) {
+ VECCOPY(etags[ml->e].fno, no);
+ etags[ml->e].has_fno = 1;
+ } else if (!etags[ml->e].tag) {
+ edge_angle_cos = INPR(etags[ml->e].fno, no);
+ if (edge_angle_cos < threshold) {
+ etags[ml->e].tag = 1;
+ }
+ }
+ }
}
}
- return result;
-}
-
-/* returns the other vert in the given edge
- */
-static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- if(edge->verts[0] == vert) return edge->verts[1];
- else return edge->verts[0];
-}
-
-/* returns the other edge in the given face that uses the given vert
- * returns NULL if no other edge in the given face uses the given vert
- * (this should never happen)
- */
-static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
- SmoothEdge *edge)
-{
- int i,j;
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- SmoothEdge *tmp_edge = face->edges[i];
- if(tmp_edge == edge) continue;
-
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
- if(tmp_edge->verts[j] == vert) return tmp_edge;
- }
-
- /* if we get to here, something's wrong (there should always be 2 edges
- * which use the same vert in a face)
- */
- return NULL;
-}
-
-/* returns a face attached to the given edge which is not the given face.
- * returns NULL if no other faces use this edge.
- */
-static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
-{
- LinkNode *node;
-
- for(node = edge->faces; node != NULL; node = node->next)
- if(node->link != face) return node->link;
-
- return NULL;
-}
-
-#if 0
-/* copies source list to target, overwriting target (target is not freed)
- * nodes in the copy will be in the same order as in source
- */
-static void linklist_copy(LinkNode **target, LinkNode *source)
-{
- LinkNode *node = NULL;
- *target = NULL;
-
- for(; source; source = source->next) {
- if(node) {
- node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
- node = node->next;
-} else {
- node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
-}
- node->link = source->link;
- node->next = NULL;
-}
-}
-#endif
-
- /* appends source to target if it's not already in target */
- static void linklist_append_unique(LinkNode **target, void *source)
-{
- LinkNode *node;
- LinkNode *prev = NULL;
-
- /* check if source value is already in the list */
- for(node = *target; node; prev = node, node = node->next)
- if(node->link == source) return;
-
- node = MEM_mallocN(sizeof(*node), "nlink");
- node->next = NULL;
- node->link = source;
-
- if(prev) prev->next = node;
- else *target = node;
-}
-
-/* appends elements of source which aren't already in target to target */
-static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
-{
- for(; source; source = source->next)
- linklist_append_unique(target, source->link);
-}
-
-#if 0 /* this is no longer used, it should possibly be removed */
-/* prepends prepend to list - doesn't copy nodes, just joins the lists */
-static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
-{
- if(prepend) {
- LinkNode *node = prepend;
- while(node->next) node = node->next;
-
- node->next = *list;
- *list = prepend;
-}
-}
-#endif
-
-/* returns 1 if the linked list contains the given pointer, 0 otherwise
- */
-static int linklist_contains(LinkNode *list, void *ptr)
-{
- LinkNode *node;
-
- for(node = list; node; node = node->next)
- if(node->link == ptr) return 1;
-
- return 0;
-}
-
-/* returns 1 if the first linked list is a subset of the second (comparing
- * pointer values), 0 if not
- */
-static int linklist_subset(LinkNode *list1, LinkNode *list2)
-{
- for(; list1; list1 = list1->next)
- if(!linklist_contains(list2, list1->link))
- return 0;
-
- return 1;
-}
-
-#if 0
-/* empties the linked list
- * frees pointers with freefunc if freefunc is not NULL
- */
-static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
-{
- BLI_linklist_free(*list, freefunc);
- *list = NULL;
-}
-#endif
-
-/* removes the first instance of value from the linked list
- * frees the pointer with freefunc if freefunc is not NULL
- */
-static void linklist_remove_first(LinkNode **list, void *value,
- LinkNodeFreeFP freefunc)
-{
- LinkNode *node = *list;
- LinkNode *prev = NULL;
-
- while(node && node->link != value) {
- prev = node;
- node = node->next;
- }
-
- if(node) {
- if(prev)
- prev->next = node->next;
- else
- *list = node->next;
-
- if(freefunc)
- freefunc(node->link);
-
- MEM_freeN(node);
- }
-}
-
-/* removes all elements in source from target */
-static void linklist_remove_list(LinkNode **target, LinkNode *source,
- LinkNodeFreeFP freefunc)
-{
- for(; source; source = source->next)
- linklist_remove_first(target, source->link, freefunc);
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void print_ptr(void *ptr)
-{
- printf("%p\n", ptr);
-}
+ mp = mpoly;
+ for (i=0; i<cddm->numPolyData; i++, mp++) {
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ if (etags[ml->e].tag)
+ continue;
-static void print_edge(void *ptr)
-{
- SmoothEdge *edge = ptr;
- printf(" %4d", edge->newIndex);
-}
+ prevl = mloop + mp->loopstart + ((j-1)+mp->totloop) % mp->totloop;
-static void print_face(void *ptr)
-{
- SmoothFace *face = ptr;
- printf(" %4d", face->newIndex);
-}
-#endif
-
-typedef struct ReplaceData {
- void *find;
- void *replace;
-} ReplaceData;
+ if (!edge_get_vuser(membase, etags+prevl->e, ml->v)) {
+ vu = new_vuser(membase);
+ vu->ov = vu->v = ml->v;
+ edge_set_vuser(membase, etags+prevl->e, ml->v, vu);
+ }
-static void edge_replace_vert(void *ptr, void *userdata)
-{
- SmoothEdge *edge = ptr;
- SmoothVert *find = ((ReplaceData *)userdata)->find;
- SmoothVert *replace = ((ReplaceData *)userdata)->replace;
- int i;
+ if (!edge_get_vuser(membase, etags+ml->e, ml->v)) {
+ vu = new_vuser(membase);
+ vu->ov = vu->v = ml->v;
+ edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+ }
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing vert %4d with %4d in edge %4d",
- find->newIndex, replace->newIndex, edge->newIndex);
- printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
+ /*continue if previous edge is tagged*/
+ if (etags[prevl->e].tag)
+ continue;
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
- if(edge->verts[i] == find) {
- linklist_append_list_unique(&replace->faces, edge->faces);
- linklist_remove_list(&find->faces, edge->faces, NULL);
+ /*merge together adjacent split vert users*/
+ if (edge_get_vuser(membase, etags+prevl->e, ml->v)
+ != edge_get_vuser(membase, etags+ml->e, ml->v))
+ {
+ vu = edge_get_vuser(membase, etags+prevl->e, ml->v);
+ vu2 = edge_get_vuser(membase, etags+ml->e, ml->v);
- edge->verts[i] = replace;
+ /*remove from vu2's users list and add to vu's*/
+ for (e=edge_get_first(vu2); e; e=enext) {
+ enext = edge_get_next(e, ml->v);
+ edge_set_vuser(membase, e, ml->v, vu);
+ }
+ }
}
}
-#ifdef EDGESPLIT_DEBUG_3
- printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-}
-
-static void face_replace_vert(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- int i;
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
- edge_replace_vert(face->edges[i], userdata);
-}
-
-static void face_replace_edge(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- SmoothEdge *find = ((ReplaceData *)userdata)->find;
- SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
- int i;
-
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing edge %4d with %4d in face %4d",
- find->newIndex, replace->newIndex, face->newIndex);
- if(face->edges[3])
- printf(": {%2d %2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(": {%2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- if(face->edges[i] == find) {
- linklist_remove_first(&face->edges[i]->faces, face, NULL);
- BLI_linklist_prepend(&replace->faces, face);
- face->edges[i] = replace;
- }
- }
+ mp = mpoly;
+ for (i=0; i<cddm->numPolyData; i++, mp++) {
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ if (!etags[ml->e].tag)
+ continue;
-#ifdef EDGESPLIT_DEBUG_3
- if(face->edges[3])
- printf(" -> {%2d %2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(" -> {%2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-}
+ prevl = mloop + mp->loopstart + ((j-1)+mp->totloop) % mp->totloop;
-static int edge_is_loose(SmoothEdge *edge)
-{
- return !(edge->faces && edge->faces->next);
-}
+ if (!etags[prevl->e].tag) {
+ vu = edge_get_vuser(membase, etags+prevl->e, ml->v);
+ if (!vu) {
+ vu = new_vuser(membase);
+ vu->ov = vu->v = ml->v;
+ edge_set_vuser(membase, etags+prevl->e, ml->v, vu);
+ }
-static int edge_is_sharp(SmoothEdge *edge, int flags,
- float threshold)
-{
-#ifdef EDGESPLIT_DEBUG_1
- printf("edge %d: ", edge->newIndex);
-#endif
- if(edge->flag & ME_SHARP) {
- /* edge can only be sharp if it has at least 2 faces */
- if(!edge_is_loose(edge)) {
-#ifdef EDGESPLIT_DEBUG_1
- printf("sharp\n");
-#endif
- return 1;
- } else {
- /* edge is loose, so it can't be sharp */
- edge->flag &= ~ME_SHARP;
+ edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+ } else {
+ vu = new_vuser(membase);
+ vu->ov = vu->v = ml->v;
+ edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+ }
}
}
-#ifdef EDGESPLIT_DEBUG_1
- printf("not sharp\n");
-#endif
- return 0;
-}
-
-/* finds another sharp edge which uses vert, by traversing faces around the
- * vert until it does one of the following:
- * - hits a loose edge (the edge is returned)
- * - hits a sharp edge (the edge is returned)
- * - returns to the start edge (NULL is returned)
- */
-static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
- LinkNode **visited_faces, float threshold, int flags)
-{
- SmoothFace *face = NULL;
- SmoothEdge *edge2 = NULL;
- /* holds the edges we've seen so we can avoid looping indefinitely */
- LinkNode *visited_edges = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- /* get a face on which to start */
- if(edge->faces) face = edge->faces->link;
- else return NULL;
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge);
+ curv = cddm->numVertData;
+ cure = cddm->numEdgeData;
+ mp = mpoly;
+ for (i=0; i<cddm->numPolyData; i++, mp++) {
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ e = etags + ml->e;
+ if (e->v1user && !e->v1user->done) {
+ e->v1user->done = 1;
+ BLI_array_growone(mvert);
- /* get the next edge */
- edge2 = other_edge(face, vert, edge);
-
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* search until we hit a loose edge or a sharp edge or an edge we've
- * seen before
- */
- while(face && !edge_is_sharp(edge2, flags, threshold)
- && !linklist_contains(visited_edges, edge2)) {
-#ifdef EDGESPLIT_DEBUG_3
- printf("current face %4d; current edge %4d\n", face->newIndex,
- edge2->newIndex);
-#endif
- /* get the next face */
- face = other_face(edge2, face);
-
- /* if face == NULL, edge2 is a loose edge */
- if(face) {
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge2);
-
- /* get the next edge */
- edge2 = other_edge(face, vert, edge2);
-#ifdef EDGESPLIT_DEBUG_3
- printf("next face %4d; next edge %4d\n",
- face->newIndex, edge2->newIndex);
- } else {
- printf("loose edge: %4d\n", edge2->newIndex);
-#endif
- }
- }
-
- /* either we came back to the start edge or we found a sharp/loose edge */
- if(linklist_contains(visited_edges, edge2))
- /* we came back to the start edge */
- edge2 = NULL;
-
- BLI_linklist_free(visited_edges, NULL);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
- "returning edge %d\n",
- edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
-#endif
- return edge2;
-}
+ mvert[curv] = mvert[e->v1user->ov];
+ e->v1user->v = curv;
-static void split_single_vert(SmoothVert *vert, SmoothFace *face,
- SmoothMesh *mesh)
-{
- SmoothVert *copy_vert;
- ReplaceData repdata;
-
- copy_vert = smoothvert_copy(vert, mesh);
-
- repdata.find = vert;
- repdata.replace = copy_vert;
- face_replace_vert(face, &repdata);
-}
-
-typedef struct PropagateEdge {
- struct PropagateEdge *next, *prev;
- SmoothEdge *edge;
- SmoothVert *vert;
-} PropagateEdge;
-
-static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->reusestack.first;
-
- if(pedge) {
- BLI_remlink(&mesh->reusestack, pedge);
- }
- else {
- if(!mesh->arena) {
- mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
- BLI_memarena_use_calloc(mesh->arena);
- }
-
- pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
- }
-
- pedge->edge = edge;
- pedge->vert = vert;
- BLI_addhead(&mesh->propagatestack, pedge);
-}
+ curv++;
+ }
-static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->propagatestack.first;
+ if (e->v2user && !e->v2user->done) {
+ e->v2user->done = 1;
+ BLI_array_growone(mvert);
- if(pedge) {
- *edge = pedge->edge;
- *vert = pedge->vert;
- BLI_remlink(&mesh->propagatestack, pedge);
- BLI_addhead(&mesh->reusestack, pedge);
- }
- else {
- *edge = NULL;
- *vert = NULL;
- }
-}
+ mvert[curv] = mvert[e->v2user->ov];
+ e->v2user->v = curv;
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
+ curv++;
+ }
-static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
- SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
+ vu = edge_get_vuser(membase, e, ml->v);
+ if (!vu)
+ continue;
+ ml->v = vu->v;
+
+#if 0 //BMESH_TODO should really handle edges here, but for now use cddm_calc_edges
+ /*ok, now we have to deal with edges. . .*/
+ if (etags[ml->e].tag) {
+ if (etags[ml->e].used) {
+ BLI_array_growone(medge);
+ BLI_array_growone(etags);
+ medge[cure] = medge[ml->e];
+
+ ml->e = cure;
+ etags[cure].used = 1;
+ cure++;
+ }
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
- mesh->threshold, mesh->flags);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so we've hit a dead end */
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- if(edge_is_loose(edge)) {
- /* edge is loose, so we can split edge2 at this vert */
- split_edge(edge2, vert, mesh);
- } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
- /* both edges are sharp, so we can split the pair at vert */
- split_edge(edge, vert, mesh);
- } else {
- /* edge is not sharp, so try to split edge2 at its other vert */
- split_edge(edge2, other_vert(edge2, vert), mesh);
- }
- } else { /* edge2 is loose */
- if(edge_is_loose(edge)) {
- SmoothVert *vert2;
- ReplaceData repdata;
-
- /* can't split edge, what should we do with vert? */
- if(linklist_subset(vert->faces, visited_faces)) {
- /* vert has only one fan of faces attached; don't split it */
+ vu = etags[ml->e].v1user;
+ vu2 = etags[ml->e].v2user;
+
+ if (vu)
+ medge[ml->e].v1 = vu->v;
+ if (vu2)
+ medge[ml->e].v2 = vu2->v;
} else {
- /* vert has more than one fan of faces attached; split it */
- vert2 = smoothvert_copy(vert, mesh);
+ etags[ml->e].used = 1;
- /* replace vert with its copy in visited_faces */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
+ if (vu->ov == etags[ml->e].v1)
+ medge[ml->e].v1 = vu->v;
+ else if (vu->ov == etags[ml->e].v2)
+ medge[ml->e].v2 = vu->v;
}
- } else {
- /* edge is not loose, so it must be sharp; split it */
- split_edge(edge, vert, mesh);
- }
- }
-
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
#endif
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- SmoothVert *vert2;
- ReplaceData repdata;
- /* the list of faces traversed while looking for a sharp edge */
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
- mesh->threshold, mesh->flags);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so try the other vert */
- vert2 = other_vert(edge, vert);
- push_propagate_stack(edge, vert2, mesh);
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- /* replace edge2 with its copy in visited_faces */
- repdata.find = edge2;
- repdata.replace = copy_edge2;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* all copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertices at either end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
- push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
- } else {
- /* edge2 is loose */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertex at the other end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
+ }
}
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
- int flags, int *extra_edges)
-{
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
- int i;
-
- *extra_edges = 0;
-
- /* loop through edges, counting potential new ones */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- int sharp = 0;
-
- /* treat all non-manifold edges (3 or more faces) as sharp */
- if(edge->faces && edge->faces->next && edge->faces->next->next) {
- LinkNode *node;
-
- /* this edge is sharp */
- sharp = 1;
- /* add an extra edge for every face beyond the first */
- *extra_edges += 2;
- for(node = edge->faces->next->next->next; node; node = node->next)
- (*extra_edges)++;
- } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
- && !edge_is_loose(edge)) {
- /* (the edge can only be sharp if we're checking angle or flag,
- * and it has at least 2 faces) */
-
- /* if we're checking the sharp flag and it's set, good */
- if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
- /* this edge is sharp */
- sharp = 1;
-
- (*extra_edges)++;
- } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
- /* we know the edge has 2 faces, so check the angle */
- SmoothFace *face1 = edge->faces->link;
- SmoothFace *face2 = edge->faces->next->link;
- float edge_angle_cos = Inpf(face1->normal,
- face2->normal);
+ /*resize customdata arrays and add new medge/mvert arrays*/
+ vdata = cddm->vertData;
+ edata = cddm->edgeData;
+
+ /*make sure we don't copy over mvert/medge layers*/
+ CustomData_set_layer(&vdata, CD_MVERT, NULL);
+ CustomData_set_layer(&edata, CD_MEDGE, NULL);
+ CustomData_free_layer_active(&vdata, CD_MVERT, cddm->numVertData);
+ CustomData_free_layer_active(&edata, CD_MEDGE, cddm->numEdgeData);
+
+ memset(&cddm->vertData, 0, sizeof(CustomData));
+ memset(&cddm->edgeData, 0, sizeof(CustomData));
+
+ CustomData_copy(&vdata, &cddm->vertData, CD_MASK_DERIVEDMESH, CD_CALLOC, curv);
+ CustomData_copy_data(&vdata, &cddm->vertData, 0, 0, cddm->numVertData);
+ CustomData_free(&vdata, cddm->numVertData);
+ cddm->numVertData = curv;
+
+ CustomData_copy(&edata, &cddm->edgeData, CD_MASK_DERIVEDMESH, CD_CALLOC, cure);
+ CustomData_copy_data(&edata, &cddm->edgeData, 0, 0, cddm->numEdgeData);
+ CustomData_free(&edata, cddm->numEdgeData);
+ cddm->numEdgeData = cure;
+
+ CDDM_set_mvert(cddm, mvert);
+ CDDM_set_medge(cddm, medge);
- if(edge_angle_cos < threshold) {
- /* this edge is sharp */
- sharp = 1;
+ free_membase(membase);
+ MEM_freeN(etags);
+
+ /*edge calculation isn't working correctly, so just brute force it*/
+ cddm->numEdgeData = 0;
+ CDDM_calc_edges_poly(cddm);
+
+ cddm->numFaceData = mesh_recalcTesselation(&cddm->faceData,
+ &cddm->loopData, &cddm->polyData,
+ mvert, cddm->numFaceData,
+ cddm->numLoopData, cddm->numPolyData);
- (*extra_edges)++;
- }
- }
- }
+ CDDM_set_mface(cddm, DM_get_tessface_data_layer(cddm, CD_MFACE));
+ CDDM_calc_normals(cddm);
- /* set/clear sharp flag appropriately */
- if(sharp) edge->flag |= ME_SHARP;
- else edge->flag &= ~ME_SHARP;
- }
+ return cddm;
}
-static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
-{
- SmoothVert *vert;
- int i;
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
- mesh->flags = flags;
-
- /* loop through edges, splitting sharp ones */
- /* can't use an iterator here, because we'll be adding edges */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
-
- if(edge_is_sharp(edge, flags, mesh->threshold)) {
- split_edge(edge, edge->verts[0], mesh);
-
- do {
- pop_propagate_stack(&edge, &vert, mesh);
- if(edge && smoothedge_has_vert(edge, vert))
- propagate_split(edge, vert, mesh);
- } while(edge);
- }
- }
-}
-static int count_bridge_verts(SmoothMesh *mesh)
+static void edgesplitModifier_initData(ModifierData *md)
{
- int i, j, count = 0;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
-
- /* if there are other faces sharing this vertex but not
- * these edges, the vertex will be split, so count it
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next) {
- count++;
- }
- }
- }
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
- /* each bridge vert will be counted once per face that uses it,
- * so count is too high, but it's ok for now
+ /* default to 30-degree split angle, sharpness from both angle & flag
*/
- return count;
+ emd->split_angle = 30;
+ emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
}
-static void split_bridge_verts(SmoothMesh *mesh)
+static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
{
- int i,j;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+ EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
- /* if there are other faces sharing this vertex but not
- * these edges, split the vertex
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next)
- /* FIXME this needs to find all faces that share edges with
- * this one and split off together
- */
- split_single_vert(vert, face, mesh);
- }
- }
+ temd->split_angle = emd->split_angle;
+ temd->flags = emd->flags;
}
static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
Object *ob, DerivedMesh *dm)
{
- SmoothMesh *mesh;
- DerivedMesh *result;
- int max_verts, max_edges;
-
if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
return dm;
-
- /* 1. make smoothmesh with initial number of elements */
- mesh = smoothmesh_from_derivedmesh(dm);
-
- /* 2. count max number of elements to add */
- tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
- max_verts = max_edges * 2 + mesh->max_verts;
- max_verts += count_bridge_verts(mesh);
- max_edges += mesh->max_edges;
-
- /* 3. reallocate smoothmesh arrays & copy elements across */
- /* 4. remap copied elements' pointers to point into the new arrays */
- smoothmesh_resize_verts(mesh, max_verts);
- smoothmesh_resize_edges(mesh, max_edges);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Pre-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_sharp_edges(mesh, emd->split_angle, emd->flags);
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-edge-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_bridge_verts(mesh);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-vert-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
-#ifdef EDGESPLIT_DEBUG_0
- printf("Edgesplit: Estimated %d verts & %d edges, "
- "found %d verts & %d edges\n", max_verts, max_edges,
- mesh->num_verts, mesh->num_edges);
-#endif
-
- result = CDDM_from_smoothmesh(mesh);
- smoothmesh_free(mesh);
-
- return result;
+
+ return doEdgeSplit(dm, emd);
}
static DerivedMesh *edgesplitModifier_applyModifier(
@@ -3365,7 +2558,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);
@@ -3449,7 +2642,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);
@@ -3585,12 +2778,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;
@@ -3763,7 +2956,7 @@ static void displaceModifier_deformVerts(
{
DerivedMesh *dm;
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
else return;
@@ -3777,13 +2970,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);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
CDDM_apply_vert_coords(dm, vertexCos);
CDDM_calc_normals(dm);
@@ -3903,7 +3096,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);
@@ -4009,8 +3202,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) {
@@ -4108,7 +3301,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);
@@ -4144,9 +3337,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++) {
@@ -4222,7 +3415,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];
@@ -4448,7 +3641,7 @@ static void smoothModifier_deformVerts(
{
DerivedMesh *dm;
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else dm = CDDM_from_mesh(ob->data, ob);
CDDM_apply_vert_coords(dm, vertexCos);
@@ -4461,13 +3654,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);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
CDDM_apply_vert_coords(dm, vertexCos);
CDDM_calc_normals(dm);
@@ -5042,14 +4235,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);
@@ -5186,12 +4379,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;
@@ -5448,7 +4641,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;
@@ -5456,8 +4649,8 @@ 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 if(derivedData) dm = CDDM_copy(derivedData, 0);
+ else dm = CDDM_from_BMEditMesh(editData, ob->data);
if(wmd->flag & MOD_WAVE_NORM) {
CDDM_apply_vert_coords(dm, vertexCos);
@@ -5548,13 +4741,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);
@@ -5563,14 +4756,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);
@@ -5780,12 +4973,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);
@@ -6073,7 +5266,7 @@ static void collisionModifier_deformVerts(
MVert *tempVert = NULL;
/* if possible use/create DerivedMesh */
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
if(!ob->pd)
@@ -6117,8 +5310,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);
@@ -6242,7 +5435,7 @@ static void surfaceModifier_deformVerts(
surmd->dm->release(surmd->dm);
/* if possible use/create DerivedMesh */
- if(derivedData) surmd->dm = CDDM_copy(derivedData);
+ if(derivedData) surmd->dm = CDDM_copy(derivedData, 0);
else surmd->dm = get_original_dm(md->scene, ob, NULL, 0);
if(!ob->pd)
@@ -6359,8 +5552,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);
@@ -6504,7 +5697,7 @@ static void particleSystemModifier_deformVerts(
}
/* make new dm */
- psmd->dm=CDDM_copy(dm);
+ psmd->dm=CDDM_copy(dm, 0);
CDDM_apply_vert_coords(psmd->dm, vertexCos);
CDDM_calc_normals(psmd->dm);
@@ -6519,7 +5712,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;
@@ -6527,7 +5720,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){
@@ -6542,12 +5735,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);
@@ -6673,7 +5866,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;
@@ -6689,7 +5882,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);
@@ -6759,8 +5952,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;
@@ -6790,7 +5983,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;
@@ -6807,14 +6000,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);
@@ -6873,8 +6067,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;
@@ -6956,12 +6150,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");
@@ -7047,14 +6241,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++){
@@ -7069,10 +6263,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;
}
@@ -7106,7 +6300,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];
@@ -7114,8 +6308,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++;
@@ -7138,13 +6332,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++;
@@ -7215,18 +6409,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++;
@@ -7316,18 +6510,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++;
@@ -7356,18 +6550,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++;
@@ -7421,7 +6615,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;
}
@@ -7444,7 +6639,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;
@@ -7466,7 +6661,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);
@@ -7485,7 +6680,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 */
@@ -7551,8 +6746,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;
@@ -7567,7 +6762,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;
@@ -7588,6 +6783,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
psmd->psys->lattice= NULL;
}
+ CDDM_tessfaces_to_faces(explode);
return explode;
}
@@ -7621,7 +6817,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;
@@ -7864,10 +7060,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];
@@ -7877,11 +7073,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;
@@ -8043,13 +7238,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;
@@ -8182,7 +7377,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived
/* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
if(dataMask)
{
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
else if(ob->type==OB_LATTICE) dm = NULL;
else return;
@@ -8200,15 +7395,15 @@ 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);
if(dataMask)
{
- if(derivedData) dm = CDDM_copy(derivedData);
- else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
+ else if(ob->type==OB_MESH) dm = CDDM_from_BMEditMesh(editData, ob->data);
else if(ob->type==OB_LATTICE) dm = NULL;
else return;
@@ -8296,7 +7491,7 @@ static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, Deriv
/* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
if(dataMask)
{
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
else if(ob->type==OB_LATTICE) dm = NULL;
else return;
@@ -8315,7 +7510,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);
@@ -8323,8 +7518,8 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, Edi
/* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
if(dataMask)
{
- if(derivedData) dm = CDDM_copy(derivedData);
- else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
+ 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..84bbb1fb5d7
--- /dev/null
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -0,0 +1,728 @@
+/*
+* $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 "BLI_cellalloc.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 "BLI_array.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, *mvert;
+ MEdge *me, *medge;
+ DMFaceIter *dfiter;
+ DMLoopIter *dliter;
+ BMVert *v, **vtable, **verts=NULL;
+ BMEdge *e, **etable, **edges=NULL;
+ BMFace *f;
+ BMIter liter;
+ BLI_array_declare(verts);
+ BLI_array_declare(edges);
+ int numTex, numCol;
+ int i, j, k, 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_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
+ CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE);
+ CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
+ CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, 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 = mvert = 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;
+ }
+ MEM_freeN(mvert);
+
+ /*do edges*/
+ me = medge = 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;
+ }
+ MEM_freeN(medge);
+
+ /*do faces*/
+ k = 0;
+ dfiter = dm->newFaceIter(dm);
+ for (; !dfiter->done; dfiter->step(dfiter)) {
+ BMLoop *l;
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ dliter = dfiter->getLoopsIter(dfiter);
+ for (j=0; !dliter->done; dliter->step(dliter), j++) {
+ BLI_array_growone(verts);
+ BLI_array_growone(edges);
+
+ verts[j] = vtable[dliter->vindex];
+ edges[j] = etable[dliter->eindex];
+ }
+
+ if (j < 2)
+ break;
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, dfiter->len, 0);
+
+ if (!f)
+ continue;
+
+ f->head.flag = MEFlags_To_BMFlags(dfiter->flags, BM_FACE);
+ f->mat_nr = dfiter->mat_nr;
+
+ 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);
+ }
+ dfiter->free(dfiter);
+
+ MEM_freeN(vtable);
+ MEM_freeN(etable);
+
+ BLI_array_free(verts);
+ BLI_array_free(edges);
+
+ if (!em) em = BMEdit_Create(bm);
+ else BMEdit_RecalcTesselation(em);
+
+ return em;
+}
+
+static float vertarray_size(MVert *mvert, int numVerts, int axis)
+{
+ int i;
+ float min_co, max_co;
+
+ /* if there are no vertices, width is 0 */
+ if(numVerts == 0) return 0;
+
+ /* find the minimum and maximum coordinates on the desired axis */
+ min_co = max_co = mvert->co[axis];
+ ++mvert;
+ for(i = 1; i < numVerts; ++i, ++mvert) {
+ if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
+ if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
+ }
+
+ return max_co - min_co;
+}
+
+/* finds the best possible flipped name. For renaming; check for unique names afterwards */
+/* if strip_number: removes number extensions */
+static void vertgroup_flip_name (char *name, int strip_number)
+{
+ int len;
+ char prefix[128]={""}; /* The part before the facing */
+ char suffix[128]={""}; /* The part after the facing */
+ char replace[128]={""}; /* The replacement string */
+ char number[128]={""}; /* The number extension string */
+ char *index=NULL;
+
+ len= strlen(name);
+ if(len<3) return; // we don't do names like .R or .L
+
+ /* We first check the case with a .### extension, let's find the last period */
+ if(isdigit(name[len-1])) {
+ index= strrchr(name, '.'); // last occurrance
+ if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
+ if(strip_number==0)
+ strcpy(number, index);
+ *index= 0;
+ len= strlen(name);
+ }
+ }
+
+ strcpy (prefix, name);
+
+#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
+
+ /* first case; separator . - _ with extensions r R l L */
+ if( IS_SEPARATOR(name[len-2]) ) {
+ switch(name[len-1]) {
+ case 'l':
+ prefix[len-1]= 0;
+ strcpy(replace, "r");
+ break;
+ case 'r':
+ prefix[len-1]= 0;
+ strcpy(replace, "l");
+ break;
+ case 'L':
+ prefix[len-1]= 0;
+ strcpy(replace, "R");
+ break;
+ case 'R':
+ prefix[len-1]= 0;
+ strcpy(replace, "L");
+ break;
+ }
+ }
+ /* case; beginning with r R l L , with separator after it */
+ else if( IS_SEPARATOR(name[1]) ) {
+ switch(name[0]) {
+ case 'l':
+ strcpy(replace, "r");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'r':
+ strcpy(replace, "l");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'L':
+ strcpy(replace, "R");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'R':
+ strcpy(replace, "L");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ }
+ }
+ else if(len > 5) {
+ /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
+ index = BLI_strcasestr(prefix, "right");
+ if (index==prefix || index==prefix+len-5) {
+ if(index[0]=='r')
+ strcpy (replace, "left");
+ else {
+ if(index[1]=='I')
+ strcpy (replace, "LEFT");
+ else
+ strcpy (replace, "Left");
+ }
+ *index= 0;
+ strcpy (suffix, index+5);
+ }
+ else {
+ index = BLI_strcasestr(prefix, "left");
+ if (index==prefix || index==prefix+len-4) {
+ if(index[0]=='l')
+ strcpy (replace, "right");
+ else {
+ if(index[1]=='E')
+ strcpy (replace, "RIGHT");
+ else
+ strcpy (replace, "Right");
+ }
+ *index= 0;
+ strcpy (suffix, index+4);
+ }
+ }
+ }
+
+#undef IS_SEPARATOR
+
+ sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
+}
+
+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 = dm; //copying shouldn't be necassary here, as all modifiers return CDDM's
+ 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, maxVerts;
+ int finalVerts, finalEdges, finalFaces;
+ int *indexMap = NULL;
+ DerivedMesh *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);
+
+ 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)
+ Mat4Invert(obinv, ob->obmat);
+ else
+ Mat4One(obinv);
+
+ Mat4MulSerie(result_mat, offset,
+ obinv, amd->offset_ob->obmat,
+ NULL, NULL, NULL, NULL, NULL);
+ 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(INPR(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) */
+ Mat4One(final_offset);
+
+ for(j=0; j < count - 1; j++) {
+ Mat4MulMat4(tmp_mat, final_offset, offset);
+ Mat4CpyMat4(final_offset, tmp_mat);
+ }
+
+ 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;
+ 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);
+
+ 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);
+
+ if (amd->flags & MOD_ARR_MERGE)
+ BMO_Exec_Op(em->bm, &weldop);
+
+ BMO_Finish_Op(em->bm, &weldop);
+
+ 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 */
+#define VERT_NEW 1
+
+DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+ Object *ob,
+ DerivedMesh *dm,
+ int initFlags,
+ int axis)
+{
+ float tolerance = mmd->tolerance;
+ DerivedMesh *result, *cddm;
+ BMEditMesh *em;
+ BMesh *bm;
+ BMOIter siter1;
+ BMOperator op;
+ BMVert *v1;
+ int vector_size=0, a, b;
+ bDeformGroup *def, *defb;
+ bDeformGroup **vector_def = NULL;
+ float mtx[4][4], imtx[4][4];
+ int j;
+
+ cddm = dm; //copying shouldn't be necassary here, as all modifiers return CDDM's
+ em = CDDM_To_BMesh(dm, NULL);
+
+ /*convienence variable*/
+ bm = em->bm;
+
+ 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 mtx2[4][4], vec[3];
+
+ Mat4Invert(mtx2, mmd->mirror_ob->obmat);
+ Mat4MulMat4(mtx, ob->obmat, mtx2);
+ } else {
+ Mat4One(mtx);
+ }
+
+ BMO_InitOpf(bm, &op, "mirror geom=%avef mat=%m4 mergedist=%f axis=%d",
+ mtx, mmd->tolerance, axis);
+
+ BMO_Exec_Op(bm, &op);
+
+ BMO_CallOpf(bm, "reversefaces faces=%s", &op, "newout");
+
+ /*handle vgroup stuff*/
+ if (mmd->flag & MOD_MIR_VGROUP) {
+ BMO_ITER(v1, &siter1, bm, &op, "newout", BM_VERT) {
+ MDeformVert *dvert = CustomData_bmesh_get(&bm->vdata, v1->head.data, CD_MDEFORMVERT);
+
+ if (dvert) {
+ for(j = 0; j < dvert[0].totweight; ++j) {
+ char tmpname[32];
+
+ if(dvert->dw[j].def_nr < 0 ||
+ dvert->dw[j].def_nr >= vector_size)
+ continue;
+
+ def = vector_def[dvert->dw[j].def_nr];
+ strcpy(tmpname, def->name);
+ vertgroup_flip_name(tmpname,0);
+
+ for(b = 0, defb = ob->defbase.first; defb;
+ defb = defb->next, b++)
+ {
+ if(!strcmp(defb->name, tmpname))
+ {
+ dvert->dw[j].def_nr = b;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ BMO_Finish_Op(bm, &op);
+
+ BMEdit_RecalcTesselation(em);
+ result = CDDM_from_BMEditMesh(em, NULL); //CDDM_copy(getEditDerivedBMesh(em, ob, NULL), 0);
+
+ BMEdit_Free(em);
+ MEM_freeN(em);
+
+ if (vector_def) MEM_freeN(vector_def);
+
+ return result;
+}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index ecffbb3d15f..07b86b8251c 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -474,7 +474,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int dista
mrdm = multires_dm_create_from_derived(&mmd_sub, 1, orig, ob, 0, 0);
totsubvert = mrdm->getNumVerts(mrdm);
totsubedge = mrdm->getNumEdges(mrdm);
- totsubface = mrdm->getNumFaces(mrdm);
+ totsubface = mrdm->getNumTessFaces(mrdm);
orig->needsFree = 1;
orig->release(orig);
@@ -1205,7 +1205,7 @@ static void multiresModifier_update(DerivedMesh *dm)
final = multires_subdisp_pre(dm, totlvl - lvl, 0);
multires_subdisp(orig, ob, 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 eb5beb734a1..cb9748ddb85 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -99,6 +99,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"
@@ -898,7 +899,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);
@@ -2368,12 +2369,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->mode & OB_MODE_EDIT) {
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 ea8562c0ca8..555f66c86c8 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -57,6 +57,7 @@
#include "BLI_listbase.h"
#include "BLI_rand.h"
#include "BLI_threads.h"
+#include "BLI_cellalloc.h"
#include "BKE_anim.h"
@@ -685,7 +686,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
data->totchildcache= psys->totchildcache;
if(psmd->dm)
- data->dm= CDDM_copy(psmd->dm);
+ data->dm= CDDM_copy(psmd->dm, 0);
data->totdmvert= psmd->totdmvert;
data->totdmedge= psmd->totdmedge;
data->totdmface= psmd->totdmface;
@@ -784,9 +785,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)
@@ -1487,7 +1488,7 @@ static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int
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);
}
@@ -1535,11 +1536,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 */
@@ -1608,7 +1609,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;
@@ -1632,15 +1633,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;
@@ -1698,7 +1699,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);
@@ -3139,10 +3140,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]);
@@ -3448,7 +3449,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
@@ -3460,7 +3461,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);
@@ -4061,7 +4062,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);
}
@@ -4081,11 +4082,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 45050127582..00b1672dea6 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -290,7 +290,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX);
}
else { /* FROM_FACE/FROM_VOLUME */
- totdmelem= dm->getNumFaces(dm);
+ totdmelem= dm->getNumTessFaces(dm);
totelem= me->totface;
origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
}
@@ -422,8 +422,8 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
int a, a1, a2, a0mul, a1mul, a2mul, totface;
int amax= from==PART_FROM_FACE ? 3 : 1;
- totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ totface=dm->getNumTessFaces(dm);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
for(a=0; a<amax; a++){
if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@ -432,7 +432,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);
@@ -645,7 +645,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
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:
@@ -665,7 +665,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
if(from==PART_FROM_VOLUME){
MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
- tot=dm->getNumFaces(dm);
+ tot=dm->getNumTessFaces(dm);
psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0);
@@ -677,7 +677,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
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 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
return;
}
- mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
+ mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
randu= rng_getFloat(thread->rng);
randv= rng_getFloat(thread->rng);
@@ -1088,7 +1088,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
break;
case PART_FROM_VOLUME:
case PART_FROM_FACE:
- tot = dm->getNumFaces(dm);
+ tot = dm->getNumTessFaces(dm);
break;
case PART_FROM_PARTICLE:
if(psys->target_ob)
@@ -1148,7 +1148,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
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]);
@@ -1217,7 +1217,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
}
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) {
@@ -1292,7 +1292,7 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
}
else {
if(dm->numFaceData)
- COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
}
if(COMPARE_ORIG_INDEX) {
@@ -2509,8 +2509,8 @@ int psys_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos
VECCOPY(p_max,pa_minmax+3);
}
- totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ totface=dm->getNumTessFaces(dm);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
mvert=dm->getVertDataArray(dm,CD_MVERT);
/* lets intersect the faces */
@@ -2985,7 +2985,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
}
if(!dm) {
- dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0);
+ dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0);
DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index efb7db04029..92c586f0001 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/smoke.c b/source/blender/blenkernel/intern/smoke.c
index fbc052db6f3..a52a98a1969 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -291,7 +291,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
if(!smd->coll->bvhtree)
{
- smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
+ smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
}
return 1;
}
@@ -302,7 +302,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive
static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
{
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
int i = 0, divs = 0;
int *tridivs = NULL;
float cell_len = 1.0 / 50.0; // for res = 50
@@ -310,16 +310,16 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
int quads = 0, facecounter = 0;
// count quads
- for(i = 0; i < dm->getNumFaces(dm); i++)
+ for(i = 0; i < dm->getNumTessFaces(dm); i++)
{
if(mface[i].v4)
quads++;
}
- calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len);
+ calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len);
// count triangle divisions
- for(i = 0; i < dm->getNumFaces(dm) + quads; i++)
+ for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
{
divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
}
@@ -336,7 +336,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
VECCOPY(&scs->points[i * 3], tmpvec);
}
- for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++)
+ for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
{
int again = 0;
do
@@ -1128,7 +1128,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm);
- smd->coll->dm = CDDM_copy(dm);
+ smd->coll->dm = CDDM_copy(dm, 1);
// rigid movement support
Mat4CpyMat4(smd->coll->mat_old, smd->coll->mat);
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 089f2a5ebfb..dfefc79af9d 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -69,6 +69,7 @@ variables on the UI for now
#include "BLI_arithb.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
+#include "BLI_cellalloc.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
@@ -245,11 +246,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;
@@ -278,7 +279,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");
@@ -341,10 +342,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..782da0f5c10 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -51,6 +51,7 @@
#include "BKE_multires.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
+#include "BKE_tessmesh.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
@@ -58,6 +59,8 @@
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BLI_edgehash.h"
+#include "PIL_time.h"
+#include "BLI_array.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -76,42 +79,50 @@ typedef struct _VertData {
struct CCGDerivedMesh {
DerivedMesh dm;
- CCGSubSurf *ss;
+ CSubSurf *ss;
int drawInteriorEdges, useSubsurfUv;
- struct {int startVert; CCGVert *vert;} *vertMap;
- struct {int startVert; int startEdge; CCGEdge *edge;} *edgeMap;
+ struct {int startVert; CCVert *vert;} *vertMap;
+ struct {int startVert; int startEdge; CCEdge *edge;} *edgeMap;
struct {int startVert; int startEdge;
- int startFace; CCGFace *face;} *faceMap;
+ int startFace; CCFace *face;} *faceMap;
+ /*maps final faces to faceMap faces*/
+ int *reverseFaceMap;
+
+ EdgeHash *ehash;
};
typedef struct CCGDerivedMesh CCGDerivedMesh;
-static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
-static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
-static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
+static int cgdm_getVertMapIndex(CSubSurf *ss, CCVert *v);
+static int cgdm_getEdgeMapIndex(CSubSurf *ss, CCEdge *e);
+static int cgdm_getFaceMapIndex(CSubSurf *ss, CCFace *f);
+static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss,
+ int drawInteriorEdges,
+ int useSubsurfUv,
+ DerivedMesh *dm);
///
-static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
+static void *arena_alloc(CCAllocHDL a, int numBytes) {
return BLI_memarena_alloc(a, numBytes);
}
-static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
+static void *arena_realloc(CCAllocHDL a, void *ptr, int newSize, int oldSize) {
void *p2 = BLI_memarena_alloc(a, newSize);
if (ptr) {
memcpy(p2, ptr, oldSize);
}
return p2;
}
-static void arena_free(CCGAllocatorHDL a, void *ptr) {
+static void arena_free(CCAllocHDL a, void *ptr) {
}
-static void arena_release(CCGAllocatorHDL a) {
+static void arena_release(CCAllocHDL a) {
BLI_memarena_free(a);
}
-static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useFlatSubdiv) {
+static CSubSurf *_getSubSurf(CSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int useFlatSubdiv) {
CCGMeshIFC ifc;
- CCGSubSurf *ccgSS;
+ CSubSurf *ccgSS;
/* subdivLevels==0 is not allowed */
subdivLevels = MAX2(subdivLevels, 1);
@@ -120,12 +131,12 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin
int oldUseAging;
useAging = !!useAging;
- ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
+ CCS_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
if (oldUseAging!=useAging) {
- ccgSubSurf_free(prevSS);
+ CCS_free(prevSS);
} else {
- ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
+ CCS_setSubdivisionLevels(prevSS, subdivLevels);
return prevSS;
}
@@ -140,33 +151,33 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin
if (useArena) {
CCGAllocatorIFC allocatorIFC;
- CCGAllocatorHDL allocator = BLI_memarena_new((1<<16));
+ CCAllocHDL allocator = BLI_memarena_new((1<<16));
allocatorIFC.alloc = arena_alloc;
allocatorIFC.realloc = arena_realloc;
allocatorIFC.free = arena_free;
allocatorIFC.release = arena_release;
- ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
+ ccgSS = CCS_new(&ifc, subdivLevels, &allocatorIFC, allocator);
} else {
- ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
+ ccgSS = CCS_new(&ifc, subdivLevels, NULL, NULL);
}
if (useAging) {
- ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
+ CCS_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
}
- ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no));
+ CCS_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no));
return ccgSS;
}
-static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
- CCGVert *v0 = ccgSubSurf_getEdgeVert0(e);
- CCGVert *v1 = ccgSubSurf_getEdgeVert1(e);
- int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
- int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
- int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
+static int getEdgeIndex(CSubSurf *ss, CCEdge *e, int x, int edgeSize) {
+ CCVert *v0 = CCS_getEdgeVert0(e);
+ CCVert *v1 = CCS_getEdgeVert1(e);
+ int v0idx = *((int*) CCS_getVertUserData(ss, v0));
+ int v1idx = *((int*) CCS_getVertUserData(ss, v1));
+ int edgeBase = *((int*) CCS_getEdgeUserData(ss, e));
if (x==0) {
return v0idx;
@@ -176,27 +187,28 @@ static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
return edgeBase + x-1;
}
}
-static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
- int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+BM_INLINE int getFaceIndex(CSubSurf *ss, CCFace *f, int S, int x, int y, int edgeSize, int gridSize) {
+ int faceBase = *((int*) CCS_getFaceUserData(ss, f));
+ int numVerts = CCS_getFaceNumVerts(f);
if (x==gridSize-1 && y==gridSize-1) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
- return *((int*) ccgSubSurf_getVertUserData(ss, v));
+ CCVert *v = CCS_getFaceVert(ss, f, S);
+ return *((int*) CCS_getVertUserData(ss, v));
} else if (x==gridSize-1) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
- CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
- int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
- if (v==ccgSubSurf_getEdgeVert0(e)) {
+ CCVert *v = CCS_getFaceVert(ss, f, S);
+ CCEdge *e = CCS_getFaceEdge(ss, f, S);
+ int edgeBase = *((int*) CCS_getEdgeUserData(ss, e));
+ if (v==CCS_getEdgeVert0(e)) {
return edgeBase + (gridSize-1-y)-1;
} else {
return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
}
} else if (y==gridSize-1) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
- CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
- int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
- if (v==ccgSubSurf_getEdgeVert0(e)) {
+ CCVert *v = CCS_getFaceVert(ss, f, S);
+ CCEdge *e = CCS_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
+ int edgeBase = *((int*) CCS_getEdgeUserData(ss, e));
+ if (v==CCS_getEdgeVert0(e)) {
return edgeBase + (gridSize-1-x)-1;
} else {
return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
@@ -213,7 +225,7 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg
}
}
-static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
+static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCVertHDL *fverts) {
unsigned int *fv = &mf->v1;
UvMapVert *v, *nv;
int j, nverts= mf->v4? 4: 3;
@@ -230,25 +242,26 @@ 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);
+static int ss_sync_from_uv(CSubSurf *ss, CSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
+#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;
float limit[2];
- CCGVertHDL fverts[4];
+ CCVertHDL fverts[4];
EdgeHash *ehash;
- float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
+ float creaseFactor = (float)CCS_getSubdivisionLevels(ss);
limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
if (!vmap)
return 0;
- ccgSubSurf_initFullSync(ss);
+ CCS_initFullSync(ss);
/* create vertices */
for (i=0; i<totvert; i++) {
@@ -263,15 +276,15 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
if (v->separate) {
- CCGVert *ssv;
- CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
+ CCVert *ssv;
+ CCVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
float uv[3];
uv[0]= (tface+v->f)->uv[v->tfindex][0];
uv[1]= (tface+v->f)->uv[v->tfindex][1];
uv[2]= 0.0f;
- ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
+ CCS_syncVert(ss, vhdl, uv, seam, &ssv);
}
}
}
@@ -282,7 +295,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
for (i=0; i<totface; i++) {
MFace *mf = &((MFace*) mface)[i];
int nverts= mf->v4? 4: 3;
- CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
+ CCFace *origf= CCS_getFace(origss, SET_INT_IN_POINTER(i));
unsigned int *fv = &mf->v1;
get_face_uv_map_vert(vmap, mf, i, fverts);
@@ -294,16 +307,16 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
MVert *mv1 = mvert + *(fv+((j+1)%nverts));
if (!BLI_edgehash_haskey(ehash, v0, v1)) {
- CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
- CCGEdgeHDL ehdl= SET_INT_IN_POINTER(i*4 + j);
+ CCEdge *e, *orige= CCS_getFaceEdge(origss, origf, j);
+ CCEdgeHDL ehdl= SET_INT_IN_POINTER(i*4 + j);
float crease;
if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
crease = creaseFactor;
else
- crease = ccgSubSurf_getEdgeCrease(orige);
+ crease = CCS_getEdgeCrease(orige);
- ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
+ CCS_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
BLI_edgehash_insert(ehash, v0, v1, NULL);
}
}
@@ -315,24 +328,25 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
for (i=0; i<totface; i++) {
MFace *mf = &((MFace*) mface)[i];
int nverts= mf->v4? 4: 3;
- CCGFace *f;
+ CCFace *f;
get_face_uv_map_vert(vmap, mf, i, fverts);
- ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
+ CCS_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
}
free_uv_vert_map(vmap);
- ccgSubSurf_processSync(ss);
+ CCS_processSync(ss);
+#endif
return 1;
}
-static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
+static void set_subsurf_uv(CSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
{
- CCGSubSurf *uvss;
- CCGFace **faceMap;
+ CSubSurf *uvss;
+ CCFace **faceMap;
MTFace *tf;
- CCGFaceIterator *fi;
+ CCFaceIterator *fi;
int index, gridSize, gridFaces, edgeSize, totface, x, y, S;
MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n);
MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
@@ -341,38 +355,38 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
return;
/* create a CCGSubsurf from uv's */
- uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
+ uvss = _getSubSurf(NULL, CCS_getSubdivisionLevels(ss), 0, 1, 0);
if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) {
- ccgSubSurf_free(uvss);
+ CCS_free(uvss);
return;
}
/* get some info from CCGSubsurf */
- totface = ccgSubSurf_getNumFaces(uvss);
- edgeSize = ccgSubSurf_getEdgeSize(uvss);
- gridSize = ccgSubSurf_getGridSize(uvss);
+ totface = CCS_getNumFaces(uvss);
+ edgeSize = CCS_getEdgeSize(uvss);
+ gridSize = CCS_getGridSize(uvss);
gridFaces = gridSize - 1;
- /* make a map from original faces to CCGFaces */
+ /* make a map from original faces to CCFaces */
faceMap = MEM_mallocN(totface*sizeof(*faceMap), "facemapuv");
- fi = ccgSubSurf_getFaceIterator(uvss);
- for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(uvss, f))] = f;
+ fi = CCS_getFaceIterator(uvss);
+ for(; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ faceMap[GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(uvss, f))] = f;
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
/* load coordinates from uvss into tface */
tf= tface;
for(index = 0; index < totface; index++) {
- CCGFace *f = faceMap[index];
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = faceMap[index];
+ int numVerts = CCS_getFaceNumVerts(f);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData= ccgSubSurf_getFaceGridDataArray(uvss, f, S);
+ VertData *faceGridData= CCS_getFaceGridDataArray(uvss, f, S);
for(y = 0; y < gridFaces; y++) {
for(x = 0; x < gridFaces; x++) {
@@ -392,20 +406,20 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
}
}
- ccgSubSurf_free(uvss);
+ CCS_free(uvss);
MEM_freeN(faceMap);
}
#if 0
-static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditmesh, DispListMesh *dlm, MEdge *medge, MTFace *tface)
+static unsigned int ss_getEdgeFlags(CSubSurf *ss, CCEdge *e, int ssFromEditmesh, DispListMesh *dlm, MEdge *medge, MTFace *tface)
{
unsigned int flags = 0;
- int N = ccgSubSurf_getEdgeNumFaces(e);
+ int N = CCS_getEdgeNumFaces(e);
if (!N) flags |= ME_LOOSEEDGE;
if (ssFromEditmesh) {
- EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(e);
+ EditEdge *eed = CCS_getEdgeEdgeHandle(e);
flags |= ME_EDGEDRAW|ME_EDGERENDER;
if (eed->seam) {
@@ -427,7 +441,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,75 +485,167 @@ static void calc_ss_weights(int gridFaces,
}
}
-static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
+/* face weighting */
+typedef struct FaceVertWeightEntry {
+ FaceVertWeight *weight;
+ float *w;
+ int valid;
+} FaceVertWeightEntry;
+
+typedef struct WeightTable {
+ FaceVertWeightEntry *weight_table;
+ int len;
+} WeightTable;
+
+static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
+{
+ int x, y, i, j;
+ float *w, w1, w2, w4, fac, fac2, fx, fy;
+
+ if (wtable->len <= faceLen) {
+ void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2");
+
+ if (wtable->len) {
+ 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) {
+ wtable->weight_table[faceLen].valid = 1;
+ wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float)*faceLen*faceLen*(gridCuts+2)*(gridCuts+2), "weight table alloc");
+ fac = 1.0 / (float)faceLen;
+
+ for (i=0; i<faceLen; i++) {
+ for (x=0; x<gridCuts+2; x++) {
+ for (y=0; y<gridCuts+2; y++) {
+ fx = 0.5f - (float)x / (float)(gridCuts+1) / 2.0f;
+ fy = 0.5f - (float)y / (float)(gridCuts+1) / 2.0f;
+
+ fac2 = faceLen - 4;
+ w1 = (1.0f - fx) * (1.0f - fy) + (-fac2*fx*fy*fac);
+ w2 = (1.0f - fx + fac2*fx*-fac) * (fy);
+ w4 = (fx) * (1.0 - fy + -fac2*fy*fac);
+
+ fac2 = 1.0 - (w1+w2+w4);
+ fac2 = fac2 / (float)(faceLen-3);
+ for (j=0; j<faceLen; j++)
+ w[j] = fac2;
+
+ w[i] = w1;
+ w[(i-1+faceLen)%faceLen] = w2;
+ w[(i+1)%faceLen] = w4;
+
+ w += faceLen;
+ }
+ }
+ }
+ }
+
+ return wtable->weight_table[faceLen].w;
+}
+
+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].w);
+ }
+}
+
+static DerivedMesh *ss_to_cdderivedmesh(CSubSurf *ss, int ssFromEditmesh,
int drawInteriorEdges, int useSubsurfUv,
DerivedMesh *dm, MultiresSubsurf *ms)
{
+ DerivedMesh *cgdm, *result;
+ double curt = PIL_check_seconds_timer();
+
+ cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
+ result = CDDM_copy(cgdm, 1);
+
+ printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt);
+
+ cgdm->needsFree = 1;
+ cgdm->release(cgdm);
+
+ CDDM_calc_normals(result);
+
+ return result;
+#if 0
DerivedMesh *result;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
int gridFaces = gridSize - 1;
int edgeBase, faceBase;
int i, j, k, S, x, y, index;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
- CCGFace **faceMap2;
- CCGEdge **edgeMap2;
- CCGVert **vertMap2;
+ int *vertIdx = NULL;
+ BLI_array_declare(vertIdx);
+ CCVertIterator *vi;
+ CCEdgeIterator *ei;
+ CCFaceIterator *fi;
+ CCFace **faceMap2;
+ CCEdge **edgeMap2;
+ CCVert **vertMap2;
int totvert, totedge, totface;
MVert *mvert;
MEdge *med;
+ float *w = NULL;
+ WeightTable wtable;
+ BLI_array_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);
+ totvert = CCS_getNumVerts(ss);
vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
- vi = ccgSubSurf_getVertIterator(ss);
- for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ vi = CCS_getVertIterator(ss);
+ for(; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
- vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
+ vertMap2[GET_INT_FROM_POINTER(CCS_getVertVertHandle(v))] = v;
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
- totedge = ccgSubSurf_getNumEdges(ss);
+ totedge = CCS_getNumEdges(ss);
edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap");
- ei = ccgSubSurf_getEdgeIterator(ss);
- for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ ei = CCS_getEdgeIterator(ss);
+ for(; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
- edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
+ edgeMap2[GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e))] = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
- fi = ccgSubSurf_getFaceIterator(ss);
- for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ fi = CCS_getFaceIterator(ss);
+ for(; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
- faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
+ faceMap2[GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f))] = f;
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
if(ms) {
- result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss),
- ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ result = MultiresDM_new(ms, dm, CCS_getNumFinalVerts(ss),
+ CCS_getNumFinalEdges(ss),
+ CCS_getNumFinalFaces(ss), 0, 0);
}
else {
if(dm) {
- result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
- ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ result = CDDM_from_template(dm, CCS_getNumFinalVerts(ss),
+ CCS_getNumFinalEdges(ss),
+ CCS_getNumFinalFaces(ss), 0, 0);
} else {
- result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
- ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
+ result = CDDM_new(CCS_getNumFinalVerts(ss),
+ CCS_getNumFinalEdges(ss),
+ CCS_getNumFinalFaces(ss), 0, 0);
}
}
@@ -549,38 +655,49 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
origIndex = result->getVertData(result, 0, CD_ORIGINDEX);
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];
+ CCFace *f = faceMap2[index];
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
+ FaceVertWeight *weight = 0;//get_ss_weights(&wtable, gridFaces-1, numVerts);
+
+ BLI_array_empty(vertIdx);
for(S = 0; S < numVerts; S++) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ CCVert *v = CCS_getFaceVert(ss, f, S);
+ BLI_array_growone(vertIdx);
- vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ vertIdx[S] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
}
+#if 0
DM_interp_vert_data(dm, result, vertIdx, weight[0][0], numVerts, i);
- VecCopyf(mvert->co, ccgSubSurf_getFaceCenterData(f));
+#endif
+ VecCopyf(mvert->co, CCS_getFaceCenterData(f));
*origIndex = ORIGINDEX_NONE;
++mvert;
++origIndex;
i++;
+ BLI_array_empty(w);
+ for (x=0; x<numVerts; x++) {
+ BLI_array_growone(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];
+#if 0
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);
+#endif
VecCopyf(mvert->co,
- ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ CCS_getFaceGridEdgeData(ss, f, S, x));
*origIndex = ORIGINDEX_NONE;
++mvert;
@@ -588,22 +705,29 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
i++;
}
}
+
+ BLI_array_empty(w);
+ for (x=0; x<numVerts; x++) {
+ BLI_array_growone(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];
+#if 0
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);
+#endif
+
VecCopyf(mvert->co,
- ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ CCS_getFaceGridData(ss, f, S, x, y));
*origIndex = ORIGINDEX_NONE;
++mvert;
++origIndex;
@@ -611,50 +735,51 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
}
}
-
- *((int*)ccgSubSurf_getFaceUserData(ss, f)) = faceBase;
+ *((int*)CCS_getFaceUserData(ss, f)) = faceBase;
faceBase += 1 + numVerts * ((gridSize-2) + (gridSize-2) * (gridSize-2));
}
edgeBase = i;
for(index = 0; index < totedge; index++) {
- CCGEdge *e = edgeMap2[index];
+ CCEdge *e = edgeMap2[index];
int x;
int vertIdx[2];
- CCGVert *v;
- v = ccgSubSurf_getEdgeVert0(e);
- vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
- v = ccgSubSurf_getEdgeVert1(e);
- vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
-
+ CCVert *v;
+ v = CCS_getEdgeVert0(e);
+ vertIdx[0] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+ v = CCS_getEdgeVert1(e);
+ vertIdx[1] = GET_INT_FROM_POINTER(CCS_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);
- VecCopyf(mvert->co, ccgSubSurf_getEdgeData(ss, e, x));
+ 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, CCS_getEdgeData(ss, e, x));
*origIndex = ORIGINDEX_NONE;
++mvert;
++origIndex;
i++;
}
- *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase;
+ *((int*)CCS_getEdgeUserData(ss, e)) = edgeBase;
edgeBase += edgeSize-2;
}
for(index = 0; index < totvert; index++) {
- CCGVert *v = vertMap2[index];
+ CCVert *v = vertMap2[index];
int vertIdx;
- vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ vertIdx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
DM_copy_vert_data(dm, result, vertIdx, i, 1);
- VecCopyf(mvert->co, ccgSubSurf_getVertData(ss, v));
+ VecCopyf(mvert->co, CCS_getVertData(ss, v));
- *((int*)ccgSubSurf_getVertUserData(ss, v)) = i;
- *origIndex = ccgDM_getVertMapIndex(ss, v);
+ *((int*)CCS_getVertUserData(ss, v)) = i;
+ *origIndex = cgdm_getVertMapIndex(ss, v);
++mvert;
++origIndex;
i++;
@@ -666,8 +791,8 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
origIndex = result->getEdgeData(result, 0, CD_ORIGINDEX);
for(index = 0; index < totface; index++) {
- CCGFace *f = faceMap2[index];
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = faceMap2[index];
+ int numVerts = CCS_getFaceNumVerts(f);
for(k = 0; k < numVerts; k++) {
for(x = 0; x < gridFaces; x++) {
@@ -707,12 +832,12 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
for(index = 0; index < totedge; index++) {
- CCGEdge *e = edgeMap2[index];
+ CCEdge *e = edgeMap2[index];
unsigned int flags = 0;
char bweight = 0;
- int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
+ int edgeIdx = GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e));
- if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
+ if(!CCS_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
if(edgeIdx != -1 && dm) {
@@ -728,7 +853,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
med->flag = flags;
med->bweight = bweight;
- *origIndex = ccgDM_getEdgeMapIndex(ss, e);
+ *origIndex = cgdm_getEdgeMapIndex(ss, e);
++med;
++origIndex;
i++;
@@ -737,32 +862,32 @@ 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];
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = faceMap2[index];
+ int numVerts = CCS_getFaceNumVerts(f);
int mat_nr;
int flag;
- int mapIndex = ccgDM_getFaceMapIndex(ss, f);
- int faceIdx = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+ int mapIndex = cgdm_getFaceMapIndex(ss, f);
+ int faceIdx = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
if(!ssFromEditmesh) {
MFace origMFace;
- dm->getFace(dm, faceIdx, &origMFace);
+ dm->getTessFace(dm, faceIdx, &origMFace);
mat_nr = origMFace.mat_nr;
flag = origMFace.flag;
} else {
- EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
+ BMFace *ef = CCS_getFaceFaceHandle(ss, f);
mat_nr = ef->mat_nr;
- flag = ef->flag;
+ flag = BMFlags_To_MEFlags(ef);
}
for(S = 0; S < numVerts; S++) {
- FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
-
+ FaceVertWeight *weight = 0;//get_ss_weights(&wtable, gridFaces-1, 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 +900,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;
@@ -788,11 +913,12 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
w[j][nextS] = (*weight)[j][2];
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 +933,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);
+
+ BLI_array_free(vertIdx);
if(useSubsurfUv) {
CustomData *fdata = &result->faceData;
@@ -821,79 +948,89 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
}
CDDM_calc_normals(result);
-
+ CDDM_tessfaces_to_faces(result);
+
+ BLI_array_free(w);
return result;
+#endif
}
-static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
+static void ss_sync_from_derivedmesh(CSubSurf *ss, DerivedMesh *dm,
float (*vertexCos)[3], int useFlatSubdiv)
{
- float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
- CCGVertHDL fVerts[4];
+ float creaseFactor = (float) CCS_getSubdivisionLevels(ss);
+ CCVertHDL *fVerts = NULL;
+ BLI_array_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);
+ CCS_initFullSync(ss);
mv = mvert;
index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
for(i = 0; i < totvert; i++, mv++, index++) {
- CCGVert *v;
+ CCVert *v;
if(vertexCos) {
- ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
+ CCS_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
} else {
- ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
+ CCS_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
}
- ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = *index;
+ ((int*)CCS_getVertUserData(ss, v))[1] = *index;
}
me = medge;
index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
for(i = 0; i < totedge; i++, me++, index++) {
- CCGEdge *e;
+ CCEdge *e;
float crease;
crease = useFlatSubdiv ? creaseFactor :
me->crease * creaseFactor / 255.0f;
- ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1),
+ CCS_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1),
SET_INT_IN_POINTER(me->v2), crease, &e);
- ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = *index;
+ ((int*)CCS_getEdgeUserData(ss, e))[1] = *index;
}
+
+ fiter = dm->newFaceIter(dm);
+ for (i=0; !fiter->done; fiter->step(fiter), i++) {
+ CCFace *f;
+ BLI_array_empty(fVerts);
- mf = mface;
- index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
- for (i = 0; i < totface; i++, mf++, index++) {
- CCGFace *f;
+ index = (int*) fiter->getCDData(fiter, CD_ORIGINDEX, -1);
+ liter = fiter->getLoopsIter(fiter);
- 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);
+ for (; !liter->done; liter->step(liter)) {
+ BLI_array_growone(fVerts);
+ fVerts[BLI_array_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(CCS_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;
}
@@ -901,59 +1038,62 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
return;
}
- ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = *index;
+ ((int*)CCS_getFaceUserData(ss, f))[1] = *index;
}
+ fiter->free(fiter);
- ccgSubSurf_processSync(ss);
+ CCS_processSync(ss);
+
+ BLI_array_free(fVerts);
}
/***/
-static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) {
- return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
+static int cgdm_getVertMapIndex(CSubSurf *ss, CCVert *v) {
+ return ((int*) CCS_getVertUserData(ss, v))[1];
}
-static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) {
- return ((int*) ccgSubSurf_getEdgeUserData(ss, e))[1];
+static int cgdm_getEdgeMapIndex(CSubSurf *ss, CCEdge *e) {
+ return ((int*) CCS_getEdgeUserData(ss, e))[1];
}
-static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) {
- return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
+static int cgdm_getFaceMapIndex(CSubSurf *ss, CCFace *f) {
+ return ((int*) CCS_getFaceUserData(ss, f))[1];
}
-static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
- int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
+static void cgdm_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCVertIterator *vi = CCS_getVertIterator(ss);
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
+ int i, edgeSize = CCS_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
- if (!ccgSubSurf_getNumVerts(ss))
+ if (!CCS_getNumVerts(ss))
min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
- for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
- float *co = ccgSubSurf_getVertData(ss, v);
+ for (; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
+ float *co = CCS_getVertData(ss, v);
DO_MINMAX(co, min_r, max_r);
}
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
for (i=0; i<edgeSize; i++)
DO_MINMAX(edgeData[i].co, min_r, max_r);
}
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
for (y=0; y<gridSize; y++)
for (x=0; x<gridSize; x++)
@@ -961,52 +1101,52 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
}
}
- ccgFaceIterator_free(fi);
- ccgEdgeIterator_free(ei);
- ccgVertIterator_free(vi);
+ CCFIter_free(fi);
+ CCEIter_free(ei);
+ CCVIter_free(vi);
}
-static int ccgDM_getNumVerts(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumVerts(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
+ return CCS_getNumFinalVerts(cgdm->ss);
}
-static int ccgDM_getNumEdges(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumEdges(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
+ return CCS_getNumFinalEdges(cgdm->ss);
}
-static int ccgDM_getNumFaces(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumTessFaces(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
+ return CCS_getNumFinalFaces(cgdm->ss);
}
-static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
+static void cgdm_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
int i;
memset(mv, 0, sizeof(*mv));
- if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
+ if((vertNum < cgdm->edgeMap[0].startVert) && (CCS_getNumFaces(ss) > 0)) {
/* this vert comes from face data */
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
- CCGFace *f;
+ int lastface = CCS_getNumFaces(ss) - 1;
+ CCFace *f;
int x, y, grid, numVerts;
int offset;
- int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridSize = CCS_getGridSize(ss);
int gridSideVerts;
int gridInternalVerts;
int gridSideEnd;
int gridInternalEnd;
i = 0;
- while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
+ while(i < lastface && vertNum >= cgdm->faceMap[i + 1].startVert)
++i;
- f = ccgdm->faceMap[i].face;
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ f = cgdm->faceMap[i].face;
+ numVerts = CCS_getFaceNumVerts(f);
gridSideVerts = gridSize - 2;
gridInternalVerts = gridSideVerts * gridSideVerts;
@@ -1014,76 +1154,76 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
gridSideEnd = 1 + numVerts * gridSideVerts;
gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
- offset = vertNum - ccgdm->faceMap[i].startVert;
+ offset = vertNum - cgdm->faceMap[i].startVert;
if(offset < 1) {
- VecCopyf(mv->co, ccgSubSurf_getFaceCenterData(f));
+ VecCopyf(mv->co, CCS_getFaceCenterData(f));
} else if(offset < gridSideEnd) {
offset -= 1;
grid = offset / gridSideVerts;
x = offset % gridSideVerts + 1;
- VecCopyf(mv->co, ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x));
+ VecCopyf(mv->co, CCS_getFaceGridEdgeData(ss, f, grid, x));
} else if(offset < gridInternalEnd) {
offset -= gridSideEnd;
grid = offset / gridInternalVerts;
offset %= gridInternalVerts;
y = offset / gridSideVerts + 1;
x = offset % gridSideVerts + 1;
- VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y));
+ VecCopyf(mv->co, CCS_getFaceGridData(ss, f, grid, x, y));
}
- } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
+ } else if((vertNum < cgdm->vertMap[0].startVert) && (CCS_getNumEdges(ss) > 0)) {
/* this vert comes from edge data */
- CCGEdge *e;
- int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
+ CCEdge *e;
+ int lastedge = CCS_getNumEdges(ss) - 1;
int x;
i = 0;
- while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
+ while(i < lastedge && vertNum >= cgdm->edgeMap[i + 1].startVert)
++i;
- e = ccgdm->edgeMap[i].edge;
+ e = cgdm->edgeMap[i].edge;
- x = vertNum - ccgdm->edgeMap[i].startVert + 1;
- VecCopyf(mv->co, ccgSubSurf_getEdgeData(ss, e, x));
+ x = vertNum - cgdm->edgeMap[i].startVert + 1;
+ VecCopyf(mv->co, CCS_getEdgeData(ss, e, x));
} else {
/* this vert comes from vert data */
- CCGVert *v;
- i = vertNum - ccgdm->vertMap[0].startVert;
+ CCVert *v;
+ i = vertNum - cgdm->vertMap[0].startVert;
- v = ccgdm->vertMap[i].vert;
- VecCopyf(mv->co, ccgSubSurf_getVertData(ss, v));
+ v = cgdm->vertMap[i].vert;
+ VecCopyf(mv->co, CCS_getVertData(ss, v));
}
}
-static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
+static void cgdm_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
int i;
memset(med, 0, sizeof(*med));
- if(edgeNum < ccgdm->edgeMap[0].startEdge) {
+ if(edgeNum < cgdm->edgeMap[0].startEdge) {
/* this edge comes from face data */
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
- CCGFace *f;
+ int lastface = CCS_getNumFaces(ss) - 1;
+ CCFace *f;
int x, y, grid, numVerts;
int offset;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int gridSideEdges;
int gridInternalEdges;
i = 0;
- while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
+ while(i < lastface && edgeNum >= cgdm->faceMap[i + 1].startEdge)
++i;
- f = ccgdm->faceMap[i].face;
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ f = cgdm->faceMap[i].face;
+ numVerts = CCS_getFaceNumVerts(f);
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
- offset = edgeNum - ccgdm->faceMap[i].startEdge;
+ offset = edgeNum - cgdm->faceMap[i].startEdge;
grid = offset / (gridSideEdges + gridInternalEdges);
offset %= (gridSideEdges + gridInternalEdges);
@@ -1105,18 +1245,18 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
}
} else {
/* this vert comes from edge data */
- CCGEdge *e;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ CCEdge *e;
+ int edgeSize = CCS_getEdgeSize(ss);
int x, *edgeFlag;
unsigned int flags = 0;
- i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
+ i = (edgeNum - cgdm->edgeMap[0].startEdge) / (edgeSize - 1);
- e = ccgdm->edgeMap[i].edge;
+ e = cgdm->edgeMap[i].edge;
- if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
+ if(!CCS_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
- x = edgeNum - ccgdm->edgeMap[i].startEdge;
+ x = edgeNum - cgdm->edgeMap[i].startEdge;
med->v1 = getEdgeIndex(ss, e, x, edgeSize);
med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
@@ -1132,33 +1272,33 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
}
}
-static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
+static void cgdm_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ int gridSize = CCS_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int gridSideEdges = gridSize - 1;
int gridFaces = gridSideEdges * gridSideEdges;
int i;
- CCGFace *f;
+ CCFace *f;
int numVerts;
int offset;
int grid;
int x, y;
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
+ int lastface = CCS_getNumFaces(ss) - 1;
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
memset(mf, 0, sizeof(*mf));
+ if (faceNum >= cgdm->dm.numFaceData)
+ return;
- i = 0;
- while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
- ++i;
+ i = cgdm->reverseFaceMap[faceNum];
- f = ccgdm->faceMap[i].face;
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ f = cgdm->faceMap[i].face;
+ numVerts = CCS_getFaceNumVerts(f);
- offset = faceNum - ccgdm->faceMap[i].startFace;
+ offset = faceNum - cgdm->faceMap[i].startFace;
grid = offset / gridFaces;
offset %= gridFaces;
y = offset / gridSideEdges;
@@ -1169,31 +1309,34 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
mf->v3 = getFaceIndex(ss, f, grid, x+1, y+1, edgeSize, gridSize);
mf->v4 = getFaceIndex(ss, f, grid, x+1, y+0, edgeSize, gridSize);
- if(faceFlags) mf->flag = faceFlags[i*4];
- else mf->flag = ME_SMOOTH;
+ if(faceFlags) {
+ mf->flag = faceFlags[i*4];
+ mf->mat_nr = faceFlags[i*4+1];
+ } else
+ mf->flag = ME_SMOOTH;
}
-static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
+static void cgdm_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
int index;
int totvert, totedge, totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int i = 0;
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = cgdm->faceMap[index].face;
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
- VecCopyf(mvert[i++].co, ccgSubSurf_getFaceCenterData(f));
+ VecCopyf(mvert[i++].co, CCS_getFaceCenterData(f));
for(S = 0; S < numVerts; S++) {
for(x = 1; x < gridSize - 1; x++) {
VecCopyf(mvert[i++].co,
- ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ CCS_getFaceGridEdgeData(ss, f, S, x));
}
}
@@ -1201,53 +1344,53 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
for(y = 1; y < gridSize - 1; y++) {
for(x = 1; x < gridSize - 1; x++) {
VecCopyf(mvert[i++].co,
- ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ CCS_getFaceGridData(ss, f, S, x, y));
}
}
}
}
- totedge = ccgSubSurf_getNumEdges(ss);
+ totedge = CCS_getNumEdges(ss);
for(index = 0; index < totedge; index++) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
+ CCEdge *e = cgdm->edgeMap[index].edge;
int x;
for(x = 1; x < edgeSize - 1; x++) {
- VecCopyf(mvert[i++].co, ccgSubSurf_getEdgeData(ss, e, x));
+ VecCopyf(mvert[i++].co, CCS_getEdgeData(ss, e, x));
}
}
- totvert = ccgSubSurf_getNumVerts(ss);
+ totvert = CCS_getNumVerts(ss);
for(index = 0; index < totvert; index++) {
- CCGVert *v = ccgdm->vertMap[index].vert;
+ CCVert *v = cgdm->vertMap[index].vert;
- VecCopyf(mvert[i].co, ccgSubSurf_getVertData(ss, v));
+ VecCopyf(mvert[i].co, CCS_getVertData(ss, v));
i++;
}
}
-static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
+static void cgdm_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
int index;
int totedge, totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int i = 0;
int *edgeFlags = dm->getEdgeDataArray(dm, CD_FLAGS);
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = cgdm->faceMap[index].face;
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
for(S = 0; S < numVerts; S++) {
for(x = 0; x < gridSize - 1; x++) {
MEdge *med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
@@ -1259,7 +1402,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
MEdge *med;
med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, x, y,
edgeSize, gridSize);
@@ -1268,7 +1411,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
i++;
med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, y, x,
edgeSize, gridSize);
@@ -1280,14 +1423,14 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
}
}
- totedge = ccgSubSurf_getNumEdges(ss);
+ totedge = CCS_getNumEdges(ss);
for(index = 0; index < totedge; index++) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
+ CCEdge *e = cgdm->edgeMap[index].edge;
unsigned int flags = 0;
int x;
- int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
+ int edgeIdx = GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e));
- if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
+ if(!CCS_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
if(edgeFlags) {
if(edgeIdx != -1) {
@@ -1308,21 +1451,178 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
}
}
-static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
+struct cgdm_faceIter;
+
+typedef struct cgdm_loopIter {
+ DMLoopIter head;
+ int curloop;
+ int lindex; //loop index within the mesh, not the face
+ CCGDerivedMesh *cgdm;
+ struct cgdm_faceIter *fiter;
+} cgdm_loopIter;
+
+typedef struct cgdm_faceIter {
+ DMFaceIter head;
+ CCGDerivedMesh *cgdm;
+ MFace *mface, *mf;
+
+ cgdm_loopIter liter;
+ EdgeHash *ehash; /*edge map for populating loopiter->eindex*/
+} cgdm_faceIter;
+
+void cgdm_faceIterStep(void *self)
+{
+ cgdm_faceIter *fiter = self;
+
+ if (!fiter->cgdm || !fiter->cgdm->ss) {
+ fiter->head.done = 1;
+ return;
+ }
+
+ fiter->head.index++;
+
+ if (fiter->head.index >= CCS_getNumFinalFaces(fiter->cgdm->ss)) {
+ fiter->head.done = 1;
+ return;
+ };
+
+ fiter->mf++;
+
+ fiter->head.flags = fiter->mface->flag;
+ fiter->head.mat_nr = fiter->mface->mat_nr;
+ fiter->head.len = 4;
+}
+
+void *cgdm_faceIterCData(void *self, int type, int layer)
+{
+ cgdm_faceIter *fiter = self;
+
+ if (layer == -1)
+ return CustomData_get(&fiter->cgdm->dm.polyData, fiter->head.index, type);
+ else
+ return CustomData_get_n(&fiter->cgdm->dm.polyData, type, fiter->head.index, layer);
+}
+
+void cgdm_loopIterStep(void *self)
+{
+ cgdm_loopIter *liter = self;
+ MFace *mf = &liter->fiter->mface;
+ int i, v1, v2;
+
+ liter->head.index++;
+ i = liter->head.index;
+
+ if (liter->head.index >= 4) {
+ liter->head.done = 1;
+ return;
+ }
+
+ switch (i) {
+ case 0:
+ v1 = liter->fiter->mf->v1;
+ v2 = liter->fiter->mf->v2;
+ break;
+ case 1:
+ v1 = liter->fiter->mf->v2;
+ v2 = liter->fiter->mf->v3;
+ break;
+ case 2:
+ v1 = liter->fiter->mf->v3;
+ v2 = liter->fiter->mf->v4;
+ break;
+ case 3:
+ v1 = liter->fiter->mf->v4;
+ v2 = liter->fiter->mf->v1;
+ break;
+ }
+
+ liter->head.vindex = v1;
+ liter->head.eindex = GET_INT_FROM_POINTER(BLI_edgehash_lookup(liter->fiter->cgdm->ehash, v1, v2));
+ liter->lindex += 1;
+
+ cgdm_getFinalVert((DerivedMesh*)liter->cgdm, v1, &liter->head.v);
+}
+
+void *cgdm_loopIterGetVCData(void *self, int type, int layer)
+{
+ cgdm_loopIter *liter = self;
+
+ if (layer == -1)
+ return CustomData_get(&liter->cgdm->dm.vertData, liter->head.vindex, type);
+ else return CustomData_get_n(&liter->cgdm->dm.vertData, type, liter->head.vindex, layer);
+}
+
+void *cgdm_loopIterGetCData(void *self, int type, int layer)
+{
+ cgdm_loopIter *liter = self;
+
+ if (layer == -1)
+ return CustomData_get(&liter->cgdm->dm.loopData, liter->lindex, type);
+ else return CustomData_get_n(&liter->cgdm->dm.loopData, type, liter->lindex, layer);
+}
+
+DMLoopIter *cgdm_faceIterGetLIter(void *self)
+{
+ cgdm_faceIter *fiter = self;
+
+ fiter->liter.head.index = -1;
+ fiter->liter.head.done = 0;
+ fiter->liter.head.step(&fiter->liter);
+
+ return (DMLoopIter*) &fiter->liter;
+}
+
+void cgdm_faceIterFree(void *vfiter)
+{
+ cgdm_faceIter *fiter = vfiter;
+
+ MEM_freeN(fiter->mface);
+ MEM_freeN(fiter);
+}
+
+DMFaceIter *cgdm_newFaceIter(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ cgdm_faceIter *fiter = MEM_callocN(sizeof(cgdm_faceIter), "cgdm_faceIter");
+ MEdge medge;
+ int i, totedge = cgdm_getNumEdges(dm);
+
+ fiter->cgdm = dm;
+ fiter->liter.cgdm = dm;
+ fiter->mface = fiter->mf = dm->dupTessFaceArray(dm);
+ fiter->mf--;
+
+ fiter->head.free = cgdm_faceIterFree;
+ fiter->head.step = cgdm_faceIterStep;
+ fiter->head.index = -1;
+ fiter->head.getCDData = cgdm_faceIterCData;
+ fiter->head.getLoopsIter = cgdm_faceIterGetLIter;
+
+ fiter->liter.fiter = fiter;
+ fiter->liter.head.getLoopCDData = cgdm_loopIterGetCData;
+ fiter->liter.head.getVertCDData = cgdm_loopIterGetVCData;
+ fiter->liter.head.step = cgdm_loopIterStep;
+ fiter->liter.lindex = -1;
+
+ fiter->head.step(fiter);
+
+ return fiter;
+}
+
+static void cgdm_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
+{
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
int index;
int totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int i = 0;
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = cgdm->faceMap[index].face;
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
int mat_nr = 0;
int flag = ME_SMOOTH; /* assume face is smooth by default */
@@ -1349,114 +1649,114 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
}
}
-static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
+static void cgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ int edgeSize = CCS_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
int i;
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
- CCGFace **faceMap2;
- CCGEdge **edgeMap2;
- CCGVert **vertMap2;
+ CCVertIterator *vi;
+ CCEdgeIterator *ei;
+ CCFaceIterator *fi;
+ CCFace **faceMap2;
+ CCEdge **edgeMap2;
+ CCVert **vertMap2;
int index, totvert, totedge, totface;
- totvert = ccgSubSurf_getNumVerts(ss);
+ totvert = CCS_getNumVerts(ss);
vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
- vi = ccgSubSurf_getVertIterator(ss);
- for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ vi = CCS_getVertIterator(ss);
+ for (; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
- vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
+ vertMap2[GET_INT_FROM_POINTER(CCS_getVertVertHandle(v))] = v;
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
- totedge = ccgSubSurf_getNumEdges(ss);
+ totedge = CCS_getNumEdges(ss);
edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap");
- ei = ccgSubSurf_getEdgeIterator(ss);
- for (i=0; !ccgEdgeIterator_isStopped(ei); i++,ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ ei = CCS_getEdgeIterator(ss);
+ for (i=0; !CCEIter_isStopped(ei); i++,CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
- edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
+ edgeMap2[GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e))] = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
- fi = ccgSubSurf_getFaceIterator(ss);
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ fi = CCS_getFaceIterator(ss);
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
- faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
+ faceMap2[GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f))] = f;
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
i = 0;
for (index=0; index<totface; index++) {
- CCGFace *f = faceMap2[index];
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = faceMap2[index];
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
- VecCopyf(cos[i++], ccgSubSurf_getFaceCenterData(f));
+ VecCopyf(cos[i++], CCS_getFaceCenterData(f));
for (S=0; S<numVerts; S++) {
for (x=1; x<gridSize-1; x++) {
- VecCopyf(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ VecCopyf(cos[i++], CCS_getFaceGridEdgeData(ss, f, S, x));
}
}
for (S=0; S<numVerts; S++) {
for (y=1; y<gridSize-1; y++) {
for (x=1; x<gridSize-1; x++) {
- VecCopyf(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ VecCopyf(cos[i++], CCS_getFaceGridData(ss, f, S, x, y));
}
}
}
}
for (index=0; index<totedge; index++) {
- CCGEdge *e= edgeMap2[index];
+ CCEdge *e= edgeMap2[index];
int x;
for (x=1; x<edgeSize-1; x++) {
- VecCopyf(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
+ VecCopyf(cos[i++], CCS_getEdgeData(ss, e, x));
}
}
for (index=0; index<totvert; index++) {
- CCGVert *v = vertMap2[index];
- VecCopyf(cos[i++], ccgSubSurf_getVertData(ss, v));
+ CCVert *v = vertMap2[index];
+ VecCopyf(cos[i++], CCS_getVertData(ss, v));
}
MEM_freeN(vertMap2);
MEM_freeN(edgeMap2);
MEM_freeN(faceMap2);
}
-static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
+static void cgdm_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCVertIterator *vi = CCS_getVertIterator(cgdm->ss);
- for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
- VertData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
- int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
+ for (; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
+ VertData *vd = CCS_getVertData(cgdm->ss, v);
+ int index = cgdm_getVertMapIndex(cgdm->ss, v);
if (index!=-1)
func(userData, index, vd->co, vd->no, NULL);
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
}
-static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
+static void cgdm_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ int i, edgeSize = CCS_getEdgeSize(ss);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
- int index = ccgDM_getEdgeMapIndex(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
+ int index = cgdm_getEdgeMapIndex(ss, e);
if (index!=-1) {
for (i=0; i<edgeSize-1; i++)
@@ -1464,73 +1764,73 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData
}
}
- ccgEdgeIterator_free(ei);
+ CCEIter_free(ei);
}
-static void ccgDM_drawVerts(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+static void cgdm_drawVerts(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ int edgeSize = CCS_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
+ CCVertIterator *vi;
+ CCEdgeIterator *ei;
+ CCFaceIterator *fi;
glBegin(GL_POINTS);
- vi = ccgSubSurf_getVertIterator(ss);
- for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
- glVertex3fv(ccgSubSurf_getVertData(ss, v));
+ vi = CCS_getVertIterator(ss);
+ for (; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
+ glVertex3fv(CCS_getVertData(ss, v));
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
- ei = ccgSubSurf_getEdgeIterator(ss);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ ei = CCS_getEdgeIterator(ss);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
int x;
for (x=1; x<edgeSize-1; x++)
- glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
+ glVertex3fv(CCS_getEdgeData(ss, e, x));
}
- ccgEdgeIterator_free(ei);
+ CCEIter_free(ei);
- fi = ccgSubSurf_getFaceIterator(ss);
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ fi = CCS_getFaceIterator(ss);
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int x, y, S, numVerts = CCS_getFaceNumVerts(f);
- glVertex3fv(ccgSubSurf_getFaceCenterData(f));
+ glVertex3fv(CCS_getFaceCenterData(f));
for (S=0; S<numVerts; S++)
for (x=1; x<gridSize-1; x++)
- glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ glVertex3fv(CCS_getFaceGridEdgeData(ss, f, S, x));
for (S=0; S<numVerts; S++)
for (y=1; y<gridSize-1; y++)
for (x=1; x<gridSize-1; x++)
- glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ glVertex3fv(CCS_getFaceGridData(ss, f, S, x, y));
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
glEnd();
}
-static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
- int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
+static void cgdm_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
+ int i, edgeSize = CCS_getEdgeSize(ss);
+ int gridSize = CCS_getGridSize(ss);
int useAging;
- ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
+ CCS_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
- if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e))
+ if (!drawLooseEdges && !CCS_getEdgeNumFaces(e))
continue;
if (useAging && !(G.f&G_BACKBUFSEL)) {
- int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
+ int ageCol = 255-CCS_getEdgeAge(ss, e)*4;
glColor3ub(0, ageCol>0?ageCol:0, 0);
}
@@ -1546,13 +1846,13 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
glColor3ub(0, 0, 0);
}
- if (ccgdm->drawInteriorEdges) {
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ if (cgdm->drawInteriorEdges) {
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
glBegin(GL_LINE_STRIP);
for (x=0; x<gridSize; x++)
@@ -1574,20 +1874,20 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
}
}
- ccgFaceIterator_free(fi);
- ccgEdgeIterator_free(ei);
+ CCFIter_free(fi);
+ CCEIter_free(ei);
}
-static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
+static void cgdm_drawLooseEdges(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ int i, edgeSize = CCS_getEdgeSize(ss);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
- if (!ccgSubSurf_getEdgeNumFaces(e)) {
+ if (!CCS_getEdgeNumFaces(e)) {
glBegin(GL_LINE_STRIP);
for (i=0; i<edgeSize-1; i++) {
glVertex3fv(edgeData[i].co);
@@ -1597,10 +1897,10 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
}
}
- ccgEdgeIterator_free(ei);
+ CCEIter_free(ei);
}
-static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
+static void cgdm_glNormalFast(float *a, float *b, float *c, float *d)
{
float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
@@ -1615,17 +1915,17 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
}
/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
- char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
-
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
- int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+static void cgdm_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
+ int gridSize = CCS_getGridSize(ss);
+ char *faceFlags = DM_get_tessface_data_layer(dm, CD_FLAGS);
+
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
+ int index = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
int drawSmooth, mat_nr;
if(faceFlags) {
@@ -1642,7 +1942,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *
glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
if (drawSmooth) {
for (y=0; y<gridSize-1; y++) {
@@ -1667,7 +1967,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *
float *c = faceGridData[(y+1)*gridSize + x + 1].co;
float *d = faceGridData[(y+1)*gridSize + x].co;
- ccgDM_glNormalFast(a, b, c, d);
+ cgdm_glNormalFast(a, b, c, d);
glVertex3fv(d);
glVertex3fv(c);
@@ -1680,22 +1980,22 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *
}
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
}
/* Only used by non-editmesh types */
-static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
GPUVertexAttribs gattribs;
DMVertexAttribs attribs;
- MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
- int gridSize = ccgSubSurf_getGridSize(ss);
+ MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
+ int gridSize = CCS_getGridSize(ss);
int gridFaces = gridSize - 1;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int edgeSize = CCS_getEdgeSize(ss);
int transp, orig_transp, new_transp;
- char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
+ char *faceFlags = DM_get_tessface_data_layer(dm, CD_FLAGS);
int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
doDraw = 0;
@@ -1727,14 +2027,14 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
} \
}
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
for(a = 0, i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
+ CCFace *f = cgdm->faceMap[i].face;
int S, x, y, drawSmooth;
- int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
- int origIndex = ccgDM_getFaceMapIndex(ss, f);
+ int index = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
+ int origIndex = cgdm_getFaceMapIndex(ss, f);
- numVerts = ccgSubSurf_getFaceNumVerts(f);
+ numVerts = CCS_getFaceNumVerts(f);
if(faceFlags) {
drawSmooth = (faceFlags[index*4] & ME_SMOOTH);
@@ -1770,7 +2070,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
VertData *vda, *vdb;
if (drawSmooth) {
@@ -1816,7 +2116,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
float *dco = faceGridData[(y+1)*gridSize + x].co;
- ccgDM_glNormalFast(aco, bco, cco, dco);
+ cgdm_glNormalFast(aco, bco, cco, dco);
PASSATTRIB(0, 1, 1);
glVertex3fv(dco);
@@ -1837,18 +2137,18 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
#undef PASSATTRIB
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
}
-static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
-static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
+static void cgdm_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
+ int gridSize = CCS_getGridSize(ss);
unsigned char *cp1, *cp2;
int useTwoSide=1;
@@ -1865,12 +2165,12 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned ch
glEnable(GL_CULL_FACE);
glBegin(GL_QUADS);
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
for (y=0; y<gridSize-1; y++) {
for (x=0; x<gridSize-1; x++) {
float *a = faceGridData[(y+0)*gridSize + x].co;
@@ -1906,28 +2206,28 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned ch
}
glEnd();
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
}
-static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
- int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
+static void cgdm_drawFacesTex_common(DerivedMesh *dm,
+ int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
int (*drawParamsMapped)(void *userData, int index),
void *userData)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- MCol *mcol = DM_get_face_data_layer(dm, CD_MCOL);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
- char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
- int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ MCol *mcol = DM_get_tessface_data_layer(dm, CD_MCOL);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ char *faceFlags = DM_get_tessface_data_layer(dm, CD_FLAGS);
+ int i, totface, flag, gridSize = CCS_getGridSize(ss);
int gridFaces = gridSize - 1;
- totface = ccgSubSurf_getNumFaces(ss);
+ totface = CCS_getNumFaces(ss);
for(i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
- int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
- int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+ CCFace *f = cgdm->faceMap[i].face;
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
+ int drawSmooth, index = cgdm_getFaceMapIndex(ss, f);
+ int origIndex = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
unsigned char *cp= NULL;
int mat_nr;
@@ -1941,7 +2241,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
}
if(drawParams)
- flag = drawParams(tf, mcol, mat_nr);
+ flag = drawParams(tf, mcol!=NULL, mat_nr);
else
flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1;
@@ -1958,7 +2258,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
}
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
VertData *a, *b;
if (drawSmooth) {
@@ -2013,7 +2313,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
float *c_co = faceGridData[(y+1)*gridSize + x + 1].co;
float *d_co = faceGridData[(y+1)*gridSize + x].co;
- ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
+ cgdm_glNormalFast(a_co, b_co, c_co, d_co);
if(tf) glTexCoord2fv(tf->uv[1]);
if(cp) glColor3ub(cp[7], cp[6], cp[5]);
@@ -2041,21 +2341,21 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
}
}
-static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
+static void cgdm_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
+ cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
}
-static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
+ cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
+static void cgdm_drawUVEdges(DerivedMesh *dm)
{
- MFace *mf = dm->getFaceArray(dm);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
+ MFace *mf = dm->getTessFaceArray(dm);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i;
if (tf) {
@@ -2084,20 +2384,20 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm)
}
}
-static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
- int i, gridSize = ccgSubSurf_getGridSize(ss);
- char *faceFlags = dm->getFaceDataArray(dm, CD_FLAGS);
-
- for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
- int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
+static void cgdm_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
+ int i, gridSize = CCS_getGridSize(ss);
+ char *faceFlags = dm->getTessFaceDataArray(dm, CD_FLAGS);
+
+ for (i=0; !CCFIter_isStopped(fi); i++,CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int S, x, y, numVerts = CCS_getFaceNumVerts(f);
+ int drawSmooth, index = cgdm_getFaceMapIndex(ss, f);
int origIndex;
- origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+ origIndex = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
if(faceFlags) drawSmooth = (faceFlags[origIndex*4] & ME_SMOOTH);
else drawSmooth = 1;
@@ -2113,7 +2413,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
}
for (S=0; S<numVerts; S++) {
- VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ VertData *faceGridData = CCS_getFaceGridDataArray(ss, f, S);
if (drawSmooth) {
glShadeModel(GL_SMOOTH);
for (y=0; y<gridSize-1; y++) {
@@ -2162,25 +2462,25 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
}
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
}
-static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ int i, useAging, edgeSize = CCS_getEdgeSize(ss);
- ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
+ CCS_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
- int index = ccgDM_getEdgeMapIndex(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
+ int index = cgdm_getEdgeMapIndex(ss, e);
glBegin(GL_LINE_STRIP);
if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
if (useAging && !(G.f&G_BACKBUFSEL)) {
- int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
+ int ageCol = 255-CCS_getEdgeAge(ss, e)*4;
glColor3ub(0, ageCol>0?ageCol:0, 0);
}
@@ -2192,20 +2492,20 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *u
glEnd();
}
- ccgEdgeIterator_free(ei);
+ CCEIter_free(ei);
}
-static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
- int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+static void cgdm_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCEdgeIterator *ei = CCS_getEdgeIterator(ss);
+ int i, useAging, edgeSize = CCS_getEdgeSize(ss);
- ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
+ CCS_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
- for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
- VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
- int index = ccgDM_getEdgeMapIndex(ss, e);
+ for (; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
+ VertData *edgeData = CCS_getEdgeDataArray(ss, e);
+ int index = cgdm_getEdgeMapIndex(ss, e);
glBegin(GL_LINE_STRIP);
if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
@@ -2213,7 +2513,7 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v
setDrawInterpOptions(userData, index, (float) i/(edgeSize-1));
if (useAging && !(G.f&G_BACKBUFSEL)) {
- int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
+ int ageCol = 255-CCS_getEdgeAge(ss, e)*4;
glColor3ub(0, ageCol>0?ageCol:0, 0);
}
@@ -2223,196 +2523,495 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v
glEnd();
}
- ccgEdgeIterator_free(ei);
+ CCEIter_free(ei);
}
-static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+static void cgdm_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CSubSurf *ss = cgdm->ss;
+ CCFaceIterator *fi = CCS_getFaceIterator(ss);
- for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
- int index = ccgDM_getFaceMapIndex(ss, f);
+ for (; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
+ int index = cgdm_getFaceMapIndex(ss, f);
if (index!=-1) {
/* Face center data normal isn't updated atm. */
- VertData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
+ VertData *vd = CCS_getFaceGridData(ss, f, 0, 0, 0);
func(userData, index, vd->co, vd->no);
}
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
}
-static void ccgDM_release(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static void cgdm_release(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
if (DM_release(dm)) {
- MEM_freeN(ccgdm->vertMap);
- MEM_freeN(ccgdm->edgeMap);
- MEM_freeN(ccgdm->faceMap);
- MEM_freeN(ccgdm);
+ MEM_freeN(cgdm->vertMap);
+ MEM_freeN(cgdm->edgeMap);
+ MEM_freeN(cgdm->faceMap);
+ MEM_freeN(cgdm->reverseFaceMap);
+ BLI_edgehash_free(cgdm->ehash, NULL);
+ MEM_freeN(cgdm);
+ }
+}
+
+
+void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int loopstart, int findex,
+ int polyindex, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, 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;
+
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
+ for (j=0; j<4; j++, mloopuv++) {
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<4; j++, mloopcol++) {
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mloopcol = CustomData_get(ldata, loopstart, CD_WEIGHT_MLOOPCOL);
+ mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<4; j++, mloopcol++) {
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
}
}
-static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
+/*this function requires dm to be a CDDM*/
+static CCGDerivedMesh *getCCGDerivedMesh(CSubSurf *ss,
int drawInteriorEdges,
int useSubsurfUv,
DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
- CCGVertIterator *vi;
- CCGEdgeIterator *ei;
- CCGFaceIterator *fi;
+ CCGDerivedMesh *cgdm = MEM_callocN(sizeof(*cgdm), "cgdm");
+ CCVertIterator *vi;
+ CCEdgeIterator *ei;
+ CCFaceIterator *fi;
int index, totvert, totedge, totface;
int i;
int vertNum, edgeNum, faceNum;
- int *vertOrigIndex, *faceOrigIndex; /* *edgeOrigIndex - as yet, unused */
+ int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex; /* *edgeOrigIndex - as yet, unused */
int *edgeFlags;
- char *faceFlags;
+ char *faceFlags, *polyFlags;
+ int *loopidx = NULL, *vertidx = NULL;
+ BLI_array_declare(loopidx);
+ BLI_array_declare(vertidx);
+ int loopindex, loopindex2;
int edgeSize;
int gridSize;
- int gridFaces;
+ int gridFaces, gridCuts;
int gridSideVerts;
/*int gridInternalVerts; - as yet unused */
int gridSideEdges;
+ int numTex, numCol;
int gridInternalEdges;
+ float *w = NULL, one = 1.0f;
+ WeightTable wtable = {0};
/* MVert *mvert = NULL; - as yet unused */
- MEdge *medge = NULL;
+ MCol *mcol;
+ MEdge *medge = NULL, medge2;
MFace *mface = NULL;
- FaceVertWeight *qweight, *tweight;
-
- DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss),
- ccgSubSurf_getNumFinalEdges(ss),
- ccgSubSurf_getNumFinalFaces(ss));
- DM_add_face_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
- DM_add_edge_layer(&ccgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
-
- CustomData_set_layer_flag(&ccgdm->dm.faceData, CD_FLAGS, CD_FLAG_NOCOPY);
- CustomData_set_layer_flag(&ccgdm->dm.edgeData, CD_FLAGS, CD_FLAG_NOCOPY);
-
- ccgdm->dm.getMinMax = ccgDM_getMinMax;
- ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
- ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
-
- ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
- ccgdm->dm.getVert = ccgDM_getFinalVert;
- ccgdm->dm.getEdge = ccgDM_getFinalEdge;
- ccgdm->dm.getFace = ccgDM_getFinalFace;
- ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
- ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyFaceArray = 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.getVertDataArray = DM_get_vert_data_layer;
- ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
- ccgdm->dm.getFaceDataArray = DM_get_face_data_layer;
-
- ccgdm->dm.getVertCos = ccgdm_getVertCos;
- ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
- ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
- ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
+ MPoly *mpoly = NULL;
+
+ DM_from_template(&cgdm->dm, dm, CCS_getNumFinalVerts(ss),
+ CCS_getNumFinalEdges(ss),
+ CCS_getNumFinalFaces(ss),
+ CCS_getNumFinalFaces(ss)*4,
+ CCS_getNumFinalFaces(ss));
+ DM_add_tessface_layer(&cgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
+ DM_add_face_layer(&cgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
+ DM_add_edge_layer(&cgdm->dm, CD_FLAGS, CD_CALLOC, NULL);
+
+ numTex = CustomData_number_of_layers(&cgdm->dm.loopData, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(&cgdm->dm.loopData, CD_MLOOPCOL);
- ccgdm->dm.drawVerts = ccgDM_drawVerts;
- ccgdm->dm.drawEdges = ccgDM_drawEdges;
- ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
- ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
- ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
- ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
- ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
- ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
- ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
- ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
- ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
-
- ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
- ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
+ if (numTex && CustomData_number_of_layers(&cgdm->dm.faceData, CD_MTFACE) != numTex)
+ CustomData_from_bmeshpoly(&cgdm->dm.faceData, &cgdm->dm.polyData, &cgdm->dm.loopData, CCS_getNumFinalFaces(ss));
+ else if (numCol && CustomData_number_of_layers(&cgdm->dm.faceData, CD_MCOL) != numCol)
+ CustomData_from_bmeshpoly(&cgdm->dm.faceData, &cgdm->dm.polyData, &cgdm->dm.loopData, CCS_getNumFinalFaces(ss));
+
+ CustomData_set_layer_flag(&cgdm->dm.faceData, CD_FLAGS, CD_FLAG_NOCOPY);
+ CustomData_set_layer_flag(&cgdm->dm.edgeData, CD_FLAGS, CD_FLAG_NOCOPY);
+
+ cgdm->dm.getMinMax = cgdm_getMinMax;
+ cgdm->dm.getNumVerts = cgdm_getNumVerts;
+ cgdm->dm.getNumTessFaces = cgdm_getNumTessFaces;
+ cgdm->dm.getNumFaces = cgdm_getNumTessFaces;
+
+ cgdm->dm.newFaceIter = cgdm_newFaceIter;
+
+ cgdm->dm.getNumEdges = cgdm_getNumEdges;
+ cgdm->dm.getVert = cgdm_getFinalVert;
+ cgdm->dm.getEdge = cgdm_getFinalEdge;
+ cgdm->dm.getTessFace = cgdm_getFinalFace;
+ cgdm->dm.copyVertArray = cgdm_copyFinalVertArray;
+ cgdm->dm.copyEdgeArray = cgdm_copyFinalEdgeArray;
+ cgdm->dm.copyTessFaceArray = cgdm_copyFinalFaceArray;
+ cgdm->dm.getVertData = DM_get_vert_data;
+ cgdm->dm.getEdgeData = DM_get_edge_data;
+ cgdm->dm.getTessFaceData = DM_get_face_data;
+ cgdm->dm.getVertDataArray = DM_get_vert_data_layer;
+ cgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
+ cgdm->dm.getTessFaceDataArray = DM_get_tessface_data_layer;
+
+ cgdm->dm.getVertCos = cgdm_getVertCos;
+ cgdm->dm.foreachMappedVert = cgdm_foreachMappedVert;
+ cgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge;
+ cgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter;
- ccgdm->dm.release = ccgDM_release;
+ cgdm->dm.drawVerts = cgdm_drawVerts;
+ cgdm->dm.drawEdges = cgdm_drawEdges;
+ cgdm->dm.drawLooseEdges = cgdm_drawLooseEdges;
+ cgdm->dm.drawFacesSolid = cgdm_drawFacesSolid;
+ cgdm->dm.drawFacesColored = cgdm_drawFacesColored;
+ cgdm->dm.drawFacesTex = cgdm_drawFacesTex;
+ cgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL;
+ cgdm->dm.drawMappedFaces = cgdm_drawMappedFaces;
+ cgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex;
+ cgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL;
+ cgdm->dm.drawUVEdges = cgdm_drawUVEdges;
+
+ cgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp;
+ cgdm->dm.drawMappedEdges = cgdm_drawMappedEdges;
- ccgdm->ss = ss;
- ccgdm->drawInteriorEdges = drawInteriorEdges;
- ccgdm->useSubsurfUv = useSubsurfUv;
+ cgdm->dm.release = cgdm_release;
+
+ cgdm->ss = ss;
+ cgdm->drawInteriorEdges = drawInteriorEdges;
+ cgdm->useSubsurfUv = useSubsurfUv;
- totvert = ccgSubSurf_getNumVerts(ss);
- ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
- vi = ccgSubSurf_getVertIterator(ss);
- for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
+ totvert = CCS_getNumVerts(ss);
+ cgdm->vertMap = MEM_mallocN(totvert * sizeof(*cgdm->vertMap), "vertMap");
+ vi = CCS_getVertIterator(ss);
+ for(; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
- ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
+ cgdm->vertMap[GET_INT_FROM_POINTER(CCS_getVertVertHandle(v))].vert = v;
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
- totedge = ccgSubSurf_getNumEdges(ss);
- ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
- ei = ccgSubSurf_getEdgeIterator(ss);
- for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+ totedge = CCS_getNumEdges(ss);
+ cgdm->edgeMap = MEM_mallocN(totedge * sizeof(*cgdm->edgeMap), "edgeMap");
+ ei = CCS_getEdgeIterator(ss);
+ for(; !CCEIter_isStopped(ei); CCEIter_next(ei)) {
+ CCEdge *e = CCEIter_getCurrent(ei);
- ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
+ cgdm->edgeMap[GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e))].edge = e;
}
- totface = ccgSubSurf_getNumFaces(ss);
- ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
- fi = ccgSubSurf_getFaceIterator(ss);
- for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ totface = CCS_getNumFaces(ss);
+ cgdm->faceMap = MEM_mallocN(totface * sizeof(*cgdm->faceMap), "faceMap");
+ fi = CCS_getFaceIterator(ss);
+ for(; !CCFIter_isStopped(fi); CCFIter_next(fi)) {
+ CCFace *f = CCFIter_getCurrent(fi);
- ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))].face = f;
+ cgdm->faceMap[GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f))].face = f;
}
- ccgFaceIterator_free(fi);
+ CCFIter_free(fi);
+
+ cgdm->reverseFaceMap = MEM_callocN(sizeof(int)*CCS_getNumFinalFaces(ss), "reverseFaceMap");
- edgeSize = ccgSubSurf_getEdgeSize(ss);
- gridSize = ccgSubSurf_getGridSize(ss);
+ edgeSize = CCS_getEdgeSize(ss);
+ gridSize = CCS_getGridSize(ss);
gridFaces = gridSize - 1;
gridSideVerts = gridSize - 2;
+ gridCuts = gridSize - 2;
/*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
- calc_ss_weights(gridFaces, &qweight, &tweight);
-
vertNum = 0;
edgeNum = 0;
faceNum = 0;
/* mvert = dm->getVertArray(dm); - as yet unused */
medge = dm->getEdgeArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
+
+ /*CDDM hack*/
+ mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+
+ vertOrigIndex = DM_get_vert_data_layer(&cgdm->dm, CD_ORIGINDEX);
+ /*edgeOrigIndex = DM_get_edge_data_layer(&cgdm->dm, CD_ORIGINDEX);*/
+ faceOrigIndex = DM_get_tessface_data_layer(&cgdm->dm, CD_ORIGINDEX);
+ faceFlags = DM_get_tessface_data_layer(&cgdm->dm, CD_FLAGS);
+
+ polyOrigIndex = DM_get_face_data_layer(&cgdm->dm, CD_ORIGINDEX);
+ polyFlags = DM_get_face_data_layer(&cgdm->dm, CD_FLAGS);
+
+ if (!CustomData_has_layer(&cgdm->dm.faceData, CD_MCOL))
+ DM_add_tessface_layer(&cgdm->dm, CD_MCOL, CD_CALLOC, NULL);
+
+ mcol = DM_get_tessface_data_layer(&cgdm->dm, CD_MCOL);
+
+ faceNum = 0;
+ loopindex = loopindex2 = 0; //current loop index
+ for (index = 0; index < totface; index++) {
+ CCFace *f = cgdm->faceMap[index].face;
+ int numVerts = CCS_getFaceNumVerts(f);
+ int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
+ int mapIndex = cgdm_getFaceMapIndex(ss, f);
+ int origIndex = GET_INT_FROM_POINTER(CCS_getFaceFaceHandle(ss, f));
+ int g2_wid = gridCuts+2;
+ float *w2;
+ int s, x, y;
+
+ w = get_ss_weights(&wtable, gridCuts, numVerts);
+
+ cgdm->faceMap[index].startVert = vertNum;
+ cgdm->faceMap[index].startEdge = edgeNum;
+ cgdm->faceMap[index].startFace = faceNum;
+
+ /* set the face base vert */
+ *((int*)CCS_getFaceUserData(ss, f)) = vertNum;
+
+ BLI_array_empty(loopidx);
+ for (s=0; s<numVerts; s++) {
+ BLI_array_growone(loopidx);
+ loopidx[s] = loopindex++;
+ }
+
+ BLI_array_empty(vertidx);
+ for(s = 0; s < numVerts; s++) {
+ CCVert *v = CCS_getFaceVert(ss, f, s);
+
+ BLI_array_growone(vertidx);
+ vertidx[s] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+ }
+
+
+ /*I think this is for interpolating the center vert?*/
+ w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1);
+ DM_interp_vert_data(dm, &cgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+ if (vertOrigIndex)
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+
+ /*interpolate per-vert data*/
+ for(s = 0; s < numVerts; s++) {
+ for(x = 1; x < gridFaces; x++) {
+ w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts;
+ DM_interp_vert_data(dm, &cgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+
+ if (vertOrigIndex)
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+ }
+
+ /*interpolate per-vert data*/
+ for(s = 0; s < numVerts; s++) {
+ for(y = 1; y < gridFaces; y++) {
+ for(x = 1; x < gridFaces; x++) {
+ w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
+ DM_interp_vert_data(dm, &cgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+
+ if (vertOrigIndex)
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+ }
+ }
+
+ for(i = 0; i < numFinalEdges; ++i)
+ *(int *)DM_get_edge_data(&cgdm->dm, edgeNum + i,
+ CD_ORIGINDEX) = ORIGINDEX_NONE;
+ for (s=0; s<numVerts; s++) {
+ /*interpolate per-face data*/
+ for (y=0; y<gridFaces; y++) {
+ for (x=0; x<gridFaces; x++) {
+ w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
+ CustomData_interp(&dm->loopData, &cgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts;
+ CustomData_interp(&dm->loopData, &cgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts;
+ CustomData_interp(&dm->loopData, &cgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts;
+ CustomData_interp(&dm->loopData, &cgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ /*copy over poly data, e.g. mtexpoly*/
+ CustomData_copy_data(&dm->polyData, &cgdm->dm.polyData, origIndex, faceNum, 1);
+
+ /*generate tesselated face data used for drawing*/
+ ccg_loops_to_corners(&cgdm->dm.faceData, &cgdm->dm.loopData,
+ &cgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol);
+
+ /*set original index data*/
+ *faceOrigIndex = origIndex;
+ *polyOrigIndex = origIndex;
+
+ cgdm->reverseFaceMap[faceNum] = index;
+
+ faceOrigIndex++;
+ polyOrigIndex++;
+ faceNum++;
+ }
+ }
+ }
+
+ polyFlags[0] = mpoly[origIndex].flag;
+ polyFlags[1] = mpoly[origIndex].mat_nr;
+ faceFlags[0] = polyFlags[0];
+ faceFlags[1] = polyFlags[1];
+
+ faceFlags += 4;
+ polyFlags += 4;
+ edgeNum += numFinalEdges;
+ }
+
+ edgeFlags = DM_get_edge_data_layer(&cgdm->dm, CD_FLAGS);
+ for(index = 0; index < totedge; ++index) {
+ CCEdge *e = cgdm->edgeMap[index].edge;
+ int numFinalEdges = edgeSize - 1;
+ int mapIndex = cgdm_getEdgeMapIndex(ss, e);
+ int x;
+ int vertIdx[2];
+ int edgeIdx = GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e));
+
+ CCVert *v;
+ v = CCS_getEdgeVert0(e);
+ vertIdx[0] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+ v = CCS_getEdgeVert1(e);
+ vertIdx[1] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+
+ cgdm->edgeMap[index].startVert = vertNum;
+ cgdm->edgeMap[index].startEdge = edgeNum;
+
+ /* set the edge base vert */
+ *((int*)CCS_getEdgeUserData(ss, e)) = vertNum;
+
+ 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, &cgdm->dm, vertIdx, w, 2, vertNum);
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+
+ for(i = 0; i < numFinalEdges; ++i) {
+ if(edgeIdx >= 0 && edgeFlags)
+ edgeFlags[edgeNum + i] = medge[edgeIdx].flag;
+
+ *(int *)DM_get_edge_data(&cgdm->dm, edgeNum + i,
+ CD_ORIGINDEX) = mapIndex;
+ }
+
+ edgeNum += numFinalEdges;
+ }
+
+ for(index = 0; index < totvert; ++index) {
+ CCVert *v = cgdm->vertMap[index].vert;
+ int mapIndex = cgdm_getVertMapIndex(cgdm->ss, v);
+ int vidx;
+
+ vidx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+
+ cgdm->vertMap[index].startVert = vertNum;
+
+ /* set the vert base vert */
+ *((int*) CCS_getVertUserData(ss, v)) = vertNum;
+
+ DM_copy_vert_data(dm, &cgdm->dm, vidx, vertNum, 1);
+
+ *vertOrigIndex = mapIndex;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
- vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
- /*edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);*/
- faceOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+ cgdm->dm.numVertData = vertNum;
+ cgdm->dm.numEdgeData = edgeNum;
+ cgdm->dm.numFaceData = faceNum;
+ cgdm->dm.numLoopData = loopindex2;
+ cgdm->dm.numPolyData = faceNum;
- faceFlags = DM_get_face_data_layer(&ccgdm->dm, CD_FLAGS);
+ BLI_array_free(vertidx);
+ BLI_array_free(loopidx);
+ free_ss_weights(&wtable);
+ cgdm->ehash = BLI_edgehash_new();
+ for (i=0; i<cgdm->dm.numEdgeData; i++) {
+ cgdm_getFinalEdge((DerivedMesh*)cgdm, i, &medge2);
+ BLI_edgehash_insert(cgdm->ehash, medge2.v1, medge2.v2, SET_INT_IN_POINTER(i));
+ }
+#if 0
for(index = 0; index < totface; ++index) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
+ CCFace *f = cgdm->faceMap[index].face;
+ int numVerts = CCS_getFaceNumVerts(f);
int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
- int mapIndex = ccgDM_getFaceMapIndex(ss, f);
- int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+ int mapIndex = cgdm_getFaceMapIndex(ss, f);
+ int origIndex = GET_INT_FROM_POINTER(CCS_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;
- ccgdm->faceMap[index].startFace = faceNum;
+ cgdm->faceMap[index].startVert = vertNum;
+ cgdm->faceMap[index].startEdge = edgeNum;
+ cgdm->faceMap[index].startFace = faceNum;
/* set the face base vert */
- *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
-
+ *((int*)CCS_getFaceUserData(ss, f)) = vertNum;
for(S = 0; S < numVerts; S++) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ CCVert *v = CCS_getFaceVert(ss, f, S);
+ BLI_array_growone(vertIdx);
- vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ vertIdx[S] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
}
- DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
+ DM_interp_vert_data(dm, &cgdm->dm, vertIdx, weight[0][0],
numVerts, vertNum);
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
@@ -2422,14 +3021,17 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
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,
+ DM_interp_vert_data(dm, &cgdm->dm, vertIdx, w,
numVerts, vertNum);
+#endif
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
++vertNum;
@@ -2443,12 +3045,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,
+ DM_interp_vert_data(dm, &cgdm->dm, vertIdx, w,
numVerts, vertNum);
+#endif
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
++vertNum;
@@ -2457,7 +3061,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
for(i = 0; i < numFinalEdges; ++i)
- *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ *(int *)DM_get_edge_data(&cgdm->dm, edgeNum + i,
CD_ORIGINDEX) = ORIGINDEX_NONE;
for(S = 0; S < numVerts; S++) {
@@ -2472,6 +3076,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
FaceVertWeight w;
int j;
+#if 1 //BMESH_TODO
for(j = 0; j < 4; ++j) {
w[j][prevS] = (*weight)[j][0];
w[j][S] = (*weight)[j][1];
@@ -2479,9 +3084,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, &cgdm->dm, &origIndex, NULL,
&w, 1, faceNum);
weight++;
+#endif
*faceOrigIndex = mapIndex;
@@ -2498,42 +3104,42 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
if(useSubsurfUv) {
- CustomData *fdata = &ccgdm->dm.faceData;
+ CustomData *fdata = &cgdm->dm.faceData;
CustomData *dmfdata = &dm->faceData;
int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
for (i=0; i<numlayer && i<dmnumlayer; i++)
- set_subsurf_uv(ss, dm, &ccgdm->dm, i);
+ set_subsurf_uv(ss, dm, &cgdm->dm, i);
}
- edgeFlags = DM_get_edge_data_layer(&ccgdm->dm, CD_FLAGS);
+ edgeFlags = DM_get_edge_data_layer(&cgdm->dm, CD_FLAGS);
for(index = 0; index < totedge; ++index) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
+ CCEdge *e = cgdm->edgeMap[index].edge;
int numFinalEdges = edgeSize - 1;
- int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
+ int mapIndex = cgdm_getEdgeMapIndex(ss, e);
int x;
int vertIdx[2];
- int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
+ int edgeIdx = GET_INT_FROM_POINTER(CCS_getEdgeEdgeHandle(e));
- CCGVert *v;
- v = ccgSubSurf_getEdgeVert0(e);
- vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
- v = ccgSubSurf_getEdgeVert1(e);
- vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ CCVert *v;
+ v = CCS_getEdgeVert0(e);
+ vertIdx[0] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+ v = CCS_getEdgeVert1(e);
+ vertIdx[1] = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
- ccgdm->edgeMap[index].startVert = vertNum;
- ccgdm->edgeMap[index].startEdge = edgeNum;
+ cgdm->edgeMap[index].startVert = vertNum;
+ cgdm->edgeMap[index].startEdge = edgeNum;
/* set the edge base vert */
- *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
+ *((int*)CCS_getEdgeUserData(ss, e)) = vertNum;
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, &ccgdm->dm, vertIdx, w, 2, vertNum);
+ DM_interp_vert_data(dm, &cgdm->dm, vertIdx, w, 2, vertNum);
*vertOrigIndex = ORIGINDEX_NONE;
++vertOrigIndex;
++vertNum;
@@ -2543,7 +3149,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
if(edgeIdx >= 0 && edgeFlags)
edgeFlags[edgeNum + i] = medge[edgeIdx].flag;
- *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ *(int *)DM_get_edge_data(&cgdm->dm, edgeNum + i,
CD_ORIGINDEX) = mapIndex;
}
@@ -2551,18 +3157,18 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
for(index = 0; index < totvert; ++index) {
- CCGVert *v = ccgdm->vertMap[index].vert;
- int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
+ CCVert *v = cgdm->vertMap[index].vert;
+ int mapIndex = cgdm_getVertMapIndex(cgdm->ss, v);
int vertIdx;
- vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ vertIdx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
- ccgdm->vertMap[index].startVert = vertNum;
+ cgdm->vertMap[index].startVert = vertNum;
/* set the vert base vert */
- *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
+ *((int*) CCS_getVertUserData(ss, v)) = vertNum;
- DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
+ DM_copy_vert_data(dm, &cgdm->dm, vertIdx, vertNum, 1);
*vertOrigIndex = mapIndex;
++vertOrigIndex;
@@ -2572,7 +3178,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
MEM_freeN(qweight);
MEM_freeN(tweight);
- return ccgdm;
+ BLI_array_free(vertIdx);
+#endif
+ return cgdm;
}
/***/
@@ -2600,7 +3208,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
useSubsurfUv, dm);
} else if(useRenderParams) {
/* Do not use cache in render mode. */
- CCGSubSurf *ss;
+ CSubSurf *ss;
int levels;
levels= smd->renderLevels; // XXX get_render_subsurf_level(&scene->r, smd->renderLevels);
@@ -2614,13 +3222,13 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
useSubsurfUv, dm, ms);
- ccgSubSurf_free(ss);
+ CCS_free(ss);
return result;
} else {
- int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
+ int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental);
int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
- CCGSubSurf *ss;
+ CSubSurf *ss;
/* It is quite possible there is a much better place to do this. It
* depends a bit on how rigourously we expect this function to never
@@ -2631,7 +3239,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
* comment that no one will read? Hmmm. - zr
*/
if(smd->emCache) {
- ccgSubSurf_free(smd->emCache);
+ CCS_free(smd->emCache);
smd->emCache = NULL;
}
@@ -2650,7 +3258,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
useSubsurfUv, dm);*/
} else {
if (smd->mCache && isFinalCalc) {
- ccgSubSurf_free(smd->mCache);
+ CCS_free(smd->mCache);
smd->mCache = NULL;
}
@@ -2665,7 +3273,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
useSubsurfUv, dm, ms);
- ccgSubSurf_free(ss);
+ CCS_free(ss);
return result;
}
@@ -2678,7 +3286,21 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
int useRenderParams, float (*vertCos)[3],
int isFinalCalc, int editMode)
{
- return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode);
+ DerivedMesh *cddm = NULL, *result;
+
+ if (!CDDM_Check(dm)) {
+ cddm = CDDM_copy(dm, 0);
+ dm = cddm;
+ }
+
+ result = subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode);
+
+ if (cddm) {
+ cddm->needsFree = 1;
+ cddm->release(cddm);
+ }
+
+ return result;
}
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
@@ -2688,19 +3310,19 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
* calculated vert positions is incorrect for the verts
* on the boundary of the mesh.
*/
- CCGSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0);
+ CSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0);
float edge_sum[3], face_sum[3];
- CCGVertIterator *vi;
+ CCVertIterator *vi;
DerivedMesh *dm = CDDM_from_mesh(me, NULL);
ss_sync_from_derivedmesh(ss, dm, NULL, 0);
- vi = ccgSubSurf_getVertIterator(ss);
- for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(vi);
- int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
- int N = ccgSubSurf_getVertNumEdges(v);
- int numFaces = ccgSubSurf_getVertNumFaces(v);
+ vi = CCS_getVertIterator(ss);
+ for (; !CCVIter_isStopped(vi); CCVIter_next(vi)) {
+ CCVert *v = CCVIter_getCurrent(vi);
+ int idx = GET_INT_FROM_POINTER(CCS_getVertVertHandle(v));
+ int N = CCS_getVertNumEdges(v);
+ int numFaces = CCS_getVertNumFaces(v);
float *co;
int i;
@@ -2708,12 +3330,12 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
for (i=0; i<N; i++) {
- CCGEdge *e = ccgSubSurf_getVertEdge(v, i);
- VecAddf(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
+ CCEdge *e = CCS_getVertEdge(v, i);
+ VecAddf(edge_sum, edge_sum, CCS_getEdgeData(ss, e, 1));
}
for (i=0; i<numFaces; i++) {
- CCGFace *f = ccgSubSurf_getVertFace(v, i);
- VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(f));
+ CCFace *f = CCS_getVertFace(v, i);
+ VecAddf(face_sum, face_sum, CCS_getFaceCenterData(f));
}
/* ad-hoc correction for boundary vertices, to at least avoid them
@@ -2721,14 +3343,14 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
if(numFaces && numFaces != N)
VecMulf(face_sum, (float)N/(float)numFaces);
- co = ccgSubSurf_getVertData(ss, v);
+ co = CCS_getVertData(ss, v);
positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5));
positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5));
positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5));
}
- ccgVertIterator_free(vi);
+ CCVIter_free(vi);
- ccgSubSurf_free(ss);
+ CCS_free(ss);
dm->release(dm);
}
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
index 325798f325f..ec0f31e3dc9 100644
--- a/source/blender/blenkernel/nla_private.h
+++ b/source/blender/blenkernel/nla_private.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: nla_private.h 21537 2009-07-11 22:22:53Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index e6aded12f3b..f4d91891dd1 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -320,9 +320,6 @@ void Mat3Clr(float *m);
void Mat3One(float m[][3]);
void Mat4One(float m[][4]);
-void Mat3Scale(float m[][3], float scale);
-void Mat4Scale(float m[][4], float scale);
-
void Mat3Ortho(float mat[][3]);
void Mat4Ortho(float mat[][4]);
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
new file mode 100644
index 00000000000..c01d821cb8b
--- /dev/null
+++ b/source/blender/blenlib/BLI_array.h
@@ -0,0 +1,91 @@
+/**
+ * Array library
+ *
+ *
+ * ***** 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) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+this library needs to be changed to not use macros quite so heavily,
+and to be more of a complete array API. The way arrays are
+exposed to client code as normal C arrays is very useful though, imho.
+it does require some use of macros, however.
+
+anyway, it's used a bit too heavily to simply rewrite as a
+more "correct" solution without macros entirely. I originally wrote this
+to be very easy to use, without the normal pain of most array libraries.
+This was especially helpful when it came to the massive refactors necessary for
+bmesh, and really helped to speed the process up. - joeedh
+
+little array macro library. example of usage:
+
+int *arr = NULL;
+BLI_array_declare(arr);
+int i;
+
+for (i=0; i<10; i++) {
+ BLI_array_growone(arr);
+ arr[i] = something;
+}
+BLI_array_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 BLI_array_declare(arr) int _##arr##_count=0; void *_##arr##_tmp
+
+/*this returns the entire size of the array, including any buffering.*/
+#define BLI_array_totalsize(arr) ((signed int)((arr)==NULL ? 0 : MEM_allocN_len(arr) / sizeof(*arr)))
+
+/*this returns the logical size of the array, not including buffering.*/
+#define BLI_array_count(arr) _##arr##_count
+
+/*grow the array by one. zeroes the new elements.*/
+#define BLI_array_growone(arr) \
+ BLI_array_totalsize(arr) > _##arr##_count ? _##arr##_count++ : \
+ ((_##arr##_tmp = MEM_callocN(sizeof(*arr)*(_##arr##_count*2+2), #arr " " __FILE__ " ")),\
+ (arr && memcpy(_##arr##_tmp, arr, sizeof(*arr) * _##arr##_count)),\
+ (arr && (MEM_freeN(arr),1)),\
+ (arr = _##arr##_tmp),\
+ _##arr##_count++)
+
+/*appends an item to the array and returns a pointer to the item in the array.
+ item is not a pointer, but actual data value.*/
+#define BLI_array_append(arr, item) (BLI_array_growone(arr), arr[_##arr##_count] = item, (arr+_##arr##_count))
+
+/*grow an array by a specified number of items.*/
+#define BLI_array_growitems(arr, num) {int _i; for (_i=0; _i<(num); _i++) {BLI_array_growone(arr);}}
+#define BLI_array_free(arr) if (arr) MEM_freeN(arr)
+
+/*resets the logical size of an array to zero, but doesn't
+ free the memory.*/
+#define BLI_array_empty(arr) _##arr##_count=0
+
+/*set the count of the array, doesn't actually increase the allocated array
+ size. don't use this unless you know what your doing.*/
+#define BLI_array_set_length(arr, count) _##arr##_count = (count)
diff --git a/source/blender/blenlib/BLI_cellalloc.h b/source/blender/blenlib/BLI_cellalloc.h
new file mode 100644
index 00000000000..cd10e9febe8
--- /dev/null
+++ b/source/blender/blenlib/BLI_cellalloc.h
@@ -0,0 +1,49 @@
+/**
+ *
+ * ***** 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) 2008 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ I wrote this as a hack so vgroups won't be quite so slow. I really
+ should replace it with something else, but I need to spend some time
+ thinking as to what the proper solution would be (other then totally
+ rewriting vgroups, of course).
+
+ this is just a simple allocator that spawns mempools for unique size
+ requests. hardly ideal, I know. *something* like this may be
+ unavoidable, but it should certainly be possible to make it
+ non-global and internal to the vgroup code.
+
+ -joeedh sep. 17 2009
+*/
+
+//BMESH_TODO: kill this library before merging with trunk
+void *BLI_cellalloc_malloc(long size, char *tag);
+void *BLI_cellalloc_calloc(long size, char *tag);
+void BLI_cellalloc_free(void *mem);
+void BLI_cellalloc_printleaks(void);
+int BLI_cellalloc_get_totblock(void);
+void BLI_cellalloc_destroy(void);
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index abbd17c3635..85b0b9023ec 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -32,6 +32,10 @@
#ifndef BLI_EDGEHASH_H
#define BLI_EDGEHASH_H
+#include "MEM_guardedalloc.h"
+#include "BKE_utildefines.h"
+#include "BLI_mempool.h"
+
struct EdgeHash;
struct EdgeHashIterator;
typedef struct EdgeHash EdgeHash;
@@ -45,22 +49,22 @@ void BLI_edgehash_free (EdgeHash *eh, EdgeHashFreeFP valfreefp);
/* Insert edge (v0,v1) into hash with given value, does
* not check for duplicates.
*/
-void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val);
+//void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val);
/* Return value for given edge (v0,v1), or NULL if
* if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and
* lack of key then see BLI_edgehash_lookup_p().
*/
-void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1);
+//void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1);
/* Return pointer to value for given edge (v0,v1),
* or NULL if key does not exist in hash.
*/
-void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1);
+//void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1);
/* Return boolean true/false if edge (v0,v1) in hash. */
-int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1);
+//int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1);
/* Return number of keys in hash. */
int BLI_edgehash_size (EdgeHash *eh);
@@ -95,5 +99,99 @@ void BLI_edgehashIterator_step (EdgeHashIterator *ehi);
/* Determine if an iterator is done. */
int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi);
+/**************inlined code************/
+static unsigned int _ehash_hashsizes[]= {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
+ 268435459
+};
+
+#define EDGEHASH(v0,v1) ((v0*39)^(v1*31))
+
+/***/
+
+typedef struct EdgeEntry EdgeEntry;
+struct EdgeEntry {
+ EdgeEntry *next;
+ int v0, v1;
+ void *val;
+};
+
+struct EdgeHash {
+ EdgeEntry **buckets;
+ BLI_mempool *epool;
+ int nbuckets, nentries, cursize;
+};
+
+
+BM_INLINE void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
+ unsigned int hash;
+ EdgeEntry *e= BLI_mempool_alloc(eh->epool);
+
+ if (v1<v0) {
+ v0 ^= v1;
+ v1 ^= v0;
+ v0 ^= v1;
+ }
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+
+ e->v0 = v0;
+ e->v1 = v1;
+ e->val = val;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ if (++eh->nentries>eh->nbuckets*3) {
+ EdgeEntry *e, **old= eh->buckets;
+ int i, nold= eh->nbuckets;
+
+ eh->nbuckets= _ehash_hashsizes[++eh->cursize];
+ eh->buckets= MEM_mallocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets");
+ BMEMSET(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ EdgeEntry *n= e->next;
+
+ hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ MEM_freeN(old);
+ }
+}
+
+BM_INLINE void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
+ unsigned int hash;
+ EdgeEntry *e;
+
+ if (v1<v0) {
+ v0 ^= v1;
+ v1 ^= v0;
+ v0 ^= v1;
+ }
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+ for (e= eh->buckets[hash]; e; e= e->next)
+ if (v0==e->v0 && v1==e->v1)
+ return &e->val;
+
+ return NULL;
+}
+
+BM_INLINE void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
+ void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
+
+ return value_p?*value_p:NULL;
+}
+
+BM_INLINE int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
+ return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+}
+
#endif
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/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index c9a8b1b841f..3ee767ec156 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -32,31 +32,48 @@
#ifndef BLI_GHASH_H
#define BLI_GHASH_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
-struct GHash;
-typedef struct GHash GHash;
+#include "BKE_utildefines.h"
-typedef struct GHashIterator {
- GHash *gh;
- int curBucket;
- struct Entry *curEntry;
-} GHashIterator;
+#include "BLI_mempool.h"
+#include "BLI_blenlib.h"
typedef unsigned int (*GHashHashFP) (void *key);
typedef int (*GHashCmpFP) (void *a, void *b);
typedef void (*GHashKeyFreeFP) (void *key);
typedef void (*GHashValFreeFP) (void *val);
+typedef struct Entry {
+ struct Entry *next;
+
+ void *key, *val;
+} Entry;
+
+typedef struct GHash {
+ GHashHashFP hashfp;
+ GHashCmpFP cmpfp;
+
+ Entry **buckets;
+ struct BLI_mempool *entrypool;
+ int nbuckets, nentries, cursize;
+} GHash;
+
+typedef struct GHashIterator {
+ GHash *gh;
+ int curBucket;
+ struct Entry *curEntry;
+} GHashIterator;
+
GHash* BLI_ghash_new (GHashHashFP hashfp, GHashCmpFP cmpfp);
void BLI_ghash_free (GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
-void BLI_ghash_insert (GHash *gh, void *key, void *val);
-int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
-void* BLI_ghash_lookup (GHash *gh, void *key);
-int BLI_ghash_haskey (GHash *gh, void *key);
+//BM_INLINE void BLI_ghash_insert (GHash *gh, void *key, void *val);
+//BM_INLINE int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+//BM_INLINE void* BLI_ghash_lookup (GHash *gh, void *key);
+//BM_INLINE int BLI_ghash_haskey (GHash *gh, void *key);
int BLI_ghash_size (GHash *gh);
@@ -129,9 +146,121 @@ int BLI_ghashutil_strcmp (void *a, void *b);
unsigned int BLI_ghashutil_inthash (void *ptr);
int BLI_ghashutil_intcmp(void *a, void *b);
-#ifdef __cplusplus
-}
-#endif
+/*begin of macro-inlined functions*/
+extern unsigned int hashsizes[];
+#if 0
+#define BLI_ghash_insert(gh, _k, _v){\
+ unsigned int _hash= (gh)->hashfp(_k)%gh->nbuckets;\
+ Entry *_e= BLI_mempool_alloc((gh)->entrypool);\
+ _e->key= _k;\
+ _e->val= _v;\
+ _e->next= (gh)->buckets[_hash];\
+ (gh)->buckets[_hash]= _e;\
+ if (++(gh)->nentries>(gh)->nbuckets*3) {\
+ Entry *_e, **_old= (gh)->buckets;\
+ int _i, _nold= (gh)->nbuckets;\
+ (gh)->nbuckets= hashsizes[++(gh)->cursize];\
+ (gh)->buckets= malloc((gh)->nbuckets*sizeof(*(gh)->buckets));\
+ memset((gh)->buckets, 0, (gh)->nbuckets*sizeof(*(gh)->buckets));\
+ for (_i=0; _i<_nold; _i++) {\
+ for (_e= _old[_i]; _e;) {\
+ Entry *_n= _e->next;\
+ _hash= (gh)->hashfp(_e->key)%(gh)->nbuckets;\
+ _e->next= (gh)->buckets[_hash];\
+ (gh)->buckets[_hash]= _e;\
+ _e= _n;\
+ }\
+ }\
+ free(_old); } }
#endif
+/*---------inlined functions---------*/
+BM_INLINE void BLI_ghash_insert(GHash *gh, void *key, void *val) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e= BLI_mempool_alloc(gh->entrypool);
+
+ e->key= key;
+ e->val= val;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ if (++gh->nentries>gh->nbuckets*3) {
+ Entry *e, **old= gh->buckets;
+ int i, nold= gh->nbuckets;
+
+ gh->nbuckets= hashsizes[++gh->cursize];
+ gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
+ memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ Entry *n= e->next;
+
+ hash= gh->hashfp(e->key)%gh->nbuckets;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ free(old);
+ }
+}
+
+BM_INLINE void* BLI_ghash_lookup(GHash *gh, void *key)
+{
+ if(gh) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return e->val;
+ }
+ return NULL;
+}
+
+BM_INLINE int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+ Entry *p = 0;
+
+ for (e= gh->buckets[hash]; e; e= e->next) {
+ if (gh->cmpfp(key, e->key)==0) {
+ Entry *n= e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+ BLI_mempool_free(gh->entrypool, e);
+
+
+ e= n;
+ if (p)
+ p->next = n;
+ else
+ gh->buckets[hash] = n;
+
+ --gh->nentries;
+ return 1;
+ }
+ p = e;
+ }
+
+ return 0;
+}
+
+BM_INLINE int BLI_ghash_haskey(GHash *gh, void *key) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return 1;
+
+ return 0;
+}
+
+#endif
diff --git a/source/blender/blenlib/intern/BLI_cellalloc.c b/source/blender/blenlib/intern/BLI_cellalloc.c
new file mode 100644
index 00000000000..efed99011d0
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_cellalloc.c
@@ -0,0 +1,174 @@
+/**
+ *
+ * ***** 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) 2008 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ Simple, fast memory allocator that uses many BLI_mempools for allocation.
+ this is meant to be used by lots of relatively small objects.
+
+ this is a temporary and inperfect fix for performance issues caused
+ by vgroups. it needs to be replaced with something better, preferably
+ integrated into guardedalloc.
+*/
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+
+#include "DNA_listBase.h"
+#include "BLI_mempool.h"
+
+#include <string.h>
+
+static BLI_mempool **pools;
+static int totpool = 0;
+ListBase active_mem = {NULL, NULL};
+static int celltotblock = 0;
+
+#define MEMIDCHECK ('a' | ('b' << 4) | ('c' << 8) | ('d' << 12))
+
+typedef struct MemHeader {
+ struct MemHeader *next, *prev;
+
+ int size;
+ char *tag;
+ int idcheck;
+} MemHeader;
+
+//#define USE_GUARDEDALLOC
+
+void *BLI_cellalloc_malloc(long size, char *tag)
+{
+ MemHeader *memh;
+ int slot = size + sizeof(MemHeader);
+
+#ifdef USE_GUARDEDALLOC
+ return MEM_mallocN(size, tag);
+#endif
+ if (!slot)
+ return NULL;
+
+ /*stupid optimization trick.
+ round up to nearest 16 bytes boundary.
+ this is to reduce the number of potential
+ pools. hopefully it'll help.*/
+ slot += 16 - (slot & 15);
+
+ if (slot >= totpool) {
+ void *tmp;
+
+ tmp = calloc(1, sizeof(void*)*(slot+1));
+ if (pools) {
+ memcpy(tmp, pools, totpool*sizeof(void*));
+ }
+
+ pools = tmp;
+ totpool = slot+1;
+ }
+
+ if (!pools[slot]) {
+ pools[slot] = BLI_mempool_create(slot, 1, 128);
+ }
+
+ memh = BLI_mempool_alloc(pools[slot]);
+ memh->size = size;
+ memh->idcheck = MEMIDCHECK;
+ memh->tag = tag;
+ BLI_addtail(&active_mem, memh);
+ celltotblock++;
+
+ return memh + 1;
+}
+
+void *BLI_cellalloc_calloc(long size, char *tag)
+{
+ void *mem = BLI_cellalloc_malloc(size, tag);
+ BMEMSET(mem, 0, size);
+
+ return mem;
+}
+
+void BLI_cellalloc_free(void *mem)
+{
+ MemHeader *memh = mem;
+ int slot;
+
+#ifdef USE_GUARDEDALLOC
+ MEM_freeN(mem);
+ return;
+#endif
+ if (!memh)
+ return;
+
+ memh--;
+ if (memh->idcheck != MEMIDCHECK) {
+ printf("Error in BLI_cellalloc: attempt to free invalid block.\n");
+ return;
+ }
+
+ slot = memh->size + sizeof(MemHeader);
+ slot += 16 - (slot & 15);
+
+ if (memh->size > 0 && slot < totpool) {
+ BLI_remlink(&active_mem, memh);
+ BLI_mempool_free(pools[slot], memh);
+ celltotblock--;
+ } else {
+ printf("Error in BLI_cellalloc: attempt to free corrupted block.\n");
+ }
+}
+
+void BLI_cellalloc_printleaks(void)
+{
+ MemHeader *memh;
+
+ if (!active_mem.first) return;
+
+ for (memh=active_mem.first; memh; memh=memh->next) {
+ printf("%s %d %p\n", memh->tag, memh->size, memh+1);
+ }
+}
+
+int BLI_cellalloc_get_totblock(void)
+{
+ return celltotblock;
+}
+
+void BLI_cellalloc_destroy(void)
+{
+ int i;
+
+ for (i=0; i<totpool; i++) {
+ if (pools[i]) {
+ BLI_mempool_destroy(pools[i]);
+ pools[i] = NULL;
+ }
+ }
+} \ No newline at end of file
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 80cd507520c..c8918b11368 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -33,16 +33,19 @@
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
+#include "BLI_mempool.h"
#include "BLO_sys_types.h" // for intptr_t support
+#include "BKE_utildefines.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/***/
-static unsigned int hashsizes[]= {
+unsigned int hashsizes[]= {
1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
@@ -51,28 +54,14 @@ static unsigned int hashsizes[]= {
/***/
-typedef struct Entry Entry;
-struct Entry {
- Entry *next;
-
- void *key, *val;
-};
-
-struct GHash {
- GHashHashFP hashfp;
- GHashCmpFP cmpfp;
-
- Entry **buckets;
- int nbuckets, nentries, cursize;
-};
-
/***/
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), 1024, 1024);
+
gh->cursize= 0;
gh->nentries= 0;
gh->nbuckets= hashsizes[gh->cursize];
@@ -83,92 +72,9 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) {
return gh;
}
-void BLI_ghash_insert(GHash *gh, void *key, void *val) {
- unsigned int hash= gh->hashfp(key)%gh->nbuckets;
- Entry *e= malloc(sizeof(*e));
-
- e->key= key;
- e->val= val;
- e->next= gh->buckets[hash];
- gh->buckets[hash]= e;
-
- if (++gh->nentries>gh->nbuckets*3) {
- Entry *e, **old= gh->buckets;
- int i, nold= gh->nbuckets;
-
- gh->nbuckets= hashsizes[++gh->cursize];
- gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
- memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
-
- for (i=0; i<nold; i++) {
- for (e= old[i]; e;) {
- Entry *n= e->next;
-
- hash= gh->hashfp(e->key)%gh->nbuckets;
- e->next= gh->buckets[hash];
- gh->buckets[hash]= e;
-
- e= n;
- }
- }
-
- free(old);
- }
-}
-
-void* BLI_ghash_lookup(GHash *gh, void *key)
-{
- if(gh) {
- unsigned int hash= gh->hashfp(key)%gh->nbuckets;
- Entry *e;
-
- for (e= gh->buckets[hash]; e; e= e->next)
- if (gh->cmpfp(key, e->key)==0)
- return e->val;
- }
- return NULL;
-}
-
-int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
-{
- unsigned int hash= gh->hashfp(key)%gh->nbuckets;
- Entry *e;
- Entry *p = 0;
-
- for (e= gh->buckets[hash]; e; e= e->next) {
- if (gh->cmpfp(key, e->key)==0) {
- Entry *n= e->next;
-
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
- free(e);
-
-
- e= n;
- if (p)
- p->next = n;
- else
- gh->buckets[hash] = n;
-
- --gh->nentries;
- return 1;
- }
- p = e;
- }
-
- return 0;
-}
-
-int BLI_ghash_haskey(GHash *gh, void *key) {
- unsigned int hash= gh->hashfp(key)%gh->nbuckets;
- Entry *e;
-
- for (e= gh->buckets[hash]; e; e= e->next)
- if (gh->cmpfp(key, e->key)==0)
- return 1;
-
- return 0;
-}
+#ifdef BLI_ghash_insert
+#undef BLI_ghash_insert
+#endif
int BLI_ghash_size(GHash *gh) {
return gh->nentries;
@@ -177,21 +83,23 @@ int BLI_ghash_size(GHash *gh) {
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) {
int i;
- for (i=0; i<gh->nbuckets; i++) {
- Entry *e;
-
- for (e= gh->buckets[i]; e; ) {
- Entry *n= e->next;
-
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
- free(e);
+ if (keyfreefp || valfreefp) {
+ for (i=0; i<gh->nbuckets; i++) {
+ Entry *e;
- e= n;
+ for (e= gh->buckets[i]; e; ) {
+ Entry *n= e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+
+ 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 485ba7cbd08..9c4113bb13a 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -21,7 +21,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Geoffery Bantle
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -31,9 +31,14 @@
*/
#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
#include "BLI_blenlib.h"
-#include "DNA_listBase.h"
#include "BLI_linklist.h"
+
+#include "DNA_listBase.h"
+
#include <string.h>
typedef struct BLI_freenode{
@@ -60,6 +65,9 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk)
if (esize < sizeof(void*))
esize = sizeof(void*);
+ if (esize < sizeof(void*))
+ esize = sizeof(void*);
+
/*allocate the pool structure*/
pool = MEM_mallocN(sizeof(BLI_mempool),"memory pool");
pool->esize = esize;
@@ -68,7 +76,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");
@@ -88,6 +97,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;
@@ -123,7 +133,7 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
void *BLI_mempool_calloc(BLI_mempool *pool){
void *retval=NULL;
retval = BLI_mempool_alloc(pool);
- memset(retval, 0, pool->esize);
+ BMEMSET(retval, 0, pool->esize);
return retval;
}
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index 6c9ae78bac4..a5c4a03cdd6 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -131,6 +131,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];
@@ -138,6 +158,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)
{
@@ -885,7 +912,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;
@@ -1428,6 +1455,28 @@ void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3])
AxisAngleToQuat(q, axis, angle);
}
+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..5b98c3194bc 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -22,7 +22,7 @@
*
* The Original Code is: none of this file.
*
- * Contributor(s): Daniel Dunbar
+ * Contributor(s): Daniel Dunbar, Joseph Eagar
*
* ***** END GPL LICENSE BLOCK *****
* A general (pointer -> pointer) hash table ADT
@@ -33,112 +33,20 @@
#include "MEM_guardedalloc.h"
#include "BLI_edgehash.h"
-
-/***/
-
-static unsigned int hashsizes[]= {
- 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
- 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
- 268435459
-};
-
-#define EDGEHASH(v0,v1) ((v0*39)^(v1*31))
-
-/***/
-
-typedef struct Entry Entry;
-struct Entry {
- Entry *next;
- int v0, v1;
- void *val;
-};
-
-struct EdgeHash {
- Entry **buckets;
- int nbuckets, nentries, cursize;
-};
+#include "BLI_mempool.h"
/***/
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->nbuckets= _ehash_hashsizes[eh->cursize];
- return eh;
-}
-
-void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
- unsigned int hash;
- Entry *e= malloc(sizeof(*e));
+ eh->buckets= MEM_callocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets 2");
+ eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512);
- if (v1<v0) {
- v0 ^= v1;
- v1 ^= v0;
- v0 ^= v1;
- }
- hash = EDGEHASH(v0,v1)%eh->nbuckets;
-
- e->v0 = v0;
- e->v1 = v1;
- e->val = val;
- e->next= eh->buckets[hash];
- eh->buckets[hash]= e;
-
- if (++eh->nentries>eh->nbuckets*3) {
- Entry *e, **old= eh->buckets;
- int i, nold= eh->nbuckets;
-
- eh->nbuckets= hashsizes[++eh->cursize];
- eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
-
- for (i=0; i<nold; i++) {
- for (e= old[i]; e;) {
- Entry *n= e->next;
-
- hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
- e->next= eh->buckets[hash];
- eh->buckets[hash]= e;
-
- e= n;
- }
- }
-
- free(old);
- }
-}
-
-void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
- unsigned int hash;
- Entry *e;
-
- if (v1<v0) {
- v0 ^= v1;
- v1 ^= v0;
- v0 ^= v1;
- }
- hash = EDGEHASH(v0,v1)%eh->nbuckets;
- for (e= eh->buckets[hash]; e; e= e->next)
- if (v0==e->v0 && v1==e->v1)
- return &e->val;
-
- return NULL;
-}
-
-void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
- void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
-
- return value_p?*value_p:NULL;
-}
-
-int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
- return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+ return eh;
}
int BLI_edgehash_size(EdgeHash *eh) {
@@ -149,13 +57,13 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
int i;
for (i=0; i<eh->nbuckets; i++) {
- Entry *e;
+ EdgeEntry *e;
for (e= eh->buckets[i]; e; ) {
- Entry *n= e->next;
+ EdgeEntry *n= e->next;
if (valfreefp) valfreefp(e->val);
- free(e);
+ BLI_mempool_free(eh->epool, e);
e= n;
}
@@ -167,8 +75,10 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
BLI_edgehash_clear(eh, valfreefp);
-
- free(eh->buckets);
+
+ BLI_mempool_destroy(eh->epool);
+
+ MEM_freeN(eh->buckets);
MEM_freeN(eh);
}
@@ -178,11 +88,11 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
struct EdgeHashIterator {
EdgeHash *eh;
int curBucket;
- Entry *curEntry;
+ EdgeEntry *curEntry;
};
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 +105,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/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index bd9ed85efa2..df7d608027b 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -44,6 +45,8 @@
#include "BLI_scanfill.h"
#include "BLI_callbacks.h"
+#include "BKE_utildefines.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -152,7 +155,7 @@ static void *new_mem_element(int size)
{
int blocksize= 16384;
static int offs= 0; /* the current free adress */
- static struct mem_elements *cur= 0;
+ static struct mem_elements *cur= 0, *first;
static ListBase lb= {0, 0};
void *adr;
@@ -160,6 +163,10 @@ static void *new_mem_element(int size)
printf("incorrect use of new_mem_element\n");
}
else if(size== -1) {
+ /*keep the first block*/
+ first = lb.first;
+ BLI_remlink(&lb, first);
+
cur= lb.first;
while(cur) {
MEM_freeN(cur->data);
@@ -167,6 +174,12 @@ static void *new_mem_element(int size)
}
BLI_freelistN(&lb);
+ /*reset the block we're keeping*/
+ BLI_addtail(&lb, first);
+ memset(first->data, 0, blocksize);
+ cur = first;
+ offs = 0;
+
return NULL;
}
@@ -768,6 +781,7 @@ int BLI_edgefill(int mode, int mat_nr)
- struct elements xs en ys are not used here: don't hide stuff in it
- edge flag ->f becomes 2 when it's a new edge
- mode: & 1 is check for crossings, then create edges (TO DO )
+ - mode: & 2 is enable shortest diagonal test for quads
*/
ListBase tempve, temped;
EditVert *eve;
@@ -778,11 +792,42 @@ int BLI_edgefill(int mode, int mat_nr)
/* reset variables */
eve= fillvertbase.first;
+ a = 0;
while(eve) {
eve->f= 0;
eve->xs= 0;
eve->h= 0;
eve= eve->next;
+ a += 1;
+ }
+
+ if (a == 3) {
+ eve = fillvertbase.first;
+
+ addfillface(eve, eve->next, eve->next->next, 0);
+ return 1;
+ } else if (a == 4) {
+ float vec1[3], vec2[3];
+
+ eve = fillvertbase.first;
+
+ if (mode & 2) {
+ /*use shortest diagonal for quad*/
+ VecSubf(vec1, eve->co, eve->next->next->co);
+ VecSubf(vec2, eve->next->co, eve->next->next->next->co);
+
+ if (INPR(vec1, vec1) < INPR(vec2, vec2)) {
+ addfillface(eve, eve->next, eve->next->next, 0);
+ addfillface(eve->next->next, eve->next->next->next, eve, 0);
+ } else{
+ addfillface(eve->next, eve->next->next, eve->next->next->next, 0);
+ addfillface(eve->next->next->next, eve, eve->next, 0);
+ }
+ } else {
+ addfillface(eve, eve->next, eve->next->next, 0);
+ addfillface(eve->next->next, eve->next->next->next, eve, 0);
+ }
+ return 1;
}
/* first test vertices if they are in edges */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 0004187b1c6..8efdbdd1905 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -104,6 +104,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_storage_types.h" // for relname flags
+#include "BLI_cellalloc.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
@@ -3235,6 +3236,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;
@@ -3261,6 +3282,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);
@@ -3279,7 +3301,19 @@ static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
return;
for (i=0; i<count; i++) {
+ void *tmp;
+
mdverts[i].dw=newdataadr(fd, mdverts[i].dw);
+
+ /*convert to vgroup allocation system*/
+ if (mdverts[i].dw) {
+ tmp = BLI_cellalloc_malloc(MEM_allocN_len(mdverts[i].dw), "vgroups from readfile.c");
+ memcpy(tmp, mdverts[i].dw, MEM_allocN_len(mdverts[i].dw));
+
+ MEM_freeN(mdverts[i].dw);
+ mdverts[i].dw = tmp;
+ }
+
if (!mdverts[i].dw)
mdverts[i].totweight=0;
}
@@ -3298,6 +3332,8 @@ static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps)
}
}
+/*this isn't really a public api function, so prototyped here*/
+void customData_update_typemap(CustomData *data);
static void direct_link_customdata(FileData *fd, CustomData *data, int count)
{
int i = 0;
@@ -3314,6 +3350,126 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
i++;
}
}
+
+ customData_update_typemap(data);
+}
+
+
+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)
@@ -3324,12 +3480,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) {
@@ -3346,10 +3507,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);
@@ -3399,6 +3562,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 e3d061d8e4b..72e1b5b1b78 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1506,6 +1506,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/blenpluginapi/SConscript b/source/blender/blenpluginapi/SConscript
index b310bcb95ec..77faaa7b7f4 100644
--- a/source/blender/blenpluginapi/SConscript
+++ b/source/blender/blenpluginapi/SConscript
@@ -7,6 +7,8 @@ incs = '. .. #/intern/guardedalloc ../blenlib ../imbuf ../makesdna'
defs = []
+incs += ' ' + env["BF_PTHREADS_INC"]
+
if env['WITH_BF_QUICKTIME']:
defs.append('WITH_QUICKTIME')
incs += ' ' + env['BF_QUICKTIME_INC']
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
new file mode 100644
index 00000000000..b20ac35b575
--- /dev/null
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+FILE(GLOB SRC intern/*.c operators/*.c)
+
+SET(INC . intern
+ ../makesdna ../blenkernel ../blenlib ../../../intern/guardedalloc ../editors/include ../editors/mesh)
+
+BLENDERLIB(bf_bmesh "${SRC}" "${INC}")
+
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..fac86f79e23
--- /dev/null
+++ b/source/blender/bmesh/bmesh.h
@@ -0,0 +1,362 @@
+/**
+ * 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_scene_types.h"
+#include "DNA_customdata_types.h"
+
+#include "BKE_customdata.h"
+
+#include "BLI_mempool.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 BMesh;
+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 "header" flags/markings (sharp, seam, select, hidden, ect)
+ note that this is different from the "tool" flags.
+ * 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_LOOP 4
+#define BM_FACE 8
+#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
+
+/*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)
+#define BM_PINNED (1<<8)
+
+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; /*the element type, can be BM_VERT, BM_EDGE, BM_LOOP, or BM_FACE*/
+ int eflag1, eflag2; /*Flags used by eulers. Try and get rid of/minimize some of these*/
+
+ /*this is only used to store temporary integers.
+ don't use it for anything else.
+ use the BMINDEX_GET and BMINDEX_SET macros to access it*/
+ int index;
+ struct BMFlagLayer *flags; /*Dynamically allocated block of flag layers for operators to use*/
+ void *data; /*customdata block*/
+} 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;
+
+ /*selection order list*/
+ ListBase selected;
+
+ /*active face pointer*/
+ struct BMFace *act_face;
+} BMesh;
+
+typedef struct BMVert {
+ struct BMHeader head;
+ float co[3];
+ float no[3];
+ struct BMEdge *edge;
+ 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);
+
+/*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);
+
+/*rotates an edge topologically, either clockwise (if ccw=0) or counterclockwise
+ (if ccw is 1).*/
+BMEdge *BM_Rotate_Edge(BMesh *bm, BMEdge *e, int ccw);
+
+/*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);
+
+void BM_flip_normal(BMesh *bm, BMFace *f);
+
+/*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..4b53e023d3f
--- /dev/null
+++ b/source/blender/bmesh/bmesh_error.h
@@ -0,0 +1,55 @@
+#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
+#define BMERR_INVALID_SELECTION 9
+
+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",
+ "Invalid selection",
+};
+
+#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..cae022d66bd
--- /dev/null
+++ b/source/blender/bmesh/bmesh_iterators.h
@@ -0,0 +1,78 @@
+/*
+ * 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_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
+
+/*these are topological iterators.*/
+#define BM_EDGES_OF_VERT 4
+#define BM_FACES_OF_VERT 5
+#define BM_LOOPS_OF_VERT 6
+#define BM_FACES_OF_EDGE 7
+#define BM_VERTS_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
+
+#define BM_ITER(ele, iter, bm, type, data) \
+ ele = BMIter_New(iter, bm, type, data); \
+ for ( ; ele; ele=BMIter_Step(iter))
+
+#define BM_ITER_SELECT(ele, iter, bm, type, data)\
+for (ele = BMIter_New(iter, bm, type, data); ele; ele=BMIter_Step(iter)) {\
+ if (BM_TestHFlag(ele, BM_HIDDEN) || !BM_TestHFlag(ele, BM_SELECT)) continue;
+
+#define BM_ITER_NOTSELECT(ele, iter, bm, type, data)\
+for (ele = BMIter_New(iter, bm, type, data); ele; ele=BMIter_Step(iter)) {\
+ if (BM_TestHFlag(ele, BM_HIDDEN) || BM_TestHFlag(ele, BM_SELECT)) continue;
+
+
+/*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..1d80b297222
--- /dev/null
+++ b/source/blender/bmesh/bmesh_marking.h
@@ -0,0 +1,52 @@
+#ifndef BM_MARKING_H
+#define BM_MARKING_H
+
+typedef struct BMEditSelection
+{
+ struct BMEditSelection *next, *prev;
+ short type;
+ void *data;
+} BMEditSelection;
+
+/* pinning code */
+void BM_Pin(BMesh *bm, void *element, int pin);
+void BM_Pin_Vert(BMesh *bm, BMVert *v, int pin);
+void BM_Pin_Edge(BMesh *bm, BMEdge *e, int pin);
+void BM_Pin_Face(BMesh *bm, BMFace *f, int pin);
+
+/*geometry hiding code*/
+void BM_Hide(BMesh *bm, void *element, int hide);
+void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide);
+void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide);
+void BM_Hide_Face(BMesh *bm, BMFace *f, int hide);
+
+/*Selection code*/
+void BM_Select(struct BMesh *bm, void *element, int select);
+/*I don't use this function anywhere, been using BM_TestHFlag instead.
+ Need to decide either to keep it and convert everything over, or
+ chuck it.*/
+int BM_Selected(BMesh *bm, void *element);
+
+void BM_clear_flag_all(BMesh *bm, int flag);
+
+/*individual element select functions, BM_Select is a shortcut for these
+ that automatically detects which one to use*/
+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, int respectflag);
+
+/*edit selection stuff*/
+void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese);
+void BM_editselection_normal(float *normal, BMEditSelection *ese);
+void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese);
+void BM_remove_selection(BMesh *bm, void *data);
+void BM_store_selection(BMesh *bm, void *data);
+void BM_validate_selections(BMesh *bm);
+void BM_clear_selection_history(BMesh *em);
+
+#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..820f43a3094
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operator_api.h
@@ -0,0 +1,452 @@
+#ifndef _BMESH_OPERATOR_H
+#define _BMESH_OPERATOR_H
+
+#include "BLI_memarena.h"
+#include "BLI_ghash.h"
+
+#include "BKE_utildefines.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*/
+#define BMO_TestFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask & (flag))
+#define BMO_SetFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask |= (flag))
+#define BMO_ClearFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask &= ~(flag))
+
+/*profiling showed a significant amount of time spent in BMO_TestFlag
+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.
+ %e - pass in a single element.
+ %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);
+
+/*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);
+
+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]);
+
+void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag);
+
+/*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, int type);
+/*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, int type);
+
+/*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, int type);
+/*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, int type);
+
+/*puts every element of type type (which is a bitmask) with header flag
+ flag, into a slot. note: ignores hidden elements (e.g. elements with
+ header flag BM_HIDDEN set).*/
+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);
+int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, char *slotname);
+
+/*Counts the number of edges with tool flag toolflag around
+ v*/
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
+
+/*inserts a key/value mapping into a mapping slot. note that it copies the
+ value, it doesn't store a reference to it.*/
+//BM_INLINE 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.*/
+//BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
+ //void *element, float val);
+
+//returns 1 if the specified pointer is in the map.
+//BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, char *slotname, void *element);
+
+/*returns a point to the value of a specific key.*/
+//BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, char *slotname, void *element);
+
+/*returns the float part of a key/float pair.*/
+//BM_INLINE 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.*/
+//BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ //void *key, void *val);
+//BM_INLINE 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;
+
+void *BMO_FirstElem(BMOperator *op, char *slotname);
+
+/*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))
+
+/******************* Inlined Functions********************/
+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;
+
+extern const int BMOP_OPSLOT_TYPEINFO[];
+
+BM_INLINE 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);
+}
+
+
+BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, float val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
+}
+
+BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
+ void *element, void *val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
+}
+
+BM_INLINE 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);
+}
+
+BM_INLINE 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;
+}
+
+BM_INLINE 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;
+}
+
+BM_INLINE 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;
+}
+
+#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..620d7576141
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operators.h
@@ -0,0 +1,93 @@
+#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,
+};
+
+/*quad innervert values*/
+enum {
+ SUBD_INNERVERT,
+ SUBD_PATH,
+ SUBD_FAN,
+ SUBD_STRAIGHT_CUT,
+};
+
+/* similar face selection slot values */
+enum {
+ SIMFACE_MATERIAL = 201,
+ SIMFACE_IMAGE,
+ SIMFACE_AREA,
+ SIMFACE_PERIMETER,
+ SIMFACE_NORMAL,
+ SIMFACE_COPLANAR,
+};
+
+/* similar edge selection slot values */
+enum {
+ SIMEDGE_LENGTH = 101,
+ SIMEDGE_DIR,
+ SIMEDGE_FACE,
+ SIMEDGE_FACE_ANGLE,
+ SIMEDGE_CREASE,
+ SIMEDGE_SEAM,
+ SIMEDGE_SHARP,
+};
+
+/* similar vertex selection slot values */
+enum {
+ SIMVERT_NORMAL = 0,
+ SIMVERT_FACE,
+ SIMVERT_VGROUP,
+};
+
+enum {
+ OPUVC_AXIS_X = 1,
+ OPUVC_AXIS_Y
+};
+
+enum {
+ DIRECTION_CW = 1,
+ DIRECTION_CCW
+};
+
+/* vertex path selection values */
+enum {
+ VPATH_SELECT_EDGE_LENGTH = 0,
+ VPATH_SELECT_TOPOLOGICAL
+};
+
+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,
+ int cornertype, int singleedge, int gridfill);
+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..4f185d8725c
--- /dev/null
+++ b/source/blender/bmesh/bmesh_queries.h
@@ -0,0 +1,89 @@
+#ifndef BMESH_QUERIES_H
+#define BMESH_QUERIES_H
+#include <stdio.h>
+
+/*Queries*/
+
+/*get the area of face f*/
+float BM_face_area(BMFace *f);
+
+/*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_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 BMEdge *e, struct BMVert *v);
+
+/*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..3d6891c1c39
--- /dev/null
+++ b/source/blender/bmesh/bmesh_walkers.h
@@ -0,0 +1,73 @@
+#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;
+ int flag;
+} BMWalker;
+
+/*initialize a walker. searchmask restricts some (not all) walkers to
+ elements with a specific tool flag set. flags is specific to each walker.*/
+void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask, int flags);
+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.
+
+ takes a vert as an arugment, and spits out edges, restrict flag acts
+ on the edges as well.*/
+ BMW_SHELL,
+ /*walk over an edge loop. search flag doesn't do anything.*/
+ BMW_LOOP,
+ BMW_FACELOOP,
+ BMW_EDGERING,
+ /*#define BMW_RING 2*/
+ //walk over uv islands; takes a loop as input. restrict flag
+ //restricts the walking to loops whose vert has restrict flag set as a
+ //tool flag.
+ //
+ //the flag parameter to BMW_Init maps to a loop customdata layer index.
+ BMW_LOOPDATA_ISLAND,
+ /*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..3f26bcb6bfc
--- /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_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_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..c444927824a
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -0,0 +1,601 @@
+/**
+ * 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 "BLI_array.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
+ }*/
+
+ /*clear flags first*/
+ for(i = 0; i < len; i++){
+ BMO_ClearFlag(bm, edges[i]->v1, BM_EDGEVERT);
+ BMO_ClearFlag(bm, edges[i]->v2, BM_EDGEVERT);
+ }
+
+ 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);
+ } else return NULL;
+
+ 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_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;
+ BLI_array_declare(vtable);
+ BMEdge *e, *e2, **edges = NULL, **etable = NULL;
+ BLI_array_declare(edges);
+ BLI_array_declare(etable);
+ BMLoop *l, *l2, **loops = NULL;
+ BLI_array_declare(loops);
+ BMFace *f, *f2, **ftable = NULL;
+ BLI_array_declare(ftable);
+ BMEditSelection *ese;
+ BMIter iter, liter;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+ int i, j;
+
+ /*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);
+ BLI_array_growone(vtable);
+ VECCOPY(v2->no, v->no);
+
+ vtable[BLI_array_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);
+ BLI_array_growone(etable);
+ etable[BLI_array_count(etable)-1] = e2;
+
+ BMINDEX_SET(e, i);
+ BMINDEX_SET(e2, i);
+ }
+
+ f = BMIter_New(&iter, bmold, BM_FACES_OF_MESH, NULL);
+ for (i=0; f; f=BMIter_Step(&iter), i++) {
+ BLI_array_empty(loops);
+ BLI_array_empty(edges);
+ l = BMIter_New(&liter, bmold, BM_LOOPS_OF_FACE, f);
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
+ BLI_array_growone(loops);
+ BLI_array_growone(edges);
+ loops[j] = l;
+ edges[j] = 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[BLI_array_count(loops)-1]->v)];
+ v2 = vtable[BMINDEX_GET(loops[0]->v)];
+ }
+
+ f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
+
+ BMINDEX_SET(f, i);
+ BLI_array_growone(ftable);
+ ftable[i] = f2;
+
+ BM_Copy_Attributes(bmold, bm, f, f2);
+ VECCOPY(f2->no, f->no);
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f2);
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
+ BM_Copy_Attributes(bmold, bm, loops[j], l);
+ }
+
+ if (f == bmold->act_face) bm->act_face = f2;
+ }
+
+ /*copy over edit selection history*/
+ for (ese=bmold->selected.first; ese; ese=ese->next) {
+ void *ele;
+
+ if (ese->type == BM_VERT)
+ ele = vtable[BMINDEX_GET(ese->data)];
+ else if (ese->type == BM_EDGE)
+ ele = etable[BMINDEX_GET(ese->data)];
+ else if (ese->type == BM_FACE) {
+ ele = ftable[BMINDEX_GET(ese->data)];
+ }
+
+ BM_store_selection(bm, ele);
+ }
+
+ BLI_array_free(etable);
+ BLI_array_free(vtable);
+ BLI_array_free(ftable);
+
+ BLI_array_free(loops);
+ BLI_array_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_PINNED) f |= ME_PIN;
+ 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;
+ f |= ME_EDGEDRAW;
+ } else if (h->type == BM_VERT) {
+ if (h->flag & BM_SELECT) f |= BM_SELECT;
+ }
+
+ 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 (flag & ME_PIN) f |= BM_PINNED;
+
+ 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..746969a00e0
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_eulers.c
@@ -0,0 +1,1204 @@
+/**
+ * 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++) {
+ BMNode *diskbase;
+ BMEdge *curedge;
+ BMVert *v1;
+ int j;
+
+ for (j=0; j<2; j++) {
+ int a, len=0;
+
+ v1 = j ? elist[i]->v2 : elist[i]->v1;
+ diskbase = bmesh_disk_getpointer(v1->edge, v1);
+ len = bmesh_cycle_length(diskbase);
+
+ for(a=0,curedge=v1->edge;a<len;a++,curedge = bmesh_disk_nextedge(curedge,v1)){
+ curedge->head.eflag1 = curedge->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..76d0947c23d
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -0,0 +1,267 @@
+/**
+ * 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 "BLI_array.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);
+ }
+}
+
+/*
+ BM Data Vert Average
+
+ Sets all the customdata (e.g. vert, loop) associated with a vert
+ to the average of the face regions surrounding it.
+*/
+
+//CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);
+
+void BM_Data_Vert_Average(BMesh *bm, BMFace *f)
+{
+ BMIter iter;
+
+
+}
+
+/**
+ * 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;
+ BLI_mempool *oldpool = olddata->pool;
+ void *block;
+
+ CustomData_bmesh_init_pool(data, data==&bm->ldata ? 2048 : 512);
+
+ 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_DEFAULT, 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..1c88c16acc2
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -0,0 +1,438 @@
+#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;
+}
+
+
+/*
+ * LOOP OF VERT CALLBACKS
+ *
+*/
+
+static void loop_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 *loop_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;
+ 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_LOOPS_OF_VERT:
+ iter->begin = loop_of_vert_begin;
+ iter->step = loop_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..20557451a03
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -0,0 +1,710 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <string.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*/
+ switch (bm->selectmode) {
+ case SCE_SELECT_VERTEX:
+ case SCE_SELECT_EDGE:
+ case SCE_SELECT_FACE:
+ case SCE_SELECT_EDGE|SCE_SELECT_FACE:
+ testiso = 1;
+ break;
+ default:
+ testiso = 0;
+ break;
+ }
+
+ 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_Select(bm, e->v1, 1);
+ BM_Select(bm, e->v2, 1);
+ }
+ 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_Select_Vert(bm, l->v, 1);
+ BM_Select_Edge(bm, l->e, 1);
+ l = ((BMLoop*)(l->head.next));
+ }while(l != f->loopbase);
+ }
+ else{
+ BMIter liter, fiter, eiter;
+ BMFace *f2;
+ BMLoop *l;
+ BMEdge *e;
+
+ if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
+ BM_ClearHFlag(&(f->head), BM_SELECT);
+
+ /*flush down to edges*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (BM_TestHFlag(f2, BM_SELECT))
+ break;
+ }
+
+ if (!f2) {
+ BM_Select(bm, l->e, 0);
+ }
+ }
+
+ /*flush down to verts*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, l->v) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ break;
+ }
+
+ if (!e) {
+ BM_Select(bm, l->v, 0);
+ }
+ }
+ }
+}
+
+/*
+ * 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, int respecthide)
+{
+ 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 (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ 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 (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ 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 (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (head->flag & flag) tot++;
+ }
+ }
+
+ return tot;
+}
+
+/*note: by design, this will not touch the editselection history stuff*/
+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_Selected(BMesh *bm, void *element)
+{
+ BMHeader *head = element;
+ return BM_TestHFlag(head, BM_SELECT);
+}
+
+
+/* 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 BM_editselection_center(BMesh *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, efa, center);
+ }
+}
+
+void BM_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 BM_editselection_plane(BMesh *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 */
+ BM_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 //BMESH_TODO
+
+ 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 BM_check_selection(BMesh *em, void *data)
+{
+ BMEditSelection *ese;
+
+ for(ese = em->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void BM_remove_selection(BMesh *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 BM_clear_selection_history(BMesh *em)
+{
+ BLI_freelistN(&em->selected);
+ em->selected.first = em->selected.last = NULL;
+}
+
+void BM_store_selection(BMesh *em, void *data)
+{
+ BMEditSelection *ese;
+ if(!BM_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 BM_validate_selections(BMesh *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;
+ }
+}
+
+void BM_clear_flag_all(BMesh *bm, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ if (flag & BM_SELECT)
+ BM_clear_selection_history(bm);
+
+ 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, bm, type, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (flag & BM_SELECT) BM_Select(bm, ele, 0);
+ BM_ClearHFlag(ele, flag);
+ }
+ }
+}
+
+
+/***************** Pinning **************/
+
+#define SETPIN(ele) pin ? BM_SetHFlag(ele, BM_PINNED) : BM_ClearHFlag(ele, BM_PINNED);
+
+
+void BM_Pin_Vert(BMesh *bm, BMVert *v, int pin)
+{
+ SETPIN(v);
+}
+
+void BM_Pin_Edge(BMesh *bm, BMEdge *e, int pin)
+{
+ SETPIN(e->v1);
+ SETPIN(e->v2);
+}
+
+void BM_Pin_Face(BMesh *bm, BMFace *f, int pin)
+{
+ BMIter vfiter;
+ BMVert *vf;
+
+ BM_ITER(vf, &vfiter, bm, BM_VERTS_OF_FACE, f) {
+ SETPIN(vf);
+ }
+}
+
+void BM_Pin(BMesh *bm, void *element, int pin)
+{
+ BMHeader *h = element;
+
+ switch (h->type) {
+ case BM_VERT:
+ BM_Pin_Vert(bm, element, pin);
+ break;
+ case BM_EDGE:
+ BM_Pin_Edge(bm, element, pin);
+ break;
+ case BM_FACE:
+ BM_Pin_Face(bm, element, pin);
+ break;
+ }
+}
+
+
+
+/***************** Mesh Hiding stuff *************/
+
+#define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
+
+static void vert_flush_hide(BMesh *bm, BMVert *v) {
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BM_TestHFlag(e, BM_HIDDEN))
+ return;
+ }
+
+ BM_SetHFlag(v, BM_HIDDEN);
+}
+
+static void edge_flush_hide(BMesh *bm, BMEdge *e) {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ if (!BM_TestHFlag(f, BM_HIDDEN))
+ return;
+ }
+
+ BM_SetHFlag(e, BM_HIDDEN);
+}
+
+void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
+{
+ /*vert hiding: vert + surrounding edges and faces*/
+ BMIter iter, fiter;
+ BMEdge *e;
+ BMFace *f;
+
+ SETHIDE(v);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ SETHIDE(e);
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+ }
+}
+
+void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
+{
+ BMIter iter;
+ BMFace *f;
+ BMVert *v;
+
+ /*edge hiding: faces around the edge*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+
+ SETHIDE(e);
+
+ /*hide vertices if necassary*/
+ vert_flush_hide(bm, e->v1);
+ vert_flush_hide(bm, e->v2);
+}
+
+void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
+{
+ BMIter iter;
+ BMLoop *l;
+
+ /**/
+ SETHIDE(f);
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ edge_flush_hide(bm, l->e);
+ }
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ vert_flush_hide(bm, l->v);
+ }
+}
+
+void BM_Hide(BMesh *bm, void *element, int hide)
+{
+ BMHeader *h = element;
+
+ switch (h->type) {
+ case BM_VERT:
+ BM_Hide_Vert(bm, element, hide);
+ break;
+ case BM_EDGE:
+ BM_Hide_Edge(bm, element, hide);
+ break;
+ case BM_FACE:
+ BM_Hide_Face(bm, element, hide);
+ break;
+ }
+}
+
+
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
new file mode 100644
index 00000000000..4ca436ea7fc
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -0,0 +1,304 @@
+/**
+ * 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);
+
+ if (bm->edar) MEM_freeN(bm->edar);
+ if (bm->vtar) MEM_freeN(bm->vtar);
+ if (bm->plar) MEM_freeN(bm->plar);
+
+ BLI_freelistN(&bm->selected);
+
+ 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*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+
+ 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*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+ if (f->head.flag & BM_NONORMCALC)
+ continue;
+
+ bmesh_update_face_normal(bm, f, projectverts);
+ }
+
+ /*Zero out vertex normals*/
+ BM_ITER(v, &verts, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ v->no[0] = v->no[1] = v->no[2] = 0.0;
+ }
+
+ /*add face normals to vertices*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+
+ 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*/
+ BM_ITER(v, &verts, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ 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){
+ 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);
+
+ /*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..33b131f5f1d
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -0,0 +1,465 @@
+#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 "BLI_array.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) {
+ (*ne)->head.flag = e->head.flag;
+ BM_Copy_Attributes(bm, bm, e, *ne);
+ }
+
+ /*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;
+ BLI_array_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)) {
+ BLI_array_growone(verts);
+ verts[BLI_array_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<BLI_array_count(verts); i++) {
+ for (j=0; j<BLI_array_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;
+ }
+ }
+ }
+
+ BLI_array_free(verts);
+ return ret;
+}
+
+/*
+ BM Rotate Edge
+
+ Spins an edge topologically, either counter-clockwise or clockwise.
+ If ccw is true, the edge is spun counter-clockwise, otherwise it is
+ spun clockwise.
+
+ Returns the spun edge. Note that this works by dissolving the edge
+ then re-creating it, so the returned edge won't have the same pointer
+ address as the original one.
+
+ Returns NULL on error (e.g., if the edge isn't surrounded by exactly
+ two faces).
+*/
+BMEdge *BM_Rotate_Edge(BMesh *bm, BMEdge *e, int ccw)
+{
+ BMVert *v1, *v2;
+ BMLoop *l, *l1, *l2, *nl;
+ BMFace *f;
+ BMIter liter;
+
+ v1 = e->v1;
+ v2 = e->v2;
+
+ if (BM_Edge_FaceCount(e) != 2)
+ return NULL;
+
+ f = BM_Join_Faces(bm, e->loop->f, ((BMLoop*)e->loop->radial.next->data)->f, e);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (l->v == v1)
+ l1 = l;
+ else if (l->v == v2)
+ l2 = l;
+ }
+
+ if (ccw) {
+ l1 = (BMLoop*) l1->head.prev;
+ l2 = (BMLoop*) l2->head.prev;
+ } else {
+ l1 = (BMLoop*) l1->head.next;
+ l2 = (BMLoop*) l2->head.next;
+ }
+
+ if (!BM_Split_Face(bm, f, l1->v, l2->v, &nl, NULL))
+ return NULL;
+
+ return nl->e;
+}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
new file mode 100644
index 00000000000..f61cf451944
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -0,0 +1,894 @@
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include <stdio.h>
+
+/*
+This file defines (and documents) all bmesh operators (bmops).
+
+Do not rename any operator or slot names! otherwise you must go
+through the code and find all references to them!
+
+A word on slot names:
+
+For geometry input slots, the following are valid names:
+* verts
+* edges
+* faces
+* edgefacein
+* vertfacein
+* vertedgein
+* vertfacein
+* geom
+
+The basic rules are, for single-type geometry slots, use the plural of the
+type name (e.g. edges). for double-type slots, use the two type names plus
+"in" (e.g. edgefacein). for three-type slots, use geom.
+
+for output slots, for single-type geometry slots, use the type name plus "out",
+(e.g. vertout), for double-type slots, use the two type names plus "out",
+(e.g. vertfaceout), for three-type slots, use geom. note that you can also
+use more esohteric names (e.g. skirtout) do long as the comment next to the
+slot definition tells you what types of elements are in it.
+
+*/
+
+/*
+ok, I'm going to write a little docgen script. so all
+bmop comments must conform to the following template/rules:
+
+template (py quotes used because nested comments don't work
+on all C compilers):
+
+"""
+Region Extend.
+
+paragraph1, Extends bleh bleh bleh.
+Bleh Bleh bleh.
+
+Another paragraph.
+
+Another paragraph.
+"""
+
+so the first line is the "title" of the bmop.
+subsequent line blocks seperated by blank lines
+are paragraphs. individual descriptions of slots
+would be extracted from comments
+next to them, e.g.
+
+{BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region
+
+the doc generator would automatically detect the presence of "output slot"
+and flag the slot as an output. the same happens for "input slot". also
+note that "edges", "faces", "verts", "loops", and "geometry" are valid
+substitutions for "slot".
+
+note that slots default to being input slots.
+*/
+
+/*
+ Vertex Smooth
+
+ Smoothes vertices by using a basic vertex averaging scheme.
+*/
+BMOpDefine def_vertexsmooth = {
+ "vertexsmooth",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_INT, "mirror_clip_x"}, //set vertices close to the x axis before the operation to 0
+ {BMOP_OPSLOT_INT, "mirror_clip_y"}, //set vertices close to the y axis before the operation to 0
+ {BMOP_OPSLOT_INT, "mirror_clip_z"}, //set vertices close to the z axis before the operation to 0
+ {BMOP_OPSLOT_FLT, "clipdist"}, //clipping threshod for the above three slots
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_vertexsmooth_exec,
+ 0
+};
+
+/*
+ Right-Hand Faces
+
+ Computes an "outside" normal for the specified input faces.
+*/
+
+BMOpDefine def_righthandfaces = {
+ "righthandfaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_righthandfaces_exec,
+ 0
+};
+
+/*
+ Region Extend
+
+ used to implement the select more/less tools.
+ this puts some geometry surrounding regions of
+ geometry in geom into geomout.
+
+ if usefaces is 0 then geomout spits out verts and edges,
+ otherwise it spits out faces.
+ */
+BMOpDefine def_regionextend = {
+ "regionextend",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output slot, computed boundary geometry.
+ {BMOP_OPSLOT_INT, "constrict"}, //find boundary inside the regions, not outside.
+ {BMOP_OPSLOT_INT, "usefaces"}, //extend from faces instead of edges
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_regionextend_exec,
+ 0
+};
+
+/*
+ Edge Rotate
+
+ Rotates edges topologically. Also known as "spin edge" to some people.
+ Simple example: [/] becomes [|] then [\].
+*/
+BMOpDefine def_edgerotate = {
+ "edgerotate",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //newly spun edges
+ {BMOP_OPSLOT_INT, "ccw"}, //rotate edge counter-clockwise if true, othewise clockwise
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_edgerotate_exec,
+ 0
+};
+
+/*
+ Reverse Faces
+
+ Reverses the winding (vertex order) of faces. This has the effect of
+ flipping the normal.
+*/
+BMOpDefine def_reversefaces = {
+ "reversefaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input faces
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_reversefaces_exec,
+ 0
+};
+
+/*
+ Edge Bisect
+
+ Splits input edges (but doesn't do anything else).
+ This creates a 2-valence vert.
+*/
+BMOpDefine def_edgebisect = {
+ "edgebisect",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_INT, "numcuts"}, //number of cuts
+ {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"}, //newly created vertices and edges
+ {0} /*null-terminating sentinel*/,
+ },
+ esplit_exec,
+ 0
+};
+
+/*
+ Mirror
+
+ Mirrors geometry along an axis. The resulting geometry is welded on using
+ mergedist. Pairs of original/mirrored vertices are welded using the mergedist
+ parameter (which defines the minimum distance for welding to happen).
+*/
+
+BMOpDefine def_mirror = {
+ "mirror",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix defining the mirror transformation
+ {BMOP_OPSLOT_FLT, "mergedist"}, //maximum distance for merging. does no merging if 0.
+ {BMOP_OPSLOT_ELEMENT_BUF, "newout"}, //output geometry, mirrored
+ {BMOP_OPSLOT_INT, "axis"}, //the axis to use, 0, 1, or 2 for x, y, z
+ {BMOP_OPSLOT_INT, "mirror_u"}, //mirror UVs across the u axis
+ {BMOP_OPSLOT_INT, "mirror_v"}, //mirror UVs across the v axis
+ {0, /*null-terminating sentinel*/}},
+ bmesh_mirror_exec,
+ 0,
+};
+
+/*
+ Find Doubles
+
+ Takes input verts and find vertices they should weld to. Outputs a
+ mapping slot suitable for use with the weld verts bmop.
+*/
+BMOpDefine def_finddoubles = {
+ "finddoubles",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "keepverts"}, //list of verts to keep
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {BMOP_OPSLOT_MAPPING, "targetmapout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_finddoubles_exec,
+ 0,
+};
+
+/*
+ Remove Doubles
+
+ Finds groups of vertices closer then dist and merges them together,
+ using the weld verts bmop.
+*/
+BMOpDefine def_removedoubles = {
+ "removedoubles",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input verts
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {0, /*null-terminating sentinel*/}},
+ bmesh_removedoubles_exec,
+ 0,
+};
+
+/*
+ Auto Merge
+
+ Finds groups of vertices closer then dist and merges them together,
+ using the weld verts bmop. The merges must go from a vert not in
+ verts to one in verts.
+*/
+BMOpDefine def_automerge = {
+ "automerge",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input verts
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {0, /*null-terminating sentinel*/}},
+ bmesh_automerge_exec,
+ 0,
+};
+
+/*
+ Collapse Connected
+
+ Collapses connected vertices
+*/
+BMOpDefine def_collapse = {
+ "collapse",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_collapse_exec,
+ 0,
+};
+
+
+/*
+ Facedata point Merge
+
+ Merge uv/vcols at a specific vertex.
+*/
+BMOpDefine def_pointmerge_facedata = {
+ "pointmerge_facedata",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "snapv"}, /*snap vertex*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_pointmerge_facedata_exec,
+ 0,
+};
+
+/*
+ Average Vertices Facevert Data
+
+ Merge uv/vcols associated with the input vertices at
+ the bounding box center. (I know, it's not averaging but
+ the vert_snap_to_bb_center is just too long).
+*/
+BMOpDefine def_vert_average_facedata = {
+ "vert_average_facedata",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_vert_average_facedata_exec,
+ 0,
+};
+
+/*
+ Point Merge
+
+ Merge verts together at a point.
+*/
+BMOpDefine def_pointmerge = {
+ "pointmerge",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {BMOP_OPSLOT_VEC, "mergeco"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_pointmerge_exec,
+ 0,
+};
+
+/*
+ Collapse Connected UVs
+
+ Collapses connected UV vertices.
+*/
+BMOpDefine def_collapse_uvs = {
+ "collapse_uvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_collapsecon_exec,
+ 0,
+};
+
+/*
+ Weld Verts
+
+ Welds verts together (kindof like remove doubles, merge, etc, all of which
+ use or will use this bmop). You pass in mappings from vertices to the vertices
+ they weld with.
+*/
+BMOpDefine def_weldverts = {
+ "weldverts",
+ {{BMOP_OPSLOT_MAPPING, "targetmap"}, /*maps welded vertices to verts they should weld to.*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_weldverts_exec,
+ 0,
+};
+
+/*
+ Make Vertex
+
+ Creates a single vertex; this bmop was necassary
+ for click-create-vertex.
+*/
+BMOpDefine def_makevert = {
+ "makevert",
+ {{BMOP_OPSLOT_VEC, "co"}, //the coordinate of the new vert
+ {BMOP_OPSLOT_ELEMENT_BUF, "newvertout"}, //the new vert
+ {0, /*null-terminating sentinel*/}},
+ bmesh_makevert_exec,
+ 0,
+};
+
+/*
+ Contextual Create
+
+ This is basically fkey, it creates
+ new faces from vertices, makes stuff from edge nets,
+ makes wire edges, etc. It also dissolves
+ faces.
+
+ Three verts become a triangle, four become a quad. Two
+ become a wire edge.
+ */
+BMOpDefine def_contextual_create= {
+ "contextual_create",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry.
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //newly-made face(s)
+ {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,
+};
+
+/*
+ Edgenet Prepare
+
+ Identifies several useful edge loop cases and modifies them so
+ they'll become a face when edgenet_fill is called. The cases covered are:
+
+ * One single loop; an edge is added to connect the ends
+ * Two loops; two edges are added to connect the endpoints (based on the
+ shortest distance between each endpont).
+*/
+BMOpDefine def_edgenet_prepare= {
+ "edgenet_prepare",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //new edges
+ {0, /*null-terminating sentinel*/}},
+ bmesh_edgenet_prepare,
+ 0,
+};
+
+/*
+ Rotate
+
+ Rotate vertices around a center, using a 3x3 rotation
+ matrix. Equivilent of the old rotateflag function.
+*/
+BMOpDefine def_rotate = {
+ "rotate",
+ {{BMOP_OPSLOT_VEC, "cent"}, //center of rotation
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix defining rotation
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_rotate_exec,
+ 0,
+};
+
+/*
+ Translate
+
+ Translate vertices by an offset. Equivelent of the
+ old translateflag function.
+*/
+BMOpDefine def_translate= {
+ "translate",
+ {{BMOP_OPSLOT_VEC, "vec"}, //translation offset
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_translate_exec,
+ 0,
+};
+
+/*
+ Scale
+
+ Scales vertices by an offset.
+*/
+BMOpDefine def_scale= {
+ "scale",
+ {{BMOP_OPSLOT_VEC, "vec"}, //scale factor
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_scale_exec,
+ 0,
+};
+
+
+/*
+ Transform
+
+ Transforms a set of vertices by a matrix. Multiplies
+ the vertex coordinates with the matrix.
+*/
+BMOpDefine def_transform = {
+ "transform",
+ {{BMOP_OPSLOT_MAT, "mat"}, //transform matrix
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_transform_exec,
+ 0,
+};
+
+/*
+ Object Load BMesh
+
+ Loads a bmesh into an object/mesh. This is a "private"
+ bmop.
+*/
+BMOpDefine def_object_load_bmesh = {
+ "object_load_bmesh",
+ {{BMOP_OPSLOT_PNT, "scene"},
+ {BMOP_OPSLOT_PNT, "object"},
+ {0, /*null-terminating sentinel*/}},
+ object_load_bmesh_exec,
+ 0,
+};
+
+
+/*
+ BMesh to Mesh
+
+ Converts a bmesh to a Mesh
+*/
+BMOpDefine def_bmesh_to_mesh = {
+ "bmesh_to_mesh",
+ {{BMOP_OPSLOT_PNT, "meshptr"}, //pointer to a mesh structure to fill in
+ {BMOP_OPSLOT_INT, "notesselation"}, //don't calculate mfaces
+ {0, /*null-terminating sentinel*/}},
+ bmesh_to_mesh_exec,
+ 0,
+};
+
+/*
+ Mesh to BMesh
+
+ Load the contents of a mesh into the bmesh.
+*/
+BMOpDefine def_mesh_to_bmesh = {
+ "mesh_to_bmesh",
+ {{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a Mesh structure
+ {0, /*null-terminating sentinel*/}},
+ mesh_to_bmesh_exec,
+ 0
+};
+
+/*
+ Individual Face Extrude
+
+ Extrudes faces individually.
+*/
+BMOpDefine def_extrude_indivface = {
+ "extrude_face_indiv",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input faces
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //output faces
+ {BMOP_OPSLOT_ELEMENT_BUF, "skirtout"}, //output skirt geometry, faces and edges
+ {0} /*null-terminating sentinel*/},
+ bmesh_extrude_face_indiv_exec,
+ 0
+};
+
+/*
+ Extrude Only Edges
+
+ Extrudes Edges into faces, note that this is very simple, there's no fancy
+ winged extrusion.
+*/
+BMOpDefine def_extrude_onlyedge = {
+ "extrude_edge_only",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output geometry
+ {0} /*null-terminating sentinel*/},
+ bmesh_extrude_onlyedge_exec,
+ 0
+};
+
+/*
+ Individual Vertex Extrude
+
+ Extrudes wire edges from vertices.
+*/
+BMOpDefine def_extrudeverts_indiv = {
+ "extrude_vert_indiv",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //output wire edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output vertices
+ {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"},
+
+ {BMOP_OPSLOT_INT, "quadcornertype"}, //quad corner type, see bmesh_operators.h
+ {BMOP_OPSLOT_INT, "gridfill"}, //fill in fully-selected faces with a grid
+ {BMOP_OPSLOT_INT, "singleedge"}, //tesselate the case of one edge selected in a quad or triangle
+
+ {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
+};
+
+/*
+ Similar faces select
+
+ Select similar faces (area/material/perimeter....).
+*/
+BMOpDefine def_similarfaces = {
+ "similarfaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /* output faces */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similarfaces_exec,
+ 0
+};
+
+/*
+ Similar edges select
+
+ Select similar edges (length, direction, edge, seam,....).
+*/
+BMOpDefine def_similaredges = {
+ "similaredges",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, /* output edges */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similaredges_exec,
+ 0
+};
+
+/*
+ Similar vertices select
+
+ Select similar vertices (normal, face, vertex group,....).
+*/
+BMOpDefine def_similarverts = {
+ "similarverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /* input vertices */
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similarverts_exec,
+ 0
+};
+
+/*
+** uv rotation
+** cycle the uvs
+*/
+BMOpDefine def_meshrotateuvs = {
+ "meshrotateuvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_INT, "dir"}, /* direction */
+ {0} /*null-terminating sentinel*/},
+ bmesh_rotateuvs_exec,
+ 0
+};
+
+/*
+** uv reverse
+** reverse the uvs
+*/
+BMOpDefine def_meshreverseuvs = {
+ "meshreverseuvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0} /*null-terminating sentinel*/},
+ bmesh_reverseuvs_exec,
+ 0
+};
+
+/*
+** color rotation
+** cycle the colors
+*/
+BMOpDefine def_meshrotatecolors = {
+ "meshrotatecolors",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_INT, "dir"}, /* direction */
+ {0} /*null-terminating sentinel*/},
+ bmesh_rotatecolors_exec,
+ 0
+};
+
+/*
+** color reverse
+** reverse the colors
+*/
+BMOpDefine def_meshreversecolors = {
+ "meshreversecolors",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0} /*null-terminating sentinel*/},
+ bmesh_reversecolors_exec,
+ 0
+};
+
+/*
+ Similar vertices select
+
+ Select similar vertices (normal, face, vertex group,....).
+*/
+BMOpDefine def_vertexshortestpath = {
+ "vertexshortestpath",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "startv"}, /* start vertex */
+ {BMOP_OPSLOT_ELEMENT_BUF, "endv"}, /* end vertex */
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_vertexshortestpath_exec,
+ 0
+};
+
+/*
+ Edge Split
+
+ Disconnects faces along input edges.
+ */
+BMOpDefine def_edgesplit = {
+ "edgesplit",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout1"}, /* old output disconnected edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout2"}, /* new output disconnected edges */
+ {0} /*null-terminating sentinel*/},
+ bmesh_edgesplitop_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,
+ &def_mirror,
+ &def_edgebisect,
+ &def_reversefaces,
+ &def_edgerotate,
+ &def_regionextend,
+ &def_righthandfaces,
+ &def_vertexsmooth,
+ &def_extrude_onlyedge,
+ &def_extrude_indivface,
+ &def_collapse_uvs,
+ &def_pointmerge,
+ &def_collapse,
+ &def_similarfaces,
+ &def_similaredges,
+ &def_similarverts,
+ &def_pointmerge_facedata,
+ &def_vert_average_facedata,
+ &def_meshrotateuvs,
+ &def_bmesh_to_mesh,
+ &def_meshreverseuvs,
+ &def_edgenet_prepare,
+ &def_meshrotatecolors,
+ &def_meshreversecolors,
+ &def_vertexshortestpath,
+ &def_scale,
+ &def_edgesplit,
+ &def_automerge,
+};
+
+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..da2f98f6db8
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -0,0 +1,1309 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.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);
+
+/*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_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;
+}
+
+void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag) {
+ BMIter iter;
+ BMHeader *ele;
+ int i=0, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ for (i=0; i<3; i++) {
+ if (i==0 && !(type & BM_VERT))
+ continue;
+ if (i==1 && !(type & BM_EDGE))
+ continue;
+ if (i==2 && !(type & BM_FACE))
+ continue;
+
+ BM_ITER(ele, &iter, bm, types[i], NULL) {
+ BMO_ClearFlag(bm, ele, flag);
+ }
+ }
+}
+
+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;
+}
+
+int BMO_CountSlotMap(BMesh *bm, BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype == BMOP_OPSLOT_MAPPING) )
+ return 0;
+
+ return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
+}
+
+#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_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);
+ }
+}
+
+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, 1);
+
+ 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(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(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(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(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(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, 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, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ if (flag & BM_SELECT)
+ BM_Select(bm, data[i], 1);
+ BM_SetHFlag(data[i], flag);
+ }
+}
+
+/*
+ *
+ * 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, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ if (flag & BM_SELECT)
+ BM_Select(bm, data[i], 0);
+ BM_ClearHFlag(data[i], flag);
+ }
+}
+
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag)
+{
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0, count=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 (BMO_TestFlag(bm, curedge, toolflag))
+ count++;
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+
+ return count;
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Flags elements in a slots buffer
+ *
+*/
+
+void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ 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, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ 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_FirstElem(BMOperator *op, char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ if (slot->slottype != BMOP_OPSLOT_ELEMENT_BUF)
+ return NULL;
+
+ return slot->data.buf ? *(void**)slot->data.buf : NULL;
+}
+
+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 'e': {
+ BMHeader *ele = va_arg(vlist, void*);
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void*)*4);
+ slot->len = 1;
+ *((void**)slot->data.buf) = ele;
+
+ 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, format is:\n \"%s\"\n", fmt);
+ va_end(list);
+ return 0;
+ }
+
+ BMO_Exec_Op(bm, &op);
+ BMO_Finish_Op(bm, &op);
+
+ va_end(list);
+ return 1;
+}
+
+
+/*
+ * BMO_SETFLAG
+ *
+ * Sets a flag for a certain element
+ *
+*/
+#ifdef BMO_SetFlag
+#undef BMO_SetFlag
+#endif
+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
+ *
+*/
+
+#ifdef BMO_ClearFlag
+#undef BMO_ClearFlag
+#endif
+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
+ *
+ *
+*/
+
+#ifdef BMO_TestFlag
+#undef BMO_TestFlag
+#endif
+int BMO_TestFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ if(head->flags[bm->stackdepth-1].mask & flag)
+ return 1;
+ return 0;
+}
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..e5e05921195
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -0,0 +1,65 @@
+#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);
+void bmesh_mirror_exec(BMesh *bm, BMOperator *op);
+void esplit_exec(BMesh *bm, BMOperator *op);
+void bmesh_reversefaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op);
+void bmesh_regionextend_exec(BMesh *bm, BMOperator *op);
+void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op);
+void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op);
+void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op);
+void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op);
+void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op);
+void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
+void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_similaredges_exec(BMesh *bm, BMOperator *op);
+void bmesh_similarverts_exec(BMesh *bm, BMOperator *op);
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
+void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op);
+void object_load_bmesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op);
+void bmesh_rotatecolors_exec(BMesh *bm, BMOperator *op);
+void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op);
+void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op);
+void bmesh_scale_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgesplitop_exec(BMesh *bm, BMOperator *op);
+void bmesh_automerge_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..072f0a4bbb4
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -0,0 +1,912 @@
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.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.
+ *
+*/
+#define FEQ(f1, f2) (ABS((double)(f1)-(double)(f2)) < 0.1)
+
+static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
+{
+
+ double u[3], v[3], w[3];/*, *w, v1[3], v2[3];*/
+ double n[3] = {0.0, 0.0, 0.0}, l, v1[3], v2[3];
+ double l2;
+ int i, s=0;
+
+ /*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++){
+ VECCOPY(u, verts[i]);
+ VECCOPY(v, verts[(i+1) % nverts]);
+ VECCOPY(w, verts[(i+2) % nverts]);
+
+#if 0
+ VECSUB(v1, w, v);
+ VECSUB(v2, v, u);
+ Normalize_d(v1);
+ Normalize_d(v2);
+
+ l = INPR(v1, v2);
+ if (ABS(l-1.0) < 0.1)
+ continue;
+#endif
+ /* 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 = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ l = sqrt(l);
+ /*fast square root, newton/babylonian method:
+ l2 = l*0.1;
+
+ l2 = (l/l2 + l2)*0.5;
+ l2 = (l/l2 + l2)*0.5;
+ l2 = (l/l2 + l2)*0.5;
+ */
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ } else l = 1.0f / l;
+
+ 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;
+}
+
+float BM_face_area(BMFace *f)
+{
+ BMLoop *l;
+ BMIter iter;
+ float (*verts)[3], stackv[100][3];
+ float area, center[3];
+ int i;
+
+ if (f->len <= 100)
+ verts = stackv;
+ else verts = MEM_callocN(sizeof(float)*f->len*3, "bm_face_area tmp");
+
+ i = 0;
+ BM_ITER(l, &iter, NULL, BM_LOOPS_OF_FACE, f) {
+ VECCOPY(verts[i], l->v->co);
+ i++;
+ }
+
+ compute_poly_center(center, &area, verts, f->len);
+
+ if (f->len > 100)
+ MEM_freeN(verts);
+
+ return area;
+}
+/*
+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[200][3];
+ float (*proj)[3] = f->len < 200 ? 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_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 face.
+ * Note that this updates the calculated
+ * normal.
+*/
+void BM_flip_normal(BMesh *bm, BMFace *f)
+{
+ bmesh_loop_reverse(bm, f);
+ BM_Face_UpdateNormal(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, ret;
+
+/* 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);*/
+
+ /*do an interval test on the x and y axes*/
+ /*first do x axis*/
+ #define T 0.01
+ if (ABS(v1[1]-v2[1]) < T && ABS(v3[1]-v4[1]) < T &&
+ ABS(v1[1]-v3[1]) < T) {
+ if (v3[0] >= v1[0] && v3[0] <= v2[0])
+ return 1;
+ if (v4[0] >= v1[0] && v4[0] <= v2[0])
+ return 1;
+ if (v3[0] <= v1[0] && v4[0] >= v2[0])
+ return 1;
+ }
+
+ /*now do y axis*/
+ if (ABS(v1[0]-v2[0]) < T && ABS(v3[0]-v4[0]) < T &&
+ ABS(v1[0]-v3[0]) < T) {
+ if (v3[1] >= v1[1] && v3[1] <= v2[1])
+ return 1;
+ if (v4[1] >= v1[1] && v4[1] <= v2[1])
+ return 1;
+ if (v3[1] <= v1[1] && v4[1] >= v2[1])
+ return 1;
+ }
+
+ /*now test winding*/
+ 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..267bcd54a42
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -0,0 +1,562 @@
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "BLI_arithb.h"
+#include "BLI_array.h"
+
+#include "BKE_utildefines.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 || !v2 || v1 == v2)
+ return NULL;
+
+ 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;
+ BMLoop *l;
+ BMIter iter;
+
+ BM_ITER(l, &iter, NULL, BM_LOOPS_OF_VERT, v)
+ count++;
+
+ return count;
+#if 0 //this code isn't working
+ 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;
+#endif
+}
+
+/**
+ * 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 = INPR(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..664e07f805b
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -0,0 +1,780 @@
+/**
+ * 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--;
+ BM_remove_selection(bm, v);
+
+ 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--;
+ BM_remove_selection(bm, e);
+
+ 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_remove_selection(bm, f);
+
+ 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..1bad95ab0b1
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_to_editmesh.c
@@ -0,0 +1,316 @@
+#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 "BLI_array.h"
+#include "BLI_array.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, flag;
+
+ em = MEM_callocN(sizeof(EditMesh), "EditMesh from bmesh");
+
+ em->selectmode = bm->selectmode;
+
+ flag = CD_MASK_BMESH & ~CD_MASK_MTEXPOLY;
+
+ CustomData_copy(&bm->vdata, &em->vdata, flag, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &em->edata, flag, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &em->fdata, flag, 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) {
+ face = 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..9d5953f03fe
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -0,0 +1,917 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "BKE_utildefines.h"
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_mempool.h"
+#include "BLI_array.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 step may push multiple new states onto the stack at once.
+
+ * 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;
+ int nocalc;
+} faceloopWalker;
+
+typedef struct edgeringWalker {
+ struct edgeringWalker * prev;
+ BMLoop *l;
+} edgeringWalker;
+
+typedef struct uvedgeWalker {
+ struct uvedgeWalker *prev;
+ BMLoop *l;
+} uvedgeWalker;
+
+/* 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);
+
+static void edgeringWalker_begin(BMWalker *walker, void *data);
+static void *edgeringWalker_yield(BMWalker *walker);
+static void *edgeringWalker_step(BMWalker *walker);
+
+static void uvedgeWalker_begin(BMWalker *walker, void *data);
+static void *uvedgeWalker_yield(BMWalker *walker);
+static void *uvedgeWalker_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->currentstate ? walker->step(walker) : NULL;
+}
+
+/*
+ * 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 flag)
+{
+ int size = 0;
+
+ memset(walker, 0, sizeof(BMWalker));
+
+ walker->flag = flag;
+ 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;
+ case BMW_EDGERING:
+ walker->begin = edgeringWalker_begin;
+ walker->step = edgeringWalker_step;
+ walker->yield = edgeringWalker_yield;
+ size = sizeof(edgeringWalker);
+ break;
+ case BMW_LOOPDATA_ISLAND:
+ walker->begin = uvedgeWalker_begin;
+ walker->step = uvedgeWalker_step;
+ walker->yield = uvedgeWalker_yield;
+ size = sizeof(uvedgeWalker);
+ 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){
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v = data;
+ shellWalker *shellWalk = NULL;
+
+ if (!v->edge)
+ return;
+
+ if (walker->restrictflag) {
+ BM_ITER(e, &eiter, walker->bm, BM_EDGES_OF_VERT, v) {
+ if (BMO_TestFlag(walker->bm, e, walker->restrictflag))
+ break;
+ }
+ } else {
+ e = v->edge;
+ }
+
+ if (!e)
+ return;
+
+ if (BLI_ghash_haskey(walker->visithash, e))
+ return;
+
+ BMW_pushstate(walker);
+
+ shellWalk = walker->currentstate;
+ shellWalk->base = v;
+ shellWalk->curedge = e;
+ BLI_ghash_insert(walker->visithash, e, NULL);
+}
+
+static void *shellWalker_yield(BMWalker *walker)
+{
+ shellWalker *shellWalk = walker->currentstate;
+ return shellWalk->curedge;
+}
+
+static void *shellWalker_step(BMWalker *walker)
+{
+ shellWalker *swalk = walker->currentstate;
+ BMEdge *e, *e2;
+ BMVert *v;
+ BMIter iter;
+ int i;
+
+ BMW_popstate(walker);
+
+ e = swalk->curedge;
+ for (i=0; i<2; i++) {
+ v = i ? e->v2 : e->v1;
+ BM_ITER(e2, &iter, walker->bm, BM_EDGES_OF_VERT, v) {
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, e2, walker->restrictflag))
+ continue;
+ if (BLI_ghash_haskey(walker->visithash, e2))
+ continue;
+
+ BMW_pushstate(walker);
+ BLI_ghash_insert(walker->visithash, e2, NULL);
+
+ swalk = walker->currentstate;
+ swalk->curedge = e2;
+ }
+ }
+
+ return e;
+}
+
+#if 0
+static void *shellWalker_step(BMWalker *walker)
+{
+ BMEdge *curedge, *next = NULL;
+ BMVert *ov = NULL;
+ int restrictpass = 1;
+ shellWalker shellWalk = *((shellWalker*)walker->currentstate);
+
+ if (!BLI_ghash_haskey(walker->visithash, shellWalk.base))
+ BLI_ghash_insert(walker->visithash, shellWalk.base, NULL);
+
+ BMW_popstate(walker);
+
+
+ /*find the next edge whose other vertex has not been visited*/
+ curedge = shellWalk.curedge;
+ do{
+ if (!BLI_ghash_haskey(walker->visithash, curedge)) {
+ if(!walker->restrictflag || (walker->restrictflag &&
+ BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
+ {
+ ov = BM_OtherEdgeVert(curedge, shellWalk.base);
+
+ /*push a new state onto the stack*/
+ BMW_pushstate(walker);
+ BLI_ghash_insert(walker->visithash, curedge, NULL);
+
+ /*populate the new state*/
+
+ ((shellWalker*)walker->currentstate)->base = ov;
+ ((shellWalker*)walker->currentstate)->curedge = curedge;
+ }
+ }
+ curedge = bmesh_disk_nextedge(curedge, shellWalk.base);
+ }while(curedge != shellWalk.curedge);
+
+ return shellWalk.curedge;
+}
+#endif
+
+/* 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 (!l)
+ return owalk.cur;
+
+ 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);
+
+ if (!l)
+ break;
+
+ l2 = bmesh_radial_nextloop(l);
+
+ if (l2 == l) {
+ break;
+ }
+
+ l = l2;
+ i += 1;
+ }
+ }
+
+ if (!l)
+ return owalk.cur;
+
+ 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;
+ lwalk->nocalc = 0;
+ 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;
+ lwalk->nocalc = 0;
+
+ 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, *origl = lwalk->l;
+
+ BMW_popstate(walker);
+
+ l = l->radial.next->data;
+
+ if (lwalk->nocalc)
+ return f;
+
+ if (BLI_ghash_haskey(walker->visithash, l->f)) {
+ l = lwalk->l;
+ l = l->head.next->next;
+ if (l == l->radial.next->data) {
+ l = l->head.prev->prev;
+ }
+ l = l->radial.next->data;
+ }
+
+ if (!BLI_ghash_haskey(walker->visithash, l->f)) {
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ lwalk->l = l;
+
+ if (l->f->len != 4) {
+ lwalk->nocalc = 1;
+ lwalk->l = origl;
+ } else
+ lwalk->nocalc = 0;
+
+ BLI_ghash_insert(walker->visithash, l->f, NULL);
+ }
+
+ return f;
+}
+
+static void edgeringWalker_begin(BMWalker *walker, void *data)
+{
+ edgeringWalker *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->e, NULL);
+
+ /*rewind*/
+ while (walker->currentstate) {
+ owalk = *((edgeringWalker*)walker->currentstate);
+ BMW_walk(walker);
+ }
+
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ *lwalk = owalk;
+
+ if (lwalk->l->f->len != 4)
+ lwalk->l = lwalk->l->radial.next->data;
+
+ 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->e, NULL);
+}
+
+static void *edgeringWalker_yield(BMWalker *walker)
+{
+ edgeringWalker *lwalk = walker->currentstate;
+
+ if (!lwalk) return NULL;
+
+ return lwalk->l->e;
+}
+
+static void *edgeringWalker_step(BMWalker *walker)
+{
+ edgeringWalker *lwalk = walker->currentstate;
+ BMEdge *e = lwalk->l->e;
+ BMLoop *l = lwalk->l, *origl = lwalk->l;
+
+ BMW_popstate(walker);
+
+ l = l->radial.next->data;
+ l = l->head.next->next;
+
+ if (l->f->len != 4) {
+ l = lwalk->l->head.next->next;
+ }
+
+ if (l->f->len == 4 && !BLI_ghash_haskey(walker->visithash, l->e)) {
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ lwalk->l = l;
+
+ BLI_ghash_insert(walker->visithash, l->e, NULL);
+ }
+
+ return e;
+}
+
+static void uvedgeWalker_begin(BMWalker *walker, void *data)
+{
+ uvedgeWalker *lwalk;
+ BMLoop *l = data;
+
+ if (BLI_ghash_haskey(walker->visithash, l))
+ return;
+
+ BMW_pushstate(walker);
+ lwalk = walker->currentstate;
+ lwalk->l = l;
+ BLI_ghash_insert(walker->visithash, l, NULL);
+}
+
+static void *uvedgeWalker_yield(BMWalker *walker)
+{
+ uvedgeWalker *lwalk = walker->currentstate;
+
+ if (!lwalk) return NULL;
+}
+
+static void *uvedgeWalker_step(BMWalker *walker)
+{
+ uvedgeWalker *lwalk = walker->currentstate;
+ BMLoop *l, *l2, *l3, *nl, *cl;
+ BMIter liter;
+ void *d1, *d2;
+ int i, j, rlen, type;
+
+ l = lwalk->l;
+ nl = l->head.next;
+ type = walker->bm->ldata.layers[walker->flag].type;
+
+ BMW_popstate(walker);
+
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, l->e, walker->restrictflag))
+ return l;
+
+ /*go over loops around l->v and nl->v and see which ones share l and nl's
+ mloopuv's coordinates. in addition, push on l->head.next if necassary.*/
+ for (i=0; i<2; i++) {
+ cl = i ? nl : l;
+ BM_ITER(l2, &liter, walker->bm, BM_LOOPS_OF_VERT, cl->v) {
+ d1 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
+ cl->head.data, walker->flag);
+
+ rlen = BM_Edge_FaceCount(l2->e);
+ for (j=0; j<rlen; j++) {
+ if (BLI_ghash_haskey(walker->visithash, l2))
+ continue;
+ if (walker->restrictflag && !(BMO_TestFlag(walker->bm, l2->e, walker->restrictflag)))
+ {
+ if (l2->v != cl->v)
+ continue;
+ }
+
+ l3 = l2->v != cl->v ? (BMLoop*)l2->head.next : l2;
+ d2 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
+ l3->head.data, walker->flag);
+
+ if (!CustomData_data_equals(type, d1, d2))
+ continue;
+
+ BMW_pushstate(walker);
+ BLI_ghash_insert(walker->visithash, l2, NULL);
+ lwalk = walker->currentstate;
+
+ lwalk->l = l2;
+
+ l2 = l2->radial.next->data;
+ }
+ }
+ }
+
+ return l;
+}
+
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..cf30f4ae5aa
--- /dev/null
+++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c
@@ -0,0 +1,474 @@
+
+#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 "BLI_array.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..c2a0a984c91
--- /dev/null
+++ b/source/blender/bmesh/operators/bmesh_dupeops.c
@@ -0,0 +1,572 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.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, BM_ALL);
+
+ /*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, BM_ALL);
+
+ /*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, BM_ALL);
+
+ 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..a1d51468d57
--- /dev/null
+++ b/source/blender/bmesh/operators/connectops.c
@@ -0,0 +1,127 @@
+#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_array.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;
+ BLI_array_declare(loops);
+ BMLoop *l, *nl;
+ BMVert *v1, *v2, **verts = NULL;
+ BLI_array_declare(verts);
+ int i;
+
+ BMO_Flag_Buffer(bm, op, "verts", VERT_INPUT, BM_VERT);
+
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
+ BLI_array_empty(loops);
+ BLI_array_empty(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)
+ {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = lastl;
+
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = l;
+
+ }
+ lastl = l;
+ }
+ }
+
+ if (BLI_array_count(loops) == 0) continue;
+
+ if (BLI_array_count(loops) > 2) {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = loops[BLI_array_count(loops)-2];
+
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = loops[0];
+ }
+
+ BM_LegalSplits(bm, f, loops, BLI_array_count(loops)/2);
+
+ for (i=0; i<BLI_array_count(loops)/2; i++) {
+ if (loops[i*2]==NULL) continue;
+
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = loops[i*2]->v;
+
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = loops[i*2+1]->v;
+ }
+
+ for (i=0; i<BLI_array_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);
+ BLI_array_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);
+
+ BLI_array_free(loops);
+ BLI_array_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..9ae96436caa
--- /dev/null
+++ b/source/blender/bmesh/operators/createops.c
@@ -0,0 +1,596 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_heap.h"
+#include "BLI_ghash.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#define ELE_NEW 1
+#define ELE_OUT 2
+
+typedef struct EPathNode {
+ struct EPathNode *next, *prev;
+ BMVert *v;
+ BMEdge *e;
+} EPathNode;
+
+typedef struct EPath {
+ ListBase nodes;
+ float weight;
+} EPath;
+
+typedef struct PathBase {
+ BLI_mempool *nodepool, *pathpool;
+} PathBase;
+
+typedef struct EdgeData {
+ int tag;
+ int ftag;
+} EdgeData;
+
+#define EDGE_MARK 1
+#define EDGE_VIS 2
+
+#define FACE_NEW 1
+
+PathBase *edge_pathbase_new(void)
+{
+ PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
+
+ pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512);
+ pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512);
+
+ return pb;
+}
+
+void edge_pathbase_free(PathBase *pathbase)
+{
+ BLI_mempool_destroy(pathbase->nodepool);
+ BLI_mempool_destroy(pathbase->pathpool);
+ MEM_freeN(pathbase);
+}
+
+EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
+{
+ EPath *path2;
+ EPathNode *node, *node2;
+
+ path2 = BLI_mempool_calloc(pb->pathpool);
+
+ for (node=path->nodes.first; node; node=node->next) {
+ node2 = BLI_mempool_calloc(pb->nodepool);
+ *node2 = *node;
+ BLI_addtail(&path2->nodes, node2);
+ }
+
+ node2 = BLI_mempool_calloc(pb->nodepool);
+ node2->v = appendv;
+ node2->e = e;
+
+ BLI_addtail(&path2->nodes, node2);
+
+ return path2;
+}
+
+EPath *edge_path_new(PathBase *pb, BMVert *start)
+{
+ EPath *path;
+ EPathNode *node;
+
+ path = BLI_mempool_calloc(pb->pathpool);
+ node = BLI_mempool_calloc(pb->nodepool);
+
+ node->v = start;
+ node->e = NULL;
+
+ BLI_addtail(&path->nodes, node);
+ path->weight = 0.0f;
+
+ return path;
+}
+
+float edge_weight_path(EPath *path, EdgeData *edata)
+{
+ EPathNode *node;
+ float w;
+
+ for (node=path->nodes.first; node; node=node->next) {
+ if (node->e) {
+ w += edata[BMINDEX_GET(node->e)].ftag;
+ }
+
+ w += 1.0f;
+ }
+
+ return w;
+}
+
+
+void edge_free_path(PathBase *pathbase, EPath *path)
+{
+ EPathNode *node, *next;
+
+ for (node=path->nodes.first; node; node=next) {
+ next = node->next;
+ BLI_mempool_free(pathbase->nodepool, node);
+ }
+
+ BLI_mempool_free(pathbase->pathpool, path);
+}
+
+EPath *edge_find_shortest_path(BMesh *bm, BMEdge *edge, EdgeData *edata, PathBase *pathbase)
+{
+ BMIter iter;
+ BMEdge *e;
+ GHash *gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ BMVert *v1, *v2;
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+ Heap *heap = BLI_heap_new();
+ EPath *path = NULL, *path2;
+ EPathNode *node;
+ int i;
+
+ path = edge_path_new(pathbase, edge->v1);
+ BLI_heap_insert(heap, path->weight, path);
+ path = NULL;
+
+ while (BLI_heap_size(heap)) {
+ if (path)
+ edge_free_path(pathbase, path);
+ path = BLI_heap_popmin(heap);
+ v1 = ((EPathNode*)path->nodes.last)->v;
+
+ if (v1 == edge->v2) {
+ /*make sure this path loop doesn't already exist*/
+ i = 0;
+ BLI_array_empty(verts);
+ for (i=0, node = path->nodes.first; node; node=node->next, i++) {
+ BLI_array_growone(verts);
+ verts[i] = node->v;
+ }
+
+ if (!BM_Face_Exists(bm, verts, i, NULL))
+ break;
+ else
+ continue;
+ }
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v1) {
+ if (e == edge || !BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+
+ v2 = BM_OtherEdgeVert(e, v1);
+
+ if (BLI_ghash_haskey(gh, v2))
+ continue;
+
+ BLI_ghash_insert(gh, v2, NULL);
+
+ path2 = edge_copy_add_path(pathbase, path, v2, e);
+ path2->weight = edge_weight_path(path2, edata);
+
+ BLI_heap_insert(heap, path2->weight, path2);
+ }
+
+ if (BLI_heap_size(heap) == 0)
+ path = NULL;
+ }
+
+ BLI_array_free(verts);
+ BLI_heap_free(heap, NULL);
+ BLI_ghash_free(gh, NULL, NULL);
+
+ return path;
+}
+
+void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter;
+ BMOIter siter;
+ BMEdge *e, *edge;
+ BMFace *f;
+ EPath *path;
+ EPathNode *node;
+ EdgeData *edata;
+ BMEdge **edges = NULL;
+ PathBase *pathbase = edge_pathbase_new();
+ BLI_array_declare(edges);
+ int i;
+
+ if (!bm->totvert || !bm->totedge)
+ return;
+
+ edata = MEM_callocN(sizeof(EdgeData)*bm->totedge, "EdgeData");
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMINDEX_SET(e, i);
+
+ if (!BMO_TestFlag(bm, e, EDGE_MARK)) {
+ edata[i].tag = 2;
+ }
+
+ i += 1;
+ }
+
+ while (1) {
+ edge = NULL;
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (edata[BMINDEX_GET(e)].tag < 2) {
+ edge = e;
+ break;
+ }
+ }
+
+ if (!edge)
+ break;
+
+ edata[BMINDEX_GET(edge)].tag += 1;
+
+ path = edge_find_shortest_path(bm, edge, edata, pathbase);
+ if (!path)
+ continue;
+
+ BLI_array_empty(edges);
+ i = 0;
+ for (node=path->nodes.first; node; node=node->next) {
+ if (!node->next)
+ continue;
+
+ e = BM_Edge_Exist(node->v, node->next->v);
+
+ /*this should never happen*/
+ if (!e)
+ break;
+
+ edata[BMINDEX_GET(e)].ftag++;
+ BLI_array_growone(edges);
+ edges[i++] = e;
+ }
+
+ BLI_array_growone(edges);
+ edges[i++] = edge;
+
+ f = BM_Make_Ngon(bm, edge->v1, edge->v2, edges, i, 1);
+ if (f)
+ BMO_SetFlag(bm, f, FACE_NEW);
+
+ edge_free_path(pathbase, path);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_NEW, BM_FACE);
+
+ BLI_array_free(edges);
+ edge_pathbase_free(pathbase);
+ MEM_freeN(edata);
+}
+
+/* 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;
+}
+
+BMEdge *edge_next(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e2;
+ int i;
+
+ for (i=0; i<2; i++) {
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, i?e->v2:e->v1) {
+ if (BMO_TestFlag(bm, e2, EDGE_MARK)
+ && !BMO_TestFlag(bm, e2, EDGE_VIS) && e2 != e)
+ {
+ return e2;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMEdge *e, *e2;
+ BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
+ BLI_array_declare(edges1);
+ BLI_array_declare(edges2);
+ BLI_array_declare(edges);
+ int ok = 1;
+ int i, count;
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+
+ /*validate that each edge has at most one other tagged edge in the
+ disk cycle around each of it's vertices*/
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ for (i=0; i<2; i++) {
+ count = BMO_Vert_CountEdgeFlags(bm, i?e->v2:e->v1, EDGE_MARK);
+ if (count > 2) {
+ ok = 0;
+ break;
+ }
+ }
+
+ if (!ok) break;
+ }
+
+ /*we don't have valid edge layouts, return*/
+ if (!ok)
+ return;
+
+
+ /*find connected loops within the input edges*/
+ count = 0;
+ while (1) {
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (!BMO_TestFlag(bm, e, EDGE_VIS)) {
+ if (BMO_Vert_CountEdgeFlags(bm, e->v1, EDGE_MARK)==1)
+ break;
+ if (BMO_Vert_CountEdgeFlags(bm, e->v2, EDGE_MARK)==1)
+ break;
+ }
+ }
+
+ if (!e) break;
+
+ if (!count)
+ edges = edges1;
+ else if (count==1)
+ edges = edges2;
+ else break;
+
+ i = 0;
+ while (e) {
+ BMO_SetFlag(bm, e, EDGE_VIS);
+ BLI_array_growone(edges);
+ edges[i] = e;
+
+ e = edge_next(bm, e);
+ i++;
+ }
+
+ if (!count) {
+ edges1 = edges;
+ BLI_array_set_length(edges1, BLI_array_count(edges));
+ } else {
+ edges2 = edges;
+ BLI_array_set_length(edges2, BLI_array_count(edges));
+ }
+
+ BLI_array_empty(edges);
+ count++;
+ }
+
+#define EDGECON(e1, e2) (e1->v1 == e2->v1 || e1->v2 == e2->v2 || e1->v1 == e2->v2)
+
+ if (edges1 && BLI_array_count(edges1) > 2 && EDGECON(edges1[0], edges1[BLI_array_count(edges1)-1])) {
+ if (edges2 && BLI_array_count(edges2) > 2 && EDGECON(edges2[0], edges2[BLI_array_count(edges2)-1])) {
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+ return;
+ } else {
+ edges1 = edges2;
+ edges2 = NULL;
+ }
+ }
+
+ if (edges2 && BLI_array_count(edges2) > 2 && EDGECON(edges2[0], edges2[BLI_array_count(edges2)-1])) {
+ edges2 = NULL;
+ }
+
+ /*two unconnected loops, connect them*/
+ if (edges1 && edges2) {
+ BMVert *v1, *v2, *v3, *v4;
+
+ if (BLI_array_count(edges1)==1) {
+ v1 = edges1[0]->v1;
+ v2 = edges1[0]->v2;
+ } else {
+ if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+ v1 = edges1[0]->v2;
+ else v1 = edges1[0]->v1;
+
+ i = BLI_array_count(edges1)-1;
+ if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+ v2 = edges1[i]->v2;
+ else v2 = edges1[i]->v1;
+ }
+
+ if (BLI_array_count(edges2)==1) {
+ v3 = edges2[0]->v1;
+ v4 = edges2[0]->v2;
+ } else {
+ if (BM_Vert_In_Edge(edges2[1], edges2[0]->v1))
+ v3 = edges2[0]->v2;
+ else v3 = edges2[0]->v1;
+
+ i = BLI_array_count(edges2)-1;
+ if (BM_Vert_In_Edge(edges2[i-1], edges2[i]->v1))
+ v4 = edges2[i]->v2;
+ else v4 = edges2[i]->v1;
+ }
+
+ if (VecLenf(v1->co, v3->co) > VecLenf(v1->co, v4->co)) {
+ BMVert *v;
+ v = v3;
+ v3 = v4;
+ v4 = v;
+ }
+
+ e = BM_Make_Edge(bm, v1, v3, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ e = BM_Make_Edge(bm, v2, v4, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ } else if (edges1) {
+ BMVert *v1, *v2;
+
+ if (BLI_array_count(edges1) > 1) {
+ if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+ v1 = edges1[0]->v2;
+ else v1 = edges1[0]->v1;
+
+ i = BLI_array_count(edges1)-1;
+ if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+ v2 = edges1[i]->v2;
+ else v2 = edges1[i]->v1;
+
+ e = BM_Make_Edge(bm, v1, v2, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", ELE_NEW, BM_EDGE);
+
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+
+#undef EDGECON
+}
+
+/*this is essentially new fkey*/
+void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator op2;
+ BMOIter oiter;
+ BMIter iter;
+ BMHeader *h;
+ BMVert *v, *verts[4];
+ BMEdge *e;
+ 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);
+ }
+
+ /*call edgenet create*/
+ /* call edgenet prepare op so additional face creation cases work*/
+ BMO_InitOpf(bm, &op2, "edgenet_prepare edges=%fe", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+ BMO_Flag_Buffer(bm, &op2, "edgeout", ELE_NEW, BM_EDGE);
+ BMO_Finish_Op(bm, &op2);
+
+ BMO_InitOpf(bm, &op2, "edgenet_fill edges=%fe", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+
+ /*return if edge net create did something*/
+ if (BMO_CountSlotBuf(bm, &op2, "faceout")) {
+ BMO_CopySlot(&op2, op, "faceout", "faceout");
+ BMO_Finish_Op(bm, &op2);
+ return;
+ }
+
+ BMO_Finish_Op(bm, &op2);
+
+ /*now call dissolve faces*/
+ BMO_InitOpf(bm, &op2, "dissolvefaces faces=%ff", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+
+ /*if we dissolved anything, then return.*/
+ if (BMO_CountSlotBuf(bm, &op2, "regionout")) {
+ BMO_CopySlot(&op2, op, "regionout", "faceout");
+ BMO_Finish_Op(bm, &op2);
+ return;
+ }
+
+ 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);
+ }
+}
diff --git a/source/blender/bmesh/operators/dissolveops.c b/source/blender/bmesh/operators/dissolveops.c
new file mode 100644
index 00000000000..c04f6a3e638
--- /dev/null
+++ b/source/blender/bmesh/operators/dissolveops.c
@@ -0,0 +1,431 @@
+#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_array.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, 0);
+ 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;
+ BLI_array_declare(region);
+ BLI_array_declare(regions);
+ BMLoop ***regions = NULL;
+ BMLoop **region = NULL;
+ BMWalker regwalker;
+ int i, j, fcopied;
+
+ BMO_Flag_Buffer(bm, op, "faces", FACE_MARK, BM_FACE);
+
+ /*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;
+
+ BLI_array_empty(region);
+ region = NULL; /*forces different allocation*/
+
+ /*yay, walk!*/
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK, 0);
+ 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)) {
+ BLI_array_growone(region);
+ region[BLI_array_count(region)-1] = l2;
+ break;
+ }
+ }
+ if (bmesh_radial_nextloop(l2) == l2) {
+ BLI_array_growone(region);
+ region[BLI_array_count(region)-1] = l2;
+ }
+ }
+ }
+ BMW_End(&regwalker);
+
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK, 0);
+ 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;
+ }
+
+ BLI_array_growone(region);
+ BLI_array_growone(regions);
+ regions[BLI_array_count(regions)-1] = region;
+ region[BLI_array_count(region)-1] = NULL;
+ }
+
+ for (i=0; i<BLI_array_count(regions); i++) {
+ BMEdge **edges = NULL;
+ BLI_array_declare(edges);
+
+ region = regions[i];
+ for (j=0; region[j]; j++) {
+ BLI_array_growone(edges);
+ edges[BLI_array_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);
+
+ BLI_array_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<BLI_array_count(regions); i++) {
+ if (regions[i]) BLI_array_free(regions[i]);
+ }
+
+ BLI_array_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;
+ BLI_array_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)
+ {
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = v;
+ }
+ }
+
+ /*clean up extreneous 2-valence vertices*/
+ for (i=0; i<BLI_array_count(verts); i++) {
+ BM_Collapse_Vert(bm, verts[i]->edge, verts[i], 1.0);
+ }
+
+ BLI_array_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, BM_VERT);
+
+ 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/edgesplitop.c b/source/blender/bmesh/operators/edgesplitop.c
new file mode 100644
index 00000000000..1a878d2bd8b
--- /dev/null
+++ b/source/blender/bmesh/operators/edgesplitop.c
@@ -0,0 +1,357 @@
+/**
+ * $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. 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): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_array.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>
+
+typedef struct EdgeTag {
+ BMVert *newv1, *newv2;
+ BMEdge *newe1, *newe2;
+ int tag;
+} EdgeTag;
+
+#define EDGE_SEAM 1
+#define EDGE_DEL 2
+#define EDGE_MARK 4
+#define EDGE_RET1 8
+#define EDGE_RET2 16
+
+#define FACE_DEL 1
+#define FACE_NEW 2
+
+static BMFace *remake_face(BMesh *bm, EdgeTag *etags, BMFace *f, BMVert **verts)
+{
+ BMIter liter1, liter2;
+ EdgeTag *et;
+ BMFace *f2;
+ BMLoop *l, *l2;
+ BMEdge **edges = (BMEdge**) verts; /*he he, can reuse this, sneaky! ;)*/
+ BMVert *lastv1, *lastv2, *v1, *v2;
+ int i;
+
+ /*we do final edge last*/
+ lastv1 = verts[f->len-1];
+ lastv2 = verts[0];
+ v1 = verts[0];
+ v2 = verts[1];
+ for (i=0; i<f->len-1; i++) {
+ edges[i] = BM_Make_Edge(bm, verts[i], verts[i+1], NULL, 1);
+
+ if (!edges[i])
+ return NULL;
+ }
+
+ edges[i] = BM_Make_Edge(bm, lastv1, lastv2, NULL, 1);
+
+ f2 = BM_Make_Ngon(bm, v1, v2, edges, f->len, 0);
+ if (!f2)
+ return NULL;
+
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ l = BMIter_New(&liter1, bm, BM_LOOPS_OF_FACE, f);
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ for (; l && l2; l=BMIter_Step(&liter1), l2=BMIter_Step(&liter2)) {
+ BM_Copy_Attributes(bm, bm, l, l2);
+ if (l->e != l2->e) {
+ /*set up data for figuring out the two sides of
+ the splits*/
+ BMINDEX_SET(l2->e, BMINDEX_GET(l->e));
+ et = etags + BMINDEX_GET(l->e);
+
+ if (!et->newe1) et->newe1 = l2->e;
+ else et->newe2 = l2->e;
+
+ if (BMO_TestFlag(bm, l->e, EDGE_SEAM))
+ BMO_SetFlag(bm, l2->e, EDGE_SEAM);
+
+ BM_Copy_Attributes(bm, bm, l->e, l2->e);
+ }
+
+ BMO_SetFlag(bm, l->e, EDGE_MARK);
+ BMO_SetFlag(bm, l2->e, EDGE_MARK);
+ }
+
+ return f2;
+}
+
+void tag_out_edges(BMesh *bm, EdgeTag *etags, BMOperator *op)
+{
+ EdgeTag *et;
+ BMIter iter;
+ BMLoop *l, *startl;
+ BMEdge *e;
+ BMVert *v;
+ int i;
+
+ while (1) {
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_SEAM))
+ continue;
+
+ et = etags + BMINDEX_GET(e);
+ if (!et->tag && e->loop) {
+ break;
+ }
+ }
+
+ if (!e)
+ break;
+
+ /*ok we found an edge, part of a region of splits we need
+ to identify. now walk along it.*/
+ for (i=0; i<2; i++) {
+ l = e->loop;
+
+ v = i ? ((BMLoop*)l->head.next)->v : l->v;
+
+ while (1) {
+ et = etags + BMINDEX_GET(l->e);
+ if (et->newe1 == l->e) {
+ if (et->newe1) {
+ BMO_SetFlag(bm, et->newe1, EDGE_RET1);
+ BMO_ClearFlag(bm, et->newe1, EDGE_SEAM);
+ }
+ if (et->newe2) {
+ BMO_SetFlag(bm, et->newe2, EDGE_RET2);
+ BMO_ClearFlag(bm, et->newe2, EDGE_SEAM);
+ }
+ } else {
+ if (et->newe1) {
+ BMO_SetFlag(bm, et->newe1, EDGE_RET2);
+ BMO_ClearFlag(bm, et->newe1, EDGE_SEAM);
+ }
+ if (et->newe2) {
+ BMO_SetFlag(bm, et->newe2, EDGE_RET1);
+ BMO_ClearFlag(bm, et->newe2, EDGE_SEAM);
+ }
+ }
+
+ startl = l;
+ do {
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+ if (BM_Edge_FaceCount(l->e) != 2)
+ break;
+ l = (BMLoop*) l->radial.next->data;
+ } while (l != startl && !BMO_TestFlag(bm, l->e, EDGE_SEAM));
+
+ if (l == startl || !BMO_TestFlag(bm, l->e, EDGE_SEAM))
+ break;
+
+ if (l->v == v) {
+ v = ((BMLoop*)l->head.next)->v;
+ } else v = l->v;
+ }
+ }
+ }
+}
+
+void bmesh_edgesplitop_exec(BMesh *bm, BMOperator *op)
+{
+ EdgeTag *etags, *et;
+ BMIter iter, liter;
+ BMOIter siter;
+ BMFace *f, *f2;
+ BMLoop *l, *nextl, *prevl, *l2, *l3;
+ BMEdge *e, *e2;
+ BLI_array_declare(verts);
+ BMVert *v, *v2, **verts = NULL;
+ int i, j;
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_SEAM, BM_EDGE);
+
+ /*single marked edges unconnected to any other marked edges
+ are illegal, go through and unmark them*/
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ for (i=0; i<2; i++) {
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, i ? e->v2 : e->v1) {
+ if (e != e2 && BMO_TestFlag(bm, e2, EDGE_SEAM))
+ break;
+ }
+ if (e2)
+ break;
+ }
+ if (!e2)
+ BMO_ClearFlag(bm, e, EDGE_SEAM);
+ }
+
+ etags = MEM_callocN(sizeof(EdgeTag)*bm->totedge, "EdgeTag");
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMINDEX_SET(e, i);
+ i++;
+ }
+
+#ifdef ETV
+#undef ETV
+#endif
+#ifdef SETETV
+#undef SETETV
+#endif
+
+#define ETV(et, v, l) (l->e->v1 == v ? et->newv1 : et->newv2)
+#define SETETV(et, v, l, vs) l->e->v1 == v ? (et->newv1 = vs) : (et->newv2 = vs)
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, f, FACE_NEW))
+ continue;
+
+ BLI_array_empty(verts);
+ BLI_array_growitems(verts, f->len);
+ memset(verts, 0, sizeof(BMVert*)*f->len);
+
+ i = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (!BMO_TestFlag(bm, l->e, EDGE_SEAM)) {
+ if (!verts[i]) {
+ et = etags + BMINDEX_GET(l->e);
+ if (ETV(et, l->v, l))
+ verts[i] = ETV(et, l->v, l);
+ else verts[i] = l->v;
+ }
+ i++;
+ continue;
+ }
+
+ BMO_SetFlag(bm, l->e, EDGE_DEL);
+
+ nextl = (BMLoop*) l->head.next;
+ prevl = (BMLoop*) l->head.prev;
+
+ for (j=0; j<2; j++) {
+ l2 = j ? nextl : prevl;
+ v = j ? l2->v : l->v;
+
+ if (BMO_TestFlag(bm, l2->e, EDGE_SEAM)) {
+ if (!verts[j ? (i+1) % f->len : i]) {
+ /*make unique vert here for this face only*/
+ v2 = BM_Make_Vert(bm, v->co, NULL);
+ VECCOPY(v2->no, v->no);
+ BM_Copy_Attributes(bm, bm, v, v2);
+
+ verts[j ? (i+1) % f->len : i] = v2;
+ } else v2 = verts[j ? (i+1) % f->len : i];
+ } else {
+ /*generate unique vert for non-seam edge(s)
+ around the manifold vert fan if necassary*/
+
+ /*first check that we have two seam edges
+ somewhere within this fan*/
+ l3 = l2;
+ do {
+ if (BM_Edge_FaceCount(l3->e) != 2) {
+ /*if we hit a boundary edge, tag
+ l3 as null so we know to disconnect
+ it*/
+ if (BM_Edge_FaceCount(l3->e) == 1)
+ l3 = NULL;
+ break;
+ }
+
+ l3 = (BMLoop*)l3->radial.next->data;
+ l3 = BM_OtherFaceLoop(l3->e, l3->f, v);
+ } while (l3 != l2 && !BMO_TestFlag(bm, l3->e, EDGE_SEAM));
+
+ if (l3 == NULL || (BMO_TestFlag(bm, l3->e, EDGE_SEAM) && l3->e != l->e)) {
+ et = etags + BMINDEX_GET(l2->e);
+ if (ETV(et, v, l2) == NULL) {
+ v2 = BM_Make_Vert(bm, v->co, NULL);
+ VECCOPY(v2->no, v->no);
+ BM_Copy_Attributes(bm, bm, v, v2);
+
+ l3 = l2;
+ do {
+ SETETV(et, v, l3, v2);
+ if (BM_Edge_FaceCount(l3->e) != 2)
+ break;
+
+ l3 = (BMLoop*)l3->radial.next->data;
+ l3 = BM_OtherFaceLoop(l3->e, l3->f, v);
+
+ et = etags + BMINDEX_GET(l3->e);
+ } while (l3 != l2 && !BMO_TestFlag(bm, l3->e, EDGE_SEAM));
+ } else v2 = ETV(et, v, l2);
+
+ verts[j ? (i+1) % f->len : i] = v2;
+ } else verts[j ? (i+1) % f->len : i] = v;
+ }
+ }
+
+ i++;
+ }
+
+ f2 = remake_face(bm, etags, f, verts);
+ if (!f2)
+ continue;
+
+ BMO_SetFlag(bm, f, FACE_DEL);
+ BMO_SetFlag(bm, f2, FACE_NEW);
+ }
+
+ BMO_CallOpf(bm, "del geom=%ff context=%i", FACE_DEL, DEL_ONLYFACES);
+
+ /*test EDGE_MARK'd edges if we need to delete them, EDGE_MARK
+ is set in remake_face*/
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ if (!e->loop)
+ BMO_SetFlag(bm, e, EDGE_DEL);
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%fe context=%i", EDGE_DEL, DEL_EDGES);
+
+ tag_out_edges(bm, etags, op);
+ BMO_Flag_To_Slot(bm, op, "edgeout1", EDGE_RET1, BM_EDGE);
+ BMO_Flag_To_Slot(bm, op, "edgeout2", EDGE_RET2, BM_EDGE);
+
+ BLI_array_free(verts);
+ if (etags) MEM_freeN(etags);
+}
+
+#undef ETV
+#undef SETETV
diff --git a/source/blender/bmesh/operators/extrudeops.c b/source/blender/bmesh/operators/extrudeops.c
new file mode 100644
index 00000000000..fb9c13f54c2
--- /dev/null
+++ b/source/blender/bmesh/operators/extrudeops.c
@@ -0,0 +1,310 @@
+#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 "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define EXT_INPUT 1
+#define EXT_KEEP 2
+#define EXT_DEL 4
+
+void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter liter, liter2;
+ BMFace *f, *f2, *f3;
+ BMLoop *l, *l2, *l3, *l4;
+ BMEdge **edges = NULL, *e, *laste;
+ BMVert *v, *lastv, *firstv;
+ BLI_array_declare(edges);
+ int i;
+
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ BLI_array_empty(edges);
+ i = 0;
+ firstv = lastv = NULL;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BLI_array_growone(edges);
+
+ v = BM_Make_Vert(bm, l->v->co, NULL);
+ BM_Copy_Attributes(bm, bm, l->v, v);
+
+ if (lastv) {
+ e = BM_Make_Edge(bm, lastv, v, l->e, 0);
+ edges[i++] = e;
+ }
+
+ lastv = v;
+ laste = l->e;
+ if (!firstv) firstv = v;
+ }
+
+ BLI_array_growone(edges);
+ e = BM_Make_Edge(bm, v, firstv, laste, 0);
+ edges[i++] = e;
+
+ BMO_SetFlag(bm, f, EXT_DEL);
+
+ f2 = BM_Make_Ngon(bm, edges[0]->v1, edges[0]->v2, edges, f->len, 0);
+ BMO_SetFlag(bm, f2, EXT_KEEP);
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_Copy_Attributes(bm, bm, l, l2);
+ l3 = l->head.next;
+ l4 = l2->head.next;
+
+ f3 = BM_Make_QuadTri(bm, l3->v, l4->v, l2->v, l->v, f, 0);
+
+ BM_Copy_Attributes(bm, bm, l->head.next, f3->loopbase);
+ BM_Copy_Attributes(bm, bm, l->head.next, f3->loopbase->head.next);
+ BM_Copy_Attributes(bm, bm, l, f3->loopbase->head.next->next);
+ BM_Copy_Attributes(bm, bm, l, f3->loopbase->head.next->next->next);
+
+ l2 = BMIter_Step(&liter2);
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%ff context=%d", EXT_DEL, DEL_ONLYFACES);
+
+ BMO_Flag_To_Slot(bm, op, "faceout", EXT_KEEP, BM_FACE);
+}
+
+void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMOperator dupeop;
+ BMVert *v1, *v2, *v3, *v4;
+ BMEdge *e, *e2;
+ BMFace *f;
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ BMO_SetFlag(bm, e, EXT_INPUT);
+ BMO_SetFlag(bm, e->v1, EXT_INPUT);
+ BMO_SetFlag(bm, e->v2, EXT_INPUT);
+ }
+
+ BMO_InitOpf(bm, &dupeop, "dupe geom=%fve", EXT_INPUT);
+ BMO_Exec_Op(bm, &dupeop);
+
+ e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
+ for (; e; e=BMO_IterStep(&siter)) {
+ e2 = BMO_IterMapVal(&siter);
+ e2 = *(BMEdge**)e2;
+
+ if (e->loop && e->v1 != e->loop->v) {
+ v1 = e->v1;
+ v2 = e->v2;
+ v3 = e2->v2;
+ v4 = e2->v1;
+ } else {
+ v1 = e2->v1;
+ v2 = e2->v2;
+ v3 = e->v2;
+ v4 = e->v1;
+ }
+ /*not sure what to do about example face, pass NULL for now.*/
+ f = BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);
+
+ if (BMO_TestFlag(bm, e, EXT_INPUT))
+ e = e2;
+
+ BMO_SetFlag(bm, f, EXT_KEEP);
+ BMO_SetFlag(bm, e, EXT_KEEP);
+ BMO_SetFlag(bm, e->v1, EXT_KEEP);
+ BMO_SetFlag(bm, e->v2, EXT_KEEP);
+
+ }
+
+ BMO_Finish_Op(bm, &dupeop);
+
+ BMO_Flag_To_Slot(bm, op, "geomout", EXT_KEEP, BM_ALL);
+}
+
+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;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, "dupe");
+
+ BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
+
+ /*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..15bc1f25bba
--- /dev/null
+++ b/source/blender/bmesh/operators/mesh_conv.c
@@ -0,0 +1,463 @@
+#include <string.h>
+
+#include "MEM_guardedalloc.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 "BKE_customdata.h"
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_array.h"
+
+#include "ED_mesh.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+/*
+ * MESH CONV.C
+ *
+ * This file contains functions
+ * for converting a Mesh
+ * into a Bmesh, and back again.
+ *
+*/
+
+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 = NULL;
+ BLI_array_declare(fedges);
+ BMFace *f;
+ int i, j, li, 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(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->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]);
+
+ 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);
+
+ /*this is necassary for selection counts to work properly*/
+ if(v->head.flag & BM_SELECT) BM_Select_Vert(bm, v, 1);
+
+ /*transfer flags*/
+ v->head.flag = MEFlags_To_BMFlags(mvert->flag, BM_VERT);
+ v->bweight = (float)mvert->bweight / 255.0f;
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+ }
+
+ if (!me->totedge) {
+ MEM_freeN(vt);
+ 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;
+
+ /*this is necassary for selection counts to work properly*/
+ if (e->head.flag & BM_SELECT) BM_Select(bm, e, 1);
+
+ /*transfer flags*/
+ e->head.flag = MEFlags_To_BMFlags(medge->flag, BM_EDGE);
+ }
+
+ if (!me->totpoly) {
+ MEM_freeN(vt);
+ MEM_freeN(et);
+ return;
+ }
+
+ mpoly = me->mpoly;
+ li = 0;
+ for (i=0; i<me->totpoly; i++, mpoly++) {
+ BMVert *v1, *v2;
+ BMIter iter;
+ BMLoop *l;
+
+ BLI_array_empty(fedges);
+ for (j=0; j<mpoly->totloop; j++) {
+ ml = &me->mloop[mpoly->loopstart+j];
+ v = vt[ml->v];
+ e = et[ml->e];
+
+ BLI_array_growone(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);
+
+ if (!f) {
+ printf("Warning! Bad face in mesh"
+ " \"%s\" at index %d!\n", me->id.name+2, i);
+ continue;
+ }
+
+ /*this is necassary for selection counts to work properly*/
+ if (f->head.flag & BM_SELECT) BM_Select(bm, f, 1);
+
+ /*transfer flags*/
+ f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
+
+ f->mat_nr = mpoly->mat_nr;
+ if (i == me->act_face) bm->act_face = f;
+
+ /*Copy over loop customdata*/
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data);
+ li++;
+ }
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
+ }
+
+ BLI_array_free(fedges);
+
+ MEM_freeN(vt);
+ MEM_freeN(et);
+}
+
+
+static void loops_to_corners(BMesh *bm, Mesh *me, int findex,
+ BMFace *f, BMLoop *ls[3], int numTex, int numCol)
+{
+ BMLoop *l;
+ 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;
+
+ for (j=0; j<3; j++) {
+ l = ls[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(&me->fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<3; j++) {
+ l = ls[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;
+ }
+ }
+}
+
+void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
+ Object *ob = BMO_Get_Pnt(op, "object");
+ Scene *scene = BMO_Get_Pnt(op, "scene");
+ Mesh *me = ob->data;
+
+ BMO_CallOpf(bm, "bmesh_to_mesh meshptr=%p", me);
+
+ /*BMESH_TODO eventually we'll have to handle shapekeys here*/
+}
+
+void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
+ Mesh *me = BMO_Get_Pnt(op, "meshptr");
+ 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, totface, numTex, numCol;
+ int dotess = !BMO_Get_Int(op, "notesselation");
+
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ /* 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");
+
+ /*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->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->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
+ CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ VECCOPY(mvert->co, v->co);
+
+ mvert->no[0] = (short) (v->no[0]*32767.0f);
+ mvert->no[1] = (short) (v->no[1]*32767.0f);
+ mvert->no[2] = (short) (v->no[2]*32767.0f);
+
+ mvert->flag = BMFlags_To_MEFlags(v);
+
+ BMINDEX_SET(v, i);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
+
+ i++;
+ mvert++;
+ }
+
+ 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);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
+
+ i++;
+ medge++;
+ }
+
+ /*new scanfill tesselation code*/
+ if (dotess) {
+ /*first counter number of faces we'll need*/
+ totface = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *eve, *lasteve = NULL, *firsteve = NULL;
+ EditFace *efa;
+
+ i = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ eve = BLI_addfillvert(l->v->co);
+ eve->tmp.p = l;
+
+ BMINDEX_SET(l, i);
+
+ if (lasteve) {
+ BLI_addfilledge(lasteve, eve);
+ }
+
+ lasteve = eve;
+ if (!firsteve) firsteve = eve;
+
+ i++;
+ }
+
+ BLI_addfilledge(lasteve, firsteve);
+ BLI_edgefill(0, 0);
+
+ for (efa=fillfacebase.first; efa; efa=efa->next)
+ totface++;
+
+ BLI_end_edgefill();
+ }
+
+ me->totface = totface;
+
+ /* new tess face block */
+ if(totface==0) mface= NULL;
+ else mface= MEM_callocN(totface*sizeof(MFace), "loadeditbMesh face");
+
+ CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
+ CustomData_from_bmeshpoly(&me->fdata, &bm->pdata, &bm->ldata, totface);
+
+ mesh_update_customdata_pointers(me);
+
+ i = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *eve, *lasteve = NULL, *firsteve = NULL;
+ EditFace *efa;
+ BMLoop *ls[3];
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ eve = BLI_addfillvert(l->v->co);
+ eve->tmp.p = l;
+
+ if (lasteve) {
+ BLI_addfilledge(lasteve, eve);
+ }
+
+ lasteve = eve;
+ if (!firsteve) firsteve = eve;
+ }
+
+ BLI_addfilledge(lasteve, firsteve);
+ BLI_edgefill(0, 0);
+
+ for (efa=fillfacebase.first; efa; efa=efa->next) {
+ ls[0] = efa->v1->tmp.p;
+ ls[1] = efa->v2->tmp.p;
+ ls[2] = efa->v3->tmp.p;
+
+ /*ensure correct winding. I believe this is
+ analogous to bubble sort on three elements.*/
+ if (BMINDEX_GET(ls[0]) > BMINDEX_GET(ls[1])) {
+ SWAP(BMLoop*, ls[0], ls[1]);
+ }
+ if (BMINDEX_GET(ls[1]) > BMINDEX_GET(ls[2])) {
+ SWAP(BMLoop*, ls[1], ls[2]);
+ }
+ if (BMINDEX_GET(ls[0]) > BMINDEX_GET(ls[1])) {
+ SWAP(BMLoop*, ls[0], ls[1]);
+ }
+
+ mface->mat_nr = f->mat_nr;
+ mface->flag = BMFlags_To_MEFlags(f);
+
+ mface->v1 = BMINDEX_GET(ls[0]->v);
+ mface->v2 = BMINDEX_GET(ls[1]->v);
+ mface->v3 = BMINDEX_GET(ls[2]->v);
+
+ test_index_face(mface, &me->fdata, i, 1);
+
+ loops_to_corners(bm, me, i, f, ls, numTex, numCol);
+ mface++;
+ i++;
+ }
+ BLI_end_edgefill();
+ }
+ }
+
+ 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);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l->head.data, j);
+ }
+
+ if (f == bm->act_face) me->act_face = i;
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
+
+ i++;
+ mpoly++;
+ }
+
+ mesh_update_customdata_pointers(me);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/operators/mirror.c b/source/blender/bmesh/operators/mirror.c
new file mode 100644
index 00000000000..c928ff89daa
--- /dev/null
+++ b/source/blender/bmesh/operators/mirror.c
@@ -0,0 +1,123 @@
+#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 "BLI_array.h"
+
+#include "bmesh.h"
+
+/*
+ * MIRROR.C
+ *
+ * mirror bmop.
+ *
+*/
+
+#define ELE_NEW 1
+
+void bmesh_mirror_exec(BMesh *bm, BMOperator *op) {
+ BMOperator dupeop, weldop;
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, *v2, **vmap = NULL;
+ BLI_array_declare(vmap);
+ BMEdge *e, **emap = NULL;
+ BLI_array_declare(emap);
+ float mtx[4][4];
+ float imtx[4][4];
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ float dist = BMO_Get_Float(op, "mergedist");
+ int i, ototvert, ototedge, axis = BMO_Get_Int(op, "axis");
+ int mirroru = BMO_Get_Int(op, "mirror_u");
+ int mirrorv = BMO_Get_Int(op, "mirror_v");
+
+ ototvert = bm->totvert;
+ ototedge = bm->totedge;
+
+ BMO_Get_Mat4(op, "mat", mtx);
+ Mat4Invert(imtx, mtx);
+
+ BMO_InitOpf(bm, &dupeop, "dupe geom=%s", op, "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ BMO_Flag_Buffer(bm, &dupeop, "newout", ELE_NEW, BM_ALL);
+
+ /*create old -> new mapping*/
+ i = 0;
+ v2 = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) {
+ BLI_array_growone(vmap);
+ vmap[i] = v;
+
+ BMINDEX_SET(v2, i);
+ v2 = BMIter_Step(&iter);
+
+ i += 1;
+ }
+
+ /*feed old data to transform bmop*/
+ scale[axis] = -1.0f;
+ BMO_CallOpf(bm, "transform verts=%fv mat=%m4", ELE_NEW, mtx);
+ BMO_CallOpf(bm, "scale verts=%fv vec=%v", ELE_NEW, scale);
+ BMO_CallOpf(bm, "transform verts=%fv mat=%m4", ELE_NEW, imtx);
+
+ BMO_Init_Op(&weldop, "weldverts");
+
+ v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; i<ototvert; i++) {
+ if (ABS(v->co[axis]) <= dist) {
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", vmap[i], v);
+ }
+ v = BMIter_Step(&iter);
+ }
+
+ if (mirroru || mirrorv) {
+ BMFace *f;
+ BMLoop *l;
+ MLoopUV *luv;
+ int totlayer;
+ BMIter liter;
+
+ BMO_ITER(f, &siter, bm, &dupeop, "newout", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ for (i=0; i<totlayer; i++) {
+ luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ if (mirroru)
+ luv->uv[0] = 1.0 - luv->uv[0];
+ if (mirrorv)
+ luv->uv[1] = 1.0 - luv->uv[1];
+ }
+ }
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+
+ BMO_Finish_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &dupeop);
+
+ BMO_Flag_To_Slot(bm, op, "newout", ELE_NEW, BM_ALL);
+
+ BLI_array_free(vmap);
+ BLI_array_free(emap);
+}
+
diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c
new file mode 100644
index 00000000000..e91c71a498c
--- /dev/null
+++ b/source/blender/bmesh/operators/removedoubles.c
@@ -0,0 +1,607 @@
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_ghash.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.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;
+ BLI_array_declare(edges);
+ BMLoop *l, *l2, **loops = NULL;
+ BLI_array_declare(loops);
+ BMFace *f, *f2;
+ int a, b;
+
+ 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) {
+ if (BMO_TestFlag(bm, e->v1, ELE_DEL) || BMO_TestFlag(bm, e->v2, ELE_DEL)) {
+ 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 (v == v2)
+ BMO_SetFlag(bm, e, EDGE_COL);
+ else if (!BM_Edge_Exist(v, v2))
+ 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|ELE_DEL);
+ 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;
+ }
+
+ BLI_array_empty(edges);
+ BLI_array_empty(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) {
+ for (b=0; b<a; b++) {
+ if (edges[b] == e2)
+ break;
+ }
+ if (b != a)
+ continue;
+
+ BLI_array_growone(edges);
+ BLI_array_growone(loops);
+
+ edges[a] = e2;
+ loops[a] = l;
+
+ a++;
+ }
+ }
+
+ if (BLI_array_count(loops) < 3)
+ continue;
+
+ 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);
+
+ a = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f2) {
+ l2 = loops[a];
+ BM_Copy_Attributes(bm, bm, l2, l);
+
+ a++;
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%fvef context=%i", ELE_DEL, DEL_ONLYTAGGED);
+
+ BLI_array_free(edges);
+ BLI_array_free(loops);
+}
+
+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
+#define VERT_MARK 16
+#define VERT_IN 32
+
+#define EDGE_MARK 1
+
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, *snapv;
+ BMLoop *l, *firstl = NULL;
+ float fac;
+ int i, tot;
+
+ snapv = BMO_IterNew(&siter, bm, op, "snapv", BM_VERT);
+ tot = BM_Vert_FaceCount(snapv);
+
+ if (!tot)
+ return;
+
+ fac = 1.0f / tot;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, snapv) {
+ if (!firstl) {
+ firstl = l;
+ }
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ int type = bm->ldata.layers[i].type;
+ void *e1, *e2;
+
+ e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i);
+ e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+
+ CustomData_data_multiply(type, e2, fac);
+
+ if (l != firstl)
+ CustomData_data_add(type, e1, e2);
+ }
+ }
+ }
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ if (l == firstl)
+ continue;
+
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
+ }
+ }
+}
+
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMLoop *l, *firstl = NULL;
+ CDBlockBytes min, max;
+ void *block;
+ int i, type;
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (!CustomData_layer_has_math(&bm->ldata, i))
+ continue;
+
+ type = bm->ldata.layers[i].type;
+ CustomData_data_initminmax(type, &min, &max);
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ CustomData_data_dominmax(type, block, &min, &max);
+ }
+ }
+
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ CustomData_data_copy_value(type, &min, block);
+ }
+ }
+ }
+}
+
+void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMOIter siter;
+ BMVert *v, *snapv = NULL;
+ float vec[3];
+
+ BMO_Get_Vec(op, "mergeco", vec);
+
+ //BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
+ BMO_Init_Op(&weldop, "weldverts");
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ if (!snapv) {
+ snapv = v;
+ VECCOPY(snapv->co, vec);
+ } else {
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+}
+
+void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMWalker walker;
+ BMIter iter;
+ BMEdge *e, **edges = NULL;
+ BLI_array_declare(edges);
+ float min[3], max[3];
+ int i, tot;
+
+ BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
+ BMO_Init_Op(&weldop, "weldverts");
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMW_Init(&walker, bm, BMW_SHELL, EDGE_MARK, 0);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+
+ e = BMW_Begin(&walker, e->v1);
+ BLI_array_empty(edges);
+
+ INIT_MINMAX(min, max);
+ for (tot=0; e; tot++, e=BMW_Step(&walker)) {
+ BLI_array_growone(edges);
+ edges[tot] = e;
+
+ DO_MINMAX(e->v1->co, min, max);
+ DO_MINMAX(e->v2->co, min, max);
+ }
+
+ VECADD(min, min, max);
+ VECMUL(min, 0.5f);
+
+ /*snap edges to a point. for initial testing purposes anyway.*/
+ for (i=0; i<tot; i++) {
+ VECCOPY(edges[i]->v1->co, min);
+ VECCOPY(edges[i]->v2->co, min);
+
+ if (edges[i]->v1 != edges[0]->v1)
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1);
+ if (edges[i]->v2 != edges[0]->v1)
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1);
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+
+ BMW_End(&walker);
+ BLI_array_free(edges);
+}
+
+/*uv collapse function*/
+void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
+{
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l, *l2;
+ BMWalker walker;
+ void **blocks = NULL;
+ BLI_array_declare(blocks);
+ CDBlockBytes min, max;
+ int i, tot, type = bm->ldata.layers[layer].type;
+
+ BMO_Clear_Flag_All(bm, op, BM_ALL, 65535);
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMW_Init(&walker, bm, BMW_LOOPDATA_ISLAND, EDGE_MARK, layer);
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (BMO_TestFlag(bm, l->e, EDGE_MARK)) {
+ /*walk*/
+ BLI_array_empty(blocks);
+ tot = 0;
+ l2 = BMW_Begin(&walker, l);
+
+ CustomData_data_initminmax(type, &min, &max);
+ for (tot=0; l2; tot++, l2=BMW_Step(&walker)) {
+ BLI_array_growone(blocks);
+ blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer);
+ CustomData_data_dominmax(type, blocks[tot], &min, &max);
+ }
+
+ if (tot) {
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ /*snap CD (uv, vcol) points to their centroid*/
+ for (i=0; i<tot; i++) {
+ CustomData_data_copy_value(type, &min, blocks[i]);
+ }
+ }
+ }
+ }
+ }
+
+ BMW_End(&walker);
+ BLI_array_free(blocks);
+}
+
+void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op)
+{
+ int i;
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i))
+ bmesh_collapsecon_do_layer(bm, op, i);
+ }
+}
+
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMOIter oiter;
+ BMVert *v, *v2;
+ BMVert **verts=NULL;
+ BLI_array_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) {
+ BLI_array_growone(verts);
+ verts[i++] = v;
+ }
+
+ /*sort by vertex coordinates added together*/
+ qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
+
+ len = BLI_array_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);
+ }
+ }
+ }
+
+ BLI_array_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;
+ BLI_array_declare(verts);
+ float dist, distsqr;
+ int i, j, len, keepvert;
+
+ dist = BMO_Get_Float(op, "dist");
+ distsqr = dist*dist;
+
+ i = 0;
+ BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+ BLI_array_growone(verts);
+ verts[i++] = v;
+ }
+
+ keepvert = BMO_IterNew(&oiter, bm, op, "keepverts", BM_VERT) != NULL;
+
+ /*sort by vertex coordinates added together*/
+ qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
+
+ BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP, BM_VERT);
+
+ len = BLI_array_count(verts);
+ for (i=0; i<len; i++) {
+ v = verts[i];
+ if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
+
+ for (j=i+1; j<len; j++) {
+ v2 = verts[j];
+ if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+ > distsqr) break;
+
+ if (keepvert) {
+ if (BMO_TestFlag(bm, v2, VERT_KEEP) == BMO_TestFlag(bm, v, VERT_KEEP))
+ continue;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ BLI_array_free(verts);
+}
+
+void bmesh_automerge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter oiter;
+ BMOperator weldop;
+ BMVert *v, *v2;
+ BMVert **verts=NULL;
+ BLI_array_declare(verts);
+ float dist, distsqr;
+ int i, j, len, keepvert;
+
+ dist = BMO_Get_Float(op, "dist");
+ distsqr = dist*dist;
+
+ i = 0;
+ BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+ BLI_array_growone(verts);
+ verts[i++] = v;
+ }
+
+ BMO_Init_Op(&weldop, "weldverts");
+
+ /*sort by vertex coordinates added together*/
+ qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
+
+ BMO_Flag_Buffer(bm, op, "verts", VERT_KEEP, BM_VERT);
+
+ len = BLI_array_count(verts);
+ for (i=0; i<len; i++) {
+ v = verts[i];
+ if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
+
+ for (j=i+1; j<len; j++) {
+ v2 = verts[j];
+ if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+ > distsqr) break;
+
+ /* only allow unselected -> selected */
+ if (BMO_TestFlag(bm, v2, VERT_IN))
+ continue;
+
+ if (VecLenCompare(v->co, v2->co, dist)) {
+ BMO_SetFlag(bm, v2, VERT_DOUBLE);
+ BMO_SetFlag(bm, v, VERT_TARGET);
+
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", v2, v);
+ }
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+
+ BLI_array_free(verts);
+}
diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c
new file mode 100644
index 00000000000..2b72a734c83
--- /dev/null
+++ b/source/blender/bmesh/operators/subdivideop.c
@@ -0,0 +1,1043 @@
+/**
+ * $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. 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): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_array.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 quad_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 quad_1edge = {
+ {1, 0, 0, 0},
+ quad_1edge_split,
+ 4,
+};
+
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_path(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 quad_2edge_path = {
+ {1, 1, 0, 0},
+ quad_2edge_split_path,
+ 4,
+};
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_innervert(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMVert *v, *lastv;
+ BMEdge *e, *ne;
+ int i, numcuts = params->numcuts;
+
+ lastv = verts[numcuts];
+
+ for (i=numcuts-1; i>=0; i--) {
+ e = connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
+ &nf);
+
+ v = BM_Split_Edge(bm, e->v1, e, &ne, 0.5f);
+ connect_smallest_face(bm, lastv, v, &nf);
+ lastv = v;
+ }
+
+ connect_smallest_face(bm, lastv, verts[numcuts*2+2], &nf);
+}
+
+subdpattern quad_2edge_innervert = {
+ {1, 1, 0, 0},
+ quad_2edge_split_innervert,
+ 4,
+};
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_fan(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMVert *v, *lastv;
+ BMEdge *e, *ne;
+ int i, numcuts = params->numcuts;
+
+ lastv = verts[2];
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts*2+2], &nf);
+ connect_smallest_face(bm, verts[numcuts+(numcuts-i)],
+ verts[numcuts*2+2], &nf);
+ }
+}
+
+subdpattern quad_2edge_fan = {
+ {1, 1, 0, 0},
+ quad_2edge_split_fan,
+ 4,
+};
+
+/* s s
+v8--v7--v6-v5
+| |
+| v4 s
+| |
+| v3 s
+| s s |
+v9-v0--v1-v2
+
+*/
+static void quad_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 quad_3edge = {
+ {1, 1, 1, 0},
+ quad_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 quad_4edge_subdivide(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 tri_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 tri_1edge = {
+ {1, 0, 0},
+ tri_1edge_split,
+ 3,
+};
+
+/* v5
+ / \
+ s v6/---\ v4 s
+ / \ / \
+sv7/---v---\ v3 s
+ / \/ \/ \
+ v8--v0--v1--v2
+ s s
+*/
+static void tri_3edge_subdivide(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 tri_3edge = {
+ {1, 1, 1},
+ tri_3edge_subdivide,
+ 3,
+};
+
+
+subdpattern quad_4edge = {
+ {1, 1, 1, 1},
+ quad_4edge_subdivide,
+ 4,
+};
+
+subdpattern *patterns[] = {
+ NULL, //quad single edge pattern is inserted here
+ NULL, //quad corner vert pattern is inserted here
+ NULL, //tri single edge pattern is inserted here
+ NULL,
+ &quad_3edge,
+ NULL,
+};
+
+#define PLEN (sizeof(patterns) / sizeof(void*))
+
+typedef struct subd_facedata {
+ BMVert *start; subdpattern *pat;
+ int totedgesel; //only used if pat was NULL, e.g. no pattern was found
+} subd_facedata;
+
+void esubdivide_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMOpSlot *einput;
+ BMEdge *edge, **edges = NULL;
+ BLI_array_declare(edges);
+ BMFace *face;
+ BMLoop *nl;
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+ BMIter fiter, liter;
+ subdpattern *pat;
+ subdparams params;
+ subd_facedata *facedata = NULL;
+ BLI_array_declare(facedata);
+ BMLoop *l, **splits = NULL, **loops = NULL;
+ BLI_array_declare(splits);
+ BLI_array_declare(loops);
+ float smooth, fractal;
+ int beauty, cornertype, singleedge, gridfill;
+ int i, j, matched, a, b, numcuts, totesel;
+
+ BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
+
+ numcuts = BMO_Get_Int(op, "numcuts");
+ smooth = BMO_Get_Float(op, "smooth");
+ fractal = BMO_Get_Float(op, "fractal");
+ beauty = BMO_Get_Int(op, "beauty");
+ cornertype = BMO_Get_Int(op, "quadcornertype");
+ singleedge = BMO_Get_Int(op, "singleedge");
+ gridfill = BMO_Get_Int(op, "gridfill");
+
+ patterns[1] = NULL;
+ //straight cut is patterns[1] == NULL
+ switch (cornertype) {
+ case SUBD_PATH:
+ patterns[1] = &quad_2edge_path;
+ break;
+ case SUBD_INNERVERT:
+ patterns[1] = &quad_2edge_innervert;
+ break;
+ case SUBD_FAN:
+ patterns[1] = &quad_2edge_fan;
+ break;
+ }
+
+ if (singleedge) {
+ patterns[0] = &quad_1edge;
+ patterns[2] = &tri_1edge;
+ } else {
+ patterns[0] = NULL;
+ patterns[2] = NULL;
+ }
+
+ if (gridfill) {
+ patterns[3] = &quad_4edge;
+ patterns[5] = &tri_3edge;
+ } else {
+ patterns[3] = NULL;
+ patterns[5] = NULL;
+ }
+
+ /*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)) {
+ BMEdge *e1 = NULL, *e2 = NULL;
+ float vec1[3], vec2[3];
+
+ /*figure out which pattern to use*/
+
+ BLI_array_empty(edges);
+ BLI_array_empty(verts);
+ matched = 0;
+
+ i = 0;
+ totesel = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ BLI_array_growone(edges);
+ BLI_array_growone(verts);
+ edges[i] = nl->e;
+ verts[i] = nl->v;
+
+ if (BMO_TestFlag(bmesh, edges[i], SUBD_SPLIT)) {
+ if (!e1) e1 = edges[i];
+ else e2 = edges[i];
+
+ totesel++;
+ }
+
+ i++;
+ }
+
+ /*make sure the two edges have a valid angle to each other*/
+ if (totesel == 2 && (e1->v1 == e2->v1 || e1->v1 == e2->v2
+ || e1->v2 == e2->v1 || e1->v2 == e2->v1)) {
+ float angle;
+
+ VecSubf(vec1, e1->v2->co, e1->v1->co);
+ VecSubf(vec2, e2->v2->co, e2->v1->co);
+ Normalize(vec1);
+ Normalize(vec2);
+
+ angle = INPR(vec1, vec2);
+ angle = ABS(angle);
+ if (ABS(angle-1.0) < 0.01)
+ totesel = 0;
+ }
+
+ 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) {
+ BLI_array_growone(facedata);
+ b = BLI_array_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.*/
+ BLI_array_growone(facedata);
+ }
+
+ /*obvously don't test for other patterns matching*/
+ continue;
+ }
+
+ for (i=0; i<PLEN; i++) {
+ pat = patterns[i];
+ if (!pat) continue;
+
+ 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) {
+ BLI_array_growone(facedata);
+ j = BLI_array_count(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+
+ facedata[j].pat = pat;
+ facedata[j].start = verts[a];
+ break;
+ }
+ }
+
+ }
+
+ if (!matched && totesel) {
+ BLI_array_growone(facedata);
+ j = BLI_array_count(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ facedata[j].totedgesel = totesel;
+ }
+ }
+
+ 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) BLI_array_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*/
+ BLI_array_empty(verts);
+ if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0)
+ continue;
+
+ pat = facedata[i].pat;
+ if (!pat && facedata[i].totedgesel == 2) { /*ok, no pattern. we still may be able to do something.*/
+ BMFace *nf;
+ int vlen;
+
+ BLI_array_empty(loops);
+ BLI_array_empty(splits);
+
+ /*for case of two edges, connecting them shouldn't be too hard*/
+ BM_ITER(l, &liter, bmesh, BM_LOOPS_OF_FACE, face) {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = l;
+ }
+
+ vlen = BLI_array_count(loops);
+
+ /*find the boundary of one of the split edges*/
+ for (a=1; a<vlen; a++) {
+ if (!BMO_TestFlag(bmesh, loops[a-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[a]->v, ELE_INNER))
+ break;
+ }
+
+ if (BMO_TestFlag(bmesh, loops[(a+numcuts+1)%vlen]->v, ELE_INNER)) {
+ b = (a+numcuts+1)%vlen;
+ } else {
+ /*find the boundary of the other edge.*/
+ for (j=0; j<vlen; j++) {
+ b = (j + a + numcuts + 1) % vlen;
+ if (!BMO_TestFlag(bmesh, loops[b==0 ? vlen-1 : b-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[b]->v, ELE_INNER))
+ break;
+ }
+ }
+
+ b += numcuts - 1;
+
+ for (j=0; j<numcuts; j++) {
+ BLI_array_growone(splits);
+ splits[BLI_array_count(splits)-1] = loops[a];
+
+ BLI_array_growone(splits);
+ splits[BLI_array_count(splits)-1] = loops[b];
+
+ b = (b-1) % vlen;
+ a = (a+1) % vlen;
+ }
+
+ //BM_LegalSplits(bmesh, face, splits, BLI_array_count(splits)/2);
+
+ for (j=0; j<BLI_array_count(splits)/2; j++) {
+ if (splits[j*2]) {
+ BMFace *nf;
+
+ nf = BM_Split_Face(bmesh, face, splits[j*2]->v, splits[j*2+1]->v, &nl, NULL);
+ }
+ }
+
+ i++;
+ continue;
+ } else if (!pat) {
+ i++;
+ 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++) {
+ BLI_array_growone(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) BLI_array_free(facedata);
+ if (edges) BLI_array_free(edges);
+ if (verts) BLI_array_free(verts);
+ BLI_array_free(splits);
+ BLI_array_free(loops);
+
+ 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, int cornertype, int singleedge, int gridfill)
+{
+ BMOperator op;
+
+ BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
+ "beauty=%d numcuts=%d quadcornertype=%d singleedge=%d "
+ "gridfill=%d",
+ flag, smooth, fractal, beauty, numcuts,
+ cornertype, singleedge, gridfill);
+
+ 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);
+ }
+ } else if (seltype == SUBDIV_SELECT_LOOPCUT) {
+ BMOIter iter;
+ BMHeader *ele;
+ int i;
+
+ /*deselect input*/
+ BM_clear_flag_all(bm, BM_SELECT);
+
+ 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
+
+void esplit_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ subdparams params;
+
+ params.numcuts = BMO_GetSlot(op, "numcuts")->data.i;
+ params.op = op;
+
+ /*go through and split edges*/
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "outsplit",
+ ELE_SPLIT, BM_ALL);
+}
+
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..1951e9dffa0
--- /dev/null
+++ b/source/blender/bmesh/operators/triangulateop.c
@@ -0,0 +1,56 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+#include "BLI_array.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;
+ BLI_array_declare(newfaces);
+ float (*projectverts)[3] = NULL;
+ BLI_array_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) {
+ BLI_array_empty(projectverts);
+ BLI_array_empty(newfaces);
+ for (lastlen=0; lastlen<face->len; lastlen++) {
+ BLI_array_growone(projectverts);
+ BLI_array_growone(projectverts);
+ BLI_array_growone(projectverts);
+ BLI_array_growone(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);
+
+ BLI_array_free(projectverts);
+ BLI_array_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..81ddb9a7e8e
--- /dev/null
+++ b/source/blender/bmesh/operators/utils.c
@@ -0,0 +1,1300 @@
+#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_array.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "BLI_heap.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);
+ }
+}
+
+void bmesh_translate_exec(BMesh *bm, BMOperator *op)
+{
+ 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_scale_exec(BMesh *bm, BMOperator *op)
+{
+ float mat[3][3], vec[3];
+
+ BMO_Get_Vec(op, "vec", vec);
+
+ Mat3One(mat);
+ mat[0][0] = vec[0];
+ mat[1][1] = vec[1];
+ mat[2][2] = vec[2];
+
+ BMO_CallOpf(bm, "transform mat=%m3 verts=%s", mat, op, "verts");
+}
+
+void bmesh_rotate_exec(BMesh *bm, BMOperator *op)
+{
+ float 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);
+}
+
+void bmesh_reversefaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMFace *f;
+
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ BM_flip_normal(bm, f);
+ }
+}
+
+void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e, *e2;
+ int ccw = BMO_Get_Int(op, "ccw");
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (!(e2 = BM_Rotate_Edge(bm, e, ccw))) {
+ BMO_RaiseError(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge");
+ return;
+ }
+
+ BMO_SetFlag(bm, e2, 1);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", 1, BM_EDGE);
+}
+
+#define SEL_FLAG 1
+#define SEL_ORIG 2
+
+static void bmesh_regionextend_extend(BMesh *bm, BMOperator *op, int usefaces)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMIter eiter;
+ BMOIter siter;
+
+ if (!usefaces) {
+ BMO_ITER(v, &siter, bm, op, "geom", BM_VERT) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, SEL_ORIG))
+ break;
+ }
+
+ if (e) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BMO_SetFlag(bm, e, SEL_FLAG);
+ BMO_SetFlag(bm, BM_OtherEdgeVert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ } else {
+ BMIter liter, fiter;
+ BMFace *f, *f2;
+ BMLoop *l;
+
+ BMO_ITER(f, &siter, bm, op, "geom", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (!BMO_TestFlag(bm, f2, SEL_ORIG))
+ BMO_SetFlag(bm, f2, SEL_FLAG);
+ }
+ }
+ }
+ }
+}
+
+static void bmesh_regionextend_constrict(BMesh *bm, BMOperator *op, int usefaces)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMIter eiter;
+ BMOIter siter;
+
+ if (!usefaces) {
+ BMO_ITER(v, &siter, bm, op, "geom", BM_VERT) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, SEL_ORIG))
+ break;
+ }
+
+ if (e) {
+ BMO_SetFlag(bm, v, SEL_FLAG);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BMO_SetFlag(bm, e, SEL_FLAG);
+ }
+ }
+ }
+ } else {
+ BMIter liter, fiter;
+ BMFace *f, *f2;
+ BMLoop *l;
+
+ BMO_ITER(f, &siter, bm, op, "geom", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (!BMO_TestFlag(bm, f2, SEL_ORIG)) {
+ BMO_SetFlag(bm, f, SEL_FLAG);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void bmesh_regionextend_exec(BMesh *bm, BMOperator *op)
+{
+ int usefaces = BMO_Get_Int(op, "usefaces");
+ int constrict = BMO_Get_Int(op, "constrict");
+
+ BMO_Flag_Buffer(bm, op, "geom", SEL_ORIG, BM_ALL);
+
+ if (constrict)
+ bmesh_regionextend_constrict(bm, op, usefaces);
+ else
+ bmesh_regionextend_extend(bm, op, usefaces);
+
+ BMO_Flag_To_Slot(bm, op, "geomout", SEL_FLAG, BM_ALL);
+}
+
+/********* righthand faces implementation ********/
+
+#define FACE_VIS 1
+#define FACE_FLAG 2
+#define FACE_MARK 4
+
+/* NOTE: these are the original righthandfaces comment in editmesh_mods.c,
+ copied here for reference.
+*/
+ /* based at a select-connected to witness loose objects */
+
+ /* count per edge the amount of faces */
+
+ /* find the ultimate left, front, upper face (not manhattan dist!!) */
+ /* also evaluate both triangle cases in quad, since these can be non-flat */
+
+ /* put normal to the outside, and set the first direction flags in edges */
+
+ /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
+ /* this is in fact the 'select connected' */
+
+ /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
+
+/*note: this function uses recursion, which is a little unusual for a bmop
+ function, but acceptable I think.*/
+void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter liter, liter2;
+ BMOIter siter;
+ BMFace *f, *startf, **fstack = NULL;
+ BLI_array_declare(fstack);
+ BMLoop *l, *l2;
+ float maxx, cent[3];
+ int i, maxi;
+
+ startf= NULL;
+ maxx= -1.0e10;
+
+ BMO_Flag_Buffer(bm, op, "faces", FACE_FLAG, BM_FACE);
+
+ /*find a starting face*/
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ if (BMO_TestFlag(bm, f, FACE_VIS))
+ continue;
+
+ if (!startf) startf = f;
+
+ BM_Compute_Face_Center(bm, f, cent);
+
+ cent[0] = cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
+ if (cent[0] > maxx) {
+ maxx = cent[0];
+ startf = f;
+ }
+ }
+
+ if (!startf) return;
+
+ BM_Compute_Face_Center(bm, startf, cent);
+
+ /*make sure the starting face has the correct winding*/
+ if (cent[0]*startf->no[0] + cent[1]*startf->no[1] + cent[2]*startf->no[2] < 0.0)
+ BM_flip_normal(bm, startf);
+
+ /*now that we've found our starting face, make all connected faces
+ have the same winding. this is done recursively, using a manual
+ stack (if we use simple function recursion, we'd end up overloading
+ the stack on large meshes).*/
+
+ BLI_array_growone(fstack);
+ fstack[0] = startf;
+ BMO_SetFlag(bm, startf, FACE_VIS);
+
+ i = 0;
+ maxi = 1;
+ while (i >= 0) {
+ f = fstack[i];
+ i--;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_LOOP, l) {
+ if (!BMO_TestFlag(bm, l2->f, FACE_FLAG) || l2 == l)
+ continue;
+
+ if (!BMO_TestFlag(bm, l2->f, FACE_VIS)) {
+ BMO_SetFlag(bm, l2->f, FACE_VIS);
+ i++;
+
+ if (l2->v == l->v)
+ BM_flip_normal(bm, l2->f);
+
+ if (i == maxi) {
+ BLI_array_growone(fstack);
+ maxi++;
+ }
+
+ fstack[i] = l2->f;
+ }
+ }
+ }
+ }
+
+ BLI_array_free(fstack);
+
+ /*check if we have faces yet to do. if so, recurse.*/
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ if (!BMO_TestFlag(bm, f, FACE_VIS)) {
+ bmesh_righthandfaces_exec(bm, op);
+ break;
+ }
+ }
+}
+
+void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BLI_array_declare(cos);
+ float (*cos)[3] = NULL;
+ float *co, *co2, clipdist = BMO_Get_Float(op, "clipdist");
+ int i, j, clipx, clipy, clipz;
+
+ clipx = BMO_Get_Int(op, "mirror_clip_x");
+ clipy = BMO_Get_Int(op, "mirror_clip_y");
+ clipz = BMO_Get_Int(op, "mirror_clip_z");
+
+ i = 0;
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BLI_array_growone(cos);
+ co = cos[i];
+
+ j = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ co2 = BM_OtherEdgeVert(e, v)->co;
+ VECADD(co, co, co2);
+ j += 1;
+ }
+
+ if (!j) {
+ VECCOPY(co, v->co);
+ i++;
+ continue;
+ }
+
+ co[0] /= (float)j;
+ co[1] /= (float)j;
+ co[2] /= (float)j;
+
+ co[0] = v->co[0]*0.5 + co[0]*0.5;
+ co[1] = v->co[1]*0.5 + co[1]*0.5;
+ co[2] = v->co[2]*0.5 + co[2]*0.5;
+
+ if (clipx && fabs(v->co[0]) < clipdist)
+ co[0] = 0.0f;
+ if (clipy && fabs(v->co[1]) < clipdist)
+ co[1] = 0.0f;
+ if (clipz && fabs(v->co[2]) < clipdist)
+ co[2] = 0.0f;
+
+ i++;
+ }
+
+ i = 0;
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ VECCOPY(v->co, cos[i]);
+ i++;
+ }
+
+ BLI_array_free(cos);
+}
+
+/*
+** compute the centroid of an ngon
+**
+** NOTE: This should probably go to bmesh_polygon.c and replace the function that compute its center
+** basing on bounding box
+*/
+static void ngon_center(float *v, BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ v[0] = v[1] = v[2] = 0;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ VecAddf(v, v, l->v->co);
+ }
+
+ if( f->len )
+ {
+ v[0] /= f->len;
+ v[1] /= f->len;
+ v[2] /= f->len;
+ }
+}
+
+/*
+** compute the perimeter of an ngon
+**
+** NOTE: This should probably go to bmesh_polygon.c
+*/
+static float ngon_perimeter(BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ int num_verts = 0;
+ float v[3], sv[3];
+ float perimeter = 0.0f;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if( num_verts == 0 ) {
+ sv[0] = v[0] = l->v->co[0];
+ sv[1] = v[1] = l->v->co[1];
+ sv[2] = v[2] = l->v->co[2];
+ num_verts++;
+ } else {
+ perimeter += VecLenf(v, l->v->co);
+ v[0] = l->v->co[0];
+ v[1] = l->v->co[1];
+ v[2] = l->v->co[2];
+ num_verts++;
+ }
+ }
+
+ perimeter += VecLenf(v, sv);
+
+ return perimeter;
+}
+
+/*
+** compute the fake surface of an ngon
+** This is done by decomposing the ngon into triangles who share the centroid of the ngon
+** while this method is far from being exact, it should garantee an invariance.
+**
+** NOTE: This should probably go to bmesh_polygon.c
+*/
+static float ngon_fake_area(BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ int num_verts = 0;
+ float v[3], sv[3], c[3];
+ float area = 0.0f;
+
+ ngon_center(c, bm, f);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if( num_verts == 0 ) {
+ sv[0] = v[0] = l->v->co[0];
+ sv[1] = v[1] = l->v->co[1];
+ sv[2] = v[2] = l->v->co[2];
+ num_verts++;
+ } else {
+ area += AreaT3Dfl(v, c, l->v->co);
+ v[0] = l->v->co[0];
+ v[1] = l->v->co[1];
+ v[2] = l->v->co[2];
+ num_verts++;
+ }
+ }
+
+ area += AreaT3Dfl(v, c, sv);
+
+ return area;
+}
+
+/*
+** extra face data (computed data)
+*/
+typedef struct tmp_face_ext {
+ BMFace *f; /* the face */
+ float c[3]; /* center */
+ union {
+ float area; /* area */
+ float perim; /* perimeter */
+ float d; /* 4th component of plane (the first three being the normal) */
+ struct Image *t; /* image pointer */
+ };
+} tmp_face_ext;
+
+/*
+** Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces
+*/
+void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter fm_iter;
+ BMFace *fs, *fm;
+ BMOIter fs_iter;
+ int num_sels = 0, num_total = 0, i = 0, idx = 0;
+ float angle = 0.0f;
+ tmp_face_ext *f_ext = NULL;
+ int *indices = NULL;
+ float t_no[3]; /* temporary normal */
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_FACE);
+
+ /*
+ ** The first thing to do is to iterate through all the the selected items and mark them since
+ ** they will be in the selection anyway.
+ ** This will increase performance, (especially when the number of originaly selected faces is high)
+ ** so the overall complexity will be less than $O(mn)$ where is the total number of selected faces,
+ ** and n is the total number of faces
+ */
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if (!BMO_TestFlag(bm, fs, FACE_MARK)) { /* is this really needed ? */
+ BMO_SetFlag(bm, fs, FACE_MARK);
+ num_sels++;
+ }
+ }
+
+ /* allocate memory for the selected faces indices and for all temporary faces */
+ indices = (int*)MEM_callocN(sizeof(int) * num_sels, "face indices util.c");
+ f_ext = (tmp_face_ext*)MEM_callocN(sizeof(tmp_face_ext) * num_total, "f_ext util.c");
+
+ /* loop through all the faces and fill the faces/indices structure */
+ BM_ITER(fm, &fm_iter, bm, BM_FACES_OF_MESH, NULL) {
+ f_ext[i].f = fm;
+ if (BMO_TestFlag(bm, fm, FACE_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+ i++;
+ }
+
+ /*
+ ** Save us some computation burden: In case of perimeter/area/coplanar selection we compute
+ ** only once.
+ */
+ if( type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE ) {
+ for( i = 0; i < num_total; i++ ) {
+ switch( type ) {
+ case SIMFACE_PERIMETER:
+ /* set the perimeter */
+ f_ext[i].perim = ngon_perimeter(bm, f_ext[i].f);
+ break;
+
+ case SIMFACE_COPLANAR:
+ /* compute the center of the polygon */
+ ngon_center(f_ext[i].c, bm, f_ext[i].f);
+
+ /* normalize the polygon normal */
+ VecCopyf(t_no, f_ext[i].f->no);
+ Normalize(t_no);
+
+ /* compute the plane distance */
+ f_ext[i].d = Inpf(t_no, f_ext[i].c);
+ break;
+
+ case SIMFACE_AREA:
+ f_ext[i].area = ngon_fake_area(bm, f_ext[i].f);
+ break;
+
+ case SIMFACE_IMAGE:
+ f_ext[i].t = NULL;
+ if( CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY) ) {
+ MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY);
+ f_ext[i].t = mtpoly->tpage;
+ }
+ break;
+ }
+ }
+ }
+
+ /* now select the rest (if any) */
+ for( i = 0; i < num_total; i++ ) {
+ fm = f_ext[i].f;
+ if( !BMO_TestFlag(bm, fm, FACE_MARK) && !BM_TestHFlag(fm, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ fs = f_ext[indices[idx]].f;
+ switch( type ) {
+ case SIMFACE_MATERIAL:
+ if( fm->mat_nr == fs->mat_nr ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_IMAGE:
+ if( f_ext[i].t == f_ext[indices[idx]].t ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_NORMAL:
+ angle = RAD2DEG(VecAngle2(fs->no, fm->no)); /* if the angle between the normals -> 0 */
+ if( angle / 180.0 <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_COPLANAR:
+ angle = RAD2DEG(VecAngle2(fs->no, fm->no)); /* angle -> 0 */
+ if( angle / 180.0 <= thresh ) { /* and dot product difference -> 0 */
+ if( fabs(f_ext[i].d - f_ext[indices[idx]].d) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ }
+ break;
+
+ case SIMFACE_AREA:
+ if( fabs(f_ext[i].area - f_ext[indices[idx]].area) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_PERIMETER:
+ if( fabs(f_ext[i].perim - f_ext[indices[idx]].perim) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(f_ext);
+ MEM_freeN(indices);
+
+ /* transfer all marked faces to the output slot */
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_MARK, BM_FACE);
+}
+
+/******************************************************************************
+** Similar Edges
+******************************************************************************/
+#define EDGE_MARK 1
+
+/*
+** compute the angle of an edge (i.e. the angle between two faces)
+*/
+static float edge_angle(BMesh *bm, BMEdge *e)
+{
+ BMIter fiter;
+ BMFace *f;
+ int num_faces = 0;
+ float n1[3], n2[3];
+ float angle = 0.0f;
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ if( num_faces == 0 ) {
+ n1[0] = f->no[0];
+ n1[1] = f->no[1];
+ n1[2] = f->no[2];
+ num_faces++;
+ } else {
+ n2[0] = f->no[0];
+ n2[1] = f->no[1];
+ n2[2] = f->no[2];
+ num_faces++;
+ }
+ }
+
+ angle = VecAngle2(n1, n2);
+
+ return angle;
+}
+/*
+** extra edge information
+*/
+typedef struct tmp_edge_ext {
+ BMEdge *e;
+ union {
+ float dir[3];
+ float angle; /* angle between the faces*/
+ };
+
+ union {
+ float length; /* edge length */
+ int faces; /* faces count */
+ };
+} tmp_edge_ext;
+
+/*
+** select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** choices are length, direction, face, ...
+*/
+void bmesh_similaredges_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter es_iter; /* selected edges iterator */
+ BMIter e_iter; /* mesh edges iterator */
+ BMEdge *es; /* selected edge */
+ BMEdge *e; /* mesh edge */
+ int idx = 0, i = 0, f = 0;
+ int *indices = NULL;
+ tmp_edge_ext *e_ext = NULL;
+ float *angles = NULL;
+ float angle;
+
+ int num_sels = 0, num_total = 0;
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_EDGE);
+
+ /* iterate through all selected edges and mark them */
+ BMO_ITER(es, &es_iter, bm, op, "edges", BM_EDGE) {
+ BMO_SetFlag(bm, es, EDGE_MARK);
+ num_sels++;
+ }
+
+ /* allocate memory for the selected edges indices and for all temporary edges */
+ indices = (int*)MEM_callocN(sizeof(int) * num_sels, "indices util.c");
+ e_ext = (tmp_edge_ext*)MEM_callocN(sizeof(tmp_edge_ext) * num_total, "e_ext util.c");
+
+ /* loop through all the edges and fill the edges/indices structure */
+ BM_ITER(e, &e_iter, bm, BM_EDGES_OF_MESH, NULL) {
+ e_ext[i].e = e;
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+ i++;
+ }
+
+ /* save us some computation time by doing heavy computation once */
+ if( type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR ||
+ type == SIMEDGE_FACE_ANGLE ) {
+ for( i = 0; i < num_total; i++ ) {
+ switch( type ) {
+ case SIMEDGE_LENGTH: /* compute the length of the edge */
+ e_ext[i].length = VecLenf(e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+ break;
+
+ case SIMEDGE_DIR: /* compute the direction */
+ VecSubf(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+ break;
+
+ case SIMEDGE_FACE: /* count the faces around the edge */
+ e_ext[i].faces = BM_Edge_FaceCount(e_ext[i].e);
+ break;
+
+ case SIMEDGE_FACE_ANGLE:
+ e_ext[i].faces = BM_Edge_FaceCount(e_ext[i].e);
+ if( e_ext[i].faces == 2 )
+ e_ext[i].angle = edge_angle(bm, e_ext[i].e);
+ break;
+ }
+ }
+ }
+
+ /* select the edges if any */
+ for( i = 0; i < num_total; i++ ) {
+ e = e_ext[i].e;
+ if( !BMO_TestFlag(bm, e, EDGE_MARK) && !BM_TestHFlag(e, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ es = e_ext[indices[idx]].e;
+ switch( type ) {
+ case SIMEDGE_LENGTH:
+ if( fabs(e_ext[i].length - e_ext[indices[idx]].length) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_DIR:
+ /* compute the angle between the two edges */
+ angle = RAD2DEG(VecAngle2(e_ext[i].dir, e_ext[indices[idx]].dir));
+
+ if( angle > 90.0 ) /* use the smallest angle between the edges */
+ angle = fabs(angle - 180.0f);
+
+ if( angle / 90.0 <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_FACE:
+ if( e_ext[i].faces == e_ext[indices[idx]].faces ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_FACE_ANGLE:
+ if( e_ext[i].faces == 2 ) {
+ if( e_ext[indices[idx]].faces == 2 ) {
+ if( fabs(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ }
+ } else cont = 0;
+ break;
+
+ case SIMEDGE_CREASE:
+ if( fabs(e->crease - es->crease) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_SEAM:
+ if( BM_TestHFlag(e, BM_SEAM) == BM_TestHFlag(es, BM_SEAM) ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_SHARP:
+ if( BM_TestHFlag(e, BM_SHARP) == BM_TestHFlag(es, BM_SHARP) ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(e_ext);
+ MEM_freeN(indices);
+
+ /* transfer all marked edges to the output slot */
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_MARK, BM_EDGE);
+}
+
+/******************************************************************************
+** Similar Vertices
+******************************************************************************/
+#define VERT_MARK 1
+
+typedef struct tmp_vert_ext {
+ BMVert *v;
+ union {
+ int num_faces; /* adjacent faces */
+ MDeformVert *dvert; /* deform vertex */
+ };
+} tmp_vert_ext;
+
+/*
+** select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** choices are normal, face, vertex group...
+*/
+void bmesh_similarverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter vs_iter; /* selected verts iterator */
+ BMIter v_iter; /* mesh verts iterator */
+ BMVert *vs; /* selected vertex */
+ BMVert *v; /* mesh vertex */
+ tmp_vert_ext *v_ext = NULL;
+ int *indices = NULL;
+ int num_total = 0, num_sels = 0, i = 0, idx = 0;
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_VERT);
+
+ /* iterate through all selected edges and mark them */
+ BMO_ITER(vs, &vs_iter, bm, op, "verts", BM_VERT) {
+ BMO_SetFlag(bm, vs, VERT_MARK);
+ num_sels++;
+ }
+
+ /* allocate memory for the selected vertices indices and for all temporary vertices */
+ indices = (int*)MEM_mallocN(sizeof(int) * num_sels, "vertex indices");
+ v_ext = (tmp_vert_ext*)MEM_mallocN(sizeof(tmp_vert_ext) * num_total, "vertex extra");
+
+ /* loop through all the vertices and fill the vertices/indices structure */
+ BM_ITER(v, &v_iter, bm, BM_VERTS_OF_MESH, NULL) {
+ v_ext[i].v = v;
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+
+ switch( type ) {
+ case SIMVERT_FACE:
+ /* calling BM_Vert_FaceCount every time is time consumming, so call it only once per vertex */
+ v_ext[i].num_faces = BM_Vert_FaceCount(v);
+ break;
+
+ case SIMVERT_VGROUP:
+ if( CustomData_has_layer(&(bm->vdata),CD_MDEFORMVERT) ) {
+ v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT);
+ } else v_ext[i].dvert = NULL;
+ break;
+ }
+
+ i++;
+ }
+
+ /* select the vertices if any */
+ for( i = 0; i < num_total; i++ ) {
+ v = v_ext[i].v;
+ if( !BMO_TestFlag(bm, v, VERT_MARK) && !BM_TestHFlag(v, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ vs = v_ext[indices[idx]].v;
+ switch( type ) {
+ case SIMVERT_NORMAL:
+ /* compare the angle between the normals */
+ if( RAD2DEG(VecAngle2(v->no, vs->no) / 180.0 <= thresh )) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+
+ }
+ break;
+ case SIMVERT_FACE:
+ /* number of adjacent faces */
+ if( v_ext[i].num_faces == v_ext[indices[idx]].num_faces ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMVERT_VGROUP:
+ if( v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL ) {
+ int v1, v2;
+ for( v1 = 0; v1 < v_ext[i].dvert->totweight && cont == 1; v1++ ) {
+ for( v2 = 0; v2 < v_ext[indices[idx]].dvert->totweight; v2++ ) {
+ if( v_ext[i].dvert->dw[v1].def_nr == v_ext[indices[idx]].dvert->dw[v2].def_nr ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(indices);
+ MEM_freeN(v_ext);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+/******************************************************************************
+** Cycle UVs for a face
+******************************************************************************/
+
+void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ int n;
+
+ int dir = BMO_Get_Int(op, "dir");
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPUV) ) {
+ if( dir == DIRECTION_CW ) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *f_luv; /* first face loop uv */
+ float p_uv[2]; /* previous uvs */
+ float t_uv[2]; /* tmp uvs */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ if( n == 0 ) {
+ f_luv = luv;
+ p_uv[0] = luv->uv[0];
+ p_uv[1] = luv->uv[1];
+ } else {
+ t_uv[0] = luv->uv[0];
+ t_uv[1] = luv->uv[1];
+ luv->uv[0] = p_uv[0];
+ luv->uv[1] = p_uv[1];
+ p_uv[0] = t_uv[0];
+ p_uv[1] = t_uv[1];
+ }
+ n++;
+ }
+
+ f_luv->uv[0] = p_uv[0];
+ f_luv->uv[1] = p_uv[1];
+ } else if( dir == DIRECTION_CCW ) { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *p_luv; /*previous loop uv */
+ MLoopUV *luv;
+ float t_uv[2]; /* current uvs */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* previous loop uv is the current loop uv */
+ luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ if( n == 0 ) {
+ p_luv = luv;
+ t_uv[0] = luv->uv[0];
+ t_uv[1] = luv->uv[1];
+ } else {
+ p_luv->uv[0] = luv->uv[0];
+ p_luv->uv[1] = luv->uv[1];
+ p_luv = luv;
+ }
+ n++;
+ }
+
+ luv->uv[0] = t_uv[0];
+ luv->uv[1] = t_uv[1];
+ }
+ }
+ }
+
+}
+
+/******************************************************************************
+** Reverse UVs for a face
+******************************************************************************/
+
+void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ BLI_array_declare(uvs);
+ float (*uvs)[2] = NULL;
+ int max_vert_count = 0;
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPUV) ) {
+ BMLoop *lf; /* current face loops */
+ MLoopUV *f_luv; /* first face loop uv */
+ int num_verts = fs->len;
+ int i = 0;
+
+ BLI_array_empty(uvs);
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+
+ /* current loop uv is the previous loop uv */
+ BLI_array_growone(uvs);
+ uvs[i][0] = luv->uv[0];
+ uvs[i][1] = luv->uv[1];
+ i++;
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ i = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ luv->uv[0] = uvs[(fs->len - i - 1)][0];
+ luv->uv[1] = uvs[(fs->len - i - 1)][1];
+ i++;
+ }
+ }
+ }
+
+ BLI_array_free(uvs);
+}
+
+/******************************************************************************
+** Cycle colors for a face
+******************************************************************************/
+
+void bmesh_rotatecolors_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ int n;
+
+ int dir = BMO_Get_Int(op, "dir");
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL) ) {
+ if( dir == DIRECTION_CW ) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *f_lcol; /* first face loop color */
+ MLoopCol p_col; /* previous color */
+ MLoopCol t_col; /* tmp color */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop color is the previous loop color */
+ MLoopCol *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ if( n == 0 ) {
+ f_lcol = luv;
+ p_col = *luv;
+ } else {
+ t_col = *luv;
+ *luv = p_col;
+ p_col = t_col;
+ }
+ n++;
+ }
+
+ *f_lcol = p_col;
+ } else if( dir == DIRECTION_CCW ) { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *p_lcol; /*previous loop color */
+ MLoopCol *lcol;
+ MLoopCol t_col; /* current color */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* previous loop color is the current loop color */
+ lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ if( n == 0 ) {
+ p_lcol = lcol;
+ t_col = *lcol;
+ } else {
+ *p_lcol = *lcol;
+ p_lcol = lcol;
+ }
+ n++;
+ }
+
+ *lcol = t_col;
+ }
+ }
+ }
+}
+
+/******************************************************************************
+** Reverse colors for a face
+******************************************************************************/
+
+void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ BLI_array_declare(cols);
+ MLoopCol *cols = NULL;
+ int max_vert_count = 0;
+
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL) ) {
+ BMLoop *lf; /* current face loops */
+ MLoopCol *f_lcol; /* first face loop color */
+ int num_verts = fs->len;
+ int i = 0;
+
+ BLI_array_empty(cols);
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+
+ /* current loop uv is the previous loop color */
+ BLI_array_growone(cols);
+ cols[i] = *lcol;
+ i++;
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ i = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop color */
+ MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ *lcol = cols[(fs->len - i - 1)];
+ i++;
+ }
+ }
+ }
+
+ BLI_array_free(cols);
+}
+
+
+/******************************************************************************
+** shortest vertex path select
+******************************************************************************/
+
+typedef struct element_node {
+ BMVert *v; /* vertex */
+ BMVert *parent; /* node parent id */
+ float weight; /* node weight */
+ HeapNode *hn; /* heap node */
+} element_node;
+
+void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter vs_iter, vs2_iter; /* selected verts iterator */
+ BMIter v_iter; /* mesh verts iterator */
+ BMVert *vs, *sv, *ev; /* starting vertex, ending vertex */
+ BMVert *v; /* mesh vertex */
+ Heap *h = NULL;
+
+ element_node *vert_list = NULL;
+
+ int num_total = 0, num_sels = 0, i = 0;
+ int type = BMO_Get_Int(op, "type");
+
+ BMO_ITER(vs, &vs_iter, bm, op, "startv", BM_VERT)
+ sv = vs;
+ BMO_ITER(vs, &vs_iter, bm, op, "endv", BM_VERT)
+ ev = vs;
+
+ num_total = BM_Count_Element(bm, BM_VERT);
+
+ /* allocate memory for the nodes */
+ vert_list = (element_node*)MEM_mallocN(sizeof(element_node) * num_total, "vertex nodes");
+
+ /* iterate through all the mesh vertices */
+ /* loop through all the vertices and fill the vertices/indices structure */
+ i = 0;
+ BM_ITER(v, &v_iter, bm, BM_VERTS_OF_MESH, NULL) {
+ vert_list[i].v = v;
+ vert_list[i].parent = NULL;
+ vert_list[i].weight = FLT_MAX;
+ BMINDEX_SET(v, i);
+ i++;
+ }
+
+ /*
+ ** we now have everything we need, start Dijkstra path finding algorithm
+ */
+
+ /* set the distance/weight of the start vertex to 0 */
+ vert_list[BMINDEX_GET(sv)].weight = 0.0f;
+
+ h = BLI_heap_new();
+
+ for( i = 0; i < num_total; i++ )
+ vert_list[i].hn = BLI_heap_insert(h, vert_list[i].weight, vert_list[i].v);
+
+ while( !BLI_heap_empty(h) ) {
+ BMEdge *e;
+ BMIter e_i;
+ float v_weight;
+
+ /* take the vertex with the lowest weight out of the heap */
+ BMVert *v = (BMVert*)BLI_heap_popmin(h);
+
+ if( vert_list[BMINDEX_GET(v)].weight == FLT_MAX ) /* this means that there is no path */
+ break;
+
+ v_weight = vert_list[BMINDEX_GET(v)].weight;
+
+ BM_ITER(e, &e_i, bm, BM_EDGES_OF_VERT, v) {
+ BMVert *u;
+ float e_weight = v_weight;
+
+ if( type == VPATH_SELECT_EDGE_LENGTH )
+ e_weight += VecLenf(e->v1->co, e->v2->co);
+ else e_weight += 1.0f;
+
+ u = ( e->v1 == v ) ? e->v2 : e->v1;
+
+ if( e_weight < vert_list[BMINDEX_GET(u)].weight ) { /* is this path shorter ? */
+ /* add it if so */
+ vert_list[BMINDEX_GET(u)].parent = v;
+ vert_list[BMINDEX_GET(u)].weight = e_weight;
+
+ /* we should do a heap update node function!!! :-/ */
+ BLI_heap_remove(h, vert_list[BMINDEX_GET(u)].hn);
+ BLI_heap_insert(h, e_weight, u);
+ }
+ }
+ }
+
+ /* now we trace the path (if it exists) */
+ v = ev;
+
+ while( vert_list[BMINDEX_GET(v)].parent != NULL ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ v = vert_list[BMINDEX_GET(v)].parent;
+ }
+
+ BLI_heap_free(h, NULL);
+ MEM_freeN(vert_list);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
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/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index d13d7ce2ff2..5433e317bd1 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -27,65 +27,61 @@
FILE(GLOB SRC */*.c)
SET(INC ../windowmanager
- ../editors/include
- ../../../intern/guardedalloc ../../../intern/memutil
- ../blenlib ../makesdna ../makesrna ../blenkernel
- ../include ../imbuf ../render/extern/include
- ../../../intern/bsp/extern
- ../../../intern/decimation/extern ../blenloader ../python
- ../../kernel/gen_system ../readstreamglue
- ../../../intern/elbeem/extern
- ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include ../../../intern/smoke/extern
- ../../../intern/audaspace/intern
- ../nodes
- ../gpu
- ../blenfont
+ ../editors/include
+ ../../../intern/guardedalloc ../../../intern/memutil
+ ../blenlib ../makesdna ../makesrna ../blenkernel
+ ../include ../imbuf ../render/extern/include
+ ../../../intern/bsp/extern ../radiosity/extern/include
+ ../../../intern/decimation/extern ../blenloader ../python
+ ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue
+ ../quicktime ../../../intern/elbeem/extern
+ ../../../intern/ghost ../../../intern/opennl/extern ../../../extern/glew/include ../../../intern/smoke/extern
+ ../nodes ../bmesh
+ ../gpu
+ ../blenfont
+ ${SDL_INC}
../ikplugin
)
-IF(WITH_GAMEENGINE)
- ADD_DEFINITIONS(-DGAMEBLENDER)
-ENDIF(WITH_GAMEENGINE)
-
IF(WITH_INTERNATIONAL)
- ADD_DEFINITIONS(-DINTERNATIONAL)
+ ADD_DEFINITIONS(-DINTERNATIONAL)
ENDIF(WITH_INTERNATIONAL)
IF(WITH_OPENEXR)
- ADD_DEFINITIONS(-DWITH_OPENEXR)
+ ADD_DEFINITIONS(-DWITH_OPENEXR)
ENDIF(WITH_OPENEXR)
IF(WITH_OPENJPEG)
- ADD_DEFINITIONS(-DWITH_OPENJPEG)
+ ADD_DEFINITIONS(-DWITH_OPENJPEG)
ENDIF(WITH_OPENJPEG)
IF(WITH_QUICKTIME)
- SET(INC ${INC} ../quicktime ${QUICKTIME_INC})
- ADD_DEFINITIONS(-DWITH_QUICKTIME)
+ SET(INC ${INC} ${QUICKTIME_INC})
+ ADD_DEFINITIONS(-DWITH_QUICKTIME)
ENDIF(WITH_QUICKTIME)
IF(WITH_FFMPEG)
- SET(INC ${INC} ${FFMPEG_INC})
- ADD_DEFINITIONS(-DWITH_FFMPEG)
+ SET(INC ${INC} ${FFMPEG_INC})
+ ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG)
IF(NOT WITH_ELBEEM)
- ADD_DEFINITIONS(-DDISABLE_ELBEEM)
+ ADD_DEFINITIONS(-DDISABLE_ELBEEM)
ENDIF(NOT WITH_ELBEEM)
IF(WITH_PYTHON)
- SET(INC ${INC} ${PYTHON_INC})
+ SET(INC ${INC} ${PYTHON_INC})
ELSE(WITH_PYTHON)
- ADD_DEFINITIONS(-DDISABLE_PYTHON)
+ ADD_DEFINITIONS(-DDISABLE_PYTHON)
ENDIF(WITH_PYTHON)
IF(WIN32)
- SET(INC ${INC} ${PTHREADS_INC})
+ SET(INC ${INC} ${PTHREADS_INC})
ENDIF(WIN32)
# TODO buildinfo
IF(BF_BUILDINFO)
- ADD_DEFINITIONS(-DNAN_BUILDINFO)
+ ADD_DEFINITIONS(-DNAN_BUILDINFO)
ENDIF(BF_BUILDINFO)
BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}")
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 82843a49851..160f505c3f5 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -1116,8 +1116,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);
@@ -1143,8 +1143,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);
VECADDFAC( end, isec->start, isec->vec, isec->labda );
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 50411c9d998..d4b695e1b7f 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 wmKeyConfig;
struct ReportList;
@@ -51,37 +50,105 @@ struct MCol;
struct UvVertMap;
struct UvMapVert;
struct CustomData;
+struct BMEditSelection;
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+struct UvVertMap;
+struct UvMapVert;
struct Material;
struct Object;
-#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 // deprecated, use mesh
#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 */
+
+void EDBM_RecalcNormals(struct BMEditMesh *em);
+
+void EDBM_MakeEditBMesh(struct ToolSettings *ts, 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);
+
+/*flushes based on the current select mode. if in vertex select mode,
+ verts select/deselect edges and faces, if in edge select mode,
+ edges select/deselect faces and vertices, and in face select mode faces select/deselect
+ edges and vertices.*/
+void EDBM_selectmode_flush(struct BMEditMesh *em);
+
+int EDBM_get_actSelection(struct BMEditMesh *em, struct BMEditSelection *ese);
+
+/*exactly the same as EDBM_selectmode_flush, but you pass in the selectmode
+ instead of using the current one*/
+void EDBM_select_flush(struct BMEditMesh *em, int selectmode);
+void EDBM_deselect_flush(struct BMEditMesh *em);
+
+void EDBM_selectmode_set(struct BMEditMesh *em);
+void EDBM_convertsel(struct BMEditMesh *em, short oldmode, short selectmode);
+
+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);
+int EDBM_vertColorCheck(struct BMEditMesh *em);
+
+void EDBM_pin_mesh(struct BMEditMesh *em, int swap);
+void EDBM_unpin_mesh(struct BMEditMesh *em, int swap);
+
+void EDBM_hide_mesh(struct BMEditMesh *em, int swap);
+void EDBM_reveal_mesh(struct BMEditMesh *em);
+
+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);
+
+void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
+void EDBM_set_actFace(struct BMEditMesh *em, struct BMFace *efa);
+
+int EDBM_texFaceCheck(struct BMEditMesh *em);
+struct MTexPoly *EDBM_get_active_mtexpoly(struct BMEditMesh *em, struct BMFace **act_efa, int sloppy);
+
+void EDBM_free_uv_vert_map(struct UvVertMap *vmap);
+struct UvMapVert *EDBM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
+struct UvVertMap *EDBM_make_uv_vert_map(struct BMEditMesh *em, int selected, int do_face_idx_array, float *limit);
+
+void EDBM_toggle_select_all(struct BMEditMesh *em);
+void EDBM_set_flag_all(struct BMEditMesh *em, int flag);
/* 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);
@@ -94,8 +161,8 @@ void ED_keymap_mesh(struct wmKeyConfig *keyconf);
void ED_spacetypes_init(void);
void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-void make_editMesh(struct Scene *scene, struct Object *ob);
-void load_editMesh(struct Scene *scene, struct Object *ob);
+struct EditMesh *make_editMesh(struct Scene *scene, struct Object *ob);
+void load_editMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em);
void remake_editMesh(struct Scene *scene, struct Object *ob);
void free_editMesh(struct EditMesh *em);
@@ -117,6 +184,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);
@@ -141,11 +209,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);
@@ -157,9 +222,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);
-
void EM_automerge(struct Scene *scene, struct Object *obedit, int update);
/* editface.c */
@@ -183,6 +245,20 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int ver
struct MDeformWeight *ED_vgroup_weight_verify(struct MDeformVert *dv, int defgroup);
struct MDeformWeight *ED_vgroup_weight_get(struct MDeformVert *dv, int defgroup);
+/**
+ * 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
+ */
+
+struct BMVert *EDBM_findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict);
+struct BMEdge *EDBM_findnearestedge(struct ViewContext *vc, int *dist);
+struct BMFace *EDBM_findnearestface(struct ViewContext *vc, int *dist);
+
/*needed by edge slide*/
struct EditVert *editedge_getOtherVert(struct EditEdge *eed, struct EditVert *eve);
struct EditVert *editedge_getSharedVert(struct EditEdge *eed, struct EditEdge *eed2);
@@ -205,4 +281,3 @@ int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob
int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
#endif /* ED_MESH_H */
-
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 8823437cf79..bf9b95d49d8 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -47,10 +47,10 @@ int ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obed
int ED_uvedit_test_silent(struct Object *obedit);
int ED_uvedit_test(struct Object *obedit);
-int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf);
-int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf);
+int uvedit_face_selected(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
+int uvedit_edge_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+int uvedit_uv_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
int ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima, float co[2], float uv[2]);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 2752402fb66..307dbd74872 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;
@@ -97,9 +97,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/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 1ae3634c73b..6e7814ad0f8 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -202,6 +202,9 @@ enum {
TH_DOPESHEET_CHANNELOB,
TH_DOPESHEET_CHANNELSUBOB,
+
+ TH_PIN,
+ TH_PIN_OPAC,
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 26a50cc3c24..5e148717963 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -355,6 +355,10 @@ char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_DOPESHEET_CHANNELSUBOB:
cp= ts->ds_subchannel;
break;
+ case TH_PIN:
+ cp= ts->pin; break;
+ case TH_PIN_OPAC:
+ cp= &ts->pin_opac; break;
}
}
@@ -475,6 +479,9 @@ void ui_theme_init_userdef(void)
SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80); // alpha 80 is not meant editable, used for wire+action draw
+
+ SETCOL(btheme->tv3d.pin, 115, 171, 209, 255);
+ btheme->tv3d.pin_opac = 40;
/* space buttons */
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
index 00391b3474a..ac46ee157cc 100644
--- a/source/blender/editors/mesh/SConscript
+++ b/source/blender/editors/mesh/SConscript
@@ -7,6 +7,7 @@ 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 '
if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c
new file mode 100644
index 00000000000..3e1d5034328
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_select.c
@@ -0,0 +1,1772 @@
+/**
+ * $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 "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 "BLI_array.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 "UI_resources.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(Scene *scene, Object *obedit, int update)
+{
+ BMEditMesh *em;
+ int len;
+
+ if ((scene->toolsettings->automerge) &&
+ (obedit && obedit->type==OB_MESH) &&
+ (((Mesh*)obedit->data)->mr==NULL))
+ {
+ em = ((Mesh*)obedit->data)->edit_btmesh;
+ if (!em)
+ return;
+
+ BMO_CallOpf(em->bm, "automerge verts=%hv dist=%f", BM_SELECT, scene->toolsettings->doublimit);
+ if (update) {
+ DAG_id_flush_update(obedit->data, 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(paint_facesel_test(vc->obact));
+ 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(paint_facesel_test(vc->obact));
+ 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;
+ 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;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ 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;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ 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;
+ }
+ }
+}
+
+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;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ data.pass = 0;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ 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 ************** */
+
+static EnumPropertyItem prop_similar_types[] = {
+ {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
+ {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
+
+ {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
+ {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
+ {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
+ {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
+ {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
+ {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
+
+ {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
+ {SIMFACE_AREA, "AREA", 0, "Area", ""},
+ {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
+ {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* selects new faces/edges/verts based on the existing selection */
+
+static int similar_face_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similarfaces faces=%hf type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+/* ***************************************************** */
+
+/* EDGE GROUP */
+
+/* wrap the above function but do selection flushing edge to face */
+static int similar_edge_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similaredges edges=%he type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_ALL);
+ EDBM_selectmode_flush(em);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+/* ********************************* */
+
+/*
+VERT GROUP
+ mode 1: same normal
+ mode 2: same number of face users
+ mode 3: same vertex groups
+*/
+
+
+static int similar_vert_select_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similarverts verts=%hv type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ EDBM_selectmode_flush(em);
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int select_similar_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if(type < 100)
+ return similar_vert_select_exec(C, op);
+ else if(type < 200)
+ return similar_edge_select_exec(C, op);
+ else
+ return similar_face_select_exec(C, op);
+}
+
+static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ EnumPropertyItem *item= NULL;
+ int a, totitem= 0;
+
+ if(obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for (a=SIMVERT_NORMAL; a<SIMEDGE_LENGTH; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ } else if(em->selectmode & SCE_SELECT_EDGE) {
+ for (a=SIMEDGE_LENGTH; a<SIMFACE_MATERIAL; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ } else if(em->selectmode & SCE_SELECT_FACE) {
+ for (a=SIMFACE_MATERIAL; a<=SIMFACE_COPLANAR; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ }
+ RNA_enum_item_end(&item, &totitem);
+
+ *free= 1;
+
+ return item;
+ }
+
+ return NULL;
+}
+
+void MESH_OT_select_similar(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Select Similar";
+ ot->idname= "MESH_OT_select_similar";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= select_similar_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select similar vertices, edges or faces by property types.";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
+ RNA_def_enum_funcs(prop, select_similar_type_itemf);
+}
+
+/* ***************************************************** */
+
+/* **************** LOOP SELECTS *************** */
+/*faceloop_select, edgeloop_select, and edgering_select, are left
+ here for reference purposes temporarily, but have all been replaced
+ by uses of walker_select.*/
+
+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, 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_GEOM|ND_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;
+ ot->description= "Select a loop of connected edges by connection type.";
+
+ /* 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;
+
+ /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
+ view3d_validate_backbuf(&vc);
+
+ 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)
+ walker_select(em, BMW_EDGERING, eed, select);
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(ring)
+ walker_select(em, BMW_EDGERING, eed, select);
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+
+ EDBM_selectmode_flush(em);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_GEOM|ND_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;
+ ot->description= "Select a loop of connected edges.";
+
+ /* 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->bm->selected.last) {
+ EditSelection *ese = em->bm->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 (CTX_data_tool_settings(C)->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_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+ }
+#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;
+ ot->description= "Select shortest path between two selections.";
+
+ /* 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, 0);
+ }
+ }
+ 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_GEOM|ND_SELECT, vc.obedit);
+}
+
+static void EDBM_strip_selections(BMEditMesh *em)
+{
+ BMEditSelection *ese, *nextese;
+
+ if(!(em->selectmode & SCE_SELECT_VERTEX)){
+ ese = em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_VERT) BLI_freelinkN(&(em->bm->selected),ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_EDGE)){
+ ese=em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_FACE)){
+ ese=em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_FACE) BLI_freelinkN(&(em->bm->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;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
+{
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+
+ if(em->bm->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, eve, !BM_TestHFlag(eve, BM_SELECT));
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, eed, !BM_TestHFlag(eed, BM_SELECT));
+ }
+ }
+ else {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, efa, !BM_TestHFlag(efa, BM_SELECT));
+ }
+
+ }
+// if (EM_texFaceCheck())
+}
+
+static int select_inverse_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ EDBM_select_swap(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_inverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Inverse";
+ ot->idname= "MESH_OT_select_inverse";
+ ot->description= "Select inverse of (un)selected vertices, edges or faces.";
+
+ /* api callbacks */
+ ot->exec= select_inverse_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ViewContext vc;
+ BMWalker walker;
+ BMEditMesh *em;
+ BMVert *eve;
+ BMEdge *e, *eed;
+ BMFace *efa;
+ short done=1, toggle=0;
+ int sel= !RNA_boolean_get(op->ptr, "deselect");
+ int limit= RNA_boolean_get(op->ptr, "limit");
+
+ /* unified_finednearest needs ogl */
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ em = vc.em;
+
+ if(vc.em->bm->totedge==0)
+ return OPERATOR_CANCELLED;
+
+ vc.mval[0]= event->mval[0];
+ vc.mval[1]= event->mval[1];
+
+ /* return warning! */
+
+ /*if(limit) {
+ int retval= select_linked_limited_invoke(&vc, 0, sel);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return retval;
+ }*/
+
+ if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ if (efa) {
+ eed = efa->loopbase->e;
+ } else if (!eed) {
+ if (!eve || !eve->edge)
+ return OPERATOR_CANCELLED;
+
+ eed = eve->edge;
+ }
+
+ BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
+ e = BMW_Begin(&walker, eed->v1);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(em->bm, e->v1, sel);
+ BM_Select(em->bm, e->v2, sel);
+ }
+ BMW_End(&walker);
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "MESH_OT_select_linked_pick";
+
+ /* api callbacks */
+ ot->invoke= select_linked_pick_invoke;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "select/deselect all vertices linked to the edge under the mouse cursor.";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BLI_array_declare(verts);
+ BMVert **verts = NULL;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BMWalker walker;
+ int i, tot;
+
+ tot = 0;
+ BM_ITER_SELECT(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ BLI_array_growone(verts);
+ verts[tot++] = v;
+ }
+ }
+
+ BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
+ for (i=0; i<tot; i++) {
+ e = BMW_Begin(&walker, verts[i]);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(em->bm, e->v1, 1);
+ BM_Select(em->bm, e->v2, 1);
+ }
+ }
+ BMW_End(&walker);
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ BLI_array_free(verts);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked All";
+ ot->idname= "MESH_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select all vertices linked to the active mesh.";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+/* ******************** **************** */
+
+static int select_more(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "MESH_OT_select_more";
+ ot->description= "Select more vertices, edges or faces connected to initial selection.";
+
+ /* api callbacks */
+ ot->exec= select_more;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int select_less(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 1, usefaces);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Less";
+ ot->idname= "MESH_OT_select_less";
+ ot->description= "Deselect vertices, edges or faces at the boundary of each selection region.";
+
+ /* api callbacks */
+ ot->exec= select_less;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/mesh/bmesh_selecthistory.c b/source/blender/editors/mesh/bmesh_selecthistory.c
new file mode 100644
index 00000000000..25c037170fa
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_selecthistory.c
@@ -0,0 +1,126 @@
+/**
+ * $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 "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 "BLI_array.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
+
+/*these wrap equivilent bmesh functions. I'm in two minds of it we should
+ just use the bm functions directly; on the one hand, there's no real
+ need (at the moment) to wrap them, but on the other hand having these
+ wrapped avoids a confusing mess of mixing BM_ and EDBM_ namespaces.*/
+
+void EDBM_editselection_center(BMEditMesh *em, float *center, BMEditSelection *ese)
+{
+ BM_editselection_center(em->bm, center, ese);
+}
+
+void EDBM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ BM_editselection_normal(normal, ese);
+}
+
+/* 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)
+{
+ BM_editselection_plane(em->bm, plane, ese);
+}
+
+void EDBM_remove_selection(BMEditMesh *em, void *data)
+{
+ BM_remove_selection(em->bm, data);
+}
+
+void EDBM_store_selection(BMEditMesh *em, void *data)
+{
+ BM_store_selection(em->bm, data);
+}
+
+void EDBM_validate_selections(BMEditMesh *em)
+{
+ BM_validate_selections(em->bm);
+}
diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c
new file mode 100644
index 00000000000..ad1654d2f3a
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_tools.c
@@ -0,0 +1,3364 @@
+ /* $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 "BLI_array.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"
+
+#include "editbmesh_bvh.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)
+{
+ ToolSettings *ts = CTX_data_tool_settings(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,
+ ts->editbutflag|flag,
+ cuts, 0, RNA_enum_get(op->ptr, "quadcorner"),
+ RNA_boolean_get(op->ptr, "tess_single_edge"),
+ RNA_boolean_get(op->ptr, "gridfill"));
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+/* Note, these values must match delete_mesh() event values */
+static EnumPropertyItem prop_mesh_cornervert_types[] = {
+ {SUBD_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
+ {SUBD_PATH, "PATH", 0, "Path", ""},
+ {SUBD_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
+ {SUBD_FAN, "FAN", 0, "Fan", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+void MESH_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->description= "Subdivide selected edges.";
+ 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, 20, "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);
+
+ /*props */
+ RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT, "Quad Corner Type", "Method used for subdividing two adjacent edges in a quad");
+ RNA_def_boolean(ot->srna, "tess_single_edge", 0, "Tesselate Single Edge", "Adds triangles to single edges belonging to triangles or quads");
+ RNA_def_boolean(ot->srna, "gridfill", 1, "Grid Fill", "Fill Fully Selected Triangles and Quads With A Grid");
+}
+
+/* individual face extrude */
+/* will use vertex normals for extrusion directions, so *nor is unaffected */
+short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
+{
+ BMOIter siter;
+ BMIter liter;
+ BMFace *f;
+ BMLoop *l;
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_face_indiv faces=%hf", flag);
+
+ /*deselect original verts*/
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+
+ BMO_ITER(f, &siter, em->bm, &bmop, "faceout", BM_FACE) {
+ BM_Select(em->bm, f, 1);
+
+ /*set face vertex normals to face normal*/
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ VECCOPY(l->v->no, f->no);
+ }
+ }
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 's'; // s is shrink/fatten
+}
+
+#if 0
+short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
+ 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 */
+short EDBM_Extrude_edges_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
+{
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_edge_only edges=%he", flag);
+
+ /*deselect original verts*/
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_VERT|BM_EDGE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 'n'; // n is normal grab
+}
+
+#if 0
+/* nor is filled with constraint vector */
+short EDBM_Extrude_edges_indiv(BMEditMesh *em, short flag, float *nor)
+{
+ 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
+ return 'n'; // n is for normal constraint
+}
+#endif
+
+/* extrudes individual vertices */
+short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor)
+{
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag);
+
+ /*deselect original verts*/
+ BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "verts", BM_SELECT, BM_VERT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_VERT);
+
+ 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);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_repeat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Repeat Mesh";
+ ot->description= "Extrude selected vertices, edges or faces repeatedly.";
+ 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, op, SELECT, nor);
+ else transmode= EDBM_Extrude_face_indiv(em, op, 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;
+}
+
+/* extrude without transform */
+static int mesh_extrude_region_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_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_extrude_region_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;
+ float nor[3];
+ int constraint_axis[3] = {0, 0, 1};
+ int tmode;
+
+ tmode = EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ 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_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_region(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Region";
+ ot->idname= "MESH_OT_extrude_region";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_region_invoke;
+ ot->exec= mesh_extrude_region_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", "");
+}
+
+static int mesh_extrude_verts_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_extrude_verts_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;
+ float nor[3];
+ int constraint_axis[3] = {0, 0, 1};
+ int tmode;
+
+ tmode = EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ 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_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Only Vertices";
+ ot->idname= "MESH_OT_extrude_verts_indiv";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_verts_invoke;
+ ot->exec= mesh_extrude_verts_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", "");
+}
+
+static int mesh_extrude_edges_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_extrude_edges_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;
+ float nor[3];
+ int constraint_axis[3] = {0, 0, 1};
+ int tmode;
+
+ tmode = EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ 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_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Only Edges";
+ ot->idname= "MESH_OT_extrude_edges_indiv";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_edges_invoke;
+ ot->exec= mesh_extrude_edges_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", "");
+}
+
+static int mesh_extrude_faces_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_extrude_faces_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;
+ float nor[3];
+ int constraint_axis[3] = {0, 0, 1};
+ int tmode;
+
+ tmode = EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ RNA_enum_set(op->ptr, "proportional", 0);
+ RNA_boolean_set(op->ptr, "mirror", 0);
+
+ if (tmode == 's') {
+ WM_operator_name_call(C, "TFM_OT_shrink_fatten", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ } else {
+ 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_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Individual Faces";
+ ot->idname= "MESH_OT_extrude_faces_indiv";
+
+ /* api callbacks */
+ ot->invoke= mesh_extrude_faces_invoke;
+ ot->exec= mesh_extrude_faces_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", "");
+}
+
+int extrude_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->bm->totvertsel==0) {
+ return OPERATOR_CANCELLED;
+ } else if(em->bm->totvertsel==1) {
+ WM_operator_name_call(C, "MESH_OT_extrude_verts_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ } else if(em->bm->totedgesel==0) {
+ WM_operator_name_call(C, "MESH_OT_extrude_verts_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ } else if(em->bm->totfacesel==0) {
+ // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
+ uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
+
+ uiPupMenuEnd(C, pup);
+ } else if(em->bm->totfacesel==1) {
+ // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
+ uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
+ uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
+
+ uiPupMenuEnd(C, pup);
+ } else {
+ // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
+ uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
+ uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
+ uiItemO(layout, "Only Verts", 0, "MESH_OT_extrude_verts_indiv");
+
+ uiPupMenuEnd(C, pup);
+ }
+ } else if (em->selectmode & SCE_SELECT_EDGE) {
+ if (em->bm->totedge==0)
+ return OPERATOR_CANCELLED;
+ else if (em->bm->totedgesel==1)
+ WM_operator_name_call(C, "MESH_OT_extrude_edges_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ else if (em->bm->totfacesel==0) {
+ WM_operator_name_call(C, "MESH_OT_extrude_edges_indiv", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ } else if (em->bm->totfacesel==1) {
+ // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
+ uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
+
+ uiPupMenuEnd(C, pup);
+ } else {
+ // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
+ uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
+ uiItemO(layout, "Only Edges", 0, "MESH_OT_extrude_edges_indiv");
+
+ uiPupMenuEnd(C, pup);
+ }
+
+ } else if (em->selectmode & SCE_SELECT_FACE) {
+ if (em->bm->totfacesel==0)
+ return OPERATOR_CANCELLED;
+ else if (em->bm->totfacesel==1)
+ WM_operator_name_call(C, "MESH_OT_extrude_region", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ else {
+ // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ pup= uiPupMenuBegin(C, "Extrude", 0);
+ layout= uiPupMenuLayout(pup);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
+
+ uiItemO(layout, "Region", 0, "MESH_OT_extrude_region");
+ uiItemO(layout, "Individual Faces", 0, "MESH_OT_extrude_faces_indiv");
+
+ uiPupMenuEnd(C, pup);
+ }
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void MESH_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude";
+ ot->description= "Extrude selected vertices, edges or faces.";
+ ot->idname= "MESH_OT_extrude";
+
+ /* api callbacks */
+ ot->invoke= extrude_menu_invoke;
+ ot->poll= ED_operator_editmesh;
+}
+
+/* ******************** (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_GEOM|ND_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";
+ ot->description= "(de)select all vertices, edges or faces.";
+
+ /* 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 *v1;
+ BMIter iter;
+ float min[3], max[3];
+ int done= 0;
+
+ em_setup_viewcontext(C, &vc);
+
+ INIT_MINMAX(min, max);
+
+ BM_ITER_SELECT(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH, NULL)
+ 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_GEOM|ND_DATA, vc.obedit->data);
+ DAG_id_flush_update(vc.obedit->data, 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->description= "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor.";
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int delete_mesh(bContext *C, 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_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->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(C, obedit, op, RNA_enum_get(op->ptr, "type"), scene);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->description= "Delete selected vertices, edges or faces.";
+ 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, BM_FACE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_face_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Edge/Face";
+ ot->description= "Add an edge or face to selected.";
+ 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_tool_settings(C)->selectmode = em->selectmode;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_selection_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Selection Mode";
+ ot->description= "Set the selection mode type.";
+ 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_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL)
+ BM_ClearHFlag(eed, BM_SEAM);
+ }
+ }
+ else {
+ BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL)
+ BM_SetHFlag(eed, BM_SEAM);
+ }
+ }
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_seam(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Seam";
+ ot->idname= "MESH_OT_mark_seam";
+ ot->description= "(un)mark selected edges as a 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_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL)
+ BM_SetHFlag(eed, BM_SHARP);
+ }
+ } else {
+ BM_ITER_SELECT(eed, &iter, bm, BM_EDGES_OF_MESH, NULL)
+ BM_ClearHFlag(eed, BM_SHARP);
+ }
+ }
+
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Sharp";
+ ot->idname= "MESH_OT_mark_sharp";
+ ot->description= "(un)mark selected edges as 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", "");
+}
+
+
+static int editbmesh_vert_connect(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;
+ BMOperator bmop;
+ int len = 0;
+
+ BMO_InitOpf(bm, &bmop, "connectverts verts=%hv", BM_SELECT);
+ BMO_Exec_Op(bm, &bmop);
+ len = BMO_GetSlot(&bmop, "edgeout")->len;
+ BMO_Finish_Op(bm, &bmop);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void MESH_OT_vert_connect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertex Connect";
+ ot->idname= "MESH_OT_vert_connect";
+
+ /* api callbacks */
+ ot->exec= editbmesh_vert_connect;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int editbmesh_edge_split(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;
+ BMOperator bmop;
+ int len = 0;
+
+ BMO_InitOpf(bm, &bmop, "edgesplit edges=%he numcuts=%d", BM_SELECT, RNA_int_get(op->ptr,"number_cuts"));
+ BMO_Exec_Op(bm, &bmop);
+ len = BMO_GetSlot(&bmop, "outsplit")->len;
+ BMO_Finish_Op(bm, &bmop);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void MESH_OT_edge_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Edge Split";
+ ot->idname= "MESH_OT_edge_split";
+
+ /* api callbacks */
+ ot->exec= editbmesh_edge_split;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+}
+
+/****************** add duplicate operator ***************/
+
+static int mesh_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "dupe geom=%hvef", BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "newout", BM_SELECT, BM_ALL);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ WM_cursor_wait(1);
+ mesh_duplicate_exec(C, op);
+ WM_cursor_wait(0);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate";
+ ot->description= "Duplicate selected vertices, edges or faces.";
+ ot->idname= "MESH_OT_duplicate";
+
+ /* api callbacks */
+ ot->invoke= mesh_duplicate_invoke;
+ ot->exec= mesh_duplicate_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+static int flip_normals(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+
+ if (!EDBM_CallOpf(em, op, "reversefaces facaes=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_flip_normals(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Flip Normals";
+ ot->description= "Flip the direction of selected face's vertex and face normals";
+ ot->idname= "MESH_OT_flip_normals";
+
+ /* api callbacks */
+ ot->exec= flip_normals;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+//#define DIRECTION_CW 1
+//#define DIRECTION_CCW 2
+
+static const EnumPropertyItem direction_items[]= {
+ {DIRECTION_CW, "CW", 0, "Clockwise", ""},
+ {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+/* only accepts 1 selected edge, or 2 selected faces */
+static int edge_rotate_selected(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMOperator bmop;
+ BMEdge *eed;
+ BMIter iter;
+ int ccw = RNA_int_get(op->ptr, "direction") == 1; // direction == 2 when clockwise and ==1 for counter CW.
+ short edgeCount = 0;
+
+ if (!(em->bm->totfacesel == 2 || em->bm->totedgesel == 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ return OPERATOR_CANCELLED;
+ }
+
+ /*first see if we have two adjacent faces*/
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_Edge_FaceCount(eed) == 2) {
+ if ((BM_TestHFlag(eed->loop->f, BM_SELECT) && BM_TestHFlag(((BMLoop*)eed->loop->radial.next->data)->f, BM_SELECT))
+ && !(BM_TestHFlag(eed->loop->f, BM_HIDDEN) || BM_TestHFlag(((BMLoop*)eed->loop->radial.next->data)->f, BM_HIDDEN)))
+ {
+ break;
+ }
+ }
+ }
+
+ /*ok, we don't have two adjacent faces, but we do have two selected ones.
+ that's an error condition.*/
+ if (!eed && em->bm->totfacesel == 2) {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!eed) {
+ BM_ITER_SELECT(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL)
+ if (BM_TestHFlag(eed, BM_SELECT))
+ break;
+ }
+ }
+
+ /*this should never happen*/
+ if (!eed)
+ return OPERATOR_CANCELLED;
+
+ EDBM_InitOpf(em, &bmop, op, "edgerotate edges=%e ccw=%d", eed, ccw);
+ BMO_Exec_Op(em->bm, &bmop);
+
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_EDGE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Selected Edge";
+ ot->description= "Rotate selected edge or adjoining faces.";
+ ot->idname= "MESH_OT_edge_rotate";
+
+ /* api callbacks */
+ ot->exec= edge_rotate_selected;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around.");
+}
+
+/* pinning code */
+
+/* swap is 0 or 1, if 1 it pins not selected */
+void EDBM_pin_mesh(BMEditMesh *em, int swap)
+{
+ BMIter iter;
+ BMHeader *h;
+ int itermode;
+
+ if(em==NULL) return;
+
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ itermode = BM_VERTS_OF_MESH;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ itermode = BM_EDGES_OF_MESH;
+ else
+ itermode = BM_FACES_OF_MESH;
+
+ BM_ITER(h, &iter, em->bm, itermode, NULL) {
+ if (BM_TestHFlag(h, BM_SELECT) ^ swap)
+ BM_Pin(em->bm, h, 1);
+ }
+
+ EDBM_selectmode_flush(em);
+}
+
+static int pin_mesh_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;
+ Mesh *me= ((Mesh *)obedit->data);
+
+ me->drawflag |= ME_DRAW_PINS;
+
+ EDBM_pin_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_pin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Pin Selection";
+ ot->idname= "MESH_OT_pin";
+
+ /* api callbacks */
+ ot->exec= pin_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Pin (un)selected vertices, edges or faces.";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Pin unselected rather than selected.");
+}
+
+/* swap is 0 or 1, if 1 it unhides not selected */
+void EDBM_unpin_mesh(BMEditMesh *em, int swap)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & SCE_SELECT_VERTEX | SCE_SELECT_EDGE)};
+ int itermode;
+
+ if(em==NULL) return;
+
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ itermode = BM_VERTS_OF_MESH;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ itermode = BM_EDGES_OF_MESH;
+ else
+ itermode = BM_FACES_OF_MESH;
+
+ BM_ITER(ele, &iter, em->bm, itermode, NULL) {
+ if (BM_TestHFlag(ele, BM_SELECT) ^ swap)
+ BM_Pin(em->bm, ele, 0);
+ }
+
+ EDBM_selectmode_flush(em);
+}
+
+static int unpin_mesh_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;
+ Mesh *me= ((Mesh *)obedit->data);
+
+ EDBM_unpin_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_unpin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Unpin Selection";
+ ot->idname= "MESH_OT_unpin";
+ ot->description= "Unpin (un)selected vertices, edges or faces.";
+
+ /* api callbacks */
+ ot->exec= unpin_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Unpin unselected rather than selected.");
+}
+
+
+/* swap is 0 or 1, if 1 it hides not selected */
+void EDBM_hide_mesh(BMEditMesh *em, int swap)
+{
+ BMIter iter;
+ BMHeader *h;
+ int itermode;
+
+ if(em==NULL) return;
+
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ itermode = BM_VERTS_OF_MESH;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ itermode = BM_EDGES_OF_MESH;
+ else
+ itermode = BM_FACES_OF_MESH;
+
+ BM_ITER(h, &iter, em->bm, itermode, NULL) {
+ if (BM_TestHFlag(h, BM_SELECT) ^ swap)
+ BM_Hide(em->bm, h, 1);
+ }
+
+ /*original hide flushing comment (OUTDATED):
+ hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
+ /* - vertex hidden, always means edge is hidden too
+ - edge hidden, always means face is hidden too
+ - face hidden, only set face hide
+ - then only flush back down what's absolute hidden
+ */
+
+}
+
+static int hide_mesh_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;
+
+ EDBM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selection";
+ ot->idname= "MESH_OT_hide";
+
+ /* api callbacks */
+ ot->exec= hide_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Hide (un)selected vertices, edges or faces.";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
+}
+
+
+void EDBM_reveal_mesh(BMEditMesh *em)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int sels[3] = {1, !(em->selectmode & SCE_SELECT_VERTEX), !(em->selectmode & SCE_SELECT_VERTEX | SCE_SELECT_EDGE)};
+
+ for (i=0; i<3; i++) {
+ BM_ITER(ele, &iter, em->bm, types[i], NULL) {
+ if (BM_TestHFlag(ele, BM_HIDDEN)) {
+ BM_Hide(em->bm, ele, 0);
+
+ if (sels[i])
+ BM_Select(em->bm, ele, 1);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+}
+
+static int reveal_mesh_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;
+
+ EDBM_reveal_mesh(em);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Hidden";
+ ot->idname= "MESH_OT_reveal";
+ ot->description= "Reveal all hidden vertices, edges and faces.";
+
+ /* api callbacks */
+ ot->exec= reveal_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int normals_make_consistent_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;
+
+ if (!EDBM_CallOpf(em, op, "righthandfaces faces=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ if (RNA_boolean_get(op->ptr, "inside"))
+ EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_normals_make_consistent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Normals Consistent";
+ ot->description= "Make face and vertex normals point either outside or inside the mesh";
+ ot->idname= "MESH_OT_normals_make_consistent";
+
+ /* api callbacks */
+ ot->exec= normals_make_consistent_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
+}
+
+
+
+static int do_smooth_vertex(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ ModifierData *md;
+ int mirrx=0, mirry=0, mirrz=0;
+ int i, repeat;
+
+ /* if there is a mirror modifier with clipping, flag the verts that
+ * are within tolerance of the plane(s) of reflection
+ */
+ for(md=obedit->modifiers.first; md; md=md->next) {
+ if(md->type==eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ mirrx = 1;
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ mirry = 1;
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ mirrz = 1;
+ }
+ }
+ }
+
+ repeat = RNA_int_get(op->ptr,"repeat");
+ if (!repeat)
+ repeat = 1;
+
+ for (i=0; i<repeat; i++) {
+ if (!EDBM_CallOpf(em, op, "vertexsmooth verts=%hv mirror_clip_x=%d mirror_clip_y=%d mirror_clip_z=%d",
+ BM_SELECT, mirrx, mirry, mirrz))
+ {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ //BMESH_TODO: need to handle the x-axis editing option here properly.
+ //should probably make a helper function for that? I dunno.
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Vertex";
+ ot->description= "Flatten angles of selected vertices.";
+ ot->idname= "MESH_OT_vertices_smooth";
+
+ /* api callbacks */
+ ot->exec= do_smooth_vertex;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
+}
+
+
+static int bm_test_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ RegionView3D *r3d = CTX_wm_region_view3d(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMBVHTree *tree = BMBVH_NewBVH(em);
+ BMIter iter;
+ BMEdge *e;
+
+ /*hide all back edges*/
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(e, BM_SELECT))
+ continue;
+
+ if (!BMBVH_EdgeVisible(tree, e, r3d, obedit))
+ BM_Select(em->bm, e, 0);
+ }
+
+ BMBVH_FreeBVH(tree);
+
+#if 0 //uv island walker test
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l, *l2;
+ MLoopUV *luv;
+ BMWalker walker;
+ int i=0;
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ }
+ }
+
+ BMW_Init(&walker, em->bm, BMW_UVISLAND, 0);
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ l2 = BMW_Begin(&walker, l);
+ for (; l2; l2=BMW_Step(&walker)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+ }
+ }
+
+ BMW_End(&walker);
+#endif
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_bm_test(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "BMesh Test Operator";
+ ot->idname= "MESH_OT_bm_test";
+
+ /* api callbacks */
+ ot->exec= bm_test_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ //RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
+}
+
+/********************** Smooth/Solid Operators *************************/
+
+void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
+{
+ BMIter iter;
+ BMFace *efa;
+
+ if(em==NULL) return;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(efa, BM_SELECT)) {
+ if (smooth)
+ BM_SetHFlag(efa, BM_SMOOTH);
+ else
+ BM_ClearHFlag(efa, BM_SMOOTH);
+ }
+ }
+}
+
+static int mesh_faces_shade_smooth_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;
+
+ mesh_set_smooth_faces(em, 1);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shade Smooth";
+ ot->description= "Display faces smooth (using vertex normals).";
+ ot->idname= "MESH_OT_faces_shade_smooth";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_smooth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int mesh_faces_shade_flat_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;
+
+ mesh_set_smooth_faces(em, 0);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_flat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shade Flat";
+ ot->description= "Display faces flat.";
+ ot->idname= "MESH_OT_faces_shade_flat";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_flat_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/********************** UV/Color Operators *************************/
+
+
+static const EnumPropertyItem axis_items[]= {
+ {OPUVC_AXIS_X, "X", 0, "X", ""},
+ {OPUVC_AXIS_Y, "Y", 0, "Y", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static int mesh_rotate_uvs(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the direction from RNA */
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshrotateuvs faces=%hf dir=%d", BM_SELECT, dir);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_reverse_uvs(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshreverseuvs faces=%hf", BM_SELECT);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_rotate_colors(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the direction from RNA */
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshrotatecolors faces=%hf dir=%d", BM_SELECT, dir);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+
+ /* dependencies graph and notification stuff */
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+
+static int mesh_reverse_colors(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshreversecolors faces=%hf", BM_SELECT);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+#if 0
+ Scene *scene= CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ EditFace *efa;
+ short change = 0;
+ MCol tmpcol, *mcol;
+ int axis= RNA_enum_get(op->ptr, "axis");
+
+ if (!EM_vertColorCheck(em)) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ for(efa=em->faces.first; efa; efa=efa->next) {
+ if (efa->f & SELECT) {
+ mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ if (axis == AXIS_Y) {
+ 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;
+ }
+ }
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+
+ if(!change)
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+#endif
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_uvs_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate UVs";
+ ot->idname= "MESH_OT_uvs_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around.");
+}
+
+//void MESH_OT_uvs_mirror(wmOperatorType *ot)
+void MESH_OT_uvs_reverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reverse UVs";
+ ot->idname= "MESH_OT_uvs_reverse";
+
+ /* api callbacks */
+ ot->exec= mesh_reverse_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around.");
+}
+
+void MESH_OT_colors_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Colors";
+ ot->idname= "MESH_OT_colors_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around.");
+}
+
+void MESH_OT_colors_reverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reverse Colors";
+ ot->idname= "MESH_OT_colors_reverse";
+
+ /* api callbacks */
+ ot->exec= mesh_reverse_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
+}
+
+
+static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
+{
+ BMVert *mergevert;
+ BMEditSelection *ese;
+
+ /* do sanity check in mergemenu in edit.c ?*/
+ if(first == 0){
+ ese = em->bm->selected.last;
+ mergevert= (BMVert*)ese->data;
+ }
+ else{
+ ese = em->bm->selected.first;
+ mergevert = (BMVert*)ese->data;
+ }
+
+ if (!BM_TestHFlag(mergevert, BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ if (uvmerge) {
+ if (!EDBM_CallOpf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_SELECT, mergevert))
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, mergevert->co))
+ return OPERATOR_CANCELLED;
+
+ return OPERATOR_FINISHED;
+}
+
+static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
+ int target, int uvmerge, wmOperator *wmop)
+{
+ BMIter iter;
+ BMVert *v;
+ float *vco, co[3], cent[3] = {0.0f, 0.0f, 0.0f}, fac;
+ int i;
+
+ if (target) {
+ vco = give_cursor(scene, v3d);
+ VECCOPY(co, vco);
+ Mat4MulVecfl(ob->imat, co);
+ } else {
+ i = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(v, BM_SELECT))
+ continue;
+ VECADD(cent, cent, v->co);
+ i++;
+ }
+
+ if (!i)
+ return OPERATOR_CANCELLED;
+
+ fac = 1.0f / (float)i;
+ VECMUL(cent, fac);
+ VECCOPY(co, cent);
+ }
+
+ if (!co)
+ return OPERATOR_CANCELLED;
+
+ if (uvmerge) {
+ if (!EDBM_CallOpf(em, wmop, "vert_average_facedata verts=%hv", BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, co))
+ return OPERATOR_CANCELLED;
+
+ return OPERATOR_FINISHED;
+}
+
+static int merge_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int status= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
+
+ switch(RNA_enum_get(op->ptr, "type")) {
+ case 3:
+ status = merge_target(em, scene, v3d, obedit, 0, uvs, op);
+ break;
+ case 4:
+ status = merge_target(em, scene, v3d, obedit, 1, uvs, op);
+ break;
+ case 1:
+ status = merge_firstlast(em, 0, uvs, op);
+ break;
+ case 6:
+ status = merge_firstlast(em, 1, uvs, op);
+ break;
+ case 5:
+ status = 1;
+ if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
+ status = 0;
+ break;
+ }
+
+ if(!status)
+ return OPERATOR_CANCELLED;
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static EnumPropertyItem merge_type_items[]= {
+ {6, "FIRST", 0, "At First", ""},
+ {1, "LAST", 0, "At Last", ""},
+ {3, "CENTER", 0, "At Center", ""},
+ {4, "CURSOR", 0, "At Cursor", ""},
+ {5, "COLLAPSE", 0, "Collapse", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+ Object *obedit;
+ EnumPropertyItem *item= NULL;
+ int totitem= 0;
+
+ if(!C) /* needed for docs */
+ return merge_type_items;
+
+ obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->bm->selected.first && em->bm->selected.last &&
+ ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT) {
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ }
+ else if(em->bm->selected.first && ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT)
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ else if(em->bm->selected.last && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT)
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
+ RNA_enum_item_end(&item, &totitem);
+
+ *free= 1;
+
+ return item;
+ }
+
+ return NULL;
+}
+
+void MESH_OT_merge(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Merge";
+ ot->idname= "MESH_OT_merge";
+
+ /* api callbacks */
+ ot->exec= merge_exec;
+ ot->invoke= WM_menu_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
+ RNA_def_enum_funcs(prop, merge_type_itemf);
+ RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Move UVs according to merge.");
+}
+
+
+static int removedoublesflag_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;
+ BMOperator bmop;
+ char msg[100];
+ int count;
+
+ EDBM_InitOpf(em, &bmop, op, "finddoubles verts=%hv dist=%f",
+ BM_SELECT, RNA_float_get(op->ptr, "mergedist"));
+ BMO_Exec_Op(em->bm, &bmop);
+
+ count = BMO_CountSlotMap(em->bm, &bmop, "targetmapout");
+
+ if (!EDBM_CallOpf(em, op, "weldverts targetmap=%s", &bmop, "targetmapout")) {
+ BMO_Finish_Op(em->bm, &bmop);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ /*we need a better way of reporting this, since this doesn't work
+ with the last operator panel correctly.
+ if(count)
+ {
+ sprintf(msg, "Removed %d vertices", count);
+ BKE_report(op->reports, RPT_INFO, msg);
+ }
+ */
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_remove_doubles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Doubles";
+ ot->idname= "MESH_OT_remove_doubles";
+
+ /* api callbacks */
+ ot->exec= removedoublesflag_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f,
+ "Merge Distance",
+ "Minimum distance between elements to merge.", 0.00001, 10.0);
+}
+
+/************************ Vertex Path Operator *************************/
+
+typedef struct PathNode {
+ int u;
+ int visited;
+ ListBase edges;
+} PathNode;
+
+typedef struct PathEdge {
+ struct PathEdge *next, *prev;
+ int v;
+ float w;
+} PathEdge;
+
+
+
+int select_vertex_path_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+ BMEditSelection *sv, *ev;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ sv = em->bm->selected.last;
+ if( sv != NULL )
+ ev = sv->prev;
+ else return OPERATOR_CANCELLED;
+ if( ev == NULL )
+ return OPERATOR_CANCELLED;
+
+ if( sv->type != BM_VERT || ev->type != BM_VERT )
+ return OPERATOR_CANCELLED;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "vertexshortestpath startv=%e endv=%e type=%d", sv->data, ev->data, type);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* DO NOT clear the existing selection */
+ /* EDBM_clear_flag_all(em, BM_SELECT); */
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ EDBM_selectmode_flush(em);
+
+ /* dependencies graph and notification stuff */
+/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob);
+*/
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+#if 0
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ 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;
+
+ ese = ((EditSelection*)em->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=em->verts.first; eve; eve=eve->next){
+ eve->f1 = 0;
+ }
+
+ s->f1 = 1;
+
+ unbalanced = 1;
+ totnodes = 1;
+ while(unbalanced){
+ unbalanced = 0;
+ for(eed=em->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=em->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=em->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=em->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(em);
+ }
+ }
+ else {
+ BKE_mesh_end_editmesh(obedit->data, em);
+ BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+ BKE_mesh_end_editmesh(obedit->data, em);
+#endif
+}
+
+void MESH_OT_select_vertex_path(wmOperatorType *ot)
+{
+ static const EnumPropertyItem type_items[] = {
+ {VPATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
+ {VPATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Select Vertex Path";
+ ot->idname= "MESH_OT_select_vertex_path";
+
+ /* api callbacks */
+ ot->exec= select_vertex_path_exec;
+ ot->invoke= WM_menu_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", type_items, VPATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance.");
+}
+/********************** Rip Operator *************************/
+
+#if 0
+/* helper for below */
+static void mesh_rip_setface(EditMesh *em, 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(em, sefa->v1, sefa->v2, sefa->e1);
+ sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2);
+ if(sefa->v4) {
+ sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3);
+ sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4);
+ }
+ else
+ sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3);
+
+}
+#endif
+
+/* helper to find edge for edge_rip */
+static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval)
+{
+ float vec1[3], vec2[3], mvalf[2];
+
+ view3d_project_float(ar, co1, vec1, mat);
+ view3d_project_float(ar, co2, vec2, mat);
+ mvalf[0]= (float)mval[0];
+ mvalf[1]= (float)mval[1];
+
+ return PdistVL2Dfl(mvalf, vec1, vec2);
+}
+
+/* based on mouse cursor position, it defines how is being ripped */
+static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMOperator bmop;
+ BMBVHTree *bvhtree;
+ BMOIter siter;
+ BMIter iter, eiter, liter;
+ BMLoop *l;
+ BMEdge *e, *e2, *closest = NULL;
+ BMVert *v;
+ int side = 0, i;
+ float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1], 0.0f};
+ float dist = FLT_MAX, d;
+
+ view3d_get_object_project_mat(rv3d, obedit, projectMat);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ BMINDEX_SET(e, 1);
+ else BMINDEX_SET(e, 0);
+ }
+
+ /*handle case of one vert selected. we identify
+ the closest edge around that vert to the mouse cursor,
+ then rip the two adjacent edges in the vert fan.*/
+ if (em->bm->totvertsel == 1 && em->bm->totedgesel == 0 && em->bm->totfacesel == 0) {
+ /*find selected vert*/
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT))
+ break;
+ }
+
+ /*this should be impossible, but sanity checks are a good thing*/
+ if (!v)
+ return OPERATOR_CANCELLED;
+
+ /*find closest edge to mouse cursor*/
+ e2 = NULL;
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_VERT, v) {
+ d = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, event->mval);
+ if (d < dist) {
+ dist = d;
+ e2 = e;
+ }
+ }
+
+ if (!e2)
+ return OPERATOR_CANCELLED;
+
+ /*rip two adjacent edges*/
+ if (BM_Edge_FaceCount(e2) == 1) {
+ l = e2->loop;
+ e = BM_OtherFaceLoop(e2, l->f, v);
+
+ BMINDEX_SET(e, 1);
+ BM_SetHFlag(e, BM_SELECT);
+ } else if (BM_Edge_FaceCount(e2) == 2) {
+ l = e2->loop;
+ e = BM_OtherFaceLoop(e2, l->f, v);
+ BMINDEX_SET(e, 1);
+ BM_SetHFlag(e, BM_SELECT);
+
+ l = e2->loop->radial.next->data;
+ e = BM_OtherFaceLoop(e2, l->f, v);
+ BMINDEX_SET(e, 1);
+ BM_SetHFlag(e, BM_SELECT);
+ }
+ } else {
+ /*expand edge selection*/
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ e2 = NULL;
+ i = 0;
+ BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v) {
+ if (BMINDEX_GET(e)) {
+ e2 = e;
+ i++;
+ }
+ }
+
+ if (i == 1 && e2->loop) {
+ l = BM_OtherFaceLoop(e2, e2->loop->f, v);
+ l = (BMLoop*)l->radial.next->data;
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+
+ if (l)
+ BM_Select(em->bm, l->e, 1);
+ }
+ }
+ }
+
+ if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he", BM_SELECT)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /*build bvh tree for edge visibility tests*/
+ bvhtree = BMBVH_NewBVH(em);
+
+ for (i=0; i<2; i++) {
+ BMO_ITER(e, &siter, em->bm, &bmop, i ? "edgeout2":"edgeout1", BM_EDGE) {
+ float cent[3] = {0, 0, 0}, mid[4], vec[3];
+
+ if (!BMBVH_EdgeVisible(bvhtree, e, rv3d, obedit))
+ continue;
+
+ /*method for calculating distance:
+
+ for each edge: calculate face center, then made a vector
+ from edge midpoint to face center. offset edge midpoint
+ by a small amount along this vector.*/
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, e->loop->f) {
+ VecAddf(cent, cent, l->v->co);
+ }
+ VecMulf(cent, 1.0f/(float)e->loop->f->len);
+
+ VecAddf(mid, e->v1->co, e->v2->co);
+ VecMulf(mid, 0.5f);
+ VecSubf(vec, cent, mid);
+ Normalize(vec);
+ VecMulf(vec, 0.01f);
+ VecAddf(mid, mid, vec);
+
+ /*yay we have our comparison point, now project it*/
+ view3d_project_float(ar, mid, mid, projectMat);
+
+ vec[0] = fmval[0] - mid[0];
+ vec[1] = fmval[1] - mid[1];
+ d = vec[0]*vec[0] + vec[1]*vec[1];
+
+ if (d < dist) {
+ side = i;
+ closest = e;
+ dist = d;
+ }
+ }
+ }
+
+ EDBM_clear_flag_all(em, BM_SELECT);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, side?"edgeout2":"edgeout1", BM_SELECT, BM_EDGE);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ BMINDEX_SET(e, 1);
+ else BMINDEX_SET(e, 0);
+ }
+
+ /*constrict edge selection again*/
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ e2 = NULL;
+ i = 0;
+ BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v) {
+ if (BMINDEX_GET(e)) {
+ e2 = e;
+ i++;
+ }
+ }
+
+ if (i == 1)
+ BM_Select(em->bm, e2, 0);
+ }
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ BMBVH_FreeBVH(bvhtree);
+ return OPERATOR_CANCELLED;
+ }
+
+ BMBVH_FreeBVH(bvhtree);
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+#if 0 //BMESH_TODO
+ ARegion *ar= CTX_wm_region(C);
+ RegionView3D *rv3d= ar->regiondata;
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditVert *eve, *nextve;
+ EditEdge *eed, *seed= NULL;
+ EditFace *efa, *sefa= NULL;
+ float projectMat[4][4], vec[3], dist, mindist;
+ short doit= 1, *mval= event->mval;
+
+ /* select flush... vertices are important */
+ EM_selectmode_set(em);
+
+ view3d_get_object_project_mat(rv3d, obedit, projectMat);
+
+ /* 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(ar, 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) {
+ BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+ if(sefa==NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+
+ /* 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(em, 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(ar, 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(ar, 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(ar, 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(ar, projectMat,
+ sefa->e4->v1->co,
+ sefa->e4->v2->co, mval);
+ if(dist<mindist) {
+ seed= sefa->e4;
+ mindist= dist;
+ }
+ }
+ }
+
+ if(seed==NULL) { // never happens?
+ BKE_report(op->reports, RPT_ERROR, "No proper edge found to start");
+ BKE_mesh_end_editmesh(obedit->data, em);
+ return OPERATOR_CANCELLED;
+ }
+
+ faceloop_select(em, 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(em, 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) {
+ EM_select_edge(eed, 0);
+ EM_remove_selection(em, eed, EDITEDGE);
+ EM_select_edge(newed, 1);
+ }
+ 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(em, 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(em, 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(em, eed);
+ free_editedge(em, 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(em, eve);
+ }
+ }
+
+ DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+
+// RNA_enum_set(op->ptr, "proportional", 0);
+// RNA_boolean_set(op->ptr, "mirror", 0);
+// WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
+#endif
+}
+
+void MESH_OT_rip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rip";
+ ot->idname= "MESH_OT_rip";
+
+ /* api callbacks */
+ ot->invoke= mesh_rip_invoke;
+ ot->poll= EM_view3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ Properties_Proportional(ot);
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+} \ No newline at end of file
diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c
new file mode 100644
index 00000000000..bf7889ef3c0
--- /dev/null
+++ b/source/blender/editors/mesh/bmeshutils.c
@@ -0,0 +1,784 @@
+ /* $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 "BLI_array.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;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ 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);
+ em->emcopyusers = 0;
+ em->emcopy = NULL;
+ return 0;
+ } else {
+ em->emcopyusers--;
+ if (em->emcopyusers < 0) {
+ printf("warning: em->emcopyusers was less then zero.\n");
+ }
+
+ if (em->emcopyusers <= 0) {
+ 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;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ 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;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ BMO_Exec_Op(bm, &bmop);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, NULL, 0);
+}
+
+void EDBM_MakeEditBMesh(ToolSettings *ts, 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 = ts->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);
+}
+
+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->bm->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_select_flush(BMEditMesh *em, int selectmode)
+{
+ em->bm->selectmode = selectmode;
+ BM_SelectMode_Flush(em->bm);
+ em->bm->selectmode = em->selectmode;
+}
+
+/*BMESH_TODO*/
+void EDBM_deselect_flush(BMEditMesh *em)
+{
+}
+
+
+void EDBM_selectmode_flush(BMEditMesh *em)
+{
+ em->bm->selectmode = em->selectmode;
+ BM_SelectMode_Flush(em->bm);
+}
+
+/*EDBM_select_[more/less] are api functions, I think the uv editor
+ uses them? though the select more/less ops themselves do not.*/
+void EDBM_select_more(BMEditMesh *em)
+{
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ BMO_InitOpf(em->bm, &bmop,
+ "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+ BMO_Finish_Op(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
+}
+
+void EDBM_select_less(BMEditMesh *em)
+{
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ BMO_InitOpf(em->bm, &bmop,
+ "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+ BMO_Finish_Op(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
+}
+
+int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
+{
+ BMEditSelection *ese_last = em->bm->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;
+
+ if (flag & BM_SELECT)
+ BM_clear_selection_history(em->bm);
+
+ 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;
+}
+
+typedef struct undomesh {
+ Mesh me;
+ int selectmode;
+} undomesh;
+
+/*undo simply makes copies of a bmesh*/
+static void *editbtMesh_to_undoMesh(void *emv)
+{
+ BMEditMesh *em = emv;
+ undomesh *me = MEM_callocN(sizeof(undomesh), "undo Mesh");
+
+ /*we recalc the tesselation here, to avoid seeding calls to
+ BMEdit_RecalcTesselation throughout the code.*/
+ BMEdit_RecalcTesselation(em);
+
+ BMO_CallOpf(em->bm, "bmesh_to_mesh meshptr=%p notesselation=%i", me, 1);
+ me->selectmode = em->selectmode;
+
+ return me;
+}
+
+static void undoMesh_to_editbtMesh(void *umv, void *emv)
+{
+ BMEditMesh *em = emv, *em2;
+ undomesh *me = umv;
+ BMesh *bm;
+ int allocsize[4] = {512, 512, 2048, 512};
+
+ BMEdit_Free(em);
+
+ bm = BM_Make_Mesh(allocsize);
+ BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p", me);
+
+ em2 = BMEdit_Create(bm);
+ *em = *em2;
+
+ em->selectmode = me->selectmode;
+
+ MEM_freeN(em2);
+}
+
+
+static void free_undo(void *umv)
+{
+ free_mesh(umv, 0);
+ MEM_freeN(umv);
+}
+
+/* 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);
+}
+
+/*write comment here*/
+UvVertMap *EDBM_make_uv_vert_map(BMEditMesh *em, int selected, int do_face_idx_array, float *limit)
+{
+ BMVert *ev;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ /* vars from original func */
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ unsigned int a;
+ int totverts, i, totuv;
+
+ if (do_face_idx_array)
+ EDBM_init_index_arrays(em, 0, 0, 1);
+
+ /* we need the vert */
+ totverts=0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(ev, totverts);
+ totverts++;
+ }
+
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT)))
+ totuv += efa->len;
+ }
+
+ if(totuv==0) {
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+ vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap) {
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+
+ vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
+ buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
+
+ if (!vmap->vert || !vmap->buf) {
+ free_uv_vert_map(vmap);
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT))) {
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ buf->tfindex= i;
+ buf->f= a;
+ buf->separate = 0;
+
+ buf->next= vmap->vert[BMINDEX_GET(l->v)];
+ vmap->vert[BMINDEX_GET(l->v)]= buf;
+
+ buf++;
+ i++;
+ }
+ }
+
+ a++;
+ }
+
+ /* sort individual uvs for each vert */
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while(vlist) {
+ v= vlist;
+ vlist= vlist->next;
+ v->next= newvlist;
+ newvlist= v;
+
+ efa = EDBM_get_face_for_index(em, v->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv = luv->uv;
+
+ lastv= NULL;
+ iterv= vlist;
+
+ while(iterv) {
+ next= iterv->next;
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv2 = luv->uv;
+
+ Vec2Subf(uvdiff, uv2, uv);
+
+ if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
+ if(lastv) lastv->next= next;
+ else vlist= next;
+ iterv->next= newvlist;
+ newvlist= iterv;
+ }
+ else
+ lastv=iterv;
+
+ iterv= next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a]= newvlist;
+ a++;
+ }
+
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+
+ return vmap;
+}
+
+
+UvMapVert *EDBM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
+{
+ return vmap->vert[v];
+}
+
+void EDBM_free_uv_vert_map(UvVertMap *vmap)
+{
+ if (vmap) {
+ if (vmap->vert) MEM_freeN(vmap->vert);
+ if (vmap->buf) MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
+}
+
+
+/* last_sel, use em->act_face otherwise get the last selected face in the editselections
+ * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
+MTexPoly *EDBM_get_active_mtexpoly(BMEditMesh *em, BMFace **act_efa, int sloppy)
+{
+ BMFace *efa = NULL;
+
+ if(!EDBM_texFaceCheck(em))
+ return NULL;
+
+ efa = EDBM_get_actFace(em, sloppy);
+
+ if (efa) {
+ if (act_efa) *act_efa = efa;
+ return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ }
+
+ if (act_efa) *act_efa= NULL;
+ return NULL;
+}
+
+/* can we edit UV's for this mesh?*/
+int EDBM_texFaceCheck(BMEditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY);
+}
+
+int EDBM_vertColorCheck(BMEditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
+}
+
diff --git a/source/blender/editors/mesh/editbmesh_bvh.c b/source/blender/editors/mesh/editbmesh_bvh.c
new file mode 100644
index 00000000000..d93100e3740
--- /dev/null
+++ b/source/blender/editors/mesh/editbmesh_bvh.c
@@ -0,0 +1,288 @@
+ /* $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 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 "BLI_array.h"
+#include "BLI_kdopbvh.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"
+
+#include "editbmesh_bvh.h"
+
+typedef struct BMBVHTree {
+ BMEditMesh *em;
+ BMesh *bm;
+ BVHTree *tree;
+ float epsilon;
+} BMBVHTree;
+
+BMBVHTree *BMBVH_NewBVH(BMEditMesh *em)
+{
+ BMBVHTree *tree = MEM_callocN(sizeof(*tree), "BMBVHTree");
+ float cos[3][3];
+ int i;
+
+ BMEdit_RecalcTesselation(em);
+
+ tree->em = em;
+ tree->bm = em->bm;
+ tree->epsilon = FLT_EPSILON*2.0f;
+
+ tree->tree = BLI_bvhtree_new(em->tottri, tree->epsilon, 8, 8);
+
+ for (i=0; i<em->tottri; i++) {
+ VECCOPY(cos[0], em->looptris[i][0]->v->co);
+ VECCOPY(cos[1], em->looptris[i][1]->v->co);
+ VECCOPY(cos[2], em->looptris[i][2]->v->co);
+
+ BLI_bvhtree_insert(tree->tree, i, (float*)cos, 3);
+ }
+
+ BLI_bvhtree_balance(tree->tree);
+
+ return tree;
+}
+
+void BMBVH_FreeBVH(BMBVHTree *tree)
+{
+ BLI_bvhtree_free(tree->tree);
+ MEM_freeN(tree);
+}
+
+/*taken from bvhutils.c*/
+static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, float *v0,
+ float *v1, float *v2, float *uv, float e)
+{
+ float dist;
+#if 0
+ float vv1[3], vv2[3], vv3[3], cent[3];
+
+ /*expand triangle by an epsilon. this is probably a really stupid
+ way of doing it, but I'm too tired to do better work.*/
+ VECCOPY(vv1, v0);
+ VECCOPY(vv2, v1);
+ VECCOPY(vv3, v2);
+
+ VecAddf(cent, vv1, vv2);
+ VecAddf(cent, cent, vv3);
+ VecMulf(cent, 1.0f/3.0f);
+
+ VecSubf(vv1, vv1, cent);
+ VecSubf(vv2, vv2, cent);
+ VecSubf(vv3, vv3, cent);
+
+ VecMulf(vv1, 1.0f + e);
+ VecMulf(vv2, 1.0f + e);
+ VecMulf(vv3, 1.0f + e);
+
+ VecAddf(vv1, vv1, cent);
+ VecAddf(vv2, vv2, cent);
+ VecAddf(vv3, vv3, cent);
+
+ if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, vv1, vv2, vv3, &dist, uv))
+ return dist;
+#else
+ if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, v0, v1, v2, &dist, uv))
+ return dist;
+#endif
+
+ return FLT_MAX;
+}
+
+static void raycallback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ BMBVHTree *tree = userdata;
+ BMLoop **ls = tree->em->looptris[index];
+ float dist, uv[2], co1[3], co2[3], co3[3];
+
+ dist = ray_tri_intersection(ray, hit->dist, ls[0]->v->co, ls[1]->v->co,
+ ls[2]->v->co, uv, tree->epsilon);
+ if (dist < hit->dist) {
+ hit->dist = dist;
+ hit->index = index;
+
+ VECCOPY(hit->no, ls[0]->v->no);
+
+ VECCOPY(co1, ls[0]->v->co);
+ VECCOPY(co2, ls[1]->v->co);
+ VECCOPY(co3, ls[2]->v->co);
+
+ VecMulf(co1, uv[0]);
+ VecMulf(co2, uv[1]);
+ VecMulf(co3, 1.0f-uv[0]-uv[1]);
+
+ VecAddf(hit->co, co1, co2);
+ VecAddf(hit->co, hit->co, co3);
+ }
+}
+
+BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout)
+{
+ BVHTreeRayHit hit;
+
+ hit.dist = FLT_MAX;
+ hit.index = -1;
+
+ BLI_bvhtree_ray_cast(tree->tree, co, dir, FLT_MAX, &hit, raycallback, tree);
+ if (hit.dist != FLT_MAX && hit.index != -1) {
+ if (hitout) {
+ VECCOPY(hitout, hit.co);
+ }
+
+ return tree->em->looptris[hit.index][0]->f;
+ }
+
+ return NULL;
+}
+
+#if 0 //BMESH_TODO: not implemented yet
+int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
+{
+
+}
+#endif
+
+static BMFace *edge_ray_cast(BMBVHTree *tree, float *co, float *dir, float *hitout, BMEdge *e)
+{
+ BMFace *f = BMBVH_RayCast(tree, co, dir, hitout);
+
+ if (f && BM_Edge_In_Face(f, e))
+ return NULL;
+
+ return f;
+}
+
+int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d, Object *obedit)
+{
+ BMFace *f;
+ float co1[3], co2[3], co3[3], dir1[4], dir2[4], dir3[4];
+ float origin[3], invmat[4][4];
+ float epsilon = 0.01f;
+
+ VECCOPY(origin, r3d->viewinv[3]);
+ Mat4Invert(invmat, obedit->obmat);
+ Mat4MulVecfl(invmat, origin);
+
+ VECCOPY(co1, e->v1->co);
+ VecAddf(co2, e->v1->co, e->v2->co);
+ VecMulf(co2, 0.5f);
+ VECCOPY(co3, e->v2->co);
+
+ /*ok, idea is to generate rays going from the camera origin to the
+ three points on the edge (v1, mid, v2)*/
+ VecSubf(dir1, origin, co1);
+ VecSubf(dir2, origin, co2);
+ VecSubf(dir3, origin, co3);
+
+ Normalize(dir1);
+ Normalize(dir2);
+ Normalize(dir3);
+
+ VecMulf(dir1, epsilon);
+ VecMulf(dir2, epsilon);
+ VecMulf(dir3, epsilon);
+
+ /*offset coordinates slightly along view vectors, to avoid
+ hitting the faces that own the edge.*/
+ VecAddf(co1, co1, dir1);
+ VecAddf(co2, co2, dir2);
+ VecAddf(co3, co3, dir3);
+
+ Normalize(dir1);
+ Normalize(dir2);
+ Normalize(dir3);
+
+ /*do three samplings: left, middle, right*/
+ f = edge_ray_cast(tree, co1, dir1, NULL, e);
+ if (f && !edge_ray_cast(tree, co2, dir2, NULL, e))
+ return 1;
+ else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e))
+ return 1;
+ else if (!f)
+ return 1;
+
+ return 0;
+}
diff --git a/source/blender/editors/mesh/editbmesh_bvh.h b/source/blender/editors/mesh/editbmesh_bvh.h
new file mode 100644
index 00000000000..fbbf26b24e0
--- /dev/null
+++ b/source/blender/editors/mesh/editbmesh_bvh.h
@@ -0,0 +1,15 @@
+struct BMEditMesh;
+struct BMFace;
+struct BMEdge;
+struct BMVert;
+struct RegionView3D;
+
+struct BMBVHTree;
+typedef struct BMBVHTree BMBVHTree;
+
+BMBVHTree *BMBVH_NewBVH(struct BMEditMesh *em);
+void BMBVH_FreeBVH(BMBVHTree *tree);
+
+struct BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout);
+int BMBVH_EdgeVisible(BMBVHTree *tree, struct BMEdge *e,
+ struct RegionView3D *r3d, struct Object *obedit);
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 8f9dea00a1b..bb69ab16a45 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -104,10 +104,10 @@ void object_facesel_flush_dm(Object *ob)
if(me==NULL || dm==NULL || !CustomData_has_layer( &dm->faceData, CD_ORIGINDEX))
return;
- faces = dm->getFaceArray(dm);
- totface = dm->getNumFaces(dm);
+ faces = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
- index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
mf= faces;
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index b0c51131041..e2bbb63f5c5 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"
@@ -72,6 +73,7 @@
#include "BKE_softbody.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "LBM_fluidsim.h"
@@ -92,6 +94,8 @@
/* own include */
#include "mesh_intern.h"
+#include "bmesh.h"
+
/*
editmesh.c:
- add/alloc/free data
@@ -113,22 +117,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++;
@@ -158,8 +161,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--;
}
@@ -257,11 +259,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);
@@ -294,9 +297,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)
@@ -308,8 +310,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--;
}
@@ -385,7 +386,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;
@@ -468,55 +471,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)
+void set_editMesh(EditMesh *dst, EditMesh *src)
{
- 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)
-{
- callocvert= calloc_em;
- callocedge= calloc_em;
- callocface= calloc_em;
+ free_editMesh(dst);
+ *dst = *src;
}
/* do not free editmesh itself here */
@@ -528,7 +486,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);
@@ -744,7 +707,7 @@ static void edge_drawflags(Mesh *me, EditMesh *em)
}
/* turns Mesh into editmesh */
-void make_editMesh(Scene *scene, Object *ob)
+EditMesh *make_editMesh(Scene *scene, Object *ob)
{
Mesh *me= ob->data;
MFace *mface;
@@ -759,13 +722,7 @@ void make_editMesh(Scene *scene, Object *ob)
float *co;
int tot, a, 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;
@@ -773,18 +730,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();
}
/* make editverts */
@@ -892,8 +840,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
@@ -926,14 +872,13 @@ void make_editMesh(Scene *scene, Object *ob)
}
/* 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;
@@ -1301,6 +1246,7 @@ static EnumPropertyItem prop_separate_types[] = {
/* return 1: success */
static int mesh_separate_selected(Scene *scene, Base *editbase)
{
+#if 0
EditMesh *em, *emnew;
EditVert *eve, *v1;
EditEdge *eed, *e1;
@@ -1348,8 +1294,8 @@ static int mesh_separate_selected(Scene *scene, Base *editbase)
basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */
assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
me->id.us--;
- make_editMesh(scene, basenew->object);
- emnew= menew->edit_mesh;
+ emnew = make_editMesh(scene, basenew->object);
+ //emnew= menew->edit_mesh;
CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
@@ -1393,7 +1339,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);
MEM_freeN(menew->edit_mesh);
menew->edit_mesh= NULL;
@@ -1407,11 +1353,13 @@ static int mesh_separate_selected(Scene *scene, Base *editbase)
BKE_mesh_end_editmesh(me, em);
return 1;
+#endif
}
/* return 1: success */
static int mesh_separate_material(Scene *scene, Base *editbase)
{
+#if 0
Mesh *me= editbase->object->data;
EditMesh *em= BKE_mesh_get_editmesh(me);
unsigned char curr_mat;
@@ -1430,11 +1378,14 @@ static int mesh_separate_material(Scene *scene, Base *editbase)
BKE_mesh_end_editmesh(me, em);
return 1;
+#endif
}
/* return 1: success */
static int mesh_separate_loose(Scene *scene, Base *editbase)
{
+ return 0;
+#if 0
Mesh *me;
EditMesh *em;
int doit= 1;
@@ -1463,6 +1414,7 @@ static int mesh_separate_loose(Scene *scene, Base *editbase)
BKE_mesh_end_editmesh(me, em);
return 1;
+#endif
}
@@ -1547,6 +1499,7 @@ typedef struct UndoMesh {
EditVertC *verts;
EditEdgeC *edges;
EditFaceC *faces;
+ EditFaceC *act_face;
EditSelectionC *selected;
int totvert, totedge, totface, totsel;
short selectmode;
@@ -1555,247 +1508,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 *************/
@@ -1898,6 +1610,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 d703ba1fb35..e6baa6d9db8 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"
@@ -72,6 +73,8 @@
#include "ED_view3d.h"
#include "ED_object.h"
+#include "bmesh.h"
+
#include "mesh_intern.h"
/* bpymenu removed XXX */
@@ -117,129 +120,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_GEOM|ND_DATA, vc.obedit->data);
- DAG_id_flush_update(vc.obedit->data, OB_RECALC_DATA);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Duplicate or Extrude at 3D Cursor";
- ot->description= "Duplicate and extrude selected vertices, edges or faces towards 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;
-}
-
-
/* ********************** */
/* selected faces get hidden edges */
@@ -668,12 +548,53 @@ void addfaces_from_edgenet(EditMesh *em)
// XXX DAG_id_flush_update(obedit->data, 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;
+
+ 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;
+
+ if (len) return;
+ }
+
+ em = BKE_mesh_get_editmesh(me);
/* how many selected ? */
if(em->selectmode & SCE_SELECT_EDGE) {
@@ -693,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_id_flush_update(obedit->data, 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;
}
@@ -741,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 */
@@ -782,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);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->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->description= "Add an edge or face to selected.";
- 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
@@ -1106,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) {
@@ -1605,47 +1502,3 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
}
-
-/****************** add duplicate operator ***************/
-
-static int mesh_duplicate_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(ob->data);
-
- adduplicateflag(em, SELECT);
-
- BKE_mesh_end_editmesh(ob->data, em);
-
- DAG_id_flush_update(ob->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- WM_cursor_wait(1);
- mesh_duplicate_exec(C, op);
- WM_cursor_wait(0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_duplicate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Duplicate";
- ot->description= "Duplicate selected vertices, edges or faces.";
- ot->idname= "MESH_OT_duplicate";
-
- /* api callbacks */
- ot->invoke= mesh_duplicate_invoke;
- ot->exec= mesh_duplicate_exec;
-
- ot->poll= ED_operator_editmesh;
-
- /* to give to transform */
- RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
-}
-
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 28103828dd4..03f29edc3fd 100644
--- a/source/blender/editors/mesh/editmesh_loop.c
+++ b/source/blender/editors/mesh/editmesh_loop.c
@@ -62,6 +62,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "PIL_time.h"
@@ -78,6 +79,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() {}
@@ -203,6 +205,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;
@@ -393,6 +396,7 @@ void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
return;
+#endif
}
@@ -476,7 +480,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*/
@@ -622,29 +626,187 @@ 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)
{
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 *be;
+ BMOperator bmop;
CutCurve curve[MAX_CUTS];
struct GHash *gh;
float isect=0.0;
float *scr, co[4];
- int len=0;
+ int len=0, isected, flag, i;
short numcuts=1, mode= RNA_int_get(op->ptr, "type");
/* edit-object needed for matrix, and ar->regiondata for projections to work */
if (ELEM3(NULL, obedit, ar, ar->regiondata))
return OPERATOR_CANCELLED;
- 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;;
}
@@ -658,57 +820,52 @@ 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;
- }
- eed= eed->next;
+ 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_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);
+ } else BMO_ClearFlag(bm, be, 1);
+ } else BMO_ClearFlag(bm, be, 1);
}
- 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);
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
@@ -716,7 +873,6 @@ static int knife_cut_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-
void MESH_OT_knife_cut(wmOperatorType *ot)
{
PropertyRNA *prop;
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
index 74870778d02..a57d56ec1eb 100644
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -78,14 +78,13 @@ editmesh_mods.c, UI level access, no geometry changes
#include "WM_api.h"
#include "WM_types.h"
-#include "UI_resources.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"
@@ -102,6 +101,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;
@@ -115,28 +115,25 @@ void EM_select_mirrored(Object *obedit, EditMesh *em)
}
}
}
+#endif
}
-void EM_automerge(Scene *scene, Object *obedit, int update)
+void EM_automerge(int update)
{
- Mesh *me= obedit ? obedit->data : NULL; /* can be NULL */
- int len;
-
- if ((scene->toolsettings->automerge) &&
- (obedit && obedit->type==OB_MESH && (obedit->mode & OB_MODE_EDIT)) &&
- (me->mr==NULL)
- ) {
- Mesh *me= (Mesh*)obedit->data;
- EditMesh *em= me->edit_mesh;
-
- len = removedoublesflag(em, 1, 1, scene->toolsettings->doublimit);
- if (len) {
- em->totvert -= len; /* saves doing a countall */
- if (update) {
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- }
- }
- }
+// 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_id_flush_update(obedit->data, OB_RECALC_DATA);
+// }
+// }
+// }
}
/* ****************************** SELECTION ROUTINES **************** */
@@ -333,38 +330,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;
@@ -373,917 +338,8 @@ static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int
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;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- 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;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- 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;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- 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;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- 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 */
-
-/* VERT GROUP */
-
-#define SIMVERT_NORMAL 0
-#define SIMVERT_FACE 1
-#define SIMVERT_VGROUP 2
-#define SIMVERT_TOT 3
-
-/* EDGE GROUP */
-
-#define SIMEDGE_LENGTH 101
-#define SIMEDGE_DIR 102
-#define SIMEDGE_FACE 103
-#define SIMEDGE_FACE_ANGLE 104
-#define SIMEDGE_CREASE 105
-#define SIMEDGE_SEAM 106
-#define SIMEDGE_SHARP 107
-#define SIMEDGE_TOT 108
-
-/* FACE GROUP */
-
-#define SIMFACE_MATERIAL 201
-#define SIMFACE_IMAGE 202
-#define SIMFACE_AREA 203
-#define SIMFACE_PERIMETER 204
-#define SIMFACE_NORMAL 205
-#define SIMFACE_COPLANAR 206
-#define SIMFACE_TOT 207
-
-static EnumPropertyItem prop_similar_types[] = {
- {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMVERT_FACE, "FACE", 0, "Amount of Vertices in Face", ""},
- {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
- {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
- {SIMEDGE_FACE, "FACE", 0, "Amount of Vertices in Face", ""},
- {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
- {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
- {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
- {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
- {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
- {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
- {SIMFACE_AREA, "AREA", 0, "Area", ""},
- {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
- {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMFACE_COPLANAR, "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, EditMesh *em, int mode)
-{
- EditFace *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==SIMFACE_AREA) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.fp= EM_face_area(efa);
- }
- } else if (mode==SIMFACE_PERIMETER) {
- 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==SIMFACE_MATERIAL) { /* 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==SIMFACE_IMAGE) { /* 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==SIMFACE_AREA || mode==SIMFACE_PERIMETER) { /* 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==SIMFACE_NORMAL) {
- float angle;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (!(efa->f & SELECT) && !efa->h) {
- angle= RAD2DEG(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==SIMFACE_COPLANAR) { /* 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= RAD2DEG(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;
-}
-
-static int similar_face_select_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
-
- int selcount = similar_face_select__internal(scene, em, RNA_int_get(op->ptr, "type"));
-
- if (selcount) {
- /* here was an edge-mode only select flush case, has to be generalized */
- EM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-/* ***************************************************** */
-
-static int similar_edge_select__internal(ToolSettings *ts, EditMesh *em, int mode)
-{
- EditEdge *eed, *base_eed=NULL;
- unsigned int selcount=0; /* count how many new edges we select*/
-
- /*count how many visible selected edges there are,
- so we can return when there are none left */
- unsigned int deselcount=0;
-
- short ok=0;
- float thresh= ts->select_thresh;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!eed->h) {
- if (eed->f & SELECT) {
- eed->f1=1;
- ok=1;
- } else {
- eed->f1=0;
- deselcount++;
- }
- /* set all eed->tmp.l to 0 we use it later.
- for counting face users*/
- eed->tmp.l=0;
- eed->f2=0; /* only for mode SIMEDGE_FACE_ANGLE, edge animations */
- }
- }
-
- if (!ok || !deselcount) /* no data selected OR no more data to select*/
- return 0;
-
- if (mode==SIMEDGE_LENGTH) { /*store length*/
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!eed->h) /* dont calc data for hidden edges*/
- eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
- }
- } else if (mode==SIMEDGE_FACE) { /*store face users*/
- EditFace *efa;
- /* cound how many faces each edge uses use tmp->l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->e1->tmp.l++;
- efa->e2->tmp.l++;
- efa->e3->tmp.l++;
- if (efa->e4) efa->e4->tmp.l++;
- }
- } else if (mode==SIMEDGE_FACE_ANGLE) { /*store edge angles */
- EditFace *efa;
- int j;
- /* cound how many faces each edge uses use tmp.l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- /* here we use the edges temp data to assign a face
- if a face has alredy been assigned (eed->f2==1)
- we calculate the angle between the current face and
- the edges previously found face.
- store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
- but tagging eed->f2==2, so we know not to look at it again.
- This only works for edges that connect to 2 faces. but its good enough
- */
-
- /* se we can loop through face edges*/
- j=0;
- eed= efa->e1;
- while (j<4) {
- if (j==1) eed= efa->e2;
- else if (j==2) eed= efa->e3;
- else if (j==3) {
- eed= efa->e4;
- if (!eed)
- break;
- } /* done looping */
-
- if (!eed->h) { /* dont calc data for hidden edges*/
- if (eed->f2==2)
- break;
- else if (eed->f2==0) /* first access, assign the face */
- eed->tmp.f= efa;
- else if (eed->f2==1) /* second, we assign the angle*/
- eed->tmp.fp= RAD2DEG(VecAngle2(eed->tmp.f->n, efa->n))/180;
- eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
- }
- j++;
- }
- }
- }
-
- for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
- if (base_eed->f1) {
- if (mode==SIMEDGE_LENGTH) { /* same length */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_DIR) { /* same direction */
- float base_dir[3], dir[3], angle;
- VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!(eed->f & SELECT) && !eed->h) {
- VecSubf(dir, eed->v1->co, eed->v2->co);
- angle= RAD2DEG(VecAngle2(base_dir, dir));
-
- if (angle>90) /* use the smallest angle between the edges */
- angle= fabs(angle-180.0f);
-
- if (angle/90.0<=thresh) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- } else if (mode==SIMEDGE_FACE) { /* face users */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- base_eed->tmp.l==eed->tmp.l
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_FACE_ANGLE && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- eed->f2==2 &&
- (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_CREASE) { /* edge crease */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (fabs(base_eed->crease-eed->crease) <= thresh)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_SEAM) { /* edge seam */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (eed->seam == base_eed->seam)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_SHARP) { /* edge sharp */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (eed->sharp == base_eed->sharp)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- }
- }
- return selcount;
-}
-/* wrap the above function but do selection flushing edge to face */
-static int similar_edge_select_exec(bContext *C, wmOperator *op)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
-
- int selcount = similar_edge_select__internal(ts, em, RNA_int_get(op->ptr, "type"));
-
- if (selcount) {
- /* here was an edge-mode only select flush case, has to be generalized */
- EM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-/* ********************************* */
-
-static int similar_vert_select_exec(bContext *C, wmOperator *op)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- EditVert *eve, *base_eve=NULL;
- unsigned int selcount=0; /* count how many new edges we select*/
-
- /*count how many visible selected edges there are,
- so we can return when there are none left */
- unsigned int deselcount=0;
- int mode= RNA_enum_get(op->ptr, "type");
-
- short ok=0;
- float thresh= ts->select_thresh;
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (!eve->h) {
- if (eve->f & SELECT) {
- eve->f1=1;
- ok=1;
- } else {
- eve->f1=0;
- deselcount++;
- }
- /* set all eve->tmp.l to 0 we use them later.*/
- eve->tmp.l=0;
- }
-
- }
-
- if (!ok || !deselcount) { /* no data selected OR no more data to select*/
- BKE_mesh_end_editmesh(me, em);
- return 0;
- }
-
- if(mode == SIMVERT_FACE) {
- /* store face users */
- EditFace *efa;
-
- /* count how many faces each edge uses use tmp->l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->v1->tmp.l++;
- efa->v2->tmp.l++;
- efa->v3->tmp.l++;
- if (efa->v4) efa->v4->tmp.l++;
- }
- }
-
-
- for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
- if (base_eve->f1) {
-
- if(mode == SIMVERT_NORMAL) {
- float angle;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (!(eve->f & SELECT) && !eve->h) {
- angle= RAD2DEG(VecAngle2(base_eve->no, eve->no));
- if (angle/180.0<=thresh) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) {/*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- }
- }
- }
- }
- else if(mode == SIMVERT_FACE) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (
- !(eve->f & SELECT) &&
- !eve->h &&
- base_eve->tmp.l==eve->tmp.l
- ) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) {/*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- }
- }
- }
- else if(mode == SIMVERT_VGROUP) {
- MDeformVert *dvert, *base_dvert;
- short i, j; /* weight index */
-
- base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
- CD_MDEFORMVERT);
-
- if (!base_dvert || base_dvert->totweight == 0) {
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- dvert= CustomData_em_get(&em->vdata, eve->data,
- CD_MDEFORMVERT);
-
- if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
- /* do the extra check for selection in the following if, so were not
- checking verts that may be alredy selected */
- for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) {
- for (j=0; dvert->totweight >j; j++) {
- if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) { /*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- break;
- }
- }
- }
- }
- }
- }
- }
- } /* end basevert loop */
-
- if(selcount) {
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-static int select_similar_exec(bContext *C, wmOperator *op)
-{
- int type= RNA_enum_get(op->ptr, "type");
-
- if(type < 100)
- return similar_vert_select_exec(C, op);
- else if(type < 200)
- return similar_edge_select_exec(C, op);
- else
- return similar_face_select_exec(C, op);
-}
-
-static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *ptr, int *free)
-{
- Object *obedit= CTX_data_edit_object(C);
- EnumPropertyItem *item= NULL;
- int a, totitem= 0;
-
- if(obedit && obedit->type == OB_MESH) {
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(a=SIMVERT_NORMAL; a<=SIMVERT_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(a=SIMEDGE_LENGTH; a<=SIMEDGE_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- else if(em->selectmode & SCE_SELECT_FACE) {
- for(a=SIMFACE_MATERIAL; a<=SIMFACE_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
-
- return item;
-}
-
-void MESH_OT_select_similar(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Select Similar";
- ot->description= "Select similar vertices, edges or faces by property types.";
- ot->idname= "MESH_OT_select_similar";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= select_similar_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
- RNA_def_enum_funcs(prop, select_similar_type_itemf);
-}
-
/* ******************************************* */
-
int mesh_layers_menu_charlen(CustomData *data, int type)
{
int i, len = 0;
@@ -1710,9 +766,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)
@@ -1782,6 +838,7 @@ void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
}
}
}
+#endif
/* helper for edgeloop_select, checks for eed->f2 tag in faces */
@@ -1990,583 +1047,7 @@ static int loop_multiselect(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void MESH_OT_loop_multi_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Multi Select Loops";
- ot->description= "Select a loop of connected edges by connection type.";
- 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;
- 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;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
-
- 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_GEOM|ND_SELECT, vc.obedit->data);
- }
-}
-
-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->description= "Select a loop of connected edges.";
- 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;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
-
- 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_id_flush_update(vc.obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
- }
-}
-
-
-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->description= "Select shortest path between two selections.";
- 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_GEOM|ND_SELECT, vc.obedit->data);
-
-}
-
-/* *********** select linked ************* */
-
-/* for use with selectconnected_delimit_mesh only! */
-#define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
-#define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
-
-#define face_tag(efa)\
-if(efa->v4) efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
-else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
-
-/* all - 1) use all faces for extending the selection 2) only use the mouse face
-* sel - 1) select 0) deselect
-* */
-
-/* legacy warning, this function combines too much :) */
-static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
-{
- EditMesh *em= vc->em;
- EditFace *efa;
- EditEdge *eed;
- EditVert *eve;
- short done=1, change=0;
-
- if(em->faces.first==0) return OPERATOR_CANCELLED;
-
- /* flag all edges+faces as off*/
- for(eed= em->edges.first; eed; eed= eed->next)
- eed->tmp.l=0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.l = 0;
- }
-
- if (all) {
- // XXX verts?
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT)
- eed->tmp.l= 1;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
-
- if (efa->f & SELECT) {
- face_tag(efa);
- } else {
- efa->tmp.l = 0;
- }
- }
- }
- else {
- if( unified_findnearest(vc, &eve, &eed, &efa) ) {
-
- if(efa) {
- efa->tmp.l = 1;
- face_tag(efa);
- }
- else if(eed)
- eed->tmp.l= 1;
- else {
- for(eed= em->edges.first; eed; eed= eed->next)
- if(eed->v1==eve || eed->v2==eve)
- break;
- eed->tmp.l= 1;
- }
- }
- else
- return OPERATOR_FINISHED;
- }
-
- while(done==1) {
- done= 0;
- /* simple algo - select all faces that have a selected edge
- * this intern selects the edge, repeat until nothing is left to do */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if ((efa->tmp.l == 0) && (!efa->h)) {
- if (is_face_tag(efa)) {
- face_tag(efa);
- done= 1;
- }
- }
- }
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (efa->tmp.l) {
- if (sel) {
- if (!(efa->f & SELECT)) {
- EM_select_face(efa, 1);
- change = 1;
- }
- } else {
- if (efa->f & SELECT) {
- EM_select_face(efa, 0);
- change = 1;
- }
- }
- }
- }
-
- if (!change)
- return OPERATOR_CANCELLED;
-
- if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */
- for(efa= em->faces.first; efa; efa= efa->next)
- if (efa->f & SELECT)
- EM_select_face(efa, 1);
-
- // if (EM_texFaceCheck())
-
- return OPERATOR_FINISHED;
-}
-
-#undef is_edge_delimit_ok
-#undef is_face_tag
-#undef face_tag
-
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- Object *obedit= CTX_data_edit_object(C);
- ViewContext vc;
- EditVert *eve, *v1, *v2;
- EditEdge *eed;
- EditFace *efa;
- short done=1, toggle=0;
- int sel= !RNA_boolean_get(op->ptr, "deselect");
- int limit= RNA_boolean_get(op->ptr, "limit");
-
- /* unified_finednearest needs ogl */
- view3d_operator_needs_opengl(C);
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
-
- if(vc.em->edges.first==0) return OPERATOR_CANCELLED;
-
- vc.mval[0]= event->mval[0];
- vc.mval[1]= event->mval[1];
-
- /* return warning! */
- if(limit) {
- int retval= select_linked_limited_invoke(&vc, 0, sel);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- return retval;
- }
-
- if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_CANCELLED;
- }
-
- /* clear test flags */
- for(v1= vc.em->verts.first; v1; v1= v1->next) v1->f1= 0;
-
- /* start vertex/face/edge */
- if(eve) eve->f1= 1;
- else if(eed) eed->v1->f1= eed->v2->f1= 1;
- else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
-
- /* set flag f1 if affected */
- while(done==1) {
- done= 0;
- toggle++;
-
- if(toggle & 1) eed= vc.em->edges.first;
- else eed= vc.em->edges.last;
-
- while(eed) {
- v1= eed->v1;
- v2= eed->v2;
-
- if(eed->h==0) {
- if(v1->f1 && v2->f1==0) {
- v2->f1= 1;
- done= 1;
- }
- else if(v1->f1==0 && v2->f1) {
- v1->f1= 1;
- done= 1;
- }
- }
-
- if(toggle & 1) eed= eed->next;
- else eed= eed->prev;
- }
- }
-
- /* now use vertex f1 flag to select/deselect */
- for(eed= vc.em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f1 && eed->v2->f1)
- EM_select_edge(eed, sel);
- }
- for(efa= vc.em->faces.first; efa; efa= efa->next) {
- if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
- EM_select_face(efa, sel);
- }
- /* no flush needed, connected geometry is done */
-
-// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_linked_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Linked";
- ot->description= "(un)select all vertices linked to the active mesh.";
- ot->idname= "MESH_OT_select_linked_pick";
-
- /* api callbacks */
- ot->invoke= select_linked_pick_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
-}
-
-
/* ************************* */
-
-void selectconnected_mesh_all(EditMesh *em)
-{
- EditVert *v1,*v2;
- EditEdge *eed;
- short done=1, toggle=0;
-
- if(em->edges.first==0) return;
-
- while(done==1) {
- done= 0;
-
- toggle++;
- if(toggle & 1) eed= em->edges.first;
- else eed= em->edges.last;
-
- while(eed) {
- v1= eed->v1;
- v2= eed->v2;
- if(eed->h==0) {
- if(v1->f & SELECT) {
- if( (v2->f & SELECT)==0 ) {
- v2->f |= SELECT;
- done= 1;
- }
- }
- else if(v2->f & SELECT) {
- if( (v1->f & SELECT)==0 ) {
- v1->f |= SELECT;
- done= 1;
- }
- }
- }
- if(toggle & 1) eed= eed->next;
- else eed= eed->prev;
- }
- }
-
- /* now use vertex select flag to select rest */
- EM_select_flush(em);
-
- // if (EM_texFaceCheck())
-}
-
-static int select_linked_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if( RNA_boolean_get(op->ptr, "limit") ) {
- ViewContext vc;
- em_setup_viewcontext(C, &vc);
- select_linked_limited_invoke(&vc, 1, 1);
- }
- else
- selectconnected_mesh_all(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Linked All";
- ot->description= "Select all vertices linked to the active mesh.";
- ot->idname= "MESH_OT_select_linked";
-
- /* api callbacks */
- ot->exec= select_linked_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
-}
-
-
/* ************************* */
/* swap is 0 or 1, if 1 it hides not selected */
@@ -2672,37 +1153,6 @@ void EM_hide_mesh(EditMesh *em, int swap)
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
}
-static int hide_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_hide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Hide Selection";
- ot->description= "Hide (un)selected vertices, edges or faces.";
- ot->idname= "MESH_OT_hide";
-
- /* api callbacks */
- ot->exec= hide_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
-}
-
void EM_reveal_mesh(EditMesh *em)
{
EditVert *eve;
@@ -2739,34 +1189,6 @@ void EM_reveal_mesh(EditMesh *em)
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
}
-static int reveal_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_reveal_mesh(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_reveal(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Reveal Hidden";
- ot->description= "Reveal all hidden vertices, edges and faces.";
- ot->idname= "MESH_OT_reveal";
-
- /* api callbacks */
- ot->exec= reveal_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
int select_by_number_vertices_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
@@ -3212,70 +1634,10 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-void EM_select_swap(EditMesh *em) /* exported for UV */
+static int bmesh_test_exec(bContext *C, wmOperator *op)
{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- if(eve->f & SELECT) eve->f &= ~SELECT;
- else eve->f|= SELECT;
- }
- }
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- EM_select_edge(eed, !(eed->f & SELECT));
- }
- }
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- EM_select_face(efa, !(efa->f & SELECT));
- }
- }
- }
-
- EM_selectmode_flush(em);
-
-// if (EM_texFaceCheck())
-
-}
-
-static int select_inverse_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_select_swap(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_inverse(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Inverse";
- ot->description= "Select inverse of (un)selected vertices, edges or faces.";
- ot->idname= "MESH_OT_select_inverse";
-
- /* api callbacks */
- ot->exec= select_inverse_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ return OPERATOR_CANCELLED;
}
-
/* ******************** (de)select all operator **************** */
void EM_toggle_select_all(EditMesh *em) /* exported for UV */
@@ -3291,36 +1653,18 @@ void EM_select_all(EditMesh *em)
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_GEOM|ND_SELECT, obedit->data);
- 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->description= "(de)select all vertices, edges or faces.";
- 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;
}
/* ******************** **************** */
-
void EM_select_more(EditMesh *em)
{
EditVert *eve;
@@ -3360,36 +1704,6 @@ void EM_select_more(EditMesh *em)
}
}
-static int select_more(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)) ;
-
- EM_select_more(em);
-
-// if (EM_texFaceCheck(em))
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select More";
- ot->description= "Select more vertices, edges or faces connected to initial selection.";
- ot->idname= "MESH_OT_select_more";
-
- /* api callbacks */
- ot->exec= select_more;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
void EM_select_less(EditMesh *em)
{
EditEdge *eed;
@@ -3451,35 +1765,6 @@ void EM_select_less(EditMesh *em)
}
}
-static int select_less(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_select_less(em);
-
-// if (EM_texFaceCheck(em))
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Less";
- ot->description= "Select less vertices, edges or faces connected to initial selection.";
- ot->idname= "MESH_OT_select_less";
-
- /* api callbacks */
- ot->exec= select_less;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
static void selectrandom_mesh(EditMesh *em, float perc) /* randomly selects a user-set % of vertices/edges/faces */
{
EditVert *eve;
@@ -3580,186 +1865,7 @@ void EM_deselect_by_material(EditMesh *em, int index)
EM_selectmode_flush(em);
}
-static void mesh_selection_type(ToolSettings *ts, EditMesh *em, int val)
-{
- if(val>0) {
- if(val==1) {
- em->selectmode= SCE_SELECT_VERTEX;
- EM_selectmode_set(em);
- }
- else if(val==2) {
- //if(ctrl) EM_convertsel(em, em->selectmode, SCE_SELECT_EDGE);
- em->selectmode= SCE_SELECT_EDGE;
- EM_selectmode_set(em);
- }
-
- else{
- //if((ctrl)) EM_convertsel(em, em->selectmode, SCE_SELECT_FACE);
- em->selectmode= SCE_SELECT_FACE;
- EM_selectmode_set(em);
- }
-
- /* note, em stores selectmode to be able to pass it on everywhere without scene,
- this is only until all select modes and toolsettings are settled more */
- ts->selectmode= em->selectmode;
-// if (EM_texFaceCheck())
- }
-}
-
-static EnumPropertyItem prop_mesh_edit_types[] = {
- {1, "VERT", ICON_VERTEXSEL, "Vertices", ""},
- {2, "EDGE", ICON_EDGESEL, "Edges", ""},
- {3, "FACE", ICON_FACESEL, "Faces", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int mesh_selection_type_exec(bContext *C, wmOperator *op)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- mesh_selection_type(ts, em, RNA_enum_get(op->ptr,"type"));
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_selection_type(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Selection Mode";
- ot->description= "Set the selection mode type.";
- 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)
-{
- 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_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_seam(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Seam";
- ot->description= "(un)mark selected edges as a 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)
-{
- 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_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_sharp(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Sharp";
- ot->description= "(un)mark selected edges as 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 */
void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning */
{
@@ -3971,45 +2077,7 @@ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning *
waitcursor(0);
}
-
-static int righthandfaces_exec(bContext *C, wmOperator *op)
-{
- 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 */
-
- // XXX need other args
- righthandfaces(em, RNA_boolean_get(op->ptr, "inside"));
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); //TODO is this needed ?
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_normals_make_consistent(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Make Normals Consistent";
- ot->description= "Flip all selected vertex and face normals in a consistent direction.";
- ot->idname= "MESH_OT_normals_make_consistent";
-
- /* api callbacks */
- ot->exec= righthandfaces_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
-}
-
/* ********** ALIGN WITH VIEW **************** */
-
-
static void editmesh_calc_selvert_center(EditMesh *em, float cent_r[3])
{
EditVert *eve;
@@ -4182,176 +2250,6 @@ void editmesh_align_view_to_selected(Object *obedit, EditMesh *em, wmOperator *o
}
/* **************** VERTEX DEFORMS *************** */
-
-static int smooth_vertex(bContext *C, wmOperator *op)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditVert *eve, *eve_mir = NULL;
- EditEdge *eed;
- float *adror, *adr, fac;
- float fvec[3];
- int teller=0;
- ModifierData *md;
-
- /* 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;
- }
-
- adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- eve->tmp.p = (void*)adr;
- eve->f1= 0;
- eve->f2= 0;
- adr+= 3;
- }
- eve= eve->next;
- }
-
- /* if there is a mirror modifier with clipping, flag the verts that
- * are within tolerance of the plane(s) of reflection
- */
- for(md=obedit->modifiers.first; 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) {
- if(eve->f & SELECT) {
-
- 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;
- }
- }
- }
- }
- }
- }
-
- eed= em->edges.first;
- while(eed) {
- if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
- fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
- fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
- fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
-
- if((eed->v1->f & SELECT) && eed->v1->f1<255) {
- eed->v1->f1++;
- VecAddf(eed->v1->tmp.p, eed->v1->tmp.p, fvec);
- }
- if((eed->v2->f & SELECT) && eed->v2->f1<255) {
- eed->v2->f1++;
- VecAddf(eed->v2->tmp.p, eed->v2->tmp.p, fvec);
- }
- }
- eed= eed->next;
- }
-
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- if(eve->f1) {
-
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- eve_mir= editmesh_get_x_mirror_vert(obedit, em, eve->co);
- }
-
- adr = eve->tmp.p;
- fac= 0.5/(float)eve->f1;
-
- eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
- eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
- eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
-
-
- /* clip if needed by mirror modifier */
- if (eve->f2) {
- if (eve->f2 & 1) {
- eve->co[0]= 0.0f;
- }
- if (eve->f2 & 2) {
- eve->co[1]= 0.0f;
- }
- if (eve->f2 & 4) {
- eve->co[2]= 0.0f;
- }
- }
-
- if (eve_mir) {
- eve_mir->co[0]=-eve->co[0];
- eve_mir->co[1]= eve->co[1];
- eve_mir->co[2]= eve->co[2];
- }
-
- }
- eve->tmp.p= NULL;
- }
- eve= eve->next;
- }
- MEM_freeN(adror);
-
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int smooth_vertex_exec(bContext *C, wmOperator *op)
-{
- int repeat = RNA_int_get(op->ptr, "repeat");
- int i;
-
- if (!repeat) repeat = 1;
-
- for (i=0; i<repeat; i++) {
- smooth_vertex(C, op);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertices_smooth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Smooth Vertex";
- ot->description= "Flatten angles of selected vertices.";
- ot->idname= "MESH_OT_vertices_smooth";
-
- /* api callbacks */
- ot->exec= smooth_vertex_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Smooth Iterations", "", 1, INT_MAX);
-}
-
void vertexnoise(Object *obedit, EditMesh *em)
{
Material *ma;
@@ -4508,45 +2406,3 @@ void flipface(EditMesh *em, EditFace *efa)
if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
}
-
-
-static int flip_normals(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditFace *efa;
-
- efa= em->faces.first;
- while(efa) {
- if( efa->f & SELECT ){
- flipface(em, efa);
- }
- efa= efa->next;
- }
-
- /* update vertex normals too */
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_flip_normals(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Flip Normals";
- ot->description= "Toggle the direction of selected face's vertex and face normals.";
- ot->idname= "MESH_OT_flip_normals";
-
- /* api callbacks */
- ot->exec= flip_normals;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index d447040e8ea..9c26c812de9 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;}
@@ -140,7 +143,7 @@ static int vergface(const void *v1, const void *v2)
/* *********************************** */
-static void convert_to_triface(EditMesh *em, int direction)
+void convert_to_triface(EditMesh *em, int direction)
{
EditFace *efa, *efan, *next;
float fac;
@@ -479,44 +482,6 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
return a; /* amount */
}
-static int removedoublesflag_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- /*char msg[100];*/
-
- /*XXX this messes up last operator panel
- int cnt = removedoublesflag(em,1,0,RNA_float_get(op->ptr, "limit"));
- if(cnt)
- {
- sprintf(msg, "Removed %d vertices", cnt);
- BKE_report(op->reports, RPT_INFO, msg);
- }*/
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_remove_doubles(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Remove Doubles";
- ot->description= "Remove duplicate vertices.";
- ot->idname= "MESH_OT_remove_doubles";
-
- /* api callbacks */
- ot->exec= removedoublesflag_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_float(ot->srna, "limit", 0.0001f, 0.000001f, 50.0f, "Merge Threshold", "Minimum distance between merged verts", 0.00001f, 2.0f);
-}
-
// XXX is this needed?
/* called from buttons */
static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
@@ -529,6 +494,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;
@@ -543,9 +509,7 @@ void xsortvert_flag(bContext *C, int flag)
if(eve->f & flag)
sortblock[i].v1 = eve;
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
-
qsort(sortblock, amount, sizeof(xvertsort), vergxco);
/* make temporal listbase */
@@ -562,7 +526,7 @@ void xsortvert_flag(bContext *C, int flag)
addlisttolist(&vc.em->verts, &tbase);
MEM_freeN(sortblock);
-
+#endif
}
/* called from buttons */
@@ -645,12 +609,15 @@ void extrude_mesh(Scene *scene, 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;
@@ -700,6 +667,8 @@ void extrude_mesh(Scene *scene, 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)
{
@@ -749,7 +718,6 @@ void MESH_OT_extrude(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Extrude";
- ot->description= "Extrude selected vertices, edges or faces.";
ot->idname= "MESH_OT_extrude";
/* api callbacks */
@@ -759,7 +727,13 @@ void MESH_OT_extrude(wmOperatorType *ot)
/* 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", "");
}
+#endif
static int split_mesh(bContext *C, wmOperator *op)
{
@@ -787,7 +761,6 @@ void MESH_OT_split(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Split";
- ot->description= "Split selected geometry into separate disconnected mesh.";
ot->idname= "MESH_OT_split";
/* api callbacks */
@@ -798,7 +771,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)
{
Object *obedit= CTX_data_edit_object(C);
@@ -847,7 +822,6 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Extrude Repeat Mesh";
- ot->description= "Extrude selected vertices, edges or faces repeatedly.";
ot->idname= "MESH_OT_extrude_repeat";
/* api callbacks */
@@ -861,7 +835,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 ******************** */
@@ -981,7 +955,6 @@ void MESH_OT_spin(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Spin";
- ot->description= "Extrude selected vertices in a circle around the cursor in indicated viewport.";
ot->idname= "MESH_OT_spin";
/* api callbacks */
@@ -1089,7 +1062,6 @@ void MESH_OT_screw(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Screw";
- ot->description= "Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport.";
ot->idname= "MESH_OT_screw";
/* api callbacks */
@@ -1154,194 +1126,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)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int type= RNA_enum_get(op->ptr, "type");
-
- if(type==6)
- return WM_operator_name_call(C, "MESH_OT_delete_edgeloop", WM_OP_EXEC_DEFAULT, NULL);
-
- delete_mesh(obedit, em, op, type);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Delete";
- ot->description= "Delete selected vertices, edges or faces.";
- 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 ------------------------------*/
@@ -1394,7 +1178,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;
@@ -1407,7 +1191,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 */
@@ -2255,7 +2039,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++) {
@@ -2394,7 +2178,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)
{
@@ -3126,13 +2910,13 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert
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 = RAD2DEG(VecAngle2(noA1, noA2));
+ 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 = RAD2DEG(VecAngle2(noB1, noB2));
+ else normalBDiff = VecAngle2(noB1, noB2);
//if(!normalBDiff) normalBDiff = 179;
measure += (normalADiff/360) + (normalBDiff/360);
@@ -3147,10 +2931,10 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert
diff = 0.0;
diff = (
- fabs(RAD2DEG(VecAngle2(edgeVec1, edgeVec2)) - 90) +
- fabs(RAD2DEG(VecAngle2(edgeVec2, edgeVec3)) - 90) +
- fabs(RAD2DEG(VecAngle2(edgeVec3, edgeVec4)) - 90) +
- fabs(RAD2DEG(VecAngle2(edgeVec4, edgeVec1)) - 90)) / 360;
+ 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;
@@ -3502,13 +3286,6 @@ void edge_flip(EditMesh *em)
MEM_freeN(efaar);
}
-#define DIRECTION_CW 1
-#define DIRECTION_CCW 2
-
-static const EnumPropertyItem direction_items[]= {
- {DIRECTION_CW, "CW", 0, "Clockwise", ""},
- {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""},
- {0, NULL, 0, NULL, NULL}};
#define AXIS_X 1
#define AXIS_Y 2
@@ -3516,273 +3293,8 @@ static const EnumPropertyItem direction_items[]= {
static const EnumPropertyItem axis_items[]= {
{AXIS_X, "X", 0, "X", ""},
{AXIS_Y, "Y", 0, "Y", ""},
- {0, NULL, 0, NULL, NULL}};
-
-static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
-{
- 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;
-
- /* 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) {
- BKE_report(op->reports, RPT_ERROR, "Memory allocation failed");
- 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(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
- newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
- }
- else if(fac1 == 4 && fac2 == 3) {
- if(dir == DIRECTION_CW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
- newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
- } else if (dir == DIRECTION_CCW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
- newFace[1]= EM_face_from_faces(em, 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 == DIRECTION_CW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
- newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
- } else if (dir == DIRECTION_CCW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
- newFace[1]= EM_face_from_faces(em, 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 == DIRECTION_CW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
- newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
- } else if (dir == DIRECTION_CCW) {
- newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
- newFace[1]= EM_face_from_faces(em, 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 == DIRECTION_CW || (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(em, eed);
- free_editedge(em, eed);
- BLI_remlink(&em->faces, face[0]);
- free_editface(em, face[0]);
- BLI_remlink(&em->faces, face[1]);
- free_editface(em, face[1]);
-}
-
-// XXX ton please check
-/* only accepts 1 selected edge, or 2 selected faces */
-static int edge_rotate_selected(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- EditEdge *eed;
- EditFace *efa;
- int dir = RNA_int_get(op->ptr, "direction"); // dir == 2 when clockwise and ==1 for counter CW.
- short edgeCount = 0;
-
- /*clear new flag for new edges, count selected edges */
- for(eed= em->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= em->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= em->edges.first; eed; eed= eed->next) {
- if(eed->f1==2) edgeCount++;
- }
- if(edgeCount==1) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f1==2) {
- edge_rotate(em, op, eed,dir);
- break;
- }
- }
- }
- else
- {
- BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
- }
- else if(edgeCount==1) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- EM_select_edge(eed, 0);
- edge_rotate(em, op, eed,dir);
- break;
- }
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- /* flush selected vertices (again) to edges/faces */
- EM_select_flush(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_edge_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rotate Selected Edge";
- ot->description= "Rotate selected edge or adjoining faces.";
- ot->idname= "MESH_OT_edge_rotate";
-
- /* api callbacks */
- ot->exec= edge_rotate_selected;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around.");
-}
-
+ {0, NULL, 0, NULL, NULL},
+};
/******************* BEVEL CODE STARTS HERE ********************/
@@ -3873,11 +3385,11 @@ typedef struct SlideVert {
EditVert origvert;
} SlideVert;
-#if 0
int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc)
{
return 0;
/* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */
+#if 0
useless:
goto useless // because it doesn't do anything right now
@@ -4659,35 +4171,9 @@ useless:
}
return 1;
-}
#endif // END OF XXX
-
-int EdgeLoopDelete(EditMesh *em, wmOperator *op)
-{
-#if 0 //XXX won't work with new edgeslide
-
- /* 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 = 0; // XXX scene->toolsettings->uvcalc_flag;
- // scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
-
- if(!EdgeSlide(em, op, 1, 1)) {
- return 0;
- }
-
- /* restore uvcalc flag */
- // scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
-
- EM_select_more(em);
- removedoublesflag(em, 1,0, 0.001);
- EM_select_flush(em);
- // DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- return 1;
-#endif
- return 0;
}
-
/* -------------------- More tools ------------------ */
#if 0
void mesh_set_face_flags(EditMesh *em, short mode)
@@ -4757,271 +4243,6 @@ void mesh_set_face_flags(EditMesh *em, short mode)
}
#endif
-/********************** Rip Operator *************************/
-
-/* helper to find edge for edge_rip */
-static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval)
-{
- float vec1[3], vec2[3], mvalf[2];
-
- view3d_project_float(ar, co1, vec1, mat);
- view3d_project_float(ar, 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(EditMesh *em, 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(em, sefa->v1, sefa->v2, sefa->e1);
- sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2);
- if(sefa->v4) {
- sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3);
- sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4);
- }
- else
- sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3);
-
-}
-
-/* based on mouse cursor position, it defines how is being ripped */
-static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- ARegion *ar= CTX_wm_region(C);
- RegionView3D *rv3d= ar->regiondata;
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- EditVert *eve, *nextve;
- EditEdge *eed, *seed= NULL;
- EditFace *efa, *sefa= NULL;
- float projectMat[4][4], vec[3], dist, mindist;
- short doit= 1, *mval= event->mval;
-
- /* select flush... vertices are important */
- EM_selectmode_set(em);
-
- view3d_get_object_project_mat(rv3d, obedit, projectMat);
-
- /* 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(ar, 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) {
- BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
- if(sefa==NULL) {
- BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
-
- /* 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(em, 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(ar, 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(ar, 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(ar, 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(ar, projectMat,
- sefa->e4->v1->co,
- sefa->e4->v2->co, mval);
- if(dist<mindist) {
- seed= sefa->e4;
- mindist= dist;
- }
- }
- }
-
- if(seed==NULL) { // never happens?
- BKE_report(op->reports, RPT_ERROR, "No proper edge found to start");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- faceloop_select(em, 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(em, 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) {
- EM_select_edge(eed, 0);
- EM_remove_selection(em, eed, EDITEDGE);
- EM_select_edge(newed, 1);
- }
- 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(em, 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(em, 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(em, eed);
- free_editedge(em, 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(em, eve);
- }
- }
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
-// RNA_enum_set(op->ptr, "proportional", 0);
-// RNA_boolean_set(op->ptr, "mirror", 0);
-// WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_rip(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rip";
- ot->description= "Rip selection from mesh (quads only).";
- ot->idname= "MESH_OT_rip";
-
- /* api callbacks */
- ot->invoke= mesh_rip_invoke;
- ot->poll= EM_view3d_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* to give to transform */
- Properties_Proportional(ot);
- RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
-}
-
-
/************************ Shape Operators *************************/
void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
@@ -5068,6 +4289,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;
@@ -5144,6 +4366,7 @@ void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock
}
}
return;
+#endif
}
@@ -5643,7 +4866,7 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert)
}
}
-static int collapseEdges(EditMesh *em)
+int collapseEdges(EditMesh *em)
{
EditVert *eve;
EditEdge *eed;
@@ -5709,406 +4932,7 @@ static int collapseEdges(EditMesh *em)
return mergecount;
}
-static int merge_firstlast(EditMesh *em, int first, int uvmerge)
-{
- EditVert *eve,*mergevert;
- EditSelection *ese;
-
- /* do sanity check in mergemenu in edit.c ?*/
- if(first == 0){
- ese = em->selected.last;
- mergevert= (EditVert*)ese->data;
- }
- else{
- ese = em->selected.first;
- mergevert = (EditVert*)ese->data;
- }
-
- if(mergevert->f&SELECT){
- for (eve=em->verts.first; eve; eve=eve->next){
- if (eve->f&SELECT)
- VECCOPY(eve->co,mergevert->co);
- }
- }
-
- if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
-
- for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
- for(eve=em->verts.first; eve; eve=eve->next){
- if(eve->f&SELECT) eve->f1 = 1;
- }
- collapseuvs(em, mergevert);
- }
-
- return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-
-static void em_snap_to_center(EditMesh *em)
-{
- EditVert *eve;
- float cent[3] = {0.0f, 0.0f, 0.0f};
- int i=0;
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- VecAddf(cent, cent, eve->co);
- i++;
- }
- }
-
- if (!i)
- return;
-
- VecMulf(cent, 1.0f / (float)i);
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- VECCOPY(eve->co, cent);
- }
- }
-}
-
-static void em_snap_to_cursor(EditMesh *em, bContext *C)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob= CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- EditVert *eve;
- float co[3], *vco, invmat[4][4];
-
- Mat4Invert(invmat, ob->obmat);
-
- vco = give_cursor(scene, v3d);
- VECCOPY(co, vco);
- Mat4MulVecfl(invmat, co);
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- VECCOPY(eve->co, co);
- }
- }
-}
-
-static int merge_target(bContext *C, EditMesh *em, int target, int uvmerge)
-{
- EditVert *eve;
-
- // XXX not working
- if(target) em_snap_to_cursor(em, C);
- else em_snap_to_center(em);
-
- if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
- for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
- for(eve=em->verts.first; eve; eve=eve->next){
- if(eve->f&SELECT) eve->f1 = 1;
- }
- collapseuvs(em, NULL);
- }
-
- return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-#undef MERGELIMIT
-
-static int merge_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int count= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
-
- switch(RNA_enum_get(op->ptr, "type")) {
- case 3:
- count = merge_target(C, em, 0, uvs);
- break;
- case 4:
- count = merge_target(C, em, 1, uvs);
- break;
- case 1:
- count = merge_firstlast(em, 0, uvs);
- break;
- case 6:
- count = merge_firstlast(em, 1, uvs);
- break;
- case 5:
- count = collapseEdges(em);
- break;
- }
-
- if(!count)
- return OPERATOR_CANCELLED;
-
- BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices.", count);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static EnumPropertyItem merge_type_items[]= {
- {6, "FIRST", 0, "At First", ""},
- {1, "LAST", 0, "At Last", ""},
- {3, "CENTER", 0, "At Center", ""},
- {4, "CURSOR", 0, "At Cursor", ""},
- {5, "COLLAPSE", 0, "Collapse", ""},
- {0, NULL, 0, NULL, NULL}};
-
-static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
-{
- Object *obedit= CTX_data_edit_object(C);
- EnumPropertyItem *item= NULL;
- int totitem= 0;
-
- if(obedit && obedit->type == OB_MESH) {
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- if(em->selected.first && em->selected.last &&
- ((EditSelection*)em->selected.first)->type == EDITVERT && ((EditSelection*)em->selected.last)->type == EDITVERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
- }
- else if(em->selected.first && ((EditSelection*)em->selected.first)->type == EDITVERT)
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
- else if(em->selected.last && ((EditSelection*)em->selected.last)->type == EDITVERT)
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
- }
-
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
-
- return item;
-}
-
-void MESH_OT_merge(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Merge";
- ot->description= "Merge selected vertices.";
- ot->idname= "MESH_OT_merge";
-
- /* api callbacks */
- ot->exec= merge_exec;
- ot->invoke= WM_menu_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
- RNA_def_enum_funcs(prop, merge_type_itemf);
- RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
-}
-
-/************************ Vertex Path Operator *************************/
-
-typedef struct PathNode {
- int u;
- int visited;
- ListBase edges;
-} PathNode;
-
-typedef struct PathEdge {
- struct PathEdge *next, *prev;
- int v;
- float w;
-} PathEdge;
-#define PATH_SELECT_EDGE_LENGTH 0
-#define PATH_SELECT_TOPOLOGICAL 1
-
-static int select_vertex_path_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- 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;
-
- ese = ((EditSelection*)em->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=em->verts.first; eve; eve=eve->next){
- eve->f1 = 0;
- }
-
- s->f1 = 1;
-
- unbalanced = 1;
- totnodes = 1;
- while(unbalanced){
- unbalanced = 0;
- for(eed=em->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=em->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=em->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=em->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(em);
- }
- }
- else {
- BKE_mesh_end_editmesh(obedit->data, em);
- BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected");
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_vertex_path(wmOperatorType *ot)
-{
- static const EnumPropertyItem type_items[] = {
- {PATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
- {PATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "Select Vertex Path";
- ot->description= "Select shortest path between two vertices by distance type.";
- ot->idname= "MESH_OT_select_vertex_path";
-
- /* api callbacks */
- ot->exec= select_vertex_path_exec;
- ot->invoke= WM_menu_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "type", type_items, PATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance.");
-}
/********************** Region/Loop Operators *************************/
@@ -6157,7 +4981,6 @@ void MESH_OT_region_to_loop(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Region to Loop";
- ot->description= "Select a region as a loop of connected edges.";
ot->idname= "MESH_OT_region_to_loop";
/* api callbacks */
@@ -6202,8 +5025,8 @@ static int validate_loop(EditMesh *em, Collection *edgecollection)
return(1);
}
-static int loop_bisect(EditMesh *em, Collection *edgecollection){
-
+static int loop_bisect(EditMesh *em, Collection *edgecollection)
+{
EditFace *efa, *sf1, *sf2;
EditEdge *eed, *sed;
CollectedEdge *curredge;
@@ -6333,7 +5156,6 @@ void MESH_OT_loop_to_region(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Loop to Region";
- ot->description= "Select a loop of connected edges as a region.";
ot->idname= "MESH_OT_loop_to_region";
/* api callbacks */
@@ -6344,403 +5166,6 @@ void MESH_OT_loop_to_region(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-/********************** UV/Color Operators *************************/
-
-// XXX please check if these functions do what you want them to
-/* texface and vertex color editmode tools for the face menu */
-
-static int mesh_rotate_uvs(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- EditFace *efa;
- short change = 0;
- MTFace *tf;
- float u1, v1;
- int dir= RNA_enum_get(op->ptr, "direction");
-
- if (!EM_texFaceCheck(em)) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers.");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- 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 (dir == DIRECTION_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;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int mesh_mirror_uvs(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- EditFace *efa;
- short change = 0;
- MTFace *tf;
- float u1, v1;
- int axis= RNA_enum_get(op->ptr, "axis");
-
- if (!EM_texFaceCheck(em)) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers.");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if (axis == AXIS_Y) {
- 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;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int mesh_rotate_colors(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- EditFace *efa;
- short change = 0;
- MCol tmpcol, *mcol;
- int dir= RNA_enum_get(op->ptr, "direction");
-
- if (!EM_vertColorCheck(em)) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers.");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- 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 (dir == DIRECTION_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;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-
-static int mesh_mirror_colors(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- EditFace *efa;
- short change = 0;
- MCol tmpcol, *mcol;
- int axis= RNA_enum_get(op->ptr, "axis");
-
- if (!EM_vertColorCheck(em)) {
- BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- if (axis == AXIS_Y) {
- 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;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_uvs_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rotate UVs";
- ot->description= "Rotate selected UVs.";
- ot->idname= "MESH_OT_uvs_rotate";
-
- /* api callbacks */
- ot->exec= mesh_rotate_uvs;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around.");
-}
-
-void MESH_OT_uvs_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mirror UVs";
- ot->description= "Mirror selected UVs.";
- ot->idname= "MESH_OT_uvs_mirror";
-
- /* api callbacks */
- ot->exec= mesh_mirror_uvs;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around.");
-}
-
-void MESH_OT_colors_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rotate Colors";
- ot->description= "Rotate UV/image color layer.";
- ot->idname= "MESH_OT_colors_rotate";
-
- /* api callbacks */
- ot->exec= mesh_rotate_colors;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around.");
-}
-
-void MESH_OT_colors_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mirror Colors";
- ot->description= "Mirror UV/image color layer.";
- ot->idname= "MESH_OT_colors_mirror";
-
- /* api callbacks */
- ot->exec= mesh_mirror_colors;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- 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)
-{
- ToolSettings *ts= CTX_data_tool_settings(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, ts->editbutflag|flag, cuts, 0);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_subdivide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Subdivide";
- ot->description= "Subdivide selected edges.";
- 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
@@ -7007,7 +5432,6 @@ void MESH_OT_fill(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Fill";
- ot->description= "Create a segment, edge or face.";
ot->idname= "MESH_OT_fill";
/* api callbacks */
@@ -7037,7 +5461,6 @@ void MESH_OT_beauty_fill(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Beauty Fill";
- ot->description= "Arrange geometry on a selected surface to avoid skinny faces.";
ot->idname= "MESH_OT_beauty_fill";
/* api callbacks */
@@ -7053,14 +5476,15 @@ void MESH_OT_beauty_fill(wmOperatorType *ot)
static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
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_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -7068,7 +5492,6 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Quads to Tris";
- ot->description= "Convert selected quads to triangles.";
ot->idname= "MESH_OT_quads_convert_to_tris";
/* api callbacks */
@@ -7097,7 +5520,6 @@ void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Tris to Quads";
- ot->description= "Convert selected triangles to quads.";
ot->idname= "MESH_OT_tris_convert_to_quads";
/* api callbacks */
@@ -7126,7 +5548,6 @@ void MESH_OT_edge_flip(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Edge Flip";
- ot->description= "Flip selected edge or adjoining faces.";
ot->idname= "MESH_OT_edge_flip";
/* api callbacks */
@@ -7136,78 +5557,3 @@ void MESH_OT_edge_flip(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-
-/********************** Smooth/Solid Operators *************************/
-
-static void mesh_set_smooth_faces(EditMesh *em, short smooth)
-{
- EditFace *efa;
-
- if(em==NULL) return;
-
- for(efa= em->faces.first; efa; efa=efa->next) {
- if(efa->f & SELECT) {
- if(smooth) efa->flag |= ME_SMOOTH;
- else efa->flag &= ~ME_SMOOTH;
- }
- }
-}
-
-static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- mesh_set_smooth_faces(em, 1);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shade Smooth";
- ot->description= "Display faces 'smooth' (using vertex normals).";
- ot->idname= "MESH_OT_faces_shade_smooth";
-
- /* api callbacks */
- ot->exec= mesh_faces_shade_smooth_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int mesh_faces_shade_flat_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- mesh_set_smooth_faces(em, 0);
-
- DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_faces_shade_flat(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shade Flat";
- ot->description= "Display faces 'flat'.";
- ot->idname= "MESH_OT_faces_shade_flat";
-
- /* api callbacks */
- ot->exec= mesh_faces_shade_flat_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c
index 4ef25238a84..9a2a953f643 100644
--- a/source/blender/editors/mesh/loopcut.c
+++ b/source/blender/editors/mesh/loopcut.c
@@ -47,6 +47,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
#include "BLI_editVert.h"
+#include "BLI_array.h"
#include "BKE_blender.h"
#include "BKE_context.h"
@@ -54,6 +55,8 @@
#include "BKE_scene.h"
#include "BKE_utildefines.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_depsgraph.h"
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
@@ -90,8 +93,8 @@ typedef struct tringselOpData {
ViewContext vc;
Object *ob;
- EditMesh *em;
- EditEdge *eed;
+ BMEditMesh *em;
+ BMEdge *eed;
int extend;
int do_cut;
@@ -122,13 +125,13 @@ static void ringsel_draw(const bContext *C, ARegion *ar, void *arg)
static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
{
- EditMesh *em = lcd->em;
- EditEdge *startedge = lcd->eed;
- EditEdge *eed;
- EditFace *efa;
- EditVert *v[2][2];
+ BMEditMesh *em = lcd->em;
+ BMEdge *startedge = lcd->eed;
+ BMEdge *eed, *lasteed;
+ BMVert *v[2][2];
+ BMWalker walker;
float (*edges)[2][3] = NULL;
- V_DYNDECLARE(edges);
+ BLI_array_declare(edges);
float co[2][3];
int looking=1, i, tot=0;
@@ -142,110 +145,104 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
}
if (!lcd->extend) {
- EM_clear_flag_all(lcd->em, SELECT);
+ EDBM_clear_flag_all(lcd->em, BM_SELECT);
}
- /* 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 */
+ if (select) {
+ BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
+ eed = BMW_Begin(&walker, startedge);
+ for (; eed; eed=BMW_Step(&walker)) {
+ BM_Select(em->bm, eed, 1);
+ }
+ BMW_End(&walker);
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
+ return;
}
- 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 == 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;
- }
+ BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
+ eed = startedge = BMW_Begin(&walker, startedge);
+ for (lasteed=NULL; eed; eed=BMW_Step(&walker)) {
+ if (lasteed) {
+ BMIter liter;
+ BMLoop *l, *l2;
+ int rev;
+
+ v[0][0] = eed->v1;
+ v[0][1] = eed->v2;
+ v[1][0] = lasteed->v1;
+ v[1][1] = lasteed->v2;
+
+#if 0 //hrm. this code may be useful later.
+ /*find correct order for v[1]*/
+
+ l = eed->loop;
+ if (!(BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_LOOP, l) {
+ if (BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))
+ break;
}
}
+
+ /*this should never happen*/
+ if (!l) {
+ lasteed = eed;
+ continue;
+ }
+
+ l2 = BM_OtherFaceLoop(l->e, l->f, l->v);
+ rev = (l2 == (BMLoop*)l->head.prev);
+ while (l2->v != lasteed->v1 && l2->v != lasteed->v2) {
+ l2 = rev ? (BMLoop*)l2->head.prev : (BMLoop*)l2->head.next;
+ }
+
+ if (l2->v == lasteed->v1) {
+ v[1][0] = lasteed->v1;
+ v[1][1] = lasteed->v2;
+ } else {
+ v[1][0] = lasteed->v2;
+ v[1][1] = lasteed->v1;
+ }
+#endif
+ for(i=1;i<=previewlines;i++){
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+
+ BLI_array_growone(edges);
+ VECCOPY(edges[tot][0], co[0]);
+ VECCOPY(edges[tot][1], co[1]);
+ tot++;
+ }
}
+ lasteed = eed;
}
- if(previewlines > 0 && !select){
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4 == NULL) { continue; }
- if(efa->h == 0){
- if(efa->e1->f2 == 1){
- if(efa->e1->h == 1 || efa->e3->h == 1 )
- continue;
-
- v[0][0] = efa->v1;
- v[0][1] = efa->v2;
- v[1][0] = efa->v4;
- v[1][1] = efa->v3;
- } else if(efa->e2->f2 == 1){
- if(efa->e2->h == 1 || efa->e4->h == 1)
- continue;
- v[0][0] = efa->v2;
- v[0][1] = efa->v3;
- v[1][0] = efa->v1;
- v[1][1] = efa->v4;
- } else { continue; }
-
- for(i=1;i<=previewlines;i++){
- co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
- co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
- co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
-
- co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
- co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
- co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
-
- V_GROW(edges);
- VECCOPY(edges[tot][0], co[0]);
- VECCOPY(edges[tot][1], co[1]);
- tot++;
- }
- }
- }
- } else {
- select = (startedge->f & SELECT) == 0;
-
- /* select the edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2) EM_select_edge(eed, select);
+ if (BM_Edge_Share_Faces(lasteed, startedge)) {
+ v[0][0] = startedge->v1;
+ v[0][1] = startedge->v2;
+ v[1][0] = lasteed->v1;
+ v[1][1] = lasteed->v2;
+ for(i=1;i<=previewlines;i++){
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+
+ BLI_array_growone(edges);
+ VECCOPY(edges[tot][0], co[0]);
+ VECCOPY(edges[tot][1], co[1]);
+ tot++;
}
}
+ BMW_End(&walker);
lcd->edges = edges;
lcd->totedge = tot;
}
@@ -264,9 +261,12 @@ static void ringsel_finish(bContext *C, wmOperator *op)
if (lcd->eed) {
edgering_sel(lcd, cuts, 1);
if (lcd->do_cut) {
- EditMesh *em = BKE_mesh_get_editmesh(lcd->ob->data);
- esubdivideflag(lcd->ob, em, SELECT, 0.0f, 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT);
-
+ BMEditMesh *em = lcd->em;
+ BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f,
+ 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT,
+ SUBD_PATH, 0, 0);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT|ND_DATA, lcd->ob->data);
DAG_id_flush_update(lcd->ob->data, OB_RECALC_DATA);
}
WM_event_add_notifier(C, NC_GEOM|ND_DATA, lcd->ob->data);
@@ -303,7 +303,7 @@ static int ringsel_init (bContext *C, wmOperator *op, int do_cut)
lcd->ar= CTX_wm_region(C);
lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST);
lcd->ob = CTX_data_edit_object(C);
- lcd->em= BKE_mesh_get_editmesh((Mesh *)lcd->ob->data);
+ lcd->em= ((Mesh *)lcd->ob->data)->edit_btmesh;
lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend");
lcd->do_cut = do_cut;
em_setup_viewcontext(C, &lcd->vc);
@@ -323,7 +323,7 @@ static int ringsel_cancel (bContext *C, wmOperator *op)
static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt)
{
tringselOpData *lcd;
- EditEdge *edge;
+ BMEdge *edge;
int dist = 75;
view3d_operator_needs_opengl(C);
@@ -338,7 +338,7 @@ static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt)
lcd->vc.mval[0] = evt->mval[0];
lcd->vc.mval[1] = evt->mval[1];
- edge = findnearestedge(&lcd->vc, &dist);
+ edge = EDBM_findnearestedge(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
ringsel_find_edge(lcd, C, lcd->ar, 1);
@@ -351,7 +351,7 @@ static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt)
static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
{
tringselOpData *lcd;
- EditEdge *edge;
+ BMEdge *edge;
int dist = 75;
view3d_operator_needs_opengl(C);
@@ -366,7 +366,7 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
lcd->vc.mval[0] = evt->mval[0];
lcd->vc.mval[1] = evt->mval[1];
- edge = findnearestedge(&lcd->vc, &dist);
+ edge = EDBM_findnearestedge(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
ringsel_find_edge(lcd, C, lcd->ar, 1);
@@ -424,11 +424,11 @@ static int ringsel_modal (bContext *C, wmOperator *op, wmEvent *event)
break;
case MOUSEMOVE: { /* mouse moved somewhere to select another loop */
int dist = 75;
- EditEdge *edge;
+ BMEdge *edge;
lcd->vc.mval[0] = event->mval[0];
lcd->vc.mval[1] = event->mval[1];
- edge = findnearestedge(&lcd->vc, &dist);
+ edge = EDBM_findnearestedge(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 6ed2ca08c9c..848930e156b 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -48,6 +48,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
@@ -68,12 +69,17 @@
static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
{
Mesh *me = ob->data;
- 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);
- int i, actindex, rndindex, cloneindex, maskindex;
+ int i, actindex, rndindex, cloneindex, maskindex, tot = me->totpoly;
+ if (layer->type == CD_MLOOPCOL) {
+ data = (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata;
+ tot = me->totloop;
+ }
+
/* ok, deleting a non-active layer needs to preserve the active layer indices.
to do this, we store a pointer to the .data member of both layer and the active layer,
(to detect if we're deleting the active layer or not), then use the active
@@ -87,15 +93,15 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
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);
+ CustomData_free_layer_active(data, type, tot);
mesh_update_customdata_pointers(me);
}
- if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
+ if(!CustomData_has_layer(data, type) && (type == CD_MLOOPCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
/* reconstruct active layer */
@@ -158,30 +164,30 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
int ED_mesh_uv_texture_add(bContext *C, Scene *scene, Object *ob, Mesh *me)
{
- EditMesh *em;
+ BMEditMesh *em;
int layernum;
- if(me->edit_mesh) {
- em= me->edit_mesh;
+ if(me->edit_btmesh) {
+ 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, MAX_MTFACE);
+ CustomData_set_layer_active(&em->bm->pdata, MAX_MTFACE, layernum);
}
else {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ layernum= CustomData_number_of_layers(&me->pdata, MAX_MTFACE);
if(layernum >= MAX_MTFACE)
return OPERATOR_CANCELLED;
if(me->mtface)
- CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
+ CustomData_add_layer(&me->pdata, MAX_MTFACE, CD_DUPLICATE, me->mtpoly, me->totpoly);
else
- CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
+ CustomData_add_layer(&me->pdata, MAX_MTFACE, CD_DEFAULT, NULL, me->totpoly);
- CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
+ CustomData_set_layer_active(&me->pdata, MAX_MTFACE, layernum);
mesh_update_customdata_pointers(me);
}
@@ -196,8 +202,8 @@ int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
CustomDataLayer *cdl;
int index;
- 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];
if(!cdl)
return 0;
@@ -211,37 +217,39 @@ int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me)
{
- EditMesh *em;
- MCol *mcol;
+ BMEditMesh *em;
+ MLoopCol *mcol;
int layernum;
- if(me->edit_mesh) {
- em= me->edit_mesh;
+ if(me->edit_btmesh) {
+ 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 0;
- 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->pdata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
}
else {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
- if(layernum >= MAX_MCOL)
+ layernum= CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if(layernum >= CD_MLOOPCOL)
return 0;
- 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);
+ /*BMESH_TODO
if(!mcol)
shadeMeshMCol(scene, ob, me);
+ */
}
DAG_id_flush_update(&me->id, OB_RECALC_DATA);
@@ -255,8 +263,8 @@ int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
CustomDataLayer *cdl;
int index;
- 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->pdata, CD_MLOOPCOL);
+ cdl= (index == -1)? NULL: &me->pdata.layers[index];
if(!cdl)
return 0;
@@ -618,7 +626,7 @@ static void mesh_add_faces(Mesh *mesh, int len)
void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
{
- if(mesh->edit_mesh) {
+ if(mesh->edit_btmesh) {
BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode.");
return;
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 7ee7fe1ebde..4a1532af3b0 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -32,11 +32,53 @@
#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_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 +87,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);
@@ -61,7 +110,7 @@ extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1, struct Ed
extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges);
extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2);
-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);
@@ -143,12 +192,15 @@ 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);
void MESH_OT_select_non_manifold(struct wmOperatorType *ot);
void MESH_OT_select_linked(struct wmOperatorType *ot);
void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
+void MESH_OT_pin(struct wmOperatorType *ot);
+void MESH_OT_unpin(struct wmOperatorType *ot);
void MESH_OT_hide(struct wmOperatorType *ot);
void MESH_OT_reveal(struct wmOperatorType *ot);
void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot);
@@ -166,13 +218,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(Scene *scene, Object *obedit, 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
@@ -183,7 +235,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 */
@@ -196,7 +248,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);
@@ -220,9 +272,12 @@ void MESH_OT_loop_to_region(struct wmOperatorType *ot);
void MESH_OT_region_to_loop(struct wmOperatorType *ot);
void MESH_OT_uvs_rotate(struct wmOperatorType *ot);
-void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
+//void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
+void MESH_OT_uvs_reverse(struct wmOperatorType *ot);
void MESH_OT_colors_rotate(struct wmOperatorType *ot);
-void MESH_OT_colors_mirror(struct wmOperatorType *ot);
+//void MESH_OT_colors_mirror(struct wmOperatorType *ot);
+
+void MESH_OT_colors_reverse(struct wmOperatorType *ot);
void MESH_OT_delete(struct wmOperatorType *ot);
void MESH_OT_rip(struct wmOperatorType *ot);
@@ -236,6 +291,15 @@ void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
void MESH_OT_sticky_add(struct wmOperatorType *ot);
void MESH_OT_sticky_remove(struct wmOperatorType *ot);
+/* ************* bmesh_tools.c ***********/
+void MESH_OT_vert_connect(struct wmOperatorType *ot);
+void MESH_OT_edge_split(struct wmOperatorType *ot);
+void MESH_OT_extrude_region(struct wmOperatorType *ot);
+void MESH_OT_extrude_verts_indiv(struct wmOperatorType *ot);
+void MESH_OT_extrude_edges_indiv(struct wmOperatorType *ot);
+void MESH_OT_extrude_faces_indiv(struct wmOperatorType *ot);
+void MESH_OT_bm_test(struct wmOperatorType *ot);
+
void MESH_OT_edgering_select(struct wmOperatorType *ot);
void MESH_OT_loopcut(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index c8d85aace47..7b2522ac3d2 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -77,6 +77,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_select_linked_pick);
WM_operatortype_append(MESH_OT_select_random);
WM_operatortype_append(MESH_OT_selection_type);
+ WM_operatortype_append(MESH_OT_pin);
+ WM_operatortype_append(MESH_OT_unpin);
WM_operatortype_append(MESH_OT_hide);
WM_operatortype_append(MESH_OT_reveal);
WM_operatortype_append(MESH_OT_select_by_number_vertices);
@@ -112,9 +114,11 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_region_to_loop);
WM_operatortype_append(MESH_OT_uvs_rotate);
- WM_operatortype_append(MESH_OT_uvs_mirror);
+ //WM_operatortype_append(MESH_OT_uvs_mirror);
+ WM_operatortype_append(MESH_OT_uvs_reverse);
WM_operatortype_append(MESH_OT_colors_rotate);
- WM_operatortype_append(MESH_OT_colors_mirror);
+ //WM_operatortype_append(MESH_OT_colors_mirror);
+ WM_operatortype_append(MESH_OT_colors_reverse);
WM_operatortype_append(MESH_OT_fill);
WM_operatortype_append(MESH_OT_beauty_fill);
@@ -146,7 +150,16 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_vertex_color_remove);
WM_operatortype_append(MESH_OT_sticky_add);
WM_operatortype_append(MESH_OT_sticky_remove);
+ WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_edge_split);
+
+ WM_operatortype_append(MESH_OT_extrude_region);
+ WM_operatortype_append(MESH_OT_extrude_verts_indiv);
+ WM_operatortype_append(MESH_OT_extrude_edges_indiv);
+ WM_operatortype_append(MESH_OT_extrude_faces_indiv);
+ WM_operatortype_append(MESH_OT_bm_test);
+
WM_operatortype_append(MESH_OT_edgering_select);
WM_operatortype_append(MESH_OT_loopcut);
}
@@ -173,10 +186,16 @@ void ED_operatormacros_mesh(void)
otmacro= WM_operatortype_macro_define(ot, "TFM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER);
+ /*ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude", OPTYPE_UNDO|OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "MESH_OT_extrude");
otmacro= WM_operatortype_macro_define(ot, "TFM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_enum_set(otm->ptr, "proportional", 0);
+ RNA_boolean_set(otm->ptr, "mirror", 0);
+
+ RNA_enum_set(otm->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
+ RNA_boolean_set_array(otm->ptr, "constraint_axis", constraint_axis);*/
+
}
/* note mesh keymap also for other space? */
@@ -203,11 +222,14 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_select_non_manifold", MKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0);
-
+
+ WM_keymap_add_item(keymap, "MESH_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_more", EQUALKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_select_less", MINUSKEY, KM_PRESS, KM_CTRL, 0);
+
WM_keymap_add_item(keymap, "MESH_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "deselect", 1);
@@ -216,12 +238,19 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_edges_select_sharp", SKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0);
WM_keymap_add_item(keymap, "MESH_OT_vertices_transform_to_sphere", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT , 0);
-
WM_keymap_add_item(keymap, "MESH_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_edge_split", MKEY, KM_PRESS, 0, 0);
/* selection mode */
WM_keymap_add_item(keymap, "MESH_OT_selection_type", TABKEY, KM_PRESS, KM_CTRL, 0);
+ /* pin */
+ WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_pin", RETKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1);
+ WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_unpin", RETKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "unselected", 1);
+
/* hide */
WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1);
@@ -231,7 +260,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "inside", 1);
- WM_keymap_add_item(keymap, "MESH_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_extrude", EKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "MESH_OT_vert_connect", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_screw", NINEKEY, KM_PRESS, KM_CTRL, 0);
@@ -250,11 +281,13 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_region_to_loop",SIXKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_uvs_rotate",SEVENKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0);
+ //WM_keymap_add_item(keymap, "MESH_OT_uvs_mirror",SEVENKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_uvs_reverse",SEVENKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_colors_rotate",EIGHTKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
+ //WM_keymap_add_item(keymap, "MESH_OT_colors_mirror",EIGHTKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_colors_reverse",EIGHTKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_rip_move",VKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0);
/* add/remove */
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index fad73e19e16..629e7bacc20 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -73,6 +73,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"
@@ -119,15 +120,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;
@@ -144,6 +147,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)
@@ -291,18 +296,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);
@@ -452,7 +465,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)
*/
@@ -471,14 +520,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);
@@ -839,7 +894,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;
@@ -865,10 +920,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 {
@@ -906,10 +963,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));
}
}
@@ -965,7 +1024,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;
@@ -983,7 +1042,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;
}
@@ -1033,7 +1092,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 6ecc80f2d81..a6f034c9c33 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 ../../ikplugin'
+incs += ' ../../makesrna ../../python ../../ikplugin ../../bmesh'
defs = []
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index bd8b865a6c9..08689e9b62b 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -112,6 +112,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_modifier.h"
+#include "BKE_tessmesh.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -297,16 +298,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(obedit->restore_mode & OB_MODE_WEIGHT_PAINT)
@@ -336,21 +338,10 @@ void ED_object_exit_editmode(bContext *C, int flag)
/* freedata only 0 now on file saves and render */
if(freedata) {
- ListBase pidlist;
- PTCacheID *pid;
-
/* for example; displist make is different in editmode */
scene->obedit= NULL; // XXX for context
-
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, obedit);
- for(pid=pidlist.first; pid; pid=pid->next) {
- if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- BLI_freelistN(&pidlist);
- BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
+ BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_DEPSGRAPH);
/* also flush ob recalc, doesn't take much overhead, but used for particles */
DAG_id_flush_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
@@ -410,7 +401,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
ok= 1;
scene->obedit= ob; // context sees this
- make_editMesh(scene, ob);
+ EDBM_MakeEditBMesh(CTX_data_tool_settings(C), scene, ob);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
}
@@ -1965,26 +1956,29 @@ static int object_mode_set_compat(bContext *C, wmOperator *op, Object *ob)
ObjectMode mode = RNA_enum_get(op->ptr, "mode");
if(ob) {
- if(mode == OB_MODE_OBJECT)
- return 1;
-
switch(ob->type) {
+ case OB_EMPTY:
+ case OB_LAMP:
+ case OB_CAMERA:
+ if(mode & OB_MODE_OBJECT)
+ return 1;
+ return 0;
case OB_MESH:
- if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
+ if(mode & ( OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
return 1;
return 0;
case OB_CURVE:
case OB_SURF:
case OB_FONT:
case OB_MBALL:
- if(mode & (OB_MODE_EDIT))
+ if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT))
return 1;
return 0;
case OB_LATTICE:
- if(mode & (OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT))
+ if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT))
return 1;
case OB_ARMATURE:
- if(mode & (OB_MODE_EDIT|OB_MODE_POSE))
+ if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_POSE))
return 1;
}
}
@@ -2000,7 +1994,7 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
int toggle = RNA_boolean_get(op->ptr, "toggle");
if(!ob || !object_mode_set_compat(C, op, ob))
- return OPERATOR_PASS_THROUGH;
+ return OPERATOR_CANCELLED;
/* Exit current mode if it's not the mode we're setting */
if(ob->mode != OB_MODE_OBJECT && ob->mode != mode)
@@ -2041,7 +2035,7 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
- prop= RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", "");
+ prop= RNA_def_enum(ot->srna, "mode", object_mode_items, 0, "Mode", "");
RNA_def_enum_funcs(prop, object_mode_set_itemsf);
RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index dd3e5969a75..94a5ad6fa9f 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -44,7 +44,7 @@
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
-#include "BLI_editVert.h"
+#include "BLI_cellalloc.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -57,6 +57,7 @@
#include "BKE_mesh.h"
#include "BKE_paint.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -112,10 +113,10 @@ MDeformWeight *ED_vgroup_weight_verify(MDeformVert *dv, int defgroup)
if(newdw)
return newdw;
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
if(dv->dw) {
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
- MEM_freeN(dv->dw);
+ BLI_cellalloc_free(dv->dw);
}
dv->dw=newdw;
@@ -218,13 +219,13 @@ void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
* deform weight, and reshuffle the others
*/
if(dvert->totweight) {
- newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight),
+ newdw = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight),
"deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
memcpy(newdw+i, dvert->dw+i+1,
sizeof(MDeformWeight)*(dvert->totweight-i));
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
}
dvert->dw=newdw;
}
@@ -317,11 +318,11 @@ void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, in
/* if we are doing an additive assignment, then
* we need to create the deform weight
*/
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1),
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1),
"deformWeight");
if(dv->dw){
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
- MEM_freeN(dv->dw);
+ BLI_cellalloc_free(dv->dw);
}
dv->dw=newdw;
@@ -390,10 +391,11 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
}
+
static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
{
MDeformVert *dvert= NULL;
- EditVert *eve;
+ BMVert *eve;
Mesh *me;
int i;
@@ -401,10 +403,10 @@ static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
if(ob->type==OB_MESH) {
me= ob->data;
- if(me->edit_mesh) {
- eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
+ if(me->edit_btmesh) {
+ eve= BMIter_AtIndex(me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL, vertnum);
if(!eve) return 0.0f;
- dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
+ dvert= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT);
vertnum= 0;
}
else
@@ -461,33 +463,30 @@ void ED_vgroup_select_by_name(Object *ob, char *name)
/* only in editmode */
static void vgroup_select_verts(Object *ob, int select)
{
- EditVert *eve;
+ BMVert *eve;
MDeformVert *dvert;
int i;
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- 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_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert && dvert->totweight){
for(i=0; i<dvert->totweight; i++){
if(dvert->dw[i].def_nr == (ob->actdef-1)){
- if(select) eve->f |= SELECT;
- else eve->f &= ~SELECT;
-
+ BM_Select(em->bm, eve, select);
break;
}
}
}
}
/* this has to be called, because this function operates on vertices only */
- if(select) EM_select_flush(em); // vertices to edges/faces
- else EM_deselect_flush(em);
-
- BKE_mesh_end_editmesh(me, em);
+ if(select) EDBM_selectmode_flush(em); // vertices to edges/faces
+ else EDBM_deselect_flush(em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -686,12 +685,11 @@ static void vgroup_delete_object_mode(Object *ob)
/* Remove the group */
BLI_freelinkN(&ob->defbase, dg);
}
-
/* only in editmode */
/* removes from active defgroup, if allverts==0 only selected vertices */
static void vgroup_active_remove_verts(Object *ob, int allverts)
{
- EditVert *eve;
+ BMVert *eve;
MDeformVert *dvert;
MDeformWeight *newdw;
bDeformGroup *dg, *eg;
@@ -703,19 +701,20 @@ static void vgroup_active_remove_verts(Object *ob, int allverts)
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- 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_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
- if(dvert && dvert->dw && ((eve->f & 1) || allverts)){
+ if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){
for(i=0; i<dvert->totweight; i++){
/* Find group */
eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
if(eg == dg){
dvert->totweight--;
- if(dvert->totweight){
- newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
+ if (dvert->totweight){
+ newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
@@ -725,7 +724,7 @@ static void vgroup_active_remove_verts(Object *ob, int allverts)
dvert->dw=newdw;
}
else{
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free (dvert->dw);
dvert->dw=NULL;
break;
}
@@ -733,7 +732,6 @@ static void vgroup_active_remove_verts(Object *ob, int allverts)
}
}
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -768,19 +766,19 @@ static void vgroup_delete_edit_mode(Object *ob)
/* Make sure that any verts with higher indices are adjusted accordingly */
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
MDeformVert *dvert;
- 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_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert)
for(i=0; i<dvert->totweight; i++)
if(dvert->dw[i].def_nr > (ob->actdef-1))
dvert->dw[i].def_nr--;
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type==OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -828,7 +826,7 @@ static void vgroup_delete_edit_mode(Object *ob)
static int vgroup_object_in_edit_mode(Object *ob)
{
if(ob->type == OB_MESH)
- return (((Mesh*)ob->data)->edit_mesh != NULL);
+ return (((Mesh*)ob->data)->edit_btmesh != NULL);
else if(ob->type == OB_LATTICE)
return (((Lattice*)ob->data)->editlatt != NULL);
@@ -869,7 +867,7 @@ static void vgroup_delete_all(Object *ob)
/* only in editmode */
static void vgroup_assign_verts(Object *ob, float weight)
{
- EditVert *eve;
+ BMVert *eve;
bDeformGroup *dg, *eg;
MDeformWeight *newdw;
MDeformVert *dvert;
@@ -879,16 +877,17 @@ static void vgroup_assign_verts(Object *ob, float weight)
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
- EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT);
+ if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
+ BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
/* Go through the list of editverts and assign them */
- 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_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
- if(dvert && (eve->f & 1)){
+ if(dvert && BM_TestHFlag(eve, BM_SELECT)) {
done=0;
/* See if this vert already has a reference to this group */
/* If so: Change its weight */
@@ -904,10 +903,10 @@ static void vgroup_assign_verts(Object *ob, float weight)
}
/* If not: Add the group and set its weight */
if(!done){
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
}
dvert->dw=newdw;
@@ -919,7 +918,6 @@ static void vgroup_assign_verts(Object *ob, float weight)
}
}
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -1320,4 +1318,3 @@ void OBJECT_OT_vertex_group_menu(wmOperatorType *ot)
ot->poll= vertex_group_poll;
ot->exec= vertex_group_menu_exec;
}
-
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 74ed6451d29..a1570810e94 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -1024,7 +1024,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(edit->emitter_field);
- totface=dm->getNumFaces(dm);
+ totface=dm->getNumTessFaces(dm);
totvert=dm->getNumVerts(dm);
edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
@@ -1036,7 +1036,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/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 1dc08a162b7..fd81e828bea 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -562,7 +562,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
continue;
}
- mface = CDDM_get_face(dm,nearest.index);
+ mface = CDDM_get_tessface(dm,nearest.index);
VecCopyf(v[0], CDDM_get_vert(dm,mface->v1)->co);
VecCopyf(v[1], CDDM_get_vert(dm,mface->v2)->co);
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index bddc5ed10e0..3e1e99a7a6a 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -7,7 +7,7 @@ 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 += ' ../../blenloader'
+incs += ' ../../blenloader ../../bmesh'
if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index a9023194271..e03a118e86e 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -51,6 +51,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_world.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
@@ -278,13 +279,15 @@ 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;
+ }
}
}
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -336,14 +339,15 @@ 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;
-
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+/*BMESH_TODO
if(em) {
if(select)
EM_select_by_material(em, ob->actcol-1);
else
EM_deselect_by_material(em, ob->actcol-1);
}
+*/
}
else if ELEM(ob->type, OB_CURVE, OB_SURF) {
ListBase *editnurb= ((Curve*)ob->data)->editnurb;
diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile
index 00698917be5..c88e53f5f97 100644
--- a/source/blender/editors/screen/Makefile
+++ b/source/blender/editors/screen/Makefile
@@ -42,6 +42,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I../../windowmanager
CPPFLAGS += -I../../blenloader
CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../bmesh
CPPFLAGS += -I../../blenlib
CPPFLAGS += -I../../makesdna
CPPFLAGS += -I../../makesrna
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
index 847a1cddfb4..97ce70ad71d 100644
--- a/source/blender/editors/screen/SConscript
+++ b/source/blender/editors/screen/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf'
incs += ' ../../blenloader ../../windowmanager ../../python ../../makesrna'
-incs += ' ../../render/extern/include'
+incs += ' ../../render/extern/include ../../bmesh'
incs += ' #/intern/guardedalloc #/extern/glew/include'
defs = ''
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index eeddeee25bf..fe29b574cf0 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -57,6 +57,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BKE_sound.h"
#include "WM_api.h"
@@ -214,7 +215,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;
}
@@ -241,36 +242,27 @@ int ED_operator_posemode(bContext *C)
int ED_operator_uvedit(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
if(obedit && obedit->type==OB_MESH)
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- if(em && (em->faces.first) && (CustomData_has_layer(&em->fdata, CD_MTFACE))) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
+ if (em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
return 1;
- }
- if(obedit)
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
int ED_operator_uvmap(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
if(obedit && obedit->type==OB_MESH)
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
- if(em && (em->faces.first)) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ if(em && (em->bm->totface))
return 1;
- }
- if(obedit)
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
@@ -2224,7 +2216,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
ScreenAnimData *sad= wt->customdata;
ScrArea *sa;
int sync;
-
+
/* sync, don't sync, or follow scene setting */
if(sad->flag & ANIMPLAY_FLAG_SYNC) sync= 1;
else if(sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync= 0;
@@ -2233,7 +2225,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
if(sync) {
/* skip frames */
int step = floor(wt->duration * FPS);
- if(sad->flag & ANIMPLAY_FLAG_REVERSE) // XXX does this option work with audio?
+ if (sad->flag & ANIMPLAY_FLAG_REVERSE) // XXX does this option work with audio?
scene->r.cfra -= step;
else
scene->r.cfra += step;
@@ -2241,7 +2233,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
}
else {
/* one frame +/- */
- if(sad->flag & ANIMPLAY_FLAG_REVERSE)
+ if (sad->flag & ANIMPLAY_FLAG_REVERSE)
scene->r.cfra--;
else
scene->r.cfra++;
@@ -2283,7 +2275,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
ED_update_for_newframe(C, 1);
-
+
sound_update_playing(C);
for(sa= screen->areabase.first; sa; sa= sa->next) {
@@ -2333,7 +2325,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
ScrArea *sa= CTX_wm_area(C);
int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
int sync= -1;
-
+
if(RNA_property_is_set(op->ptr, "sync"))
sync= (RNA_boolean_get(op->ptr, "sync"));
@@ -2345,7 +2337,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
/* update region if TIME_REGION was set, to leftmost 3d window */
ED_screen_animation_timer_update(C, stime->redraws);
- }
+ }
else {
int redraws = TIME_REGION|TIME_ALL_3D_WIN;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 7596191e781..6118fdb4a02 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -2956,11 +2956,11 @@ static void project_paint_begin(ProjPaintState *ps)
}
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 13fbd2179b8..9a2ce42e7db 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -90,9 +90,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];
@@ -103,7 +103,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/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 5afc4954c9c..4a45df9eb91 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -43,7 +43,8 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
-
+#include "BLI_memarena.h"
+#include "BLI_cellalloc.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
@@ -203,7 +204,7 @@ static unsigned int vpaint_get_current_col(VPaint *vp)
return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
}
-void do_shared_vertexcol(Mesh *me)
+static void do_shared_vertex_tesscol(Mesh *me)
{
/* if no mcol: do not do */
/* if tface: only the involved faces, otherwise all */
@@ -269,6 +270,63 @@ void do_shared_vertexcol(Mesh *me)
MEM_freeN(scolmain);
}
+void do_shared_vertexcol(Mesh *me)
+{
+ MLoop *ml = me->mloop;
+ MLoopCol *lcol = me->mloopcol;
+ MTexPoly *mtp = me->mtpoly;
+ MPoly *mp = me->mpoly;
+ float (*scol)[5];
+ int i;
+
+ /* if no mloopcol: do not do */
+ /* if mtexpoly: only the involved faces, otherwise all */
+
+ if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return;
+
+ scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol");
+
+ for (i=0; i<me->totloop; i++, ml++, lcol++) {
+ if (i >= mp->loopstart + mp->totloop) {
+ mp++;
+ if (mtp) mtp++;
+ }
+
+ if (mtp && !(mtp->mode & TF_SHAREDCOL))
+ continue;
+
+ scol[ml->v][0] += lcol->r;
+ scol[ml->v][1] += lcol->g;
+ scol[ml->v][2] += lcol->b;
+ scol[ml->v][3] += lcol->a;
+ scol[ml->v][4] += 1.0;
+ }
+
+ for (i=0; i<me->totvert; i++) {
+ if (!scol[i][4]) continue;
+
+ scol[i][0] /= scol[i][4];
+ scol[i][1] /= scol[i][4];
+ scol[i][2] /= scol[i][4];
+ scol[i][3] /= scol[i][4];
+ }
+
+ ml = me->mloop;
+ lcol = me->mloopcol;
+ for (i=0; i<me->totloop; i++, ml++, lcol++) {
+ if (!scol[ml->v][4]) continue;
+
+ lcol->r = scol[ml->v][0];
+ lcol->g = scol[ml->v][1];
+ lcol->b = scol[ml->v][2];
+ lcol->a = scol[ml->v][3];
+ }
+
+ MEM_freeN(scol);
+
+ do_shared_vertex_tesscol(me);
+}
+
void make_vertexcol(Scene *scene, int shade) /* single ob */
{
Object *ob;
@@ -285,21 +343,26 @@ void make_vertexcol(Scene *scene, int shade) /* single ob */
if(me==0) return;
/* copies from shadedisplist to mcol */
- if(!me->mcol) {
- CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
- mesh_update_customdata_pointers(me);
- }
+ if(!me->mcol)
+ CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
+ if (!me->mloopcol)
+ CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
+
+ mesh_update_customdata_pointers(me);
+
+ /*
if(shade)
shadeMeshMCol(scene, ob, me);
else
memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
-
+ */
+
DAG_id_flush_update(&me->id, OB_RECALC_DATA);
}
-static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
+static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
{
if(vp->vpaint_prev) {
MEM_freeN(vp->vpaint_prev);
@@ -307,10 +370,10 @@ static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
}
vp->tot= tot;
- if(mcol==NULL || tot==0) return;
+ if(lcol==NULL || tot==0) return;
- vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
- memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
+ vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev");
+ memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot);
}
@@ -333,10 +396,12 @@ static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
void clear_vpaint(Scene *scene, int selected)
{
Mesh *me;
- MFace *mf;
+ MFace *mf;
+ MPoly *mp;
+ MLoopCol *lcol;
Object *ob;
unsigned int paintcol, *mcol;
- int i;
+ int i, j;
ob= OBACT;
me= get_mesh(ob);
@@ -357,6 +422,18 @@ void clear_vpaint(Scene *scene, int selected)
mcol[3] = paintcol;
}
}
+
+ mp = me->mpoly;
+ lcol = me->mloopcol;
+ for (i=0; i<me->totpoly; i++, mp++) {
+ if (!(!selected || mp->flag & ME_FACE_SEL))
+ continue;
+
+ lcol = me->mloopcol + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, lcol++) {
+ *(int*)lcol = paintcol;
+ }
+ }
DAG_id_flush_update(&me->id, OB_RECALC_DATA);
}
@@ -853,13 +930,14 @@ static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float
/* else */
/* sets wp->weight to the closest weight value to vertex */
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
+#if 0
void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
{
ViewContext vc;
ToolSettings *ts= scene->toolsettings;
Object *ob= OBACT;
Mesh *me= get_mesh(ob);
- int index;
+ int index, i;
short mval[2], sco[2];
if (!me) return;
@@ -867,13 +945,13 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
// getmouseco_areawin(mval);
index= view3d_sample_backbuf(&vc, mval[0], mval[1]);
- if(index && index<=me->totface) {
- MFace *mface;
-
- mface= ((MFace *)me->mface) + index-1;
+ if(index && index<=me->totpoly) {
+ MPoly *mpoly;
+ mpoly= ((MPoly *)me->mpoly) + index-1;
if(mode==1) { /* sampe which groups are in here */
MDeformVert *dv;
+ MLoop *ml;
int a, totgroup;
totgroup= BLI_countlist(&ob->defbase);
@@ -881,28 +959,14 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
int totmenu=0;
int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
- dv= me->dvert+mface->v1;
- for(a=0; a<dv->totweight; a++) {
- if (dv->dw[a].def_nr<totgroup)
- groups[dv->dw[a].def_nr]= 1;
- }
- dv= me->dvert+mface->v2;
- for(a=0; a<dv->totweight; a++) {
+ ml = me->mloop+mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ dv = me->dvert+ml->v;
if (dv->dw[a].def_nr<totgroup)
groups[dv->dw[a].def_nr]= 1;
+
}
- dv= me->dvert+mface->v3;
- for(a=0; a<dv->totweight; a++) {
- if (dv->dw[a].def_nr<totgroup)
- groups[dv->dw[a].def_nr]= 1;
- }
- if(mface->v4) {
- dv= me->dvert+mface->v4;
- for(a=0; a<dv->totweight; a++) {
- if (dv->dw[a].def_nr<totgroup)
- groups[dv->dw[a].def_nr]= 1;
- }
- }
+
for(a=0; a<totgroup; a++)
if(groups[a]) totmenu++;
@@ -936,28 +1000,19 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
else {
DerivedMesh *dm;
MDeformWeight *dw;
- float w1, w2, w3, w4, co[3], fac;
+ MLoop *ml;
+ float w, co[3], fmin = 10000000.0f;
+ int loopi = mpoly->loopstart;
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
if(dm->getVertCo==NULL) {
//notice("Not supported yet");
}
else {
- /* calc 3 or 4 corner weights */
- dm->getVertCo(dm, mface->v1, co);
- project_short_noclip(ar, co, sco);
- w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
-
- dm->getVertCo(dm, mface->v2, co);
- project_short_noclip(ar, co, sco);
- w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
-
- dm->getVertCo(dm, mface->v3, co);
- project_short_noclip(ar, co, sco);
- w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
-
- if(mface->v4) {
- dm->getVertCo(dm, mface->v4, co);
+ /* find minimum distance */
+ ml = me->mloop + mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ dm->getVertCo(dm, ml->v, co);
project_short_noclip(ar, co, sco);
w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
}
@@ -980,8 +1035,13 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
if(mface->v4) {
dw= ED_vgroup_weight_get(me->dvert+mface->v4, ob->actdef-1);
if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
+>>>>>>> .merge-right.r23146
}
}
+
+ ml = me->mloop + loopi;
+ dw= get_defweight(me->dvert+ml->v, ob->actdef-1);
+ if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
}
dm->release(dm);
}
@@ -989,6 +1049,7 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
}
}
+#endif
static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, float paintweight, int vgroup_mirror)
{
@@ -1230,6 +1291,13 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
me= get_mesh(ob);
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
+ /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+ so instead we have to regenerate the tesselation faces altogether.*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata,
+ me->mvert, me->totface, me->totloop, me->totpoly);
+ mesh_update_customdata_pointers(me);
+ makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
+
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert)
ED_vgroup_data_create(&me->id);
@@ -1351,22 +1419,22 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(wp->flag & VP_COLINDEX) {
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
- if(mface->mat_nr!=ob->actcol-1) {
+ if(mpoly->mat_nr!=ob->actcol-1) {
indexar[index]= 0;
}
}
}
}
- if((G.f & G_FACESELECT) && me->mface) {
+ if((G.f & G_FACESELECT) && me->mpoly) {
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
- if((mface->flag & ME_FACE_SEL)==0) {
+ if((mpoly->flag & ME_FACE_SEL)==0) {
indexar[index]= 0;
}
}
@@ -1382,13 +1450,14 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
paintweight= ts->vgroup_weight;
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
-
- (me->dvert+mface->v1)->flag= 1;
- (me->dvert+mface->v2)->flag= 1;
- (me->dvert+mface->v3)->flag= 1;
- if(mface->v4) (me->dvert+mface->v4)->flag= 1;
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= me->mpoly + (indexar[index]-1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
+
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ (me->dvert+ml->v)->flag = 1;
+ }
if(wp->mode==VP_BLUR) {
MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = ED_vgroup_weight_verify;
@@ -1396,15 +1465,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(wp->flag & VP_ONLYVGROUP)
dw_func= ED_vgroup_weight_get;
- dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- if(mface->v4) {
- dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
+ ml = me->mloop + mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ dw = dw_func(me->dvert+ml->v, ob->actdef-1);
+ if (dw) {
+ paintweight += dw->weight;
+ totw++;
+ }
}
}
}
@@ -1415,40 +1482,18 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
-
- if((me->dvert+mface->v1)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v1)->flag= 0;
- }
-
- if((me->dvert+mface->v2)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v2)->flag= 0;
- }
-
- if((me->dvert+mface->v3)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v3)->flag= 0;
- }
-
- if((me->dvert+mface->v4)->flag) {
- if(mface->v4) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= me->mpoly + (indexar[index]-1);
+ MLoop *ml=me->mloop+mpoly->loopstart;
+ int i;
+
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ if ((me->dvert+ml->v)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*ml->v, mval);
if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror);
+ do_weight_paint_vertex(wp, ob, ml->v, alpha, paintweight, wpd->vgroup_mirror);
}
- (me->dvert+mface->v4)->flag= 0;
+ (me->dvert+ml->v)->flag= 0;
}
}
}
@@ -1551,7 +1596,7 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
return OPERATOR_FINISHED;
}
- if(me && me->mcol==NULL) make_vertexcol(scene, 0);
+ if(me && me->mloopcol==NULL) make_vertexcol(scene, 0);
/* toggle: end vpaint */
if(ob->mode & OB_MODE_VERTEX_PAINT) {
@@ -1620,14 +1665,60 @@ For future:
*/
+typedef struct polyfacemap_e {
+ struct polyfacemap_e *next, *prev;
+ int facenr;
+} polyfacemap_e;
+
typedef struct VPaintData {
ViewContext vc;
unsigned int paintcol;
int *indexar;
float *vertexcosnos;
float vpimat[3][3];
+
+ /*mpoly -> mface mapping*/
+ MemArena *arena;
+ ListBase *polyfacemap;
} VPaintData;
+static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me,
+ Object *ob, Scene *scene)
+{
+ MFace *mf;
+ polyfacemap_e *e;
+ int *origIndex;
+ int i;
+
+ vd->arena = BLI_memarena_new(1<<13);
+ BLI_memarena_use_calloc(vd->arena);
+
+ vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly);
+
+ /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+ so instead we have to regenerate the tesselation faces altogether.*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata,
+ me->mvert, me->totface, me->totloop, me->totpoly);
+ mesh_update_customdata_pointers(me);
+ makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
+
+ origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
+ mf = me->mface;
+
+ if (!origIndex)
+ return;
+
+ for (i=0; i<me->totface; i++, mf++, origIndex++) {
+ if (*origIndex == ORIGINDEX_NONE)
+ continue;
+
+ e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e));
+ e->facenr = i;
+
+ BLI_addtail(&vd->polyfacemap[*origIndex], e);
+ }
+}
+
static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event)
{
ToolSettings *ts= CTX_data_tool_settings(C);
@@ -1635,15 +1726,19 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
VPaint *vp= ts->vpaint;
struct VPaintData *vpd;
Object *ob= CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
Mesh *me;
float mat[4][4], imat[4][4];
/* context checks could be a poll() */
me= get_mesh(ob);
- if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
+ if(me==NULL || me->totpoly==0)
+ return OPERATOR_PASS_THROUGH;
- if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0);
- if(me->mcol==NULL) return OPERATOR_CANCELLED;
+ if(me->mloopcol==NULL)
+ make_vertexcol(CTX_data_scene(C), 0);
+ if(me->mloopcol==NULL)
+ return OPERATOR_CANCELLED;
/* make mode data storage */
vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
@@ -1653,9 +1748,10 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
vpd->indexar= get_indexarray();
vpd->paintcol= vpaint_get_current_col(vp);
+ vpaint_build_poly_facemap(vpd, me, ob, scene);
/* for filtering */
- copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
+ copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
/* some old cruft to sort out later */
Mat4MulMat4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
@@ -1705,6 +1801,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
Brush *brush = paint_brush(&vp->paint);
ViewContext *vc= &vpd->vc;
Object *ob= vc->obact;
+ polyfacemap_e *e;
Mesh *me= ob->data;
float mat[4][4];
int *indexar= vpd->indexar;
@@ -1726,7 +1823,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* which faces are involved */
if(vp->flag & VP_AREA) {
- totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size);
+ totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush->size);
}
else {
indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
@@ -1736,19 +1833,111 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
Mat4SwapMat4(vc->rv3d->persmat, mat);
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface)
- vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval);
+ if(vp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+
+ if(mpoly->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
}
+ if((G.f & G_FACESELECT) && me->mface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+ if((mpoly->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ }
+ }
+ }
+
Mat4SwapMat4(vc->rv3d->persmat, mat);
/* was disabled because it is slow, but necessary for blur */
if(vp->mode == VP_BLUR)
do_shared_vertexcol(me);
- ED_region_tag_redraw(vc->ar);
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+ MFace *mf;
+ MCol *mc;
+ MLoop *ml;
+ MLoopCol *mlc;
+ unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
+ unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
+ int i, j, alpha;
+
+ if(vp->mode==VP_BLUR) {
+ unsigned int blend[5] = {0};
+ char *col;
+
+ for (j=0; j<mpoly->totloop; j += 2) {
+ col = (char*)(lcol + j);
+ blend[0] += col[0];
+ blend[1] += col[1];
+ blend[2] += col[2];
+ blend[3] += col[3];
+ }
+
+ blend[0] /= mpoly->totloop;
+ blend[1] /= mpoly->totloop;
+ blend[2] /= mpoly->totloop;
+ blend[3] /= mpoly->totloop;
+ col = (char*)(blend + 4);
+ col[0] = blend[0];
+ col[1] = blend[1];
+ col[2] = blend[2];
+ col[3] = blend[3];
+
+ vpd->paintcol = *((unsigned int*)col);
+ }
+
+ ml = me->mloop + mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*ml->v, mval);
+ if(alpha) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, alpha);
+ }
+
+ #ifdef CPYCOL
+ #undef CPYCOL
+ #endif
+ #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
+
+ /*update vertex colors for tesselations incrementally,
+ rather then regenerating the tesselation altogether.*/
+ for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) {
+ mf = me->mface + e->facenr;
+ mc = me->mcol + e->facenr*4;
+
+ ml = me->mloop + mpoly->loopstart;
+ mlc = me->mloopcol + mpoly->loopstart;
+ for (j=0; j<mpoly->totloop; j++, ml++, mlc++) {
+ if (ml->v == mf->v1)
+ CPYCOL(mc, mlc);
+ else if (ml->v == mf->v2)
+ CPYCOL(mc+1, mlc);
+ else if (ml->v == mf->v3)
+ CPYCOL(mc+2, mlc);
+ else if (mf->v4 && ml->v == mf->v4)
+ CPYCOL(mc+3, mlc);
+
+ }
+ }
+ #undef CPYCOL
+ }
+ }
+
+ Mat4SwapMat4(vc->rv3d->persmat, mat);
+ do_shared_vertexcol(me);
+
+ ED_region_tag_redraw(vc->ar);
DAG_id_flush_update(ob->data, OB_RECALC_DATA);
}
@@ -1763,7 +1952,8 @@ static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
/* frees prev buffer */
copy_vpaint_prev(ts->vpaint, NULL, 0);
-
+ BLI_memarena_free(vpd->arena);
+
MEM_freeN(vpd);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 4f667ab7976..ca9656250c8 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1138,10 +1138,10 @@ static void sculpt_update_mesh_elements(bContext *C)
if((ss->multires = sculpt_multires_active(ob))) {
//DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
ss->totvert = dm->getNumVerts(dm);
- ss->totface = dm->getNumFaces(dm);
+ ss->totface = dm->getNumTessFaces(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_image/Makefile b/source/blender/editors/space_image/Makefile
index af15b1d9724..a55b4e58dfa 100644
--- a/source/blender/editors/space_image/Makefile
+++ b/source/blender/editors/space_image/Makefile
@@ -47,6 +47,7 @@ CPPFLAGS += -I../../makesrna
CPPFLAGS += -I../../imbuf
CPPFLAGS += -I../../python
CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I../../bmesh
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
# own include
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index 874549e6949..2b1d5589cb3 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../render/extern/include ../../makesrna'
+incs += ' ../../render/extern/include ../../makesrna ../../bmesh'
defs = []
diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c
index e0fd652bf92..3e15ae1f1f5 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_image/space_image.c b/source/blender/editors/space_image/space_image.c
index e64bb1a4209..9a4bab03534 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -50,6 +50,7 @@
#include "BKE_mesh.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -257,13 +258,13 @@ static void image_refresh(const bContext *C, ScrArea *sa)
if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin));
else if(obedit && obedit->type == OB_MESH) {
Mesh *me= (Mesh*)obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- MTFace *tf;
+ BMEditMesh *em= me->edit_btmesh;
+ MTexPoly *tf;
- if(em && EM_texFaceCheck(em)) {
+ if(em && EDBM_texFaceCheck(em)) {
sima->image= ima= NULL;
- tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */
+ tf = EDBM_get_active_mtexpoly(em, NULL, 1); /* partially selected face is ok */
if(tf && (tf->mode & TF_TEX)) {
/* don't need to check for pin here, see above */
@@ -273,8 +274,6 @@ static void image_refresh(const bContext *C, ScrArea *sa)
else sima->curtile= tf->tile;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
}
@@ -765,13 +764,9 @@ int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
return 0;
if(obedit && obedit->type == OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
- int ret;
-
- ret = EM_texFaceCheck(em);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
- BKE_mesh_end_editmesh(obedit->data, em);
- return ret;
+ return EDBM_texFaceCheck(em);
}
return 0;
@@ -784,13 +779,9 @@ int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
if(ED_space_image_show_paint(sima))
if(obedit && obedit->type == OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
- int ret;
-
- ret = EM_texFaceCheck(em);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
- BKE_mesh_end_editmesh(obedit->data, em);
- return ret;
+ return EDBM_texFaceCheck(em);
}
return 0;
diff --git a/source/blender/editors/space_info/Makefile b/source/blender/editors/space_info/Makefile
index 931c2f2097c..99ab1d2c514 100644
--- a/source/blender/editors/space_info/Makefile
+++ b/source/blender/editors/space_info/Makefile
@@ -47,6 +47,7 @@ CPPFLAGS += -I../../makesdna
CPPFLAGS += -I../../makesrna
CPPFLAGS += -I../../imbuf
CPPFLAGS += -I../../python
+CPPFLAGS += -I../../bmesh
CPPFLAGS += -I../../blenfont
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index 01268115687..ba1110274ff 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -4,7 +4,7 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf ../../blenfont'
-incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../bmesh ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
defs = []
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 60cac0a00fa..9261a2a5d8d 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -46,6 +46,7 @@
#include "BKE_mesh.h"
#include "BKE_particle.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "ED_armature.h"
#include "ED_mesh.h"
@@ -138,26 +139,16 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
static void stats_object_edit(Object *obedit, SceneStats *stats)
{
if(obedit->type==OB_MESH) {
- /* Mesh Edit */
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+
+ stats->totvert = em->bm->totvert;
+ stats->totvertsel = em->bm->totvertsel;
- for(eve= em->verts.first; eve; eve=eve->next) {
- stats->totvert++;
- if(eve->f & SELECT) stats->totvertsel++;
- }
- for(eed= em->edges.first; eed; eed=eed->next) {
- stats->totedge++;
- if(eed->f & SELECT) stats->totedgesel++;
- }
- for(efa= em->faces.first; efa; efa=efa->next) {
- stats->totface++;
- if(efa->f & SELECT) stats->totfacesel++;
- }
+ stats->totedge = em->bm->totedge;
+ stats->totedgesel = em->bm->totedgesel;
- EM_validate_selections(em);
+ stats->totface = em->bm->totface;
+ stats->totfacesel = em->bm->totfacesel;
}
else if(obedit->type==OB_ARMATURE){
/* Armature Edit */
diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript
index fd0dfe83852..5493e2d739f 100644
--- a/source/blender/editors/space_node/SConscript
+++ b/source/blender/editors/space_node/SConscript
@@ -14,7 +14,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
if env['CC'] == 'gcc':
#cf.append('-Werror')
pass
-
+
if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index 057c98a1d49..84420da9076 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'
incs += ' #/intern/smoke/extern'
incs += ' #source/kernel/gen_system'
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 365b9ff03f7..0d8e1381756 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -63,6 +63,7 @@
#include "BKE_paint.h"
#include "BKE_property.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -399,7 +400,7 @@ static void draw_textured_end()
glPopMatrix();
}
-static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr)
+static int draw_tface__set_draw_legacy(MTFace *tface, int has_vcol, int matnr)
{
if (tface && (tface->mode&TF_INVISIBLE)) return 0;
@@ -409,7 +410,7 @@ static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr)
} else if (tface && tface->mode&TF_OBCOL) {
glColor3ubv(Gtexdraw.obcol);
return 2; /* Don't set color */
- } else if (!mcol) {
+ } else if (!has_vcol) {
if (tface) glColor3f(1.0, 1.0, 1.0);
else {
Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
@@ -438,15 +439,15 @@ static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
static void add_tface_color_layer(DerivedMesh *dm)
{
MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
- MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
+ MFace *mface = dm->getTessFaceArray(dm);
MCol *finalCol;
int i,j;
- MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
- finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
- for(i=0;i<dm->getNumFaces(dm);i++) {
+ finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumTessFaces(dm),"add_tface_color_layer");
+ for(i=0;i<dm->getNumTessFaces(dm);i++) {
if (tface && (tface->mode&TF_INVISIBLE)) {
if( mcol )
memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4);
@@ -506,30 +507,53 @@ static void add_tface_color_layer(DerivedMesh *dm)
static int draw_tface_mapped__set_draw(void *userData, int index)
{
Mesh *me = (Mesh*)userData;
- MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
- MFace *mface = (me->mface)? &me->mface[index]: NULL;
- MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
- int matnr = me->mface[index].mat_nr;
- if (mface && mface->flag&ME_HIDE) return 0;
- return draw_tface__set_draw(tface, mcol, matnr);
+ MTexPoly *tpoly = (me->mtpoly)? &me->mtpoly[index]: NULL;
+ MPoly *mpoly = (me->mpoly)? &me->mpoly[index]: NULL;
+ MTFace mtf;
+ int matnr = me->mpoly[index].mat_nr;
+
+ if (mpoly && mpoly->flag&ME_HIDE) return 0;
+
+ memset(&mtf, 0, sizeof(mtf));
+ if (tpoly) {
+ mtf.flag = tpoly->flag;
+ mtf.tpage = tpoly->tpage;
+ mtf.transp = tpoly->transp;
+ mtf.mode = tpoly->mode;
+ mtf.tile = tpoly->tile;
+ mtf.unwrap = tpoly->unwrap;
+ }
+
+ return draw_tface__set_draw(&mtf, CustomData_has_layer(&me->ldata, CD_MLOOPCOL), matnr);
}
static int draw_em_tf_mapped__set_draw(void *userData, int index)
{
- EditMesh *em = userData;
- EditFace *efa= EM_get_face_for_index(index);
- MTFace *tface;
- MCol *mcol;
- int matnr;
+ BMEditMesh *em = userData;
+ BMFace *efa= EDBM_get_face_for_index(em, index);
+ MTexPoly *tpoly;
+ MTFace mtf;
+ int matnr, has_vcol;
- if (efa==NULL || efa->h)
+ if (efa==NULL || BM_TestHFlag(efa, BM_HIDDEN))
return 0;
- tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+ tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ has_vcol = CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
matnr = efa->mat_nr;
- return draw_tface__set_draw(tface, mcol, matnr);
+ memset(&mtf, 0, sizeof(mtf));
+
+ if (tpoly) {
+ mtf.flag = tpoly->flag;
+ mtf.tpage = tpoly->tpage;
+ mtf.transp = tpoly->transp;
+ mtf.mode = tpoly->mode;
+ mtf.tile = tpoly->tile;
+ mtf.unwrap = tpoly->unwrap;
+ }
+
+ return draw_tface__set_draw(&mtf, has_vcol, matnr);
}
static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
@@ -643,7 +667,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o
if(ob->mode & OB_MODE_EDIT) {
glColor4f(1.0f,1.0f,1.0f,1.0f);
- dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_mesh);
+ dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_btmesh);
} else if(faceselect) {
if(ob->mode & OB_MODE_WEIGHT_PAINT)
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 78dd53e7271..dfbdce14992 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -94,6 +94,8 @@
#include "BKE_smoke.h"
#include "BKE_unit.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
#include "smoke_API.h"
#include "BIF_gl.h"
@@ -232,7 +234,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));
@@ -1307,16 +1309,21 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
* use the object matrix in the useual way */
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};
+ float co2[3];
+
+ VECCOPY(co2, co);
+
+ Mat4MulVecfl(data->vc.obedit->obmat, co2);
if (data->clipVerts) {
- view3d_project_short_clip(data->vc.ar, co, s);
+ project_short(data->vc.ar, co2, s);
} else {
- view3d_project_short_noclip(data->vc.ar, co, s);
+ project_short_noclip(data->vc.ar, co2, s);
}
if (s[0]!=IS_CLIPPED)
@@ -1324,36 +1331,43 @@ 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];
+ float v1_co[3], v2_co[3];
+
+ VECCOPY(v1_co, v0co);
+ VECCOPY(v2_co, v1co);
- if (eed->h==0) {
+ Mat4MulVecfl(data->vc.obedit->obmat, v1_co);
+ Mat4MulVecfl(data->vc.obedit->obmat, v2_co);
+
+ 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]);
+ project_short(data->vc.ar, v1_co, s[0]);
+ project_short(data->vc.ar, v2_co, s[1]);
} else {
- view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
- view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
+ project_short_noclip(data->vc.ar, v1_co, s[0]);
+ project_short_noclip(data->vc.ar, v2_co, s[1]);
if (data->clipVerts==2) {
if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
@@ -1366,48 +1380,51 @@ 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;
+ float cent2[3];
+ BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
short s[2];
- if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
- view3d_project_short_clip(data->vc.ar, cent, s);
+ VECCOPY(cent2, cent);
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
+ Mat4MulVecfl(data->vc.obedit->obmat, cent2);
+ project_short(data->vc.ar, cent2, 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);
}
@@ -1471,46 +1488,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)
{
- ToolSettings *ts= ((Scene *)userData)->toolsettings;
- EditFace *efa = EM_get_face_for_index(index);
+ Scene *scene= ((void **)userData)[0];
+ BMEditMesh *em = ((void **)userData)[1];
+ BMFace *efa = EDBM_get_face_for_index(em, index);
+ ToolSettings *ts= scene->toolsettings;
- 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 *em, Scene *scene, DerivedMesh *dm)
{
+ void *ptrs[2] = {scene, em};
+
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) {
@@ -1524,20 +1549,78 @@ 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();
+}
+
+/* check if all verts of the face are pinned */
+static int check_pinned_face(BMesh *bm, BMFace *efa)
+{
+ BMIter vfiter;
+ BMVert *v;
+ int vcount = 0;
+
+ BM_ITER(v, &vfiter, bm, BM_VERTS_OF_FACE, efa) {
+ if(BM_TestHFlag(v, BM_PINNED)) vcount ++;
+ }
+
+ if( vcount == efa->len) return 1;
+ return 0;
+}
+
+static void draw_dm_vert_pins__mapFunc(void *userData, int index, float *co)
+{
+ struct {BMEditMesh *em; Mesh *me;} *data = userData;
+ BMVert *eve = EDBM_get_vert_for_index(data->em, index);
+ BMFace *fv;
+ BMIter fviter;
+ float vsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ int small=0;
+
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if (BM_TestHFlag(eve, BM_PINNED)) {
+ BM_ITER(fv, &fviter, data->em->bm, BM_FACES_OF_VERT, eve) {
+ small += check_pinned_face(data->em->bm, fv);
+ }
+ if(small == 0) {
+ bglEnd();
+ glPointSize(vsize*1.5);
+ glBegin(GL_POINTS);
+ glVertex3fv(co);
+ }
+ else {
+ bglEnd();
+ glPointSize(vsize*0.5);
+ glBegin(GL_POINTS);
+ glVertex3fv(co);
+ }
+ }
+ }
+}
+
+static void draw_dm_vert_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me)
+{
+ struct { BMEditMesh *em; Mesh *me;} data;
+
+ data.em = em;
+ data.me = me;
+
+ dm->foreachMappedVert(dm, draw_dm_vert_pins__mapFunc, &data);
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);
@@ -1575,13 +1658,18 @@ typedef struct {
} EditMeshDerivedMesh;
#endif
-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;
//GPUBuffer *buffer;
//float *varray;
data.sel = sel;
data.eve_act = eve_act;
+ data.em = em;
+
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
+ bglEnd();
#if 0
/* first come the unselected vertices, then the selected */
@@ -1640,16 +1728,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;
@@ -1664,13 +1754,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);
}
@@ -1678,24 +1770,24 @@ 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)[0], 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);
+ BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], 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];
+ unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
+ unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
glColor4ub( col0[0] + (col1[0]-col0[0])*t,
col0[1] + (col1[1]-col0[1])*t,
@@ -1703,9 +1795,9 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i
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] = {baseCol, selCol};
+ unsigned char *cols[3] = {em, baseCol, selCol};
#if 0
int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
@@ -1760,25 +1852,75 @@ static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, un
/* 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 !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
+}
+
+static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
+}
+
+/* Draw only pinned edges */
+static int draw_dm_edges_pins__setDrawOptions(void *userData, int index)
+{
+ struct {BMEditMesh *em; Mesh *me;} *data = userData;
+
+ BMEdge *eed = EDBM_get_edge_for_index(data->em, index);
+ BMIter feiter;
+ BMFace *fe;
+
+ int fcount, fpcount = 0;
+ int pin = 0;
+
+ /* If pinned faces are drawn then only draw pinned edges at the borders.
+ This looks way better and the user still has all the info he needs. */
+ if(data->me->drawflag & ME_DRAW_PINS) {
+ if( BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED) ) {
+ pin = 1;
- return (eed->h==0 && eed->seam);
+ fcount = 0;
+ BM_ITER(fe, &feiter, data->em->bm, BM_FACES_OF_EDGE, eed) {
+ fcount ++;
+ fpcount += check_pinned_face(data->em->bm, fe);
+ }
+ }
+ }
+ else {
+ pin = BM_TestHFlag(eed->v1, BM_PINNED) && BM_TestHFlag(eed->v2, BM_PINNED);
+ }
+
+ if( !BM_TestHFlag(eed, BM_HIDDEN)) {
+ /* Edges with at least one adherent pinned face are considered borders.
+ If there are more than two adherent faces overall of which at least two are pinned it's also consideres a border. */
+ if( fpcount == 2 && fcount <= 2) {
+ return 0; }
+ else {
+ return pin; }
+ }
}
-static void draw_dm_edges_seams(DerivedMesh *dm)
+
+static void draw_dm_edges_pins(BMEditMesh *em, DerivedMesh *dm, Mesh *me)
{
- dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
+ struct { BMEditMesh *em; Mesh *me;} data;
+
+ data.em = em;
+ data.me = me;
+
+ dm->drawMappedEdges(dm, draw_dm_edges_pins__setDrawOptions, &data);
}
/* 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);
}
@@ -1786,18 +1928,35 @@ 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; Mesh *me;} *data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->em, index);
unsigned char *col;
+ BMIter vfiter;
+ BMVert *v;
+ int vcount, pin=0;
+ int opac = UI_GetThemeValue(TH_PIN_OPAC);
- if (efa->h==0) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
+
+ /* Check if all verts of a face are pinned. If so, then display it in a darker shade. */
+ if(data->me->drawflag & ME_DRAW_PINS)
+ pin = check_pinned_face(data->em->bm, efa);
+
if (efa == data->efa_act) {
- glColor4ubv(data->cols[2]);
+ if(pin==0) { glColor4ubv(data->cols[2]); }
+ else {
+ col = data->cols[2];
+ glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55);
+ }
+
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);
+
+ if(pin==0) { glColor4ubv(col); }
+ else { glColor4ub(col[0]-col[0]*0.9, col[1]-col[1]*0.9, col[2]-col[2]*0.9, opac*2.55); }
+
return 1;
}
}
@@ -1805,11 +1964,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, Mesh *me)
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
+
//EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
- EditFace *efa;
+ BMFace *efa;
unsigned char *col;
GPUBuffer *buffer;
unsigned char *varray;
@@ -1817,11 +1978,13 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned
int i, draw=0;
int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
data.cols[0] = baseCol;
+ data.em = em;
data.cols[1] = selCol;
data.cols[2] = actCol;
data.efa_act = efa_act;
+ data.me = me;
-
+#if 0 //BMESH_TODO
buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
int prevdraw = 0;
@@ -2035,34 +2198,38 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned
}
GPU_buffer_unbind();
} else {
+#endif
dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
+
+#if 0
}
GPU_buffer_free( buffer, 0 );
+#endif
}
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 {
@@ -2071,26 +2238,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);
}
}
@@ -2104,7 +2271,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;
@@ -2141,13 +2309,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) {
@@ -2161,7 +2329,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;
@@ -2194,21 +2364,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);
}
}
@@ -2219,8 +2389,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, UnitSettings *unit)
+static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
+ Object *ob, BMEditMesh *em, UnitSettings *unit)
{
+#if 0
Mesh *me= ob->data;
EditEdge *eed;
EditFace *efa;
@@ -2392,13 +2564,14 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
glEnable(GL_DEPTH_TEST);
bglPolygonOffset(rv3d->dist, 0.0f);
}
+#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;
}
@@ -2408,31 +2581,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;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->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)) {
@@ -2440,7 +2615,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);
@@ -2451,9 +2626,10 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
}
else {
/* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
- GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
+ GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->tottri*3*2, 0 );
float *varray;
- EditFace *efa;
+ BMFace *efa;
+ BMLoop **ls;
int i, curmat = 0, draw = 0;
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
@@ -2469,9 +2645,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
GPU_interleaved_setup( buffer, datatype );
glShadeModel(GL_SMOOTH);
varray = GPU_buffer_lock_stream( buffer );
- for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
- int drawSmooth = (efa->flag & ME_SMOOTH);
- if( efa->h == 0 ) {
+ for (i=0; i<em->tottri; i++) {
+ int drawSmooth;
+
+ ls = em->looptris[i];
+ efa = ls[0]->f;
+ drawSmooth = BM_TestHFlag(efa, BM_SMOOTH);
+
+ if( !BM_TestHFlag(efa, BM_HIDDEN) ) {
curmat = efa->mat_nr+1;
draw = 1;
}
@@ -2494,48 +2675,26 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
}
if( draw != 0 ) {
if(!drawSmooth) {
- VECCOPY(&varray[numfaces*18],efa->v1->co);
- VECCOPY(&varray[numfaces*18+3],efa->n);
+ VECCOPY(&varray[numfaces*18], ls[0]->v->co);
+ VECCOPY(&varray[numfaces*18+3], efa->no);
- VECCOPY(&varray[numfaces*18+6],efa->v2->co);
- VECCOPY(&varray[numfaces*18+9],efa->n);
+ VECCOPY(&varray[numfaces*18+6], ls[1]->v->co);
+ VECCOPY(&varray[numfaces*18+9], efa->no);
- VECCOPY(&varray[numfaces*18+12],efa->v3->co);
- VECCOPY(&varray[numfaces*18+15],efa->n);
+ VECCOPY(&varray[numfaces*18+12], ls[2]->v->co);
+ VECCOPY(&varray[numfaces*18+15], efa->no);
numfaces++;
- if( efa->v4 ) {
- VECCOPY(&varray[numfaces*18],efa->v3->co);
- VECCOPY(&varray[numfaces*18+3],efa->n);
-
- VECCOPY(&varray[numfaces*18+6],efa->v4->co);
- VECCOPY(&varray[numfaces*18+9],efa->n);
-
- VECCOPY(&varray[numfaces*18+12],efa->v1->co);
- VECCOPY(&varray[numfaces*18+15],efa->n);
- numfaces++;
- }
}
else {
- VECCOPY(&varray[numfaces*18],efa->v1->co);
- VECCOPY(&varray[numfaces*18+3],efa->v1->no);
+ VECCOPY(&varray[numfaces*18],ls[0]->v->co);
+ VECCOPY(&varray[numfaces*18+3],ls[0]->v->no);
- VECCOPY(&varray[numfaces*18+6],efa->v2->co);
- VECCOPY(&varray[numfaces*18+9],efa->v2->no);
+ VECCOPY(&varray[numfaces*18+6],ls[1]->v->co);
+ VECCOPY(&varray[numfaces*18+9],ls[1]->v->no);
- VECCOPY(&varray[numfaces*18+12],efa->v3->co);
- VECCOPY(&varray[numfaces*18+15],efa->v3->no);
+ VECCOPY(&varray[numfaces*18+12],ls[2]->v->co);
+ VECCOPY(&varray[numfaces*18+15],ls[2]->v->no);
numfaces++;
- if( efa->v4 ) {
- VECCOPY(&varray[numfaces*18],efa->v3->co);
- VECCOPY(&varray[numfaces*18+3],efa->v3->no);
-
- VECCOPY(&varray[numfaces*18+6],efa->v4->co);
- VECCOPY(&varray[numfaces*18+9],efa->v4->no);
-
- VECCOPY(&varray[numfaces*18+12],efa->v1->co);
- VECCOPY(&varray[numfaces*18+15],efa->v1->no);
- numfaces++;
- }
}
}
prevdraw = draw;
@@ -2592,7 +2751,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, me);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2607,7 +2766,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, me);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2619,14 +2778,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);
@@ -2636,20 +2795,30 @@ 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);
+ }
+
+ if(me->drawflag & ME_DRAW_PINS) {
+ UI_ThemeColor(TH_PIN);
+ glLineWidth(2);
+
+ draw_dm_edges_pins(em, cageDM, me);
+
+ glColor3ub(0,0,0);
+ glLineWidth(1);
}
- 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);
@@ -2658,11 +2827,15 @@ 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_PINS) {
+ UI_ThemeColor(TH_PIN);
+ draw_dm_vert_pins(em, cageDM, me);
}
if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
@@ -2675,7 +2848,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
GPU_disable_material();
}
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
/* Mesh drawing routines */
@@ -2730,7 +2903,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)
@@ -2925,7 +3098,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) {
@@ -2937,9 +3110,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) {
@@ -6005,44 +6178,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;
@@ -6053,9 +6231,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);
@@ -6063,23 +6241,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);
}
}
@@ -6087,7 +6268,11 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot
{
Mesh *me = userData;
- if (!(me->mface[index].flag&ME_HIDE)) {
+ /*sanity check*/
+ if (index >= me->totpoly)
+ return 0;
+
+ if (!(me->mpoly[index].flag&ME_HIDE)) {
return 1;
} else {
return 0;
@@ -6118,7 +6303,7 @@ static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob)
if( !GPU_buffer_legacy(dm) ) {
int *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
int ind;
- colors = MEM_mallocN(dm->getNumFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid");
+ colors = MEM_mallocN(dm->getNumTessFaces(dm)*sizeof(MCol)*4,"bbs_mesh_solid");
for(i=0;i<dm->getNumFaces(dm);i++) {
if( index != 0 )
ind = index[i];
@@ -6163,36 +6348,36 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
{
if(ob->mode & OB_MODE_EDIT) {
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);
}
@@ -6218,7 +6403,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
int glsl;
if(ob->mode & OB_MODE_EDIT)
- 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 0cdf849d453..c50aa4fc2ed 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -70,6 +70,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
@@ -167,31 +168,30 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, 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;
@@ -215,8 +215,6 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, 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 c0a0241c74c..95900e6faa3 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -65,6 +65,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"
@@ -1680,12 +1681,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
View3D *v3d= sa->spacedata.first;
Object *obedit = CTX_data_edit_object(C);
Object *ob = CTX_data_active_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
int bit, ctrl= win->eventstate->ctrl, shift= win->eventstate->shift;
PointerRNA props_ptr;
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 */
@@ -1743,7 +1744,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_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Vertex");
}
@@ -1752,12 +1753,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_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Edge");
}
@@ -1766,12 +1767,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_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Face");
}
@@ -1859,9 +1860,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)
@@ -2163,7 +2161,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)");
@@ -2180,8 +2178,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
xco+= XIC;
uiBlockEndAlign(block);
header_xco_step(ar, &xco, &yco, &maxco, XIC);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
uiBlockBeginAlign(block);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 8dc7d6a0518..eb85c4ff722 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -64,6 +64,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "RE_pipeline.h" // make_stars
@@ -80,10 +81,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 "ED_mball.h"
#include "UI_interface.h"
@@ -152,43 +153,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;
-
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->h==0) {
- if(EM_check_backbuf(index)) {
- eve->f = select?(eve->f|1):(eve->f&~1);
+ BMVert *eve;
+ BMIter iter;
+ int index= bm_wireoffs;
+
+ 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(EDBM_check_backbuf(index)) {
+ 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;
-
- for(eed= em->edges.first; eed; eed= eed->next, index++) {
- if(eed->h==0) {
- if(EM_check_backbuf(index)) {
- EM_select_edge(eed, select);
+ BMEdge *eed;
+ BMIter iter;
+ int index= bm_solidoffs;
+
+ 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(EDBM_check_backbuf(index)) {
+ 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) {
- if(EM_check_backbuf(index)) {
- EM_select_face_fgon(em, efa, select);
+ 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(EDBM_check_backbuf(index)) {
+ BM_Select_Face(em->bm, efa, select);
}
}
}
@@ -201,7 +208,7 @@ void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
if (mface) {
for(a=1; a<=me->totface; a++, mface++) {
- if(EM_check_backbuf(a)) {
+ if(EDBM_check_backbuf(a)) {
mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL);
}
}
@@ -402,53 +409,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;
@@ -463,14 +469,14 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- 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;
@@ -482,7 +488,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 {
@@ -491,7 +497,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
@@ -658,7 +664,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);
@@ -728,6 +734,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 */
@@ -754,7 +766,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;
@@ -777,7 +789,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", "");
}
@@ -1285,43 +1297,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;
@@ -1330,17 +1346,17 @@ 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);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- 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;
@@ -1352,7 +1368,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 {
@@ -1362,7 +1378,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)
@@ -1402,7 +1418,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_GEOM|ND_SELECT, obedit->data);
@@ -1488,7 +1504,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);
@@ -1574,6 +1589,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)
@@ -1609,8 +1629,8 @@ 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);
- Object *obact= CTX_data_active_object(C);
short extend= RNA_boolean_get(op->ptr, "extend");
+ Object *obact= CTX_data_active_object(C);
short center= RNA_boolean_get(op->ptr, "center");
short enumerate= RNA_boolean_get(op->ptr, "enumerate");
@@ -1661,38 +1681,37 @@ void VIEW3D_OT_select(wmOperatorType *ot)
/* -------------------- 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;
Object *ob= vc->obact;
@@ -1700,11 +1719,11 @@ 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));
- EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE);
- EM_free_backbuf();
+ //bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ //BMESH_TODO EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE);
+ //EDBM_free_backbuf();
// XXX object_tface_flags_changed(OBACT, 0);
}
@@ -1712,17 +1731,17 @@ 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));
+ bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
-
data.select = selecting;
data.mval[0] = mval[0];
data.mval[1] = mval[1];
data.radius = rad;
+ data.vc = vc;
- if(ts->selectmode & SCE_SELECT_VERTEX) {
+ if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) {
if(bbsel) {
EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
} else {
@@ -1730,7 +1749,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 {
@@ -1738,7 +1757,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 {
@@ -1746,8 +1765,8 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
}
}
- EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_free_backbuf();
+ 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 767f18649fa..128597d4d5f 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"
@@ -107,10 +108,10 @@ static void special_transvert_update(Scene *scene, Object *obedit)
if(obedit) {
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
-
+
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(eed, BM_HIDDEN) && BM_TestHFlag(eed, 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(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(&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++;
}
}
@@ -302,7 +330,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
int totmalloc= 0;
for(nu= cu->editnurb->first; nu; nu= nu->next) {
- if(nu->type == CU_BEZIER)
+ if((nu->type & 7)==CU_BEZIER)
totmalloc += 3*nu->pntsu;
else
totmalloc += nu->pntsu*nu->pntsv;
@@ -311,7 +339,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
nu= cu->editnurb->first;
while(nu) {
- if(nu->type == CU_BEZIER) {
+ if((nu->type & 7)==CU_BEZIER) {
a= nu->pntsu;
bezt= nu->bezt;
while(a--) {
@@ -514,7 +542,7 @@ static int snap_sel_to_grid(bContext *C, wmOperator *op)
/* auto-keyframing */
// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
}
else {
ob->recalc |= OB_RECALC_OB;
@@ -555,7 +583,6 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Selection to Grid";
- ot->description= "Snap selected item(s) to nearest grid node.";
ot->idname= "VIEW3D_OT_snap_selected_to_grid";
/* api callbacks */
@@ -641,7 +668,7 @@ static int snap_sel_to_curs(bContext *C, wmOperator *op)
/* auto-keyframing */
// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
}
else {
ob->recalc |= OB_RECALC_OB;
@@ -681,7 +708,6 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Selection to Cursor";
- ot->description= "Snap selected item(s) to cursor.";
ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
/* api callbacks */
@@ -717,7 +743,6 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Cursor to Grid";
- ot->description= "Snap cursor to nearest grid node.";
ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
/* api callbacks */
@@ -824,7 +849,6 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Cursor to Selected";
- ot->description= "Snap cursor to center of selected item(s).";
ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
/* api callbacks */
@@ -850,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);
@@ -874,7 +898,6 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Cursor to Active";
- ot->description= "Snap cursor to active item.";
ot->idname= "VIEW3D_OT_snap_cursor_to_active";
/* api callbacks */
@@ -1033,7 +1056,7 @@ static int snap_selected_to_center(bContext *C, wmOperator *op)
/* auto-keyframing */
ob->pose->flag |= POSE_DO_UNLOCK;
// XXX autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_id_flush_update(ob->data, OB_RECALC_DATA);
}
else {
ob->recalc |= OB_RECALC_OB;
@@ -1074,7 +1097,6 @@ void VIEW3D_OT_snap_selected_to_center(wmOperatorType *ot)
/* identifiers */
ot->name= "Snap Selection to Center";
- ot->description= "Snap selected items to selections geometric center.";
ot->idname= "VIEW3D_OT_snap_selected_to_center";
/* api callbacks */
@@ -1141,7 +1163,6 @@ void VIEW3D_OT_snap_menu(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Snap Menu";
- ot->description= "Display snap menu.";
ot->idname= "VIEW3D_OT_snap_menu";
/* api callbacks */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 8b378f05eb2..8aafe24e702 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -623,8 +623,8 @@ void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
{
float vec4[4];
- adr[0]= IS_CLIPPED;
VECCOPY(vec4, vec);
+ adr[0]= IS_CLIPPED;
vec4[3]= 1.0;
Mat4MulVec4fl(mat, vec4);
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 4c24d366162..7128bd9c6a9 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -3947,8 +3947,9 @@ int BoneEnvelope(TransInfo *t, short mval[2])
static int createSlideVerts(TransInfo *t)
{
+#if 0
Mesh *me = t->obedit->data;
- EditMesh *em = me->edit_mesh;
+ BMEditMesh *em = me->edit_btmesh;
EditFace *efa;
EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
EditVert *ev, *nearest = NULL;
@@ -4415,10 +4416,12 @@ static int createSlideVerts(TransInfo *t)
t->customData = sld;
return 1;
+#endif
}
void freeSlideVerts(TransInfo *t)
{
+#if 0
TransDataSlideUv *suv;
SlideData *sld = t->customData;
int uvlay_idx;
@@ -4447,6 +4450,7 @@ void freeSlideVerts(TransInfo *t)
MEM_freeN(sld);
t->customData = NULL;
+#endif
}
void initEdgeSlide(TransInfo *t)
@@ -4478,6 +4482,7 @@ void initEdgeSlide(TransInfo *t)
int doEdgeSlide(TransInfo *t, float perc)
{
+#if 0
Mesh *me= t->obedit->data;
EditMesh *em = me->edit_mesh;
SlideData *sld = t->customData;
@@ -4586,7 +4591,7 @@ int doEdgeSlide(TransInfo *t, float perc)
}
}
-
+#endif
return 1;
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 496a9665371..764256c476d 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"
@@ -138,6 +139,7 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
+#include "BLI_array.h"
//#include "editmesh.h"
//
@@ -148,6 +150,7 @@
extern ListBase editelems;
#include "transform.h"
+#include "bmesh.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -1890,22 +1893,54 @@ 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);
}
+#define VertsToTransData(t, td, em, eve) \
+ td->flag = 0;\
+ td->loc = eve->co;\
+ VECCOPY(td->center, td->loc);\
+ if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))\
+ get_face_center(td->center, em, eve);\
+ VECCOPY(td->iloc, td->loc);\
+ VECCOPY(td->axismtx[2], eve->no);\
+ td->axismtx[0][0] =\
+ td->axismtx[0][1] =\
+ td->axismtx[0][2] =\
+ td->axismtx[1][0] =\
+ td->axismtx[1][1] =\
+ td->axismtx[1][2] = 0.0f;\
+ td->ext = NULL;\
+ td->val = NULL;\
+ td->extra = NULL;\
+ if (t->mode == TFM_BWEIGHT) {\
+ td->val = &(eve->bweight);\
+ td->ival = eve->bweight;\
+ }
+
+#if 0
//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)
+inline void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve)
{
td->flag = 0;
//if(key)
@@ -1935,6 +1970,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert
td->ival = eve->bweight;
}
}
+#endif
/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
@@ -1971,13 +2007,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);
@@ -2006,17 +2042,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 */
@@ -2074,7 +2111,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) {
@@ -2106,13 +2143,16 @@ 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;
+ int count=0, countsel=0, a, totleft, *selstate = NULL;
+ BLI_array_declare(selstate);
int propmode = t->flag & T_PROP_EDIT;
int mirror = 0;
@@ -2123,36 +2163,56 @@ 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++;
+ /* now we can count. we store selection state in selstate, since
+ get_crazy_mapped_editverts messes up the index state of the
+ verts*/
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ BLI_array_growone(selstate);
+
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(BMINDEX_GET(eve)) {
+ selstate[a] = 1;
+ countsel++;
+ }
if(propmode) count++;
}
}
@@ -2161,10 +2221,10 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
if (countsel==0) return;
/* check active */
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->selected.last;
if ( ese->type == EDITVERT ) {
- eve_act = (EditVert *)ese->data;
+ eve_act = (BMVert *)ese->data;
}
}
@@ -2174,7 +2234,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)");
@@ -2182,7 +2242,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) {
@@ -2190,7 +2250,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
@@ -2211,8 +2271,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(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && selstate[a] && eve->co[0]!=0.0f) {
if(eve->co[0]<0.0f)
{
t->mirror = -1;
@@ -2223,36 +2284,44 @@ 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 || selstate[a]) {
+ VertsToTransData(t, tob, bm, eve);
+
+ /* pinned */
+ if(BM_TestHFlag(eve,BM_PINNED)) tob->flag |= TD_SKIP;
/* selected */
- if(eve->f1) tob->flag |= TD_SELECTED;
+ if(selstate[a]) 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)
@@ -2261,7 +2330,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
else
Mat3MulMat3(mat, mtx, qmat);
}
- else
+ else*/
Mat3MulMat3(mat, mtx, defmats[a]);
Mat3Inv(imat, mat);
@@ -2275,10 +2344,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++;
}
}
@@ -2300,11 +2371,14 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
MEM_freeN(vectors);
MEM_freeN(nears);
}
+
/* crazy space free */
if(quats)
MEM_freeN(quats);
if(defmats)
MEM_freeN(defmats);
+
+ BLI_array_free(selstate);
}
/* *** NODE EDITOR *** */
@@ -2443,30 +2517,33 @@ static void createTransUVs(bContext *C, TransInfo *t)
Scene *scene = CTX_data_scene(C);
TransData *td = NULL;
TransData2D *td2d = NULL;
- MTFace *tf;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
int count=0, countsel=0;
int propmode = t->flag & T_PROP_EDIT;
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
- EditFace *efa;
-
if(!ED_uvedit_test(t->obedit)) return;
/* count */
- for (efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ if(!uvedit_face_visible(scene, ima, efa, tf)) {
+ BMINDEX_SET(efa, 0);
+ continue;
+ }
+
+ BMINDEX_SET(efa, 1);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l))
+ countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
- if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
if(propmode)
- count += (efa->v4)? 4: 3;
- } else {
- efa->tmp.p = NULL;
+ count += efa->len;
}
}
@@ -2485,20 +2562,17 @@ static void createTransUVs(bContext *C, TransInfo *t)
td= t->data;
td2d= t->data2d;
- for (efa= em->faces.first; efa; efa= efa->next) {
- if ((tf=(MTFace *)efa->tmp.p)) {
- if (propmode) {
- UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
- UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
- UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
- if(efa->v4)
- UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
- } else {
- if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
- if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
- if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (!propmode && !uvedit_uv_selected(em, scene, l))
+ continue;
+
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_selected(em, scene, l));
}
}
@@ -4773,7 +4847,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 8dc71710d82..66b46ab5b96 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -85,6 +85,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"
@@ -126,19 +127,19 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3])
if (t->persp != V3D_ORTHO)
{
float p1[4], p2[4];
-
+
VECCOPY(p1, coord);
p1[3] = 1.0f;
VECCOPY(p2, p1);
p2[3] = 1.0f;
Mat4MulVec4fl(t->viewmat, p2);
-
+
p2[0] = 2.0f * p2[0];
p2[1] = 2.0f * p2[1];
p2[2] = 2.0f * p2[2];
-
+
Mat4MulVec4fl(t->viewinv, p2);
-
+
VecSubf(vec, p1, p2);
}
else {
@@ -154,11 +155,11 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
ModifierData *md= ob->modifiers.first;
float tolerance[3] = {0.0f, 0.0f, 0.0f};
int axis = 0;
-
+
for (; md; md=md->next) {
if (md->type==eModifierType_Mirror) {
MirrorModifierData *mmd = (MirrorModifierData*) md;
-
+
if(mmd->flag & MOD_MIR_CLIPPING) {
axis = 0;
if(mmd->flag & MOD_MIR_AXIS_X) {
@@ -177,35 +178,35 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
float mtx[4][4], imtx[4][4];
int i;
TransData *td = t->data;
-
+
if (mmd->mirror_ob) {
float obinv[4][4];
-
+
Mat4Invert(obinv, mmd->mirror_ob->obmat);
Mat4MulMat4(mtx, ob->obmat, obinv);
Mat4Invert(imtx, mtx);
}
-
+
for(i = 0 ; i < t->total; i++, td++) {
int clip;
float loc[3], iloc[3];
-
+
if (td->flag & TD_NOACTION)
break;
if (td->loc==NULL)
break;
-
+
if (td->flag & TD_SKIP)
continue;
-
+
VecCopyf(loc, td->loc);
VecCopyf(iloc, td->iloc);
-
+
if (mmd->mirror_ob) {
VecMat4MulVecfl(loc, mtx, loc);
VecMat4MulVecfl(iloc, mtx, iloc);
}
-
+
clip = 0;
if(axis & 1) {
if(fabs(iloc[0])<=tolerance[0] ||
@@ -214,7 +215,7 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
clip = 1;
}
}
-
+
if(axis & 2) {
if(fabs(iloc[1])<=tolerance[1] ||
loc[1]*iloc[1]<0.0f) {
@@ -237,19 +238,20 @@ 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++) {
if (td->flag & TD_NOACTION)
break;
@@ -257,9 +259,9 @@ static void editmesh_apply_to_mirror(TransInfo *t)
break;
if (td->flag & TD_SKIP)
continue;
-
+
eve = td->extra;
- if (eve) {
+ if(eve) {
eve->co[0]= -td->loc[0];
eve->co[1]= td->loc[1];
eve->co[2]= td->loc[2];
@@ -268,9 +270,9 @@ static void editmesh_apply_to_mirror(TransInfo *t)
if (td->flag & TD_MIRROR_EDGE)
{
td->loc[0] = 0;
- }
}
}
+}
/* tags the given ID block for refreshes (if applicable) due to
* Animation Editor editing
@@ -641,183 +643,184 @@ void recalcData(TransInfo *t)
}
if (t->obedit) {
- if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
- Curve *cu= t->obedit->data;
- Nurb *nu= cu->editnurb->first;
+ if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
+ Curve *cu= t->obedit->data;
+ Nurb *nu= cu->editnurb->first;
- DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
+ DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
- if (t->state == TRANS_CANCEL) {
- while(nu) {
- calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
- nu= nu->next;
- }
- } else {
- /* Normal updating */
- while(nu) {
- test2DNurb(nu);
- calchandlesNurb(nu);
- nu= nu->next;
- }
+ if (t->state == TRANS_CANCEL) {
+ while(nu) {
+ calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
+ nu= nu->next;
+ }
+ } else {
+ /* Normal updating */
+ while(nu) {
+ test2DNurb(nu);
+ calchandlesNurb(nu);
+ nu= nu->next;
}
}
- else if(t->obedit->type==OB_LATTICE) {
- Lattice *la= t->obedit->data;
- DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
-
- if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt);
- }
- else if (t->obedit->type == OB_MESH) {
- EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
+ }
+ else if(t->obedit->type==OB_LATTICE) {
+ Lattice *la= t->obedit->data;
+ DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
+
+ if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt);
+ }
+ else if (t->obedit->type == OB_MESH) {
+ BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
/* mirror modifier clipping? */
if(t->state != TRANS_CANCEL) {
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_id_flush_update(t->obedit->data, 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 */
- bArmature *arm= t->obedit->data;
- ListBase *edbo = arm->edbo;
- EditBone *ebo;
- TransData *td = t->data;
- int i;
+ else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
+ bArmature *arm= t->obedit->data;
+ ListBase *edbo = arm->edbo;
+ EditBone *ebo;
+ TransData *td = t->data;
+ int i;
- /* Ensure all bones are correctly adjusted */
- for (ebo = edbo->first; ebo; ebo = ebo->next){
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = edbo->first; ebo; ebo = ebo->next){
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
- /* If this bone has a parent tip that has been moved */
- if (ebo->parent->flag & BONE_TIPSEL){
- VECCOPY (ebo->head, ebo->parent->tail);
- if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
- }
- /* If this bone has a parent tip that has NOT been moved */
- else{
- VECCOPY (ebo->parent->tail, ebo->head);
- if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
- }
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL){
+ VECCOPY (ebo->head, ebo->parent->tail);
+ if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
}
-
- /* on extrude bones, oldlength==0.0f, so we scale radius of points */
- ebo->length= VecLenf(ebo->head, ebo->tail);
- if(ebo->oldlength==0.0f) {
- ebo->rad_head= 0.25f*ebo->length;
- ebo->rad_tail= 0.10f*ebo->length;
- ebo->dist= 0.25f*ebo->length;
- if(ebo->parent) {
- if(ebo->rad_head > ebo->parent->rad_tail)
- ebo->rad_head= ebo->parent->rad_tail;
- }
+ /* If this bone has a parent tip that has NOT been moved */
+ else{
+ VECCOPY (ebo->parent->tail, ebo->head);
+ if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
}
- else if(t->mode!=TFM_BONE_ENVELOPE) {
- /* if bones change length, lets do that for the deform distance as well */
- ebo->dist*= ebo->length/ebo->oldlength;
- ebo->rad_head*= ebo->length/ebo->oldlength;
- ebo->rad_tail*= ebo->length/ebo->oldlength;
- ebo->oldlength= ebo->length;
+ }
+
+ /* on extrude bones, oldlength==0.0f, so we scale radius of points */
+ ebo->length= VecLenf(ebo->head, ebo->tail);
+ if(ebo->oldlength==0.0f) {
+ ebo->rad_head= 0.25f*ebo->length;
+ ebo->rad_tail= 0.10f*ebo->length;
+ ebo->dist= 0.25f*ebo->length;
+ if(ebo->parent) {
+ if(ebo->rad_head > ebo->parent->rad_tail)
+ ebo->rad_head= ebo->parent->rad_tail;
}
}
+ else if(t->mode!=TFM_BONE_ENVELOPE) {
+ /* if bones change length, lets do that for the deform distance as well */
+ ebo->dist*= ebo->length/ebo->oldlength;
+ ebo->rad_head*= ebo->length/ebo->oldlength;
+ ebo->rad_tail*= ebo->length/ebo->oldlength;
+ ebo->oldlength= ebo->length;
+ }
+ }
- if (t->mode != TFM_BONE_ROLL)
+ if (t->mode != TFM_BONE_ROLL)
+ {
+ /* fix roll */
+ for(i = 0; i < t->total; i++, td++)
{
- /* fix roll */
- for(i = 0; i < t->total; i++, td++)
+ if (td->extra)
{
- if (td->extra)
- {
- float vec[3], up_axis[3];
- float qrot[4];
+ float vec[3], up_axis[3];
+ float qrot[4];
- ebo = td->extra;
- VECCOPY(up_axis, td->axismtx[2]);
+ ebo = td->extra;
+ VECCOPY(up_axis, td->axismtx[2]);
- if (t->mode != TFM_ROTATION)
- {
- VecSubf(vec, ebo->tail, ebo->head);
- Normalize(vec);
- RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
- QuatMulVecf(qrot, up_axis);
- }
- else
- {
- Mat3MulVecfl(t->mat, up_axis);
- }
-
- ebo->roll = ED_rollBoneToVector(ebo, up_axis);
+ if (t->mode != TFM_ROTATION)
+ {
+ VecSubf(vec, ebo->tail, ebo->head);
+ Normalize(vec);
+ RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
+ QuatMulVecf(qrot, up_axis);
+ }
+ else
+ {
+ Mat3MulVecfl(t->mat, up_axis);
}
+
+ ebo->roll = ED_rollBoneToVector(ebo, up_axis);
}
}
+ }
- if(arm->flag & ARM_MIRROR_EDIT)
- transform_armature_mirror_update(t->obedit);
+ if(arm->flag & ARM_MIRROR_EDIT)
+ transform_armature_mirror_update(t->obedit);
- }
- else
- DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
}
- else if( (t->flag & T_POSE) && t->poseobj) {
- Object *ob= t->poseobj;
- bArmature *arm= ob->data;
+ else
+ DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
+ }
+ else if( (t->flag & T_POSE) && t->poseobj) {
+ Object *ob= t->poseobj;
+ bArmature *arm= ob->data;
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. uneditable animation values)
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
- int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
-
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
- }
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
- /* old optimize trick... this enforces to bypass the depgraph */
- if (!(arm->flag & ARM_DELAYDEFORM)) {
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
- }
- else
- where_is_pose(scene, ob);
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
}
- else {
- for(base= FIRSTBASE; base; base= base->next) {
- Object *ob= base->object;
+
+ /* old optimize trick... this enforces to bypass the depgraph */
+ if (!(arm->flag & ARM_DELAYDEFORM)) {
+ DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ }
+ else
+ where_is_pose(scene, ob);
+ }
+ else {
+ for(base= FIRSTBASE; base; base= base->next) {
+ Object *ob= base->object;
- /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
- if(base->flag & BA_HAS_RECALC_OB)
- ob->recalc |= OB_RECALC_OB;
- if(base->flag & BA_HAS_RECALC_DATA)
- ob->recalc |= OB_RECALC_DATA;
+ /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
+ if(base->flag & BA_HAS_RECALC_OB)
+ ob->recalc |= OB_RECALC_OB;
+ if(base->flag & BA_HAS_RECALC_DATA)
+ ob->recalc |= OB_RECALC_DATA;
- /* if object/base is selected */
- if ((base->flag & SELECT) || (ob->flag & SELECT)) {
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. uneditable animation values)
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
- }
+ /* if object/base is selected */
+ if ((base->flag & SELECT) || (ob->flag & SELECT)) {
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
}
-
- /* proxy exception */
- if(ob->proxy)
- ob->proxy->recalc |= ob->recalc;
- if(ob->proxy_group)
- group_tag_recalc(ob->proxy_group->dup_group);
}
+
+ /* proxy exception */
+ if(ob->proxy)
+ ob->proxy->recalc |= ob->recalc;
+ if(ob->proxy_group)
+ group_tag_recalc(ob->proxy_group->dup_group);
}
+ }
if(((View3D*)t->view)->drawtype == OB_SHADED)
- reshadeall_displist(t->scene);
- }
+ reshadeall_displist(t->scene);
+}
}
void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)
@@ -828,18 +831,18 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)
if (t->spacetype == SPACE_VIEW3D)
{
View3D *v3d = t->view;
-
+
glPushMatrix();
-
+
//if(t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing
-
-
+
+
VecCopyf(v3, dir);
VecMulf(v3, v3d->far);
-
+
VecSubf(v2, center, v3);
VecAddf(v1, center, v3);
-
+
if (options & DRAWLIGHT) {
col[0] = col[1] = col[2] = 220;
}
@@ -848,13 +851,13 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)
}
UI_make_axis_color(col, col2, axis);
glColor3ubv((GLubyte *)col2);
-
+
setlinestyle(0);
glBegin(GL_LINE_STRIP);
glVertex3fv(v1);
glVertex3fv(v2);
glEnd();
-
+
glPopMatrix();
}
}
@@ -871,33 +874,33 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
-
+
/* moving: is shown in drawobject() (transform color) */
// TRANSFORM_FIX_ME
// if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
// else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
// else G.moving= G_TRANSFORM_OBJ;
-
+
t->scene = sce;
t->sa = sa;
t->ar = ar;
t->obedit = obedit;
t->settings = ts;
-
+
t->data = NULL;
t->ext = NULL;
-
+
t->helpline = HLP_NONE;
-
+
t->flag = 0;
-
+
t->redraw = 1; /* redraw first time */
-
+
if (event)
{
t->imval[0] = event->x - t->ar->winrct.xmin;
t->imval[1] = event->y - t->ar->winrct.ymin;
-
+
t->event_type = event->type;
}
else
@@ -905,45 +908,45 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
t->imval[0] = 0;
t->imval[1] = 0;
}
-
+
t->con.imval[0] = t->imval[0];
t->con.imval[1] = t->imval[1];
-
+
t->mval[0] = t->imval[0];
t->mval[1] = t->imval[1];
-
+
t->transform = NULL;
t->handleEvent = NULL;
-
+
t->total = 0;
-
+
t->val = 0.0f;
-
+
t->vec[0] =
t->vec[1] =
t->vec[2] = 0.0f;
-
+
t->center[0] =
t->center[1] =
t->center[2] = 0.0f;
-
+
Mat3One(t->mat);
-
+
t->spacetype = sa->spacetype;
if(t->spacetype == SPACE_VIEW3D)
{
View3D *v3d = sa->spacedata.first;
-
+
t->view = v3d;
t->animtimer= CTX_wm_screen(C)->animtimer;
-
+
if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
t->around = v3d->around;
-
+
if (op && RNA_struct_find_property(op->ptr, "constraint_orientation") && RNA_property_is_set(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)
{
t->current_orientation = V3D_MANIP_GLOBAL;
@@ -965,10 +968,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
{
// XXX for now, get View2D from the active region
t->view = &ar->v2d;
-
+
t->around = V3D_CENTER;
}
-
+
if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_property_is_set(op->ptr, "mirror"))
{
if (RNA_boolean_get(op->ptr, "mirror"))
@@ -986,40 +989,40 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
t->mirror = 1;
}
}
-
+
/* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
if (op && RNA_struct_find_property(op->ptr, "proportional"))
{
if (RNA_property_is_set(op->ptr, "proportional"))
{
- switch(RNA_enum_get(op->ptr, "proportional"))
- {
- case 2: /* XXX connected constant */
- t->flag |= T_PROP_CONNECTED;
- case 1: /* XXX prop on constant */
- t->flag |= T_PROP_EDIT;
- break;
- }
- }
- else
+ switch(RNA_enum_get(op->ptr, "proportional"))
{
+ case 2: /* XXX connected constant */
+ t->flag |= T_PROP_CONNECTED;
+ case 1: /* XXX prop on constant */
+ t->flag |= T_PROP_EDIT;
+ break;
+ }
+ }
+ else
+ {
if ((t->options & CTX_NO_PET) == 0 && (ts->proportional != PROP_EDIT_OFF)) {
- t->flag |= T_PROP_EDIT;
-
+ t->flag |= T_PROP_EDIT;
+
if(ts->proportional == PROP_EDIT_CONNECTED)
- t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
- }
- }
-
- if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size"))
- {
- t->prop_size = RNA_float_get(op->ptr, "proportional_size");
+ t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
}
- else
- {
- t->prop_size = ts->proportional_size;
- }
-
+ }
+
+ if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size"))
+ {
+ t->prop_size = RNA_float_get(op->ptr, "proportional_size");
+ }
+ else
+ {
+ t->prop_size = ts->proportional_size;
+ }
+
/* TRANSFORM_FIX_ME rna restrictions */
if (t->prop_size <= 0)
@@ -1027,25 +1030,25 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
t->prop_size = 1.0f;
}
- if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
- {
- t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff");
- }
- else
- {
- t->prop_mode = ts->prop_mode;
- }
+ if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
+ {
+ t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff");
+ }
+ else
+ {
+ t->prop_mode = ts->prop_mode;
+ }
}
else /* add not pet option to context when not available */
{
t->options |= CTX_NO_PET;
}
-
+
setTransformViewMatrices(t);
initNumInput(&t->num);
initNDofInput(&t->ndof);
-
+
return 1;
}
@@ -1053,16 +1056,16 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
void postTrans (TransInfo *t)
{
TransData *td;
-
+
if (t->draw_handle)
{
ED_region_draw_cb_exit(t->ar->type, t->draw_handle);
}
-
+
/* postTrans can be called when nothing is selected, so data is NULL already */
if (t->data) {
int a;
-
+
/* since ipokeys are optional on objects, we mallocced them per trans-data */
for(a=0, td= t->data; a<t->total; a++, td++) {
if (td->flag & TD_BEZTRIPLE)
@@ -1070,13 +1073,13 @@ void postTrans (TransInfo *t)
}
MEM_freeN(t->data);
}
-
+
if (t->ext) MEM_freeN(t->ext);
if (t->data2d) {
MEM_freeN(t->data2d);
t->data2d= NULL;
}
-
+
if(t->spacetype==SPACE_IMAGE) {
SpaceImage *sima= t->sa->spacedata.first;
if(sima->flag & SI_LIVE_UNWRAP)
@@ -1092,14 +1095,13 @@ void postTrans (TransInfo *t)
t->customFree(t);
}
else if (t->customData) {
- MEM_freeN(t->customData);
- }
-}
+ MEM_freeN(t->customData);
+ }}
void applyTransObjects(TransInfo *t)
{
TransData *td;
-
+
for (td = t->data; td < t->data + t->total; td++) {
VECCOPY(td->iloc, td->loc);
if (td->ext->rot) {
@@ -1127,27 +1129,27 @@ static void restoreElement(TransData *td) {
if (td->ext->size) {
VECCOPY(td->ext->size, td->ext->isize);
}
- if (td->ext->quat) {
- QUATCOPY(td->ext->quat, td->ext->iquat);
+ if (td->ext->quat) {
+ QUATCOPY(td->ext->quat, td->ext->iquat);
+ }
}
- }
-
+
if (td->flag & TD_BEZTRIPLE) {
*(td->hdata->h1) = td->hdata->ih1;
*(td->hdata->h2) = td->hdata->ih2;
}
-}
+ }
void restoreTransObjects(TransInfo *t)
{
TransData *td;
-
+
for (td = t->data; td < t->data + t->total; td++) {
restoreElement(td);
}
-
+
Mat3One(t->mat);
-
+
recalcData(t);
}
@@ -1156,7 +1158,7 @@ void calculateCenter2D(TransInfo *t)
if (t->flag & (T_EDIT|T_POSE)) {
Object *ob= t->obedit?t->obedit:t->poseobj;
float vec[3];
-
+
VECCOPY(vec, t->center);
Mat4MulVecfl(ob->obmat, vec);
projectIntView(t, vec, t->center2d);
@@ -1169,21 +1171,21 @@ void calculateCenter2D(TransInfo *t)
void calculateCenterCursor(TransInfo *t)
{
float *cursor;
-
+
cursor = give_cursor(t->scene, t->view);
VECCOPY(t->center, cursor);
-
+
/* If edit or pose mode, move cursor in local space */
if (t->flag & (T_EDIT|T_POSE)) {
Object *ob = t->obedit?t->obedit:t->poseobj;
float mat[3][3], imat[3][3];
-
+
VecSubf(t->center, t->center, ob->obmat[3]);
Mat3CpyMat4(mat, ob->obmat);
Mat3Inv(imat, mat);
Mat3MulVecfl(imat, t->center);
}
-
+
calculateCenter2D(t);
}
@@ -1191,15 +1193,15 @@ void calculateCenterCursor2D(TransInfo *t)
{
View2D *v2d= t->view;
float aspx=1.0, aspy=1.0;
-
+
if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
-
+
if (v2d) {
t->center[0] = v2d->cursor[0] * aspx;
t->center[1] = v2d->cursor[1] * aspy;
}
-
+
calculateCenter2D(t);
}
@@ -1208,7 +1210,7 @@ void calculateCenterMedian(TransInfo *t)
float partial[3] = {0.0f, 0.0f, 0.0f};
int total = 0;
int i;
-
+
for(i = 0; i < t->total; i++) {
if (t->data[i].flag & TD_SELECTED) {
if (!(t->data[i].flag & TD_NOCENTER))
@@ -1228,7 +1230,7 @@ void calculateCenterMedian(TransInfo *t)
if(i)
VecMulf(partial, 1.0f / total);
VECCOPY(t->center, partial);
-
+
calculateCenter2D(t);
}
@@ -1258,7 +1260,7 @@ void calculateCenterBound(TransInfo *t)
}
VecAddf(t->center, min, max);
VecMulf(t->center, 0.5);
-
+
calculateCenter2D(t);
}
@@ -1294,7 +1296,7 @@ void calculateCenter(TransInfo *t)
break;
} /* END EDIT MODE ACTIVE ELEMENT */
#endif
-
+
calculateCenterMedian(t);
if((t->flag & (T_EDIT|T_POSE))==0)
{
@@ -1306,10 +1308,10 @@ void calculateCenter(TransInfo *t)
projectIntView(t, t->center, t->center2d);
}
}
-
+
}
}
-
+
/* setting constraint center */
VECCOPY(t->con.center, t->center);
if(t->flag & (T_EDIT|T_POSE))
@@ -1317,7 +1319,7 @@ void calculateCenter(TransInfo *t)
Object *ob= t->obedit?t->obedit:t->poseobj;
Mat4MulVecfl(ob->obmat, t->con.center);
}
-
+
/* for panning from cameraview */
if(t->flag & T_OBJECT)
{
@@ -1326,21 +1328,21 @@ void calculateCenter(TransInfo *t)
View3D *v3d = t->view;
Scene *scene = t->scene;
RegionView3D *rv3d = t->ar->regiondata;
-
+
if(v3d->camera == OBACT && rv3d->persp==V3D_CAMOB)
{
float axis[3];
/* persinv is nasty, use viewinv instead, always right */
VECCOPY(axis, t->viewinv[2]);
Normalize(axis);
-
+
/* 6.0 = 6 grid units */
axis[0]= t->center[0]- 6.0f*axis[0];
axis[1]= t->center[1]- 6.0f*axis[1];
axis[2]= t->center[2]- 6.0f*axis[2];
-
+
projectIntView(t, axis, t->center2d);
-
+
/* rotate only needs correct 2d center, grab needs initgrabz() value */
if(t->mode==TFM_TRANSLATION)
{
@@ -1350,14 +1352,14 @@ void calculateCenter(TransInfo *t)
}
}
}
-
+
if(t->spacetype==SPACE_VIEW3D)
{
/* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */
if(t->flag & (T_EDIT|T_POSE)) {
Object *ob= t->obedit?t->obedit:t->poseobj;
float vec[3];
-
+
VECCOPY(vec, t->center);
Mat4MulVecfl(ob->obmat, vec);
initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]);
@@ -1403,7 +1405,7 @@ void calculatePropRatio(TransInfo *t)
/* Use rdist for falloff calculations, it is the real distance */
td->flag &= ~TD_NOACTION;
dist= (t->prop_size-td->rdist)/t->prop_size;
-
+
/*
* Clamp to positive numbers.
* Certain corner cases with connectivity and individual centers
@@ -1411,7 +1413,7 @@ void calculatePropRatio(TransInfo *t)
*/
if (dist < 0.0f)
dist = 0.0f;
-
+
switch(t->prop_mode) {
case PROP_SHARP:
td->factor= dist*dist;
@@ -1478,20 +1480,20 @@ float get_drawsize(ARegion *ar, float *co)
{
RegionView3D *rv3d= ar->regiondata;
float size, vec[3], len1, len2;
-
+
/* size calculus, depending ortho/persp settings, like initgrabz() */
size= rv3d->persmat[0][3]*co[0]+ rv3d->persmat[1][3]*co[1]+ rv3d->persmat[2][3]*co[2]+ rv3d->persmat[3][3];
-
+
VECCOPY(vec, rv3d->persinv[0]);
len1= Normalize(vec);
VECCOPY(vec, rv3d->persinv[1]);
len2= Normalize(vec);
-
+
size*= 0.01f*(len1>len2?len1:len2);
-
+
/* correct for window size to make widgets appear fixed size */
if(ar->winx > ar->winy) size*= 1000.0f/(float)ar->winx;
else size*= 1000.0f/(float)ar->winy;
-
+
return size;
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index bdf0a91bf89..19881c7bc5b 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -64,6 +64,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
@@ -205,20 +206,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 5173245734b..fe8e5b34b54 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -675,7 +675,7 @@ void TFM_OT_transform(struct wmOperatorType *ot)
Properties_Proportional(ot);
RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
-
+
Properties_Constraints(ot);
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index c9344b97fb2..bad744d101b 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -44,6 +44,7 @@
#include "BKE_utildefines.h"
#include "BKE_armature.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "BKE_report.h"
#include "BLI_arithb.h"
@@ -77,9 +78,9 @@ void BIF_clearTransformOrientation(bContext *C)
// Need to loop over all view3d
if(v3d && v3d->twmode >= V3D_MANIP_CUSTOM) {
v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
- }
}
-
+}
+
TransformOrientation* findOrientationName(bContext *C, char *name)
{
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
@@ -159,16 +160,16 @@ TransformOrientation *createObjectSpace(bContext *C, ReportList *reports, char *
ob = base->object;
-
+
Mat3CpyMat4(mat, ob->obmat);
Mat3Ortho(mat);
/* use object name if no name is given */
if (name[0] == 0)
- {
+{
strncpy(name, ob->id.name+2, 35);
}
-
+
return addMatrixSpace(C, mat, name, overwrite);
}
@@ -177,7 +178,7 @@ TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *na
float normal[3], plane[3];
getTransformOrientation(C, normal, plane, 0);
-
+
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
BKE_reports_prepend(reports, "Cannot use zero-length bone");
return NULL;
@@ -185,7 +186,7 @@ TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *na
if (name[0] == 0)
{
- strcpy(name, "Bone");
+ strcpy(name, "Bone");
}
return addMatrixSpace(C, mat, name, overwrite);
@@ -208,7 +209,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na
if (name[0] == 0)
{
- strcpy(name, "Vertex");
+ strcpy(name, "Vertex");
}
break;
case ORIENTATION_EDGE:
@@ -219,7 +220,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na
if (name[0] == 0)
{
- strcpy(name, "Edge");
+ strcpy(name, "Edge");
}
break;
case ORIENTATION_FACE:
@@ -230,7 +231,7 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na
if (name[0] == 0)
{
- strcpy(name, "Face");
+ strcpy(name, "Face");
}
break;
default:
@@ -296,7 +297,7 @@ TransformOrientation* addMatrixSpace(bContext *C, float mat[3][3], char name[],
if (overwrite)
{
ts = findOrientationName(C, name);
- }
+ }
else
{
uniqueOrientationName(C, name);
@@ -327,14 +328,14 @@ void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target) {
if(v3d) {
int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D
+ // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D
if (selected_index == i) {
v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
}
else if (selected_index > i) {
v3d->twmode--;
}
-
+
}
BLI_freelinkN(transform_spaces, ts);
@@ -387,7 +388,7 @@ void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) {
void BIF_selectTransformOrientationValue(bContext *C, int orientation) {
View3D *v3d = CTX_wm_view3d(C);
if(v3d) /* currently using generic poll */
- v3d->twmode = orientation;
+ v3d->twmode = orientation;
}
EnumPropertyItem *BIF_enumTransformOrientation(bContext *C)
@@ -626,16 +627,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)
{
@@ -652,30 +653,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;
}
@@ -694,12 +695,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;
}
@@ -708,12 +710,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);
@@ -723,13 +726,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;
}
@@ -745,24 +748,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);
}
}
@@ -948,9 +952,20 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
}
- VECCOPY(normal, ob->obmat[2]);
- VECCOPY(plane, ob->obmat[1]);
- result = ORIENTATION_NORMAL;
+ if (!ob) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+ plane[0] = 1.0f;
+ plane[1] = 0.0f;
+ plane[2] = 0.0f;
+
+ result = ORIENTATION_NORMAL;
+ } else {
+ VECCOPY(normal, ob->obmat[2]);
+ VECCOPY(plane, ob->obmat[1]);
+ result = ORIENTATION_NORMAL;
+ }
}
return result;
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 6cfffd1ade7..a2a7577c8d6 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"
@@ -370,9 +372,9 @@ void initSnapping(TransInfo *t, wmOperator *op)
if (RNA_struct_find_property(op->ptr, "snap_project"))
{
t->tsnap.project = RNA_boolean_get(op->ptr, "snap_project");
- }
}
}
+ }
else
{
snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP);
@@ -711,8 +713,8 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
else
{
found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode);
- }
-
+ }
+
if (found == 1)
{
float tangent[3];
@@ -1176,11 +1178,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], float 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];
@@ -1215,19 +1217,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 */
@@ -1249,11 +1251,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;
+ }
+ }
}
}
}
@@ -1281,7 +1294,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;
}
@@ -1295,11 +1308,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 */
@@ -1321,9 +1334,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;
}
@@ -1339,7 +1352,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;
}
@@ -1355,11 +1368,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 */
@@ -1381,9 +1394,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;
}
@@ -1399,7 +1414,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;
}
@@ -1416,13 +1431,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
{
@@ -1558,7 +1573,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];
@@ -1588,7 +1603,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++) {
@@ -1684,6 +1699,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;
@@ -1705,6 +1721,7 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
retval = retval || val;
dm->release(dm);
+#endif
}
}
@@ -1712,7 +1729,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;
@@ -1724,8 +1741,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/SConscript b/source/blender/editors/uvedit/SConscript
index b472b89d23d..9926eb0c7ea 100644
--- a/source/blender/editors/uvedit/SConscript
+++ b/source/blender/editors/uvedit/SConscript
@@ -5,6 +5,6 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../makesrna #/intern/opennl/extern ../../gpu'
+incs += ' ../../makesrna #/intern/opennl/extern ../../gpu ../../bmesh'
env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index fbd12007c16..f48f8441d53 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -28,6 +28,9 @@
#include <float.h>
#include <math.h>
#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -41,9 +44,11 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
+#include "BLI_array.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -119,34 +124,33 @@ static int draw_uvs_face_check(Scene *scene)
static void draw_uvs_shadow(SpaceImage *sima, Object *obedit)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
/* draws the grey mesh when painting */
glColor3ub(112, 112, 112);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int draw_uvs_dm_shadow(DerivedMesh *dm)
{
/* draw shadow mesh - this is the mesh with the modifier applied */
- if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
+ if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
glColor3ub(112, 112, 112);
dm->drawUVEdges(dm);
return 1;
@@ -155,13 +159,19 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm)
return 0;
}
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf)
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
Image *ima= sima->image;
- float aspx, aspy, col[4], tf_uv[4][2];
-
+ BLI_array_declare(tf_uv);
+ BLI_array_declare(tf_uvorig);
+ float aspx, aspy, col[4], (*tf_uv)[2] = NULL, (*tf_uvorig)[2] = NULL;
+ int i;
+
ED_space_image_uv_aspect(sima, &aspx, &aspy);
switch(sima->dt_uvstretch) {
@@ -169,21 +179,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
{
float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ BLI_array_empty(tf_uv);
+ BLI_array_empty(tf_uvorig);
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(tf_uv);
+ BLI_array_growone(tf_uvorig);
+
+ tf_uvorig[i][0] = luv->uv[0];
+ tf_uvorig[i][1] = luv->uv[1];
- totarea += EM_face_area(efa);
+ i++;
+ }
+
+ poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
+
+ totarea += BM_face_area(efa);
//totuvarea += tf_area(tf, efa->v4!=0);
- totuvarea += uv_area(tf_uv, efa->v4!=0);
+ totuvarea += poly_uv_area(tf_uv, efa->len);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ BMINDEX_SET(efa, 1);
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BMINDEX_SET(efa, 0);
}
}
@@ -191,24 +217,41 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
col[0] = 1.0;
col[1] = col[2] = 0.0;
glColor3fv(col);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tf=(MTFace *)efa->tmp.p)) {
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BMINDEX_GET(efa)) {
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
}
}
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tf=(MTFace *)efa->tmp.p)) {
- area = EM_face_area(efa) / totarea;
- uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BMINDEX_GET(efa)) {
+ area = BM_face_area(efa) / totarea;
+
+ BLI_array_empty(tf_uv);
+ BLI_array_empty(tf_uvorig);
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(tf_uv);
+ BLI_array_growone(tf_uvorig);
+
+ tf_uvorig[i][0] = luv->uv[0];
+ tf_uvorig[i][1] = luv->uv[1];
+
+ i++;
+ }
+
+ poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
+
//uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
- uvarea = uv_area(tf_uv, efa->v4!=0) / totuvarea;
+ uvarea = poly_uv_area(tf_uv, efa->len) / totuvarea;
if(area < FLT_EPSILON || uvarea < FLT_EPSILON)
areadiff = 1.0;
@@ -220,11 +263,11 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
weight_to_rgb(areadiff, col, col+1, col+2);
glColor3fv(col);
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
}
@@ -233,6 +276,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
}
case SI_UVDT_STRETCH_ANGLE:
{
+#if 0 //BMESH_TODO
float uvang1,uvang2,uvang3,uvang4;
float ang1,ang2,ang3,ang4;
float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d angle vectors */
@@ -243,7 +287,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
glShadeModel(GL_SMOOTH);
for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf= CustomData_em_get(&em->fdata, efa->head.data, CD_MTFACE);
if(uvedit_face_visible(scene, ima, efa, tf)) {
efa->tmp.p = tf;
@@ -374,11 +418,13 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
glShadeModel(GL_FLAT);
break;
+
+#endif
}
}
}
-static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFace *activetf)
+static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTexPoly *activetf)
{
Base *base;
Image *curimage;
@@ -398,17 +444,19 @@ static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFac
Mesh *me= ob->data;
if(me->mtface) {
- MFace *mface= me->mface;
- MTFace *tface= me->mtface;
- int a;
+ MPoly *mface= me->mpoly;
+ MTexPoly *tface= me->mtpoly;
+ MLoopUV *mloopuv;
+ int a, b;
- for(a=me->totface; a>0; a--, tface++, mface++) {
+ for(a=me->totpoly; a>0; a--, tface++, mface++) {
if(tface->tpage == curimage) {
glBegin(GL_LINE_LOOP);
- glVertex2fv(tface->uv[0]);
- glVertex2fv(tface->uv[1]);
- glVertex2fv(tface->uv[2]);
- if(mface->v4) glVertex2fv(tface->uv[3]);
+
+ mloopuv = me->mloopuv + mface->loopstart;
+ for (b=0; b<mface->totloop; b++, mloopuv++) {
+ glVertex2fv(mloopuv->uv);
+ }
glEnd();
}
}
@@ -422,18 +470,22 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
{
ToolSettings *ts;
Mesh *me= obedit->data;
- EditMesh *em;
- EditFace *efa, *efa_act;
- MTFace *tf, *activetf = NULL;
+ BMEditMesh *em;
+ BMFace *efa, *efa_act, *activef;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf, *activetf = NULL;
+ MLoopUV *luv;
DerivedMesh *finaldm, *cagedm;
char col1[4], col2[4];
float pointsize;
int drawfaces, interpedges, lastsel, sel;
+ int i;
Image *ima= sima->image;
- em= BKE_mesh_get_editmesh(me);
- activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */
-
+ em= me->edit_btmesh;
+ activetf= EDBM_get_active_mtexpoly(em, &efa_act, 0); /* will be set to NULL if hidden */
+ activef = EDBM_get_actFace(em, 0);
ts= scene->toolsettings;
drawfaces= draw_uvs_face_check(scene);
@@ -452,7 +504,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 */
@@ -477,45 +529,46 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
- if(tf==activetf) continue; /* important the temp pointer is set above */
+ BMINDEX_SET(efa, 1);
+ if(tf==activetf) continue; /* important the temp boolean is set above */
- if(uvedit_face_selected(scene, efa, tf))
+ if(uvedit_face_selected(scene, em, efa))
glColor4ubv((GLubyte *)col2);
else
glColor4ubv((GLubyte *)col1);
-
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BMINDEX_SET(efa, 0);
}
}
glDisable(GL_BLEND);
}
else {
/* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ BMINDEX_SET(efa, 1);
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BMINDEX_SET(efa, 0);
}
}
@@ -523,7 +576,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* 3. draw active face stippled */
- if(activetf) {
+ if(activef) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UI_ThemeColor4(TH_EDITMESH_ACTIVE);
@@ -531,11 +584,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(stipple_quarttone);
- glBegin(efa_act->v4? GL_QUADS: GL_TRIANGLES);
- glVertex2fv(activetf->uv[0]);
- glVertex2fv(activetf->uv[1]);
- glVertex2fv(activetf->uv[2]);
- if(efa_act->v4) glVertex2fv(activetf->uv[3]);
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, activef) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
glDisable(GL_POLYGON_STIPPLE);
@@ -552,39 +605,38 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
switch(sima->dt_uv) {
case SI_UVDT_DASH:
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(tf) {
cpack(0x111111);
glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
-
+
setlinestyle(2);
cpack(0x909090);
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glEnd();
-
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[0]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- else glVertex2fv(tf->uv[2]);
- glEnd();
-
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
+ /*glBegin(GL_LINE_STRIP);
+ luv = CustomData_bmesh_get(&em->bm->ldata, efa->loopbase->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ luv = CustomData_bmesh_get(&em->bm->ldata, efa->loopbase->head.next->data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ glEnd();*/
+
setlinestyle(0);
}
}
@@ -594,34 +646,32 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if(sima->dt_uv==SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f);
else glColor3f(0.0f, 0.0f, 0.0f);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
break;
case SI_UVDT_OUTLINE:
glLineWidth(3);
cpack(0x0);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
glLineWidth(1);
@@ -635,83 +685,60 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if(interpedges) {
glShadeModel(GL_SMOOTH);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if(tf) {
- glBegin(GL_LINE_LOOP);
- sel = (uvedit_uv_selected(scene, efa, tf, 0)? 1 : 0);
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[0]);
-
- sel = uvedit_uv_selected(scene, efa, tf, 1)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[1]);
-
- sel = uvedit_uv_selected(scene, efa, tf, 2)? 1 : 0;
+ glBegin(GL_LINE_LOOP);
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ sel = (uvedit_uv_selected(em, scene, l)? 1 : 0);
if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[2]);
-
- if(efa->v4) {
- sel = uvedit_uv_selected(scene, efa, tf, 3)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[3]);
- }
-
- glEnd();
+
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ i += 1;
}
+ glEnd();
}
glShadeModel(GL_FLAT);
}
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if(tf) {
- glBegin(GL_LINES);
- sel = (uvedit_edge_selected(scene, efa, tf, 0)? 1 : 0);
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 1)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 2)? 1 : 0;
+ glBegin(GL_LINE_LOOP);
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ sel = (uvedit_edge_selected(em, scene, l)? 1 : 0);
if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[2]);
-
- if(efa->v4) {
- glVertex2fv(tf->uv[3]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 3)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[3]);
- }
-
- glVertex2fv(tf->uv[0]);
-
- glEnd();
+
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ i += 1;
}
+ glEnd();
}
}
}
else {
/* no nice edges */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
}
@@ -735,11 +762,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
UI_ThemeColor(TH_WIRE);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if(tf && !uvedit_face_selected(scene, efa, tf)) {
- uv_center(tf->uv, cent, efa->v4 != NULL);
+ if(!uvedit_face_selected(scene, em, efa)) {
+ poly_uv_center(em, efa, cent);
bglVertex2fv(cent);
}
}
@@ -749,11 +777,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
UI_ThemeColor(TH_FACE_DOT);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if(tf && uvedit_face_selected(scene, efa, tf)) {
- uv_center(tf->uv, cent, efa->v4 != NULL);
+ if(uvedit_face_selected(scene, em, efa)) {
+ poly_uv_center(em, efa, cent);
bglVertex2fv(cent);
}
}
@@ -769,18 +798,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glPointSize(pointsize);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(!uvedit_uv_selected(scene, efa, tf, 0))
- bglVertex2fv(tf->uv[0]);
- if(!uvedit_uv_selected(scene, efa, tf, 1))
- bglVertex2fv(tf->uv[1]);
- if(!uvedit_uv_selected(scene, efa, tf, 2))
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && !uvedit_uv_selected(scene, efa, tf, 3))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(!uvedit_uv_selected(em, scene, l))
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
@@ -791,46 +816,39 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
cpack(0xFF);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(tf->unwrap & TF_PIN1)
- bglVertex2fv(tf->uv[0]);
- if(tf->unwrap & TF_PIN2)
- bglVertex2fv(tf->uv[1]);
- if(tf->unwrap & TF_PIN3)
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && (tf->unwrap & TF_PIN4))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if(luv->flag & MLOOPUV_PINNED)
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
/* selected uvs */
UI_ThemeColor(TH_VERTEX_SELECT);
- glPointSize(pointsize);
+ glPointSize(pointsize);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- bglVertex2fv(tf->uv[0]);
- if(uvedit_uv_selected(scene, efa, tf, 1))
- bglVertex2fv(tf->uv[1]);
- if(uvedit_uv_selected(scene, efa, tf, 2))
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if(uvedit_uv_selected(em, scene, l))
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
}
glPointSize(1.0);
- BKE_mesh_end_editmesh(obedit->data, em);
}
void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit)
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index cca357c8685..a203fc9b55b 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -30,12 +30,16 @@
#define ED_UVEDIT_INTERN_H
struct SpaceImage;
-struct EditFace;
-struct MTFace;
+struct MTexPoly;
struct Scene;
struct Image;
struct Object;
struct wmOperatorType;
+struct BMEditMesh;
+struct BMFace;
+struct BMLoop;
+struct BMEdge;
+struct BMVert;
#define UV_SELECT_ALL 1
#define UV_SELECT_PINNED 2
@@ -45,26 +49,28 @@ struct wmOperatorType;
#define TF_SEL_MASK(id) (TF_SEL1 << id)
/* visibility and selection */
-int uvedit_face_visible_nolocal(struct Scene *scene, struct EditFace *efa);
-int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf);
+int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
-int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-void uvedit_face_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-void uvedit_face_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
+/*all the uvedit_xxxx_[de]selected functions are
+ declared in ED_uvedit.h*/
+int uvedit_face_select(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
+int uvedit_face_deselect(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
-int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_edge_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_edge_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_edge_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+void uvedit_edge_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
-int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_uv_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_uv_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+void uvedit_uv_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+void uvedit_uv_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
/* geometric utilities */
void uv_center(float uv[][2], float cent[2], int quad);
float uv_area(float uv[][2], int quad);
void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy);
+float poly_uv_area(float uv[][2], int len);
+void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
+void poly_uv_center(struct BMEditMesh *em, struct BMFace *f, float cent[2]);
+
/* operators */
void UV_OT_average_islands_scale(struct wmOperatorType *ot);
void UV_OT_cube_project(struct wmOperatorType *ot);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 1641d1c8fac..df418e60254 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -30,12 +30,14 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_image_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -44,6 +46,7 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
+#include "BLI_array.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -53,6 +56,7 @@
#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -71,19 +75,20 @@
#include "uvedit_intern.h"
+#define EFA_F1_FLAG 2
+
/************************* state testing ************************/
int ED_uvedit_test(Object *obedit)
{
- EditMesh *em;
+ BMEditMesh *em;
int ret;
- if(!obedit || obedit->type != OB_MESH)
+ if(obedit->type != OB_MESH)
return 0;
- em = BKE_mesh_get_editmesh(obedit->data);
- ret = EM_texFaceCheck(em);
- BKE_mesh_end_editmesh(obedit->data, em);
+ em = ((Mesh*)obedit->data)->edit_btmesh;
+ ret = EDBM_texFaceCheck(em);
return ret;
}
@@ -92,9 +97,10 @@ int ED_uvedit_test(Object *obedit)
void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMIter iter;
+ MTexPoly *tf;
int update= 0;
/* skip assigning these procedural images... */
@@ -105,21 +111,21 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre
if(!obedit || (obedit->type != OB_MESH))
return;
- em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
- if(!em || !em->faces.first) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
+ if(!em || !em->bm->totface) {
return;
}
/* ensure we have a uv layer */
- if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
- EM_add_data_layer(em, &em->fdata, CD_MTFACE);
+ if(!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
update= 1;
}
/* now assign to all visible faces */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, previma, efa, tf)) {
if(ima) {
@@ -141,17 +147,16 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre
/* and update depdency graph */
if(update)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
/* dotile - 1, set the tile flag (from the space image)
* 2, set the tile index for the faces. */
void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, int curtile)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMIter iter;
+ MTexPoly *tf;
/* verify if we have something to do */
if(!ima || !ED_uvedit_test(obedit))
@@ -161,18 +166,17 @@ void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, i
if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
return;
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(efa->h==0 && efa->f & SELECT)
+ if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT))
tf->tile= curtile; /* set tile index */
}
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
}
/*********************** space conversion *********************/
@@ -181,13 +185,7 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
{
int width, height;
- if(sima) {
- ED_space_image_size(sima, &width, &height);
- }
- else {
- width= 256;
- height= 256;
- }
+ ED_space_image_size(sima, &width, &height);
dist[0]= pixeldist/width;
dist[1]= pixeldist/height;
@@ -195,18 +193,17 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
/*************** visibility and selection utilities **************/
-int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
+int uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- return (efa->h==0);
+ return (BM_TestHFlag(efa, BM_HIDDEN)==0);
else
- return (efa->h==0 && (efa->f & SELECT));
+ return (BM_TestHFlag(efa, BM_HIDDEN)==0 && BM_TestHFlag(efa, BM_SELECT));
}
-int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
-{
+int uvedit_face_visible(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf) {
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
@@ -215,134 +212,216 @@ int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
return uvedit_face_visible_nolocal(scene, efa);
}
-int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_selected(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- return (efa->f & SELECT);
- else
- return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
+ return (BM_TestHFlag(efa, BM_SELECT));
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (!(luv->flag & MLOOPUV_VERTSEL))
+ return 0;
+ }
+
+ return 1;
+ }
}
-void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_select(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- EM_select_face(efa, 1);
- else
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ BM_Select(em->bm, efa, 1);
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ return 1;
+ }
+
+ return 0;
}
-void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_deselect(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- EM_select_face(efa, 0);
- else
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ BM_Select(em->bm, efa, 0);
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+
+ return 1;
+ }
+
+ return 0;
}
-int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+int uvedit_edge_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- return (efa->f & SELECT);
- else if(ts->selectmode == SCE_SELECT_EDGE)
- return (*(&efa->e1 + i))->f & SELECT;
- else
- return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
+ return BM_TestHFlag(l->f, BM_SELECT);
+ else if(ts->selectmode == SCE_SELECT_EDGE) {
+ return BM_TestHFlag(l->e, BM_SELECT);
+ } else
+ return BM_TestHFlag(l->v, BM_SELECT) &&
+ BM_TestHFlag(((BMLoop*)l->head.next)->v, BM_SELECT);
+ }
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+
+ return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
}
- else
- return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
}
-void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_edge_select(BMEditMesh *em, Scene *scene, BMLoop *l)
+
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- EM_select_face(efa, 1);
+ BM_Select(em->bm, l->f, 1);
else if(ts->selectmode == SCE_SELECT_EDGE)
- EM_select_edge((*(&efa->e1 + i)), 1);
+ BM_Select(em->bm, l->e, 1);
else {
- (efa->v1 + i)->f |= SELECT;
- (efa->v1 + (i+1)%nvert)->f |= SELECT;
+ BM_Select(em->bm, l->e->v1, 1);
+ BM_Select(em->bm, l->e->v2, 1);
}
}
- else
- tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+
+ luv1->flag |= MLOOPUV_VERTSEL;
+ luv2->flag |= MLOOPUV_VERTSEL;
+ }
}
-void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_edge_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
+
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- EM_select_face(efa, 0);
+ BM_Select(em->bm, l->f, 0);
else if(ts->selectmode == SCE_SELECT_EDGE)
- EM_select_edge((*(&efa->e1 + i)), 0);
+ BM_Select(em->bm, l->e, 0);
else {
- (efa->v1 + i)->f &= ~SELECT;
- (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
+ BM_Select(em->bm, l->e->v1, 0);
+ BM_Select(em->bm, l->e->v2, 0);
}
}
- else
- tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+
+ luv1->flag &= ~MLOOPUV_VERTSEL;
+ luv2->flag &= ~MLOOPUV_VERTSEL;
+ }
}
-int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+int uvedit_uv_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- return (efa->f & SELECT);
+ return BM_TestHFlag(l->f, BM_SELECT);
else
- return (*(&efa->v1 + i))->f & SELECT;
+ return BM_TestHFlag(l, BM_SELECT);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ return luv->flag & MLOOPUV_VERTSEL;
}
- else
- return tf->flag & TF_SEL_MASK(i);
}
-void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_uv_select(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- EM_select_face(efa, 1);
+ BM_Select(em->bm, l->f, 1);
else
- (*(&efa->v1 + i))->f |= SELECT;
+ BM_Select(em->bm, l->v, 1);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag |= MLOOPUV_VERTSEL;
}
- else
- tf->flag |= TF_SEL_MASK(i);
}
-void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode == SCE_SELECT_FACE)
- EM_select_face(efa, 0);
+ BM_Select(em->bm, l->f, 0);
else
- (*(&efa->v1 + i))->f &= ~SELECT;
+ BM_Select(em->bm, l->v, 0);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag &= ~MLOOPUV_VERTSEL;
}
- else
- tf->flag &= ~TF_SEL_MASK(i);
}
/*********************** geometric utilities ***********************/
+void poly_uv_center(BMEditMesh *em, BMFace *f, float cent[2])
+{
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ cent[0] = cent[1] = 0.0f;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ cent[0] += luv->uv[0];
+ cent[1] += luv->uv[1];
+ }
+
+ cent[0] /= (float) f->len;
+ cent[1] /= (float) f->len;
+}
+
void uv_center(float uv[][2], float cent[2], int quad)
{
@@ -364,6 +443,28 @@ float uv_area(float uv[][2], int quad)
return AreaF2Dfl(uv[0], uv[1], uv[2]);
}
+float poly_uv_area(float uv[][2], int len)
+{
+ //BMESH_TODO: make this not suck
+ //maybe use scanfill? I dunno.
+
+ if(len >= 4)
+ return AreaF2Dfl(uv[0], uv[1], uv[2]) + AreaF2Dfl(uv[0], uv[2], uv[3]);
+ else
+ return AreaF2Dfl(uv[0], uv[1], uv[2]);
+
+ return 1.0;
+}
+
+void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
+{
+ int i;
+ for (i=0; i<len; i++) {
+ uv[i][0] = uv_orig[i][0]*aspx;
+ uv[i][1] = uv_orig[i][1]*aspy;
+ }
+}
+
void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
{
uv[0][0] = uv_orig[0][0]*aspx;
@@ -381,33 +482,42 @@ void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
int sel;
INIT_MINMAX2(min, max);
sel= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
- if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
- if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
- if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l))
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max);
+ sel = 1;
+ }
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
+
return sel;
}
-int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mode)
+int uvedit_center(Scene *scene, Image *ima, Object *obedit,
+ float *cent, int mode)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float min[2], max[2];
int change= 0;
@@ -418,14 +528,18 @@ int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mod
else if(mode==1) {
INIT_MINMAX2(min, max);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); change= 1;}
- if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); change= 1;}
- if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); change= 1;}
- if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); change= 1;}
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ DO_MINMAX2(luv->uv, min, max);
+ change= 1;
+ }
}
}
}
@@ -434,108 +548,147 @@ int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mod
cent[0]= (min[0]+max[0])/2.0;
cent[1]= (min[1]+max[1])/2.0;
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
/************************** find nearest ****************************/
typedef struct NearestHit {
- EditFace *efa;
- MTFace *tf;
-
- int vert, uv;
- int edge, vert2;
+ BMFace *efa;
+ MTexPoly *tf;
+ BMLoop *l, *nextl;
+ MLoopUV *luv, *nextluv;
+ int lindex; //index of loop within face
+ int vert1, vert2; //index in mesh of edge vertices
} NearestHit;
-static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
{
- MTFace *tf;
- EditFace *efa;
- EditVert *eve;
+ MTexPoly *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMVert *eve;
+ BMIter iter, liter;
+ MLoopUV *luv, *nextluv;
float mindist, dist;
- int i, nverts;
+ int i;
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
- for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
- eve->tmp.l = i;
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ BMINDEX_SET(eve, i);
+ }
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ nextluv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
- for(i=0; i<nverts; i++) {
- dist= PdistVL2Dfl(co, tf->uv[i], tf->uv[(i+1)%nverts]);
+ dist= PdistVL2Dfl(co, luv->uv, nextluv->uv);
- if(dist < mindist) {
- hit->tf= tf;
- hit->efa= efa;
- hit->edge= i;
- mindist= dist;
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+
+ hit->l = l;
+ hit->nextl = (BMLoop*)l->head.next;
+ hit->luv = luv;
+ hit->nextluv = nextluv;
+ hit->lindex = i;
+ hit->vert1 = BMINDEX_GET(hit->l->v);
+ hit->vert2 = BMINDEX_GET(((BMLoop*)hit->l->head.next)->v);
- hit->vert= (*(&efa->v1 + i))->tmp.l;
- hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
- }
+ mindist = dist;
}
+
+ i++;
}
}
}
-static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
{
- MTFace *tf;
- EditFace *efa;
+ MTexPoly *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float mindist, dist, cent[2];
- int i, nverts;
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
- cent[0]= cent[1]= 0.0f;
+ /*this will fill in hit.vert1 and hit.vert2*/
+ find_nearest_uv_edge(scene, ima, em, co, hit);
+ hit->l = hit->nextl = NULL;
+ hit->luv = hit->nextluv = NULL;
- for(i=0; i<nverts; i++) {
- cent[0] += tf->uv[i][0];
- cent[1] += tf->uv[i][1];
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ cent[0]= cent[1]= 0.0f;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- cent[0] /= nverts;
- cent[1] /= nverts;
- dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
+ cent[0] += luv->uv[0];
+ cent[1] += luv->uv[1];
+ }
- if(dist < mindist) {
- hit->tf= tf;
- hit->efa= efa;
- mindist= dist;
- }
+ cent[0] /= efa->len;
+ cent[1] /= efa->len;
+ dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
+
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+ mindist= dist;
}
}
}
-static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
+static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int nverts, int id,
+ float co[2], float uv[2])
{
- float m[3], v1[3], v2[3], c1, c2;
- int id1, id2;
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter iter;
+ float m[3], v1[3], v2[3], c1, c2, *uv1, *uv2, *uv3;
+ int id1, id2, i;
- id1= (id+nverts-1)%nverts;
- id2= (id+nverts+1)%nverts;
+ id1= (id+efa->len-1)%efa->len;
+ id2= (id+efa->len+1)%efa->len;
m[0]= co[0]-uv[0];
m[1]= co[1]-uv[1];
- Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
- Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
+
+ i = 0;
+ BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (i == id1)
+ uv1 = luv->uv;
+ else if (i == id)
+ uv2 = luv->uv;
+ else if (i == id2)
+ uv3 = luv->uv;
+
+ i++;
+ }
+
+ VecSubf(v1, uv1, uv);
+ VecSubf(v2, uv3, uv);
/* m and v2 on same side of v-v1? */
c1= v1[0]*m[1] - v1[1]*m[0];
@@ -551,83 +704,103 @@ static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float
return (c1*c2 >= 0.0f);
}
-static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
+static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em,
+ float co[2], float penalty[2], NearestHit *hit)
{
- EditFace *efa;
- EditVert *eve;
- MTFace *tf;
+ BMFace *efa;
+ BMVert *eve;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float mindist, dist;
int i, nverts;
+ /*this will fill in hit.vert1 and hit.vert2*/
+ find_nearest_uv_edge(scene, ima, em, co, hit);
+ hit->l = hit->nextl = NULL;
+ hit->luv = hit->nextluv = NULL;
+
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
- for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
- eve->tmp.l = i;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ BMINDEX_SET(eve, i);
+ }
- for(i=0; i<nverts; i++) {
- if(penalty && uvedit_uv_selected(scene, efa, tf, i))
- dist= fabs(co[0]-tf->uv[i][0])+penalty[0] + fabs(co[1]-tf->uv[i][1])+penalty[1];
- else
- dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(dist<=mindist) {
- if(dist==mindist)
- if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
- continue;
+ if(penalty && uvedit_uv_selected(em, scene, l))
+ dist= fabs(co[0]-luv->uv[0])+penalty[0] + fabs(co[1]-luv->uv[1])+penalty[1];
+ else
+ dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
- mindist= dist;
+ if(dist<=mindist) {
+ if(dist==mindist)
+ if(!nearest_uv_between(em, efa, efa->len, i, co, luv->uv)) {
+ i++;
+ continue;
+ }
- hit->uv= i;
- hit->tf= tf;
- hit->efa= efa;
+ mindist= dist;
- hit->vert= (*(&efa->v1 + i))->tmp.l;
- }
+ hit->l = l;
+ hit->nextl = (BMLoop*)l->head.next;
+ hit->luv = luv;
+ hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->head.next->data, CD_MLOOPUV);
+ hit->tf= tf;
+ hit->efa= efa;
+ hit->lindex = i;
+ hit->vert1 = BMINDEX_GET(hit->l->v);
}
+
+ i++;
}
}
}
int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float mindist, dist;
- int i, nverts, found= 0;
+ int found= 0;
mindist= 1e10f;
uv[0]= co[0];
uv[1]= co[1];
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
-
- for(i=0; i<nverts; i++) {
- dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
- if(dist<=mindist) {
- mindist= dist;
+ if(dist<=mindist) {
+ mindist= dist;
- uv[0]= tf->uv[i][0];
- uv[1]= tf->uv[i][1];
- found= 1;
- }
+ uv[0]= luv->uv[0];
+ uv[1]= luv->uv[1];
+ found= 1;
}
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
return found;
}
@@ -649,26 +822,28 @@ static void uv_vertex_loop_flag(UvMapVert *first)
first->flag= 1;
}
-static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
+static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a)
{
UvMapVert *iterv, *first;
-
- first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
+ BMLoop *l;
+
+ l = BMIter_AtIndex(NULL, BM_LOOPS_OF_FACE, efa, a);
+ first= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v));
for(iterv=first; iterv; iterv=iterv->next) {
if(iterv->separate)
first= iterv;
- if(iterv->f == efa->tmp.l)
+ if(iterv->f == BMINDEX_GET(efa))
return first;
}
return NULL;
}
-static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
+static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface)
{
UvMapVert *iterv1, *iterv2;
- EditFace *efa;
+ BMFace *efa;
int tot = 0;
/* count number of faces this edge has */
@@ -682,8 +857,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
if(iterv1->f == iterv2->f) {
/* if face already tagged, don't do this edge */
- efa= EM_get_face_for_index(iterv1->f);
- if(efa->f1)
+ efa= EDBM_get_face_for_index(em, iterv1->f);
+ if(BMO_TestFlag(em->bm, efa, EFA_F1_FLAG))
return 0;
tot++;
@@ -707,8 +882,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
break;
if(iterv1->f == iterv2->f) {
- efa= EM_get_face_for_index(iterv1->f);
- efa->f1= 1;
+ efa= EDBM_get_face_for_index(em, iterv1->f);
+ BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
break;
}
}
@@ -717,41 +892,47 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
return 1;
}
-static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
+static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit, float limit[2], int extend)
{
- EditVert *eve;
- EditFace *efa;
- MTFace *tf;
+ BMVert *eve;
+ BMFace *efa;
+ BMIter iter, liter;
+ BMLoop *l;
+ MTexPoly *tf;
UvVertMap *vmap;
UvMapVert *iterv1, *iterv2;
int a, count, looking, nverts, starttotf, select;
/* setup */
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
- for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
- eve->tmp.l = count;
+ count = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(eve, count);
+ count++;
+ }
- for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
+ count = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(!extend) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_deselect(scene, efa, tf);
+ uvedit_face_deselect(scene, em, efa);
}
-
- efa->tmp.l= count;
- efa->f1= 0;
+
+ BMO_ClearFlag(em->bm, efa, EFA_F1_FLAG);
+ BMINDEX_SET(efa, count);
+ count++;
}
-
+
/* set flags for first face and verts */
- nverts= (hit->efa->v4)? 4: 3;
- iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
- iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ nverts= hit->efa->len;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
uv_vertex_loop_flag(iterv1);
uv_vertex_loop_flag(iterv2);
starttotf= 0;
- uv_edge_tag_faces(iterv1, iterv2, &starttotf);
+ uv_edge_tag_faces(em, iterv1, iterv2, &starttotf);
/* sorry, first edge isnt even ok */
if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
@@ -762,21 +943,25 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
looking= 0;
/* find correct valence edges which are not tagged yet, but connect to tagged one */
- for(efa= em->faces.first; efa; efa=efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= (efa->v4)? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ if(!BMO_TestFlag(em->bm, efa, EFA_F1_FLAG) && uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->len;
for(a=0; a<nverts; a++) {
/* check face not hidden and not tagged */
iterv1= uv_vertex_map_get(vmap, efa, a);
iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
+
+ if (!iterv1 || !iterv2)
+ continue;
/* check if vertex is tagged and has right valence */
if(iterv1->flag || iterv2->flag) {
- if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
+ if(uv_edge_tag_faces(em, iterv1, iterv2, &starttotf)) {
looking= 1;
- efa->f1= 1;
+ BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
uv_vertex_loop_flag(iterv1);
uv_vertex_loop_flag(iterv2);
@@ -789,16 +974,14 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
}
/* do the actual select/deselect */
- nverts= (hit->efa->v4)? 4: 3;
- iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
- iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ nverts= hit->efa->len;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
iterv1->flag= 1;
iterv2->flag= 1;
if(extend) {
- tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
-
- if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
+ if(uvedit_uv_selected(em, scene, hit->l) && uvedit_uv_selected(em, scene, hit->l))
select= 0;
else
select= 1;
@@ -806,66 +989,82 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
else
select= 1;
- for(efa= em->faces.first; efa; efa=efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- nverts= (efa->v4)? 4: 3;
- for(a=0; a<nverts; a++) {
+ a = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
iterv1= uv_vertex_map_get(vmap, efa, a);
if(iterv1->flag) {
- if(select) uvedit_uv_select(scene, efa, tf, a);
- else uvedit_uv_deselect(scene, efa, tf, a);
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
+
+ a++;
}
}
/* cleanup */
- EM_free_uv_vert_map(vmap);
- EM_free_index_arrays();
+ EDBM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
return (select)? 1: -1;
}
/*********************** linked select ***********************/
-static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
+static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[2], NearestHit *hit, int extend)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
UvVertMap *vmap;
UvMapVert *vlist, *iterv, *startv;
int a, i, nverts, j, stacksize= 0, *stack;
char *flag;
- vmap= EM_make_uv_vert_map(em, 1, 1, limit);
+ vmap= EDBM_make_uv_vert_map(em, 1, 1, limit);
if(vmap == NULL)
return;
- stack= MEM_mallocN(sizeof(*stack)* BLI_countlist(&em->faces), "UvLinkStack");
- flag= MEM_callocN(sizeof(*flag)*BLI_countlist(&em->faces), "UvLinkFlag");
+ stack= MEM_mallocN(sizeof(*stack)*em->bm->totface, "UvLinkStack");
+ flag= MEM_callocN(sizeof(*flag)*em->bm->totface, "UvLinkFlag");
if(!hit) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
- stack[stacksize]= a;
- stacksize++;
- flag[a]= 1;
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+
+ break;
+ }
}
}
}
+ a++;
}
else {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(efa == hit->efa) {
stack[stacksize]= a;
stacksize++;
flag[a]= 1;
break;
}
+
+ a++;
}
}
@@ -873,15 +1072,21 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2]
stacksize--;
a= stack[stacksize];
- for(j=0, efa= em->faces.first; efa; efa= efa->next, j++)
+ j = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(j==a)
break;
- nverts= efa->v4? 4: 3;
+ j++;
+ }
+
+ nverts= efa->len;
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
- for(i=0; i<nverts; i++) {
/* make_uv_vert_map_EM sets verts tmp.l to the indicies */
- vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+ vlist= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v));
startv= vlist;
@@ -897,56 +1102,74 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2]
break;
else if(!flag[iterv->f]) {
flag[iterv->f]= 1;
- stack[stacksize]= iterv->f;;
+ stack[stacksize]= iterv->f;
stacksize++;
}
}
+
+ i++;
}
}
- if(!extend || hit) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(flag[a])
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- else
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ if(!extend || hit) {
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (flag[a])
+ luv->flag |= MLOOPUV_VERTSEL;
+ else
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
else if(extend && hit) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(efa->v4) {
- if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
- break;
- }
- else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL)
break;
}
+
+ a++;
}
if(efa) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!flag[a]) continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag &= ~MLOOPUV_VERTSEL;
}
+
+ a++;
}
}
else {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!flag[a]) continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag |= MLOOPUV_VERTSEL;
}
+
+ a++;
}
}
}
MEM_freeN(stack);
MEM_freeN(flag);
- EM_free_uv_vert_map(vmap);
+ EDBM_free_uv_vert_map(vmap);
}
/* ******************** align operator **************** */
@@ -956,31 +1179,33 @@ static void weld_align_uv(bContext *C, int tool)
Scene *scene;
Object *obedit;
Image *ima;
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float cent[2], min[2], max[2];
scene= CTX_data_scene(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
INIT_MINMAX2(min, max);
if(tool == 'a') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- DO_MINMAX2(tf->uv[0], min, max)
- if(uvedit_uv_selected(scene, efa, tf, 1))
- DO_MINMAX2(tf->uv[1], min, max)
- if(uvedit_uv_selected(scene, efa, tf, 2))
- DO_MINMAX2(tf->uv[2], min, max)
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- DO_MINMAX2(tf->uv[3], min, max)
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max)
+ }
}
}
@@ -990,41 +1215,39 @@ static void weld_align_uv(bContext *C, int tool)
uvedit_center(scene, ima, obedit, cent, 0);
if(tool == 'x' || tool == 'w') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- tf->uv[0][0]= cent[0];
- if(uvedit_uv_selected(scene, efa, tf, 1))
- tf->uv[1][0]= cent[0];
- if(uvedit_uv_selected(scene, efa, tf, 2))
- tf->uv[2][0]= cent[0];
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- tf->uv[3][0]= cent[0];
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = cent[0];
+ }
+
}
}
}
if(tool == 'y' || tool == 'w') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- tf->uv[0][1]= cent[1];
- if(uvedit_uv_selected(scene, efa, tf, 1))
- tf->uv[1][1]= cent[1];
- if(uvedit_uv_selected(scene, efa, tf, 2))
- tf->uv[2][1]= cent[1];
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- tf->uv[3][1]= cent[1];
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[1] = cent[1];
+ }
+
}
}
}
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int align_exec(bContext *C, wmOperator *op)
@@ -1089,36 +1312,39 @@ static int stitch_exec(bContext *C, wmOperator *op)
SpaceImage *sima;
Scene *scene;
Object *obedit;
- EditMesh *em;
- EditFace *efa;
- EditVert *eve;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ BMVert *eve;
Image *ima;
- MTFace *tf;
+ MTexPoly *tf;
+ MLoopUV *luv;
sima= CTX_wm_space_image(C);
scene= CTX_data_scene(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
if(RNA_boolean_get(op->ptr, "use_limit")) {
UvVertMap *vmap;
UvMapVert *vlist, *iterv;
- float newuv[2], limit[2];
+ float newuv[2], limit[2], pixels;
int a, vtot;
- limit[0]= RNA_float_get(op->ptr, "limit");
- limit[1]= limit[0];
+ pixels= RNA_float_get(op->ptr, "limit");
+ uvedit_pixel_to_float(sima, limit, pixels);
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 1, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 1, 0, limit);
if(vmap == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
-
- for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
+
+ a = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
vlist= EM_get_uv_map_vert(vmap, a);
while(vlist) {
@@ -1129,12 +1355,15 @@ static int stitch_exec(bContext *C, wmOperator *op)
if((iterv != vlist) && iterv->separate)
break;
- efa = EM_get_face_for_index(iterv->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
- newuv[0] += tf->uv[iterv->tfindex][0];
- newuv[1] += tf->uv[iterv->tfindex][1];
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ newuv[0] += luv->uv[0];
+ newuv[1] += luv->uv[1];
vtot++;
}
}
@@ -1146,95 +1375,72 @@ static int stitch_exec(bContext *C, wmOperator *op)
if((iterv != vlist) && iterv->separate)
break;
- efa = EM_get_face_for_index(iterv->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
- tf->uv[iterv->tfindex][0]= newuv[0];
- tf->uv[iterv->tfindex][1]= newuv[1];
+ luv->uv[0] = newuv[0];
+ luv->uv[1] = newuv[1];
+ vtot++;
}
}
}
vlist= iterv;
}
+
+ a++;
}
- EM_free_uv_vert_map(vmap);
- EM_free_index_arrays();
+ EDBM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
}
else {
UVVertAverage *uv_average, *uvav;
int count;
// index and count verts
- for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
- eve->tmp.l = count;
+ count=0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(eve, count);
+ count++;
+ }
uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
// gather uv averages per vert
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) {
- uvav = uv_average + efa->v1->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[0][0];
- uvav->uv[1] += tf->uv[0][1];
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 1)) {
- uvav = uv_average + efa->v2->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[1][0];
- uvav->uv[1] += tf->uv[1][1];
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 2)) {
- uvav = uv_average + efa->v3->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[2][0];
- uvav->uv[1] += tf->uv[2][1];
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uvav = uv_average + BMINDEX_GET(l->v);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
- uvav = uv_average + efa->v4->tmp.l;
uvav->count++;
- uvav->uv[0] += tf->uv[3][0];
- uvav->uv[1] += tf->uv[3][1];
+ uvav->uv[0] += luv->uv[0];
+ uvav->uv[1] += luv->uv[1];
}
}
}
// apply uv welding
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) {
- uvav = uv_average + efa->v1->tmp.l;
- tf->uv[0][0] = uvav->uv[0]/uvav->count;
- tf->uv[0][1] = uvav->uv[1]/uvav->count;
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 1)) {
- uvav = uv_average + efa->v2->tmp.l;
- tf->uv[1][0] = uvav->uv[0]/uvav->count;
- tf->uv[1][1] = uvav->uv[1]/uvav->count;
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 2)) {
- uvav = uv_average + efa->v3->tmp.l;
- tf->uv[2][0] = uvav->uv[0]/uvav->count;
- tf->uv[2][1] = uvav->uv[1]/uvav->count;
- }
-
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
- uvav = uv_average + efa->v4->tmp.l;
- tf->uv[3][0] = uvav->uv[0]/uvav->count;
- tf->uv[3][1] = uvav->uv[1]/uvav->count;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uvav = uv_average + BMINDEX_GET(l->v);
+ luv->uv[0] = uvav->uv[0]/uvav->count;
+ luv->uv[1] = uvav->uv[1]/uvav->count;
}
}
}
@@ -1245,7 +1451,6 @@ static int stitch_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1262,7 +1467,7 @@ void UV_OT_stitch(wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance.");
- RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels.", -FLT_MAX, FLT_MAX);
}
/* ******************** (de)select all operator **************** */
@@ -1272,36 +1477,39 @@ static int select_inverse_exec(bContext *C, wmOperator *op)
Scene *scene;
ToolSettings *ts;
Object *obedit;
- EditMesh *em;
- EditFace *efa;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
Image *ima;
- MTFace *tf;
+ MTexPoly *tf;
+ MLoopUV *luv;
scene= CTX_data_scene(C);
ts= CTX_data_tool_settings(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_select_swap(em);
+ EDBM_select_swap(em);
}
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- tf->flag ^= TF_SEL1;
- tf->flag ^= TF_SEL2;
- tf->flag ^= TF_SEL3;
- if(efa->v4) tf->flag ^= TF_SEL4;
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag = luv->flag ^ MLOOPUV_VERTSEL;
}
}
}
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1324,54 +1532,59 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
Scene *scene;
ToolSettings *ts;
Object *obedit;
- EditMesh *em;
- EditFace *efa;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
Image *ima;
- MTFace *tf;
- int sel;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ int sel = 1;
scene= CTX_data_scene(C);
ts= CTX_data_tool_settings(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
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;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(tf->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
- sel= 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ sel= 0;
break;
}
}
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(efa->v4) {
- if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
- else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
- }
- else {
- if(sel) tf->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
- else tf->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
- }
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (sel) luv->flag |= MLOOPUV_VERTSEL;
+ else luv->flag &= ~MLOOPUV_VERTSEL;
}
}
}
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1389,7 +1602,7 @@ void UV_OT_select_all_toggle(wmOperatorType *ot)
/* ******************** mouse select operator **************** */
-static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
+static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen)
{
int i;
@@ -1398,7 +1611,7 @@ static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], floa
if(sticky == SI_STICKY_DISABLE)
return 0;
- for(i=0; i<4; i++) {
+ for(i=0; i<hitlen; i++) {
if(hitv[i] == v) {
if(sticky == SI_STICKY_LOC) {
if(fabs(hituv[i][0]-uv[0]) < limit[0] && fabs(hituv[i][1]-uv[1]) < limit[1])
@@ -1419,14 +1632,20 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
NearestHit hit;
- int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
- int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
- float limit[2], *hituv[4], penalty[2];
-
+ int a, i, select = 1, selectmode, sticky, sync, *hitv=NULL, nvert;
+ BLI_array_declare(hitv);
+ int flush = 0, hitlen=0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
+ float limit[2], **hituv = NULL;
+ BLI_array_declare(hituv);
+ float penalty[2];
+
uvedit_pixel_to_float(sima, limit, 0.05f);
uvedit_pixel_to_float(sima, penalty, 5.0f);
@@ -1446,7 +1665,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
else {
sync= 0;
selectmode= ts->uv_selectmode;
- sticky= (sima)? sima->sticky: 1;
+ sticky= sima->sticky;
}
/* find nearest element */
@@ -1454,76 +1673,88 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
+
+ hitlen = 0;
}
else if(selectmode == UV_SELECT_VERTEX) {
/* find vertex */
find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
/* mark 1 vertex as being hit */
- for(i=0; i<4; i++)
+ for(i=0; i<hit.efa->len; i++) {
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
hitv[i]= 0xFFFFFFFF;
+ }
+
+ hitv[hit.lindex]= hit.vert1;
+ hituv[hit.lindex]= hit.luv->uv;
- hitv[hit.uv]= hit.vert;
- hituv[hit.uv]= hit.tf->uv[hit.uv];
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_EDGE) {
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
/* mark 2 edge vertices as being hit */
- for(i=0; i<4; i++)
+ for(i=0; i<hit.efa->len; i++) {
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
hitv[i]= 0xFFFFFFFF;
+ }
+
+ nvert= hit.efa->len;
- nvert= (hit.efa->v4)? 4: 3;
+ hitv[hit.lindex]= hit.vert1;
+ hitv[(hit.lindex+1)%nvert]= hit.vert2;
+ hituv[hit.lindex]= hit.luv->uv;
+ hituv[(hit.lindex+1)%nvert]= hit.nextluv->uv;
- hitv[hit.edge]= hit.vert;
- hitv[(hit.edge+1)%nvert]= hit.vert2;
- hituv[hit.edge]= hit.tf->uv[hit.edge];
- hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_FACE) {
/* find face */
find_nearest_uv_face(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
/* make active */
- EM_set_actFace(em, hit.efa);
+ EDBM_set_actFace(em, hit.efa);
/* mark all face vertices as being hit */
- for(i=0; i<4; i++)
- hituv[i]= hit.tf->uv[i];
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, hit.efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- hitv[0]= hit.efa->v1->tmp.l;
- hitv[1]= hit.efa->v2->tmp.l;
- hitv[2]= hit.efa->v3->tmp.l;
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
+ hituv[i]= luv->uv;
+ hitv[i] = BMINDEX_GET(l->v);
+ i++;
+ }
- if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
- else hitv[3]= 0xFFFFFFFF;
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_ISLAND) {
find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
if(hit.efa==NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
+
+ hitlen = 0;
}
else {
- BKE_mesh_end_editmesh(obedit->data, em);
+ hitlen = 0;
return OPERATOR_CANCELLED;
}
@@ -1537,36 +1768,36 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
else if(extend) {
if(selectmode == UV_SELECT_VERTEX) {
/* (de)select uv vertex */
- if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
- uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
+ if(uvedit_uv_selected(em, scene, hit.l)) {
+ uvedit_uv_deselect(em, scene, hit.l);
select= 0;
}
else {
- uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ uvedit_uv_select(em, scene, hit.l);
select= 1;
}
flush = 1;
}
else if(selectmode == UV_SELECT_EDGE) {
/* (de)select edge */
- if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
- uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
+ if(uvedit_edge_selected(em, scene, hit.l)) {
+ uvedit_edge_deselect(em, scene, hit.l);
select= 0;
}
else {
- uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ uvedit_edge_select(em, scene, hit.l);
select= 1;
}
flush = 1;
}
else if(selectmode == UV_SELECT_FACE) {
/* (de)select face */
- if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
- uvedit_face_deselect(scene, hit.efa, hit.tf);
+ if(uvedit_face_selected(scene, em, hit.efa)) {
+ uvedit_face_deselect(scene, em, hit.efa);
select= 0;
}
else {
- uvedit_face_select(scene, hit.efa, hit.tf);
+ uvedit_face_select(scene, em, hit.efa);
select= 1;
}
flush = -1;
@@ -1574,97 +1805,89 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
/* (de)select sticky uv nodes */
if(sticky != SI_STICKY_DISABLE) {
- EditVert *ev;
-
- for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
- ev->tmp.l = a;
+ BMVert *ev;
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(ev, a);
+ a++;
+ }
+
/* deselect */
if(select==0) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_deselect(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_deselect(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_deselect(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_deselect(scene, efa, tf, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_deselect(em, scene, l);
}
}
flush = -1;
}
/* select */
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_select(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_select(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_select(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_select(scene, efa, tf, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_select(em, scene, l);
}
}
-
+
flush = 1;
}
}
}
else {
/* deselect all */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_deselect(scene, efa, tf);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ uvedit_face_deselect(scene, em, efa);
}
if(selectmode == UV_SELECT_VERTEX) {
/* select vertex */
- uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ uvedit_uv_select(em, scene, hit.l);
flush= 1;
}
else if(selectmode == UV_SELECT_EDGE) {
/* select edge */
- uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ uvedit_edge_select(em, scene, hit.l);
flush= 1;
}
else if(selectmode == UV_SELECT_FACE) {
/* select face */
- uvedit_face_select(scene, hit.efa, hit.tf);
+ uvedit_face_select(scene, em, hit.efa);
}
/* select sticky uvs */
if(sticky != SI_STICKY_DISABLE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
if(sticky == SI_STICKY_DISABLE) continue;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_select(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_select(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_select(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_select(scene, efa, tf, 3);
+ if(sticky_select(limit, hitv, BMINDEX_GET(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_select(em, scene, l);
flush= 1;
}
}
}
}
-
+#if 0 //bmesh does flushing through the BM_Select functions, so not sure
+ //what to do about this bit.
if(sync) {
/* flush for mesh selection */
if(ts->selectmode != SCE_SELECT_FACE) {
@@ -1672,11 +1895,10 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
else if(flush==-1) EM_deselect_flush(em);
}
}
-
+#endif
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
}
@@ -1783,13 +2005,12 @@ static int select_linked_exec(bContext *C, wmOperator *op)
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
float limit[2];
int extend;
if(ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -1800,7 +2021,6 @@ static int select_linked_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1828,27 +2048,38 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
if(ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int desel = 0;
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(efa->v4) {
- if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->pdata, l->head.data, CD_MLOOPUV);
+
+ if (!(luv->flag & MLOOPUV_VERTSEL)) {
+ desel = 1;
+ break;
}
- else {
- if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
+ }
+
+ if (desel) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->pdata, l->head.data, CD_MLOOPUV);
+ luv->flag &= ~MLOOPUV_VERTSEL;
}
}
}
@@ -1856,7 +2087,6 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1890,78 +2120,77 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
* selection (so for sticky modes, vertex or location based). */
ToolSettings *ts= CTX_data_tool_settings(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
- int nverts, i;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
- * in the loop and select all MTFace UV's that use a touched vert. */
- EditVert *eve;
+ * in the loop and select all MLoopUV's that use a touched vert. */
+ BMVert *eve;
- for(eve= em->verts.first; eve; eve= eve->next)
- eve->tmp.l = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
+ BMINDEX_SET(eve, 0);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->tmp.l) {
- if(efa->v4)
- efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
- else
- efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BMINDEX_GET(efa)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ BMINDEX_SET(l->v, 1);
+ }
}
}
/* now select tagged verts */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- nverts= efa->v4? 4: 3;
- for(i=0; i<nverts; i++) {
- if((*(&efa->v1 + i))->tmp.l) {
- if(select)
- uvedit_uv_select(scene, efa, tf, i);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BMINDEX_GET(l->v)) {
+ if (select)
+ uvedit_uv_select(em, scene, l);
else
- uvedit_uv_deselect(scene, efa, tf, i);
+ uvedit_uv_deselect(em, scene, l);
}
}
}
}
else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
- EditFace *efa_vlist;
- MTFace *tf_vlist;
+ BMFace *efa_vlist;
+ MTexPoly *tf_vlist;
UvMapVert *start_vlist=NULL, *vlist_iter;
struct UvVertMap *vmap;
float limit[2];
int efa_index;
- //EditVert *eve; /* removed vert counting for now */
+ //BMVert *eve; /* removed vert counting for now */
//int a;
uvedit_pixel_to_float(sima, limit, 0.05);
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
/* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
/*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
eve->tmp.l = a; */
if(vmap == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return;
}
- for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
- if(efa->tmp.l) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- nverts= efa->v4? 4: 3;
-
- for(i=0; i<nverts; i++) {
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for (efa_index=0; efa; efa=BMIter_Step(&iter), efa_index++) {
+ if(BMINDEX_GET(efa)) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
if(select)
- uvedit_uv_select(scene, efa, tf, i);
+ uvedit_uv_select(em, scene, l);
else
- uvedit_uv_deselect(scene, efa, tf, i);
+ uvedit_uv_deselect(em, scene, l);
- vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+ vlist_iter= EDBM_get_uv_map_vert(vmap, BMINDEX_GET(l->v));
while (vlist_iter) {
if(vlist_iter->separate)
@@ -1980,35 +2209,33 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
break;
if(efa_index != vlist_iter->f) {
- efa_vlist = EM_get_face_for_index(vlist_iter->f);
- tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
+ efa_vlist = EDBM_get_face_for_index(em, vlist_iter->f);
+ tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY);
if(select)
- uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ uvedit_uv_select(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
else
- uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ uvedit_uv_deselect(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
}
vlist_iter = vlist_iter->next;
}
}
}
}
- EM_free_index_arrays();
- EM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
+ EDBM_free_uv_vert_map(vmap);
}
else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->tmp.l) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BMINDEX_GET(efa)) {
if(select)
- uvedit_face_select(scene, efa, tf);
+ uvedit_face_select(scene, em, efa);
else
- uvedit_face_deselect(scene, efa, tf);
+ uvedit_face_deselect(scene, em, efa);
}
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int border_select_exec(bContext *C, wmOperator *op)
@@ -2019,9 +2246,12 @@ static int border_select_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
ARegion *ar= CTX_wm_region(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
rcti rect;
rctf rectf;
int change, pinned, select, faces;
@@ -2051,14 +2281,16 @@ static int border_select_exec(bContext *C, wmOperator *op)
change= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
/* assume not touched */
- efa->tmp.l = 0;
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- uv_center(tface->uv, cent, efa->v4 != NULL);
+ BMINDEX_SET(efa, 0);
+
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ poly_uv_center(em, efa, cent);
if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
- efa->tmp.l = change = 1;
+ BMINDEX_SET(efa, 1);
+ change = 1;
}
}
}
@@ -2070,51 +2302,26 @@ static int border_select_exec(bContext *C, wmOperator *op)
else {
/* other selection modes */
change= 1;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
+
/* UV_SYNC_SELECTION - can't do pinned selection */
- if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 0);
- else uvedit_uv_deselect(scene, efa, tface, 0);
- }
- if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 1);
- else uvedit_uv_deselect(scene, efa, tface, 1);
- }
- if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 2);
- else uvedit_uv_deselect(scene, efa, tface, 2);
- }
- if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 3);
- else uvedit_uv_deselect(scene, efa, tface, 3);
- }
- }
- else if(pinned) {
- if((tface->unwrap & TF_PIN1) &&
- BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 0);
- else uvedit_uv_deselect(scene, efa, tface, 0);
- }
- if((tface->unwrap & TF_PIN2) &&
- BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 1);
- else uvedit_uv_deselect(scene, efa, tface, 1);
- }
- if((tface->unwrap & TF_PIN3) &&
- BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 2);
- else uvedit_uv_deselect(scene, efa, tface, 2);
+ if(BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
- if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 3);
- else uvedit_uv_deselect(scene, efa, tface, 3);
+ } else if(pinned) {
+ if ((luv->flag & MLOOPUV_PINNED) &&
+ BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
}
}
@@ -2123,20 +2330,20 @@ static int border_select_exec(bContext *C, wmOperator *op)
if(change) {
/* make sure newly selected vert selection is updated*/
+#if 0 //ok, I think the BM_Select API handles all of this?
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode != SCE_SELECT_FACE) {
if(select) EM_select_flush(em);
else EM_deselect_flush(em);
}
}
+#endif
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
+
return OPERATOR_CANCELLED;
}
@@ -2167,20 +2374,23 @@ void UV_OT_select_border(wmOperatorType *ot)
/* ******************** circle select operator **************** */
-static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
+static void select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *sima,
+ Scene *scene, int select, float *offset,
+ float *ell, BMLoop *l, MLoopUV *luv)
{
/* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
float x, y, r2, *uv;
- uv= tface->uv[index];
+
+ uv= luv->uv;
x= (uv[0] - offset[0])*ell[0];
y= (uv[1] - offset[1])*ell[1];
r2 = x*x + y*y;
if(r2 < 1.0) {
- if(select) uvedit_uv_select(scene, efa, tface, select_index);
- else uvedit_uv_deselect(scene, efa, tface, select_index);
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
}
@@ -2189,10 +2399,13 @@ int circle_select_exec(bContext *C, wmOperator *op)
SpaceImage *sima= CTX_wm_space_image(C);
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;
ARegion *ar= CTX_wm_region(C);
- EditFace *efa;
- MTFace *tface;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ MTexPoly *tface;
int x, y, radius, width, height, select;
float zoomx, zoomy, offset[2], ellipse[2];
@@ -2213,21 +2426,19 @@ int circle_select_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
/* do selection */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0);
- select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1);
- select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2);
- if(efa->v4)
- select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv);
+ }
}
+#if 0 //I think the BM_Select api stuff handles all this as necassary?
if(select) EM_select_flush(em);
else EM_deselect_flush(em);
-
+#endif
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2325,97 +2536,88 @@ void UV_OT_snap_cursor(wmOperatorType *ot)
static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, View2D *v2d)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
short change= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], v2d->cursor);
- if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], v2d->cursor);
- if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], v2d->cursor);
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], v2d->cursor);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- change= 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ VECCOPY2D(luv->uv, v2d->cursor);
+ change= 1;
+ }
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- EditVert *eve;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ BMVert *eve;
+ MTexPoly *tface;
+ MLoopUV *luv;
short change = 0;
int count = 0;
float *coords;
short *usercount, users;
/* set all verts to -1 : an unused index*/
- for(eve= em->verts.first; eve; eve= eve->next)
- eve->tmp.l=-1;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
+ BMINDEX_SET(eve, -1);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indicies and to count how much to malloc */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++;
- if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++;
- if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface)) {
+ BMINDEX_SET(efa, 0);
+ continue;
+ } else {
+ BMINDEX_SET(efa, 1);
+ }
- change = 1;
-
- /* optional speedup */
- efa->tmp.p = tface;
+ change = 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l) && BMINDEX_GET(l->v) == -1) {
+ BMINDEX_SET(l->v, count);
+ count++;
+ }
}
- else
- efa->tmp.p = NULL;
}
coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
/* add all UV coords from visible, unselected UV coords as well as counting them to average later */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tface=(MTFace *)efa->tmp.p)) {
- /* is this an unselected UV we can snap to? */
- if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
- coords[efa->v1->tmp.l*2] += tface->uv[0][0];
- coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
- usercount[efa->v1->tmp.l]++;
- change = 1;
- }
- if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
- coords[efa->v2->tmp.l*2] += tface->uv[1][0];
- coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
- usercount[efa->v2->tmp.l]++;
- change = 1;
- }
- if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
- coords[efa->v3->tmp.l*2] += tface->uv[2][0];
- coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
- usercount[efa->v3->tmp.l]++;
- change = 1;
- }
-
- if(efa->v4) {
- if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
- coords[efa->v4->tmp.l*2] += tface->uv[3][0];
- coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
- usercount[efa->v4->tmp.l]++;
- change = 1;
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
+
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BMINDEX_GET(l->v) >= 0 &&
+ (!uvedit_uv_selected(em, scene, l))) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ coords[BMINDEX_GET(l->v)*2] += luv->uv[0];
+ coords[BMINDEX_GET(l->v)*2+1] += luv->uv[1];
+ change = 1;
}
}
}
@@ -2424,46 +2626,24 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
if(!change) {
MEM_freeN(coords);
MEM_freeN(usercount);
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
/* copy the averaged unselected UVs back to the selected UVs */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tface=(MTFace *)efa->tmp.p)) {
-
- if( uvedit_uv_selected(scene, efa, tface, 0) &&
- efa->v1->tmp.l >= 0 &&
- (users = usercount[efa->v1->tmp.l])
- ) {
- tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users;
- tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users;
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMINDEX_GET(efa))
+ continue;
- if( uvedit_uv_selected(scene, efa, tface, 1) &&
- efa->v2->tmp.l >= 0 &&
- (users = usercount[efa->v2->tmp.l])
- ) {
- tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users;
- tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users;
- }
-
- if( uvedit_uv_selected(scene, efa, tface, 2) &&
- efa->v3->tmp.l >= 0 &&
- (users = usercount[efa->v3->tmp.l])
- ) {
- tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users;
- tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users;
- }
-
- if(efa->v4) {
- if( uvedit_uv_selected(scene, efa, tface, 3) &&
- efa->v4->tmp.l >= 0 &&
- (users = usercount[efa->v4->tmp.l])
- ) {
- tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users;
- tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users;
- }
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l) && BMINDEX_GET(l->v) >= 0
+ && (users = usercount[BMINDEX_GET(l->v)])) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = coords[BMINDEX_GET(l->v)*2];
+ luv->uv[1] = coords[BMINDEX_GET(l->v)*2+1];
}
}
}
@@ -2471,43 +2651,41 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
MEM_freeN(coords);
MEM_freeN(usercount);
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- Image *ima;
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ Image *ima= sima->image;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
int width= 0, height= 0;
float w, h;
short change = 0;
- if(!sima)
- return 0;
-
- ima= sima->image;
-
ED_space_image_size(sima, &width, &height);
w = (float)width;
h = (float)height;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
- if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
- if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- change = 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ snap_uv_to_pixel(luv->uv, w, h);
+ }
}
+
+ change = 1;
}
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
@@ -2569,35 +2747,34 @@ static int pin_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
int clear= RNA_boolean_get(op->ptr, "clear");
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- if(uvedit_face_visible(scene, ima, efa, tface)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
if(!clear) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
- if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
- if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
- }
- else {
- if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
- if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
- if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
+ if (uvedit_uv_selected(em, scene, l))
+ luv->flag |= MLOOPUV_PINNED;
+ } else {
+ if (uvedit_uv_selected(em, scene, l))
+ luv->flag &= ~MLOOPUV_PINNED;
}
}
}
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2623,26 +2800,28 @@ static int select_pinned_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
- if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
- if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
- if(efa->v4) {
- if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
- }
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_PINNED)
+ uvedit_uv_select(em, scene, l);
}
}
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2665,125 +2844,51 @@ static int hide_exec(bContext *C, wmOperator *op)
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
int swap= RNA_boolean_get(op->ptr, "unselected");
- int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_hide_mesh(em, swap);
+ EDBM_hide_mesh(em, swap);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
- if(swap) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(facemode) {
- /* Pretend face mode */
- if(( (efa->v4==NULL &&
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) {
-
- if(em->selectmode == SCE_SELECT_FACE) {
- efa->f &= ~SELECT;
- /* must re-select after */
- efa->e1->f &= ~SELECT;
- efa->e2->f &= ~SELECT;
- efa->e3->f &= ~SELECT;
- if(efa->e4) efa->e4->f &= ~SELECT;
- }
- else
- EM_select_face(efa, 0);
- }
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- else if(em->selectmode == SCE_SELECT_FACE) {
- if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
- if(!efa->v4)
- EM_select_face(efa, 0);
- else if(!(tf->flag & TF_SEL4))
- EM_select_face(efa, 0);
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- }
- else {
- /* EM_deselect_flush will deselect the face */
- if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT;
- if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT;
- if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT;
- if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT;
-
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- }
- }
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(facemode) {
- if( (efa->v4==NULL &&
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) {
-
- if(em->selectmode == SCE_SELECT_FACE) {
- efa->f &= ~SELECT;
- /* must re-select after */
- efa->e1->f &= ~SELECT;
- efa->e2->f &= ~SELECT;
- efa->e3->f &= ~SELECT;
- if(efa->e4) efa->e4->f &= ~SELECT;
- }
- else
- EM_select_face(efa, 0);
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int hide = 0;
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- else if(em->selectmode == SCE_SELECT_FACE) {
- if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
- EM_select_face(efa, 0);
- else if(efa->v4 && tf->flag & TF_SEL4)
- EM_select_face(efa, 0);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- else {
- /* EM_deselect_flush will deselect the face */
- if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT;
- if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT;
- if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT;
- if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT;
-
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ hide = 1;
+ break;
}
}
+
+ if (swap)
+ hide = !hide;
+
+ if (hide) {
+ BM_Select(em->bm, efa, 0);
+ uvedit_face_deselect(scene, em, efa);
+ }
}
- /*deselects too many but ok for now*/
- if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
- EM_deselect_flush(em);
+ ///*deselects too many but ok for now*/
+ //if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
+ // EM_deselect_flush(em);
- if(em->selectmode==SCE_SELECT_FACE) {
- /* de-selected all edges from faces that were de-selected.
- * now make sure all faces that are selected also have selected edges */
- for(efa= em->faces.first; efa; efa= efa->next)
- if(efa->f & SELECT)
- EM_select_face(efa, 1);
- }
- EM_validate_selections(em);
+ EDBM_validate_selections(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2809,114 +2914,44 @@ static int reveal_exec(bContext *C, wmOperator *op)
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
- int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
- int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMVert *v;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(v, BM_TestHFlag(v, BM_SELECT));
+ }
+
/* call the mesh function if we are in mesh sync sel */
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_reveal_mesh(em);
+ EDBM_reveal_mesh(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
-
- if(facemode) {
- if(em->selectmode == SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- EM_select_face(efa, 1);
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
- }
- }
- }
- else {
- /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
- if(!stickymode) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- /* All verts must be unselected for the face to be selected in the UV view */
- if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
- /* Cant use EM_select_face here because it unselects the verts
- * and we cant tell if the face was totally unselected or not */
- /*EM_select_face(efa, 1);
- *
- * See Loop with EM_select_face() below... */
- efa->f |= SELECT;
- }
- }
- }
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
- if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
- if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
- if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
- efa->f |= SELECT;
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (em->selectmode == SCE_SELECT_FACE) {
+ uvedit_face_select(scene, em, efa);
+ } else {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (!BMINDEX_GET(l->v)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
}
}
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
-
- EM_select_flush(em);
- }
- }
- else if(em->selectmode == SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- efa->f |= SELECT;
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
- }
}
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
- if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
- if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
- if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
- efa->f |= SELECT;
- }
- }
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
+ BM_Select(em->bm, efa, 1);
}
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 20f74085e52..6d87b244736 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -727,8 +727,10 @@ static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
return NULL;
}
-static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3)
+int p_face_exists(ParamHandle *phandle, ParamKey *pvkeys, int i1, int i2, int i3)
{
+ PHandle *handle = (PHandle*)phandle;
+ PHashKey *vkeys = (PHashKey*)pvkeys;
PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index f1454ee3865..8d440e2e652 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -30,6 +30,8 @@ ParamHandle *param_construct_begin();
void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy);
+int p_face_exists(ParamHandle *handle, ParamKey *vkeys, int i1, int i2, int i3);
+
void param_face_add(ParamHandle *handle,
ParamKey key,
int nverts,
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index c7258e616fa..f1041603bed 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -47,10 +47,13 @@
#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BLI_arithb.h"
#include "BLI_edgehash.h"
#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_array.h"
#include "PIL_time.h"
@@ -73,9 +76,9 @@
static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
Image *ima;
bScreen *sc;
ScrArea *sa;
@@ -83,15 +86,15 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
SpaceImage *sima;
if(ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
- if(em && em->faces.first)
- EM_add_data_layer(em, &em->fdata, CD_MTFACE);
-
+ if(em && em->bm->totface) {// && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
+ }
+
if(!ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
@@ -121,33 +124,35 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
ED_uvedit_assign_image(scene, obedit, ima, NULL);
/* select new UV's */
- for(efa=em->faces.first; efa; efa=efa->next) {
- tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_select(scene, efa, tf);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ uvedit_face_select(scene, em, efa);
}
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
/****************** Parametrizer Conversion ***************/
-ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel, short correct_aspect)
+ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em,
+ short implicit, short fill, short sel,
+ short correct_aspect)
{
ParamHandle *handle;
- EditFace *efa;
- EditEdge *eed;
- EditVert *ev;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMEdge *eed;
+ BMVert *ev;
+ BMIter iter, liter;
+ MTexPoly *tf;
int a;
handle = param_construct_begin();
if(correct_aspect) {
- efa = EM_get_actFace(em, 1);
+ efa = EDBM_get_actFace(em, 1);
if(efa) {
- MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ MTexPoly *tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
float aspx, aspy;
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
@@ -158,71 +163,103 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit,
}
/* we need the vert indicies */
- for(ev= em->verts.first, a=0; ev; ev= ev->next, a++)
- ev->tmp.l = a;
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMINDEX_SET(ev, a);
+ a++;
+ }
- for(efa= em->faces.first; efa; efa= efa->next) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *v, *lastv, *firstv;
+ EditFace *sefa;
ParamKey key, vkeys[4];
ParamBool pin[4], select[4];
+ BMLoop *ls[3];
+ MLoopUV *luvs[3];
float *co[4];
float *uv[4];
- int nverts;
+ int lsel;
- if((efa->h) || (sel && (efa->f & SELECT)==0))
+ if((BM_TestHFlag(efa, BM_HIDDEN)) || (sel && BM_TestHFlag(efa, BM_SELECT)==0))
continue;
- tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(implicit &&
- !( uvedit_uv_selected(scene, efa, tf, 0) ||
- uvedit_uv_selected(scene, efa, tf, 1) ||
- uvedit_uv_selected(scene, efa, tf, 2) ||
- (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) )
- ) {
- continue;
+ tf= (MTexPoly *)CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ lsel = 0;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ lsel = 1;
+ break;
+ }
}
+ if (implicit && !lsel)
+ continue;
+
key = (ParamKey)efa;
- vkeys[0] = (ParamKey)efa->v1->tmp.l;
- vkeys[1] = (ParamKey)efa->v2->tmp.l;
- vkeys[2] = (ParamKey)efa->v3->tmp.l;
-
- co[0] = efa->v1->co;
- co[1] = efa->v2->co;
- co[2] = efa->v3->co;
-
- uv[0] = tf->uv[0];
- uv[1] = tf->uv[1];
- uv[2] = tf->uv[2];
-
- pin[0] = ((tf->unwrap & TF_PIN1) != 0);
- pin[1] = ((tf->unwrap & TF_PIN2) != 0);
- pin[2] = ((tf->unwrap & TF_PIN3) != 0);
-
- select[0] = ((uvedit_uv_selected(scene, efa, tf, 0)) != 0);
- select[1] = ((uvedit_uv_selected(scene, efa, tf, 1)) != 0);
- select[2] = ((uvedit_uv_selected(scene, efa, tf, 2)) != 0);
-
- if(efa->v4) {
- vkeys[3] = (ParamKey)efa->v4->tmp.l;
- co[3] = efa->v4->co;
- uv[3] = tf->uv[3];
- pin[3] = ((tf->unwrap & TF_PIN4) != 0);
- select[3] = (uvedit_uv_selected(scene, efa, tf, 3) != 0);
- nverts = 4;
+
+ /*scanfill time!*/
+ firstv = lastv = NULL;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ v = BLI_addfillvert(l->v->co);
+
+ v->tmp.p = l;
+
+ if (lastv) {
+ BLI_addfilledge(lastv, v);
+ }
+
+ lastv = v;
+ if (!firstv)
+ firstv = v;
}
- else
- nverts = 3;
- param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
+ BLI_addfilledge(firstv, v);
+
+ /*mode 2 enables shortest-diagonal for quads*/
+ BLI_edgefill(2, 0);
+ for (sefa = fillfacebase.first; sefa; sefa=sefa->next) {
+ ls[0] = sefa->v1->tmp.p;
+ ls[1] = sefa->v2->tmp.p;
+ ls[2] = sefa->v3->tmp.p;
+
+ luvs[0] = CustomData_bmesh_get(&em->bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+ luvs[1] = CustomData_bmesh_get(&em->bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+ luvs[2] = CustomData_bmesh_get(&em->bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+
+ vkeys[0] = (ParamKey)BMINDEX_GET(ls[0]->v);
+ vkeys[1] = (ParamKey)BMINDEX_GET(ls[1]->v);
+ vkeys[2] = (ParamKey)BMINDEX_GET(ls[2]->v);
+
+ co[0] = ls[0]->v->co;
+ co[1] = ls[1]->v->co;
+ co[2] = ls[2]->v->co;
+
+ uv[0] = luvs[0]->uv;
+ uv[1] = luvs[1]->uv;
+ uv[2] = luvs[2]->uv;
+
+ pin[0] = (luvs[0]->flag & MLOOPUV_PINNED) != 0;
+ pin[1] = (luvs[1]->flag & MLOOPUV_PINNED) != 0;
+ pin[2] = (luvs[2]->flag & MLOOPUV_PINNED) != 0;
+
+ select[0] = uvedit_uv_selected(em, scene, ls[0]) != 0;
+ select[1] = uvedit_uv_selected(em, scene, ls[1]) != 0;
+ select[2] = uvedit_uv_selected(em, scene, ls[2]) != 0;
+
+ if (!p_face_exists(handle,vkeys,0,1,2))
+ param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
+ }
+
+ BLI_end_edgefill();
}
if(!implicit) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->seam) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SEAM)) {
ParamKey vkeys[2];
- vkeys[0] = (ParamKey)eed->v1->tmp.l;
- vkeys[1] = (ParamKey)eed->v2->tmp.l;
+ vkeys[0] = (ParamKey)BMINDEX_GET(eed->v1);
+ vkeys[1] = (ParamKey)BMINDEX_GET(eed->v2);
param_edge_set_seam(handle, vkeys);
}
}
@@ -238,7 +275,7 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit,
typedef struct MinStretch {
Scene *scene;
Object *obedit;
- EditMesh *em;
+ BMEditMesh *em;
ParamHandle *handle;
float blend;
double lasttime;
@@ -250,7 +287,7 @@ static void minimize_stretch_init(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;
MinStretch *ms;
int fill_holes= RNA_boolean_get(op->ptr, "fill_holes");
@@ -433,7 +470,7 @@ static int pack_islands_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;
ParamHandle *handle;
handle = construct_param_handle(scene, em, 1, 0, 1, 1);
@@ -444,7 +481,6 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -466,7 +502,7 @@ static int average_islands_scale_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;
ParamHandle *handle;
handle= construct_param_handle(scene, em, 1, 0, 1, 1);
@@ -477,7 +513,6 @@ static int average_islands_scale_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -499,19 +534,17 @@ static ParamHandle *liveHandle = NULL;
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
short abf = scene->toolsettings->unwrapper == 1;
short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
if(!ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return;
}
- liveHandle = construct_param_handle(scene, em, 0, fillholes, 1, 1);
+ liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
- BKE_mesh_end_editmesh(obedit->data, em);
}
void ED_uvedit_live_unwrap_re_solve(void)
@@ -542,9 +575,12 @@ void ED_uvedit_live_unwrap_end(short cancel)
#define POLAR_ZX 0
#define POLAR_ZY 1
-static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, EditMesh *em)
+static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
+ Object *ob, BMEditMesh *em)
{
- EditFace *efa;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
float min[3], max[3], *cursx;
int around= (v3d)? v3d->around: V3D_CENTER;
@@ -554,13 +590,12 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Ob
case V3D_CENTER: /* bounding box center */
min[0]= min[1]= min[2]= 1e20f;
max[0]= max[1]= max[2]= -1e20f;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- DO_MINMAX(efa->v1->co, min, max);
- DO_MINMAX(efa->v2->co, min, max);
- DO_MINMAX(efa->v3->co, min, max);
- if(efa->v4) DO_MINMAX(efa->v4->co, min, max);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_TestHFlag(efa, BM_SELECT)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ DO_MINMAX(l->v->co, min, max);
+ }
}
}
VecMidf(result, min, max);
@@ -634,7 +669,7 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
/* context checks are messy here, making it work in both 3d view and uv editor */
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;
View3D *v3d= CTX_wm_view3d(C);
RegionView3D *rv3d= CTX_wm_region_view3d(C);
/* common operator properties */
@@ -661,7 +696,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
else
uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
- BKE_mesh_end_editmesh(obedit->data, em);
}
static void uv_transform_properties(wmOperatorType *ot, int radius)
@@ -684,14 +718,17 @@ static void uv_transform_properties(wmOperatorType *ot, int radius)
RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "Radius of the sphere or cylinder.", 0.0001f, 100.0f);
}
-static void correct_uv_aspect(EditMesh *em)
+static void correct_uv_aspect(BMEditMesh *em)
{
- EditFace *efa= EM_get_actFace(em, 1);
- MTFace *tf;
+ BMFace *efa= EDBM_get_actFace(em, 1);
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float scale, aspx= 1.0f, aspy=1.0f;
if(efa) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
}
@@ -701,30 +738,28 @@ static void correct_uv_aspect(EditMesh *em)
if(aspx > aspy) {
scale= aspy/aspx;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->uv[0][0]= ((tf->uv[0][0]-0.5)*scale)+0.5;
- tf->uv[1][0]= ((tf->uv[1][0]-0.5)*scale)+0.5;
- tf->uv[2][0]= ((tf->uv[2][0]-0.5)*scale)+0.5;
- if(efa->v4)
- tf->uv[3][0]= ((tf->uv[3][0]-0.5)*scale)+0.5;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = ((luv->uv[0]-0.5)*scale)+0.5;
}
}
}
else {
scale= aspx/aspy;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->uv[0][1]= ((tf->uv[0][1]-0.5)*scale)+0.5;
- tf->uv[1][1]= ((tf->uv[1][1]-0.5)*scale)+0.5;
- tf->uv[2][1]= ((tf->uv[2][1]-0.5)*scale)+0.5;
- if(efa->v4)
- tf->uv[3][1]= ((tf->uv[3][1]-0.5)*scale)+0.5;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[1] = ((luv->uv[1]-0.5)*scale)+0.5;
}
}
}
@@ -739,10 +774,12 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds", "Scale UV coordinates to bounds after unwrapping.");
}
-static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
+static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float dx, dy, min[2], max[2];
int b, nverts;
int correct_aspect= RNA_boolean_get(op->ptr, "correct_aspect");
@@ -756,16 +793,13 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
if(scale_to_bounds) {
INIT_MINMAX2(min, max);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- DO_MINMAX2(tf->uv[0], min, max);
- DO_MINMAX2(tf->uv[1], min, max);
- DO_MINMAX2(tf->uv[2], min, max);
-
- if(efa->v4)
- DO_MINMAX2(tf->uv[3], min, max);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max);
}
}
@@ -778,31 +812,28 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
if(dy > 0.0f)
dy= 1.0f/dy;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- nverts= (efa->v4)? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- for(b=0; b<nverts; b++) {
- tf->uv[b][0]= (tf->uv[b][0]-min[0])*dx;
- tf->uv[b][1]= (tf->uv[b][1]-min[1])*dy;
- }
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->uv[0] = (luv->uv[0]-min[0])*dx;
+ luv->uv[1] = (luv->uv[1]-min[1])*dy;
}
}
}
else if(clip_to_bounds) {
/* clipping and wrapping */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- nverts= (efa->v4)? 4: 3;
-
- for(b=0; b<nverts; b++) {
- CLAMP(tf->uv[b][0], 0.0, 1.0);
- CLAMP(tf->uv[b][1], 0.0, 1.0);
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ CLAMP(luv->uv[0], 0.0, 1.0);
+ CLAMP(luv->uv[1], 0.0, 1.0);
}
}
}
@@ -814,7 +845,7 @@ static int unwrap_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;
ParamHandle *handle;
int method = RNA_enum_get(op->ptr, "method");
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
@@ -822,7 +853,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -841,7 +871,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -926,45 +955,42 @@ static int from_view_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;
ARegion *ar= CTX_wm_region(C);
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
if(RNA_boolean_get(op->ptr, "orthographic")) {
uv_map_rotation_matrix(rotmat, ar->regiondata, obedit, 90.0f, 0.0f, 1.0f);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- uv_from_view_bounds(tf->uv[0], efa->v1->co, rotmat);
- uv_from_view_bounds(tf->uv[1], efa->v2->co, rotmat);
- uv_from_view_bounds(tf->uv[2], efa->v3->co, rotmat);
- if(efa->v4)
- uv_from_view_bounds(tf->uv[3], efa->v4->co, rotmat);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv_from_view_bounds(luv->uv, l->v->co, rotmat);
}
}
}
else {
Mat4CpyMat4(rotmat, obedit->obmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- uv_from_view(ar, tf->uv[0], efa->v1->co, rotmat);
- uv_from_view(ar, tf->uv[1], efa->v2->co, rotmat);
- uv_from_view(ar, tf->uv[2], efa->v3->co, rotmat);
- if(efa->v4)
- uv_from_view(ar, tf->uv[3], efa->v4->co, rotmat);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv_from_view(ar, luv->uv, l->v->co, rotmat);
}
}
}
@@ -974,7 +1000,6 @@ static int from_view_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1010,38 +1035,75 @@ static int reset_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);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ BLI_array_declare(uvs);
+ float **uvs = NULL;
+ int i;
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BLI_array_empty(uvs);
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(uvs);
- tf->uv[0][0]= 0.0f;
- tf->uv[0][1]= 0.0f;
-
- tf->uv[1][0]= 1.0f;
- tf->uv[1][1]= 0.0f;
+ uvs[i++] = luv->uv;
+ }
+
+ if (i == 3) {
+ uvs[0][0] = 0.0;
+ uvs[0][1] = 0.0;
- tf->uv[2][0]= 1.0f;
- tf->uv[2][1]= 1.0f;
+ uvs[1][0] = 1.0;
+ uvs[1][1] = 0.0;
+
+ uvs[2][0] = 1.0;
+ uvs[2][1] = 1.0;
+ } else if (i == 4) {
+ uvs[0][0] = 0.0;
+ uvs[0][1] = 0.0;
- tf->uv[3][0]= 0.0f;
- tf->uv[3][1]= 1.0f;
+ uvs[1][0] = 1.0;
+ uvs[1][1] = 0.0;
+
+ uvs[2][0] = 1.0;
+ uvs[2][1] = 1.0;
+
+ uvs[3][0] = 0.0;
+ uvs[3][1] = 1.0;
+ /*make sure we ignore 2-sided faces*/
+ } else if (i > 2) {
+ float fac = 0.0f, dfac = 1.0f / (float)efa->len;
+
+ dfac *= M_PI*2;
+
+ for (i=0; i<efa->len; i++) {
+ uvs[i][0] = sin(fac);
+ uvs[i][1] = cos(fac);
+
+ fac += dfac;
+ }
}
}
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ BLI_array_free(uvs);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1073,55 +1135,71 @@ static void uv_sphere_project(float target[2], float source[3], float center[3],
target[0] -= 1.0f;
}
-static void uv_map_mirror(EditFace *efa, MTFace *tf)
+static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *tf)
{
+ BMLoop *l;
+ BMIter liter;
+ MLoopUV *luv;
+ BLI_array_declare(uvs);
+ float **uvs = NULL;
float dx;
- int nverts, i, mi;
+ int i, mi;
- nverts= (efa->v4)? 4: 3;
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(uvs);
+
+ uvs[i] = luv->uv;
+ i++;
+ }
mi = 0;
- for(i=1; i<nverts; i++)
- if(tf->uv[i][0] > tf->uv[mi][0])
+ for(i=1; i<efa->len; i++)
+ if(uvs[i][0] > uvs[mi][0])
mi = i;
- for(i=0; i<nverts; i++) {
+ for(i=0; i<efa->len; i++) {
if(i != mi) {
- dx = tf->uv[mi][0] - tf->uv[i][0];
- if(dx > 0.5) tf->uv[i][0] += 1.0;
+ dx = uvs[mi][0] - uvs[i][0];
+ if(dx > 0.5) uvs[i][0] += 1.0;
}
}
+
+ BLI_array_free(uvs);
}
static int sphere_project_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);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float center[3], rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
uv_map_transform(C, op, center, rotmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- uv_sphere_project(tf->uv[0], efa->v1->co, center, rotmat);
- uv_sphere_project(tf->uv[1], efa->v2->co, center, rotmat);
- uv_sphere_project(tf->uv[2], efa->v3->co, center, rotmat);
- if(efa->v4)
- uv_sphere_project(tf->uv[3], efa->v4->co, center, rotmat);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- uv_map_mirror(efa, tf);
+ uv_sphere_project(luv->uv, l->v->co, center, rotmat);
}
+
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ uv_map_mirror(em, efa, tf);
}
uv_map_clip_correct(em, op);
@@ -1129,7 +1207,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1169,31 +1246,33 @@ static int cylinder_project_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);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float center[3], rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
uv_map_transform(C, op, center, rotmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- uv_cylinder_project(tf->uv[0], efa->v1->co, center, rotmat);
- uv_cylinder_project(tf->uv[1], efa->v2->co, center, rotmat);
- uv_cylinder_project(tf->uv[2], efa->v3->co, center, rotmat);
- if(efa->v4)
- uv_cylinder_project(tf->uv[3], efa->v4->co, center, rotmat);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- uv_map_mirror(efa, tf);
+ uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
+
+ uv_map_mirror(em, efa, tf);
}
uv_map_clip_correct(em, op);
@@ -1201,7 +1280,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1227,15 +1305,17 @@ static int cube_project_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);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float no[3], cube_size, *loc, dx, dy;
int cox, coy;
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -1245,41 +1325,38 @@ static int cube_project_exec(bContext *C, wmOperator *op)
/* choose x,y,z axis for projection depending on the largest normal
* component, but clusters all together around the center of map. */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, no);
-
- no[0]= fabs(no[0]);
- no[1]= fabs(no[1]);
- no[2]= fabs(no[2]);
-
- cox=0; coy= 1;
- if(no[2]>=no[0] && no[2]>=no[1]);
- else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
- else { cox= 1; coy= 2; }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int first=1;
+
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ VECCOPY(no, efa->no);
+
+ no[0]= fabs(no[0]);
+ no[1]= fabs(no[1]);
+ no[2]= fabs(no[2]);
+
+ cox=0; coy= 1;
+ if(no[2]>=no[0] && no[2]>=no[1]);
+ else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
+ else { cox= 1; coy= 2; }
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->uv[0] = 0.5+0.5*cube_size*(loc[cox] + l->v->co[cox]);
+ luv->uv[1] = 0.5+0.5*cube_size*(loc[coy] + l->v->co[coy]);
- tf->uv[0][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v1->co[cox]);
- tf->uv[0][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v1->co[coy]);
- dx = floor(tf->uv[0][0]);
- dy = floor(tf->uv[0][1]);
- tf->uv[0][0] -= dx;
- tf->uv[0][1] -= dy;
- tf->uv[1][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v2->co[cox]);
- tf->uv[1][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v2->co[coy]);
- tf->uv[1][0] -= dx;
- tf->uv[1][1] -= dy;
- tf->uv[2][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v3->co[cox]);
- tf->uv[2][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v3->co[coy]);
- tf->uv[2][0] -= dx;
- tf->uv[2][1] -= dy;
-
- if(efa->v4) {
- tf->uv[3][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v4->co[cox]);
- tf->uv[3][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v4->co[coy]);
- tf->uv[3][0] -= dx;
- tf->uv[3][1] -= dy;
+ if (first) {
+ dx = floor(luv->uv[0]);
+ dy = floor(luv->uv[1]);
+ first = 0;
}
+
+ luv->uv[0] -= dx;
+ luv->uv[1] -= dy;
}
}
@@ -1288,7 +1365,6 @@ static int cube_project_exec(bContext *C, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/gpu/gpu_buffers.h b/source/blender/gpu/gpu_buffers.h
index 662912f9c19..7377046ee63 100644
--- a/source/blender/gpu/gpu_buffers.h
+++ b/source/blender/gpu/gpu_buffers.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: gpu_buffers.h 23816 2009-10-13 19:02:30Z nicholasbishop $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 2563f7977cc..6b465b64590 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: gpu_buffers.c 23816 2009-10-13 19:02:30Z nicholasbishop $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -269,9 +269,9 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
memset(numverts,0,sizeof(int)*32768);
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
if( mface[i].v4 )
numverts[mface[i].mat_nr+16383] += 6; /* split every quad into two triangles */
@@ -311,10 +311,11 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
if( object->indices[INDEX].element == -1 ) { \
object->indices[INDEX].element = ACTUAL; \
} else { \
- IndexLink *lnk = &object->indices[INDEX]; \
- while( lnk->next != 0 ) lnk = lnk->next; \
- lnk->next = &object->indexMem[object->indexMemUsage]; \
- lnk->next->element = ACTUAL; \
+ IndexLink *lnk = &object->indices[INDEX], *lnk2; \
+ lnk2 = &object->indexMem[object->indexMemUsage]; \
+ lnk2->element = ACTUAL; \
+ SWAP(IndexLink, *lnk, *lnk2); \
+ lnk->next = lnk2; \
object->indexMemUsage++; \
}
@@ -474,9 +475,9 @@ void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *re
DEBUG_VBO("GPU_buffer_copy_vertex\n");
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
start = index[redir[mface[i].mat_nr+16383]];
if( mface[i].v4 )
@@ -518,13 +519,13 @@ void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *re
int start;
float norm[3];
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
DEBUG_VBO("GPU_buffer_copy_normal\n");
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
start = index[redir[mface[i].mat_nr+16383]];
if( mface[i].v4 )
@@ -586,7 +587,7 @@ void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir,
DEBUG_VBO("GPU_buffer_copy_uv\n");
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
mtface = DM_get_face_data_layer(dm, CD_MTFACE);
if( mtface == 0 ) {
@@ -594,7 +595,7 @@ void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir,
return;
}
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
start = index[redir[mface[i].mat_nr+16383]];
if( mface[i].v4 )
@@ -630,11 +631,11 @@ void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *r
int i, numfaces;
unsigned char *varray = (unsigned char *)varray_;
unsigned char *mcol = (unsigned char *)user;
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
DEBUG_VBO("GPU_buffer_copy_color3\n");
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
int start = index[redir[mface[i].mat_nr+16383]];
if( mface[i].v4 )
@@ -660,11 +661,11 @@ void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *r
int i, numfaces;
unsigned char *varray = (unsigned char *)varray_;
unsigned char *mcol = (unsigned char *)user;
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
DEBUG_VBO("GPU_buffer_copy_color4\n");
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
for( i=0; i < numfaces; i++ ) {
int start = index[redir[mface[i].mat_nr+16383]];
if( mface[i].v4 )
@@ -704,7 +705,7 @@ GPUBuffer *GPU_buffer_color( DerivedMesh *dm )
dm->drawObject->colType = CD_MCOL;
}
- numfaces= dm->getNumFaces(dm);
+ numfaces= dm->getNumTessFaces(dm);
colors = MEM_mallocN(numfaces*12*sizeof(unsigned char), "GPU_buffer_color");
for( i=0; i < numfaces*4; i++ ) {
colors[i*3] = mcol[i].b;
@@ -756,7 +757,7 @@ void GPU_buffer_copy_uvedge( DerivedMesh *dm, float *varray, int *index, int *re
if(tf) {
for(i = 0; i < dm->numFaceData; i++, tf++) {
MFace mf;
- dm->getFace(dm,i,&mf);
+ dm->getTessFace(dm,i,&mf);
VECCOPY2D(&varray[j],tf->uv[0]);
VECCOPY2D(&varray[j+2],tf->uv[1]);
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index b160e7346bd..68afbcd0db2 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -210,7 +210,7 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t
/* called from within the core where_is_pose loop, all animsystems and constraints
were executed & assigned. Now as last we do an IK pass */
-static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
+static void execute_posetree(Object *ob, PoseTree *tree)
{
float R_parmat[3][3], identity[3][3];
float iR_parmat[3][3];
@@ -347,7 +347,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
* strictly speaking, it is a posechannel)
*/
- get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
/* and set and transform goal */
Mat4MulMat4(goal, rootmat, goalinv);
@@ -357,7 +357,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* same for pole vector target */
if(data->poletar) {
- get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
if(data->flag & CONSTRAINT_IK_SETANGLE) {
/* don't solve IK when we are setting the pole angle */
@@ -511,7 +511,7 @@ void iksolver_execute_tree(struct Scene *scene, struct Object *ob, struct bPose
tree->pchan[a]->flag |= POSE_CHAIN;
}
/* 5. execute the IK solver */
- execute_posetree(scene, ob, tree);
+ execute_posetree(ob, tree);
/* 6. apply the differences to the channels,
we need to calculate the original differences first */
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index b6fceabdb46..dc0c2c4c12f 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -89,7 +89,6 @@ void KDL::SetToZero(JntArray& array);
// one structure for each target in the scene
struct IK_Target
{
- struct Scene *blscene;
iTaSC::MovingFrame* target;
iTaSC::ConstraintSet* constraint;
struct bConstraint* blenderConstraint;
@@ -106,7 +105,6 @@ struct IK_Target
float eeRest[4][4]; //end effector initial pose relative to armature
IK_Target() {
- blscene = NULL;
target = NULL;
constraint = NULL;
blenderConstraint = NULL;
@@ -157,7 +155,6 @@ struct IK_Channel {
struct IK_Scene
{
- struct Scene *blscene;
IK_Scene* next;
int numchan; // number of channel in pchan
int numjoint; // number of joint in jointArray
@@ -175,7 +172,6 @@ struct IK_Scene
std::vector<IK_Target*> targets;
IK_Scene() {
- blscene = NULL;
next = NULL;
channels = NULL;
armature = NULL;
@@ -537,7 +533,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
bConstraint* constraint = (bConstraint*)target->blenderConstraint;
float tarmat[4][4];
- get_constraint_target_matrix(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
+ get_constraint_target_matrix(constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
// rootmat contains the target pose in world coordinate
// if enforce is != 1.0, blend the target position with the end effector position
@@ -605,7 +601,7 @@ static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame&
IK_Channel &rootchan = ikscene->channels[0];
// get polar target matrix in world space
- get_constraint_target_matrix(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
+ get_constraint_target_matrix(ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
// convert to armature space
Mat4MulMat4(polemat, mat, imat);
// get the target in world space (was computed before as target object are defined before base object)
@@ -1054,7 +1050,6 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
return NULL;
ikscene = new IK_Scene;
- ikscene->blscene = blscene;
arm = new iTaSC::Armature();
scene = new iTaSC::Scene();
ikscene->channels = new IK_Channel[tree->totchannel];
@@ -1387,7 +1382,6 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
// finally add the constraint
for (t=0; t<ikscene->targets.size(); t++) {
IK_Target* iktarget = ikscene->targets[t];
- iktarget->blscene = blscene;
condata= (bKinematicConstraint*)iktarget->blenderConstraint->data;
pchan = tree->pchan[iktarget->channel];
unsigned int controltype, bonecnt;
@@ -1417,22 +1411,10 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
switch (condata->type) {
case CONSTRAINT_IK_COPYPOSE:
controltype = 0;
- if (condata->flag & CONSTRAINT_IK_ROT) {
- if (!(condata->flag & CONSTRAINT_IK_NO_ROT_X))
- controltype |= iTaSC::CopyPose::CTL_ROTATIONX;
- if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Y))
- controltype |= iTaSC::CopyPose::CTL_ROTATIONY;
- if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Z))
- controltype |= iTaSC::CopyPose::CTL_ROTATIONZ;
- }
- if (condata->flag & CONSTRAINT_IK_POS) {
- if (!(condata->flag & CONSTRAINT_IK_NO_POS_X))
- controltype |= iTaSC::CopyPose::CTL_POSITIONX;
- if (!(condata->flag & CONSTRAINT_IK_NO_POS_Y))
- controltype |= iTaSC::CopyPose::CTL_POSITIONY;
- if (!(condata->flag & CONSTRAINT_IK_NO_POS_Z))
- controltype |= iTaSC::CopyPose::CTL_POSITIONZ;
- }
+ if ((condata->flag & CONSTRAINT_IK_ROT) && (condata->orientweight != 0.0))
+ controltype |= iTaSC::CopyPose::CTL_ROTATION;
+ if ((condata->weight != 0.0))
+ controltype |= iTaSC::CopyPose::CTL_POSITION;
if (controltype) {
iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen);
// set the gain
@@ -1444,10 +1426,7 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
iktarget->errorCallback = copypose_error;
iktarget->controlType = controltype;
// add the constraint
- if (condata->flag & CONSTRAINT_IK_TARGETAXIS)
- ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, iktarget->targetName, armname, "", ikscene->channels[iktarget->channel].tail);
- else
- ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail);
+ ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail);
}
break;
case CONSTRAINT_IK_DISTANCE:
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index ad686e37097..e4a16da0365 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -49,6 +49,7 @@ typedef struct CustomDataLayer {
* layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
typedef struct CustomData {
CustomDataLayer *layers; /* CustomDataLayers, ordered by type */
+ int typemap[100]; /* maps types to indices of first layer of that type */
int totlayer, maxlayer; /* number of layers, size of layers array */
int totsize, pad; /* in editmode, total size of all data layers */
void *pool; /* for Bmesh: Memory pool for allocation of blocks*/
@@ -62,23 +63,26 @@ typedef struct CustomData {
#define CD_MFACE 4
#define CD_MTFACE 5
#define CD_MCOL 6
-#define CD_ORIGINDEX 7
+#define CD_ORIGINDEX 7
#define CD_NORMAL 8
#define CD_FLAGS 9
#define CD_PROP_FLT 10
#define CD_PROP_INT 11
#define CD_PROP_STR 12
-#define CD_ORIGSPACE 13 /* for modifier stack face location mapping */
+#define CD_ORIGSPACE 13 /* for modifier stack face location mapping */
#define CD_ORCO 14
#define CD_MTEXPOLY 15
#define CD_MLOOPUV 16
#define CD_MLOOPCOL 17
#define CD_TANGENT 18
#define CD_MDISPS 19
-#define CD_WEIGHT_MCOL 20 /* for displaying weightpaint colors */
-#define CD_ID_MCOL 21
-#define CD_TEXTURE_MCOL 22
-#define CD_NUMTYPES 23
+#define CD_WEIGHT_MCOL 20 /* for displaying weightpaint colors */
+#define CD_MPOLY 21
+#define CD_MLOOP 22
+#define CD_WEIGHT_MLOOPCOL 23
+#define CD_ID_MCOL 24
+#define CD_TEXTURE_MCOL 25
+#define CD_NUMTYPES 26
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@@ -102,6 +106,9 @@ 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)
+#define CD_MASK_WEIGHT_MLOOPCOL (1 << CD_WEIGHT_MLOOPCOL)
/* 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 0f4dbaa8218..c9b12f0e147 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
@@ -150,6 +167,8 @@ typedef struct TFace {
#define ME_DRAW_FACEAREA (1 << 11)
#define ME_DRAW_EDGEANG (1 << 12)
+#define ME_DRAW_PINS (1 << 13)
+
/* old global flags:
#define G_DRAWEDGES (1 << 18)
#define G_DRAWFACES (1 << 7)
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index d53a7833d0e..9bd495b1e39 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -35,6 +35,7 @@
struct Bone;
struct Image;
+/*tesselation face, see MLoop/MPoly for the real face data*/
typedef struct MFace {
unsigned int v1, v2, v3, v4;
short mat_nr;
@@ -65,13 +66,29 @@ typedef struct MVert {
char flag, bweight, pad[2];
} MVert;
-/* at the moment alpha is abused for vertex painting
+/* tesselation vertex color data.
+ * at the moment alpha is abused for vertex painting
* and not used for transperency, note that red and blue are swapped */
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;
@@ -80,12 +97,19 @@ typedef struct MTexPoly{
typedef struct MLoopUV{
float uv[2];
+ int flag;
}MLoopUV;
+/*mloopuv->flag*/
+#define MLOOPUV_EDGESEL 1
+#define MLOOPUV_VERTSEL 2
+#define MLOOPUV_PINNED 4
+
+/* at the moment alpha is abused for vertex painting
+ * and not used for transperency, note that red and blue are swapped */
typedef struct MLoopCol{
char a, r, g, b;
- int pad; /*waste!*/
-}MLoopCol;
+} MLoopCol;
typedef struct MSticky {
float co[2];
@@ -96,6 +120,7 @@ typedef struct MSelect {
int type;
} MSelect;
+/*tesselation uv face data*/
typedef struct MTFace {
float uv[4][2];
struct Image *tpage;
@@ -185,6 +210,7 @@ typedef struct PartialVisibility {
#define ME_SPHERETEST 2
#define ME_SPHERETEMP 4
#define ME_HIDE 16
+#define ME_PIN 64
#define ME_VERT_MERGED (1<<6)
/* medge->flag (1=SELECT)*/
@@ -217,7 +243,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 4cf78c83cd0..e7f8594d00e 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -126,7 +126,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/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 6a1b22e1ed5..d67539f8ab0 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -218,6 +218,9 @@ typedef struct ThemeSpace {
char hpad[3];
char pad[4];
+
+ char pin[4];
+ int pin_opac;
} ThemeSpace;
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index 120398791a8..1cc66d0873b 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -18,7 +18,7 @@ dna = env.Clone()
makesdna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesdna/\\"" ')
makesdna_tool.Append (CPPPATH = ['#/intern/guardedalloc',
- '../../makesdna'])
+ '../../makesdna', '../', '../../bmesh'])
if env['OURPLATFORM'] == 'linuxcross':
USE_WINE = True # when cross compiling on linux 64bit this is useful
@@ -49,21 +49,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 72dc6be683c..e814a7891ca 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -8,7 +8,7 @@ objs += o
incs = '#/intern/guardedalloc ../blenkernel ../blenlib ../makesdna intern .'
incs += ' ../windowmanager ../editors/include ../imbuf ../ikplugin'
-incs += ' ../render/extern/include'
+incs += ' ../render/extern/include ../bmesh'
defs = []
diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile
index 7923ea1e7de..e597046c8ba 100644
--- a/source/blender/makesrna/intern/Makefile
+++ b/source/blender/makesrna/intern/Makefile
@@ -53,6 +53,7 @@ CPPFLAGS += -I../../ikplugin
CPPFLAGS += -I../../makesdna
CPPFLAGS += -I../../windowmanager
CPPFLAGS += -I../../editors/include
+CPPFLAGS += -I../../bmesh
CPPFLAGS += -I../../render/extern/include
CPPFLAGS += -I..
CPPFLAGS += -I.
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index c63b63ce5f7..317f3a9779e 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -32,7 +32,7 @@ defs = []
incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel'
incs += ' ../../imbuf ../../makesdna ../../makesrna ../../ikplugin'
incs += ' ../../windowmanager ../../editors/include'
-incs += ' ../../render/extern/include'
+incs += ' ../../render/extern/include ../../bmesh'
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
@@ -134,7 +134,7 @@ rna.Depends (generated_files, makesrna)
# this seems bad, how to retrieve it from scons?
build_dir = root_build_dir + os.sep +'source' + os.sep + 'blender' + os.sep + 'makesrna' + os.sep + 'intern' + os.sep
-
+
if env['OURPLATFORM'] != 'linuxcross':
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
rna.Command (generated_files, '', "\"" + root_build_dir+os.sep+"makesrna.exe\" \"" + build_dir )
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 2bb7905fc03..4ac6b98b167 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_image_api.c 23507 2009-09-27 09:19:29Z kazanbas $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 379cf75d450..7a63f7ebd1d 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_main_api.c 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 039109f75a1..ff995538d1e 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -22,6 +22,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/*note: the original vertex color stuff is now just used for
+ getting info on the layers themselves, accessing the data is
+ done through the (not yet written) mpoly interfaces.*/
+
#include <stdlib.h>
#include "RNA_define.h"
@@ -46,6 +50,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"
@@ -228,15 +233,20 @@ static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *ma
*max= me->totcol-1;
}
-static CustomData *rna_mesh_fdata(Mesh *me)
+static CustomData *rna_mesh_pdata(Mesh *me)
+{
+ return (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
+}
+
+static CustomData *rna_mesh_ldata(Mesh *me)
{
- return (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ return (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata;
}
static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *layer;
int i, length= 0;
@@ -250,7 +260,7 @@ static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
static int rna_CustomDataLayer_active_get(PointerRNA *ptr, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
if(render) return (n == CustomData_get_render_layer_index(fdata, type));
@@ -260,7 +270,7 @@ static int rna_CustomDataLayer_active_get(PointerRNA *ptr, int type, int render)
static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
if(value == 0)
@@ -273,26 +283,26 @@ static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type,
static int rna_uv_texture_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
- return (layer->type != CD_MTFACE);
+ return (layer->type != CD_MTEXPOLY);
}
static void rna_Mesh_uv_textures_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_uv_texture_check);
}
static int rna_Mesh_uv_textures_length(PointerRNA *ptr)
{
- return rna_CustomDataLayer_length(ptr, CD_MTFACE);
+ return rna_CustomDataLayer_length(ptr, CD_MTEXPOLY);
}
static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- int index= CustomData_get_active_layer_index(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ int index= CustomData_get_active_layer_index(fdata, CD_MTEXPOLY);
CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
@@ -301,13 +311,13 @@ static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr)
static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *cdl;
int a;
for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
if(value.data == cdl) {
- CustomData_set_layer_active_index(fdata, CD_MTFACE, a);
+ CustomData_set_layer_active_index(fdata, CD_MTEXPOLY, a);
mesh_update_customdata_pointers(me);
return;
}
@@ -317,166 +327,119 @@ static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value)
static int rna_Mesh_active_uv_texture_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_active_layer(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ return CustomData_get_active_layer(fdata, CD_MTEXPOLY);
}
static void rna_Mesh_active_uv_texture_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
- CustomData_set_layer_active(fdata, CD_MTFACE, value);
+ CustomData_set_layer_active(fdata, CD_MTEXPOLY, value);
mesh_update_customdata_pointers(me);
}
static void rna_Mesh_active_uv_texture_index_range(PointerRNA *ptr, int *min, int *max)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *pdata= rna_mesh_pdata(me);
*min= 0;
- *max= CustomData_number_of_layers(fdata, CD_MTFACE)-1;
+ *max= CustomData_number_of_layers(pdata, CD_MTEXPOLY)-1;
*max= MAX2(0, *max);
}
static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
+ MLoopUV *mloopuv= (MLoopUV*)ptr->data;
- values[0]= mtface->uv[0][0];
- values[1]= mtface->uv[0][1];
+ values[0]= mloopuv->uv[0];
+ values[1]= mloopuv->uv[1];
}
static void rna_MeshTextureFace_uv1_set(PointerRNA *ptr, const float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[0][0]= values[0];
- mtface->uv[0][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv2_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[1][0];
- values[1]= mtface->uv[1][1];
-}
-
-static void rna_MeshTextureFace_uv2_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[1][0]= values[0];
- mtface->uv[1][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv3_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[2][0];
- values[1]= mtface->uv[2][1];
-}
-
-static void rna_MeshTextureFace_uv3_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[2][0]= values[0];
- mtface->uv[2][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv4_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[3][0];
- values[1]= mtface->uv[3][1];
-}
-
-static void rna_MeshTextureFace_uv4_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[3][0]= values[0];
- mtface->uv[3][1]= values[1];
+ MLoopUV *mloopuv= (MLoopUV*)ptr->data;
+
+ mloopuv->uv[0] = values[0];
+ mloopuv->uv[1] = values[1];
}
static int rna_CustomDataData_numverts(PointerRNA *ptr, int type)
{
- Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
- CustomDataLayer *cdl;
- int a;
- size_t b;
+ /*BMESH_TODO
+ Mesh *me= (Mesh*)ptr->id.data;
+ CustomData *fdata= rna_mesh_fdata(me);
+ CustomDataLayer *cdl;
+ int a;
+ size_t b;
- for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
- if(cdl->type == type) {
- b= ((char*)ptr->data - ((char*)cdl->data))/CustomData_sizeof(type);
- if(b >= 0 && b < me->totface)
- return (me->mface[b].v4? 4: 3);
- }
- }
+ for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
+ if(cdl->type == type) {
+ b= ((char*)ptr->data - ((char*)cdl->data))/CustomData_sizeof(type);
+ if(b >= 0 && b < me->totface)
+ return (me->mface[b].v4? 4: 3);
+ }
+ }
- return 0;
+ return 0;*/
+ return 0;
}
static int rna_MeshTextureFace_uv_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
- length[0]= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- length[1]= 2;
- return length[0]*length[1];
+ //return rna_CustomDataData_numverts(ptr, CD_MTFACE) * 2;
+ return 0; //BMESH_TODO
}
static void rna_MeshTextureFace_uv_get(PointerRNA *ptr, float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
- int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+ //MTFace *mtface= (MTFace*)ptr->data;
+ //int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
+ //memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
}
static void rna_MeshTextureFace_uv_set(PointerRNA *ptr, const float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
- int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+ //MTFace *mtface= (MTFace*)ptr->data;
+ //int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
+ //memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
}
static void rna_MeshTextureFaceLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MTFace), me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(MTexPoly), me->totpoly, 0, NULL);
}
static int rna_MeshTextureFaceLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return me->totface;
+ return me->totpoly;
}
static int rna_MeshTextureFaceLayer_active_render_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MTFACE, 1);
+ return rna_CustomDataLayer_active_get(ptr, CD_MTEXPOLY, 1);
}
static int rna_MeshTextureFaceLayer_active_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MTFACE, 0);
+ return rna_CustomDataLayer_active_get(ptr, CD_MTEXPOLY, 0);
}
static void rna_MeshTextureFaceLayer_active_render_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 1);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MTEXPOLY, 1);
}
static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 0);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MTEXPOLY, 0);
}
static void rna_MeshTextureFaceLayer_name_set(PointerRNA *ptr, const char *value)
@@ -484,33 +447,33 @@ static void rna_MeshTextureFaceLayer_name_set(PointerRNA *ptr, const char *value
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
BLI_strncpy(cdl->name, value, sizeof(cdl->name));
- CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers);
+ CustomData_set_layer_unique_name(&me->pdata, cdl - rna_mesh_pdata(me)->layers);
}
static int rna_vertex_color_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
- return (layer->type != CD_MCOL);
+ return (layer->type != CD_MLOOPCOL);
}
static void rna_Mesh_vertex_colors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_vertex_color_check);
+ CustomData *ldata= rna_mesh_ldata(me);
+ rna_iterator_array_begin(iter, (void*)ldata->layers, sizeof(CustomDataLayer), ldata->totlayer, 0, rna_vertex_color_check);
}
static int rna_Mesh_vertex_colors_length(PointerRNA *ptr)
{
- return rna_CustomDataLayer_length(ptr, CD_MCOL);
+ return rna_CustomDataLayer_length(ptr, CD_MLOOPCOL);
}
static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- int index= CustomData_get_active_layer_index(fdata, CD_MCOL);
- CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
+ CustomData *ldata= rna_mesh_ldata(me);
+ int index= CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
+ CustomDataLayer *cdl= (index == -1)? NULL: &ldata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshColorLayer, cdl);
}
@@ -518,42 +481,47 @@ static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr)
static void rna_Mesh_active_vertex_color_set(PointerRNA *ptr, PointerRNA value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me), *fdata;
CustomDataLayer *cdl;
- int a;
+ int a, b, c;
+
+ b = 0;
+ for(cdl=ldata->layers, a=0; a<ldata->totlayer; cdl++, a++) {
+ if (cdl->type == CD_MLOOPCOL)
+ b++;
- for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
if(value.data == cdl) {
- CustomData_set_layer_active_index(fdata, CD_MCOL, a);
- mesh_update_customdata_pointers(me);
- return;
+ CustomData_set_layer_active_index(ldata, CD_MLOOPCOL, a);
+ break;
}
}
+
+ mesh_update_customdata_pointers(me);
}
static int rna_Mesh_active_vertex_color_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_active_layer(fdata, CD_MCOL);
+ CustomData *ldata= rna_mesh_ldata(me);
+ return CustomData_get_active_layer(ldata, CD_MLOOPCOL);
}
static void rna_Mesh_active_vertex_color_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me);
- CustomData_set_layer_active(fdata, CD_MCOL, value);
+ CustomData_set_layer_active(ldata, CD_MLOOPCOL, value);
mesh_update_customdata_pointers(me);
}
static void rna_Mesh_active_vertex_color_index_range(PointerRNA *ptr, int *min, int *max)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me);
*min= 0;
- *max= CustomData_number_of_layers(fdata, CD_MCOL)-1;
+ *max= CustomData_number_of_layers(ldata, CD_MLOOPCOL)-1;
*max= MAX2(0, *max);
}
@@ -561,33 +529,33 @@ static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, Poin
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MCol)*4, me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(CD_MLOOPCOL), me->totloop, 0, NULL);
}
static int rna_MeshColorLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return me->totface;
+ return me->totloop;
}
static int rna_MeshColorLayer_active_render_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MCOL, 1);
+ return rna_CustomDataLayer_active_get(ptr, CD_MLOOPCOL, 1);
}
static int rna_MeshColorLayer_active_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MCOL, 0);
+ return rna_CustomDataLayer_active_get(ptr, CD_MLOOPCOL, 0);
}
static void rna_MeshColorLayer_active_render_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 1);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MLOOPCOL, 1);
}
static void rna_MeshColorLayer_active_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 0);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MLOOPCOL, 0);
}
static void rna_MeshColorLayer_name_set(PointerRNA *ptr, const char *value)
@@ -595,7 +563,7 @@ static void rna_MeshColorLayer_name_set(PointerRNA *ptr, const char *value)
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
BLI_strncpy(cdl->name, value, sizeof(cdl->name));
- CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers);
+ CustomData_set_layer_unique_name(&me->ldata, cdl - rna_mesh_pdata(me)->layers);
}
static void rna_MeshFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -620,7 +588,7 @@ static int rna_float_layer_check(CollectionPropertyIterator *iter, void *data)
static void rna_Mesh_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_float_layer_check);
}
@@ -651,7 +619,7 @@ static int rna_MeshIntPropertyLayer_data_length(PointerRNA *ptr)
static void rna_Mesh_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_int_layer_check);
}
@@ -682,7 +650,7 @@ static int rna_MeshStringPropertyLayer_data_length(PointerRNA *ptr)
static void rna_Mesh_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_string_layer_check);
}
@@ -693,7 +661,7 @@ static int rna_Mesh_string_layers_length(PointerRNA *ptr)
static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value)
{
- MTFace *tf= (MTFace*)ptr->data;
+ MTexPoly *tf= (MTexPoly*)ptr->data;
ID *id= value.data;
if(id) {
@@ -793,7 +761,7 @@ static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr)
static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *cdl;
int a;
size_t b;
@@ -811,7 +779,7 @@ static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type
static char *rna_MeshTextureFace_path(PointerRNA *ptr)
{
- return rna_CustomDataData_path(ptr, "uv_textures", CD_MTFACE);
+ return rna_CustomDataData_path(ptr, "uv_textures", CD_MTEXPOLY);
}
static char *rna_MeshColorLayer_path(PointerRNA *ptr)
@@ -821,7 +789,7 @@ static char *rna_MeshColorLayer_path(PointerRNA *ptr)
static char *rna_MeshColor_path(PointerRNA *ptr)
{
- return rna_CustomDataData_path(ptr, "vertex_colors", CD_MCOL);
+ return rna_CustomDataData_path(ptr, "vertex_colors", CD_MLOOPCOL);
}
static char *rna_MeshSticky_path(PointerRNA *ptr)
@@ -1055,7 +1023,7 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index number of the vertex.");
}
-static void rna_def_mtface(BlenderRNA *brna)
+static void rna_def_mtexpoly(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -1096,7 +1064,7 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_property_collection_funcs(prop, "rna_MeshTextureFaceLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshTextureFaceLayer_data_length", 0, 0, 0, 0);
srna= RNA_def_struct(brna, "MeshTextureFace", NULL);
- RNA_def_struct_sdna(srna, "MTFace");
+ RNA_def_struct_sdna(srna, "MTexPoly");
RNA_def_struct_ui_text(srna, "Mesh Texture Face", "UV mapping, texturing and game engine data for a face.");
RNA_def_struct_path_func(srna, "rna_MeshTextureFace_path");
RNA_def_struct_ui_icon(srna, ICON_FACESEL_HLT);
@@ -1186,30 +1154,6 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Pinned", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
- prop= RNA_def_property(srna, "uv1", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv1_get", "rna_MeshTextureFace_uv1_set", NULL);
- RNA_def_property_ui_text(prop, "UV 1", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv2", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv2_get", "rna_MeshTextureFace_uv2_set", NULL);
- RNA_def_property_ui_text(prop, "UV 2", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv3", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv3_get", "rna_MeshTextureFace_uv3_set", NULL);
- RNA_def_property_ui_text(prop, "UV 3", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv4", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv4_get", "rna_MeshTextureFace_uv4_set", NULL);
- RNA_def_property_ui_text(prop, "UV 4", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
prop= RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
RNA_def_property_multi_array(prop, 2, uv_dim);
RNA_def_property_flag(prop, PROP_DYNAMIC);
@@ -1234,7 +1178,7 @@ static void rna_def_msticky(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
-static void rna_def_mcol(BlenderRNA *brna)
+static void rna_def_mloopcol(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -1260,6 +1204,7 @@ static void rna_def_mcol(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
RNA_def_property_boolean_funcs(prop, "rna_MeshColorLayer_active_render_get", "rna_MeshColorLayer_active_render_set");
RNA_def_property_ui_text(prop, "Active Render", "Sets the layer as active for rendering");
+
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
@@ -1272,32 +1217,6 @@ static void rna_def_mcol(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Mesh Vertex Color", "Vertex colors for a face in a Mesh.");
RNA_def_struct_path_func(srna, "rna_MeshColor_path");
- prop= RNA_def_property(srna, "color1", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color1_get", "rna_MeshColor_color1_set", NULL);
- RNA_def_property_ui_text(prop, "Color 1", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color2", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color2_get", "rna_MeshColor_color2_set", NULL);
- RNA_def_property_ui_text(prop, "Color 2", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color3", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color3_get", "rna_MeshColor_color3_set", NULL);
- RNA_def_property_ui_text(prop, "Color 3", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color4", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color4_get", "rna_MeshColor_color4_set", NULL);
- RNA_def_property_ui_text(prop, "Color 4", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
@@ -1457,7 +1376,7 @@ static void rna_def_mesh(BlenderRNA *brna)
/* UV textures */
prop= RNA_def_property(srna, "uv_textures", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_textures_begin", 0, 0, 0, "rna_Mesh_uv_textures_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
RNA_def_property_ui_text(prop, "UV Textures", "");
@@ -1477,7 +1396,7 @@ static void rna_def_mesh(BlenderRNA *brna)
/* Vertex colors */
prop= RNA_def_property(srna, "vertex_colors", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "ldata.layers", "ldata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_colors_begin", 0, 0, 0, "rna_Mesh_vertex_colors_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshColorLayer");
RNA_def_property_ui_text(prop, "Vertex Colors", "");
@@ -1495,19 +1414,19 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop= RNA_def_property(srna, "float_layers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_float_layers_begin", 0, 0, 0, "rna_Mesh_float_layers_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshFloatPropertyLayer");
RNA_def_property_ui_text(prop, "Float Property Layers", "");
prop= RNA_def_property(srna, "int_layers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_int_layers_begin", 0, 0, 0, "rna_Mesh_int_layers_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshIntPropertyLayer");
RNA_def_property_ui_text(prop, "Int Property Layers", "");
prop= RNA_def_property(srna, "string_layers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_string_layers_begin", 0, 0, 0, "rna_Mesh_string_layers_length", 0, 0, 0, 0);
RNA_def_property_struct_type(prop, "MeshStringPropertyLayer");
RNA_def_property_ui_text(prop, "String Property Layers", "");
@@ -1538,7 +1457,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop= RNA_def_property(srna, "shape_keys", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "key");
RNA_def_property_ui_text(prop, "Shape Keys", "");
-
+
/* Mesh Draw Options for Edit Mode*/
prop= RNA_def_property(srna, "draw_edges", PROP_BOOLEAN, PROP_NONE);
@@ -1584,7 +1503,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWSHARP);
RNA_def_property_ui_text(prop, "Draw Sharp", "Displays sharp edges, used with the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
-
+
prop= RNA_def_property(srna, "draw_edge_lenght", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_EDGELEN);
RNA_def_property_ui_text(prop, "Edge Length", "Displays selected edge lengths");
@@ -1600,6 +1519,10 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Face Area", "Displays the area of selected faces");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+ prop= RNA_def_property(srna, "draw_pins", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_PINS);
+ RNA_def_property_ui_text(prop, "Draw Pins", "Displays pinned mesh elements");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
/* editflag */
prop= RNA_def_property(srna, "use_mirror_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_MIRROR_X);
@@ -1627,9 +1550,9 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mvert_group(brna);
rna_def_medge(brna);
rna_def_mface(brna);
- rna_def_mtface(brna);
+ rna_def_mtexpoly(brna);
rna_def_msticky(brna);
- rna_def_mcol(brna);
+ rna_def_mloopcol(brna);
rna_def_mproperties(brna);
}
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 52ff98f66f0..32bcf5c1bc8 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_mesh_api.c 21283 2009-07-01 12:19:00Z blendix $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 20d1a898303..b70af62a556 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_nla.c 21537 2009-07-11 22:22:53Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 09e0ac3feac..8dd8d591088 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -40,6 +40,8 @@
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
+#include "BKE_tessmesh.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -406,8 +408,8 @@ static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
if((ob->mode & OB_MODE_EDIT) && ob->type==OB_MESH) {
Mesh *me= ob->data;
- if(me->edit_mesh)
- me->edit_mesh->mat_nr= value;
+ if(me->edit_btmesh)
+ me->edit_btmesh->mat_nr= value;
}
}
diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c
index 40bb131b3f9..c6791405109 100644
--- a/source/blender/makesrna/intern/rna_pose_api.c
+++ b/source/blender/makesrna/intern/rna_pose_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_pose_api.c 23425 2009-09-22 19:09:04Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 722b686218b..76778214537 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -724,6 +724,16 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop= RNA_def_property(srna, "pin", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Pin", "");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ prop= RNA_def_property(srna, "pin_opac", PROP_INT, PROP_PERCENTAGE);
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pin Face Opacity", "");
+ RNA_def_property_update(prop, NC_WINDOW, NULL);
}
static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 44c6967189d..1a5568cb4f4 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: rna_wm_api.c 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
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/Makefile b/source/blender/python/Makefile
index 8e2a04b8449..b120dc6ad46 100644
--- a/source/blender/python/Makefile
+++ b/source/blender/python/Makefile
@@ -1,5 +1,5 @@
#
-# $Id$
+# $Id: Makefile 21094 2009-06-23 00:09:26Z gsrb3d $
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c
index 767af8e0836..aa4e557126e 100644
--- a/source/blender/python/generic/BGL.c
+++ b/source/blender/python/generic/BGL.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BGL.c 21218 2009-06-28 13:27:06Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h
index 91f88549faf..35547de989f 100644
--- a/source/blender/python/generic/BGL.h
+++ b/source/blender/python/generic/BGL.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: BGL.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c
index f7b7ee866f0..cba2a0d3227 100644
--- a/source/blender/python/generic/Geometry.c
+++ b/source/blender/python/generic/Geometry.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Geometry.c 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Geometry.h b/source/blender/python/generic/Geometry.h
index 0e46c0d18db..9257e3f80fc 100644
--- a/source/blender/python/generic/Geometry.h
+++ b/source/blender/python/generic/Geometry.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Geometry.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
index 431f1987383..715c463fa1f 100644
--- a/source/blender/python/generic/Mathutils.c
+++ b/source/blender/python/generic/Mathutils.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Mathutils.c 21559 2009-07-13 12:17:07Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h
index ad67d2e511e..29cbd203741 100644
--- a/source/blender/python/generic/Mathutils.h
+++ b/source/blender/python/generic/Mathutils.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: Mathutils.h 21499 2009-07-10 18:09:53Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 05c846b16f5..c45101819ca 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: bpy_internal_import.c 21094 2009-06-23 00:09:26Z gsrb3d $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index 4e761fe8da0..0e9b2d42059 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: bpy_internal_import.h 21094 2009-06-23 00:09:26Z gsrb3d $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
index 73fcaeb457b..754eb634a0d 100644
--- a/source/blender/python/generic/euler.c
+++ b/source/blender/python/generic/euler.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: euler.c 21462 2009-07-09 15:40:04Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h
index 74d184fef81..22d87dbb766 100644
--- a/source/blender/python/generic/euler.h
+++ b/source/blender/python/generic/euler.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: euler.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
index 5a49118b519..d8100746c9a 100644
--- a/source/blender/python/generic/matrix.c
+++ b/source/blender/python/generic/matrix.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: matrix.c 21293 2009-07-01 20:55:32Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h
index 856c711c4ef..bb598e07061 100644
--- a/source/blender/python/generic/matrix.h
+++ b/source/blender/python/generic/matrix.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: matrix.h 21254 2009-06-30 00:42:17Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
index 7e12fe7925a..172d2574fcb 100644
--- a/source/blender/python/generic/quat.c
+++ b/source/blender/python/generic/quat.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: quat.c 21462 2009-07-09 15:40:04Z ton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h
index a1d01b4982d..2934bef0ad3 100644
--- a/source/blender/python/generic/quat.h
+++ b/source/blender/python/generic/quat.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: quat.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index 605f45be128..91f3f39a00f 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: vector.c 21462 2009-07-09 15:40:04Z ton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h
index a13ec0f80f3..fba53d2e2bf 100644
--- a/source/blender/python/generic/vector.h
+++ b/source/blender/python/generic/vector.h
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: vector.h 21254 2009-06-30 00:42:17Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 9e76c1d03aa..a3b807c9a8d 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -293,7 +293,10 @@ void BPY_start_python( int argc, char **argv )
Py_Initialize( );
+ /*convert argv to wchar_t*/
// PySys_SetArgv( argc, argv); // broken in py3, not a huge deal
+
+ /*temporarily set argv*/
/* sigh, why do python guys not have a char** version anymore? :( */
{
int i;
diff --git a/source/blender/python/intern/bpy_operator.h b/source/blender/python/intern/bpy_operator.h
index 46ea144fd4d..0e826eab10e 100644
--- a/source/blender/python/intern/bpy_operator.h
+++ b/source/blender/python/intern/bpy_operator.h
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h
index 2929d57ab82..9718e2d6e65 100644
--- a/source/blender/python/intern/bpy_operator_wrap.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -1,6 +1,6 @@
/**
- * $Id$
+ * $Id: bpy_operator_wrap.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/intern/bpy_ui.h b/source/blender/python/intern/bpy_ui.h
index 4182a32d3f0..95afa1f08c8 100644
--- a/source/blender/python/intern/bpy_ui.h
+++ b/source/blender/python/intern/bpy_ui.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: bpy_ui.h 21094 2009-06-23 00:09:26Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c
index 5672b9f4cb2..4ad95816f7f 100644
--- a/source/blender/readblenfile/intern/BLO_readblenfile.c
+++ b/source/blender/readblenfile/intern/BLO_readblenfile.c
@@ -171,4 +171,3 @@ cleanup:
return bfd;
}
-
diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h
deleted file mode 100644
index 5579f3896c1..00000000000
--- a/source/blender/render/intern/include/rayobject.h
+++ /dev/null
@@ -1,208 +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.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#ifndef RE_RAYOBJECT_H
-#define RE_RAYOBJECT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "RE_raytrace.h"
-#include "render_types.h"
-#include <stdio.h>
-#include <float.h>
-
-
-/* RayObject
-
- A ray object is everything where we can cast rays like:
- * a face/triangle
- * an octree
- * a bvh tree
- * an octree of bvh's
- * a bvh of bvh's
-
-
- All types of RayObjects can be created by implementing the
- callbacks of the RayObject.
-
- Due to high computing time evolved with casting on faces
- there is a special type of RayObject (named RayFace)
- which won't use callbacks like other generic nodes.
-
- In order to allow a mixture of RayFace+RayObjects,
- all RayObjects must be 4byte aligned, allowing us to use the
- 2 least significant bits (with the mask 0x03) to define the
- type of RayObject.
-
- This leads to 4 possible types of RayObject:
-
- addr&3 - type of object
- 0 Self (reserved for each structure)
- 1 RayFace (tri/quad primitive)
- 2 RayObject (generic with API callbacks)
- 3 VlakPrimitive
- (vlak primitive - to be used when we have a vlak describing the data
- eg.: on render code)
-
- 0 means it's reserved and has it own meaning inside each ray acceleration structure
- (this way each structure can use the allign offset to determine if a node represents a
- RayObject primitive, which can be used to save memory)
-
- You actually don't need to care about this if you are only using the API
- described on RE_raytrace.h
- */
-
-/* used to align a given ray object */
-#define RE_rayobject_align(o) ((RayObject*)(((intptr_t)o)&(~3)))
-
-/* used to unalign a given ray object */
-#define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1))
-#define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2))
-#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject*)(((intptr_t)o)|3))
-
-/* used to test the type of ray object */
-#define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0)
-#define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1)
-#define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2)
-#define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3)
-
-
-
-/*
- * This class is intended as a place holder for control, configuration of the rayobject like:
- * - stop building (TODO maybe when porting build to threads this could be implemented with some thread_cancel function)
- * - max number of threads and threads callback to use during build
- * ...
- */
-typedef int (*RE_rayobjectcontrol_test_break_callback)(void *data);
-typedef struct RayObjectControl RayObjectControl;
-struct RayObjectControl
-{
- void *data;
- RE_rayobjectcontrol_test_break_callback test_break;
-};
-
-/*
- * This rayobject represents a generic object. With it's own callbacks for raytrace operations.
- * It's suitable to implement things like LOD.
- */
-struct RayObject
-{
- struct RayObjectAPI *api;
-
- struct RayObjectControl control;
-};
-
-
-
-
-typedef int (*RE_rayobject_raycast_callback)(RayObject *, Isect *);
-typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject);
-typedef void (*RE_rayobject_done_callback)(RayObject *);
-typedef void (*RE_rayobject_free_callback)(RayObject *);
-typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max);
-typedef float (*RE_rayobject_cost_callback)(RayObject *);
-typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, RayHint *, float *, float *);
-
-typedef struct RayObjectAPI
-{
- RE_rayobject_raycast_callback raycast;
- RE_rayobject_add_callback add;
- RE_rayobject_done_callback done;
- RE_rayobject_free_callback free;
- RE_rayobject_merge_bb_callback bb;
- RE_rayobject_cost_callback cost;
- RE_rayobject_hint_bb_callback hint_bb;
-
-} RayObjectAPI;
-
-
-/*
- * This function differs from RE_rayobject_raycast
- * RE_rayobject_intersect does NOT perform last-hit optimization
- * So this is probably a function to call inside raytrace structures
- */
-int RE_rayobject_intersect(RayObject *r, Isect *i);
-
-/*
- * Returns distance ray must travel to hit the given bounding box
- * BB should be in format [2][3]
- */
-/* float RE_rayobject_bb_intersect(const Isect *i, const float *bb); */
-int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as bb_intersect but doens't calculates distance */
-
-/*
- * Returns the expected cost of raycast on this node, primitives have a cost of 1
- */
-float RE_rayobject_cost(RayObject *r);
-
-
-/*
- * Returns true if for some reason a heavy processing function should stop
- * (eg.: user asked to stop during a tree a build)
- */
-int RE_rayobjectcontrol_test_break(RayObjectControl *c);
-
-
-#define ISECT_EPSILON ((float)FLT_EPSILON)
-
-
-
-#if !defined(_WIN32) && !defined(_WIN64)
-
-#include <sys/time.h>
-#include <time.h>
-
-#define BENCH(a,name) \
- do { \
- double _t1, _t2; \
- struct timeval _tstart, _tend; \
- clock_t _clock_init = clock(); \
- gettimeofday ( &_tstart, NULL); \
- (a); \
- gettimeofday ( &_tend, NULL); \
- _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \
- _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \
- printf("BENCH:%s: %fs (real) %fs (cpu)\n", #name, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\
- } while(0)
-#else
-
-#define BENCH(a,name) (a)
-
-#endif
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 072083e58a7..f54d7dd20ab 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1470,7 +1470,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;
@@ -1487,7 +1487,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;
@@ -1705,8 +1705,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]);
@@ -1766,7 +1766,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);
@@ -1843,7 +1843,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);
@@ -2926,10 +2926,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;
@@ -3147,7 +3147,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;
@@ -3208,8 +3208,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/rayobject_blibvh.c b/source/blender/render/intern/source/rayobject_blibvh.c
deleted file mode 100644
index 3fd71862f54..00000000000
--- a/source/blender/render/intern/source/rayobject_blibvh.c
+++ /dev/null
@@ -1,169 +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.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#include <assert.h>
-
-#include "MEM_guardedalloc.h"
-#include "BKE_utildefines.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_arithb.h"
-#include "RE_raytrace.h"
-#include "render_types.h"
-#include "rayobject.h"
-
-static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec);
-static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob);
-static void RE_rayobject_blibvh_done(RayObject *o);
-static void RE_rayobject_blibvh_free(RayObject *o);
-static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max);
-
-static float RE_rayobject_blibvh_cost(RayObject *o)
-{
- //TODO calculate the expected cost to raycast on this structure
- return 1.0;
-}
-
-static void RE_rayobject_blibvh_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
-{
- return;
-}
-
-static RayObjectAPI bvh_api =
-{
- RE_rayobject_blibvh_intersect,
- RE_rayobject_blibvh_add,
- RE_rayobject_blibvh_done,
- RE_rayobject_blibvh_free,
- RE_rayobject_blibvh_bb,
- RE_rayobject_blibvh_cost,
- RE_rayobject_blibvh_hint_bb
-};
-
-typedef struct BVHObject
-{
- RayObject rayobj;
- RayObject **leafs, **next_leaf;
- BVHTree *bvh;
- float bb[2][3];
-
-} BVHObject;
-
-
-RayObject *RE_rayobject_blibvh_create(int size)
-{
- BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject");
- assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */
-
- obj->rayobj.api = &bvh_api;
- obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6);
- obj->next_leaf = obj->leafs = (RayObject**)MEM_callocN(size*sizeof(RayObject*), "BVHObject leafs");
-
- INIT_MINMAX(obj->bb[0], obj->bb[1]);
- return RE_rayobject_unalignRayAPI((RayObject*) obj);
-}
-
-struct BVHCallbackUserData
-{
- Isect *isec;
- RayObject **leafs;
-};
-
-static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- struct BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata;
- Isect *isec = data->isec;
- RayObject *face = data->leafs[index];
-
- if(RE_rayobject_intersect(face,isec))
- {
- hit->index = index;
-
- if(isec->mode == RE_RAY_SHADOW)
- hit->dist = 0;
- else
- hit->dist = isec->labda*isec->dist;
- }
-}
-
-static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec)
-{
- BVHObject *obj = (BVHObject*)o;
- BVHTreeRayHit hit;
- float dir[3];
- struct BVHCallbackUserData data;
- data.isec = isec;
- data.leafs = obj->leafs;
-
- VECCOPY(dir, isec->vec);
- Normalize(dir);
-
- hit.index = 0;
- hit.dist = isec->labda*isec->dist;
-
- return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, (void*)&data);
-}
-
-static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob)
-{
- BVHObject *obj = (BVHObject*)o;
- float min_max[6];
- INIT_MINMAX(min_max, min_max+3);
- RE_rayobject_merge_bb(ob, min_max, min_max+3);
-
- DO_MIN(min_max , obj->bb[0]);
- DO_MAX(min_max+3, obj->bb[1]);
-
- BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2 );
- *(obj->next_leaf++) = ob;
-}
-
-static void RE_rayobject_blibvh_done(RayObject *o)
-{
- BVHObject *obj = (BVHObject*)o;
- BLI_bvhtree_balance(obj->bvh);
-}
-
-static void RE_rayobject_blibvh_free(RayObject *o)
-{
- BVHObject *obj = (BVHObject*)o;
-
- if(obj->bvh)
- BLI_bvhtree_free(obj->bvh);
-
- if(obj->leafs)
- MEM_freeN(obj->leafs);
-
- MEM_freeN(obj);
-}
-
-static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max)
-{
- BVHObject *obj = (BVHObject*)o;
- DO_MIN( obj->bb[0], min );
- DO_MAX( obj->bb[1], max );
-}
diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c
deleted file mode 100644
index e2f4dc5a9dd..00000000000
--- a/source/blender/render/intern/source/rayobject_instance.c
+++ /dev/null
@@ -1,200 +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.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#include <assert.h>
-
-#include "MEM_guardedalloc.h"
-#include "BKE_utildefines.h"
-#include "BLI_arithb.h"
-#include "RE_raytrace.h"
-#include "rayobject.h"
-
-#define RE_COST_INSTANCE (1.0f)
-
-static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec);
-static void RE_rayobject_instance_free(RayObject *o);
-static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max);
-static float RE_rayobject_instance_cost(RayObject *o);
-
-static void RE_rayobject_instance_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
-{}
-
-static RayObjectAPI instance_api =
-{
- RE_rayobject_instance_intersect,
- NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob);
- NULL, //static void RE_rayobject_instance_done(RayObject *o);
- RE_rayobject_instance_free,
- RE_rayobject_instance_bb,
- RE_rayobject_instance_cost,
- RE_rayobject_instance_hint_bb
-};
-
-typedef struct InstanceRayObject
-{
- RayObject rayobj;
- RayObject *target;
-
- void *ob; //Object represented by this instance
- void *target_ob; //Object represented by the inner RayObject, needed to handle self-intersection
-
- float global2target[4][4];
- float target2global[4][4];
-
-} InstanceRayObject;
-
-
-RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob)
-{
- InstanceRayObject *obj= (InstanceRayObject*)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject");
- assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */
-
- obj->rayobj.api = &instance_api;
- obj->target = target;
- obj->ob = ob;
- obj->target_ob = target_ob;
-
- Mat4CpyMat4(obj->target2global, transform);
- Mat4Invert(obj->global2target, obj->target2global);
-
- return RE_rayobject_unalignRayAPI((RayObject*) obj);
-}
-
-static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
-{
- //TODO
- // *there is probably a faster way to convert between coordinates
-
- InstanceRayObject *obj = (InstanceRayObject*)o;
- int res;
- float start[3], vec[3], labda, dist;
- int changed = 0, i;
-
- //TODO - this is disabling self intersection on instances
- if(isec->orig.ob == obj->ob && obj->ob)
- {
- changed = 1;
- isec->orig.ob = obj->target_ob;
- }
-
-
- VECCOPY( start, isec->start );
- VECCOPY( vec , isec->vec );
- labda = isec->labda;
- dist = isec->dist;
-
- //Transform to target coordinates system
- VECADD( isec->vec, isec->vec, isec->start );
-
- Mat4MulVecfl(obj->global2target, isec->start);
- Mat4MulVecfl(obj->global2target, isec->vec );
-
- isec->dist = VecLenf( isec->start, isec->vec );
- VECSUB( isec->vec, isec->vec, isec->start );
-
- isec->labda *= isec->dist / dist;
-
- //Update idot_axis and bv_index
- for(i=0; i<3; i++)
- {
- isec->idot_axis[i] = 1.0f / isec->vec[i];
-
- isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0;
- isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i];
-
- isec->bv_index[2*i] = i+3*isec->bv_index[2*i];
- isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1];
- }
-
- //Raycast
- res = RE_rayobject_intersect(obj->target, isec);
-
- //Restore coordinate space coords
- if(res == 0)
- {
- isec->labda = labda;
- }
- else
- {
- isec->labda *= dist / isec->dist;
- isec->hit.ob = obj->ob;
- }
- isec->dist = dist;
- VECCOPY( isec->start, start );
- VECCOPY( isec->vec, vec );
-
- if(changed)
- isec->orig.ob = obj->ob;
-
- //Update idot_axis and bv_index
- for(i=0; i<3; i++)
- {
- isec->idot_axis[i] = 1.0f / isec->vec[i];
-
- isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0;
- isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i];
-
- isec->bv_index[2*i] = i+3*isec->bv_index[2*i];
- isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1];
- }
-
- return res;
-}
-
-static void RE_rayobject_instance_free(RayObject *o)
-{
- InstanceRayObject *obj = (InstanceRayObject*)o;
- MEM_freeN(obj);
-}
-
-static float RE_rayobject_instance_cost(RayObject *o)
-{
- InstanceRayObject *obj = (InstanceRayObject*)o;
- return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE;
-}
-
-static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
-{
- //TODO:
- // *better bb.. calculated without rotations of bb
- // *maybe cache that better-fitted-BB at the InstanceRayObject
- InstanceRayObject *obj = (InstanceRayObject*)o;
-
- float m[3], M[3], t[3];
- int i, j;
- INIT_MINMAX(m, M);
- RE_rayobject_merge_bb(obj->target, m, M);
-
- //There must be a faster way than rotating all the 8 vertexs of the BB
- for(i=0; i<8; i++)
- {
- for(j=0; j<3; j++) t[j] = i&(1<<j) ? M[j] : m[j];
- Mat4MulVecfl(obj->target2global, t);
- DO_MINMAX(t, min, max);
- }
-}
diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c
deleted file mode 100644
index 2f0a1a3f53b..00000000000
--- a/source/blender/render/intern/source/rayobject_octree.c
+++ /dev/null
@@ -1,1080 +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) 1990-1998 NeoGeo BV.
- * All rights reserved.
- *
- * Contributors: 2004/2005 Blender Foundation, full recode
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/* IMPORTANT NOTE: this code must be independent of any other render code
- to use it outside the renderer! */
-
-#include <math.h>
-#include <string.h>
-#include <stdlib.h>
-#include <float.h>
-#include <assert.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_material_types.h"
-
-#include "BKE_utildefines.h"
-
-#include "BLI_arithb.h"
-
-#include "rayobject.h"
-
-/* ********** structs *************** */
-#define BRANCH_ARRAY 1024
-#define NODE_ARRAY 4096
-
-typedef struct Branch
-{
- struct Branch *b[8];
-} Branch;
-
-typedef struct OcVal
-{
- short ocx, ocy, ocz;
-} OcVal;
-
-typedef struct Node
-{
- struct RayFace *v[8];
- struct OcVal ov[8];
- struct Node *next;
-} Node;
-
-typedef struct Octree {
- RayObject rayobj;
-
- struct Branch **adrbranch;
- struct Node **adrnode;
- float ocsize; /* ocsize: mult factor, max size octree */
- float ocfacx,ocfacy,ocfacz;
- float min[3], max[3];
- int ocres;
- int branchcount, nodecount;
-
- /* during building only */
- char *ocface;
-
- RayFace **ro_nodes;
- int ro_nodes_size, ro_nodes_used;
-
-} Octree;
-
-static int RE_rayobject_octree_intersect(RayObject *o, Isect *isec);
-static void RE_rayobject_octree_add(RayObject *o, RayObject *ob);
-static void RE_rayobject_octree_done(RayObject *o);
-static void RE_rayobject_octree_free(RayObject *o);
-static void RE_rayobject_octree_bb(RayObject *o, float *min, float *max);
-
-/*
- * This function is not expected to be called by current code state.
- */
-static float RE_rayobject_octree_cost(RayObject *o)
-{
- return 1.0;
-}
-
-static void RE_rayobject_octree_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
-{
- return;
-}
-
-static RayObjectAPI octree_api =
-{
- RE_rayobject_octree_intersect,
- RE_rayobject_octree_add,
- RE_rayobject_octree_done,
- RE_rayobject_octree_free,
- RE_rayobject_octree_bb,
- RE_rayobject_octree_cost,
- RE_rayobject_octree_hint_bb
-};
-
-/* **************** ocval method ******************* */
-/* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */
-
-#define OCVALRES 15
-#define BROW16(min, max) (((max)>=OCVALRES? 0xFFFF: (1<<(max+1))-1) - ((min>0)? ((1<<(min))-1):0) )
-
-static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov)
-{
- float min[3], max[3];
- int ocmin, ocmax;
-
- VECCOPY(min, v1);
- VECCOPY(max, v1);
- DO_MINMAX(v2, min, max);
- DO_MINMAX(v3, min, max);
- if(v4) {
- DO_MINMAX(v4, min, max);
- }
-
- ocmin= OCVALRES*(min[0]-x);
- ocmax= OCVALRES*(max[0]-x);
- ov->ocx= BROW16(ocmin, ocmax);
-
- ocmin= OCVALRES*(min[1]-y);
- ocmax= OCVALRES*(max[1]-y);
- ov->ocy= BROW16(ocmin, ocmax);
-
- ocmin= OCVALRES*(min[2]-z);
- ocmax= OCVALRES*(max[2]-z);
- ov->ocz= BROW16(ocmin, ocmax);
-
-}
-
-static void calc_ocval_ray(OcVal *ov, float xo, float yo, float zo, float *vec1, float *vec2)
-{
- int ocmin, ocmax;
-
- if(vec1[0]<vec2[0]) {
- ocmin= OCVALRES*(vec1[0] - xo);
- ocmax= OCVALRES*(vec2[0] - xo);
- } else {
- ocmin= OCVALRES*(vec2[0] - xo);
- ocmax= OCVALRES*(vec1[0] - xo);
- }
- ov->ocx= BROW16(ocmin, ocmax);
-
- if(vec1[1]<vec2[1]) {
- ocmin= OCVALRES*(vec1[1] - yo);
- ocmax= OCVALRES*(vec2[1] - yo);
- } else {
- ocmin= OCVALRES*(vec2[1] - yo);
- ocmax= OCVALRES*(vec1[1] - yo);
- }
- ov->ocy= BROW16(ocmin, ocmax);
-
- if(vec1[2]<vec2[2]) {
- ocmin= OCVALRES*(vec1[2] - zo);
- ocmax= OCVALRES*(vec2[2] - zo);
- } else {
- ocmin= OCVALRES*(vec2[2] - zo);
- ocmax= OCVALRES*(vec1[2] - zo);
- }
- ov->ocz= BROW16(ocmin, ocmax);
-}
-
-/* ************* octree ************** */
-
-static Branch *addbranch(Octree *oc, Branch *br, short ocb)
-{
- int index;
-
- if(br->b[ocb]) return br->b[ocb];
-
- oc->branchcount++;
- index= oc->branchcount>>12;
-
- if(oc->adrbranch[index]==NULL)
- oc->adrbranch[index]= MEM_callocN(4096*sizeof(Branch), "new oc branch");
-
- if(oc->branchcount>= BRANCH_ARRAY*4096) {
- printf("error; octree branches full\n");
- oc->branchcount=0;
- }
-
- return br->b[ocb]= oc->adrbranch[index]+(oc->branchcount & 4095);
-}
-
-static Node *addnode(Octree *oc)
-{
- int index;
-
- oc->nodecount++;
- index= oc->nodecount>>12;
-
- if(oc->adrnode[index]==NULL)
- oc->adrnode[index]= MEM_callocN(4096*sizeof(Node),"addnode");
-
- if(oc->nodecount> NODE_ARRAY*NODE_ARRAY) {
- printf("error; octree nodes full\n");
- oc->nodecount=0;
- }
-
- return oc->adrnode[index]+(oc->nodecount & 4095);
-}
-
-static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3])
-{
- static float nor[3], d;
- float fx, fy, fz;
-
- // init static vars
- if(face) {
- CalcNormFloat(rtf[0], rtf[1], rtf[2], nor);
- d= -nor[0]*rtf[0][0] - nor[1]*rtf[0][1] - nor[2]*rtf[0][2];
- return 0;
- }
-
- fx= x;
- fy= y;
- fz= z;
-
- if((fx)*nor[0] + (fy)*nor[1] + (fz)*nor[2] + d > 0.0f) {
- if((fx+1)*nor[0] + (fy )*nor[1] + (fz )*nor[2] + d < 0.0f) return 1;
- if((fx )*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d < 0.0f) return 1;
- if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d < 0.0f) return 1;
-
- if((fx )*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
- if((fx+1)*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
- if((fx )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
- if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
- }
- else {
- if((fx+1)*nor[0] + (fy )*nor[1] + (fz )*nor[2] + d > 0.0f) return 1;
- if((fx )*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d > 0.0f) return 1;
- if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d > 0.0f) return 1;
-
- if((fx )*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
- if((fx+1)*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
- if((fx )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
- if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
- }
-
- return 0;
-}
-
-static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3])
-{
- Branch *br;
- Node *no;
- short a, oc0, oc1, oc2, oc3, oc4, oc5;
-
- x<<=2;
- y<<=1;
-
- br= oc->adrbranch[0];
-
- if(oc->ocres==512) {
- oc0= ((x & 1024)+(y & 512)+(z & 256))>>8;
- br= addbranch(oc, br, oc0);
- }
- if(oc->ocres>=256) {
- oc0= ((x & 512)+(y & 256)+(z & 128))>>7;
- br= addbranch(oc, br, oc0);
- }
- if(oc->ocres>=128) {
- oc0= ((x & 256)+(y & 128)+(z & 64))>>6;
- br= addbranch(oc, br, oc0);
- }
-
- oc0= ((x & 128)+(y & 64)+(z & 32))>>5;
- oc1= ((x & 64)+(y & 32)+(z & 16))>>4;
- oc2= ((x & 32)+(y & 16)+(z & 8))>>3;
- oc3= ((x & 16)+(y & 8)+(z & 4))>>2;
- oc4= ((x & 8)+(y & 4)+(z & 2))>>1;
- oc5= ((x & 4)+(y & 2)+(z & 1));
-
- br= addbranch(oc, br,oc0);
- br= addbranch(oc, br,oc1);
- br= addbranch(oc, br,oc2);
- br= addbranch(oc, br,oc3);
- br= addbranch(oc, br,oc4);
- no= (Node *)br->b[oc5];
- if(no==NULL) br->b[oc5]= (Branch *)(no= addnode(oc));
-
- while(no->next) no= no->next;
-
- a= 0;
- if(no->v[7]) { /* node full */
- no->next= addnode(oc);
- no= no->next;
- }
- else {
- while(no->v[a]!=NULL) a++;
- }
-
- no->v[a]= (RayFace*) RE_rayobject_align(face);
-
- if(quad)
- calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]);
- else
- calc_ocval_face(rtf[0], rtf[1], rtf[2], NULL, x>>2, y>>1, z, &no->ov[a]);
-}
-
-static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocface, short rts[][3], float rtf[][3])
-{
- int ocx1,ocx2,ocy1,ocy2;
- int x,y,dx=0,dy=0;
- float ox1,ox2,oy1,oy2;
- float labda,labdao,labdax,labday,ldx,ldy;
-
- ocx1= rts[b1][c1];
- ocy1= rts[b1][c2];
- ocx2= rts[b2][c1];
- ocy2= rts[b2][c2];
-
- if(ocx1==ocx2 && ocy1==ocy2) {
- ocface[oc->ocres*ocx1+ocy1]= 1;
- return;
- }
-
- ox1= rtf[b1][c1];
- oy1= rtf[b1][c2];
- ox2= rtf[b2][c1];
- oy2= rtf[b2][c2];
-
- if(ox1!=ox2) {
- if(ox2-ox1>0.0f) {
- labdax= (ox1-ocx1-1.0f)/(ox1-ox2);
- ldx= -1.0f/(ox1-ox2);
- dx= 1;
- } else {
- labdax= (ox1-ocx1)/(ox1-ox2);
- ldx= 1.0f/(ox1-ox2);
- dx= -1;
- }
- } else {
- labdax=1.0f;
- ldx=0;
- }
-
- if(oy1!=oy2) {
- if(oy2-oy1>0.0f) {
- labday= (oy1-ocy1-1.0f)/(oy1-oy2);
- ldy= -1.0f/(oy1-oy2);
- dy= 1;
- } else {
- labday= (oy1-ocy1)/(oy1-oy2);
- ldy= 1.0f/(oy1-oy2);
- dy= -1;
- }
- } else {
- labday=1.0f;
- ldy=0;
- }
-
- x=ocx1; y=ocy1;
- labda= MIN2(labdax, labday);
-
- while(TRUE) {
-
- if(x<0 || y<0 || x>=oc->ocres || y>=oc->ocres);
- else ocface[oc->ocres*x+y]= 1;
-
- labdao=labda;
- if(labdax==labday) {
- labdax+=ldx;
- x+=dx;
- labday+=ldy;
- y+=dy;
- } else {
- if(labdax<labday) {
- labdax+=ldx;
- x+=dx;
- } else {
- labday+=ldy;
- y+=dy;
- }
- }
- labda=MIN2(labdax,labday);
- if(labda==labdao) break;
- if(labda>=1.0f) break;
- }
- ocface[oc->ocres*ocx2+ocy2]=1;
-}
-
-static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax)
-{
- int a, x, y, y1, y2;
-
- for(x=ocmin[c1];x<=ocmax[c1];x++) {
- a= oc->ocres*x;
- for(y=ocmin[c2];y<=ocmax[c2];y++) {
- if(ocface[a+y]) {
- y++;
- while(ocface[a+y] && y!=ocmax[c2]) y++;
- for(y1=ocmax[c2];y1>y;y1--) {
- if(ocface[a+y1]) {
- for(y2=y;y2<=y1;y2++) ocface[a+y2]=1;
- y1=0;
- }
- }
- y=ocmax[c2];
- }
- }
- }
-}
-
-static void RE_rayobject_octree_free(RayObject *tree)
-{
- Octree *oc= (Octree*)tree;
-
-#if 0
- printf("branches %d nodes %d\n", oc->branchcount, oc->nodecount);
- printf("raycount %d \n", raycount);
- printf("ray coherent %d \n", coherent_ray);
- printf("accepted %d rejected %d\n", accepted, rejected);
-#endif
- if(oc->ocface)
- MEM_freeN(oc->ocface);
-
- if(oc->adrbranch) {
- int a= 0;
- while(oc->adrbranch[a]) {
- MEM_freeN(oc->adrbranch[a]);
- oc->adrbranch[a]= NULL;
- a++;
- }
- MEM_freeN(oc->adrbranch);
- oc->adrbranch= NULL;
- }
- oc->branchcount= 0;
-
- if(oc->adrnode) {
- int a= 0;
- while(oc->adrnode[a]) {
- MEM_freeN(oc->adrnode[a]);
- oc->adrnode[a]= NULL;
- a++;
- }
- MEM_freeN(oc->adrnode);
- oc->adrnode= NULL;
- }
- oc->nodecount= 0;
-
- MEM_freeN(oc);
-}
-
-
-RayObject *RE_rayobject_octree_create(int ocres, int size)
-{
- Octree *oc= MEM_callocN(sizeof(Octree), "Octree");
- assert( RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */
-
- oc->rayobj.api = &octree_api;
-
- oc->ocres = ocres;
-
- oc->ro_nodes = (RayFace**)MEM_callocN(sizeof(RayFace*)*size, "octree rayobject nodes");
- oc->ro_nodes_size = size;
- oc->ro_nodes_used = 0;
-
-
- return RE_rayobject_unalignRayAPI((RayObject*) oc);
-}
-
-
-static void RE_rayobject_octree_add(RayObject *tree, RayObject *node)
-{
- Octree *oc = (Octree*)tree;
-
- assert( RE_rayobject_isRayFace(node) );
- assert( oc->ro_nodes_used < oc->ro_nodes_size );
- oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RE_rayobject_align(node);
-}
-
-static void octree_fill_rayface(Octree *oc, RayFace *face)
-{
- float ocfac[3], rtf[4][3];
- float co1[3], co2[3], co3[3], co4[3];
- short rts[4][3];
- short ocmin[3], ocmax[3];
- char *ocface= oc->ocface; // front, top, size view of face, to fill in
- int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2;
-
- ocfac[0]= oc->ocfacx;
- ocfac[1]= oc->ocfacy;
- ocfac[2]= oc->ocfacz;
-
- ocres2= oc->ocres*oc->ocres;
-
- VECCOPY(co1, face->v1);
- VECCOPY(co2, face->v2);
- VECCOPY(co3, face->v3);
- if(face->v4)
- VECCOPY(co4, face->v4);
-
- for(c=0;c<3;c++) {
- rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ;
- rts[0][c]= (short)rtf[0][c];
- rtf[1][c]= (co2[c]-oc->min[c])*ocfac[c] ;
- rts[1][c]= (short)rtf[1][c];
- rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ;
- rts[2][c]= (short)rtf[2][c];
- if(RE_rayface_isQuad(face)) {
- rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ;
- rts[3][c]= (short)rtf[3][c];
- }
- }
-
- for(c=0;c<3;c++) {
- oc1= rts[0][c];
- oc2= rts[1][c];
- oc3= rts[2][c];
- if(!RE_rayface_isQuad(face)) {
- ocmin[c]= MIN3(oc1,oc2,oc3);
- ocmax[c]= MAX3(oc1,oc2,oc3);
- }
- else {
- oc4= rts[3][c];
- ocmin[c]= MIN4(oc1,oc2,oc3,oc4);
- ocmax[c]= MAX4(oc1,oc2,oc3,oc4);
- }
- if(ocmax[c]>oc->ocres-1) ocmax[c]=oc->ocres-1;
- if(ocmin[c]<0) ocmin[c]=0;
- }
-
- if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) {
- ocwrite(oc, face, RE_rayface_isQuad(face), ocmin[0], ocmin[1], ocmin[2], rtf);
- }
- else {
-
- d2dda(oc, 0,1,0,1,ocface+ocres2,rts,rtf);
- d2dda(oc, 0,1,0,2,ocface,rts,rtf);
- d2dda(oc, 0,1,1,2,ocface+2*ocres2,rts,rtf);
- d2dda(oc, 1,2,0,1,ocface+ocres2,rts,rtf);
- d2dda(oc, 1,2,0,2,ocface,rts,rtf);
- d2dda(oc, 1,2,1,2,ocface+2*ocres2,rts,rtf);
- if(!RE_rayface_isQuad(face)) {
- d2dda(oc, 2,0,0,1,ocface+ocres2,rts,rtf);
- d2dda(oc, 2,0,0,2,ocface,rts,rtf);
- d2dda(oc, 2,0,1,2,ocface+2*ocres2,rts,rtf);
- }
- else {
- d2dda(oc, 2,3,0,1,ocface+ocres2,rts,rtf);
- d2dda(oc, 2,3,0,2,ocface,rts,rtf);
- d2dda(oc, 2,3,1,2,ocface+2*ocres2,rts,rtf);
- d2dda(oc, 3,0,0,1,ocface+ocres2,rts,rtf);
- d2dda(oc, 3,0,0,2,ocface,rts,rtf);
- d2dda(oc, 3,0,1,2,ocface+2*ocres2,rts,rtf);
- }
- /* nothing todo with triangle..., just fills :) */
- filltriangle(oc, 0,1,ocface+ocres2,ocmin,ocmax);
- filltriangle(oc, 0,2,ocface,ocmin,ocmax);
- filltriangle(oc, 1,2,ocface+2*ocres2,ocmin,ocmax);
-
- /* init static vars here */
- face_in_node(face, 0,0,0, rtf);
-
- for(x=ocmin[0];x<=ocmax[0];x++) {
- a= oc->ocres*x;
- for(y=ocmin[1];y<=ocmax[1];y++) {
- if(ocface[a+y+ocres2]) {
- b= oc->ocres*y+2*ocres2;
- for(z=ocmin[2];z<=ocmax[2];z++) {
- if(ocface[b+z] && ocface[a+z]) {
- if(face_in_node(NULL, x, y, z, rtf))
- ocwrite(oc, face, RE_rayface_isQuad(face), x,y,z, rtf);
- }
- }
- }
- }
- }
-
- /* same loops to clear octree, doubt it can be done smarter */
- for(x=ocmin[0];x<=ocmax[0];x++) {
- a= oc->ocres*x;
- for(y=ocmin[1];y<=ocmax[1];y++) {
- /* x-y */
- ocface[a+y+ocres2]= 0;
-
- b= oc->ocres*y + 2*ocres2;
- for(z=ocmin[2];z<=ocmax[2];z++) {
- /* y-z */
- ocface[b+z]= 0;
- /* x-z */
- ocface[a+z]= 0;
- }
- }
- }
- }
-}
-
-static void RE_rayobject_octree_done(RayObject *tree)
-{
- Octree *oc = (Octree*)tree;
- int c;
- float t00, t01, t02;
- int ocres2 = oc->ocres*oc->ocres;
-
- INIT_MINMAX(oc->min, oc->max);
-
- /* Calculate Bounding Box */
- for(c=0; c<oc->ro_nodes_used; c++)
- RE_rayobject_merge_bb( RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max);
-
- /* Alloc memory */
- oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches");
- oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes");
-
- oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree");
-
- /* the lookup table, per face, for which nodes to fill in */
- oc->ocface= MEM_callocN( 3*ocres2 + 8, "ocface");
- memset(oc->ocface, 0, 3*ocres2);
-
- for(c=0;c<3;c++) { /* octree enlarge, still needed? */
- oc->min[c]-= 0.01f;
- oc->max[c]+= 0.01f;
- }
-
- t00= oc->max[0]-oc->min[0];
- t01= oc->max[1]-oc->min[1];
- t02= oc->max[2]-oc->min[2];
-
- /* this minus 0.1 is old safety... seems to be needed? */
- oc->ocfacx= (oc->ocres-0.1)/t00;
- oc->ocfacy= (oc->ocres-0.1)/t01;
- oc->ocfacz= (oc->ocres-0.1)/t02;
-
- oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */
-
- for(c=0; c<oc->ro_nodes_used; c++)
- {
- octree_fill_rayface(oc, oc->ro_nodes[c]);
- }
-
- MEM_freeN(oc->ocface);
- oc->ocface = NULL;
- MEM_freeN(oc->ro_nodes);
- oc->ro_nodes = NULL;
-
- printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx );
- printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy );
- printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz );
-}
-
-static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max)
-{
- Octree *oc = (Octree*)tree;
- DO_MINMAX(oc->min, min, max);
- DO_MINMAX(oc->max, min, max);
-}
-
-/* check all faces in this node */
-static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval)
-{
- short nr=0;
-
- /* return on any first hit */
- if(is->mode==RE_RAY_SHADOW) {
-
- for(; no; no = no->next)
- for(nr=0; nr<8; nr++)
- {
- RayFace *face = no->v[nr];
- OcVal *ov = no->ov+nr;
-
- if(!face) break;
-
- if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) )
- {
- if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) )
- return 1;
- }
- }
- }
- else
- { /* else mirror or glass or shadowtra, return closest face */
- int found= 0;
-
- for(; no; no = no->next)
- for(nr=0; nr<8; nr++)
- {
- RayFace *face = no->v[nr];
- OcVal *ov = no->ov+nr;
-
- if(!face) break;
-
- if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) )
- {
- if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) )
- found= 1;
- }
- }
-
- return found;
- }
-
- return 0;
-}
-
-/* find the Node for the octree coord x y z */
-static Node *ocread(Octree *oc, int x, int y, int z)
-{
- Branch *br;
- int oc1;
-
- x<<=2;
- y<<=1;
-
- br= oc->adrbranch[0];
-
- if(oc->ocres==512) {
- oc1= ((x & 1024)+(y & 512)+(z & 256))>>8;
- br= br->b[oc1];
- if(br==NULL) {
- return NULL;
- }
- }
- if(oc->ocres>=256) {
- oc1= ((x & 512)+(y & 256)+(z & 128))>>7;
- br= br->b[oc1];
- if(br==NULL) {
- return NULL;
- }
- }
- if(oc->ocres>=128) {
- oc1= ((x & 256)+(y & 128)+(z & 64))>>6;
- br= br->b[oc1];
- if(br==NULL) {
- return NULL;
- }
- }
-
- oc1= ((x & 128)+(y & 64)+(z & 32))>>5;
- br= br->b[oc1];
- if(br) {
- oc1= ((x & 64)+(y & 32)+(z & 16))>>4;
- br= br->b[oc1];
- if(br) {
- oc1= ((x & 32)+(y & 16)+(z & 8))>>3;
- br= br->b[oc1];
- if(br) {
- oc1= ((x & 16)+(y & 8)+(z & 4))>>2;
- br= br->b[oc1];
- if(br) {
- oc1= ((x & 8)+(y & 4)+(z & 2))>>1;
- br= br->b[oc1];
- if(br) {
- oc1= ((x & 4)+(y & 2)+(z & 1));
- return (Node *)br->b[oc1];
- }
- }
- }
- }
- }
-
- return NULL;
-}
-
-static int cliptest(float p, float q, float *u1, float *u2)
-{
- float r;
-
- if(p<0.0f) {
- if(q<p) return 0;
- else if(q<0.0f) {
- r= q/p;
- if(r>*u2) return 0;
- else if(r>*u1) *u1=r;
- }
- }
- else {
- if(p>0.0f) {
- if(q<0.0f) return 0;
- else if(q<p) {
- r= q/p;
- if(r<*u1) return 0;
- else if(r<*u2) *u2=r;
- }
- }
- else if(q<0.0f) return 0;
- }
- return 1;
-}
-
-/* extensive coherence checks/storage cancels out the benefit of it, and gives errors... we
- need better methods, sample code commented out below (ton) */
-
-/*
-
-in top: static int coh_nodes[16*16*16][6];
-in makeoctree: memset(coh_nodes, 0, sizeof(coh_nodes));
-
-static void add_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2)
-{
- short *sp;
-
- sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ];
- sp[0]= ocx1; sp[1]= ocy1; sp[2]= ocz1;
- sp[3]= ocx2; sp[4]= ocy2; sp[5]= ocz2;
-
-}
-
-static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2)
-{
- short *sp;
-
- sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ];
- if(sp[0]==ocx1 && sp[1]==ocy1 && sp[2]==ocz1 &&
- sp[3]==ocx2 && sp[4]==ocy2 && sp[5]==ocz2) return 1;
- return 0;
-}
-
-*/
-
-/* return 1: found valid intersection */
-/* starts with is->orig.face */
-static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
-{
- Octree *oc= (Octree*)tree;
- Node *no;
- OcVal ocval;
- float vec1[3], vec2[3], start[3], end[3];
- float u1,u2,ox1,ox2,oy1,oy2,oz1,oz2;
- float labdao,labdax,ldx,labday,ldy,labdaz,ldz, ddalabda;
- float olabda = 0;
- int dx,dy,dz;
- int xo,yo,zo,c1=0;
- int ocx1,ocx2,ocy1, ocy2,ocz1,ocz2;
-
- /* clip with octree */
- if(oc->branchcount==0) return 0;
-
- /* do this before intersect calls */
-#if 0
- is->facecontr= NULL; /* to check shared edge */
- is->obcontr= 0;
- is->faceisect= is->isect= 0; /* shared edge, quad half flag */
- is->userdata= oc->userdata;
-#endif
-
- VECCOPY( start, is->start );
- VECADDFAC( end, is->start, is->vec, is->labda );
- ldx= is->vec[0]*is->labda;
- olabda = is->labda;
- u1= 0.0f;
- u2= 1.0f;
-
- /* clip with octree cube */
- if(cliptest(-ldx, start[0]-oc->min[0], &u1,&u2)) {
- if(cliptest(ldx, oc->max[0]-start[0], &u1,&u2)) {
- ldy= is->vec[1]*is->labda;
- if(cliptest(-ldy, start[1]-oc->min[1], &u1,&u2)) {
- if(cliptest(ldy, oc->max[1]-start[1], &u1,&u2)) {
- ldz = is->vec[2]*is->labda;
- if(cliptest(-ldz, start[2]-oc->min[2], &u1,&u2)) {
- if(cliptest(ldz, oc->max[2]-start[2], &u1,&u2)) {
- c1=1;
- if(u2<1.0f) {
- end[0] = start[0]+u2*ldx;
- end[1] = start[1]+u2*ldy;
- end[2] = start[2]+u2*ldz;
- }
-
- if(u1>0.0f) {
- start[0] += u1*ldx;
- start[1] += u1*ldy;
- start[2] += u1*ldz;
- }
- }
- }
- }
- }
- }
- }
-
- if(c1==0) return 0;
-
- /* reset static variables in ocread */
- //ocread(oc, oc->ocres, 0, 0);
-
- /* setup 3dda to traverse octree */
- ox1= (start[0]-oc->min[0])*oc->ocfacx;
- oy1= (start[1]-oc->min[1])*oc->ocfacy;
- oz1= (start[2]-oc->min[2])*oc->ocfacz;
- ox2= (end[0]-oc->min[0])*oc->ocfacx;
- oy2= (end[1]-oc->min[1])*oc->ocfacy;
- oz2= (end[2]-oc->min[2])*oc->ocfacz;
-
- ocx1= (int)ox1;
- ocy1= (int)oy1;
- ocz1= (int)oz1;
- ocx2= (int)ox2;
- ocy2= (int)oy2;
- ocz2= (int)oz2;
-
- if(ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) {
- no= ocread(oc, ocx1, ocy1, ocz1);
- if(no) {
- /* exact intersection with node */
- vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1;
- vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2;
- calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2);
- if( testnode(oc, is, no, ocval) ) return 1;
- }
- }
- else {
- int found = 0;
- //static int coh_ocx1,coh_ocx2,coh_ocy1, coh_ocy2,coh_ocz1,coh_ocz2;
- float dox, doy, doz;
- int eqval;
-
- /* calc labda en ld */
- dox= ox1-ox2;
- doy= oy1-oy2;
- doz= oz1-oz2;
-
- if(dox<-FLT_EPSILON) {
- ldx= -1.0f/dox;
- labdax= (ocx1-ox1+1.0f)*ldx;
- dx= 1;
- } else if(dox>FLT_EPSILON) {
- ldx= 1.0f/dox;
- labdax= (ox1-ocx1)*ldx;
- dx= -1;
- } else {
- labdax=1.0f;
- ldx=0;
- dx= 0;
- }
-
- if(doy<-FLT_EPSILON) {
- ldy= -1.0f/doy;
- labday= (ocy1-oy1+1.0f)*ldy;
- dy= 1;
- } else if(doy>FLT_EPSILON) {
- ldy= 1.0f/doy;
- labday= (oy1-ocy1)*ldy;
- dy= -1;
- } else {
- labday=1.0f;
- ldy=0;
- dy= 0;
- }
-
- if(doz<-FLT_EPSILON) {
- ldz= -1.0f/doz;
- labdaz= (ocz1-oz1+1.0f)*ldz;
- dz= 1;
- } else if(doz>FLT_EPSILON) {
- ldz= 1.0f/doz;
- labdaz= (oz1-ocz1)*ldz;
- dz= -1;
- } else {
- labdaz=1.0f;
- ldz=0;
- dz= 0;
- }
-
- xo=ocx1; yo=ocy1; zo=ocz1;
- labdao= ddalabda= MIN3(labdax,labday,labdaz);
-
- vec2[0]= ox1;
- vec2[1]= oy1;
- vec2[2]= oz1;
-
- /* this loop has been constructed to make sure the first and last node of ray
- are always included, even when ddalabda==1.0f or larger */
-
- while(TRUE) {
-
- no= ocread(oc, xo, yo, zo);
- if(no) {
-
- /* calculate ray intersection with octree node */
- VECCOPY(vec1, vec2);
- // dox,y,z is negative
- vec2[0]= ox1-ddalabda*dox;
- vec2[1]= oy1-ddalabda*doy;
- vec2[2]= oz1-ddalabda*doz;
- calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2);
-
- //is->labda = (u1+ddalabda*(u2-u1))*olabda;
- if( testnode(oc, is, no, ocval) )
- found = 1;
-
- if(is->labda < (u1+ddalabda*(u2-u1))*olabda)
- return found;
- }
-
-
- labdao= ddalabda;
-
- /* traversing ocree nodes need careful detection of smallest values, with proper
- exceptions for equal labdas */
- eqval= (labdax==labday);
- if(labday==labdaz) eqval += 2;
- if(labdax==labdaz) eqval += 4;
-
- if(eqval) { // only 4 cases exist!
- if(eqval==7) { // x=y=z
- xo+=dx; labdax+=ldx;
- yo+=dy; labday+=ldy;
- zo+=dz; labdaz+=ldz;
- }
- else if(eqval==1) { // x=y
- if(labday < labdaz) {
- xo+=dx; labdax+=ldx;
- yo+=dy; labday+=ldy;
- }
- else {
- zo+=dz; labdaz+=ldz;
- }
- }
- else if(eqval==2) { // y=z
- if(labdax < labday) {
- xo+=dx; labdax+=ldx;
- }
- else {
- yo+=dy; labday+=ldy;
- zo+=dz; labdaz+=ldz;
- }
- }
- else { // x=z
- if(labday < labdax) {
- yo+=dy; labday+=ldy;
- }
- else {
- xo+=dx; labdax+=ldx;
- zo+=dz; labdaz+=ldz;
- }
- }
- }
- else { // all three different, just three cases exist
- eqval= (labdax<labday);
- if(labday<labdaz) eqval += 2;
- if(labdax<labdaz) eqval += 4;
-
- if(eqval==7 || eqval==5) { // x smallest
- xo+=dx; labdax+=ldx;
- }
- else if(eqval==2 || eqval==6) { // y smallest
- yo+=dy; labday+=ldy;
- }
- else { // z smallest
- zo+=dz; labdaz+=ldz;
- }
-
- }
-
- ddalabda=MIN3(labdax,labday,labdaz);
- if(ddalabda==labdao) break;
- /* to make sure the last node is always checked */
- if(labdao>=1.0f) break;
- }
- }
-
- /* reached end, no intersections found */
- return 0;
-}
-
-
-
diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/source/rayobject_raycounter.c
deleted file mode 100644
index a82a21348c1..00000000000
--- a/source/blender/render/intern/source/rayobject_raycounter.c
+++ /dev/null
@@ -1,87 +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.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): André Pinto.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#include "rayobject.h"
-#include "raycounter.h"
-
-#ifdef RE_RAYCOUNTER
-
-void RE_RC_INFO(RayCounter *info)
-{
- printf("----------- Raycast counter --------\n");
- printf("Rays total: %llu\n", info->raycast.test );
- printf("Rays hit: %llu\n", info->raycast.hit );
- printf("\n");
- printf("BB tests: %llu\n", info->bb.test );
- printf("BB hits: %llu\n", info->bb.hit );
- printf("\n");
- printf("SIMD BB tests: %llu\n", info->simd_bb.test );
- printf("SIMD BB hits: %llu\n", info->simd_bb.hit );
- printf("\n");
- printf("Primitives tests: %llu\n", info->faces.test );
- printf("Primitives hits: %llu\n", info->faces.hit );
- printf("------------------------------------\n");
- printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) );
- printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) );
- printf("\n");
- printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) );
- printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) );
- printf("\n");
- printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) );
- printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) );
- printf("\n");
- printf("SIMD tests per ray: %f\n", info->simd_bb.test / ((float)info->raycast.test) );
- printf("SIMD hits per ray: %f\n", info->simd_bb.hit / ((float)info->raycast.test) );
- printf("\n");
- printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) );
- printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) );
- printf("------------------------------------\n");
-}
-
-void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp)
-{
- dest->faces.test += tmp->faces.test;
- dest->faces.hit += tmp->faces.hit;
-
- dest->bb.test += tmp->bb.test;
- dest->bb.hit += tmp->bb.hit;
-
- dest->simd_bb.test += tmp->simd_bb.test;
- dest->simd_bb.hit += tmp->simd_bb.hit;
-
- dest->raycast.test += tmp->raycast.test;
- dest->raycast.hit += tmp->raycast.hit;
-
- dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test;
- dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit;
-
- dest->raytrace_hint.test += tmp->raytrace_hint.test;
- dest->raytrace_hint.hit += tmp->raytrace_hint.hit;
-}
-
-#endif
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 5e523199755..89043a68684 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -379,25 +379,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 61080c7d807..28b45183771 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -946,7 +946,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
@@ -978,7 +978,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/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 2e456669cb1..bdafedfb65e 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -55,6 +55,7 @@
#include "BKE_packedFile.h"
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
#include "RE_pipeline.h" /* RE_ free stuff */
@@ -279,8 +280,11 @@ void WM_exit(bContext *C)
SYS_DeleteSystem(SYS_GetSystem());
- if(MEM_get_memory_blocks_in_use()!=0) {
- printf("Error Totblock: %d\n", MEM_get_memory_blocks_in_use());
+ if(MEM_get_memory_blocks_in_use()!=0 || BLI_cellalloc_get_totblock()!=0) {
+ printf("Error Totblock: %d\n",
+ BLI_cellalloc_get_totblock()+MEM_get_memory_blocks_in_use());
+ BLI_cellalloc_printleaks();
+ BLI_cellalloc_destroy();
MEM_printmemlist();
}
// delete_autosave();
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index bef41983bab..1a91e4cf8f3 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -47,6 +47,7 @@ INCLUDE_DIRECTORIES(../../intern/guardedalloc
../kernel/gen_messaging
../kernel/gen_system
../../extern/glew/include
+ ../blender/bmesh
)
@@ -105,8 +106,17 @@ ADD_EXECUTABLE(blender ${EXETYPE} ${EXESRC})
SET(TARGETDIR ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR})
-IF(WITH_INSTALL)
+<<<<<<< .working
+IF(UNIX)
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ #COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/plugins ${TARGETDIR}/
+ #COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/text/* ${TARGETDIR}/
+ )
+ENDIF(UNIX)
+=======
IF(UNIX)
ADD_CUSTOM_COMMAND(TARGET blender
POST_BUILD
@@ -115,7 +125,24 @@ IF(WITH_INSTALL)
#COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/text/* ${TARGETDIR}/
)
ENDIF(UNIX)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+IF(UNIX AND NOT APPLE)
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND rm -Rf ${TARGETDIR}/.blender
+ COMMAND mkdir ${TARGETDIR}/.blender/
+ COMMAND cp ${CMAKE_SOURCE_DIR}/bin/.blender/.bfont.ttf ${TARGETDIR}/.blender/
+ COMMAND cp ${CMAKE_SOURCE_DIR}/bin/.blender/.Blanguages ${TARGETDIR}/.blender/
+ COMMAND cp -R ${CMAKE_SOURCE_DIR}/bin/.blender/locale ${TARGETDIR}/.blender/
+ COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/scripts ${TARGETDIR}/.blender/
+ COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/ui ${TARGETDIR}/.blender/
+ COMMAND find ${TARGETDIR} -name CVS -prune -exec rm -rf {} "\;"
+ )
+ENDIF(UNIX AND NOT APPLE)
+=======
IF(UNIX AND NOT APPLE)
# Local installation, "make install" can be done after this optionally
@@ -161,7 +188,14 @@ IF(WITH_INSTALL)
COMMAND rm -rf ${TARGETDIR}/.blender/python/lib/python${PYTHON_VERSION}/site-packages
COMMAND mkdir ${TARGETDIR}/.blender/python/lib/python${PYTHON_VERSION}/site-packages # python needs it.
-
+>>>>>>> .merge-right.r23146
+
+<<<<<<< .working
+IF(APPLE)
+ SET(SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app)
+ SET(SOURCEINFO ${SOURCEDIR}/Contents/Info.plist)
+ SET(TARGETINFO ${TARGETDIR}/blender.app/Contents/Info.plist)
+=======
COMMAND rm -f ${TARGETDIR}/.blender/python/lib/python${PYTHON_VERSION}/lib-dynload/_tkinter.so
COMMAND find ${TARGETDIR}/.blender/python/lib/python${PYTHON_VERSION} -name "test" -prune -exec rm -rf {} "\;"
COMMAND find ${TARGETDIR}/.blender/python/lib/python${PYTHON_VERSION} -name "*.py?" -exec rm -rf {} "\;"
@@ -197,12 +231,78 @@ IF(WITH_INSTALL)
# end "make install"
ENDIF(UNIX AND NOT APPLE)
-
+>>>>>>> .merge-right.r23146
+
+<<<<<<< .working
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND cp -R ${SOURCEINFO} ${TARGETDIR}/blender.app/Contents/
+ COMMAND cp -R ${SOURCEDIR}/Contents/PkgInfo ${TARGETDIR}/blender.app/Contents/
+ COMMAND cp -R ${SOURCEDIR}/Contents/Resources ${TARGETDIR}/blender.app/Contents/
+ COMMAND cat ${SOURCEINFO} | sed s/VERSION/`cat ${CMAKE_SOURCE_DIR}/release/VERSION`/ | sed s/DATE/`date +'%Y-%b-%d'`/ > ${TARGETINFO}
+ COMMAND rm -Rf ${TARGETDIR}/blender.app/Contents/MacOS/.blender
+ COMMAND mkdir ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp ${CMAKE_SOURCE_DIR}/bin/.blender/.bfont.ttf ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp ${CMAKE_SOURCE_DIR}/bin/.blender/.Blanguages ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp -R ${CMAKE_SOURCE_DIR}/bin/.blender/locale ${TARGETDIR}/blender.app/Contents/Resources/
+ COMMAND cp -R ${CMAKE_SOURCE_DIR}/bin/.blender/locale ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp ${CMAKE_SOURCE_DIR}/bin/.blender/.Blanguages ${TARGETDIR}/blender.app/Contents/Resources/
+ COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/scripts ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/ui ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/io ${TARGETDIR}/blender.app/Contents/MacOS/.blender/
+ COMMAND mkdir ${TARGETDIR}/blender.app/Contents/MacOS/.blender/python/
+ COMMAND unzip -q ${LIBDIR}/release/python.zip -d ${TARGETDIR}/blender.app/Contents/MacOS/.blender/python/
+ COMMAND find ${TARGETDIR}/blender.app -name CVS -prune -exec rm -rf {} "\;"
+ COMMAND find ${TARGETDIR}/blender.app -name CVS.sandboxinfo -prune -exec rm -rf {} "\;"
+ COMMAND find ${TARGETDIR}/blender.app -name .DS_Store -prune -exec rm -rf {} "\;"
+ COMMAND find ${TARGETDIR}/blender.app -name .svn -prune -exec rm -rf {} "\;"
+ )
+ENDIF(APPLE)
+=======
IF(APPLE)
SET(SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app)
SET(SOURCEINFO ${SOURCEDIR}/Contents/Info.plist)
SET(TARGETINFO ${TARGETDIR}/blender.app/Contents/Info.plist)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+IF(WIN32)
+ FILE(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} WIN_SOURCE_DIR)
+
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND if not exist \"${TARGETDIR}\\.blender\" mkdir \"${TARGETDIR}\\.blender\"
+ COMMAND if not exist \"${TARGETDIR}\\.blender\\locale\" mkdir \"${TARGETDIR}\\.blender\\locale\"
+ COMMAND if not exist \"${TARGETDIR}\\.blender\\scripts\" mkdir \"${TARGETDIR}\\.blender\\scripts\"
+ COMMAND if not exist \"${TARGETDIR}\\.blender\\ui\" mkdir \"${TARGETDIR}\\.blender\\ui\"
+ COMMAND if not exist \"${TARGETDIR}\\plugins\" mkdir \"${TARGETDIR}\\plugins\"
+ COMMAND copy /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\.Blanguages\" \"${TARGETDIR}\\.blender\\\"
+ COMMAND copy /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\.bfont.ttf\" \"${TARGETDIR}\\.blender\\\"
+ COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\locale\\*.*\" \"${TARGETDIR}\\.blender\\locale\"
+ COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\scripts\\*.*\" \"${TARGETDIR}\\.blender\\scripts\"
+ COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\ui\\*.*\" \"${TARGETDIR}\\.blender\\ui\"
+ COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\plugins\\*.*\" \"${TARGETDIR}\\plugins\"
+ COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\text\\*.*\" \"${TARGETDIR}\"
+ COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python26.zip\" \"${TARGETDIR}\\\"
+ )
+
+ FILE(TO_NATIVE_PATH "${LIBDIR}" WIN_LIBDIR)
+
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND copy /Y \"${WIN_LIBDIR}\\gettext\\lib\\gnu_gettext.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\png\\lib\\libpng.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\sdl\\lib\\SDL.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\zlib\\lib\\zlib.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\tiff\\lib\\libtiff.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26_d.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\pthreads\\lib\\pthreadVC2.dll\" \"${TARGETDIR}\\\"
+ )
+=======
ADD_CUSTOM_COMMAND(
TARGET blender POST_BUILD MAIN_DEPENDENCY blender
COMMAND cp -Rf ${SOURCEINFO} ${TARGETDIR}/blender.app/Contents/
@@ -240,10 +340,22 @@ IF(WITH_INSTALL)
COMMAND find ${TARGETDIR}/blender.app -name .svn -prune -exec rm -rf {} "\;"
)
ENDIF(APPLE)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+ IF(WITH_INTERNATIONAL)
+=======
IF(WIN32)
FILE(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} WIN_SOURCE_DIR)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND copy /Y \"${WIN_LIBDIR}\\iconv\\lib\\iconv.dll\" \"${TARGETDIR}\\\"
+ )
+=======
ADD_CUSTOM_COMMAND(TARGET blender
POST_BUILD
MAIN_DEPENDENCY blender
@@ -260,9 +372,32 @@ IF(WITH_INSTALL)
# TODO, copy python bundle
# COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python31.zip\" \"${TARGETDIR}\\\"
)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+ ENDIF(WITH_INTERNATIONAL)
+
+ IF(WITH_FFMPEG)
+=======
FILE(TO_NATIVE_PATH "${LIBDIR}" WIN_LIBDIR)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+ ADD_CUSTOM_COMMAND(TARGET blender
+ POST_BUILD
+ MAIN_DEPENDENCY blender
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avcodec-52.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avformat-52.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avdevice-52.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\avutil-50.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libfaac-0.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libfaad-2.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libmp3lame-0.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\libx264-67.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\swscale-0.dll\" \"${TARGETDIR}\\\"
+ COMMAND copy /Y \"${WIN_LIBDIR}\\ffmpeg\\lib\\xvidcore.dll\" \"${TARGETDIR}\\\"
+ )
+=======
ADD_CUSTOM_COMMAND(TARGET blender
POST_BUILD
MAIN_DEPENDENCY blender
@@ -277,7 +412,12 @@ IF(WITH_INSTALL)
COMMAND copy /Y \"${WIN_LIBDIR}\\pthreads\\lib\\pthreadVC2.dll\" \"${TARGETDIR}\\\"
COMMAND copy /Y \"${WIN_LIBDIR}\\samplerate\\lib\\libsamplerate-0.dll\" \"${TARGETDIR}\\\"
)
+>>>>>>> .merge-right.r23146
+ ENDIF(WITH_FFMPEG)
+ENDIF(WIN32)
+<<<<<<< .working
+=======
IF(WITH_INTERNATIONAL)
ADD_CUSTOM_COMMAND(TARGET blender
POST_BUILD
@@ -333,6 +473,7 @@ IF(WITH_INSTALL)
ENDIF(WIN32)
ENDIF(WITH_INSTALL)
+>>>>>>> .merge-right.r23146
ADD_DEPENDENCIES(blender makesdna)
FILE(READ ${CMAKE_BINARY_DIR}/cmake_blender_libs.txt BLENDER_LINK_LIBS)
@@ -348,6 +489,77 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
IF(UNIX)
+<<<<<<< .working
+ # Sort libraries
+ SET(BLENDER_SORTED_LIBS
+ bf_windowmanager
+ bf_editors
+ bf_decimation
+ blender_BSP
+ bf_ghost
+ bf_string
+ blender_render
+ blender_ONL
+ bf_python
+ bf_gen_python
+ bf_blenkernel
+ bf_nodes
+ bf_bmesh
+ bf_gpu
+ bf_blenloader
+ bf_blenpluginapi
+ bf_imbuf
+ bf_blenlib
+ bf_avi
+ bf_cineon
+ bf_openexr
+ bf_dds
+ bf_readblenfile
+ blender_bop
+ bf_kernel
+ bf_decimation
+ bf_elbeem
+ bf_IK
+ bf_memutil
+ bf_guardedalloc
+ blender_CTR
+ bf_moto
+ bf_windowmanager
+ bf_editors
+ bf_blroutines
+ bf_converter
+ bf_dummy
+ bf_bullet
+ bf_smoke
+ bf_common
+ bf_ketsji
+ bf_logic
+ bf_rasterizer
+ bf_oglrasterizer
+ bf_expressions
+ bf_scenegraph
+ bf_moto
+ bf_blroutines
+ kx_network
+ bf_kernel
+ bf_ngnetwork
+ extern_bullet
+ bf_loopbacknetwork
+ bf_common
+ bf_moto
+ bf_python
+ bf_gen_python
+ bf_quicktime
+ extern_binreloc
+ extern_glew
+ extern_libopenjpeg
+ bf_videotex
+ bf_rna
+ bf_dna
+ bf_blenfont
+ bf_soundsystem
+ )
+=======
# Sort libraries
SET(BLENDER_SORTED_LIBS
bf_windowmanager
@@ -419,7 +631,10 @@ IF(UNIX)
bf_blenfont
bf_audaspace
)
+>>>>>>> .merge-right.r23146
+<<<<<<< .working
+=======
IF(WITH_CXX_GUARDEDALLOC)
SET(BLENDER_SORTED_LIBS ${BLENDER_SORTED_LIBS} bf_guardedalloc_cpp)
ENDIF(WITH_CXX_GUARDEDALLOC)
@@ -429,6 +644,7 @@ IF(UNIX)
ENDIF(WITH_QUICKTIME)
+>>>>>>> .merge-right.r23146
FOREACH(SORTLIB ${BLENDER_SORTED_LIBS})
SET(REMLIB ${SORTLIB})
FOREACH(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 6f90c2ffe84..5d92b8cadc0 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -28,7 +28,7 @@
*/
#include <stdlib.h>
#include <string.h>
-
+#include <signal.h>
/* for setuid / getuid */
#ifdef __sgi
@@ -274,12 +274,30 @@ double PIL_check_seconds_timer(void);
}
}*/
+int segmentation_handler(int sig)
+{
+ char fname[256];
+
+ if (!G.sce[0]) {
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ BLI_make_file_string("/", fname, btempdir, "quit.blend");
+ } else
+ sprintf(fname, "%s.crash.blend", G.sce);
+
+ BKE_undo_save(fname);
+
+ /*induce a real crash*/
+ signal(SIGSEGV, SIG_DFL);
+ *(int*)NULL = 0;
+}
+
int main(int argc, char **argv)
{
SYS_SystemHandle syshandle;
bContext *C= CTX_create();
int a, i, stax, stay, sizx, sizy /*XXX, scr_init = 0*/;
-
+ int no_handler = 0;
#ifdef WITH_BINRELOC
br_init( NULL );
#endif
@@ -344,6 +362,9 @@ int main(int argc, char **argv)
G.f |= G_DOSCRIPTLINKS; /* script links enabled by default */
for(a=1; a<argc; a++) {
+ if (!strcmp(argv[a], "--no_crash_handler")) {
+ no_handler = 1;
+ }
/* Handle unix and windows style help requests */
if ((!strcmp(argv[a], "--help")) || (!strcmp(argv[a], "/?"))){
@@ -412,6 +433,11 @@ int main(int argc, char **argv)
}
}
+ if (!no_handler) {
+ signal(SIGSEGV, segmentation_handler);
+ signal(SIGFPE, segmentation_handler);
+ }
+
#ifdef __sgi
setuid(getuid()); /* end superuser */
#endif
@@ -525,12 +551,12 @@ int main(int argc, char **argv)
BPY_post_start_python();
if(!G.background)
- BPY_run_ui_scripts(C, 0); /* dont need to reload the first time */
+ BPY_run_ui_scripts(C, 0); /* dont need to reload the first time */
#endif
CTX_py_init_set(C, 1);
if(!G.background)
- WM_keymap_init(C); /* after BPY_run_ui_scripts() */
+ WM_keymap_init(C); /* after BPY_run_ui_scripts() */
#ifdef WITH_QUICKTIME
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.cpp b/source/gameengine/Converter/BL_ArmatureActuator.cpp
index a018f0f938d..4105eb57d5f 100644
--- a/source/gameengine/Converter/BL_ArmatureActuator.cpp
+++ b/source/gameengine/Converter/BL_ArmatureActuator.cpp
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureActuator.cpp 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Converter/BL_ArmatureActuator.h b/source/gameengine/Converter/BL_ArmatureActuator.h
index e7e12bc2e4e..29b07b16d52 100644
--- a/source/gameengine/Converter/BL_ArmatureActuator.h
+++ b/source/gameengine/Converter/BL_ArmatureActuator.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureActuator.h 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp
index 9a9161b080f..817049c6977 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.cpp
+++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureChannel.cpp 23562 2009-09-29 21:42:40Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h
index 64b03835d83..249fa4c8ac7 100644
--- a/source/gameengine/Converter/BL_ArmatureChannel.h
+++ b/source/gameengine/Converter/BL_ArmatureChannel.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureChannel.h 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
index 42581b63ec4..4c470b67387 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureConstraint.cpp 23562 2009-09-29 21:42:40Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h
index 2a202dfe62e..c1510b3c56a 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.h
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.h
@@ -1,5 +1,5 @@
/**
- * $Id$
+ * $Id: BL_ArmatureConstraint.h 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index db32f18f63b..fb780a6404d 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -731,16 +731,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
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/GameLogic/SCA_BasicEventManager.cpp b/source/gameengine/GameLogic/SCA_BasicEventManager.cpp
index a2a7e535b5c..6d81784338e 100644
--- a/source/gameengine/GameLogic/SCA_BasicEventManager.cpp
+++ b/source/gameengine/GameLogic/SCA_BasicEventManager.cpp
@@ -2,7 +2,7 @@
* Manager for 'always' events. Since always sensors can operate in pulse
* mode, they need to be activated.
*
- * $Id$
+ * $Id: SCA_BasicEventManager.cpp 23490 2009-09-25 16:30:15Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/GameLogic/SCA_BasicEventManager.h b/source/gameengine/GameLogic/SCA_BasicEventManager.h
index 3bd2df08c07..6b68cfcbe16 100644
--- a/source/gameengine/GameLogic/SCA_BasicEventManager.h
+++ b/source/gameengine/GameLogic/SCA_BasicEventManager.h
@@ -1,7 +1,7 @@
/**
* Manager for sensor that only need to call Update
*
- * $Id$
+ * $Id: SCA_BasicEventManager.h 23499 2009-09-26 20:03:01Z nexyon $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
index 40e16744d71..007dc459793 100644
--- a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
+++ b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
@@ -1,7 +1,7 @@
/**
* Armature sensor
*
- * $Id$
+ * $Id: KX_ArmatureSensor.cpp 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.h b/source/gameengine/Ketsji/KX_ArmatureSensor.h
index 6dc6991873a..710fbe1b7bc 100644
--- a/source/gameengine/Ketsji/KX_ArmatureSensor.h
+++ b/source/gameengine/Ketsji/KX_ArmatureSensor.h
@@ -1,7 +1,7 @@
/**
* Property sensor
*
- * $Id$
+ * $Id: KX_ArmatureSensor.h 23562 2009-09-29 21:42:40Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index b7d0dd2f6e7..b5c50109e2a 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -1453,10 +1453,10 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
- numpolys = dm->getNumFaces(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
+ numpolys = dm->getNumTessFaces(dm);
numverts = dm->getNumVerts(dm);
- int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
@@ -1721,10 +1721,10 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
DerivedMesh* dm= gameobj->GetDeformer()->GetFinalMesh();
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
- numpolys = dm->getNumFaces(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
+ numpolys = dm->getNumTessFaces(dm);
numverts = dm->getNumVerts(dm);
- int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
MFace *mf;
MVert *mv;
@@ -1733,7 +1733,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
if(CustomData_has_layer(&dm->faceData, CD_MTFACE))
{
- MTFace *tface = (MTFace *)dm->getFaceDataArray(dm, CD_MTFACE);
+ MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
MTFace *tf;
vector<bool> vert_tag_array(numverts, false);
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/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index d16348defb2..ad53e1d22e9 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -777,7 +777,7 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
current_ms = &ms;
current_mesh = ms.m_mesh;
current_wireframe = wireframe;
- MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL);
+ MCol *mcol = (MCol*)ms.m_pDerivedMesh->getTessFaceDataArray(ms.m_pDerivedMesh, CD_MCOL);
if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
// GetMaterialIndex return the original mface material index,
// increment by 1 to match what derived mesh is doing
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 38d2747889a..92894c19884 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
@@ -158,7 +157,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
@@ -174,10 +173,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', 'win32-mingw'):
+ 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:
- syslibs.append(lenv['BF_PYTHON_LIB'])
+ 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']:
@@ -207,7 +208,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'])
@@ -590,7 +591,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()
@@ -681,7 +682,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'])
lenv.Append(LINKFLAGS = ['/FORCE:MULTIPLE'])
if lenv['BF_DEBUG']:
@@ -712,7 +713,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 b1584ae8784..2a48db4869c 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_PYTHON_DLL',
+ 'WITH_BF_PYTHON', 'BF_NO_PYDEBUG', '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_PYTHON_DLL',
'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_LIBSAMPLERATE', 'BF_LIBSAMPLERATE_INC', 'BF_LIBSAMPLERATE_LIB', 'BF_LIBSAMPLERATE_LIBPATH',
@@ -154,6 +154,7 @@ def read_opts(cfg, args):
localopts.AddVariables(
('LCGDIR', 'location of cvs lib dir'),
(BoolVariable('WITH_BF_PYTHON', 'Compile with python', True)),
+ ('BF_NO_PYDEBUG', 'don\'t use python debug lib', False),
('BF_PYTHON', 'base path for python', ''),
('BF_PYTHON_VERSION', 'Python version to use', ''),
('BF_PYTHON_INC', 'include path for Python headers', ''),