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
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/BL-license.txt48
-rw-r--r--intern/GPL-license.txt340
-rw-r--r--intern/Makefile38
-rw-r--r--intern/SoundSystem/Makefile54
-rw-r--r--intern/SoundSystem/SND_C-api.h356
-rw-r--r--intern/SoundSystem/SND_CDObject.h84
-rw-r--r--intern/SoundSystem/SND_DependKludge.h56
-rw-r--r--intern/SoundSystem/SND_DeviceManager.h91
-rw-r--r--intern/SoundSystem/SND_IAudioDevice.h346
-rw-r--r--intern/SoundSystem/SND_Object.h55
-rw-r--r--intern/SoundSystem/SND_Scene.h106
-rw-r--r--intern/SoundSystem/SND_SoundListener.h84
-rw-r--r--intern/SoundSystem/SND_SoundObject.h162
-rw-r--r--intern/SoundSystem/SND_Utils.h113
-rw-r--r--intern/SoundSystem/SND_WaveCache.h68
-rw-r--r--intern/SoundSystem/SND_WaveSlot.h94
-rw-r--r--intern/SoundSystem/SND_test/Makefile53
-rw-r--r--intern/SoundSystem/SND_test/SND_test.c152
-rw-r--r--intern/SoundSystem/SoundDefines.h119
-rw-r--r--intern/SoundSystem/dummy/Makefile46
-rw-r--r--intern/SoundSystem/dummy/SND_DummyDevice.cpp53
-rw-r--r--intern/SoundSystem/dummy/SND_DummyDevice.h95
-rw-r--r--intern/SoundSystem/fmod/Makefile47
-rw-r--r--intern/SoundSystem/fmod/SND_FmodDevice.cpp543
-rw-r--r--intern/SoundSystem/fmod/SND_FmodDevice.h105
-rw-r--r--intern/SoundSystem/intern/Makefile50
-rw-r--r--intern/SoundSystem/intern/SND_AudioDevice.cpp247
-rw-r--r--intern/SoundSystem/intern/SND_AudioDevice.h118
-rw-r--r--intern/SoundSystem/intern/SND_C-api.cpp391
-rw-r--r--intern/SoundSystem/intern/SND_CDObject.cpp182
-rw-r--r--intern/SoundSystem/intern/SND_DeviceManager.cpp137
-rw-r--r--intern/SoundSystem/intern/SND_IdObject.cpp75
-rw-r--r--intern/SoundSystem/intern/SND_IdObject.h59
-rw-r--r--intern/SoundSystem/intern/SND_Scene.cpp569
-rw-r--r--intern/SoundSystem/intern/SND_SoundListener.cpp184
-rw-r--r--intern/SoundSystem/intern/SND_SoundObject.cpp506
-rw-r--r--intern/SoundSystem/intern/SND_Utils.cpp395
-rw-r--r--intern/SoundSystem/intern/SND_WaveCache.cpp134
-rw-r--r--intern/SoundSystem/intern/SND_WaveSlot.cpp182
-rw-r--r--intern/SoundSystem/openal/Makefile47
-rw-r--r--intern/SoundSystem/openal/SND_OpenALDevice.cpp661
-rw-r--r--intern/SoundSystem/openal/SND_OpenALDevice.h102
-rw-r--r--intern/SoundSystem/openal/pthread_cancel.cpp65
-rw-r--r--intern/action/ACT_Action.h140
-rw-r--r--intern/action/ACT_ActionC-Api.h192
-rw-r--r--intern/action/ACT_ActionStack.h184
-rw-r--r--intern/action/Makefile52
-rw-r--r--intern/action/doc/Doxyfile746
-rw-r--r--intern/action/intern/ACT_Action.cpp64
-rw-r--r--intern/action/intern/ACT_ActionC-Api.cpp130
-rw-r--r--intern/action/intern/ACT_ActionStack.cpp241
-rw-r--r--intern/action/intern/ACT_CallbackAction.h124
-rw-r--r--intern/action/intern/Makefile42
-rw-r--r--intern/action/make/msvc_6_0/action.dsp128
-rw-r--r--intern/action/make/msvc_6_0/action.dsw29
-rw-r--r--intern/action/test/action_c_test/ActionTest.c83
-rw-r--r--intern/action/test/action_c_test/TestAction.c59
-rw-r--r--intern/action/test/action_c_test/TestAction.h50
-rw-r--r--intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp109
-rw-r--r--intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw44
-rw-r--r--intern/action/test/action_cpp_test/ActionTest.cpp83
-rw-r--r--intern/action/test/action_cpp_test/TestAction.h57
-rw-r--r--intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp105
-rw-r--r--intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw44
-rw-r--r--intern/bmfont/BMF_Api.h129
-rw-r--r--intern/bmfont/BMF_Fonts.h76
-rw-r--r--intern/bmfont/BMF_Settings.h69
-rw-r--r--intern/bmfont/Makefile52
-rw-r--r--intern/bmfont/intern/BMF_Api.cpp164
-rw-r--r--intern/bmfont/intern/BMF_BitmapFont.cpp207
-rw-r--r--intern/bmfont/intern/BMF_BitmapFont.h109
-rw-r--r--intern/bmfont/intern/BMF_FontData.h57
-rw-r--r--intern/bmfont/intern/BMF_font_helv10.cpp493
-rw-r--r--intern/bmfont/intern/BMF_font_helv12.cpp525
-rw-r--r--intern/bmfont/intern/BMF_font_helvb10.cpp492
-rw-r--r--intern/bmfont/intern/BMF_font_helvb12.cpp565
-rw-r--r--intern/bmfont/intern/BMF_font_helvb14.cpp623
-rw-r--r--intern/bmfont/intern/BMF_font_helvb8.cpp455
-rw-r--r--intern/bmfont/intern/BMF_font_scr12.cpp484
-rw-r--r--intern/bmfont/intern/BMF_font_scr14.cpp510
-rw-r--r--intern/bmfont/intern/BMF_font_scr15.cpp525
-rw-r--r--intern/bmfont/intern/Makefile44
-rw-r--r--intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp174
-rw-r--r--intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw29
-rw-r--r--intern/bmfont/test/BMF_Test.cpp225
-rw-r--r--intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp109
-rw-r--r--intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw44
-rw-r--r--intern/bsp/Makefile55
-rwxr-xr-xintern/bsp/extern/CSG_BooleanOps.h428
-rwxr-xr-xintern/bsp/intern/BSP_CSGException.h58
-rw-r--r--intern/bsp/intern/BSP_CSGHelper.cpp430
-rw-r--r--intern/bsp/intern/BSP_CSGHelper.h99
-rwxr-xr-xintern/bsp/intern/BSP_CSGISplitter.h118
-rwxr-xr-xintern/bsp/intern/BSP_CSGMesh.cpp883
-rwxr-xr-xintern/bsp/intern/BSP_CSGMesh.h345
-rwxr-xr-xintern/bsp/intern/BSP_CSGMeshBuilder.cpp152
-rwxr-xr-xintern/bsp/intern/BSP_CSGMeshBuilder.h74
-rwxr-xr-xintern/bsp/intern/BSP_CSGMeshSplitter.cpp715
-rwxr-xr-xintern/bsp/intern/BSP_CSGMeshSplitter.h208
-rwxr-xr-xintern/bsp/intern/BSP_CSGMesh_CFIterator.h272
-rwxr-xr-xintern/bsp/intern/BSP_CSGNCMeshSplitter.cpp241
-rwxr-xr-xintern/bsp/intern/BSP_CSGNCMeshSplitter.h139
-rwxr-xr-xintern/bsp/intern/BSP_CSGUserData.cpp133
-rwxr-xr-xintern/bsp/intern/BSP_CSGUserData.h136
-rwxr-xr-xintern/bsp/intern/BSP_FragNode.cpp313
-rwxr-xr-xintern/bsp/intern/BSP_FragNode.h127
-rwxr-xr-xintern/bsp/intern/BSP_FragTree.cpp319
-rwxr-xr-xintern/bsp/intern/BSP_FragTree.h146
-rwxr-xr-xintern/bsp/intern/BSP_MeshFragment.cpp279
-rwxr-xr-xintern/bsp/intern/BSP_MeshFragment.h152
-rwxr-xr-xintern/bsp/intern/BSP_MeshPrimitives.cpp301
-rw-r--r--intern/bsp/intern/BSP_MeshPrimitives.h289
-rwxr-xr-xintern/bsp/intern/BSP_Triangulate.cpp249
-rwxr-xr-xintern/bsp/intern/BSP_Triangulate.h132
-rwxr-xr-xintern/bsp/intern/CSG_BooleanOps.cpp255
-rw-r--r--intern/bsp/intern/Makefile48
-rw-r--r--intern/bsp/make/msvc6_0/bsplib.dsp211
-rw-r--r--intern/bsp/make/msvc6_0/bsplib.dsw29
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp130
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw125
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp656
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h165
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp160
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h77
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp196
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h64
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/BSP_TMesh.h354
-rw-r--r--intern/bsp/test/BSP_GhostTest/Makefile56
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/main.cpp147
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/ply.h200
-rwxr-xr-xintern/bsp/test/BSP_GhostTest/plyfile.c2548
-rw-r--r--intern/bsp/test/Makefile72
-rw-r--r--intern/container/CTR_List.h144
-rw-r--r--intern/container/CTR_Map.h152
-rw-r--r--intern/container/CTR_TaggedIndex.h226
-rw-r--r--intern/container/CTR_TaggedSetOps.h287
-rw-r--r--intern/container/CTR_UHeap.h303
-rw-r--r--intern/container/Makefile52
-rw-r--r--intern/container/intern/CTR_List.cpp149
-rw-r--r--intern/container/intern/Makefile42
-rw-r--r--intern/container/make/msvc_6_0/container.dsp133
-rw-r--r--intern/container/make/msvc_6_0/container.dsw30
-rw-r--r--intern/decimation/Makefile52
-rw-r--r--intern/decimation/extern/LOD_decimation.h119
-rw-r--r--intern/decimation/intern/LOD_DecimationClass.h118
-rw-r--r--intern/decimation/intern/LOD_EdgeCollapser.cpp408
-rw-r--r--intern/decimation/intern/LOD_EdgeCollapser.h118
-rw-r--r--intern/decimation/intern/LOD_ExternBufferEditor.h164
-rw-r--r--intern/decimation/intern/LOD_ExternNormalEditor.cpp264
-rw-r--r--intern/decimation/intern/LOD_ExternNormalEditor.h134
-rw-r--r--intern/decimation/intern/LOD_FaceNormalEditor.cpp291
-rw-r--r--intern/decimation/intern/LOD_FaceNormalEditor.h143
-rw-r--r--intern/decimation/intern/LOD_ManMesh2.cpp617
-rw-r--r--intern/decimation/intern/LOD_ManMesh2.h264
-rw-r--r--intern/decimation/intern/LOD_MeshBounds.h134
-rw-r--r--intern/decimation/intern/LOD_MeshException.h55
-rw-r--r--intern/decimation/intern/LOD_MeshPrimitives.cpp407
-rw-r--r--intern/decimation/intern/LOD_MeshPrimitives.h221
-rw-r--r--intern/decimation/intern/LOD_QSDecimator.cpp324
-rw-r--r--intern/decimation/intern/LOD_QSDecimator.h128
-rw-r--r--intern/decimation/intern/LOD_Quadric.h168
-rw-r--r--intern/decimation/intern/LOD_QuadricEditor.cpp279
-rw-r--r--intern/decimation/intern/LOD_QuadricEditor.h119
-rw-r--r--intern/decimation/intern/LOD_decimation.cpp156
-rw-r--r--intern/decimation/intern/Makefile45
-rw-r--r--intern/decimation/make/msvc_6_0/decimation.dsp188
-rw-r--r--intern/decimation/make/msvc_6_0/decimation.dsw33
-rw-r--r--intern/ghost/GHOST_C-api.h733
-rw-r--r--intern/ghost/GHOST_IEvent.h88
-rw-r--r--intern/ghost/GHOST_IEventConsumer.h66
-rw-r--r--intern/ghost/GHOST_ISystem.h282
-rw-r--r--intern/ghost/GHOST_ITimerTask.h88
-rw-r--r--intern/ghost/GHOST_IWindow.h241
-rw-r--r--intern/ghost/GHOST_Rect.h237
-rw-r--r--intern/ghost/GHOST_Types.h354
-rw-r--r--intern/ghost/Makefile52
-rw-r--r--intern/ghost/doc/Doxyfile.win747
-rw-r--r--intern/ghost/intern/GHOST_Buttons.cpp82
-rw-r--r--intern/ghost/intern/GHOST_Buttons.h76
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp778
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.cpp55
-rw-r--r--intern/ghost/intern/GHOST_CallbackEventConsumer.h77
-rw-r--r--intern/ghost/intern/GHOST_Debug.h74
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.cpp219
-rw-r--r--intern/ghost/intern/GHOST_DisplayManager.h142
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp178
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCarbon.h119
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp186
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.h106
-rwxr-xr-xintern/ghost/intern/GHOST_DisplayManagerX11.cpp125
-rwxr-xr-xintern/ghost/intern/GHOST_DisplayManagerX11.h129
-rw-r--r--intern/ghost/intern/GHOST_Event.h114
-rw-r--r--intern/ghost/intern/GHOST_EventButton.h73
-rw-r--r--intern/ghost/intern/GHOST_EventCursor.h74
-rw-r--r--intern/ghost/intern/GHOST_EventKey.h87
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp215
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h157
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.cpp259
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h70
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp98
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.cpp136
-rw-r--r--intern/ghost/intern/GHOST_ModifierKeys.h102
-rw-r--r--intern/ghost/intern/GHOST_Rect.cpp140
-rw-r--r--intern/ghost/intern/GHOST_System.cpp320
-rw-r--r--intern/ghost/intern/GHOST_System.h328
-rw-r--r--intern/ghost/intern/GHOST_SystemCarbon.cpp735
-rw-r--r--intern/ghost/intern/GHOST_SystemCarbon.h251
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h65
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp817
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h278
-rwxr-xr-xintern/ghost/intern/GHOST_SystemX11.cpp803
-rwxr-xr-xintern/ghost/intern/GHOST_SystemX11.h252
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.cpp163
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.h133
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h195
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp116
-rw-r--r--intern/ghost/intern/GHOST_Window.h255
-rw-r--r--intern/ghost/intern/GHOST_WindowCarbon.cpp581
-rw-r--r--intern/ghost/intern/GHOST_WindowCarbon.h273
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.cpp190
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.h165
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp584
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h276
-rwxr-xr-xintern/ghost/intern/GHOST_WindowX11.cpp714
-rwxr-xr-xintern/ghost/intern/GHOST_WindowX11.h292
-rw-r--r--intern/ghost/intern/Makefile65
-rw-r--r--intern/ghost/make/msvc/ghost.dsp576
-rw-r--r--intern/ghost/make/msvc/ghost.dsw58
-rwxr-xr-xintern/ghost/test/Makefile86
-rw-r--r--intern/ghost/test/gears/GHOST_C-Test.c543
-rwxr-xr-xintern/ghost/test/gears/GHOST_Test.cpp745
-rwxr-xr-xintern/ghost/test/gears/Makefile48
-rw-r--r--intern/ghost/test/make/msvc_6_0/gears.dsp102
-rw-r--r--intern/ghost/test/make/msvc_6_0/gears_C.dsp102
-rw-r--r--intern/ghost/test/make/msvc_6_0/ghost_test.dsw77
-rw-r--r--intern/ghost/test/multitest/Basic.c68
-rw-r--r--intern/ghost/test/multitest/Basic.h44
-rw-r--r--intern/ghost/test/multitest/EventToBuf.c236
-rw-r--r--intern/ghost/test/multitest/EventToBuf.h35
-rw-r--r--intern/ghost/test/multitest/GL.h43
-rw-r--r--intern/ghost/test/multitest/Makefile60
-rwxr-xr-xintern/ghost/test/multitest/MultiTest.c855
-rw-r--r--intern/ghost/test/multitest/ScrollBar.c145
-rw-r--r--intern/ghost/test/multitest/ScrollBar.h56
-rw-r--r--intern/ghost/test/multitest/Util.c73
-rw-r--r--intern/ghost/test/multitest/Util.h35
-rw-r--r--intern/ghost/test/multitest/WindowData.c60
-rw-r--r--intern/ghost/test/multitest/WindowData.h40
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h114
-rw-r--r--intern/guardedalloc/Makefile52
-rw-r--r--intern/guardedalloc/intern/Makefile42
-rw-r--r--intern/guardedalloc/intern/mallocn.c457
-rw-r--r--intern/guardedalloc/test/Makefile55
-rw-r--r--intern/guardedalloc/test/simpletest/Makefile44
-rw-r--r--intern/guardedalloc/test/simpletest/memtest.c158
-rw-r--r--intern/iksolver/Makefile52
-rw-r--r--intern/iksolver/extern/IK_solver.h207
-rw-r--r--intern/iksolver/intern/IK_CGChainSolver.cpp300
-rw-r--r--intern/iksolver/intern/IK_CGChainSolver.h178
-rw-r--r--intern/iksolver/intern/IK_Chain.cpp208
-rw-r--r--intern/iksolver/intern/IK_Chain.h194
-rw-r--r--intern/iksolver/intern/IK_ConjugateGradientSolver.cpp162
-rw-r--r--intern/iksolver/intern/IK_ConjugateGradientSolver.h195
-rw-r--r--intern/iksolver/intern/IK_JacobianSolver.cpp267
-rw-r--r--intern/iksolver/intern/IK_JacobianSolver.h171
-rw-r--r--intern/iksolver/intern/IK_LineMinimizer.h298
-rw-r--r--intern/iksolver/intern/IK_QChain.cpp280
-rw-r--r--intern/iksolver/intern/IK_QChain.h211
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.cpp327
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.h184
-rw-r--r--intern/iksolver/intern/IK_QSegment.cpp363
-rw-r--r--intern/iksolver/intern/IK_QSegment.h290
-rw-r--r--intern/iksolver/intern/IK_QSolver_Class.h107
-rw-r--r--intern/iksolver/intern/IK_Segment.cpp277
-rw-r--r--intern/iksolver/intern/IK_Segment.h217
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp196
-rw-r--r--intern/iksolver/intern/IK_Solver_Class.h93
-rw-r--r--intern/iksolver/intern/MT_ExpMap.cpp268
-rw-r--r--intern/iksolver/intern/MT_ExpMap.h219
-rw-r--r--intern/iksolver/intern/Makefile44
-rw-r--r--intern/iksolver/intern/TNT/cholesky.h128
-rw-r--r--intern/iksolver/intern/TNT/cmat.h661
-rw-r--r--intern/iksolver/intern/TNT/fcscmat.h197
-rw-r--r--intern/iksolver/intern/TNT/fmat.h609
-rw-r--r--intern/iksolver/intern/TNT/fortran.h99
-rw-r--r--intern/iksolver/intern/TNT/fspvec.h200
-rw-r--r--intern/iksolver/intern/TNT/index.h115
-rw-r--r--intern/iksolver/intern/TNT/lapack.h225
-rw-r--r--intern/iksolver/intern/TNT/lu.h236
-rw-r--r--intern/iksolver/intern/TNT/qr.h261
-rw-r--r--intern/iksolver/intern/TNT/region1d.h403
-rw-r--r--intern/iksolver/intern/TNT/region2d.h499
-rw-r--r--intern/iksolver/intern/TNT/stopwatch.h115
-rw-r--r--intern/iksolver/intern/TNT/subscript.h90
-rw-r--r--intern/iksolver/intern/TNT/svd.h507
-rw-r--r--intern/iksolver/intern/TNT/tnt.h127
-rw-r--r--intern/iksolver/intern/TNT/tntmath.h177
-rw-r--r--intern/iksolver/intern/TNT/tntreqs.h102
-rw-r--r--intern/iksolver/intern/TNT/transv.h192
-rw-r--r--intern/iksolver/intern/TNT/triang.h670
-rw-r--r--intern/iksolver/intern/TNT/trisolve.h216
-rw-r--r--intern/iksolver/intern/TNT/vec.h535
-rw-r--r--intern/iksolver/intern/TNT/vecadaptor.h321
-rw-r--r--intern/iksolver/intern/TNT/version.h52
-rw-r--r--intern/iksolver/make/msvc_6_0/iksolver.dsp244
-rw-r--r--intern/iksolver/make/msvc_6_0/iksolver.dsw35
-rw-r--r--intern/iksolver/test/Makefile67
-rw-r--r--intern/iksolver/test/ik_glut_test/Makefile42
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp95
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.h100
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp89
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h106
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp104
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h116
-rw-r--r--intern/iksolver/test/ik_glut_test/common/Makefile44
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h387
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/Makefile51
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h84
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h211
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/main.cpp361
-rw-r--r--intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp130
-rw-r--r--intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw49
-rw-r--r--intern/img/doc/Doxyfile.win747
-rw-r--r--intern/img/extern/IMG_Pixmap.h198
-rw-r--r--intern/img/extern/IMG_PixmapRGBA32.h217
-rw-r--r--intern/img/intern/IMG_Color.h144
-rw-r--r--intern/img/intern/IMG_MemPtr.h117
-rw-r--r--intern/img/intern/IMG_Pixmap.cpp85
-rw-r--r--intern/img/intern/IMG_PixmapRGBA32.cpp260
-rw-r--r--intern/img/intern/Makefile43
-rw-r--r--intern/img/make/msvc/img.dsp126
-rw-r--r--intern/img/make/msvc/img.dsw41
-rw-r--r--intern/memutil/MEM_NonCopyable.h59
-rw-r--r--intern/memutil/MEM_RefCountPtr.h294
-rw-r--r--intern/memutil/MEM_RefCounted.h120
-rw-r--r--intern/memutil/MEM_RefCountedC-Api.h90
-rw-r--r--intern/memutil/MEM_SmartPtr.h240
-rw-r--r--intern/memutil/Makefile52
-rw-r--r--intern/memutil/intern/MEM_RefCountedC-Api.cpp64
-rw-r--r--intern/memutil/intern/Makefile42
-rw-r--r--intern/memutil/make/msvc_60/memutil.dsp134
-rw-r--r--intern/memutil/make/msvc_60/memutil.dsw30
-rw-r--r--intern/moto/Makefile52
-rw-r--r--intern/moto/include/GEN_List.h120
-rw-r--r--intern/moto/include/GEN_Map.h152
-rw-r--r--intern/moto/include/MT_CmMatrix4x4.h147
-rwxr-xr-xintern/moto/include/MT_Matrix3x3.h214
-rw-r--r--intern/moto/include/MT_Matrix3x3.inl128
-rwxr-xr-xintern/moto/include/MT_Matrix4x4.h250
-rw-r--r--intern/moto/include/MT_Matrix4x4.inl108
-rwxr-xr-xintern/moto/include/MT_MinMax.h69
-rw-r--r--intern/moto/include/MT_Optimize.h42
-rw-r--r--intern/moto/include/MT_Plane3.h139
-rw-r--r--intern/moto/include/MT_Plane3.inl128
-rw-r--r--intern/moto/include/MT_Point2.h81
-rw-r--r--intern/moto/include/MT_Point2.inl54
-rw-r--r--intern/moto/include/MT_Point3.h81
-rw-r--r--intern/moto/include/MT_Point3.inl54
-rw-r--r--intern/moto/include/MT_Quaternion.h112
-rw-r--r--intern/moto/include/MT_Quaternion.inl62
-rwxr-xr-xintern/moto/include/MT_Scalar.h88
-rwxr-xr-xintern/moto/include/MT_Stream.h58
-rw-r--r--intern/moto/include/MT_Transform.h172
-rwxr-xr-xintern/moto/include/MT_Tuple2.h109
-rwxr-xr-xintern/moto/include/MT_Tuple3.h114
-rwxr-xr-xintern/moto/include/MT_Tuple4.h124
-rw-r--r--intern/moto/include/MT_Vector2.h112
-rw-r--r--intern/moto/include/MT_Vector2.inl89
-rw-r--r--intern/moto/include/MT_Vector3.h118
-rw-r--r--intern/moto/include/MT_Vector3.inl134
-rw-r--r--intern/moto/include/MT_Vector4.h102
-rw-r--r--intern/moto/include/MT_Vector4.inl80
-rw-r--r--intern/moto/include/MT_assert.h51
-rwxr-xr-xintern/moto/include/MT_random.h44
-rw-r--r--intern/moto/include/NM_Scalar.h166
-rwxr-xr-xintern/moto/intern/MT_CmMatrix4x4.cpp237
-rw-r--r--intern/moto/intern/MT_Matrix3x3.cpp37
-rw-r--r--intern/moto/intern/MT_Matrix4x4.cpp37
-rw-r--r--intern/moto/intern/MT_Plane3.cpp68
-rw-r--r--intern/moto/intern/MT_Point3.cpp37
-rw-r--r--intern/moto/intern/MT_Quaternion.cpp37
-rw-r--r--intern/moto/intern/MT_Transform.cpp138
-rw-r--r--intern/moto/intern/MT_Vector2.cpp37
-rw-r--r--intern/moto/intern/MT_Vector3.cpp37
-rw-r--r--intern/moto/intern/MT_Vector4.cpp37
-rwxr-xr-xintern/moto/intern/MT_random.cpp142
-rw-r--r--intern/moto/intern/Makefile42
-rwxr-xr-xintern/moto/make/msvc_6_0/MoTo.dsp379
-rwxr-xr-xintern/moto/make/msvc_6_0/MoTo.dsw58
-rw-r--r--intern/python/Blender.py349
-rw-r--r--intern/python/README7
-rw-r--r--intern/python/blendermodule/main.c873
-rw-r--r--intern/python/blendermodule/test.py52
-rw-r--r--intern/python/freeze/Makefile14
-rw-r--r--intern/python/freeze/README173
-rw-r--r--intern/python/freeze/README.NaN12
-rw-r--r--intern/python/freeze/bkfile.py47
-rw-r--r--intern/python/freeze/checkextensions.py91
-rw-r--r--intern/python/freeze/checkextensions_win32.py190
-rwxr-xr-xintern/python/freeze/freeze.py461
-rw-r--r--intern/python/freeze/hello.py1
-rw-r--r--intern/python/freeze/makeconfig.py61
-rw-r--r--intern/python/freeze/makefreeze.py115
-rw-r--r--intern/python/freeze/makemakefile.py57
-rw-r--r--intern/python/freeze/modulefinder.py444
-rw-r--r--intern/python/freeze/parsesetup.py98
-rw-r--r--intern/python/freeze/winmakemakefile.py146
-rw-r--r--intern/python/ivexport.py225
-rw-r--r--intern/python/modules/Blender/BGL.py1
-rw-r--r--intern/python/modules/Blender/Camera.py106
-rw-r--r--intern/python/modules/Blender/Draw.py1
-rw-r--r--intern/python/modules/Blender/Image.py52
-rw-r--r--intern/python/modules/Blender/Ipo.py279
-rw-r--r--intern/python/modules/Blender/Lamp.py168
-rw-r--r--intern/python/modules/Blender/Material.py251
-rw-r--r--intern/python/modules/Blender/Mesh.py250
-rw-r--r--intern/python/modules/Blender/NMesh.py192
-rw-r--r--intern/python/modules/Blender/Object.py391
-rw-r--r--intern/python/modules/Blender/Scene.py143
-rw-r--r--intern/python/modules/Blender/Text.py57
-rw-r--r--intern/python/modules/Blender/Types.py1
-rw-r--r--intern/python/modules/Blender/Window.py65
-rw-r--r--intern/python/modules/Blender/World.py157
-rw-r--r--intern/python/modules/Blender/__init__.py23
-rw-r--r--intern/python/modules/Blender/shadow.py195
-rw-r--r--intern/python/modules/Blender/sys.py20
-rw-r--r--intern/python/modules/Converter/__init__.py4
-rw-r--r--intern/python/modules/Converter/bimporter.py34
-rw-r--r--intern/python/modules/Converter/importer/VRMLimporter.py988
-rw-r--r--intern/python/modules/Converter/importer/__init__.py17
-rw-r--r--intern/python/modules/Converter/importloader.py23
-rw-r--r--intern/python/modules/TextTools/Constants/Sets.py39
-rw-r--r--intern/python/modules/TextTools/Constants/TagTables.py348
-rw-r--r--intern/python/modules/TextTools/Constants/__init__.py1
-rw-r--r--intern/python/modules/TextTools/TextTools.py766
-rw-r--r--intern/python/modules/TextTools/__init__.py48
-rw-r--r--intern/python/modules/TextTools/mxTextTools/__init__.py17
-rw-r--r--intern/python/modules/VRMLmain.py3
-rw-r--r--intern/python/modules/beta/Objects.py167
-rw-r--r--intern/python/modules/beta/Scenegraph.py182
-rw-r--r--intern/python/modules/beta/__init__.py1
-rw-r--r--intern/python/modules/blenderos.py24
-rw-r--r--intern/python/modules/mcf/__init__.py6
-rw-r--r--intern/python/modules/mcf/utils/__init__.py6
-rw-r--r--intern/python/modules/mcf/utils/collapse.py169
-rw-r--r--intern/python/modules/mcf/utils/copy_extend.py83
-rw-r--r--intern/python/modules/mcf/utils/cpickle_extend.py190
-rw-r--r--intern/python/modules/mcf/utils/dictbool.py80
-rw-r--r--intern/python/modules/mcf/utils/dsort.py91
-rw-r--r--intern/python/modules/mcf/utils/dummy.py91
-rw-r--r--intern/python/modules/mcf/utils/err.py37
-rw-r--r--intern/python/modules/mcf/utils/extpkl.py19
-rw-r--r--intern/python/modules/mcf/utils/fileassociation.py65
-rw-r--r--intern/python/modules/mcf/utils/findourfile.py30
-rw-r--r--intern/python/modules/mcf/utils/hier_rx.py201
-rw-r--r--intern/python/modules/mcf/utils/hierdummy.py16
-rw-r--r--intern/python/modules/mcf/utils/hierobj.py133
-rw-r--r--intern/python/modules/mcf/utils/in_place_ops.py38
-rw-r--r--intern/python/modules/mcf/utils/namespace.py224
-rw-r--r--intern/python/modules/mcf/utils/quote.py78
-rw-r--r--intern/python/modules/mcf/utils/rangeval.py64
-rw-r--r--intern/python/modules/mcf/utils/regutils_ex.py158
-rw-r--r--intern/python/modules/mcf/utils/reloader.py33
-rw-r--r--intern/python/modules/mcf/utils/singletonlist.py104
-rw-r--r--intern/python/modules/mcf/utils/tempclassmodule.py251
-rw-r--r--intern/python/modules/mcf/utils/typeclasses.py50
-rw-r--r--intern/python/modules/mcf/utils/userquery.py17
-rw-r--r--intern/python/modules/mcf/utils/ver.py17
-rw-r--r--intern/python/modules/mcf/utils/walkerable.py46
-rw-r--r--intern/python/modules/simpleparse/__init__.py5
-rw-r--r--intern/python/modules/simpleparse/bootstrap.py279
-rw-r--r--intern/python/modules/simpleparse/generator.py432
-rw-r--r--intern/python/modules/util/README.txt13
-rw-r--r--intern/python/modules/util/__init__.py2
-rw-r--r--intern/python/modules/util/quat.py109
-rw-r--r--intern/python/modules/util/tree.py215
-rw-r--r--intern/python/modules/util/vect.py480
-rw-r--r--intern/python/modules/util/vectools.py142
-rw-r--r--intern/python/modules/vrml/__init__.py1
-rw-r--r--intern/python/modules/vrml/basenodes.py974
-rw-r--r--intern/python/modules/vrml/fieldcoercian.py310
-rw-r--r--intern/python/modules/vrml/loader.py97
-rw-r--r--intern/python/modules/vrml/parser.py426
-rw-r--r--intern/python/modules/vrml/scenegraph.py833
-rw-r--r--intern/python/modules/vrml/utils/__init__.py1
-rw-r--r--intern/python/modules/vrml/utils/collapse.py169
-rw-r--r--intern/python/modules/vrml/utils/err.py37
-rw-r--r--intern/python/modules/vrml/utils/namespace.py225
-rw-r--r--intern/python/modules/vrml/utils/typeclasses.py50
-rw-r--r--intern/python/objexport/BlendImport.py157
-rw-r--r--intern/python/objexport/objimport.py119
-rw-r--r--intern/python/py_main.c2292
-rw-r--r--intern/python/ribexport.py332
-rw-r--r--intern/python/testmodule/Makefile.pre.in305
-rw-r--r--intern/python/testmodule/Setup.in2
-rwxr-xr-xintern/python/testmodule/test.py16
-rw-r--r--intern/python/testmodule/testmodule.c182
-rw-r--r--intern/python/testmodule/testmodule.py14
-rw-r--r--intern/string/Makefile52
-rw-r--r--intern/string/STR_HashedString.h154
-rw-r--r--intern/string/STR_String.h202
-rw-r--r--intern/string/intern/Makefile42
-rw-r--r--intern/string/intern/STR_String.cpp743
-rw-r--r--intern/string/make/msvc_6_0/string.dsp122
-rw-r--r--intern/string/make/msvc_6_0/string.dsw29
505 files changed, 97280 insertions, 0 deletions
diff --git a/intern/BL-license.txt b/intern/BL-license.txt
new file mode 100644
index 00000000000..606d3ef6cef
--- /dev/null
+++ b/intern/BL-license.txt
@@ -0,0 +1,48 @@
+Blender License 1.0 (the "BL", see http://www.blender.org/BL/ ).
+
+Copyright (C) 2002 Blender Foundation. All Rights Reserved.
+
+For teams that don't want to operate under the GPL, we're also offering
+this "non-GPL" Blender License option. This means that you can download
+the latest sources and tools via FTP or CVS from our site and sign an
+additional agreement with the Blender Foundation, so you can keep your
+source modifications confidential. Contact the Blender Foundation via
+email at license@blender.org so we can discuss how we handle the
+practical matters.
+
+A signed agreement allows you to do business with proprietary code, make
+special derived versions, sell executables, projects or services,
+provided that:
+
+1. The BL-ed code remains copyrighted by the original owners, and cannot
+be transferred to other parties
+
+2. The BL-ed code cannot be published or re-distributed in any way, and
+only be available for the internal staff that works directly on the
+software itself. Employees of partners with which you co-develop on the
+projects that include BL-ed code are considered 'internal staff' also.
+
+3. The BL-ed code can be used (sold, distributed) in parts or in its
+whole only as an executable or as a compiled library/module and its
+header files.
+
+4. The usage of the name Blender or the Blender logo is not included in
+this license. Instead 'including Blender Foundation release X' (or
+similar) can be used, with 'X' the version number of the initial Blender
+Foundation release which you started with.
+
+5. Note that this BL has no authority over some of the external
+libraries licenses which Blender links with.
+
+Additionally you get :
+
+1. The right to use Blender Foundation source updates for a 1 year
+period.
+
+2. Support. Details to be determined by the additional agreement.
+
+You are invited to donate your proprietary changes back to the open
+source community after a reasonable time period. You are of course free
+to choose not to do this.
+
+End of BL terms and conditions.
diff --git a/intern/GPL-license.txt b/intern/GPL-license.txt
new file mode 100644
index 00000000000..14db8fc79db
--- /dev/null
+++ b/intern/GPL-license.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/intern/Makefile b/intern/Makefile
new file mode 100644
index 00000000000..e17cc62a4e6
--- /dev/null
+++ b/intern/Makefile
@@ -0,0 +1,38 @@
+#
+# $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.
+#
+# 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 *****
+# Bounces make to subdirectories. Intended for future tinderbox tests.
+
+SOURCEDIR = intern
+
+DIRS = ghost guardedalloc bmfont decimation string memutil action moto
+DIRS += iksolver keymaker container
+
+include nan_subdirs.mk
diff --git a/intern/SoundSystem/Makefile b/intern/SoundSystem/Makefile
new file mode 100644
index 00000000000..e7f9760cc3c
--- /dev/null
+++ b/intern/SoundSystem/Makefile
@@ -0,0 +1,54 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+include nan_definitions.mk
+
+SOURCEDIR = source/gameengine/SoundSystem
+DIR = $(OCGDIR)/SoundSystem
+DIRS = intern
+DIRS += dummy
+
+ifeq ($(OS),windows)
+ DIRS += fmod
+ DIRS += openal
+endif
+ifeq ($(OS),freebsd)
+ DIRS += openal
+endif
+ifeq ($(OS),$(findstring $(OS), "linux"))
+ ifeq ($(CPU),i386)
+ DIRS += openal
+ endif
+endif
+
+include nan_subdirs.mk
diff --git a/intern/SoundSystem/SND_C-api.h b/intern/SoundSystem/SND_C-api.h
new file mode 100644
index 00000000000..9c24438c131
--- /dev/null
+++ b/intern/SoundSystem/SND_C-api.h
@@ -0,0 +1,356 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#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..59817d72485
--- /dev/null
+++ b/intern/SoundSystem/SND_CDObject.h
@@ -0,0 +1,84 @@
+/*
+ * SND_CDObject.h
+ *
+ * Implementation for CD playback
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..b1272725f9e
--- /dev/null
+++ b/intern/SoundSystem/SND_DependKludge.h
@@ -0,0 +1,56 @@
+/*
+ * SND_DependKludge.h
+ *
+ * who needs what?
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#if defined (_WIN32)
+#define USE_FMOD
+#else
+# if defined (__linux__)
+# if defined (__i386__)
+# define USE_OPENAL
+# endif
+# else
+# if defined (__FreeBSD__)
+# define USE_OPENAL
+# endif
+# ifdef USE_OPENAL
+# undef USE_OPENAL
+# endif
+# ifdef USE_FMOD
+# undef USE_FMOD
+# endif
+# endif
+#endif
diff --git a/intern/SoundSystem/SND_DeviceManager.h b/intern/SoundSystem/SND_DeviceManager.h
new file mode 100644
index 00000000000..7e643779cfe
--- /dev/null
+++ b/intern/SoundSystem/SND_DeviceManager.h
@@ -0,0 +1,91 @@
+/*
+ * SND_DeviceManager.h
+ *
+ * singleton for creating, switching and deleting audiodevices
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/intern/SoundSystem/SND_IAudioDevice.h b/intern/SoundSystem/SND_IAudioDevice.h
new file mode 100644
index 00000000000..6bcc8f0c072
--- /dev/null
+++ b/intern/SoundSystem/SND_IAudioDevice.h
@@ -0,0 +1,346 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#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..2ae9bcc1dd0
--- /dev/null
+++ b/intern/SoundSystem/SND_Object.h
@@ -0,0 +1,55 @@
+/*
+ * SND_Object.h
+ *
+ * Abstract sound object
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..c2f6e5d8c48
--- /dev/null
+++ b/intern/SoundSystem/SND_Scene.h
@@ -0,0 +1,106 @@
+/*
+ * SND_Scene.h
+ *
+ * The scene for sounds.
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..63d8eb65942
--- /dev/null
+++ b/intern/SoundSystem/SND_SoundListener.h
@@ -0,0 +1,84 @@
+/*
+ * SND_SoundListener.h
+ *
+ * A SoundListener is for sound what a camera is for vision.
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..4c47cdc27b5
--- /dev/null
+++ b/intern/SoundSystem/SND_SoundObject.h
@@ -0,0 +1,162 @@
+/*
+ * SND_SoundObject.h
+ *
+ * Implementation of the abstract sound object
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..c9c3774b180
--- /dev/null
+++ b/intern/SoundSystem/SND_Utils.h
@@ -0,0 +1,113 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#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);
+extern unsigned int SND_GetHeaderSize(void* sample);
+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..5618b8b9ecf
--- /dev/null
+++ b/intern/SoundSystem/SND_WaveCache.h
@@ -0,0 +1,68 @@
+/*
+ * SND_WaveCache.h
+ *
+ * abstract wavecache, a way to organize samples
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..3d1e0d98ae9
--- /dev/null
+++ b/intern/SoundSystem/SND_WaveSlot.h
@@ -0,0 +1,94 @@
+/*
+ * SND_WaveSlot.cpp
+ *
+ * class for storing sample related information
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..0aae4866f1c
--- /dev/null
+++ b/intern/SoundSystem/SND_test/Makefile
@@ -0,0 +1,53 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+LIBNAME = SoundSystem
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)SoundSystem
+
+include nan_compile.mk
+
+CPPFLAGS += $(NAN_LEVEL_1_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../kernel/gen_system
+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)/kernel/gen_system/$(DEBUG_DIR)libgen_system.a
+TESTLIB += $(OCGDIR)/gameengine/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..eff52aef61e
--- /dev/null
+++ b/intern/SoundSystem/SND_test/SND_test.c
@@ -0,0 +1,152 @@
+/* SND_test.c nov 2000
+*
+* testfile for the SND module
+*
+* janco verduin
+*
+* $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.
+ *
+ * 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 *****
+*/
+
+#include "SND_C-api.h"
+#include "BlenderWaveCacheCApi.h"
+#include "OpenALC-Api.h"
+#include <stdio.h>
+#include <stdlib.h>
+#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..b2c00b0ade0
--- /dev/null
+++ b/intern/SoundSystem/SoundDefines.h
@@ -0,0 +1,119 @@
+/*
+ * SoundDefines.h
+ *
+ * this is where all kinds of defines are stored
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef __SOUNDDEFINES_H
+#define __SOUNDDEFINES_H
+
+/* the types of devices */
+enum
+{
+ snd_e_dummydevice = 0,
+ snd_e_fmoddevice,
+ snd_e_openaldevice
+};
+
+/* general stuff */
+#define NUM_BUFFERS 128
+#define NUM_SOURCES 16
+
+/* openal related stuff */
+#define AL_LOOPING 0x1007
+
+/* fmod related stuff */
+#ifdef WIN32
+#define MIXRATE 22050
+#else
+#define MIXRATE 44100
+#endif
+#define NUM_FMOD_MIN_HW_CHANNELS 16
+#define NUM_FMOD_MAX_HW_CHANNELS 16
+
+/* 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..fd2c85e7464
--- /dev/null
+++ b/intern/SoundSystem/dummy/Makefile
@@ -0,0 +1,46 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+LIBNAME = DummySoundSystem
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../../kernel/gen_system
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/intern/SoundSystem/dummy/SND_DummyDevice.cpp b/intern/SoundSystem/dummy/SND_DummyDevice.cpp
new file mode 100644
index 00000000000..4d1f69c6f33
--- /dev/null
+++ b/intern/SoundSystem/dummy/SND_DummyDevice.cpp
@@ -0,0 +1,53 @@
+/*
+ * $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.
+ *
+ * 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 *****
+ * SND_FmodDevice derived from SND_IAudioDevice
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_DummyDevice.h"
+
+SND_DummyDevice::SND_DummyDevice()
+{
+}
+
+
+
+SND_DummyDevice::~SND_DummyDevice()
+{
+#ifdef ONTKEVER
+ printf("SND_DummyDevice destructor");
+#endif
+}
+
+
diff --git a/intern/SoundSystem/dummy/SND_DummyDevice.h b/intern/SoundSystem/dummy/SND_DummyDevice.h
new file mode 100644
index 00000000000..717a34550bc
--- /dev/null
+++ b/intern/SoundSystem/dummy/SND_DummyDevice.h
@@ -0,0 +1,95 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#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/fmod/Makefile b/intern/SoundSystem/fmod/Makefile
new file mode 100644
index 00000000000..bb545c36e2d
--- /dev/null
+++ b/intern/SoundSystem/fmod/Makefile
@@ -0,0 +1,47 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+LIBNAME = FmodSoundSystem
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_FMOD)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/intern/SoundSystem/fmod/SND_FmodDevice.cpp b/intern/SoundSystem/fmod/SND_FmodDevice.cpp
new file mode 100644
index 00000000000..862703d0d59
--- /dev/null
+++ b/intern/SoundSystem/fmod/SND_FmodDevice.cpp
@@ -0,0 +1,543 @@
+/*
+ * $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.
+ *
+ * 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 *****
+ * SND_FmodDevice derived from SND_IAudioDevice
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_FmodDevice.h"
+#include "SoundDefines.h"
+#include "SYS_System.h"
+#include "SND_Utils.h"
+
+SND_FmodDevice::SND_FmodDevice()
+{
+ // check if audio is wanted
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0);
+
+ m_dspunit = NULL;
+
+ if (audio == 1)
+ m_audio = false;
+ else
+ m_audio = true;
+
+ // let's check if we can get fmod to initialize...
+ if (m_audio)
+ {
+ signed char MinHardwareChannels = FSOUND_SetMinHardwareChannels(NUM_FMOD_MIN_HW_CHANNELS);
+ signed char MaxHardwareChannels = FSOUND_SetMaxHardwareChannels(NUM_FMOD_MAX_HW_CHANNELS);
+
+ if (FSOUND_Init(MIXRATE, NUM_SOURCES, 0))
+ {
+ m_max_channels = FSOUND_GetMaxChannels();
+ m_num_hardware_channels = FSOUND_GetNumHardwareChannels();
+ m_num_software_channels = NUM_SOURCES;
+
+ // let's get us a wavecache
+ m_wavecache = new SND_WaveCache();
+
+ int i;
+ for (i = 0; i < NUM_BUFFERS; i++)
+ m_buffers[i] = NULL;
+
+ for (i = 0; i < NUM_SOURCES; i++)
+ {
+ m_sources[i] = NULL;
+ m_frequencies[i] = 0;
+ m_channels[i] = 0;
+ }
+ }
+ else
+ {
+ m_audio = false;
+ }
+ }
+
+#ifdef ONTKEVER
+ int numdrivers = FSOUND_GetNumDrivers();
+ int output = FSOUND_GetOutput();
+ int oputputrate = FSOUND_GetOutputRate();
+ int mixer = FSOUND_GetMixer();
+
+ printf("maxchannels is: %d\n", m_max_channels);
+ printf("num hw channels is: %d\n", m_num_hardware_channels);
+ printf("num sw channels is: %d\n", m_num_software_channels);
+ printf("numdrivers is: %d\n", numdrivers);
+ printf("output is: %d\n", output);
+ printf("oputputrate is: %d\n", oputputrate);
+ printf("mixer is: %d\n", mixer);
+#endif
+}
+
+
+
+SND_FmodDevice::~SND_FmodDevice()
+{
+ // 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();
+ }
+
+ StopUsingDSP();
+
+ FSOUND_Close();
+}
+
+
+
+void SND_FmodDevice::UseCD() const
+{
+ // only fmod has CD support, so only create it here
+ SND_CDObject::CreateSystem();
+}
+
+
+
+void SND_FmodDevice::MakeCurrent() const
+{
+ // empty
+}
+
+
+
+SND_WaveSlot* SND_FmodDevice::LoadSample(const STR_String& name,
+ void* memlocation,
+ int size)
+{
+ SND_WaveSlot* waveslot = NULL;
+ STR_String samplename = name;
+
+ if (m_audio)
+ {
+ /* first check if the sample is supported */
+ if (SND_IsSampleValid(name, memlocation))
+ {
+ /* create the waveslot */
+ waveslot = m_wavecache->GetWaveSlot(samplename);
+
+ if (waveslot)
+ {
+ int buffer = waveslot->GetBuffer();
+
+ /* load the sample from memory? */
+ if (size && memlocation)
+ {
+ m_buffers[buffer] = FSOUND_Sample_Load(buffer, (char*)memlocation, FSOUND_LOADMEMORY, size);
+
+ /* if the loading succeeded, fill the waveslot with info */
+ if (m_buffers[buffer])
+ {
+ int sampleformat = SND_GetSampleFormat(memlocation);
+ int numberofchannels = SND_GetNumberOfChannels(memlocation);
+ int samplerate = SND_GetSampleRate(memlocation);
+ int bitrate = SND_GetBitRate(memlocation);
+ int numberofsamples = SND_GetNumberOfSamples(memlocation);
+
+ waveslot->SetFileSize(size);
+ waveslot->SetData(memlocation);
+ waveslot->SetSampleFormat(sampleformat);
+ waveslot->SetNumberOfChannels(numberofchannels);
+ waveslot->SetSampleRate(samplerate);
+ waveslot->SetBitRate(bitrate);
+ waveslot->SetNumberOfSamples(numberofsamples);
+ }
+ }
+ /* or from file? */
+ else
+ {
+ m_buffers[buffer] = FSOUND_Sample_Load(buffer, samplename.Ptr(), FSOUND_LOOP_NORMAL, NULL);
+ }
+
+#ifdef ONTKEVER
+ int error = FSOUND_GetError();
+ printf("sample load: errornumber is: %d\n", error);
+#endif
+
+ /* if the loading succeeded, mark the waveslot */
+ if (m_buffers[buffer])
+ {
+ waveslot->SetLoaded(true);
+ }
+ /* or when it failed, free the waveslot */
+ else
+ {
+ m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer());
+ waveslot = NULL;
+ }
+ }
+ }
+ }
+
+ return waveslot;
+}
+
+
+
+
+// listener's and general stuff //////////////////////////////////////////////////////
+
+
+
+/* sets the global dopplervelocity */
+void SND_FmodDevice::SetDopplerVelocity(MT_Scalar dopplervelocity) const
+{
+ /* not supported by fmod */
+ FSOUND_3D_Listener_SetDopplerFactor(dopplervelocity);
+}
+
+
+
+/* sets the global dopplerfactor */
+void SND_FmodDevice::SetDopplerFactor(MT_Scalar dopplerfactor) const
+{
+ FSOUND_3D_Listener_SetDopplerFactor(dopplerfactor);
+}
+
+
+
+/* sets the global rolloff factor */
+void SND_FmodDevice::SetListenerRollOffFactor(MT_Scalar rollofffactor) const
+{
+ // not implemented in openal
+}
+
+
+
+void SND_FmodDevice::NextFrame() const
+{
+ FSOUND_3D_Update();
+}
+
+
+
+// set the gain for the listener
+void SND_FmodDevice::SetListenerGain(float gain) const
+{
+ int fmod_gain = (int)(gain * 255);
+ FSOUND_SetSFXMasterVolume(fmod_gain);
+}
+
+
+
+void SND_FmodDevice::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};
+
+ FSOUND_3D_Listener_SetAttributes(lispos, lisvel, 0, -1, 0, 0, 0, 1);
+}
+
+
+
+// source playstate stuff ////////////////////////////////////////////////////////////
+
+
+
+// check if the sound's still playing
+int SND_FmodDevice::GetPlayState(int id)
+{
+ int result = SND_STOPPED;
+
+ // klopt niet, fixen
+ signed char isplaying = FSOUND_IsPlaying(id);
+
+ if (isplaying)
+ {
+ result = SND_PLAYING;
+ }
+
+/* hi reevan, just swap // of these 2 lines */
+// return result;
+ return 0;
+}
+
+
+
+/* sets the buffer */
+void SND_FmodDevice::SetObjectBuffer(int id, unsigned int buffer)
+{
+ m_sources[id] = m_buffers[buffer];
+}
+
+
+
+// make the source play
+void SND_FmodDevice::PlayObject(int id)
+{
+ m_channels[id] = FSOUND_PlaySound(FSOUND_FREE, m_sources[id]);
+ m_frequencies[id] = FSOUND_GetFrequency(m_channels[id]);
+// printf("fmod: play \n");
+}
+
+
+
+// make the source stop
+void SND_FmodDevice::StopObject(int id) const
+{
+ FSOUND_StopSound(m_channels[id]);
+// printf("fmod: stop \n");
+}
+
+
+
+// stop all sources
+void SND_FmodDevice::StopAllObjects()
+{
+ FSOUND_StopSound(FSOUND_ALL);
+}
+
+
+
+// pause the source
+void SND_FmodDevice::PauseObject(int id) const
+{
+ FSOUND_StopSound(m_channels[id]);
+}
+
+
+
+// source properties stuff ////////////////////////////////////////////////////////////
+
+
+
+// give openal the object's pitch
+void SND_FmodDevice::SetObjectPitch(int id, MT_Scalar pitch) const
+{
+ pitch = pitch * m_frequencies[id];
+ char result = FSOUND_SetFrequency(m_channels[id], (int)pitch);
+}
+
+
+
+// give openal the object's gain
+void SND_FmodDevice::SetObjectGain(int id, MT_Scalar gain) const
+{
+ int vol = (int)(gain * 255);
+ FSOUND_SetVolume(m_channels[id], vol);
+}
+
+
+
+// give openal the object's looping
+void SND_FmodDevice::SetObjectLoop(int id, unsigned int loopmode) const
+{
+// printf("loopmode: %d\n", loopmode);
+ switch (loopmode)
+ {
+ case SND_LOOP_OFF:
+ {
+ char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_OFF);
+// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_OFF);
+ break;
+ }
+ case SND_LOOP_NORMAL:
+ {
+ char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_NORMAL);
+// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL);
+ break;
+ }
+ case SND_LOOP_BIDIRECTIONAL:
+ {
+ char result = FSOUND_Sample_SetLoopMode(m_sources[id], FSOUND_LOOP_BIDI);
+// char result = FSOUND_SetLoopMode(m_channels[id], FSOUND_LOOP_NORMAL);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+
+void SND_FmodDevice::SetObjectLoopPoints(int id, unsigned int loopstart, unsigned int loopend) const
+{
+ FSOUND_Sample_SetLoopPoints(m_sources[id], loopstart, loopend);
+}
+
+
+
+void SND_FmodDevice::SetObjectMinGain(int id, MT_Scalar mingain) const
+{
+ /* not supported by fmod */
+}
+
+
+
+void SND_FmodDevice::SetObjectMaxGain(int id, MT_Scalar maxgain) const
+{
+ /* not supported by fmod */
+}
+
+
+
+void SND_FmodDevice::SetObjectRollOffFactor(int id, MT_Scalar rollofffactor) const
+{
+ /* not supported by fmod */
+}
+
+
+
+void SND_FmodDevice::SetObjectReferenceDistance(int id, MT_Scalar referencedistance) const
+{
+ /* not supported by fmod */
+}
+
+
+
+// give openal the object's position
+void SND_FmodDevice::ObjectIs2D(int id) const
+{
+ float obpos[3] = {0,0,0};
+ float obvel[3] = {0,0,0};
+
+ FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel);
+}
+
+
+
+void SND_FmodDevice::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;
+
+ velocity.getValue(obvel);
+ FSOUND_3D_SetAttributes(m_channels[id], obpos, obvel);
+}
+
+
+
+// cd support stuff ////////////////////////////////////////////////////////////
+
+
+void SND_FmodDevice::PlayCD(int track) const
+{
+ signed char result = FSOUND_CD_Play(track);
+
+#ifdef ONTKEVER
+ printf("play track %d, result: %c\n", track, result);
+#endif
+}
+
+
+
+void SND_FmodDevice::PauseCD(bool pause) const
+{
+ signed char result = FSOUND_CD_SetPaused(pause);
+
+#ifdef ONTKEVER
+ printf("pause cd: %d, result: %c\n", pause, result);
+#endif
+}
+
+
+
+void SND_FmodDevice::StopCD() const
+{
+ SND_CDObject* pCD = SND_CDObject::Instance();
+
+ if (pCD)
+ {
+ if (pCD->GetUsed())
+ {
+ signed char result = FSOUND_CD_Stop();
+
+#ifdef ONTKEVER
+ printf("stop cd, result: %c\n", result);
+#endif
+ }
+ }
+}
+
+
+
+void SND_FmodDevice::SetCDPlaymode(int playmode) const
+{
+ FSOUND_CD_SetPlayMode(playmode);
+}
+
+
+
+void SND_FmodDevice::SetCDGain(MT_Scalar gain) const
+{
+ int volume = gain * 255;
+ signed char result = FSOUND_CD_SetVolume(volume);
+
+#ifdef ONTKEVER
+ printf("gain: %f, volume: %d, result: %c\n", gain, volume, result);
+#endif
+}
+
+
+
+void SND_FmodDevice::StartUsingDSP()
+{
+ m_dspunit = FSOUND_DSP_GetFFTUnit();
+
+ FSOUND_DSP_SetActive(m_dspunit, true);
+}
+
+
+
+float* SND_FmodDevice::GetSpectrum()
+{
+ m_spectrum = FSOUND_DSP_GetSpectrum();
+
+ return m_spectrum;
+}
+
+
+
+void SND_FmodDevice::StopUsingDSP()
+{
+ if (m_dspunit)
+ FSOUND_DSP_SetActive(m_dspunit, false);
+} \ No newline at end of file
diff --git a/intern/SoundSystem/fmod/SND_FmodDevice.h b/intern/SoundSystem/fmod/SND_FmodDevice.h
new file mode 100644
index 00000000000..2a8dbcf0b30
--- /dev/null
+++ b/intern/SoundSystem/fmod/SND_FmodDevice.h
@@ -0,0 +1,105 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#ifndef SND_FMODDEVICE
+#define SND_FMODDEVICE
+
+#include "fmod.h"
+#include "SND_AudioDevice.h"
+#include "SoundDefines.h"
+
+class SND_FmodDevice : public SND_AudioDevice
+{
+public:
+ SND_FmodDevice();
+ ~SND_FmodDevice();
+
+ 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();
+ void StopUsingDSP();
+
+private:
+ FSOUND_SAMPLE* m_buffers[NUM_BUFFERS];
+ FSOUND_SAMPLE* m_sources[NUM_SOURCES];
+ FSOUND_DSPUNIT* m_dspunit;
+ int m_frequencies[NUM_SOURCES];
+ int m_max_channels;
+ int m_num_hardware_channels;
+ int m_num_software_channels;
+ int m_channels[NUM_SOURCES];
+ float* m_spectrum;
+};
+
+#endif //SND_FMODDEVICE
diff --git a/intern/SoundSystem/intern/Makefile b/intern/SoundSystem/intern/Makefile
new file mode 100644
index 00000000000..ae5805ad5bc
--- /dev/null
+++ b/intern/SoundSystem/intern/Makefile
@@ -0,0 +1,50 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+LIBNAME = SoundSystem
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_FMOD)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I../../../blender/include
+CPPFLAGS += -I../dummy
+CPPFLAGS += -I../fmod
+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..20800153128
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_AudioDevice.cpp
@@ -0,0 +1,247 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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;
+
+ // first, get the oldest (the first) idobject
+ SND_IdObject* pIdObject = (SND_IdObject*)m_idObjectList.getHead();
+
+ if (pIdObject->isTail())
+ {
+ result = false;
+ }
+ 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 = 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..54a8738e43f
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_AudioDevice.h
@@ -0,0 +1,118 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#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..8a4fc8f31a6
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_C-api.cpp
@@ -0,0 +1,391 @@
+/*
+ * SND_C-Api.cpp
+ *
+ * C Api for soundmodule
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..97b502970b7
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_CDObject.cpp
@@ -0,0 +1,182 @@
+/*
+ * SND_CDObject.cpp
+ *
+ * Implementation for CD playback
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_CDObject.h"
+
+
+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..a3e72f8e9f6
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_DeviceManager.cpp
@@ -0,0 +1,137 @@
+/*
+ * SND_DeviceManager.h
+ *
+ * singleton for creating, switching and deleting audiodevices
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_DeviceManager.h"
+#include "SND_DependKludge.h"
+#include "SND_DummyDevice.h"
+#ifdef USE_FMOD
+#include "SND_FmodDevice.h"
+#endif
+#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
+# ifdef USE_FMOD
+int SND_DeviceManager::m_device_type = snd_e_fmoddevice;
+# else
+int SND_DeviceManager::m_device_type = snd_e_dummydevice;
+# endif
+#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;
+ }
+}
+
+
+
+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_FMOD
+ case snd_e_fmoddevice:
+ {
+ m_instance = new SND_FmodDevice();
+ m_device_type = device_type;
+ break;
+ }
+#endif
+#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..b7e13cacbe6
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_IdObject.cpp
@@ -0,0 +1,75 @@
+/*
+ * SND_IdObject.cpp
+ *
+ * Object for storing runtime data, like id's, soundobjects etc
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_IdObject.h"
+
+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..116479eb69a
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_IdObject.h
@@ -0,0 +1,59 @@
+/*
+ * SND_IdObject.h
+ *
+ * Object for storing runtime data, like id's, soundobjects etc
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#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..5bc65f02359
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_Scene.cpp
@@ -0,0 +1,569 @@
+/*
+* SND_Scene.cpp
+*
+* The scene for sounds.
+*
+* $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.
+ *
+ * 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 *****
+*/
+
+#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 "SYS_System.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()
+{
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0);
+
+ if ((audio == 0) && 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());
+
+ // fmod doesn't support dopplervelocity, so just use the dopplerfactor instead
+#ifdef USE_FMOD
+ m_audiodevice->SetDopplerFactor(m_listener.GetDopplerVelocity());
+#else
+ m_audiodevice->SetDopplerVelocity(m_listener.GetDopplerVelocity());
+ m_audiodevice->SetDopplerFactor(m_listener.GetDopplerFactor());
+#endif
+ 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)
+ {
+ bool juststartedplaying = false;
+#ifdef USE_FMOD
+ // fmod wants these set before playing the sample
+ if (pObject->IsModified())
+ {
+ m_audiodevice->SetObjectLoop(id, pObject->GetLoopMode());
+ m_audiodevice->SetObjectLoopPoints(id, pObject->GetLoopStart(), pObject->GetLoopEnd());
+ }
+
+ // ok, properties Set. now see if it must play
+ if (pObject->GetPlaystate() == SND_MUST_PLAY)
+ {
+ m_audiodevice->PlayObject(id);
+ pObject->SetPlaystate(SND_PLAYING);
+ pObject->InitRunning();
+// printf("start play: %d\n", tijd);
+ juststartedplaying = true;
+ }
+#endif
+ 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
+ if (pObject->GetPlaystate() == SND_MUST_PLAY)
+ {
+ m_audiodevice->PlayObject(id);
+ pObject->SetPlaystate(SND_PLAYING);
+ //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 && (!juststartedplaying) && !pObject->GetLoopMode() && pObject->IsRunning())
+#ifdef WIN32
+ if ((playstate == SND_STOPPED) && !pObject->GetLoopMode())
+#else
+ if (!pObject->GetLoopMode())
+#endif
+ {
+// printf("remove: %d\n", tijd);
+ 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..281da2aa7fb
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_SoundListener.cpp
@@ -0,0 +1,184 @@
+/*
+ * SND_SoundListener.cpp
+ *
+ * A SoundListener is for sound what a camera is for vision.
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_SoundListener.h"
+
+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..69066d0a2dd
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_SoundObject.cpp
@@ -0,0 +1,506 @@
+/*
+ * SND_SoundObject.cpp
+ *
+ * Implementation of the abstract sound object
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_SoundObject.h"
+
+
+
+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()
+{
+ m_playstate = SND_MUST_PLAY;
+}
+
+
+
+void SND_SoundObject::StopSound()
+{
+ m_playstate = SND_MUST_STOP;
+}
+
+
+
+void SND_SoundObject::PauseSound()
+{
+ 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..3965c534cd3
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_Utils.cpp
@@ -0,0 +1,395 @@
+/*
+ * SND_Utils.cpp
+ *
+ * Util functions for soundthingies
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "SND_Utils.h"
+#include "SoundDefines.h"
+#include "SND_DependKludge.h"
+/*
+extern "C" {
+#include "license_key.h"
+}
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include <string.h>
+
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+//extern int LICENSE_KEY_VALID;
+#define LICENSE_KEY_VALID true
+
+#define BUFFERSIZE 32
+
+/* 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)))
+ {
+ int shortbuf = * ((short *) &buffer[20]);
+ if (shortbuf == SND_WAVE_FORMAT_PCM)
+ result = true;
+
+ /* only fmod supports compressed wav */
+#ifdef USE_FMOD
+ /* and only valid publishers may use compressed wav */
+ if (LICENSE_KEY_VALID)
+ {
+ switch (shortbuf)
+ {
+ case SND_WAVE_FORMAT_ADPCM:
+ case SND_WAVE_FORMAT_ALAW:
+ case SND_WAVE_FORMAT_MULAW:
+ case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
+ case SND_WAVE_FORMAT_CONTROL_RES_VQLPC:
+ case SND_WAVE_FORMAT_GSM_610:
+ case SND_WAVE_FORMAT_MPEG3:
+ result = true;
+ break;
+ default:
+ {
+ break;
+ }
+ }
+ }
+#endif
+ }
+#ifdef USE_FMOD
+ /* only valid publishers may use ogg vorbis */
+ else if (!memcmp(buffer, "OggS", 4) && LICENSE_KEY_VALID)
+ {
+ result = true;
+ }
+ /* only valid publishers may use mp3 */
+ else if (((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "ÿû", 2))) && LICENSE_KEY_VALID)
+ {
+ result = true;
+ }
+#endif
+ }
+ if (loadedsample)
+ {
+ free(memlocation);
+ memlocation = NULL;
+ }
+
+ return result;
+}
+
+
+
+/* checks if the passed pointer is a valid sample */
+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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ return (unsigned int)bitrate;
+}
+
+
+
+/* gets the length of the actual sample data (without the header) */
+unsigned int SND_GetNumberOfSamples(void* sample)
+{
+ unsigned int chunklength, length = 0, 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 "data"
+ while (memcmp(data, "data", 4))
+ {
+ offset += 4;
+ memcpy(data, ((char*)sample) + offset, 4);
+ }
+ offset += 4;
+ memcpy(&length, ((char*)sample) + offset, 4);
+ }
+
+ return length;
+}
+
+
+
+/* gets the size of the entire header (file - sampledata) */
+unsigned int SND_GetHeaderSize(void* sample)
+{
+ unsigned int chunklength, headersize = 0, 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 "data"
+ while (memcmp(data, "data", 4))
+ {
+ offset += 4;
+ memcpy(data, ((char*)sample) + offset, 4);
+ }
+ 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));
+ 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..279bc29aa83
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_WaveCache.cpp
@@ -0,0 +1,134 @@
+/*
+ * SND_WaveCache.cpp
+ *
+ * abstract wavecache, a way to organize samples
+ *
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifdef WIN32
+#pragma warning (disable:4786) // Get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "SND_WaveCache.h"
+#include <stdio.h>
+
+#ifndef __APPLE__
+#include <malloc.h>
+#else // __APPLE__
+#include <sys/malloc.h>
+#endif // __APPLE__
+
+
+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..51356bba4bf
--- /dev/null
+++ b/intern/SoundSystem/intern/SND_WaveSlot.cpp
@@ -0,0 +1,182 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#include "SND_WaveSlot.h"
+
+
+
+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/openal/Makefile b/intern/SoundSystem/openal/Makefile
new file mode 100644
index 00000000000..277332abde6
--- /dev/null
+++ b/intern/SoundSystem/openal/Makefile
@@ -0,0 +1,47 @@
+#
+# $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.
+#
+# 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 *****
+#
+#
+
+LIBNAME = OpenALSoundSystem
+DIR = $(OCGDIR)/gameengine/$(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../../../kernel/gen_system
+CPPFLAGS += -I../intern
+CPPFLAGS += -I..
+CPPFLAGS += -I.
diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp
new file mode 100644
index 00000000000..a5cbf8d3300
--- /dev/null
+++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp
@@ -0,0 +1,661 @@
+/*
+ * $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.
+ *
+ * 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 *****
+ * 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"
+#include "SoundDefines.h"
+#include "SYS_System.h"
+
+#include "SND_Utils.h"
+
+#include <AL/al.h>
+#include <AL/alc.h>
+#include <AL/alut.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+/* untill openal gets unified we need this hack for non-windows systems */
+#ifndef WIN32
+
+#include <malloc.h>
+
+ALvoid alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop);
+ALvoid alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq);
+
+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;
+
+ALvoid alutLoadWAVMemory(ALbyte *memory,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;
+
+ *format=AL_FORMAT_MONO16;
+ *data=NULL;
+ *size=0;
+ *freq=22050;
+ *loop=AL_FALSE;
+ if (memory)
+ {
+ Stream=memory;
+ if (Stream)
+ {
+ memcpy(&FileHdr,Stream,sizeof(WAVFileHdr_Struct));
+ Stream+=sizeof(WAVFileHdr_Struct);
+ FileHdr.Size=((FileHdr.Size+1)&~1)-4;
+ while ((FileHdr.Size!=0)&&(memcpy(&ChunkHdr,Stream,sizeof(WAVChunkHdr_Struct))))
+ {
+ Stream+=sizeof(WAVChunkHdr_Struct);
+ if (!memcmp(ChunkHdr.Id,"fmt ",4))
+ {
+ memcpy(&FmtHdr,Stream,sizeof(WAVFmtHdr_Struct));
+ 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;
+ Stream+=ChunkHdr.Size;
+ }
+ else
+ {
+ memcpy(&FmtExHdr,Stream,sizeof(WAVFmtExHdr_Struct));
+ Stream+=ChunkHdr.Size;
+ }
+ }
+ else if (!memcmp(ChunkHdr.Id,"data",4))
+ {
+ if (FmtHdr.Format==0x0001)
+ {
+ *size=ChunkHdr.Size;
+ *data=malloc(ChunkHdr.Size+31);
+ if (*data) memcpy(*data,Stream,ChunkHdr.Size);
+ memset(((char *)*data)+ChunkHdr.Size,0,31);
+ Stream+=ChunkHdr.Size;
+ }
+ else if (FmtHdr.Format==0x0011)
+ {
+ //IMA ADPCM
+ }
+ else if (FmtHdr.Format==0x0055)
+ {
+ //MP3 WAVE
+ }
+ }
+ else if (!memcmp(ChunkHdr.Id,"smpl",4))
+ {
+ memcpy(&SmplHdr,Stream,sizeof(WAVSmplHdr_Struct));
+ *loop = (SmplHdr.Loops ? AL_TRUE : AL_FALSE);
+ Stream+=ChunkHdr.Size;
+ }
+ else Stream+=ChunkHdr.Size;
+ Stream+=ChunkHdr.Size&1;
+ FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8);
+ }
+ }
+ }
+}
+
+ALvoid alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
+{
+ if (data)
+ free(data);
+}
+
+#endif /* WIN32 */
+
+
+
+SND_OpenALDevice::SND_OpenALDevice()
+{
+ // check if audio is wanted
+ SYS_SystemHandle syshandle = SYS_GetSystem();
+ int audio = SYS_GetCommandLineInt(syshandle,"noaudio",0);
+
+ if (audio != 0)
+ m_audio = false;
+ else
+ m_audio = true;
+
+ m_buffersinitialized = false;
+ m_sourcesinitialized = false;
+
+ // let's check if we can get openal to initialize...
+ if (m_audio)
+ {
+#ifdef OUDE_OPENAL
+ m_audio = true; // openal_2.12
+ alutInit(NULL, NULL); // openal_2.12
+#else
+ m_audio = false;
+
+ ALCdevice *dev = alcOpenDevice(NULL);
+ if (dev) {
+ m_context = alcCreateContext(dev, NULL);
+
+ if (m_context) {
+ alcMakeContextCurrent(m_context);
+ m_audio = true;
+ }
+ }
+
+#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 OUDE_OPENAL
+ ALenum alc_error = ALC_NO_ERROR; // openal_2.12
+#else
+ ALenum alc_error = alcGetError(); // openal_2.14+
+#endif
+
+ // let openal generate its sources
+ if (alc_error == ALC_NO_ERROR)
+ {
+ alGenSources(NUM_SOURCES, m_sources);
+ m_sourcesinitialized = true;
+ }
+ }
+
+ // let's get us a wavecache
+ if (m_audio)
+ {
+ m_wavecache = new SND_WaveCache();
+ }
+}
+
+
+
+void SND_OpenALDevice::MakeCurrent() const
+{
+#ifdef WIN32
+ alcMakeContextCurrent(m_context);
+#endif
+}
+
+
+
+SND_OpenALDevice::~SND_OpenALDevice()
+{
+ if (m_context) {
+ alcMakeContextCurrent(m_context);
+
+ if (m_buffersinitialized)
+ alDeleteBuffers(NUM_BUFFERS, m_buffers);
+
+ if (m_sourcesinitialized)
+ alDeleteSources(NUM_SOURCES, m_sources);
+ }
+}
+
+
+
+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)
+ {
+ int buffer = waveslot->GetBuffer();
+ void* data = NULL;
+ char loop = 'a';
+ int sampleformat, bitrate, numberofchannels;
+ ALenum al_error = alGetError();
+
+#ifdef OUDE_OPENAL
+ unsigned int samplerate, numberofsamples; // openal_2.12
+#else
+ int samplerate, numberofsamples, frequency; // openal_2.14+
+#endif
+
+ /* 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 */
+#ifdef OUDE_OPENAL
+ alutLoadWAVMemory((char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate); // openal_2.12
+#else
+ alutLoadWAVMemory((signed char*)memlocation, &sampleformat, &data, &numberofsamples, &samplerate, &loop);// openal_2.14+
+#endif
+ /* put it in the buffer */
+ alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate);
+ }
+ /* or from file? */
+ else
+ {
+#ifdef WIN32
+ alutLoadWAVFile((signed char*)samplename.Ptr(), &sampleformat, &data, &numberofsamples, &samplerate, &loop);
+#else
+ alutLoadWAV((char*)samplename.Ptr(), &data,
+ &sampleformat, &numberofsamples,
+ &samplerate, &frequency);
+#endif
+ /* put it in the buffer */
+ alBufferData(m_buffers[buffer], sampleformat, data, numberofsamples, samplerate);
+ }
+
+ /* 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) */
+ 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
+{
+ // 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};
+#ifdef WIN32
+ float lisori[6] = {0,1,0,0,0,1};
+#else
+ float lisori[6] = {0,0,1,0,-1,0};
+#endif
+
+ 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;
+
+ alGetSourceiv(m_sources[id], AL_SOURCE_STATE, &alstate);
+
+ 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);
+
+#ifdef WIN32
+ alSourcefv(m_sources[id], AL_VELOCITY, obvel);
+#endif
+
+ 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::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);
+
+#ifdef WIN32
+ velocity.getValue(obvel);
+ alSourcefv(m_sources[id], AL_VELOCITY, obvel);
+#endif
+
+}
diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.h b/intern/SoundSystem/openal/SND_OpenALDevice.h
new file mode 100644
index 00000000000..95940bacde2
--- /dev/null
+++ b/intern/SoundSystem/openal/SND_OpenALDevice.h
@@ -0,0 +1,102 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+#ifndef SND_OPENALDEVICE
+#define SND_OPENALDEVICE
+
+#include "SND_AudioDevice.h"
+#include "SoundDefines.h"
+
+class SND_OpenALDevice : public SND_AudioDevice
+{
+public:
+ SND_OpenALDevice();
+ ~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 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;
+
+ unsigned int m_buffers[NUM_BUFFERS];
+ unsigned int m_sources[NUM_SOURCES];
+ bool m_buffersinitialized;
+ bool m_sourcesinitialized;
+};
+
+#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..de05c742dea
--- /dev/null
+++ b/intern/SoundSystem/openal/pthread_cancel.cpp
@@ -0,0 +1,65 @@
+/* $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.
+ *
+ * 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 *****
+ * FreeBSD 3.4 does not yet have pthread_cancel (3.5 and above do)
+ */
+#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/action/ACT_Action.h b/intern/action/ACT_Action.h
new file mode 100644
index 00000000000..2b54d10359e
--- /dev/null
+++ b/intern/action/ACT_Action.h
@@ -0,0 +1,140 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#ifndef _H_ACT_ACTION_H_
+#define _H_ACT_ACTION_H_
+
+#include "MEM_RefCounted.h"
+#include "STR_String.h"
+
+/**
+ * An action that can be applied or undone.
+ * Virtual base class for actions with a name.
+ * An action object inherits the shared object reference count mechanism.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+class ACT_Action : public MEM_RefCounted {
+public:
+ /**
+ * Constructs an action with the given name .
+ * @param name the name of the action.
+ * @param applied state of the action after creation.
+ */
+ ACT_Action(const STR_String& name, bool applied = false);
+
+ /**
+ * Returns the name of the action.
+ * @param name the name of the action.
+ */
+ inline virtual void getName(STR_String& name) const;
+
+ /**
+ * Returns the name of the action as a pointer to the data of the string.
+ * @return pointer to the name of the action.
+ */
+ inline virtual char* getName();
+
+ /**
+ * Sets the name of the action.
+ * @param name the name of the action.
+ */
+ inline virtual void setName(const STR_String& name);
+
+ /**
+ * Returns whether this action is applied.
+ * @return whether this action is applied.
+ */
+ inline virtual bool getIsApplied() const;
+
+
+ /**
+ * Call this member to apply an action.
+ * Child classes should override the doApply member to implement apply functionality.
+ * @see doApply.
+ */
+ virtual void apply();
+
+ /**
+ * Call this member to undo an action .
+ * Child classes should override the doUndo member to implement undo functionality.
+ * @see doApply()
+ */
+ virtual void undo();
+
+protected:
+ /**
+ * Implementations should overload this method to provide the apply functionality.
+ */
+ virtual void doApply() = 0;
+
+ /**
+ * Implementations should overload this method to provide the undo functionality.
+ */
+ virtual void doUndo() = 0;
+
+ /** Name of this action */
+ STR_String m_name;
+ /** Is this action already applied? */
+ bool m_applied;
+};
+
+
+void ACT_Action::getName(STR_String& name) const
+{
+ name = m_name;
+}
+
+char* ACT_Action::getName()
+{
+ return m_name.Ptr();
+}
+
+void ACT_Action::setName(const STR_String& name)
+{
+ m_name = name;
+}
+
+inline bool ACT_Action::getIsApplied() const
+{
+ return m_applied;
+}
+
+#endif // _H_ACT_ACTION_H_ \ No newline at end of file
diff --git a/intern/action/ACT_ActionC-Api.h b/intern/action/ACT_ActionC-Api.h
new file mode 100644
index 00000000000..ebc1ce7d5a0
--- /dev/null
+++ b/intern/action/ACT_ActionC-Api.h
@@ -0,0 +1,192 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Interface for C access to actions.
+ * @author Maarten Gribnau
+ * @date April, 25, 2001
+ */
+
+#ifndef _H_ACT_ACTION_C_API
+#define _H_ACT_ACTION_C_API
+
+#include "MEM_RefCountedC-Api.h"
+
+/** A pointer to an action object. */
+typedef MEM_TRefCountedObjectPtr ACT_ActionPtr;
+/** A pointer to an action stack object. */
+typedef MEM_TObjectPtr ACT_ActionStackPtr;
+
+
+/** A pointer to user data passed by the callbacks. */
+typedef void* ACT_ActionUserDataPtr;
+
+/**
+ * An action apply callback routine.
+ * @param action The action that should be applied.
+ * @param userData The pointer to the user data provided when the action was created.
+ */
+typedef void (*ACT_ActionApplyProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+
+/**
+ * An action undo callback routine.
+ * @param action The action that should be undone.
+ * @param userData The pointer to the user data provided when the action was created.
+ */
+typedef void (*ACT_ActionUndoProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+
+/**
+ * An action dispose callback routine.
+ * @param action The action that is disposed.
+ * @param userData The pointer to the user data provided when the action was created.
+ */
+typedef void (*ACT_ActionDisposeProcPtr)(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An action is a shared object that can be applied or undone.
+ */
+
+/**
+ * Creates a new action.
+ * This is an action that calls the given callbacks when it needs to be applied or undone.
+ * @param name The name of the action.
+ * @param isApplied Indication as to whether the action is already applied (0 = not applied).
+ * @param userData Pointer passed to the apply/undo callbacks.
+ * @param applyProc Pointer to the callback invoked when the action needs to be applied.
+ * @param undoProc Pointer to the callback invoked when the action needs to be undone.
+ * @return The new action (null in case of error).
+ */
+extern ACT_ActionPtr ACT_ActionCreate(
+ char* name,
+ int isApplied,
+ ACT_ActionUserDataPtr userData,
+ ACT_ActionApplyProcPtr applyProc,
+ ACT_ActionUndoProcPtr undoProc,
+ ACT_ActionDisposeProcPtr disposeProc);
+
+/**
+ * Returns the name of an action.
+ * @return The name of the action (null in case of error).
+ */
+extern char* ACT_ActionGetName(ACT_ActionPtr action);
+
+
+
+/**
+ * An action stack stores actions and implements undo/redo functionality.
+ */
+
+/**
+ * Creates a new action stack.
+ * @param stackSize The maximum number of actions on the stack.
+ * @return The new stack (or NULL in case of error).
+ */
+extern ACT_ActionStackPtr ACT_ActionStackCreate(unsigned int stackSize);
+
+/**
+ * Disposes an action stack.
+ * @param stack The appropriate stack.
+ */
+extern void ACT_ActionStackDispose(ACT_ActionStackPtr stack);
+
+/**
+ * Returns the current depth of the stack.
+ * @param stack The appropriate stack.
+ * @return the current stack depth.
+ */
+extern unsigned int ACT_ActionStackGetStackDepth(ACT_ActionStackPtr stack);
+
+/**
+ * Returns the current maximum depth of the stack.
+ * @param stack The appropriate stack.
+ * @return the maximum stack depth.
+ */
+extern unsigned int ACT_ActionStackGetMaxStackDepth(ACT_ActionStackPtr stack);
+
+/**
+ * Sets new maximum depth of the stack.
+ * @param stack The appropriate stack.
+ * @param maxStackDepth The new stack depth.
+ */
+extern void ACT_ActionStackSetMaxStackDepth(ACT_ActionStackPtr stack, unsigned int maxStackDepth);
+
+/**
+ * Pushes an action on the stack.
+ * If the action has not been applied yet, it will be applied here.
+ * This will increase the reference count of the action.
+ * If there is not enough capacity, the action at the bottom of the stack is removed (and its reference count decreased).
+ * @param stack The appropriate stack.
+ * @param action the action that is pushed onto the stack.
+ */
+extern void ACT_ActionStackPush(ACT_ActionStackPtr stack, ACT_ActionPtr action);
+
+/**
+ * Returns pointer to the current undo item.
+ * @param stack The appropriate stack.
+ * @return The action scheduled for undo (0 if there is none).
+ */
+extern ACT_ActionStackPtr ACT_ActionStackPeekUndo(ACT_ActionStackPtr stack);
+
+/**
+ * Returns pointer to the current redo item.
+ * @param stack The appropriate stack.
+ * @return The action scheduled for redo (0 if there is none).
+ */
+extern ACT_ActionStackPtr ACT_ActionStackPeekRedo(ACT_ActionStackPtr stack);
+
+/**
+ * Undos the current action.
+ * @param stack The appropriate stack.
+ * This will move the current undo index down (if the stack depth allows it).
+ */
+extern void ACT_ActionStackUndo(ACT_ActionStackPtr stack);
+
+/**
+ * Redos the current action.
+ * @param stack The appropriate stack.
+ * This will move the action index up (if the stack depth allows it).
+ */
+extern void ACT_ActionStackRedo(ACT_ActionStackPtr stack);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _H_ACT_ACTION_C_API \ No newline at end of file
diff --git a/intern/action/ACT_ActionStack.h b/intern/action/ACT_ActionStack.h
new file mode 100644
index 00000000000..13db963020e
--- /dev/null
+++ b/intern/action/ACT_ActionStack.h
@@ -0,0 +1,184 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#ifndef _H_ACT_ACTIONSTACK
+#define _H_ACT_ACTIONSTACK
+
+#include "ACT_Action.h"
+#include <deque>
+
+
+/**
+ * A stack with actions that implements undo/redo capabilities.
+ * A stack can grow to a maximum number of actions by pushing actions on the stack.
+ * By calling undo and redo the apply and undo members of the actions on the stack are called.
+ * In addition, this will move the stackIndex up and down the stack.
+ * When a new action is pushed onto the stack, the actions above the current action are removed from the stack.
+ * Actions pushed onto the stack are applied if they are not applied already.
+ * @todo implement error handling (e.g. memory errors)
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+class ACT_ActionStack {
+public:
+ /**
+ * Constructs an action stack.
+ */
+ ACT_ActionStack(unsigned int maxStackDepth = 1);
+
+ /**
+ * Destructs an action stack.
+ */
+ virtual ~ACT_ActionStack();
+
+ /**
+ * Returns the current depth of the stack.
+ * @return the current stack depth.
+ */
+ virtual unsigned int getStackDepth() const;
+
+ /**
+ * Returns the current maximum depth of the stack.
+ * @return the maximum stack depth.
+ */
+ virtual unsigned int getMaxStackDepth() const;
+
+ /**
+ * Sets new maximum depth of the stack.
+ * @param maxStackDepth The new stack depth.
+ */
+ virtual void setMaxStackDepth(unsigned int maxStackDepth);
+
+ /**
+ * Pushes an action on the stack.
+ * If the action has not been applied yet, it will be applied here.
+ * This will increase the reference count of the action.
+ * If there is not enough capacity, the action at the bottom of the stack is removed (and its reference count decreased).
+ * @param action the action that is pushed onto the stack.
+ */
+ virtual void push(ACT_Action& action);
+
+ /**
+ * Returns pointer to the current undo item.
+ * @return The action scheduled for undo (0 if there is none).
+ */
+ virtual ACT_Action* peekUndo();
+
+ /**
+ * Returns pointer to the current redo item.
+ * @return The action scheduled for redo (0 if there is none).
+ */
+ virtual ACT_Action* peekRedo();
+
+ /**
+ * Flushes the action stack.
+ * All actions are removed from the stack and their reference counts decreased.
+ */
+ virtual void flush();
+
+ /**
+ * Returns whether we can undo the current action.
+ * @return Indication of the possibility to undo.
+ */
+ virtual bool canUndo() const;
+
+ /**
+ * Undos the current action.
+ * This will move the current undo index down (if the stack depth allows it).
+ */
+ virtual void undo();
+
+ /**
+ * Returns whether we can redo the current action.
+ * @return Indication of the possibility to redo.
+ */
+ virtual bool canRedo() const;
+
+ /**
+ * Redos the current action.
+ * This will move the action index up (if the stack depth allows it).
+ */
+ virtual void redo();
+
+protected:
+ /**
+ * Removes <i>numActions</i> actions from the back of the stack.
+ * @param numActions number of items to remove.
+ * @return the number of actions removed.
+ */
+ virtual unsigned int popBack(unsigned int numActions = 1);
+
+ /**
+ * Removes <i>numActions</i> actions from the front of the stack.
+ * @param numActions number of items to remove.
+ * @return the number of actions removed.
+ */
+ virtual unsigned int popFront(unsigned int numActions = 1);
+
+ /**
+ * Returns the index of the current undo action.
+ * @param index The index of the action.
+ * @return Indication as to whether the index is valid (==true).
+ */
+ virtual bool getUndoIndex(unsigned int& index) const;
+
+ /**
+ * Returns the index of the current redo action.
+ * @param index The index of the action.
+ * @return Indication as to whether the index is valid (==true).
+ */
+ virtual bool getRedoIndex(unsigned int& index) const;
+
+ /** The maximum depth of this stack. */
+ unsigned int m_maxStackDepth;
+ /** The index of the current undo action in the stack. */
+ unsigned int m_undoIndex;
+ /** Is the index of the current undo action in the stack valid? */
+ bool m_undoIndexValid;
+ /** The index of the current redo action in the stack. */
+ unsigned int m_redoIndex;
+ /** Is the index of the current redo action in the stack valid? */
+ bool m_redoIndexValid;
+ /** The stack with actions. */
+ deque<ACT_Action*> m_stack;
+};
+
+
+#endif // _H_ACT_ACTIONSTACK \ No newline at end of file
diff --git a/intern/action/Makefile b/intern/action/Makefile
new file mode 100644
index 00000000000..dd5301c034e
--- /dev/null
+++ b/intern/action/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# action main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = action
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_ACTION) ] || mkdir $(NAN_ACTION)
+ @[ -d $(NAN_ACTION)/include ] || mkdir $(NAN_ACTION)/include
+ @[ -d $(NAN_ACTION)/lib ] || mkdir $(NAN_ACTION)/lib
+ @[ -d $(NAN_ACTION)/lib/debug ] || mkdir $(NAN_ACTION)/lib/debug
+ cp -f $(DIR)/libaction.a $(NAN_ACTION)/lib/
+ cp -f $(DIR)/debug/libaction.a $(NAN_ACTION)/lib/debug/
+ cp -f *.h $(NAN_ACTION)/include/
+
diff --git a/intern/action/doc/Doxyfile b/intern/action/doc/Doxyfile
new file mode 100644
index 00000000000..2cc9de2d97c
--- /dev/null
+++ b/intern/action/doc/Doxyfile
@@ -0,0 +1,746 @@
+# Doxyfile 1.2.4
+
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+PROJECT_NAME = foundation
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
+# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
+# Polish, Portuguese and Slovene.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a class diagram (in Html and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off.
+
+CLASS_DIAGRAMS = YES
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The ENABLE_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../extern ../intern
+
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+FILE_PATTERNS = *.h *.cpp *.c
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Netscape 4.0+
+# or Internet explorer 4.0+).
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using a WORD or other.
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Warning: This feature
+# is still experimental and very incomplete.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH = ../../generic/extern
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other
+# documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented header file showing
+# the documented files that directly or indirectly include this file
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = c:\program files\doxygen\bin
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/intern/action/intern/ACT_Action.cpp b/intern/action/intern/ACT_Action.cpp
new file mode 100644
index 00000000000..ff3c01d146d
--- /dev/null
+++ b/intern/action/intern/ACT_Action.cpp
@@ -0,0 +1,64 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date April, 25, 2001
+ */
+
+#include "ACT_Action.h"
+
+
+ACT_Action::ACT_Action(const STR_String& name, bool applied)
+: m_name(name), m_applied(applied)
+{
+}
+
+
+void ACT_Action::apply()
+{
+ if (!m_applied) {
+ doApply();
+ m_applied = true;
+ }
+}
+
+
+void ACT_Action::undo()
+{
+ if (m_applied) {
+ doUndo();
+ m_applied = false;
+ }
+}
diff --git a/intern/action/intern/ACT_ActionC-Api.cpp b/intern/action/intern/ACT_ActionC-Api.cpp
new file mode 100644
index 00000000000..1c2defa333a
--- /dev/null
+++ b/intern/action/intern/ACT_ActionC-Api.cpp
@@ -0,0 +1,130 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date April, 25, 2001
+ */
+
+#include "ACT_ActionC-Api.h"
+
+#include "ACT_ActionStack.h"
+#include "ACT_CallbackAction.h"
+
+
+ACT_ActionPtr ACT_ActionCreate(
+ char* name,
+ int isApplied,
+ ACT_ActionUserDataPtr data,
+ ACT_ActionApplyProcPtr applyProc,
+ ACT_ActionUndoProcPtr undoProc,
+ ACT_ActionDisposeProcPtr disposeProc)
+{
+ STR_String tmp (name);
+ ACT_CallbackAction* action = new ACT_CallbackAction(tmp, isApplied != 0, data, applyProc, undoProc, disposeProc);
+ return (ACT_ActionPtr) action;
+}
+
+
+char* ACT_ActionGetName(ACT_ActionPtr action)
+{
+ return action ? ((ACT_Action*)action)->getName() : 0;
+}
+
+
+ACT_ActionStackPtr ACT_ActionStackCreate(unsigned int stackSize)
+{
+ return ((ACT_ActionStackPtr) (new ACT_ActionStack (stackSize)));
+}
+
+
+void ACT_ActionStackDispose(ACT_ActionStackPtr stack)
+{
+ if (stack) {
+ delete (ACT_ActionStack*) stack;
+ }
+}
+
+
+unsigned int ACT_ActionStackGetStackDepth(ACT_ActionStackPtr stack)
+{
+ return stack ? ((ACT_ActionStack*)stack)->getStackDepth() : 0;
+}
+
+unsigned int ACT_ActionStackGetMaxStackDepth(ACT_ActionStackPtr stack)
+{
+ return stack ? ((ACT_ActionStack*)stack)->getMaxStackDepth() : 0;
+}
+
+void ACT_ActionStackSetMaxStackDepth(ACT_ActionStackPtr stack, unsigned int maxStackDepth)
+{
+ if (stack) {
+ ((ACT_ActionStack*)stack)->setMaxStackDepth(maxStackDepth);
+ }
+}
+
+void ACT_ActionStackPush(ACT_ActionStackPtr stack, ACT_ActionPtr action)
+{
+ if (stack && action) {
+ ((ACT_ActionStack*)stack)->push(*((ACT_Action*)action));
+ }
+}
+
+
+ACT_ActionStackPtr ACT_ActionStackPeekUndo(ACT_ActionStackPtr stack)
+{
+ return (ACT_ActionStackPtr) (stack ? ((ACT_ActionStack*)stack)->peekUndo() : 0);
+}
+
+
+ACT_ActionStackPtr ACT_ActionStackPeekRedo(ACT_ActionStackPtr stack)
+{
+ return (ACT_ActionStackPtr) (stack ? ((ACT_ActionStack*)stack)->peekRedo() : 0);
+}
+
+
+void ACT_ActionStackUndo(ACT_ActionStackPtr stack)
+{
+ if (stack) {
+ ((ACT_ActionStack*)stack)->undo();
+ }
+}
+
+
+void ACT_ActionStackRedo(ACT_ActionStackPtr stack)
+{
+ if (stack) {
+ ((ACT_ActionStack*)stack)->redo();
+ }
+}
diff --git a/intern/action/intern/ACT_ActionStack.cpp b/intern/action/intern/ACT_ActionStack.cpp
new file mode 100644
index 00000000000..569babd95f2
--- /dev/null
+++ b/intern/action/intern/ACT_ActionStack.cpp
@@ -0,0 +1,241 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#include "ACT_ActionStack.h"
+
+
+ACT_ActionStack::ACT_ActionStack(unsigned int maxStackDepth)
+ : m_maxStackDepth(maxStackDepth),
+ m_undoIndex(0), m_undoIndexValid(false),
+ m_redoIndex(0), m_redoIndexValid(false)
+{
+}
+
+
+ACT_ActionStack::~ACT_ActionStack()
+{
+ flush();
+}
+
+
+unsigned int ACT_ActionStack::getStackDepth() const
+{
+ return m_stack.size();
+}
+
+
+unsigned int ACT_ActionStack::getMaxStackDepth() const
+{
+ return m_maxStackDepth;
+}
+
+
+void ACT_ActionStack::setMaxStackDepth(unsigned int maxStackDepth)
+{
+ if (maxStackDepth != m_maxStackDepth) {
+ if (maxStackDepth) {
+ unsigned int size = m_stack.size();
+ if (maxStackDepth < size) {
+ // New max stack size is smaller than current stack size, need to shrink stack
+ unsigned int numRemove = size - maxStackDepth;
+ if (m_undoIndex >= maxStackDepth) {
+ // Pop items from the front (throw away undo steps)
+ popFront(numRemove);
+ m_undoIndex -= numRemove;
+ m_redoIndex = m_undoIndex + 1;
+ m_redoIndexValid = m_redoIndexValid && (maxStackDepth > 1);
+ }
+ else {
+ // Pop items from the back (throw away redo steps)
+ popBack(numRemove);
+ m_redoIndexValid = m_redoIndexValid && (m_redoIndex < maxStackDepth);
+ }
+ }
+ }
+ else {
+ // New stack size is zero
+ flush();
+ }
+ m_maxStackDepth = maxStackDepth;
+ }
+}
+
+
+void ACT_ActionStack::push(ACT_Action& action)
+{
+ if (m_maxStackDepth) {
+ unsigned int size = m_stack.size();
+ if (m_redoIndexValid) {
+ // Remove items after the current action (throw away redo steps)
+ popBack(size - m_redoIndex);
+ }
+ else if (size >= m_maxStackDepth) {
+ // Remove items from the front (throw away undo steps)
+ popFront(m_maxStackDepth - size + 1);
+ }
+
+ // Store the action
+ if (!action.getIsApplied()) {
+ action.apply();
+ }
+ action.incRef();
+ m_stack.push_back(&action);
+
+ // Update action indices
+ m_redoIndex = m_stack.size();
+ m_redoIndexValid = false;
+ m_undoIndex = m_redoIndex - 1;
+ m_undoIndexValid = true;
+ }
+}
+
+
+ACT_Action* ACT_ActionStack::peekUndo()
+{
+ unsigned int i;
+ return getUndoIndex(i) ? m_stack[i] : 0;
+}
+
+
+ACT_Action* ACT_ActionStack::peekRedo()
+{
+ unsigned int i;
+ return getRedoIndex(i) ? m_stack[i] : 0;
+}
+
+
+void ACT_ActionStack::flush()
+{
+ popBack(m_stack.size());
+ m_undoIndex = 0;
+ m_undoIndexValid = false;
+ m_redoIndex = 0;
+ m_redoIndexValid = false;
+}
+
+
+bool ACT_ActionStack::canUndo() const
+{
+ unsigned int i;
+ return getUndoIndex(i);
+}
+
+
+void ACT_ActionStack::undo()
+{
+ ACT_Action* action = peekUndo();
+ if (action) {
+ action->undo();
+
+ // Update action indices
+ m_redoIndex = m_undoIndex;
+ m_redoIndexValid = true;
+ if (m_undoIndex) {
+ m_undoIndex--;
+ }
+ else {
+ m_undoIndexValid = false;
+ }
+ }
+}
+
+
+bool ACT_ActionStack::canRedo() const
+{
+ unsigned int i;
+ return getRedoIndex(i);
+}
+
+
+void ACT_ActionStack::redo()
+{
+ ACT_Action* action = peekRedo();
+ if (action) {
+ action->apply();
+
+ // Update action indices
+ m_undoIndex = m_redoIndex;
+ m_undoIndexValid = true;
+ m_redoIndex++;
+ m_redoIndexValid = m_redoIndex < m_stack.size();
+ }
+}
+
+
+unsigned int ACT_ActionStack::popFront(unsigned int numActions)
+{
+ unsigned int numRemoved = 0;
+
+ while (numActions-- && m_stack.size()) {
+ ACT_Action* action = m_stack[0];
+ action->decRef();
+ m_stack.pop_front();
+ numRemoved++;
+ }
+ return numRemoved;
+}
+
+
+unsigned int ACT_ActionStack::popBack(unsigned int numActions)
+{
+ unsigned int numRemoved = 0;
+ unsigned int size;
+
+ while (numActions-- && (size = m_stack.size())) {
+ ACT_Action* action = m_stack[size-1];
+ action->decRef();
+ m_stack.pop_back();
+ numRemoved++;
+ }
+ return numRemoved;
+}
+
+
+bool ACT_ActionStack::getUndoIndex(unsigned int& i) const
+{
+ i = m_undoIndex;
+ return m_undoIndexValid;
+}
+
+
+bool ACT_ActionStack::getRedoIndex(unsigned int& i) const
+{
+ i = m_redoIndex;
+ return m_redoIndexValid;
+}
diff --git a/intern/action/intern/ACT_CallbackAction.h b/intern/action/intern/ACT_CallbackAction.h
new file mode 100644
index 00000000000..e03e4048808
--- /dev/null
+++ b/intern/action/intern/ACT_CallbackAction.h
@@ -0,0 +1,124 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date June 17, 2001
+ */
+
+#ifndef _H_ACT_CALLBACK_ACTION_H
+#define _H_ACT_CALLBACK_ACTION_H
+
+#include "ACT_Action.h"
+#include "ACT_ActionC-Api.h"
+
+
+/**
+ * An action implementation that uses callbacks for undo and redo.
+ * @author Maarten Gribnau
+ * @date June 17, 2001
+ */
+
+class ACT_CallbackAction : public ACT_Action {
+public:
+ /**
+ * Constructs an action with the given name .
+ * @param name The name of the action.
+ * @param applied State of the action after creation.
+ * @param data Pointer to user data passed to the callbacks.
+ * @param applyProc Callback invoked for apply action.
+ * @param undoProc Callback invoked for undo action.
+ */
+ ACT_CallbackAction(
+ STR_String& name,
+ bool applied,
+ ACT_ActionUserDataPtr data,
+ ACT_ActionApplyProcPtr applyProc,
+ ACT_ActionUndoProcPtr undoProc,
+ ACT_ActionDisposeProcPtr disposeProc)
+ : ACT_Action(name, applied), m_userData(data), m_applyProc(applyProc), m_undoProc(undoProc), m_disposeProc(disposeProc)
+ {
+ }
+
+ /**
+ * Default destructor.
+ * Will call the dispose callback.
+ */
+ virtual ~ACT_CallbackAction()
+ {
+ // Should assert
+ m_disposeProc((ACT_ActionPtr)this, m_userData);
+ }
+
+
+protected:
+ /**
+ * Calls the appropriate callback.
+ */
+ inline virtual void doApply();
+
+ /**
+ * Calls the appropriate callback.
+ */
+ inline virtual void doUndo();
+
+ /** User data supplied at creation and passed to the callbacks. */
+ ACT_ActionUserDataPtr m_userData;
+
+ /** Callback invoked for apply action. */
+ ACT_ActionApplyProcPtr m_applyProc;
+
+ /** Callback invoked for undo action. */
+ ACT_ActionApplyProcPtr m_undoProc;
+
+ /** Callback invoked when the action is disposed. */
+ ACT_ActionDisposeProcPtr m_disposeProc;
+};
+
+
+inline void ACT_CallbackAction::doApply()
+{
+ // Should assert
+ m_applyProc((ACT_ActionPtr)this, m_userData);
+}
+
+
+inline void ACT_CallbackAction::doUndo()
+{
+ // Should assert
+ m_undoProc((ACT_ActionPtr)this, m_userData);
+}
+
+
+#endif // _H_ACT_CALLBACK_ACTION_H \ No newline at end of file
diff --git a/intern/action/intern/Makefile b/intern/action/intern/Makefile
new file mode 100644
index 00000000000..29f82bb7c0d
--- /dev/null
+++ b/intern/action/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# action intern Makefile
+#
+
+LIBNAME = action
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CPPFLAGS += -I..
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
diff --git a/intern/action/make/msvc_6_0/action.dsp b/intern/action/make/msvc_6_0/action.dsp
new file mode 100644
index 00000000000..3ea450b19a7
--- /dev/null
+++ b/intern/action/make/msvc_6_0/action.dsp
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Project File - Name="action" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=action - 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 "action.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 "action.mak" CFG="action - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "action - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "action - 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)" == "action - 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/action/"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/action/"
+# PROP Target_Dir ""
+# 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 "../.." /I "../../../../lib/windows/memutil/include/" /I "../../../../lib/windows/string/include/" /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
+
+!ELSEIF "$(CFG)" == "action - 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/action/debug"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/action/debug"
+# PROP Target_Dir ""
+# 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 "../.." /I "../../../../lib/windows/memutil/include/" /I "../../../../lib/windows/string/include/" /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "action - Win32 Release"
+# Name "action - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\ACT_Action.cpp
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\intern\ACT_ActionC-Api.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\ACT_ActionStack.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\ACT_CallbackAction.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\ACT_Action.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\ACT_ActionC-Api.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ACT_ActionStack.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/intern/action/make/msvc_6_0/action.dsw b/intern/action/make/msvc_6_0/action.dsw
new file mode 100644
index 00000000000..f93cbb896fd
--- /dev/null
+++ b/intern/action/make/msvc_6_0/action.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "action"=".\action.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/action/test/action_c_test/ActionTest.c b/intern/action/test/action_c_test/ActionTest.c
new file mode 100644
index 00000000000..a30163e0c3b
--- /dev/null
+++ b/intern/action/test/action_c_test/ActionTest.c
@@ -0,0 +1,83 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#include "ACT_ActionC-Api.h"
+#include "TestAction.h"
+
+int main(int argc, char *argv[])
+{
+ ACT_ActionStackPtr stack = ACT_ActionStackCreate (3);
+ ACT_ActionPtr action = ACT_ActionCreate("action1", 0, 0, printApplied, printUndone, printDisposed);
+ ACT_ActionStackPush(stack, action);
+ MEM_RefCountedDecRef(action);
+ action = ACT_ActionCreate("action2", 0, 0, printApplied, printUndone, printDisposed);
+ ACT_ActionStackPush(stack, action);
+ MEM_RefCountedDecRef(action);
+ action = ACT_ActionCreate("action3", 0, 0, printApplied, printUndone, printDisposed);
+ ACT_ActionStackPush(stack, action);
+ MEM_RefCountedDecRef(action);
+
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackRedo(stack);
+ ACT_ActionStackRedo(stack);
+ ACT_ActionStackRedo(stack);
+
+ ACT_ActionStackSetMaxStackDepth(stack, 1);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackRedo(stack);
+ ACT_ActionStackSetMaxStackDepth(stack, 5);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackRedo(stack);
+
+ action = ACT_ActionCreate("action4", 0, 0, printApplied, printUndone, printDisposed);
+ ACT_ActionStackPush(stack, action);
+ MEM_RefCountedDecRef(action);
+ ACT_ActionStackUndo(stack);
+ action = ACT_ActionCreate("action5", 0, 0, printApplied, printUndone, printDisposed);
+ ACT_ActionStackPush(stack, action);
+ MEM_RefCountedDecRef(action);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackUndo(stack);
+ ACT_ActionStackRedo(stack);
+ ACT_ActionStackRedo(stack);
+
+ return 0;
+} \ No newline at end of file
diff --git a/intern/action/test/action_c_test/TestAction.c b/intern/action/test/action_c_test/TestAction.c
new file mode 100644
index 00000000000..7b9739495d0
--- /dev/null
+++ b/intern/action/test/action_c_test/TestAction.c
@@ -0,0 +1,59 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#include <stdio.h>
+
+#include "TestAction.h"
+
+
+void printApplied(ACT_ActionPtr action, ACT_ActionUserDataPtr userData)
+{
+ printf("%s: applied\n", ACT_ActionGetName(action));
+}
+
+void printUndone(ACT_ActionPtr action, ACT_ActionUserDataPtr userData)
+{
+ printf("%s: undone\n", ACT_ActionGetName(action));
+}
+
+
+void printDisposed(ACT_ActionPtr action, ACT_ActionUserDataPtr userData)
+{
+ printf("%s: disposed\n", ACT_ActionGetName(action));
+}
diff --git a/intern/action/test/action_c_test/TestAction.h b/intern/action/test/action_c_test/TestAction.h
new file mode 100644
index 00000000000..7abf0be6919
--- /dev/null
+++ b/intern/action/test/action_c_test/TestAction.h
@@ -0,0 +1,50 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#ifndef _H_ACT_TESTACTION_C_H_
+#define _H_ACT_TESTACTION_C_H_
+
+#include "ACT_ActionC-Api.h"
+
+void printApplied(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+void printUndone(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+void printDisposed(ACT_ActionPtr action, ACT_ActionUserDataPtr userData);
+
+
+#endif // _H_ACT_TESTACTION_C_H_ \ No newline at end of file
diff --git a/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp
new file mode 100644
index 00000000000..807024f20be
--- /dev/null
+++ b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="action_c_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=action_c_test - 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 "action_c_test.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 "action_c_test.mak" CFG="action_c_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "action_c_test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "action_c_test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "action_c_test - 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/action/test"
+# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../../lib/windows/memutil/lib" /libpath:"../../../../../../lib/windows/string/lib"
+
+!ELSEIF "$(CFG)" == "action_c_test - 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/action/test/debug"
+# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test/debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../../lib/windows/memutil/lib/debug" /libpath:"../../../../../../lib/windows/string/lib/debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "action_c_test - Win32 Release"
+# Name "action_c_test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\ActionTest.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\TestAction.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\TestAction.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw
new file mode 100644
index 00000000000..688f24e4d53
--- /dev/null
+++ b/intern/action/test/action_c_test/make/msvc_6_0/action_c_test.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "action"="..\..\..\..\make\msvc_6_0\action.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "action_c_test"=".\action_c_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name action
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/action/test/action_cpp_test/ActionTest.cpp b/intern/action/test/action_cpp_test/ActionTest.cpp
new file mode 100644
index 00000000000..379cc41a5de
--- /dev/null
+++ b/intern/action/test/action_cpp_test/ActionTest.cpp
@@ -0,0 +1,83 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#include "ACT_ActionStack.h"
+#include "TestAction.h"
+
+int main()
+{
+ ACT_ActionStack testStack (3);
+ TestAction* testAction = new TestAction (STR_String("action1"));
+ testStack.push(*testAction);
+ testAction->decRef();
+ testAction = new TestAction (STR_String("action2"));
+ testStack.push(*testAction);
+ testAction->decRef();
+ testAction = new TestAction (STR_String("action3"));
+ testStack.push(*testAction);
+ testAction->decRef();
+
+ testStack.undo();
+ testStack.undo();
+ testStack.undo();
+ testStack.redo();
+ testStack.redo();
+ testStack.redo();
+
+ testStack.setMaxStackDepth(1);
+ testStack.undo();
+ testStack.redo();
+ testStack.setMaxStackDepth(5);
+ testStack.undo();
+ testStack.redo();
+
+ testAction = new TestAction (STR_String("action4"));
+ testStack.push(*testAction);
+ testAction->decRef();
+ testStack.undo();
+ testAction = new TestAction (STR_String("action5"));
+ testStack.push(*testAction);
+ testAction->decRef();
+ testStack.undo();
+ testStack.undo();
+ testStack.redo();
+ testStack.redo();
+
+ return 0;
+} \ No newline at end of file
diff --git a/intern/action/test/action_cpp_test/TestAction.h b/intern/action/test/action_cpp_test/TestAction.h
new file mode 100644
index 00000000000..83bc8fb1750
--- /dev/null
+++ b/intern/action/test/action_cpp_test/TestAction.h
@@ -0,0 +1,57 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#ifndef _H_ACT_TESTACTION
+#define _H_ACT_TESTACTION
+
+#include "ACT_Action.h"
+
+#include <iostream>
+
+class TestAction : public ACT_Action
+{
+public:
+ TestAction(const STR_String& name) : ACT_Action(name) {}
+ virtual ~TestAction() { cout << m_name.Ptr() << ": deleted\n"; }
+protected:
+ virtual void doApply() { cout << m_name.Ptr() << ": applied\n"; }
+ virtual void doUndo() { cout << m_name.Ptr() << ": undone\n"; }
+};
+
+#endif // _H_ACT_TESTACTION \ No newline at end of file
diff --git a/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp
new file mode 100644
index 00000000000..bc0c40b6d36
--- /dev/null
+++ b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsp
@@ -0,0 +1,105 @@
+# Microsoft Developer Studio Project File - Name="action_cpp_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=action_cpp_test - 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 "action_cpp_test.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 "action_cpp_test.mak" CFG="action_cpp_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "action_cpp_test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "action_cpp_test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "action_cpp_test - 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/action/test"
+# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../../lib/windows/memutil/lib" /libpath:"../../../../../../lib/windows/string/lib"
+
+!ELSEIF "$(CFG)" == "action_cpp_test - 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/action/test/debug"
+# PROP Intermediate_Dir "../../../../../../../obj/windows/intern/action/test/debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../.." /I "../../../../../../lib/windows/memutil/include/" /I "../../../../../../lib/windows/string/include/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib string.lib memutil.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../../lib/windows/memutil/lib/debug" /libpath:"../../../../../../lib/windows/string/lib/debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "action_cpp_test - Win32 Release"
+# Name "action_cpp_test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\ActionTest.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\TestAction.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw
new file mode 100644
index 00000000000..0a9d7374379
--- /dev/null
+++ b/intern/action/test/action_cpp_test/make/msvc_6_0/action_cpp_test.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "action"="..\..\..\..\make\msvc_6_0\action.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "action_cpp_test"=".\action_cpp_test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name action
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/bmfont/BMF_Api.h b/intern/bmfont/BMF_Api.h
new file mode 100644
index 00000000000..4d51bd6e0a3
--- /dev/null
+++ b/intern/bmfont/BMF_Api.h
@@ -0,0 +1,129 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * API of the OpenGL bitmap font library.
+ * Currently draws fonts using the glBitmap routine.
+ * This implies that drawing speed is heavyly dependant on
+ * the 2D capabilities of the graphics card.
+ */
+
+#ifndef __BMF_API_H
+#define __BMF_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BMF_Fonts.h"
+
+/**
+ * Returns the font for a given font type.
+ * @param font The font to retrieve.
+ * @return The font (or nil if not found).
+ */
+BMF_Font* BMF_GetFont(BMF_FontType font);
+
+/**
+ * Draws a character at the current raster position.
+ * @param font The font to use.
+ * @param c The character to draw.
+ * @return Indication of success (0 == error).
+ */
+int BMF_DrawCharacter(BMF_Font* font, char c);
+
+/**
+ * Draws a string at the current raster position.
+ * @param font The font to use.
+ * @param str The string to draw.
+ * @return Indication of success (0 == error).
+ */
+int BMF_DrawString(BMF_Font* font, char* str);
+
+/**
+ * Returns the width of a character in pixels.
+ * @param font The font to use.
+ * @param c The character.
+ * @return The length.
+ */
+int BMF_GetCharacterWidth(BMF_Font* font, char c);
+
+/**
+ * Returns the width of a string of characters.
+ * @param font The font to use.
+ * @param str The string.
+ * @return The length.
+ */
+int BMF_GetStringWidth(BMF_Font* font, char* str);
+
+/**
+ * Returns the bounding box of the font. The width and
+ * height represent the bounding box of the union of
+ * all glyps. The minimum and maximum values of the
+ * box represent the extent of the font and its positioning
+ * about the origin.
+ */
+void BMF_GetBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r);
+
+/**
+ * Convert the given @a font to a texture, and return the GL texture
+ * ID of the texture. If the texture ID is bound, text can
+ * be drawn using the texture by calling DrawStringTexture.
+ *
+ * @param font The font to create the texture from.
+ * @return The GL texture ID of the new texture, or -1 if unable
+ * to create.
+ */
+int BMF_GetFontTexture(BMF_Font* font);
+
+/**
+ * Draw the given @a str at the point @a x, @a y, @a z, using
+ * texture coordinates. This assumes that an appropriate texture
+ * has been bound, see BMF_BitmapFont::GetTexture(). The string
+ * is drawn along the positive X axis.
+ *
+ * @param font The font to draw with.
+ * @param string The c-string to draw.
+ * @param x The x coordinate to start drawing at.
+ * @param y The y coordinate to start drawing at.
+ * @param z The z coordinate to start drawing at.
+ */
+void BMF_DrawStringTexture(BMF_Font* font, char* string, float x, float y, float z);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BMF_API_H */
diff --git a/intern/bmfont/BMF_Fonts.h b/intern/bmfont/BMF_Fonts.h
new file mode 100644
index 00000000000..7848031805f
--- /dev/null
+++ b/intern/bmfont/BMF_Fonts.h
@@ -0,0 +1,76 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Defines the names of the fonts in the library.
+ */
+
+#ifndef __BMF_FONTS_H
+#define __BMF_FONTS_H
+
+#include "BMF_Settings.h"
+
+typedef enum
+{
+ BMF_kHelvetica10 = 0,
+#if BMF_INCLUDE_HELV12
+ BMF_kHelvetica12,
+#endif
+#if BMF_INCLUDE_HELVB8
+ BMF_kHelveticaBold8,
+#endif
+#if BMF_INCLUDE_HELVB10
+ BMF_kHelveticaBold10,
+#endif
+#if BMF_INCLUDE_HELVB12
+ BMF_kHelveticaBold12,
+#endif
+#if BMF_INCLUDE_HELVB14
+ BMF_kHelveticaBold14,
+#endif
+#if BMF_INCLUDE_SCR12
+ BMF_kScreen12,
+#endif
+#if BMF_INCLUDE_SCR14
+ BMF_kScreen14,
+#endif
+#if BMF_INCLUDE_SCR15
+ BMF_kScreen15,
+#endif
+ BMF_kNumFonts
+} BMF_FontType;
+
+typedef struct BMF_Font BMF_Font;
+
+#endif /* __BMF_FONTS_H */
diff --git a/intern/bmfont/BMF_Settings.h b/intern/bmfont/BMF_Settings.h
new file mode 100644
index 00000000000..24ee13ad531
--- /dev/null
+++ b/intern/bmfont/BMF_Settings.h
@@ -0,0 +1,69 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Allows you to determine which fonts to include in the library.
+ */
+
+#ifndef __BMF_SETTINGS_H
+#define __BMF_SETTINGS_H
+
+/* This font is included always */
+#define BMF_INCLUDE_HELV10 1
+
+#ifndef BMF_MINIMAL
+
+/* These fonts are included with the minimal setting defined */
+#define BMF_INCLUDE_HELV12 1
+#define BMF_INCLUDE_HELVB8 1
+#define BMF_INCLUDE_HELVB10 1
+#define BMF_INCLUDE_HELVB12 1
+#define BMF_INCLUDE_HELVB14 1
+#define BMF_INCLUDE_SCR12 1
+#define BMF_INCLUDE_SCR14 1
+#define BMF_INCLUDE_SCR15 1
+
+#else /* BMF_MINIMAL */
+#define BMF_INCLUDE_HELV12 0
+#define BMF_INCLUDE_HELVB8 0
+#define BMF_INCLUDE_HELVB10 0
+#define BMF_INCLUDE_HELVB12 0
+#define BMF_INCLUDE_HELVB14 0
+#define BMF_INCLUDE_SCR12 0
+#define BMF_INCLUDE_SCR14 0
+#define BMF_INCLUDE_SCR15 0
+
+#endif /* BMF_MINIMAL */
+
+#endif /* __BMF_SETTINGS_H */
diff --git a/intern/bmfont/Makefile b/intern/bmfont/Makefile
new file mode 100644
index 00000000000..0da2a844236
--- /dev/null
+++ b/intern/bmfont/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# bmfont main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = bmfont
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+#not ready yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_BMFONT) ] || mkdir $(NAN_BMFONT)
+ @[ -d $(NAN_BMFONT)/include ] || mkdir $(NAN_BMFONT)/include
+ @[ -d $(NAN_BMFONT)/lib ] || mkdir $(NAN_BMFONT)/lib
+ @[ -d $(NAN_BMFONT)/lib/debug ] || mkdir $(NAN_BMFONT)/lib/debug
+ cp -f $(DIR)/libbmfont.a $(NAN_BMFONT)/lib/
+ cp -f $(DIR)/debug/libbmfont.a $(NAN_BMFONT)/lib/debug/
+ cp -f *.h $(NAN_BMFONT)/include/
+
diff --git a/intern/bmfont/intern/BMF_Api.cpp b/intern/bmfont/intern/BMF_Api.cpp
new file mode 100644
index 00000000000..08e54f13174
--- /dev/null
+++ b/intern/bmfont/intern/BMF_Api.cpp
@@ -0,0 +1,164 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * Implementation of the API of the OpenGL bitmap font library.
+ */
+
+#include "BMF_Api.h"
+
+#include "BMF_BitmapFont.h"
+
+
+#if BMF_INCLUDE_HELV10
+extern BMF_FontData BMF_font_helv10;
+static BMF_BitmapFont bmfHelv10(&BMF_font_helv10);
+#endif // BMF_INCLUDE_HELV10
+#if BMF_INCLUDE_HELV12
+extern BMF_FontData BMF_font_helv12;
+static BMF_BitmapFont bmfHelv12(&BMF_font_helv12);
+#endif // BMF_INCLUDE_HELV12
+#if BMF_INCLUDE_HELVB8
+extern BMF_FontData BMF_font_helvb8;
+static BMF_BitmapFont bmfHelvb8(&BMF_font_helvb8);
+#endif // BMF_INCLUDE_HELVB8
+#if BMF_INCLUDE_HELVB10
+extern BMF_FontData BMF_font_helvb10;
+static BMF_BitmapFont bmfHelvb10(&BMF_font_helvb10);
+#endif // BMF_INCLUDE_HELVB10
+#if BMF_INCLUDE_HELVB12
+extern BMF_FontData BMF_font_helvb12;
+static BMF_BitmapFont bmfHelvb12(&BMF_font_helvb12);
+#endif // BMF_INCLUDE_HELVB12
+#if BMF_INCLUDE_HELVB14
+extern BMF_FontData BMF_font_helvb14;
+static BMF_BitmapFont bmfHelvb14(&BMF_font_helvb14);
+#endif // BMF_INCLUDE_HELVB14
+#if BMF_INCLUDE_SCR12
+extern BMF_FontData BMF_font_scr12;
+static BMF_BitmapFont bmfScreen12(&BMF_font_scr12);
+#endif // BMF_INCLUDE_SCR12
+#if BMF_INCLUDE_SCR14
+extern BMF_FontData BMF_font_scr14;
+static BMF_BitmapFont bmfScreen14(&BMF_font_scr14);
+#endif // BMF_INCLUDE_SCR14
+#if BMF_INCLUDE_SCR15
+extern BMF_FontData BMF_font_scr15;
+static BMF_BitmapFont bmfScreen15(&BMF_font_scr15);
+#endif // BMF_INCLUDE_SCR15
+
+
+BMF_Font* BMF_GetFont(BMF_FontType font)
+{
+ switch (font)
+ {
+#if BMF_INCLUDE_HELV10
+ case BMF_kHelvetica10: return (BMF_Font*) &bmfHelv10;
+#endif // BMF_INCLUDE_HELV10
+#if BMF_INCLUDE_HELV12
+ case BMF_kHelvetica12: return (BMF_Font*) &bmfHelv12;
+#endif // BMF_INCLUDE_HELV12
+#if BMF_INCLUDE_HELVB8
+ case BMF_kHelveticaBold8: return (BMF_Font*) &bmfHelvb8;
+#endif // BMF_INCLUDE_HELVB8
+#if BMF_INCLUDE_HELVB10
+ case BMF_kHelveticaBold10: return (BMF_Font*) &bmfHelvb10;
+#endif // BMF_INCLUDE_HELVB10
+#if BMF_INCLUDE_HELVB12
+ case BMF_kHelveticaBold12: return (BMF_Font*) &bmfHelvb12;
+#endif // BMF_INCLUDE_HELVB12
+#if BMF_INCLUDE_HELVB14
+ case BMF_kHelveticaBold14: return (BMF_Font*) &bmfHelvb14;
+#endif // BMF_INCLUDE_HELVB12
+#if BMF_INCLUDE_SCR12
+ case BMF_kScreen12: return (BMF_Font*) &bmfScreen12;
+#endif // BMF_INCLUDE_SCR12
+#if BMF_INCLUDE_SCR14
+ case BMF_kScreen14: return (BMF_Font*) &bmfScreen14;
+#endif // BMF_INCLUDE_SCR14
+#if BMF_INCLUDE_SCR15
+ case BMF_kScreen15: return (BMF_Font*) &bmfScreen15;
+#endif // BMF_INCLUDE_SCR15
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+int BMF_DrawCharacter(BMF_Font* font, char c)
+{
+ char str[2] = {c, '\0'};
+ return BMF_DrawString(font, str);
+}
+
+
+int BMF_DrawString(BMF_Font* font, char* str)
+{
+ if (!font) return 0;
+ ((BMF_BitmapFont*)font)->DrawString(str);
+ return 1;
+}
+
+
+int BMF_GetCharacterWidth(BMF_Font* font, char c)
+{
+ char str[2] = {c, '\0'};
+ return BMF_GetStringWidth(font, str);
+}
+
+
+int BMF_GetStringWidth(BMF_Font* font, char* str)
+{
+ if (!font) return 0;
+ return ((BMF_BitmapFont*)font)->GetStringWidth(str);
+}
+
+
+void BMF_GetBoundingBox(BMF_Font* font, int *xmin_r, int *ymin_r, int *xmax_r, int *ymax_r)
+{
+ if (!font) return;
+ ((BMF_BitmapFont*)font)->GetBoundingBox(*xmin_r, *ymin_r, *xmax_r, *ymax_r);
+}
+
+int BMF_GetFontTexture(BMF_Font* font) {
+ if (!font) return -1;
+ return ((BMF_BitmapFont*)font)->GetTexture();
+}
+
+void BMF_DrawStringTexture(BMF_Font* font, char *string, float x, float y, float z) {
+ if (!font) return;
+ ((BMF_BitmapFont*)font)->DrawStringTexture(string, x, y, z);
+}
diff --git a/intern/bmfont/intern/BMF_BitmapFont.cpp b/intern/bmfont/intern/BMF_BitmapFont.cpp
new file mode 100644
index 00000000000..bd3fe0cb899
--- /dev/null
+++ b/intern/bmfont/intern/BMF_BitmapFont.cpp
@@ -0,0 +1,207 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ */
+
+#include <string.h>
+
+#if defined(WIN32) || defined(__APPLE__)
+ #ifdef WIN32
+ #if !defined(__CYGWIN32__)
+ #pragma warning(disable:4244)
+ #endif /* __CYGWIN32__ */
+ #include <windows.h>
+ #include <GL/gl.h>
+ #else // WIN32
+ // __APPLE__ is defined
+ #include <AGL/gl.h>
+ #endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+ #include <GL/gl.h>
+#endif // defined(WIN32) || defined(__APPLE__)
+
+#include "BMF_BitmapFont.h"
+
+
+BMF_BitmapFont::BMF_BitmapFont(BMF_FontData* fontData)
+: m_fontData(fontData)
+{
+}
+
+
+BMF_BitmapFont::~BMF_BitmapFont(void)
+{
+}
+
+
+void BMF_BitmapFont::DrawString(char* str)
+{
+ GLint alignment;
+ unsigned char c;
+
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ while (c = (unsigned char) *str++) {
+ BMF_CharData & cd = m_fontData->chars[c];
+
+ if (cd.data_offset==-1) {
+ GLubyte nullBitmap = 0;
+
+ glBitmap(1, 1, 0, 0, cd.advance, 0, &nullBitmap);
+ } else {
+ GLubyte *bitmap = &m_fontData->bitmap_data[cd.data_offset];
+
+ glBitmap(cd.width, cd.height, cd.xorig, cd.yorig, cd.advance, 0, bitmap);
+ }
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
+
+int BMF_BitmapFont::GetStringWidth(char* str)
+{
+ unsigned char c;
+ int length = 0;
+
+ while (c = (unsigned char) *str++) {
+ length += m_fontData->chars[c].advance;
+ }
+
+ return length;
+}
+
+void BMF_BitmapFont::GetBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax)
+{
+ xMin = m_fontData->xmin;
+ yMin = m_fontData->ymin;
+ xMax = m_fontData->xmax;
+ yMax = m_fontData->ymax;
+}
+
+int BMF_BitmapFont::GetTexture()
+{
+ int fWidth = m_fontData->xmax - m_fontData->xmin;
+ int fHeight = m_fontData->ymax - m_fontData->ymin;
+
+ if (fWidth>=16 || fHeight>=16) {
+ return -1;
+ }
+
+ int cRows = 16, cCols = 16;
+ int cWidth = 16, cHeight = 16;
+ int iWidth = cCols*cWidth;
+ int iHeight = cRows*cHeight;
+ GLubyte *img = new GLubyte [iHeight*iWidth];
+ GLuint texId;
+
+ int baseLine = -(m_fontData->ymin);
+
+ memset(img, 0, iHeight*iWidth);
+ for (int i = 0; i<256; i++) {
+ BMF_CharData & cd = m_fontData->chars[i];
+
+ if (cd.data_offset != -1) {
+ int cellX = i%16;
+ int cellY = i/16;
+
+ for (int y = 0; y<cd.height; y++) {
+ GLubyte* imgRow = &img[(cellY*cHeight + y + baseLine - cd.yorig)*iWidth];
+ GLubyte* chrRow = &m_fontData->bitmap_data[cd.data_offset + ((cd.width+7)/8)*y];
+
+ for (int x = 0; x<cd.width; x++) {
+ GLubyte* imgPxl = &imgRow[(cellX*cWidth + x - cd.xorig)];
+ int byteIdx = x/8;
+ int bitIdx = 7 - (x%8);
+
+ if (chrRow[byteIdx]&(1<<bitIdx)) {
+ imgPxl[0] = 255;
+ }
+ }
+ }
+ }
+ }
+
+ glGenTextures(1, &texId);
+
+ glBindTexture(GL_TEXTURE_2D, texId);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
+ if (glGetError()) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE4_ALPHA4, iWidth, iHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, img);
+ }
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ delete [] img;
+
+ return texId;
+}
+
+void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z)
+{
+ unsigned char c;
+ float pos = 0;
+
+ int baseLine = -(m_fontData->ymin);
+
+ glBegin(GL_QUADS);
+ while (c = (unsigned char) *str++) {
+ BMF_CharData & cd = m_fontData->chars[c];
+
+ if (cd.data_offset != -1) {
+ float cellX = (c%16)/16.0;
+ float cellY = (c/16)/16.0;
+
+ glTexCoord2f(cellX + 1.0/16.0, cellY);
+ glVertex3f(x + pos + 16.0, -baseLine + y + 0.0, z);
+
+ glTexCoord2f(cellX + 1.0/16.0, cellY + 1.0/16.0);
+ glVertex3f(x + pos + 16.0, -baseLine + y + 16.0, z);
+
+ glTexCoord2f(cellX, cellY + 1.0/16.0);
+ glVertex3f(x + pos + 0.0, -baseLine + y + 16.0, z);
+
+ glTexCoord2f(cellX, cellY);
+ glVertex3f(x + pos + 0.0, -baseLine + y + 0.0, z);
+ }
+
+ pos += cd.advance;
+ }
+ glEnd();
+}
diff --git a/intern/bmfont/intern/BMF_BitmapFont.h b/intern/bmfont/intern/BMF_BitmapFont.h
new file mode 100644
index 00000000000..f203cb374ae
--- /dev/null
+++ b/intern/bmfont/intern/BMF_BitmapFont.h
@@ -0,0 +1,109 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ */
+
+#ifndef __BMF_BITMAP_FONT_H
+#define __BMF_BITMAP_FONT_H
+
+#include "BMF_FontData.h"
+
+/**
+ * Base class for OpenGL bitmap fonts.
+ */
+class BMF_BitmapFont
+{
+public:
+ /**
+ * Default constructor.
+ */
+ BMF_BitmapFont(BMF_FontData* fontData);
+
+ /**
+ * Destructor.
+ */
+ virtual ~BMF_BitmapFont(void);
+
+ /**
+ * Draws a string at the current raster position.
+ * @param str The string to draw.
+ */
+ void DrawString(char* str);
+
+ /**
+ * Draws a string at the current raster position.
+ * @param str The string to draw.
+ * @return The width of the string.
+ */
+ int GetStringWidth(char* str);
+
+ /**
+ * Returns the bounding box of the font. The width and
+ * height represent the bounding box of the union of
+ * all glyps. The minimum and maximum values of the
+ * box represent the extent of the font and its positioning
+ * about the origin.
+ */
+ void GetBoundingBox(int & xMin, int & yMin, int & xMax, int & yMax);
+
+ /**
+ * Convert the font to a texture, and return the GL texture
+ * ID of the texture. If the texture ID is bound, text can
+ * be drawn using the texture by calling DrawStringTexture.
+ *
+ * @return The GL texture ID of the new texture, or -1 if unable
+ * to create.
+ */
+ int GetTexture();
+
+ /**
+ * Draw the given @a string at the point @a x, @a y, @a z, using
+ * texture coordinates. This assumes that an appropriate texture
+ * has been bound, see BMF_BitmapFont::GetTexture(). The string
+ * is drawn along the positive X axis.
+ *
+ * @param string The c-string to draw.
+ * @param x The x coordinate to start drawing at.
+ * @param y The y coordinate to start drawing at.
+ * @param z The z coordinate to start drawing at.
+ */
+ void DrawStringTexture(char* string, float x, float y, float z);
+
+protected:
+ /** Pointer to the font data. */
+ BMF_FontData* m_fontData;
+};
+
+#endif // __BMF_BITMAP_FONT_H
diff --git a/intern/bmfont/intern/BMF_FontData.h b/intern/bmfont/intern/BMF_FontData.h
new file mode 100644
index 00000000000..b1e1a08f92a
--- /dev/null
+++ b/intern/bmfont/intern/BMF_FontData.h
@@ -0,0 +1,57 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ */
+
+#ifndef __BMF_FONTDATA_H__
+#define __BMF_FONTDATA_H__
+
+typedef struct {
+ signed char width, height;
+ signed char xorig, yorig;
+ signed char advance;
+
+ short data_offset;
+} BMF_CharData;
+
+typedef struct {
+ int xmin, ymin;
+ int xmax, ymax;
+
+ BMF_CharData chars[256];
+ unsigned char* bitmap_data;
+} BMF_FontData;
+
+#endif
diff --git a/intern/bmfont/intern/BMF_font_helv10.cpp b/intern/bmfont/intern/BMF_font_helv10.cpp
new file mode 100644
index 00000000000..b69796948c3
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helv10.cpp
@@ -0,0 +1,493 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELV10
+
+static unsigned char bitmap_data[]= {
+ 0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0xa0,0xa0,0x50,0x50,0xf8,0x28,0x7c,0x28,
+ 0x28,0x20,0x70,0xa8,0x28,0x70,0xa0,0xa8,
+ 0x70,0x20,0x26,0x29,0x16,0x10,0x08,0x68,
+ 0x94,0x64,0x64,0x98,0x98,0xa4,0x60,0x50,
+ 0x50,0x20,0x80,0x40,0x40,0x20,0x40,0x40,
+ 0x80,0x80,0x80,0x80,0x40,0x40,0x20,0x80,
+ 0x40,0x40,0x20,0x20,0x20,0x20,0x40,0x40,
+ 0x80,0xa0,0x40,0xa0,0x20,0x20,0xf8,0x20,
+ 0x20,0x80,0x40,0x40,0xf8,0x80,0x80,0x80,
+ 0x40,0x40,0x40,0x40,0x20,0x20,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x70,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0xc0,0x40,0xf8,0x80,
+ 0x40,0x30,0x08,0x08,0x88,0x70,0x70,0x88,
+ 0x08,0x08,0x30,0x08,0x88,0x70,0x10,0x10,
+ 0xf8,0x90,0x50,0x50,0x30,0x10,0x70,0x88,
+ 0x08,0x08,0xf0,0x80,0x80,0xf8,0x70,0x88,
+ 0x88,0xc8,0xb0,0x80,0x88,0x70,0x40,0x40,
+ 0x20,0x20,0x10,0x10,0x08,0xf8,0x70,0x88,
+ 0x88,0x88,0x70,0x88,0x88,0x70,0x70,0x88,
+ 0x08,0x68,0x98,0x88,0x88,0x70,0x80,0x00,
+ 0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x00,
+ 0x00,0x00,0x00,0x40,0x20,0x40,0x80,0x40,
+ 0x20,0xf0,0x00,0xf0,0x80,0x40,0x20,0x40,
+ 0x80,0x40,0x00,0x40,0x40,0x20,0x10,0x90,
+ 0x60,0x3e,0x00,0x40,0x00,0x9b,0x00,0xa4,
+ 0x80,0xa4,0x80,0xa2,0x40,0x92,0x40,0x4d,
+ 0x40,0x20,0x80,0x1f,0x00,0x82,0x82,0x7c,
+ 0x44,0x28,0x28,0x10,0x10,0xf0,0x88,0x88,
+ 0x88,0xf0,0x88,0x88,0xf0,0x78,0x84,0x80,
+ 0x80,0x80,0x80,0x84,0x78,0xf0,0x88,0x84,
+ 0x84,0x84,0x84,0x88,0xf0,0xf8,0x80,0x80,
+ 0x80,0xf8,0x80,0x80,0xf8,0x80,0x80,0x80,
+ 0x80,0xf0,0x80,0x80,0xf8,0x74,0x8c,0x84,
+ 0x8c,0x80,0x80,0x84,0x78,0x84,0x84,0x84,
+ 0x84,0xfc,0x84,0x84,0x84,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x60,0x90,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0x88,0x88,0x90,
+ 0x90,0xe0,0xa0,0x90,0x88,0xf0,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x92,0x92,0x92,
+ 0xaa,0xaa,0xc6,0xc6,0x82,0x8c,0x8c,0x94,
+ 0x94,0xa4,0xa4,0xc4,0xc4,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x78,0x80,0x80,0x80,
+ 0x80,0xf0,0x88,0x88,0xf0,0x02,0x7c,0x8c,
+ 0x94,0x84,0x84,0x84,0x84,0x78,0x88,0x88,
+ 0x88,0x88,0xf0,0x88,0x88,0xf0,0x70,0x88,
+ 0x88,0x08,0x70,0x80,0x88,0x70,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0xf8,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x10,0x28,
+ 0x28,0x44,0x44,0x44,0x82,0x82,0x22,0x00,
+ 0x22,0x00,0x22,0x00,0x55,0x00,0x49,0x00,
+ 0x49,0x00,0x88,0x80,0x88,0x80,0x88,0x88,
+ 0x50,0x50,0x20,0x50,0x88,0x88,0x10,0x10,
+ 0x10,0x28,0x28,0x44,0x44,0x82,0xf8,0x80,
+ 0x40,0x20,0x20,0x10,0x08,0xf8,0xc0,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,
+ 0x20,0x20,0x40,0x40,0x40,0x40,0x80,0x80,
+ 0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0xc0,0x88,0x50,0x50,0x20,0x20,0xfc,
+ 0x80,0x80,0x40,0x68,0x90,0x90,0x70,0x10,
+ 0xe0,0xb0,0xc8,0x88,0x88,0xc8,0xb0,0x80,
+ 0x80,0x60,0x90,0x80,0x80,0x90,0x60,0x68,
+ 0x98,0x88,0x88,0x98,0x68,0x08,0x08,0x60,
+ 0x90,0x80,0xf0,0x90,0x60,0x40,0x40,0x40,
+ 0x40,0x40,0xe0,0x40,0x30,0x70,0x08,0x68,
+ 0x98,0x88,0x88,0x98,0x68,0x88,0x88,0x88,
+ 0x88,0xc8,0xb0,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x00,0x80,0x90,0x90,
+ 0xa0,0xc0,0xa0,0x90,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x92,0x92,
+ 0x92,0x92,0x92,0xec,0x88,0x88,0x88,0x88,
+ 0xc8,0xb0,0x70,0x88,0x88,0x88,0x88,0x70,
+ 0x80,0x80,0xb0,0xc8,0x88,0x88,0xc8,0xb0,
+ 0x08,0x08,0x68,0x98,0x88,0x88,0x98,0x68,
+ 0x80,0x80,0x80,0x80,0xc0,0xa0,0x60,0x90,
+ 0x10,0x60,0x90,0x60,0x60,0x40,0x40,0x40,
+ 0x40,0xe0,0x40,0x40,0x70,0x90,0x90,0x90,
+ 0x90,0x90,0x20,0x20,0x50,0x50,0x88,0x88,
+ 0x28,0x28,0x54,0x54,0x92,0x92,0x88,0x88,
+ 0x50,0x20,0x50,0x88,0x80,0x40,0x40,0x60,
+ 0xa0,0xa0,0x90,0x90,0xf0,0x80,0x40,0x20,
+ 0x10,0xf0,0x20,0x40,0x40,0x40,0x40,0x80,
+ 0x40,0x40,0x40,0x20,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,
+ 0x40,0x40,0x40,0x20,0x40,0x40,0x40,0x80,
+ 0x98,0x64,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x00,0x80,0x40,0x70,0xa8,0xa0,0xa0,0xa8,
+ 0x70,0x10,0xb0,0x48,0x40,0x40,0xe0,0x40,
+ 0x48,0x30,0x90,0x60,0x90,0x90,0x60,0x90,
+ 0x20,0xf8,0x20,0xf8,0x50,0x50,0x88,0x88,
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,
+ 0x80,0x80,0x70,0x88,0x18,0x70,0xc8,0x98,
+ 0x70,0xc0,0x88,0x70,0xa0,0x38,0x44,0x9a,
+ 0xa2,0x9a,0x44,0x38,0xe0,0x00,0xa0,0x20,
+ 0xe0,0x28,0x50,0xa0,0x50,0x28,0x08,0x08,
+ 0xf8,0xe0,0x38,0x44,0xaa,0xb2,0xba,0x44,
+ 0x38,0xe0,0x60,0x90,0x90,0x60,0xf8,0x00,
+ 0x20,0x20,0xf8,0x20,0x20,0xe0,0x40,0xa0,
+ 0x60,0xc0,0x20,0x40,0xe0,0x80,0x40,0x80,
+ 0x80,0xf0,0x90,0x90,0x90,0x90,0x90,0x28,
+ 0x28,0x28,0x28,0x28,0x68,0xe8,0xe8,0xe8,
+ 0x7c,0xc0,0xc0,0x40,0x40,0x40,0xc0,0x40,
+ 0xe0,0x00,0xe0,0xa0,0xe0,0xa0,0x50,0x28,
+ 0x50,0xa0,0x21,0x00,0x17,0x80,0x13,0x00,
+ 0x09,0x00,0x48,0x00,0x44,0x00,0xc4,0x00,
+ 0x42,0x00,0x27,0x12,0x15,0x0b,0x48,0x44,
+ 0xc4,0x42,0x21,0x00,0x17,0x80,0x13,0x00,
+ 0x09,0x00,0xc8,0x00,0x24,0x00,0x44,0x00,
+ 0xe2,0x00,0x60,0x90,0x80,0x40,0x20,0x20,
+ 0x00,0x20,0x82,0x82,0x7c,0x44,0x28,0x28,
+ 0x10,0x10,0x00,0x10,0x20,0x82,0x82,0x7c,
+ 0x44,0x28,0x28,0x10,0x10,0x00,0x10,0x08,
+ 0x82,0x82,0x7c,0x44,0x28,0x28,0x10,0x10,
+ 0x00,0x28,0x10,0x82,0x82,0x7c,0x44,0x28,
+ 0x28,0x10,0x10,0x00,0x28,0x14,0x82,0x82,
+ 0x7c,0x44,0x28,0x28,0x10,0x10,0x00,0x28,
+ 0x82,0x82,0x7c,0x44,0x28,0x28,0x10,0x10,
+ 0x10,0x28,0x10,0x8f,0x80,0x88,0x00,0x78,
+ 0x00,0x48,0x00,0x2f,0x80,0x28,0x00,0x18,
+ 0x00,0x1f,0x80,0x30,0x10,0x78,0x84,0x80,
+ 0x80,0x80,0x80,0x84,0x78,0xf8,0x80,0x80,
+ 0x80,0xf8,0x80,0x80,0xf8,0x00,0x20,0x40,
+ 0xf8,0x80,0x80,0x80,0xf8,0x80,0x80,0xf8,
+ 0x00,0x20,0x10,0xf8,0x80,0x80,0xf8,0x80,
+ 0x80,0x80,0xf8,0x00,0x50,0x20,0xf8,0x80,
+ 0x80,0x80,0xf8,0x80,0x80,0xf8,0x00,0x50,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x00,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x00,0x80,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x00,0xa0,0x78,0x44,0x42,0x42,0xf2,
+ 0x42,0x44,0x78,0x8c,0x8c,0x94,0x94,0xa4,
+ 0xa4,0xc4,0xc4,0x00,0x50,0x28,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x78,0x00,0x10,
+ 0x20,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x78,0x00,0x10,0x08,0x78,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x78,0x00,0x28,0x10,0x78,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x78,0x00,
+ 0x50,0x28,0x78,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x78,0x00,0x48,0x88,0x50,0x20,0x50,
+ 0x88,0x80,0x78,0xc4,0xa4,0xa4,0x94,0x94,
+ 0x8c,0x78,0x04,0x78,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x00,0x10,0x20,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x20,
+ 0x10,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x00,0x28,0x10,0x78,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x00,0x48,0x10,0x10,
+ 0x10,0x28,0x28,0x44,0x44,0x82,0x00,0x10,
+ 0x08,0x80,0x80,0xf0,0x88,0x88,0xf0,0x80,
+ 0x80,0xa0,0x90,0x90,0x90,0xa0,0x90,0x90,
+ 0x60,0x68,0x90,0x90,0x70,0x10,0xe0,0x00,
+ 0x20,0x40,0x68,0x90,0x90,0x70,0x10,0xe0,
+ 0x00,0x20,0x10,0x68,0x90,0x90,0x70,0x10,
+ 0xe0,0x00,0x50,0x20,0x68,0x90,0x90,0x70,
+ 0x10,0xe0,0x00,0xa0,0x50,0x68,0x90,0x90,
+ 0x70,0x10,0xe0,0x00,0x50,0x68,0x90,0x90,
+ 0x70,0x10,0xe0,0x20,0x50,0x20,0x6c,0x92,
+ 0x90,0x7e,0x12,0xec,0x60,0x20,0x60,0x90,
+ 0x80,0x80,0x90,0x60,0x60,0x90,0x80,0xf0,
+ 0x90,0x60,0x00,0x20,0x40,0x60,0x90,0x80,
+ 0xf0,0x90,0x60,0x00,0x40,0x20,0x60,0x90,
+ 0x80,0xf0,0x90,0x60,0x00,0x50,0x20,0x60,
+ 0x90,0x80,0xf0,0x90,0x60,0x00,0x50,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
+ 0xa0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x00,0xa0,0x70,0x88,0x88,0x88,0x88,0x78,
+ 0x90,0x60,0x50,0x90,0x90,0x90,0x90,0x90,
+ 0xe0,0x00,0xa0,0x50,0x70,0x88,0x88,0x88,
+ 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88,
+ 0x88,0x88,0x70,0x00,0x20,0x10,0x70,0x88,
+ 0x88,0x88,0x88,0x70,0x00,0x50,0x20,0x70,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0x50,0x28,
+ 0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x50,
+ 0x20,0x00,0xf8,0x00,0x20,0x70,0x88,0xc8,
+ 0xa8,0x98,0x74,0x70,0x90,0x90,0x90,0x90,
+ 0x90,0x00,0x20,0x40,0x70,0x90,0x90,0x90,
+ 0x90,0x90,0x00,0x40,0x20,0x70,0x90,0x90,
+ 0x90,0x90,0x90,0x00,0x50,0x20,0x70,0x90,
+ 0x90,0x90,0x90,0x90,0x00,0x50,0x80,0x40,
+ 0x40,0x60,0xa0,0xa0,0x90,0x90,0x00,0x20,
+ 0x10,0x80,0x80,0xb0,0xc8,0x88,0x88,0xc8,
+ 0xb0,0x80,0x80,0x80,0x40,0x40,0x60,0xa0,
+ 0xa0,0x90,0x90,0x00,0x50,
+};
+
+BMF_FontData BMF_font_helv10 = {
+ -1, -2,
+ 10, 11,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 12, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 3, -1},
+ {1, 8, -1, 0, 3, 0},
+ {3, 2, -1, -6, 4, 8},
+ {6, 7, 0, 0, 6, 10},
+ {5, 9, 0, 1, 6, 17},
+ {8, 8, 0, 0, 9, 26},
+ {6, 8, -1, 0, 8, 34},
+ {2, 3, -1, -5, 3, 42},
+ {3, 10, 0, 2, 4, 45},
+ {3, 10, -1, 2, 4, 55},
+ {3, 3, 0, -5, 4, 65},
+ {5, 5, 0, -1, 6, 68},
+ {2, 3, 0, 2, 3, 73},
+ {5, 1, -1, -3, 7, 76},
+ {1, 1, -1, 0, 3, 77},
+ {3, 8, 0, 0, 3, 78},
+ {5, 8, 0, 0, 6, 86},
+ {2, 8, -1, 0, 6, 94},
+ {5, 8, 0, 0, 6, 102},
+ {5, 8, 0, 0, 6, 110},
+ {5, 8, 0, 0, 6, 118},
+ {5, 8, 0, 0, 6, 126},
+ {5, 8, 0, 0, 6, 134},
+ {5, 8, 0, 0, 6, 142},
+ {5, 8, 0, 0, 6, 150},
+ {5, 8, 0, 0, 6, 158},
+ {1, 6, -1, 0, 3, 166},
+ {2, 8, 0, 2, 3, 172},
+ {3, 5, -1, -1, 6, 180},
+ {4, 3, 0, -2, 5, 185},
+ {3, 5, -1, -1, 6, 188},
+ {4, 8, -1, 0, 6, 193},
+ {10, 10, 0, 2, 11, 201},
+ {7, 8, 0, 0, 7, 221},
+ {5, 8, -1, 0, 7, 229},
+ {6, 8, -1, 0, 8, 237},
+ {6, 8, -1, 0, 8, 245},
+ {5, 8, -1, 0, 7, 253},
+ {5, 8, -1, 0, 6, 261},
+ {6, 8, -1, 0, 8, 269},
+ {6, 8, -1, 0, 8, 277},
+ {1, 8, -1, 0, 3, 285},
+ {4, 8, 0, 0, 5, 293},
+ {5, 8, -1, 0, 7, 301},
+ {4, 8, -1, 0, 6, 309},
+ {7, 8, -1, 0, 9, 317},
+ {6, 8, -1, 0, 8, 325},
+ {6, 8, -1, 0, 8, 333},
+ {5, 8, -1, 0, 7, 341},
+ {7, 9, -1, 1, 8, 349},
+ {5, 8, -1, 0, 7, 358},
+ {5, 8, -1, 0, 7, 366},
+ {5, 8, 0, 0, 5, 374},
+ {6, 8, -1, 0, 8, 382},
+ {7, 8, 0, 0, 7, 390},
+ {9, 8, 0, 0, 9, 398},
+ {5, 8, -1, 0, 7, 414},
+ {7, 8, 0, 0, 7, 422},
+ {5, 8, -1, 0, 7, 430},
+ {2, 10, -1, 2, 3, 438},
+ {3, 8, 0, 0, 3, 448},
+ {2, 10, 0, 2, 3, 456},
+ {5, 5, 0, -3, 6, 466},
+ {6, 1, 0, 2, 6, 471},
+ {2, 3, 0, -5, 3, 472},
+ {5, 6, 0, 0, 5, 475},
+ {5, 8, 0, 0, 6, 481},
+ {4, 6, 0, 0, 5, 489},
+ {5, 8, 0, 0, 6, 495},
+ {4, 6, 0, 0, 5, 503},
+ {4, 8, 0, 0, 4, 509},
+ {5, 8, 0, 2, 6, 517},
+ {5, 8, 0, 0, 6, 525},
+ {1, 8, 0, 0, 2, 533},
+ {1, 9, 0, 1, 2, 541},
+ {4, 8, 0, 0, 5, 550},
+ {1, 8, 0, 0, 2, 558},
+ {7, 6, 0, 0, 8, 566},
+ {5, 6, 0, 0, 6, 572},
+ {5, 6, 0, 0, 6, 578},
+ {5, 8, 0, 2, 6, 584},
+ {5, 8, 0, 2, 6, 592},
+ {3, 6, 0, 0, 4, 600},
+ {4, 6, 0, 0, 5, 606},
+ {3, 8, 0, 0, 4, 612},
+ {4, 6, 0, 0, 5, 620},
+ {5, 6, 0, 0, 6, 626},
+ {7, 6, 0, 0, 8, 632},
+ {5, 6, 0, 0, 6, 638},
+ {4, 8, 0, 2, 5, 644},
+ {4, 6, 0, 0, 5, 652},
+ {3, 10, 0, 2, 3, 658},
+ {1, 10, -1, 2, 3, 668},
+ {3, 10, 0, 2, 3, 678},
+ {6, 2, 0, -3, 7, 688},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 3, -1},
+ {1, 8, -1, 2, 3, 690},
+ {5, 8, 0, 1, 6, 698},
+ {5, 8, 0, 0, 6, 706},
+ {4, 6, 0, -1, 5, 714},
+ {5, 8, 0, 0, 6, 720},
+ {1, 10, -1, 2, 3, 728},
+ {5, 10, 0, 2, 6, 738},
+ {3, 1, 0, -7, 3, 748},
+ {7, 7, -1, 0, 9, 749},
+ {3, 5, 0, -3, 4, 756},
+ {5, 5, 0, 0, 6, 761},
+ {5, 3, -1, -2, 7, 766},
+ {3, 1, 0, -3, 4, 769},
+ {7, 7, -1, 0, 9, 770},
+ {3, 1, 0, -7, 3, 777},
+ {4, 4, 0, -3, 4, 778},
+ {5, 7, 0, 0, 6, 782},
+ {3, 4, 0, -3, 3, 789},
+ {3, 4, 0, -3, 3, 793},
+ {2, 2, 0, -6, 3, 797},
+ {4, 8, 0, 2, 5, 799},
+ {6, 10, 0, 2, 6, 807},
+ {2, 1, 0, -3, 3, 817},
+ {2, 2, 0, 2, 3, 818},
+ {2, 4, 0, -3, 3, 820},
+ {3, 5, 0, -3, 4, 824},
+ {5, 5, 0, 0, 6, 829},
+ {9, 8, 0, 0, 9, 834},
+ {8, 8, 0, 0, 9, 850},
+ {9, 8, 0, 0, 9, 858},
+ {4, 8, -1, 2, 6, 874},
+ {7, 11, 0, 0, 7, 882},
+ {7, 11, 0, 0, 7, 893},
+ {7, 11, 0, 0, 7, 904},
+ {7, 11, 0, 0, 7, 915},
+ {7, 10, 0, 0, 7, 926},
+ {7, 11, 0, 0, 7, 936},
+ {9, 8, 0, 0, 10, 947},
+ {6, 10, -1, 2, 8, 963},
+ {5, 11, -1, 0, 7, 973},
+ {5, 11, -1, 0, 7, 984},
+ {5, 11, -1, 0, 7, 995},
+ {5, 10, -1, 0, 7, 1006},
+ {2, 11, 0, 0, 3, 1016},
+ {2, 11, -1, 0, 3, 1027},
+ {3, 11, 0, 0, 3, 1038},
+ {3, 10, 0, 0, 3, 1049},
+ {7, 8, 0, 0, 8, 1059},
+ {6, 11, -1, 0, 8, 1067},
+ {6, 11, -1, 0, 8, 1078},
+ {6, 11, -1, 0, 8, 1089},
+ {6, 11, -1, 0, 8, 1100},
+ {6, 11, -1, 0, 8, 1111},
+ {6, 10, -1, 0, 8, 1122},
+ {5, 5, 0, -1, 6, 1132},
+ {6, 10, -1, 1, 8, 1137},
+ {6, 11, -1, 0, 8, 1147},
+ {6, 11, -1, 0, 8, 1158},
+ {6, 11, -1, 0, 8, 1169},
+ {6, 10, -1, 0, 8, 1180},
+ {7, 11, 0, 0, 7, 1190},
+ {5, 8, -1, 0, 7, 1201},
+ {4, 8, 0, 0, 5, 1209},
+ {5, 9, 0, 0, 5, 1217},
+ {5, 9, 0, 0, 5, 1226},
+ {5, 9, 0, 0, 5, 1235},
+ {5, 9, 0, 0, 5, 1244},
+ {5, 8, 0, 0, 5, 1253},
+ {5, 9, 0, 0, 5, 1261},
+ {7, 6, 0, 0, 8, 1270},
+ {4, 8, 0, 2, 5, 1276},
+ {4, 9, 0, 0, 5, 1284},
+ {4, 9, 0, 0, 5, 1293},
+ {4, 9, 0, 0, 5, 1302},
+ {4, 8, 0, 0, 5, 1311},
+ {2, 9, 1, 0, 2, 1319},
+ {2, 9, 0, 0, 2, 1328},
+ {3, 9, 1, 0, 2, 1337},
+ {3, 8, 0, 0, 2, 1346},
+ {5, 9, 0, 0, 6, 1354},
+ {4, 9, 0, 0, 5, 1363},
+ {5, 9, 0, 0, 6, 1372},
+ {5, 9, 0, 0, 6, 1381},
+ {5, 9, 0, 0, 6, 1390},
+ {5, 9, 0, 0, 6, 1399},
+ {5, 8, 0, 0, 6, 1408},
+ {5, 5, 0, -1, 6, 1416},
+ {6, 6, 0, 0, 6, 1421},
+ {4, 9, 0, 0, 5, 1427},
+ {4, 9, 0, 0, 5, 1436},
+ {4, 9, 0, 0, 5, 1445},
+ {4, 8, 0, 0, 5, 1454},
+ {4, 11, 0, 2, 5, 1462},
+ {5, 10, 0, 2, 6, 1473},
+ {4, 10, 0, 2, 5, 1483},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_helv12.cpp b/intern/bmfont/intern/BMF_font_helv12.cpp
new file mode 100644
index 00000000000..45ab6531cdb
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helv12.cpp
@@ -0,0 +1,525 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELV12
+
+static unsigned char bitmap_data[]= {
+ 0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0xa0,0xa0,0xa0,0x50,0x50,0x50,0xfc,
+ 0x28,0xfc,0x28,0x28,0x20,0x70,0xa8,0xa8,
+ 0x28,0x70,0xa0,0xa8,0x70,0x20,0x23,0x00,
+ 0x14,0x80,0x14,0x80,0x13,0x00,0x08,0x00,
+ 0x68,0x00,0x94,0x00,0x94,0x00,0x62,0x00,
+ 0x72,0x8c,0x84,0x8a,0x50,0x30,0x48,0x48,
+ 0x30,0x80,0x40,0xc0,0x20,0x40,0x40,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x20,
+ 0x80,0x40,0x40,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x40,0x40,0x80,0xa0,0x40,0xa0,0x20,
+ 0x20,0xf8,0x20,0x20,0x80,0x40,0x40,0xf8,
+ 0x80,0x80,0x80,0x40,0x40,0x40,0x20,0x20,
+ 0x10,0x10,0x70,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x70,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0xe0,0x20,0xf8,0x80,0x80,0x40,
+ 0x20,0x10,0x08,0x88,0x70,0x70,0x88,0x88,
+ 0x08,0x08,0x30,0x08,0x88,0x70,0x08,0x08,
+ 0xfc,0x88,0x48,0x28,0x28,0x18,0x08,0x70,
+ 0x88,0x88,0x08,0x08,0xf0,0x80,0x80,0xf8,
+ 0x70,0x88,0x88,0x88,0xc8,0xb0,0x80,0x88,
+ 0x70,0x40,0x40,0x20,0x20,0x20,0x10,0x10,
+ 0x08,0xf8,0x70,0x88,0x88,0x88,0x88,0x70,
+ 0x88,0x88,0x70,0x70,0x88,0x08,0x08,0x78,
+ 0x88,0x88,0x88,0x70,0x80,0x00,0x00,0x00,
+ 0x00,0x80,0x80,0x40,0x40,0x00,0x00,0x00,
+ 0x00,0x40,0x0c,0x30,0xc0,0x30,0x0c,0xf8,
+ 0x00,0xf8,0xc0,0x30,0x0c,0x30,0xc0,0x20,
+ 0x00,0x20,0x20,0x10,0x10,0x88,0x88,0x70,
+ 0x3e,0x00,0x40,0x00,0x9b,0x00,0xa6,0x80,
+ 0xa2,0x40,0xa2,0x40,0x92,0x40,0x4d,0x40,
+ 0x60,0x80,0x1f,0x00,0x82,0x82,0x82,0x7c,
+ 0x44,0x44,0x28,0x28,0x10,0xf8,0x84,0x84,
+ 0x84,0xf8,0x84,0x84,0x84,0xf8,0x3c,0x42,
+ 0x80,0x80,0x80,0x80,0x80,0x42,0x3c,0xf8,
+ 0x84,0x82,0x82,0x82,0x82,0x82,0x84,0xf8,
+ 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80,
+ 0xfc,0x80,0x80,0x80,0x80,0xf8,0x80,0x80,
+ 0x80,0xfc,0x3a,0x46,0x82,0x82,0x8e,0x80,
+ 0x80,0x42,0x3c,0x82,0x82,0x82,0x82,0xfe,
+ 0x82,0x82,0x82,0x82,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x70,0x88,0x88,
+ 0x08,0x08,0x08,0x08,0x08,0x08,0x82,0x84,
+ 0x88,0x90,0xe0,0xa0,0x90,0x88,0x84,0xf8,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x88,0x80,0x88,0x80,0x94,0x80,0x94,0x80,
+ 0xa2,0x80,0xa2,0x80,0xc1,0x80,0xc1,0x80,
+ 0x80,0x80,0x82,0x86,0x8a,0x8a,0x92,0xa2,
+ 0xa2,0xc2,0x82,0x3c,0x42,0x81,0x81,0x81,
+ 0x81,0x81,0x42,0x3c,0x80,0x80,0x80,0x80,
+ 0xf8,0x84,0x84,0x84,0xf8,0x3d,0x42,0x85,
+ 0x89,0x81,0x81,0x81,0x42,0x3c,0x84,0x84,
+ 0x84,0x88,0xf8,0x84,0x84,0x84,0xf8,0x78,
+ 0x84,0x84,0x04,0x18,0x60,0x80,0x84,0x78,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0xfe,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x10,0x10,0x28,0x28,0x44,0x44,
+ 0x44,0x82,0x82,0x22,0x00,0x22,0x00,0x22,
+ 0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x88,
+ 0x80,0x88,0x80,0x88,0x80,0x82,0x44,0x44,
+ 0x28,0x10,0x28,0x44,0x44,0x82,0x10,0x10,
+ 0x10,0x10,0x28,0x44,0x44,0x82,0x82,0xfe,
+ 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0xfe,
+ 0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0xc0,0x10,0x10,0x20,0x20,
+ 0x20,0x40,0x40,0x80,0x80,0xc0,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0xc0,0x88,0x50,0x20,0xfe,0xc0,0x80,0x40,
+ 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0xb0,
+ 0xc8,0x88,0x88,0x88,0xc8,0xb0,0x80,0x80,
+ 0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x68,
+ 0x98,0x88,0x88,0x88,0x98,0x68,0x08,0x08,
+ 0x70,0x88,0x80,0xf8,0x88,0x88,0x70,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0xe0,0x40,0x30,
+ 0x70,0x88,0x08,0x68,0x98,0x88,0x88,0x88,
+ 0x98,0x68,0x88,0x88,0x88,0x88,0x88,0xc8,
+ 0xb0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x00,0x80,0x80,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40,
+ 0x88,0x90,0xa0,0xc0,0xc0,0xa0,0x90,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x92,0x92,0x92,0x92,0x92,0xda,
+ 0xa4,0x88,0x88,0x88,0x88,0x88,0xc8,0xb0,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x80,
+ 0x80,0x80,0xb0,0xc8,0x88,0x88,0x88,0xc8,
+ 0xb0,0x08,0x08,0x08,0x68,0x98,0x88,0x88,
+ 0x88,0x98,0x68,0x80,0x80,0x80,0x80,0x80,
+ 0xc0,0xa0,0x60,0x90,0x10,0x60,0x80,0x90,
+ 0x60,0x60,0x40,0x40,0x40,0x40,0x40,0xe0,
+ 0x40,0x40,0x68,0x98,0x88,0x88,0x88,0x88,
+ 0x88,0x20,0x20,0x50,0x50,0x88,0x88,0x88,
+ 0x22,0x00,0x22,0x00,0x55,0x00,0x49,0x00,
+ 0x49,0x00,0x88,0x80,0x88,0x80,0x84,0x84,
+ 0x48,0x30,0x30,0x48,0x84,0x80,0x40,0x20,
+ 0x20,0x50,0x50,0x90,0x88,0x88,0x88,0xf0,
+ 0x80,0x40,0x40,0x20,0x10,0xf0,0x30,0x40,
+ 0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,
+ 0x40,0x30,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0x20,
+ 0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,
+ 0x20,0xc0,0x98,0x64,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x00,0x80,0x40,0x70,
+ 0xc8,0xa0,0xa0,0xa0,0xa8,0x70,0x10,0xb0,
+ 0x48,0x20,0x20,0xf0,0x40,0x40,0x48,0x30,
+ 0x84,0x78,0x48,0x48,0x78,0x84,0x20,0x20,
+ 0xf8,0x20,0xf8,0x20,0x50,0x88,0x88,0x80,
+ 0x80,0x80,0x80,0x00,0x00,0x00,0x80,0x80,
+ 0x80,0x80,0x70,0x88,0x08,0x30,0x48,0x88,
+ 0x88,0x90,0x60,0x80,0x88,0x70,0xa0,0x3e,
+ 0x00,0x41,0x00,0x9c,0x80,0xa2,0x80,0xa0,
+ 0x80,0xa2,0x80,0x9c,0x80,0x41,0x00,0x3e,
+ 0x00,0xe0,0x00,0xa0,0x20,0xe0,0x28,0x50,
+ 0xa0,0x50,0x28,0x04,0x04,0x04,0xfc,0xf0,
+ 0x3e,0x00,0x41,0x00,0x94,0x80,0x94,0x80,
+ 0x98,0x80,0x94,0x80,0x9c,0x80,0x41,0x00,
+ 0x3e,0x00,0xf0,0x60,0x90,0x90,0x60,0xf8,
+ 0x00,0x20,0x20,0xf8,0x20,0x20,0xf0,0x40,
+ 0x20,0x90,0x60,0xc0,0x20,0x40,0x20,0xe0,
+ 0x80,0x40,0x80,0x80,0x80,0xe8,0x98,0x88,
+ 0x88,0x88,0x88,0x88,0x28,0x28,0x28,0x28,
+ 0x28,0x28,0x68,0xe8,0xe8,0xe8,0x68,0x3c,
+ 0x80,0xc0,0x20,0x20,0x40,0x40,0x40,0x40,
+ 0xc0,0x40,0xe0,0x00,0xe0,0xa0,0xe0,0xa0,
+ 0x50,0x28,0x50,0xa0,0x41,0x00,0x27,0x80,
+ 0x15,0x00,0x13,0x00,0x49,0x00,0x44,0x00,
+ 0x44,0x00,0xc2,0x00,0x41,0x00,0x47,0x80,
+ 0x22,0x00,0x11,0x00,0x14,0x80,0x4b,0x00,
+ 0x48,0x00,0x44,0x00,0xc2,0x00,0x41,0x00,
+ 0x21,0x00,0x17,0x80,0x15,0x00,0x0b,0x00,
+ 0xc9,0x00,0x24,0x00,0x44,0x00,0x22,0x00,
+ 0xe1,0x00,0x70,0x88,0x88,0x40,0x40,0x20,
+ 0x20,0x00,0x20,0x82,0x82,0x82,0x7c,0x44,
+ 0x44,0x28,0x10,0x10,0x00,0x10,0x20,0x82,
+ 0x82,0x82,0x7c,0x44,0x44,0x28,0x10,0x10,
+ 0x00,0x10,0x08,0x82,0x82,0x82,0x7c,0x44,
+ 0x44,0x28,0x10,0x10,0x00,0x28,0x10,0x82,
+ 0x82,0x82,0x7c,0x44,0x44,0x28,0x10,0x10,
+ 0x00,0x28,0x14,0x82,0x82,0x82,0x7c,0x44,
+ 0x44,0x28,0x10,0x10,0x00,0x28,0x82,0x82,
+ 0x82,0x7c,0x44,0x44,0x28,0x10,0x10,0x10,
+ 0x28,0x10,0x8f,0x80,0x88,0x00,0x88,0x00,
+ 0x78,0x00,0x4f,0x80,0x48,0x00,0x28,0x00,
+ 0x28,0x00,0x1f,0x80,0x30,0x08,0x08,0x3c,
+ 0x42,0x80,0x80,0x80,0x80,0x80,0x42,0x3c,
+ 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80,
+ 0xfc,0x00,0x10,0x20,0xfc,0x80,0x80,0x80,
+ 0xfc,0x80,0x80,0x80,0xfc,0x00,0x10,0x08,
+ 0xfc,0x80,0x80,0x80,0xfc,0x80,0x80,0x80,
+ 0xfc,0x00,0x28,0x10,0xfc,0x80,0x80,0x80,
+ 0xfc,0x80,0x80,0x80,0xfc,0x00,0x28,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x00,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x00,0x80,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x00,0xa0,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x00,0xa0,0x7c,0x42,
+ 0x41,0x41,0xf1,0x41,0x41,0x42,0x7c,0x82,
+ 0x86,0x8a,0x8a,0x92,0xa2,0xa2,0xc2,0x82,
+ 0x00,0x28,0x14,0x3c,0x42,0x81,0x81,0x81,
+ 0x81,0x81,0x42,0x3c,0x00,0x08,0x10,0x3c,
+ 0x42,0x81,0x81,0x81,0x81,0x81,0x42,0x3c,
+ 0x00,0x08,0x04,0x3c,0x42,0x81,0x81,0x81,
+ 0x81,0x81,0x42,0x3c,0x00,0x14,0x08,0x3c,
+ 0x42,0x81,0x81,0x81,0x81,0x81,0x42,0x3c,
+ 0x00,0x28,0x14,0x3c,0x42,0x81,0x81,0x81,
+ 0x81,0x81,0x42,0x3c,0x00,0x24,0x88,0x50,
+ 0x20,0x50,0x88,0x80,0x00,0x5e,0x00,0x21,
+ 0x00,0x50,0x80,0x48,0x80,0x44,0x80,0x44,
+ 0x80,0x42,0x80,0x21,0x00,0x1e,0x80,0x00,
+ 0x40,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x00,0x10,0x20,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x10,
+ 0x08,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x00,0x28,0x10,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x48,
+ 0x10,0x10,0x10,0x10,0x28,0x44,0x44,0x82,
+ 0x82,0x00,0x10,0x08,0x80,0x80,0xf8,0x84,
+ 0x84,0x84,0xf8,0x80,0x80,0xb0,0x88,0x88,
+ 0x88,0xb0,0x88,0x88,0x88,0x70,0x74,0x88,
+ 0x88,0x78,0x08,0x88,0x70,0x00,0x10,0x20,
+ 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0x00,
+ 0x20,0x10,0x74,0x88,0x88,0x78,0x08,0x88,
+ 0x70,0x00,0x50,0x20,0x74,0x88,0x88,0x78,
+ 0x08,0x88,0x70,0x00,0x50,0x28,0x74,0x88,
+ 0x88,0x78,0x08,0x88,0x70,0x00,0x50,0x74,
+ 0x88,0x88,0x78,0x08,0x88,0x70,0x30,0x48,
+ 0x30,0x77,0x00,0x88,0x80,0x88,0x00,0x7f,
+ 0x80,0x08,0x80,0x88,0x80,0x77,0x00,0x60,
+ 0x10,0x20,0x70,0x88,0x80,0x80,0x80,0x88,
+ 0x70,0x70,0x88,0x80,0xf8,0x88,0x88,0x70,
+ 0x00,0x20,0x40,0x70,0x88,0x80,0xf8,0x88,
+ 0x88,0x70,0x00,0x20,0x10,0x70,0x88,0x80,
+ 0xf8,0x88,0x88,0x70,0x00,0x50,0x20,0x70,
+ 0x88,0x80,0xf8,0x88,0x88,0x70,0x00,0x50,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
+ 0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x00,0x80,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x00,0xa0,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x00,0xa0,0x70,
+ 0x88,0x88,0x88,0x88,0x78,0x08,0x50,0x30,
+ 0x68,0x88,0x88,0x88,0x88,0x88,0xc8,0xb0,
+ 0x00,0x50,0x28,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x70,0x00,0x20,0x10,0x70,
+ 0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x50,
+ 0x20,0x70,0x88,0x88,0x88,0x88,0x88,0x70,
+ 0x00,0x50,0x28,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x70,0x00,0x50,0x20,0x00,0xf8,0x00,
+ 0x20,0xb8,0x44,0x64,0x54,0x4c,0x44,0x3a,
+ 0x68,0x98,0x88,0x88,0x88,0x88,0x88,0x00,
+ 0x20,0x40,0x68,0x98,0x88,0x88,0x88,0x88,
+ 0x88,0x00,0x20,0x10,0x68,0x98,0x88,0x88,
+ 0x88,0x88,0x88,0x00,0x50,0x20,0x68,0x98,
+ 0x88,0x88,0x88,0x88,0x88,0x00,0x50,0x80,
+ 0x40,0x20,0x20,0x50,0x50,0x90,0x88,0x88,
+ 0x88,0x00,0x20,0x10,0x80,0x80,0x80,0xb0,
+ 0xc8,0x88,0x88,0x88,0xc8,0xb0,0x80,0x80,
+ 0xc0,0x20,0x20,0x20,0x30,0x50,0x50,0x48,
+ 0x88,0x88,0x00,0x50,
+};
+
+BMF_FontData BMF_font_helv12 = {
+ 0, -3,
+ 11, 12,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 16, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 4, -1},
+ {1, 9, -1, 0, 3, 0},
+ {3, 3, -1, -6, 5, 9},
+ {6, 8, 0, 0, 7, 12},
+ {5, 10, -1, 1, 7, 20},
+ {9, 9, -1, 0, 11, 30},
+ {7, 9, -1, 0, 9, 48},
+ {2, 3, -1, -6, 3, 57},
+ {3, 12, -1, 3, 4, 60},
+ {3, 12, 0, 3, 4, 72},
+ {3, 3, -1, -6, 5, 84},
+ {5, 5, -1, -1, 7, 87},
+ {2, 3, -1, 2, 4, 92},
+ {5, 1, -1, -3, 8, 95},
+ {1, 1, -1, 0, 3, 96},
+ {4, 9, 0, 0, 4, 97},
+ {5, 9, -1, 0, 7, 106},
+ {3, 9, -1, 0, 7, 115},
+ {5, 9, -1, 0, 7, 124},
+ {5, 9, -1, 0, 7, 133},
+ {6, 9, 0, 0, 7, 142},
+ {5, 9, -1, 0, 7, 151},
+ {5, 9, -1, 0, 7, 160},
+ {5, 9, -1, 0, 7, 169},
+ {5, 9, -1, 0, 7, 178},
+ {5, 9, -1, 0, 7, 187},
+ {1, 6, -1, 0, 3, 196},
+ {2, 8, 0, 2, 3, 202},
+ {6, 5, 0, -1, 7, 210},
+ {5, 3, -1, -2, 7, 215},
+ {6, 5, -1, -1, 7, 218},
+ {5, 9, -1, 0, 7, 223},
+ {10, 10, -1, 1, 12, 232},
+ {7, 9, -1, 0, 9, 252},
+ {6, 9, -1, 0, 8, 261},
+ {7, 9, -1, 0, 9, 270},
+ {7, 9, -1, 0, 9, 279},
+ {6, 9, -1, 0, 8, 288},
+ {6, 9, -1, 0, 8, 297},
+ {7, 9, -1, 0, 9, 306},
+ {7, 9, -1, 0, 9, 315},
+ {1, 9, -1, 0, 3, 324},
+ {5, 9, -1, 0, 7, 333},
+ {7, 9, -1, 0, 8, 342},
+ {5, 9, -1, 0, 7, 351},
+ {9, 9, -1, 0, 11, 360},
+ {7, 9, -1, 0, 9, 378},
+ {8, 9, -1, 0, 10, 387},
+ {6, 9, -1, 0, 8, 396},
+ {8, 9, -1, 0, 10, 405},
+ {6, 9, -1, 0, 8, 414},
+ {6, 9, -1, 0, 8, 423},
+ {7, 9, 0, 0, 7, 432},
+ {6, 9, -1, 0, 8, 441},
+ {7, 9, -1, 0, 9, 450},
+ {9, 9, -1, 0, 11, 459},
+ {7, 9, -1, 0, 9, 477},
+ {7, 9, -1, 0, 9, 486},
+ {7, 9, -1, 0, 9, 495},
+ {2, 12, -1, 3, 3, 504},
+ {4, 9, 0, 0, 4, 516},
+ {2, 12, 0, 3, 3, 525},
+ {5, 3, 0, -5, 6, 537},
+ {7, 1, 0, 2, 7, 540},
+ {2, 3, 0, -6, 3, 541},
+ {6, 7, -1, 0, 7, 544},
+ {5, 9, -1, 0, 7, 551},
+ {5, 7, -1, 0, 7, 560},
+ {5, 9, -1, 0, 7, 567},
+ {5, 7, -1, 0, 7, 576},
+ {4, 9, 0, 0, 3, 583},
+ {5, 10, -1, 3, 7, 592},
+ {5, 9, -1, 0, 7, 602},
+ {1, 9, -1, 0, 3, 611},
+ {2, 12, 0, 3, 3, 620},
+ {5, 9, -1, 0, 6, 632},
+ {1, 9, -1, 0, 3, 641},
+ {7, 7, -1, 0, 9, 650},
+ {5, 7, -1, 0, 7, 657},
+ {5, 7, -1, 0, 7, 664},
+ {5, 10, -1, 3, 7, 671},
+ {5, 10, -1, 3, 7, 681},
+ {3, 7, -1, 0, 4, 691},
+ {4, 7, -1, 0, 6, 698},
+ {3, 9, 0, 0, 3, 705},
+ {5, 7, -1, 0, 7, 714},
+ {5, 7, -1, 0, 7, 721},
+ {9, 7, 0, 0, 9, 728},
+ {6, 7, 0, 0, 6, 742},
+ {5, 10, -1, 3, 7, 749},
+ {4, 7, -1, 0, 6, 759},
+ {4, 12, 0, 3, 4, 766},
+ {1, 12, -1, 3, 3, 778},
+ {4, 12, 0, 3, 4, 790},
+ {6, 2, 0, -3, 7, 802},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 4, -1},
+ {1, 10, -1, 3, 3, 804},
+ {5, 9, -1, 1, 7, 814},
+ {5, 9, -1, 0, 7, 823},
+ {6, 6, 0, -1, 7, 832},
+ {5, 9, -1, 0, 7, 838},
+ {1, 11, -1, 2, 3, 847},
+ {5, 12, 0, 3, 6, 858},
+ {3, 1, 0, -8, 3, 870},
+ {9, 9, -1, 0, 11, 871},
+ {3, 5, -1, -4, 5, 889},
+ {5, 5, -1, -1, 7, 894},
+ {6, 4, -1, -2, 8, 899},
+ {4, 1, 0, -3, 5, 903},
+ {9, 9, -1, 0, 11, 904},
+ {4, 1, 0, -8, 4, 922},
+ {4, 4, 0, -4, 5, 923},
+ {5, 7, -1, 0, 7, 927},
+ {4, 5, 0, -3, 4, 934},
+ {3, 5, 0, -3, 4, 939},
+ {2, 2, 0, -8, 2, 944},
+ {5, 10, -1, 3, 7, 946},
+ {6, 12, 0, 3, 7, 956},
+ {1, 1, -1, -3, 3, 968},
+ {3, 4, 0, 3, 3, 969},
+ {2, 5, -1, -3, 4, 973},
+ {3, 5, -1, -4, 5, 978},
+ {5, 5, -1, -1, 7, 983},
+ {9, 9, 0, 0, 10, 988},
+ {9, 9, 0, 0, 10, 1006},
+ {9, 9, 0, 0, 10, 1024},
+ {5, 9, -1, 3, 7, 1042},
+ {7, 12, -1, 0, 9, 1051},
+ {7, 12, -1, 0, 9, 1063},
+ {7, 12, -1, 0, 9, 1075},
+ {7, 12, -1, 0, 9, 1087},
+ {7, 11, -1, 0, 9, 1099},
+ {7, 12, -1, 0, 9, 1110},
+ {9, 9, -1, 0, 11, 1122},
+ {7, 12, -1, 3, 9, 1140},
+ {6, 12, -1, 0, 8, 1152},
+ {6, 12, -1, 0, 8, 1164},
+ {6, 12, -1, 0, 8, 1176},
+ {6, 11, -1, 0, 8, 1188},
+ {2, 12, 0, 0, 3, 1199},
+ {2, 12, -1, 0, 3, 1211},
+ {3, 12, 0, 0, 3, 1223},
+ {3, 11, 0, 0, 3, 1235},
+ {8, 9, 0, 0, 9, 1246},
+ {7, 12, -1, 0, 9, 1255},
+ {8, 12, -1, 0, 10, 1267},
+ {8, 12, -1, 0, 10, 1279},
+ {8, 12, -1, 0, 10, 1291},
+ {8, 12, -1, 0, 10, 1303},
+ {8, 11, -1, 0, 10, 1315},
+ {5, 5, -1, -1, 7, 1326},
+ {10, 11, 0, 1, 10, 1331},
+ {6, 12, -1, 0, 8, 1353},
+ {6, 12, -1, 0, 8, 1365},
+ {6, 12, -1, 0, 8, 1377},
+ {6, 11, -1, 0, 8, 1389},
+ {7, 12, -1, 0, 9, 1400},
+ {6, 9, -1, 0, 8, 1412},
+ {5, 9, -1, 0, 7, 1421},
+ {6, 10, -1, 0, 7, 1430},
+ {6, 10, -1, 0, 7, 1440},
+ {6, 10, -1, 0, 7, 1450},
+ {6, 10, -1, 0, 7, 1460},
+ {6, 9, -1, 0, 7, 1470},
+ {6, 10, -1, 0, 7, 1479},
+ {9, 7, -1, 0, 11, 1489},
+ {5, 10, -1, 3, 7, 1503},
+ {5, 10, -1, 0, 7, 1513},
+ {5, 10, -1, 0, 7, 1523},
+ {5, 10, -1, 0, 7, 1533},
+ {5, 9, -1, 0, 7, 1543},
+ {2, 10, 0, 0, 3, 1552},
+ {2, 10, -1, 0, 3, 1562},
+ {3, 10, 0, 0, 3, 1572},
+ {3, 9, 0, 0, 3, 1582},
+ {5, 10, -1, 0, 7, 1591},
+ {5, 10, -1, 0, 7, 1601},
+ {5, 10, -1, 0, 7, 1611},
+ {5, 10, -1, 0, 7, 1621},
+ {5, 10, -1, 0, 7, 1631},
+ {5, 10, -1, 0, 7, 1641},
+ {5, 9, -1, 0, 7, 1651},
+ {5, 5, -1, -1, 7, 1660},
+ {7, 7, 0, 0, 7, 1665},
+ {5, 10, -1, 0, 7, 1672},
+ {5, 10, -1, 0, 7, 1682},
+ {5, 10, -1, 0, 7, 1692},
+ {5, 9, -1, 0, 7, 1702},
+ {5, 13, -1, 3, 7, 1711},
+ {5, 12, -1, 3, 7, 1724},
+ {5, 12, -1, 3, 7, 1736},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_helvb10.cpp b/intern/bmfont/intern/BMF_font_helvb10.cpp
new file mode 100644
index 00000000000..4707abfeda2
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helvb10.cpp
@@ -0,0 +1,492 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELVB10
+
+static unsigned char bitmap_data[]= {
+ 0x00,0xc0,0x00,0x80,0x80,0xc0,0xc0,0xc0,
+ 0xc0,0xa0,0xa0,0xa0,0x50,0x50,0xfc,0x28,
+ 0x7e,0x28,0x28,0x20,0x70,0xa8,0x28,0x38,
+ 0x70,0xe0,0xa8,0x70,0x20,0x8c,0x56,0x2c,
+ 0x10,0x10,0x68,0xb4,0x62,0x76,0xdc,0xcc,
+ 0xde,0x70,0xd8,0xd8,0x70,0x80,0x40,0xc0,
+ 0xc0,0x20,0x60,0x40,0xc0,0xc0,0xc0,0xc0,
+ 0x40,0x60,0x20,0x80,0xc0,0x40,0x60,0x60,
+ 0x60,0x60,0x40,0xc0,0x80,0xa0,0x40,0xa0,
+ 0x30,0x30,0xfc,0x30,0x30,0x80,0x40,0xc0,
+ 0xc0,0xf8,0xc0,0xc0,0x80,0x80,0x40,0x40,
+ 0x20,0x20,0x10,0x10,0x70,0xd8,0xd8,0xd8,
+ 0xd8,0xd8,0xd8,0x70,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0xe0,0x60,0xf8,0xc0,0x60,0x30,
+ 0x18,0x18,0xd8,0x70,0x70,0xd8,0x18,0x18,
+ 0x30,0x18,0xd8,0x70,0x18,0x18,0xfc,0x98,
+ 0x58,0x38,0x18,0x08,0x70,0xd8,0x98,0x18,
+ 0xf0,0xc0,0xc0,0xf8,0x70,0xd8,0xd8,0xd8,
+ 0xf0,0xc0,0xd8,0x70,0x60,0x60,0x60,0x30,
+ 0x30,0x18,0x18,0xf8,0x70,0xd8,0xd8,0xd8,
+ 0x70,0xd8,0xd8,0x70,0x70,0xd8,0x18,0x78,
+ 0xd8,0xd8,0xd8,0x70,0xc0,0xc0,0x00,0x00,
+ 0xc0,0xc0,0x80,0x40,0xc0,0xc0,0x00,0x00,
+ 0xc0,0xc0,0x30,0x60,0xc0,0x60,0x30,0xf8,
+ 0x00,0xf8,0xc0,0x60,0x30,0x60,0xc0,0x60,
+ 0x00,0x60,0x60,0x30,0x18,0xd8,0x70,0x3e,
+ 0x00,0x40,0x00,0x9b,0x00,0xa4,0x80,0xa2,
+ 0x40,0x92,0x40,0x4d,0x40,0x60,0x80,0x1f,
+ 0x00,0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38,
+ 0x38,0xf8,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc,
+ 0xf8,0x3c,0x66,0xc2,0xc0,0xc0,0xc2,0x66,
+ 0x3c,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xd8,
+ 0xf0,0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,
+ 0xf8,0xc0,0xc0,0xc0,0xc0,0xf0,0xc0,0xc0,
+ 0xf8,0x3a,0x66,0xc6,0xce,0xc0,0xc2,0x66,
+ 0x3c,0xcc,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,
+ 0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0x70,0xd8,0x18,0x18,0x18,0x18,0x18,
+ 0x18,0xc6,0xcc,0xd8,0xf0,0xe0,0xf0,0xd8,
+ 0xcc,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc9,0x80,0xc9,0x80,0xdd,0x80,0xd5,
+ 0x80,0xf7,0x80,0xe3,0x80,0xe3,0x80,0xc1,
+ 0x80,0xc6,0xce,0xce,0xd6,0xd6,0xe6,0xe6,
+ 0xc6,0x38,0x6c,0xc6,0xc6,0xc6,0xc6,0x6c,
+ 0x38,0xc0,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,
+ 0xf8,0x02,0x3c,0x6c,0xd6,0xc6,0xc6,0xc6,
+ 0x6c,0x38,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc,
+ 0xcc,0xf8,0x78,0xcc,0x8c,0x1c,0x78,0xe0,
+ 0xcc,0x78,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0xfc,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0x10,0x38,0x38,0x6c,0x6c,0x6c,
+ 0xc6,0xc6,0x33,0x00,0x33,0x00,0x7f,0x80,
+ 0x6d,0x80,0x6d,0x80,0xcc,0xc0,0xcc,0xc0,
+ 0xcc,0xc0,0xc6,0xc6,0x6c,0x38,0x38,0x6c,
+ 0xc6,0xc6,0x18,0x18,0x18,0x3c,0x66,0x66,
+ 0xc3,0xc3,0xfc,0xc0,0x60,0x70,0x30,0x18,
+ 0x0c,0xfc,0xe0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xe0,0x10,0x10,0x20,0x20,
+ 0x40,0x40,0x80,0x80,0xe0,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0xe0,0x90,0x90,
+ 0xf0,0x60,0xfc,0xc0,0xc0,0x80,0x40,0x6c,
+ 0xd8,0xd8,0x78,0x98,0x70,0xf0,0xd8,0xd8,
+ 0xd8,0xd8,0xf0,0xc0,0xc0,0x70,0xd0,0xc0,
+ 0xc0,0xd0,0x70,0x78,0xd8,0xd8,0xd8,0xd8,
+ 0x78,0x18,0x18,0x70,0xd8,0xc0,0xf8,0xd8,
+ 0x70,0x60,0x60,0x60,0x60,0x60,0xf0,0x60,
+ 0x38,0x70,0x18,0x78,0xd8,0xd8,0xd8,0xd8,
+ 0x68,0xd8,0xd8,0xd8,0xd8,0xd8,0xf0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,
+ 0xc0,0xc0,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x00,0x60,0xcc,0xd8,0xf0,0xe0,0xf0,
+ 0xd8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xdb,0xdb,0xdb,0xdb,0xdb,
+ 0xb6,0xd8,0xd8,0xd8,0xd8,0xd8,0xb0,0x70,
+ 0xd8,0xd8,0xd8,0xd8,0x70,0xc0,0xc0,0xf0,
+ 0xd8,0xd8,0xd8,0xd8,0xb0,0x18,0x18,0x78,
+ 0xd8,0xd8,0xd8,0xd8,0x68,0xc0,0xc0,0xc0,
+ 0xc0,0xe0,0xb0,0x70,0xd8,0x18,0x70,0xd8,
+ 0x70,0x30,0x60,0x60,0x60,0x60,0xf0,0x60,
+ 0x60,0x68,0xd8,0xd8,0xd8,0xd8,0xd8,0x20,
+ 0x70,0x50,0xd8,0xd8,0xd8,0x6c,0x6c,0x6c,
+ 0xd6,0xd6,0xd6,0xcc,0xcc,0x78,0x30,0x78,
+ 0xcc,0x60,0x30,0x30,0x78,0xd8,0xd8,0xd8,
+ 0xd8,0xf8,0xc0,0x60,0x30,0x18,0xf8,0x30,
+ 0x60,0x60,0x60,0x60,0xc0,0x60,0x60,0x60,
+ 0x30,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0xc0,0x60,0x60,0x60,0x60,
+ 0x30,0x60,0x60,0x60,0xc0,0xb0,0x68,0x00,
+ 0xc0,0xc0,0xc0,0xc0,0x40,0x40,0x00,0xc0,
+ 0x40,0x70,0xd8,0xa0,0xa0,0xd8,0x70,0x10,
+ 0xd8,0x68,0x60,0x60,0xf0,0x60,0x68,0x38,
+ 0x84,0x78,0x48,0x48,0x78,0x84,0x30,0xfc,
+ 0x30,0xfc,0x48,0xcc,0x84,0x84,0x80,0x80,
+ 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,
+ 0x70,0x98,0x38,0x70,0xc8,0x98,0x70,0xe0,
+ 0xc8,0x70,0xa0,0x3c,0x42,0x9d,0xa1,0xa5,
+ 0x99,0x42,0x3c,0xe0,0x00,0xa0,0x20,0xe0,
+ 0x6c,0xd8,0x6c,0x08,0x08,0xf8,0xf0,0x3c,
+ 0x42,0xa5,0xb9,0xa5,0xbd,0x42,0x3c,0xe0,
+ 0xc0,0xa0,0x60,0xfc,0x00,0x30,0x30,0xfc,
+ 0x30,0x30,0xe0,0x40,0xa0,0x60,0xc0,0x20,
+ 0x40,0xe0,0x80,0x40,0xc0,0xc0,0xe8,0xd8,
+ 0xd8,0xd8,0xd8,0xd8,0x28,0x28,0x28,0x28,
+ 0x28,0x68,0xe8,0xe8,0xe8,0x7c,0xc0,0xc0,
+ 0x40,0x40,0x40,0xc0,0x40,0xe0,0x00,0xe0,
+ 0xa0,0xe0,0xd8,0x6c,0xd8,0x42,0x2f,0x26,
+ 0x12,0x48,0x48,0xc4,0x44,0x4e,0x24,0x2a,
+ 0x16,0x48,0x48,0xc4,0x44,0x42,0x2f,0x26,
+ 0x12,0xc8,0x28,0x44,0xe4,0x70,0xd8,0xc0,
+ 0x60,0x30,0x30,0x00,0x30,0xc6,0xc6,0xfe,
+ 0x6c,0x6c,0x6c,0x38,0x38,0x00,0x10,0x20,
+ 0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38,0x38,
+ 0x00,0x10,0x08,0xc6,0xc6,0xfe,0x6c,0x6c,
+ 0x6c,0x38,0x38,0x00,0x28,0x10,0xc6,0xc6,
+ 0xfe,0x6c,0x6c,0x6c,0x38,0x38,0x00,0x28,
+ 0x14,0xc6,0xc6,0xfe,0x6c,0x6c,0x6c,0x38,
+ 0x38,0x00,0x28,0xc6,0xc6,0xfe,0x6c,0x6c,
+ 0x6c,0x38,0x38,0x10,0x28,0x10,0xcf,0x80,
+ 0xcc,0x00,0xfc,0x00,0x6c,0x00,0x6f,0x80,
+ 0x6c,0x00,0x3c,0x00,0x3f,0x80,0x30,0x10,
+ 0x3c,0x66,0xc2,0xc0,0xc0,0xc2,0x66,0x3c,
+ 0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,0xf8,
+ 0x00,0x20,0x40,0xf8,0xc0,0xc0,0xc0,0xf8,
+ 0xc0,0xc0,0xf8,0x00,0x20,0x10,0xf8,0xc0,
+ 0xc0,0xc0,0xf8,0xc0,0xc0,0xf8,0x00,0x50,
+ 0x20,0xf8,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,
+ 0xf8,0x00,0x50,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0x00,0x40,0x80,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x80,
+ 0x40,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x00,0xa0,0x40,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x00,0x90,0x78,0x6c,
+ 0x66,0x66,0xf6,0x66,0x6c,0x78,0xc6,0xce,
+ 0xce,0xd6,0xd6,0xe6,0xe6,0xc6,0x00,0x28,
+ 0x14,0x38,0x6c,0xc6,0xc6,0xc6,0xc6,0x6c,
+ 0x38,0x00,0x08,0x10,0x38,0x6c,0xc6,0xc6,
+ 0xc6,0xc6,0x6c,0x38,0x00,0x10,0x08,0x38,
+ 0x6c,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x00,
+ 0x28,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xc6,
+ 0x6c,0x38,0x00,0x28,0x14,0x38,0x6c,0xc6,
+ 0xc6,0xc6,0xc6,0x6c,0x38,0x00,0x28,0xcc,
+ 0x78,0x30,0x78,0xcc,0xb8,0x6c,0xe6,0xd6,
+ 0xd6,0xce,0x6c,0x3a,0x78,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0x00,0x10,0x20,0x78,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,
+ 0x10,0x08,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0x00,0x50,0x20,0x78,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x48,0x18,
+ 0x18,0x18,0x3c,0x66,0x66,0xc3,0xc3,0x00,
+ 0x08,0x04,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,
+ 0xf8,0xc0,0xd0,0xc8,0xc8,0xc8,0xd0,0xc8,
+ 0xc8,0x70,0x6c,0xd8,0xd8,0x78,0x98,0x70,
+ 0x00,0x10,0x20,0x6c,0xd8,0xd8,0x78,0x98,
+ 0x70,0x00,0x20,0x10,0x6c,0xd8,0xd8,0x78,
+ 0x98,0x70,0x00,0x50,0x20,0x6c,0xd8,0xd8,
+ 0x78,0x98,0x70,0x00,0x50,0x28,0x6c,0xd8,
+ 0xd8,0x78,0x98,0x70,0x00,0x50,0x6c,0xd8,
+ 0xd8,0x78,0x98,0x70,0x20,0x50,0x20,0x6e,
+ 0xdb,0xd8,0x7f,0x9b,0x7e,0x60,0x20,0x70,
+ 0xd0,0xc0,0xc0,0xd0,0x70,0x70,0xd8,0xc0,
+ 0xf8,0xd8,0x70,0x00,0x20,0x40,0x70,0xd8,
+ 0xc0,0xf8,0xd8,0x70,0x00,0x20,0x10,0x70,
+ 0xd8,0xc0,0xf8,0xd8,0x70,0x00,0x50,0x20,
+ 0x70,0xd8,0xc0,0xf8,0xd8,0x70,0x00,0x50,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x40,
+ 0x80,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,
+ 0x80,0x40,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0x00,0xa0,0x40,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0x00,0xa0,0x70,0xd8,0xd8,0xd8,0xd8,
+ 0x70,0xa0,0x60,0x50,0xd8,0xd8,0xd8,0xd8,
+ 0xd8,0xb0,0x00,0xa0,0x50,0x70,0xd8,0xd8,
+ 0xd8,0xd8,0x70,0x00,0x20,0x40,0x70,0xd8,
+ 0xd8,0xd8,0xd8,0x70,0x00,0x20,0x10,0x70,
+ 0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x50,0x20,
+ 0x70,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0xa0,
+ 0x50,0x70,0xd8,0xd8,0xd8,0xd8,0x70,0x00,
+ 0x50,0x30,0x00,0xfc,0x00,0x30,0xb8,0x6c,
+ 0x6c,0x7c,0x6c,0x3a,0x68,0xd8,0xd8,0xd8,
+ 0xd8,0xd8,0x00,0x20,0x40,0x68,0xd8,0xd8,
+ 0xd8,0xd8,0xd8,0x00,0x20,0x10,0x68,0xd8,
+ 0xd8,0xd8,0xd8,0xd8,0x00,0x50,0x20,0x68,
+ 0xd8,0xd8,0xd8,0xd8,0xd8,0x00,0x50,0x60,
+ 0x30,0x30,0x78,0xd8,0xd8,0xd8,0xd8,0x00,
+ 0x20,0x10,0xc0,0xc0,0xf0,0xd8,0xc8,0xc8,
+ 0xd8,0xf0,0xc0,0xc0,0x60,0x30,0x30,0x78,
+ 0xd8,0xd8,0xd8,0xd8,0x00,0x50,
+};
+
+BMF_FontData BMF_font_helvb10 = {
+ -1, -2,
+ 10, 11,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 12, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 3, 0},
+ {2, 8, -1, 0, 4, 1},
+ {3, 3, -1, -5, 5, 9},
+ {7, 7, 1, 0, 6, 12},
+ {5, 10, 0, 1, 6, 19},
+ {7, 8, 0, 0, 8, 29},
+ {7, 8, 0, 0, 8, 37},
+ {2, 4, 0, -4, 3, 45},
+ {3, 10, 0, 2, 4, 49},
+ {3, 10, 0, 2, 4, 59},
+ {3, 3, 0, -5, 4, 69},
+ {6, 5, 0, -1, 6, 72},
+ {2, 4, 0, 2, 3, 77},
+ {5, 1, -1, -3, 7, 81},
+ {2, 2, 0, 0, 3, 82},
+ {4, 8, 0, 0, 4, 84},
+ {5, 8, 0, 0, 6, 92},
+ {3, 8, -1, 0, 6, 100},
+ {5, 8, 0, 0, 6, 108},
+ {5, 8, 0, 0, 6, 116},
+ {6, 8, 0, 0, 6, 124},
+ {5, 8, 0, 0, 6, 132},
+ {5, 8, 0, 0, 6, 140},
+ {5, 8, 0, 0, 6, 148},
+ {5, 8, 0, 0, 6, 156},
+ {5, 8, 0, 0, 6, 164},
+ {2, 6, 0, 0, 3, 172},
+ {2, 8, 0, 2, 3, 178},
+ {4, 5, 0, -1, 5, 186},
+ {5, 3, 0, -2, 6, 191},
+ {4, 5, 0, -1, 5, 194},
+ {5, 8, 0, 0, 6, 199},
+ {10, 9, 0, 1, 11, 207},
+ {7, 8, 0, 0, 8, 225},
+ {6, 8, 0, 0, 7, 233},
+ {7, 8, 0, 0, 8, 241},
+ {6, 8, 0, 0, 7, 249},
+ {5, 8, 0, 0, 6, 257},
+ {5, 8, 0, 0, 6, 265},
+ {7, 8, 0, 0, 8, 273},
+ {6, 8, 0, 0, 7, 281},
+ {2, 8, 0, 0, 3, 289},
+ {5, 8, 0, 0, 6, 297},
+ {7, 8, 0, 0, 7, 305},
+ {5, 8, 0, 0, 6, 313},
+ {9, 8, 0, 0, 10, 321},
+ {7, 8, 0, 0, 8, 337},
+ {7, 8, 0, 0, 8, 345},
+ {6, 8, 0, 0, 7, 353},
+ {7, 9, 0, 1, 8, 361},
+ {6, 8, 0, 0, 7, 370},
+ {6, 8, 0, 0, 7, 378},
+ {6, 8, 0, 0, 7, 386},
+ {6, 8, 0, 0, 7, 394},
+ {7, 8, 0, 0, 8, 402},
+ {10, 8, 0, 0, 11, 410},
+ {7, 8, 0, 0, 8, 426},
+ {8, 8, 0, 0, 9, 434},
+ {6, 8, 0, 0, 7, 442},
+ {3, 10, 0, 2, 4, 450},
+ {4, 8, 0, 0, 4, 460},
+ {3, 10, 0, 2, 4, 468},
+ {4, 4, 0, -4, 5, 478},
+ {6, 1, 0, 2, 6, 482},
+ {2, 4, 0, -4, 3, 483},
+ {6, 6, 0, 0, 6, 487},
+ {5, 8, 0, 0, 6, 493},
+ {4, 6, 0, 0, 5, 501},
+ {5, 8, 0, 0, 6, 507},
+ {5, 6, 0, 0, 6, 515},
+ {5, 8, 1, 0, 4, 521},
+ {5, 8, 0, 2, 6, 529},
+ {5, 8, 0, 0, 6, 537},
+ {2, 8, 0, 0, 3, 545},
+ {3, 10, 1, 2, 3, 553},
+ {6, 8, 0, 0, 6, 563},
+ {2, 8, 0, 0, 3, 571},
+ {8, 6, 0, 0, 9, 579},
+ {5, 6, 0, 0, 6, 585},
+ {5, 6, 0, 0, 6, 591},
+ {5, 8, 0, 2, 6, 597},
+ {5, 8, 0, 2, 6, 605},
+ {4, 6, 0, 0, 4, 613},
+ {5, 6, 0, 0, 6, 619},
+ {4, 8, 1, 0, 4, 625},
+ {5, 6, 0, 0, 6, 633},
+ {5, 6, 0, 0, 6, 639},
+ {7, 6, 0, 0, 8, 645},
+ {6, 6, 0, 0, 7, 651},
+ {5, 8, 0, 2, 6, 657},
+ {5, 6, 0, 0, 6, 665},
+ {4, 10, 0, 2, 5, 671},
+ {1, 10, -1, 2, 3, 681},
+ {4, 10, 0, 2, 5, 691},
+ {5, 2, 0, -3, 6, 701},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 3, 703},
+ {2, 8, -1, 2, 4, 704},
+ {5, 8, 0, 1, 6, 712},
+ {5, 8, 0, 0, 6, 720},
+ {6, 6, 0, -1, 6, 728},
+ {6, 8, 0, 0, 7, 734},
+ {1, 10, -1, 2, 3, 742},
+ {5, 10, 0, 2, 6, 752},
+ {3, 1, 0, -7, 3, 762},
+ {8, 8, -1, 0, 10, 763},
+ {3, 5, -1, -3, 5, 771},
+ {6, 3, 0, -1, 7, 776},
+ {5, 3, -1, -2, 7, 779},
+ {4, 1, 0, -3, 5, 782},
+ {8, 8, -1, 0, 10, 783},
+ {3, 1, 0, -7, 3, 791},
+ {3, 3, 0, -5, 4, 792},
+ {6, 7, 0, 0, 6, 795},
+ {3, 4, 0, -4, 3, 802},
+ {3, 4, 0, -4, 3, 806},
+ {2, 2, 0, -7, 3, 810},
+ {5, 8, 0, 2, 6, 812},
+ {6, 10, 0, 2, 6, 820},
+ {2, 1, 0, -3, 3, 830},
+ {2, 2, 0, 2, 3, 831},
+ {2, 4, 0, -4, 3, 833},
+ {3, 5, -1, -3, 5, 837},
+ {6, 3, 0, -1, 7, 842},
+ {8, 8, 0, 0, 9, 845},
+ {7, 8, 0, 0, 9, 853},
+ {8, 8, 0, 0, 9, 861},
+ {5, 8, 0, 2, 6, 869},
+ {7, 11, 0, 0, 8, 877},
+ {7, 11, 0, 0, 8, 888},
+ {7, 11, 0, 0, 8, 899},
+ {7, 11, 0, 0, 8, 910},
+ {7, 10, 0, 0, 8, 921},
+ {7, 11, 0, 0, 8, 931},
+ {9, 8, 0, 0, 10, 942},
+ {7, 10, 0, 2, 8, 958},
+ {5, 11, 0, 0, 6, 968},
+ {5, 11, 0, 0, 6, 979},
+ {5, 11, 0, 0, 6, 990},
+ {5, 10, 0, 0, 6, 1001},
+ {2, 11, 0, 0, 3, 1011},
+ {2, 11, 0, 0, 3, 1022},
+ {3, 11, 1, 0, 3, 1033},
+ {4, 10, 1, 0, 3, 1044},
+ {7, 8, 1, 0, 7, 1054},
+ {7, 11, 0, 0, 8, 1062},
+ {7, 11, 0, 0, 8, 1073},
+ {7, 11, 0, 0, 8, 1084},
+ {7, 11, 0, 0, 8, 1095},
+ {7, 11, 0, 0, 8, 1106},
+ {7, 10, 0, 0, 8, 1117},
+ {6, 5, 0, -1, 6, 1127},
+ {7, 8, 0, 0, 8, 1132},
+ {6, 11, 0, 0, 7, 1140},
+ {6, 11, 0, 0, 7, 1151},
+ {6, 11, 0, 0, 7, 1162},
+ {6, 10, 0, 0, 7, 1173},
+ {8, 11, 0, 0, 9, 1183},
+ {6, 8, 0, 0, 7, 1194},
+ {5, 8, 0, 0, 6, 1202},
+ {6, 9, 0, 0, 6, 1210},
+ {6, 9, 0, 0, 6, 1219},
+ {6, 9, 0, 0, 6, 1228},
+ {6, 9, 0, 0, 6, 1237},
+ {6, 8, 0, 0, 6, 1246},
+ {6, 9, 0, 0, 6, 1254},
+ {8, 6, 0, 0, 9, 1263},
+ {4, 8, 0, 2, 5, 1269},
+ {5, 9, 0, 0, 6, 1277},
+ {5, 9, 0, 0, 6, 1286},
+ {5, 9, 0, 0, 6, 1295},
+ {5, 8, 0, 0, 6, 1304},
+ {2, 9, 0, 0, 3, 1312},
+ {2, 9, 0, 0, 3, 1321},
+ {3, 9, 0, 0, 3, 1330},
+ {3, 8, 0, 0, 3, 1339},
+ {5, 9, 0, 0, 6, 1347},
+ {5, 9, 0, 0, 6, 1356},
+ {5, 9, 0, 0, 6, 1365},
+ {5, 9, 0, 0, 6, 1374},
+ {5, 9, 0, 0, 6, 1383},
+ {5, 9, 0, 0, 6, 1392},
+ {5, 8, 0, 0, 6, 1401},
+ {6, 5, 0, -1, 6, 1409},
+ {7, 6, 1, 0, 6, 1414},
+ {5, 9, 0, 0, 6, 1420},
+ {5, 9, 0, 0, 6, 1429},
+ {5, 9, 0, 0, 6, 1438},
+ {5, 8, 0, 0, 6, 1447},
+ {5, 11, 0, 2, 6, 1455},
+ {5, 10, 0, 2, 6, 1466},
+ {5, 10, 0, 2, 6, 1476},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_helvb12.cpp b/intern/bmfont/intern/BMF_font_helvb12.cpp
new file mode 100644
index 00000000000..7ae4f3b4dd5
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helvb12.cpp
@@ -0,0 +1,565 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELVB12
+
+static unsigned char bitmap_data[]= {
+ 0x00,0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xa0,0xa0,0xa0,0x6c,
+ 0x00,0x6c,0x00,0x6c,0x00,0xff,0x00,0x36,
+ 0x00,0x36,0x00,0x36,0x00,0x7f,0x80,0x1b,
+ 0x00,0x1b,0x00,0x1b,0x00,0x30,0x30,0x78,
+ 0xec,0xac,0x3c,0x38,0x70,0xf0,0xd4,0xdc,
+ 0x78,0x30,0x63,0x80,0x37,0xc0,0x36,0xc0,
+ 0x1f,0xc0,0x1b,0x80,0x0c,0x00,0x76,0x00,
+ 0xfe,0x00,0xdb,0x00,0xfb,0x00,0x71,0x80,
+ 0x73,0x80,0xff,0x00,0xce,0x00,0xcf,0x00,
+ 0xdd,0x80,0x79,0x80,0x38,0x00,0x6c,0x00,
+ 0x6c,0x00,0x7c,0x00,0x38,0x00,0x80,0x40,
+ 0xc0,0xc0,0x30,0x60,0x60,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0x60,0x60,0x30,
+ 0xc0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0x60,0x60,0xc0,0xd8,0x70,
+ 0x70,0xf8,0x20,0x30,0x30,0xfc,0xfc,0x30,
+ 0x30,0x80,0x40,0xc0,0xc0,0xfc,0xfc,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0x60,0x60,0x60,0x20,
+ 0x30,0x30,0x30,0x18,0x18,0x18,0x78,0xfc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xfc,
+ 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0xf0,0xf0,0x30,0xfc,0xfc,0xc0,0x60,
+ 0x70,0x38,0x18,0xcc,0xcc,0xfc,0x78,0x78,
+ 0xfc,0xcc,0xcc,0x0c,0x38,0x38,0x0c,0xcc,
+ 0xfc,0x78,0x0c,0x0c,0xfe,0xfe,0xcc,0x6c,
+ 0x6c,0x3c,0x3c,0x1c,0x1c,0x78,0xfc,0xcc,
+ 0xcc,0x0c,0xfc,0xf8,0xc0,0xc0,0xfc,0xfc,
+ 0x78,0xfc,0xcc,0xcc,0xcc,0xfc,0xf8,0xc0,
+ 0xcc,0xfc,0x78,0x60,0x60,0x60,0x30,0x30,
+ 0x30,0x18,0x18,0x0c,0xfc,0xfc,0x78,0xfc,
+ 0xcc,0xcc,0xcc,0x78,0x78,0xcc,0xcc,0xfc,
+ 0x78,0x78,0xfc,0xcc,0x0c,0x7c,0xfc,0xcc,
+ 0xcc,0xcc,0xfc,0x78,0xc0,0xc0,0x00,0x00,
+ 0x00,0x00,0xc0,0xc0,0x80,0x40,0xc0,0xc0,
+ 0x00,0x00,0x00,0x00,0xc0,0xc0,0x0c,0x38,
+ 0xe0,0xe0,0x38,0x0c,0xfc,0xfc,0x00,0xfc,
+ 0xfc,0xc0,0x70,0x1c,0x1c,0x70,0xc0,0x30,
+ 0x30,0x00,0x30,0x30,0x38,0x1c,0xcc,0xcc,
+ 0xfc,0x78,0x1f,0x00,0x71,0x80,0x40,0x00,
+ 0xdd,0x80,0xb6,0xc0,0xb2,0x40,0xb3,0x60,
+ 0xdb,0x20,0x4d,0xa0,0x60,0x40,0x39,0xc0,
+ 0x0f,0x00,0xc3,0xc3,0xff,0x7e,0x66,0x66,
+ 0x3c,0x3c,0x3c,0x18,0x18,0xf8,0xfc,0xcc,
+ 0xcc,0xcc,0xf8,0xf8,0xcc,0xcc,0xfc,0xf8,
+ 0x78,0xfc,0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xcc,0xfc,0x78,0xf8,0xfc,0xce,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0xce,0xfc,0xf8,0xfc,0xfc,
+ 0xc0,0xc0,0xc0,0xf8,0xf8,0xc0,0xc0,0xfc,
+ 0xfc,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xf8,
+ 0xc0,0xc0,0xfc,0xfc,0x76,0xfe,0xc6,0xc6,
+ 0xde,0xde,0xc0,0xc0,0xc6,0xfe,0x7c,0xc6,
+ 0xc6,0xc6,0xc6,0xc6,0xfe,0xfe,0xc6,0xc6,
+ 0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0x70,0xf8,0xd8,
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0xc6,0xce,0xcc,0xd8,0xf8,0xf0,0xf0,0xd8,
+ 0xcc,0xcc,0xc6,0xfc,0xfc,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc9,0x80,
+ 0xc9,0x80,0xdd,0x80,0xdd,0x80,0xf7,0x80,
+ 0xf7,0x80,0xe3,0x80,0xe3,0x80,0xe3,0x80,
+ 0xc1,0x80,0xc1,0x80,0xc6,0xc6,0xce,0xce,
+ 0xde,0xd6,0xf6,0xe6,0xe6,0xc6,0xc6,0x7c,
+ 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,
+ 0xfe,0x7c,0xc0,0xc0,0xc0,0xc0,0xfc,0xfe,
+ 0xc6,0xc6,0xc6,0xfe,0xfc,0x06,0x7e,0xfc,
+ 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xfe,
+ 0x7c,0xc6,0xc6,0xc6,0xce,0xfc,0xfc,0xc6,
+ 0xc6,0xc6,0xfe,0xfc,0x78,0xfc,0xcc,0x0c,
+ 0x1c,0x78,0xe0,0xc0,0xcc,0xfc,0x78,0x30,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0xfc,0xfc,0x7c,0xfe,0xc6,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0xc6,0xc6,0x18,0x18,0x18,
+ 0x3c,0x3c,0x3c,0x66,0x66,0x66,0xc3,0xc3,
+ 0x33,0x00,0x33,0x00,0x33,0x00,0x3b,0x00,
+ 0x7f,0x80,0x6d,0x80,0x6d,0x80,0x6d,0x80,
+ 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xc3,0xc3,
+ 0x66,0x7e,0x3c,0x18,0x3c,0x7e,0x66,0xc3,
+ 0xc3,0x18,0x18,0x18,0x18,0x18,0x3c,0x3c,
+ 0x66,0x66,0xc3,0xc3,0xfe,0xfe,0xc0,0x60,
+ 0x60,0x30,0x18,0x18,0x0c,0xfe,0xfe,0xe0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xe0,0x30,0x30,0x30,
+ 0x70,0x60,0x60,0x60,0xe0,0xc0,0xc0,0xc0,
+ 0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0xe0,0x88,0xd8,
+ 0x70,0x70,0x20,0xfe,0xc0,0xc0,0x80,0x40,
+ 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78,
+ 0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0xd8,
+ 0xc0,0xc0,0xc0,0x78,0xfc,0xcc,0xc0,0xc0,
+ 0xcc,0xfc,0x78,0x6c,0xfc,0xcc,0xcc,0xcc,
+ 0xcc,0xfc,0x6c,0x0c,0x0c,0x0c,0x78,0xfc,
+ 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0xf0,0xf0,0x60,0x70,
+ 0x30,0x78,0xfc,0x0c,0x6c,0xfc,0xcc,0xcc,
+ 0xcc,0xcc,0xfc,0x6c,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xec,0xfc,0xd8,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,
+ 0xc0,0xc0,0xc0,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x60,
+ 0xcc,0xd8,0xd8,0xf0,0xe0,0xf0,0xd8,0xcc,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xcc,0xc0,
+ 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,
+ 0xee,0xc0,0xff,0xc0,0xbb,0x80,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xec,0xfc,0xd8,0x78,0xfc,
+ 0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0xc0,0xc0,
+ 0xc0,0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,
+ 0xd8,0x0c,0x0c,0x0c,0x6c,0xfc,0xcc,0xcc,
+ 0xcc,0xcc,0xfc,0x6c,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xe0,0xb0,0x78,0xfc,0xcc,0x1c,
+ 0x78,0xe0,0xfc,0x78,0x30,0x70,0x60,0x60,
+ 0x60,0x60,0xf0,0xf0,0x60,0x60,0x6c,0xfc,
+ 0xdc,0xcc,0xcc,0xcc,0xcc,0xcc,0x30,0x30,
+ 0x78,0x78,0x78,0xcc,0xcc,0xcc,0x24,0x24,
+ 0x76,0x76,0x7e,0xdb,0xdb,0xdb,0xcc,0xcc,
+ 0x78,0x38,0x70,0x78,0xcc,0xcc,0xe0,0xf0,
+ 0x30,0x30,0x38,0x78,0x78,0x48,0xcc,0xcc,
+ 0xcc,0xfc,0xfc,0x60,0x30,0x30,0x18,0xfc,
+ 0xfc,0x30,0x60,0x60,0x60,0x60,0x60,0x40,
+ 0x80,0x40,0x60,0x60,0x60,0x60,0x30,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0xc0,0x60,0x60,0x60,
+ 0x60,0x60,0x20,0x10,0x20,0x60,0x60,0x60,
+ 0x60,0xc0,0x98,0xfc,0x64,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0xc0,
+ 0xc0,0x78,0xfc,0xec,0xe0,0xd0,0xd4,0xfc,
+ 0x78,0x0c,0xdc,0xfe,0x60,0x30,0x30,0xfc,
+ 0x30,0x60,0x64,0x7c,0x38,0xcc,0x78,0xcc,
+ 0xcc,0x78,0xcc,0x18,0x18,0x18,0x7e,0x18,
+ 0x7e,0x3c,0x66,0x66,0xc3,0xc3,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,
+ 0x80,0x80,0x80,0x78,0xfc,0xcc,0x1c,0x38,
+ 0x6c,0xcc,0xcc,0xd8,0x70,0xe0,0xcc,0xfc,
+ 0x78,0xd8,0xd8,0x1f,0x00,0x71,0xc0,0x6e,
+ 0xc0,0xdb,0x60,0xdb,0x60,0xd8,0x60,0xdb,
+ 0x60,0xdb,0x60,0x6e,0xc0,0x71,0xc0,0x1f,
+ 0x00,0xf0,0x00,0xd0,0xb0,0x70,0xb0,0x60,
+ 0x36,0x6c,0xd8,0x6c,0x36,0x0c,0x0c,0xfc,
+ 0xfc,0xe0,0xe0,0x1f,0x00,0x71,0xc0,0x7b,
+ 0xc0,0xdb,0x60,0xdf,0x60,0xde,0x60,0xdb,
+ 0x60,0xdb,0x60,0x7e,0xc0,0x71,0xc0,0x1f,
+ 0x00,0xf0,0xf0,0x60,0x90,0x90,0x60,0xfc,
+ 0xfc,0x00,0x30,0x30,0xfc,0xfc,0x30,0x30,
+ 0xf0,0x40,0x20,0x10,0x90,0x60,0x60,0x90,
+ 0x10,0x20,0x90,0x60,0xc0,0x70,0x30,0xc0,
+ 0xc0,0xc0,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x36,0x36,0x76,0xf6,0xf6,0xf6,0xfe,0x7e,
+ 0xc0,0xc0,0xc0,0x60,0x40,0x40,0x40,0x40,
+ 0x40,0xc0,0x40,0xf8,0x00,0x70,0xd8,0xd8,
+ 0xd8,0x70,0xd8,0x6c,0x36,0x6c,0xd8,0x20,
+ 0x80,0x27,0xc0,0x12,0x80,0x12,0x80,0x09,
+ 0x80,0x4c,0x80,0x44,0x00,0x42,0x00,0x42,
+ 0x00,0xc1,0x00,0x41,0x00,0x23,0xc0,0x21,
+ 0x00,0x10,0x80,0x10,0x40,0x0a,0x40,0x4d,
+ 0x80,0x44,0x00,0x42,0x00,0x42,0x00,0xc1,
+ 0x00,0x41,0x00,0x20,0x80,0x27,0xc0,0x12,
+ 0x80,0x12,0x80,0x09,0x80,0x6c,0x80,0x94,
+ 0x00,0x12,0x00,0x22,0x00,0x91,0x00,0x61,
+ 0x00,0x78,0xfc,0xcc,0xcc,0xe0,0x70,0x30,
+ 0x30,0x00,0x30,0x30,0xc3,0xc3,0x7e,0x7e,
+ 0x24,0x3c,0x18,0x18,0x00,0x0c,0x38,0x30,
+ 0xc3,0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18,
+ 0x00,0x30,0x1c,0x0c,0xc3,0xc3,0x7e,0x7e,
+ 0x24,0x3c,0x18,0x18,0x00,0x66,0x3c,0x18,
+ 0xc3,0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18,
+ 0x00,0x2c,0x3e,0x1a,0xc3,0xc3,0x7e,0x7e,
+ 0x24,0x3c,0x18,0x18,0x00,0x6c,0x6c,0xc3,
+ 0xc3,0x7e,0x7e,0x24,0x3c,0x18,0x18,0x00,
+ 0x18,0x34,0x18,0xc7,0xe0,0xc7,0xe0,0xfe,
+ 0x00,0x7e,0x00,0x66,0x00,0x67,0xc0,0x37,
+ 0xc0,0x36,0x00,0x3e,0x00,0x1f,0xe0,0x1f,
+ 0xe0,0x60,0x30,0x20,0x78,0xfc,0xcc,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xcc,0xfc,0x78,0xfc,
+ 0xfc,0xc0,0xf8,0xf8,0xc0,0xfc,0xfc,0x00,
+ 0x18,0x70,0x60,0xfc,0xfc,0xc0,0xf8,0xf8,
+ 0xc0,0xfc,0xfc,0x00,0x60,0x38,0x18,0xfc,
+ 0xfc,0xc0,0xf8,0xf8,0xc0,0xfc,0xfc,0x00,
+ 0xcc,0x78,0x30,0xfc,0xfc,0xc0,0xf8,0xf8,
+ 0xc0,0xfc,0xfc,0x00,0xd8,0xd8,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x30,
+ 0xe0,0xc0,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x00,0xc0,0x70,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x00,0xcc,
+ 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x00,0xd8,0xd8,0x7c,0x7e,0x67,
+ 0x63,0x63,0xfb,0xfb,0x63,0x67,0x7e,0x7c,
+ 0xc6,0xce,0xce,0xde,0xf6,0xe6,0xe6,0xc6,
+ 0x00,0x58,0x7c,0x34,0x7c,0xfe,0xc6,0xc6,
+ 0xc6,0xc6,0xfe,0x7c,0x00,0x18,0x70,0x60,
+ 0x7c,0xfe,0xc6,0xc6,0xc6,0xc6,0xfe,0x7c,
+ 0x00,0x30,0x1c,0x0c,0x7c,0xfe,0xc6,0xc6,
+ 0xc6,0xc6,0xfe,0x7c,0x00,0xcc,0x78,0x30,
+ 0x7c,0xfe,0xc6,0xc6,0xc6,0xc6,0xfe,0x7c,
+ 0x00,0x58,0x7c,0x34,0x7c,0xfe,0xc6,0xc6,
+ 0xc6,0xc6,0xfe,0x7c,0x00,0x6c,0x6c,0xcc,
+ 0x78,0x30,0x30,0x78,0xcc,0xde,0x00,0x7f,
+ 0x00,0x63,0x00,0x73,0x00,0x7b,0x00,0x6b,
+ 0x00,0x6f,0x00,0x67,0x00,0x63,0x00,0x7f,
+ 0x00,0x3d,0x80,0x7c,0xfe,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0x00,0x18,0x70,0x60,0x7c,
+ 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,
+ 0x30,0x1c,0x0c,0x7c,0xfe,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0x00,0xcc,0x78,0x30,0x7c,
+ 0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,
+ 0x6c,0x6c,0x18,0x18,0x18,0x18,0x3c,0x7e,
+ 0xe7,0xc3,0x00,0x30,0x1c,0x0c,0xc0,0xc0,
+ 0xfc,0xfe,0xc6,0xc6,0xc6,0xfe,0xfc,0xc0,
+ 0xc0,0xd8,0xdc,0xcc,0xcc,0xcc,0xd8,0xd8,
+ 0xcc,0xcc,0xfc,0x78,0x76,0xfc,0xcc,0xfc,
+ 0x7c,0x8c,0xfc,0x78,0x00,0x18,0x70,0x60,
+ 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78,
+ 0x00,0x60,0x38,0x18,0x76,0xfc,0xcc,0xfc,
+ 0x7c,0x8c,0xfc,0x78,0x00,0xcc,0x78,0x30,
+ 0x76,0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78,
+ 0x00,0x58,0x7c,0x34,0x76,0xfc,0xcc,0xfc,
+ 0x7c,0x8c,0xfc,0x78,0x00,0xd8,0xd8,0x76,
+ 0xfc,0xcc,0xfc,0x7c,0x8c,0xfc,0x78,0x00,
+ 0x30,0x68,0x30,0x77,0x80,0xff,0xc0,0xcc,
+ 0x00,0xff,0xc0,0x7f,0xc0,0x8c,0xc0,0xff,
+ 0xc0,0x7b,0x80,0x60,0x30,0x20,0x78,0xfc,
+ 0xcc,0xc0,0xc0,0xcc,0xfc,0x78,0x78,0xfc,
+ 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x00,0x18,
+ 0x70,0x60,0x78,0xfc,0xc0,0xfc,0xfc,0xcc,
+ 0xfc,0x78,0x00,0x60,0x38,0x18,0x78,0xfc,
+ 0xc0,0xfc,0xfc,0xcc,0xfc,0x78,0x00,0xcc,
+ 0x78,0x30,0x78,0xfc,0xc0,0xfc,0xfc,0xcc,
+ 0xfc,0x78,0x00,0xd8,0xd8,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0x00,0x30,0xe0,
+ 0xc0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x00,0xc0,0x70,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0x30,0x30,0x00,0xcc,0x78,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x00,0xd8,0xd8,0x78,0xfc,0xcc,0xcc,
+ 0xcc,0xcc,0xfc,0x78,0xb0,0x60,0xd0,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xec,0xfc,0xd8,0x00,
+ 0xb0,0xf8,0x68,0x78,0xfc,0xcc,0xcc,0xcc,
+ 0xcc,0xfc,0x78,0x00,0x18,0x70,0x60,0x78,
+ 0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0x00,
+ 0x60,0x38,0x18,0x78,0xfc,0xcc,0xcc,0xcc,
+ 0xcc,0xfc,0x78,0x00,0xcc,0x78,0x30,0x78,
+ 0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,0x78,0x00,
+ 0xb0,0xf8,0x68,0x78,0xfc,0xcc,0xcc,0xcc,
+ 0xcc,0xfc,0x78,0x00,0xd8,0xd8,0x30,0x30,
+ 0x00,0xfc,0xfc,0x00,0x30,0x30,0xc0,0x78,
+ 0xfc,0xcc,0xec,0xdc,0xcc,0xfc,0x78,0x0c,
+ 0x6c,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0x00,0x18,0x70,0x60,0x6c,0xfc,0xdc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0x00,0x60,0x38,0x18,
+ 0x6c,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0x00,0xcc,0x78,0x30,0x6c,0xfc,0xdc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0x00,0xd8,0xd8,0xe0,
+ 0xf0,0x30,0x30,0x38,0x78,0x78,0x48,0xcc,
+ 0xcc,0xcc,0x00,0x60,0x38,0x18,0xc0,0xc0,
+ 0xc0,0xd8,0xfc,0xcc,0xcc,0xcc,0xcc,0xfc,
+ 0xd8,0xc0,0xc0,0xc0,0xe0,0xf0,0x30,0x30,
+ 0x38,0x78,0x78,0x48,0xcc,0xcc,0xcc,0x00,
+ 0xd8,0xd8,
+};
+
+BMF_FontData BMF_font_helvb12 = {
+ -1, -3,
+ 11, 12,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 12, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 3, 0},
+ {2, 11, -1, 0, 4, 1},
+ {3, 3, 0, -8, 4, 12},
+ {9, 11, 1, 0, 7, 15},
+ {6, 13, 0, 2, 7, 37},
+ {10, 11, 0, 0, 11, 50},
+ {9, 11, 0, 0, 9, 72},
+ {2, 4, 0, -7, 3, 94},
+ {4, 14, 0, 3, 4, 98},
+ {4, 14, 1, 3, 4, 112},
+ {5, 5, 0, -6, 6, 126},
+ {6, 6, 0, -1, 7, 131},
+ {2, 4, 0, 2, 3, 137},
+ {6, 2, -1, -3, 9, 141},
+ {2, 2, 0, 0, 3, 143},
+ {5, 13, 1, 2, 4, 145},
+ {6, 11, 0, 0, 7, 158},
+ {4, 11, 0, 0, 6, 169},
+ {6, 11, 0, 0, 7, 180},
+ {6, 11, 0, 0, 7, 191},
+ {7, 11, 0, 0, 7, 202},
+ {6, 11, 0, 0, 7, 213},
+ {6, 11, 0, 0, 7, 224},
+ {6, 11, 0, 0, 7, 235},
+ {6, 11, 0, 0, 7, 246},
+ {6, 11, 0, 0, 7, 257},
+ {2, 8, -1, 0, 4, 268},
+ {2, 10, -1, 2, 4, 276},
+ {6, 6, 0, -1, 7, 286},
+ {6, 5, 0, -2, 7, 292},
+ {6, 6, 0, -1, 7, 297},
+ {6, 11, 0, 0, 7, 303},
+ {11, 12, 0, 1, 12, 314},
+ {8, 11, 0, 0, 8, 338},
+ {6, 11, -1, 0, 8, 349},
+ {6, 11, -1, 0, 8, 360},
+ {7, 11, -1, 0, 9, 371},
+ {6, 11, -1, 0, 8, 382},
+ {6, 11, -1, 0, 7, 393},
+ {7, 11, -1, 0, 9, 404},
+ {7, 11, -1, 0, 9, 415},
+ {2, 11, -2, 0, 6, 426},
+ {5, 11, 0, 0, 6, 437},
+ {7, 11, -1, 0, 8, 448},
+ {6, 11, -1, 0, 7, 459},
+ {9, 11, -1, 0, 11, 470},
+ {7, 11, -1, 0, 9, 492},
+ {7, 11, -1, 0, 9, 503},
+ {7, 11, -1, 0, 9, 514},
+ {7, 12, -1, 1, 9, 525},
+ {7, 11, -1, 0, 9, 537},
+ {6, 11, -1, 0, 8, 548},
+ {6, 11, 0, 0, 6, 559},
+ {7, 11, -1, 0, 9, 570},
+ {8, 11, 0, 0, 8, 581},
+ {10, 11, 0, 0, 10, 592},
+ {8, 11, 0, 0, 8, 614},
+ {8, 11, 0, 0, 8, 625},
+ {7, 11, 0, 0, 7, 636},
+ {3, 14, 0, 3, 4, 647},
+ {4, 11, 0, 0, 5, 661},
+ {3, 14, 0, 3, 4, 672},
+ {5, 5, 0, -6, 7, 686},
+ {7, 1, 0, 2, 7, 691},
+ {2, 4, 0, -7, 3, 692},
+ {7, 8, 0, 0, 7, 696},
+ {6, 11, 0, 0, 7, 704},
+ {6, 8, 0, 0, 7, 715},
+ {6, 11, 0, 0, 7, 723},
+ {6, 8, 0, 0, 7, 734},
+ {4, 11, 0, 0, 5, 742},
+ {6, 11, 0, 3, 7, 753},
+ {6, 11, 0, 0, 7, 764},
+ {2, 11, -1, 0, 5, 775},
+ {3, 14, 0, 3, 5, 786},
+ {6, 11, 0, 0, 6, 800},
+ {2, 11, -1, 0, 5, 811},
+ {10, 8, 0, 0, 11, 822},
+ {6, 8, 0, 0, 7, 838},
+ {6, 8, 0, 0, 7, 846},
+ {6, 11, 0, 3, 7, 854},
+ {6, 11, 0, 3, 7, 865},
+ {4, 8, 0, 0, 4, 876},
+ {6, 8, 0, 0, 7, 884},
+ {4, 10, 0, 0, 5, 892},
+ {6, 8, 0, 0, 7, 902},
+ {6, 8, 0, 0, 7, 910},
+ {8, 8, 0, 0, 9, 918},
+ {6, 8, 0, 0, 7, 926},
+ {6, 11, 0, 3, 7, 934},
+ {6, 8, 0, 0, 7, 945},
+ {4, 14, 0, 3, 4, 953},
+ {1, 13, -1, 2, 3, 967},
+ {4, 14, 0, 3, 4, 980},
+ {6, 3, 0, -3, 7, 994},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {2, 11, 0, 3, 3, 997},
+ {6, 10, 0, 1, 7, 1008},
+ {7, 11, 0, 0, 7, 1018},
+ {6, 6, 0, -3, 7, 1029},
+ {8, 11, 1, 0, 7, 1035},
+ {1, 13, -1, 2, 3, 1046},
+ {6, 14, 0, 3, 7, 1059},
+ {5, 2, 0, -9, 5, 1073},
+ {11, 11, 0, 0, 12, 1075},
+ {4, 7, 0, -4, 5, 1097},
+ {7, 5, 0, -2, 8, 1104},
+ {6, 4, -1, -3, 9, 1109},
+ {3, 2, 0, -3, 4, 1113},
+ {11, 11, 0, 0, 12, 1115},
+ {4, 2, 0, -9, 4, 1137},
+ {4, 4, -1, -7, 6, 1139},
+ {6, 9, 0, -1, 7, 1143},
+ {4, 6, 0, -5, 4, 1152},
+ {4, 6, 0, -5, 4, 1158},
+ {4, 3, -1, -9, 4, 1164},
+ {6, 11, 0, 3, 7, 1167},
+ {7, 14, -1, 3, 10, 1178},
+ {2, 2, 0, -5, 3, 1192},
+ {3, 3, -1, 3, 5, 1194},
+ {2, 6, 0, -5, 4, 1197},
+ {5, 7, 0, -4, 6, 1203},
+ {7, 5, 0, -2, 8, 1210},
+ {10, 11, 0, 0, 11, 1215},
+ {10, 11, 0, 0, 11, 1237},
+ {10, 11, 0, 0, 11, 1259},
+ {6, 11, 0, 3, 7, 1281},
+ {8, 12, 0, 0, 8, 1292},
+ {8, 12, 0, 0, 8, 1304},
+ {8, 12, 0, 0, 8, 1316},
+ {8, 12, 0, 0, 8, 1328},
+ {8, 11, 0, 0, 8, 1340},
+ {8, 12, 0, 0, 8, 1351},
+ {11, 11, 0, 0, 12, 1363},
+ {6, 14, -1, 3, 8, 1385},
+ {6, 12, -1, 0, 8, 1399},
+ {6, 12, -1, 0, 8, 1411},
+ {6, 12, -1, 0, 8, 1423},
+ {6, 11, -1, 0, 8, 1435},
+ {4, 12, -1, 0, 6, 1446},
+ {4, 12, -1, 0, 6, 1458},
+ {6, 12, 0, 0, 6, 1470},
+ {5, 11, 0, 0, 6, 1482},
+ {8, 11, 0, 0, 9, 1493},
+ {7, 12, -1, 0, 9, 1504},
+ {7, 12, -1, 0, 9, 1516},
+ {7, 12, -1, 0, 9, 1528},
+ {7, 12, -1, 0, 9, 1540},
+ {7, 12, -1, 0, 9, 1552},
+ {7, 11, -1, 0, 9, 1564},
+ {6, 6, 0, -1, 7, 1575},
+ {9, 11, 0, 0, 9, 1581},
+ {7, 12, -1, 0, 9, 1603},
+ {7, 12, -1, 0, 9, 1615},
+ {7, 12, -1, 0, 9, 1627},
+ {7, 11, -1, 0, 9, 1639},
+ {8, 12, 0, 0, 8, 1650},
+ {7, 11, -1, 0, 9, 1662},
+ {6, 11, 0, 0, 7, 1673},
+ {7, 12, 0, 0, 7, 1684},
+ {7, 12, 0, 0, 7, 1696},
+ {7, 12, 0, 0, 7, 1708},
+ {7, 12, 0, 0, 7, 1720},
+ {7, 11, 0, 0, 7, 1732},
+ {7, 12, 0, 0, 7, 1743},
+ {10, 8, 0, 0, 11, 1755},
+ {6, 11, 0, 3, 7, 1771},
+ {6, 12, 0, 0, 7, 1782},
+ {6, 12, 0, 0, 7, 1794},
+ {6, 12, 0, 0, 7, 1806},
+ {6, 11, 0, 0, 7, 1818},
+ {4, 12, 0, 0, 5, 1829},
+ {4, 12, 0, 0, 5, 1841},
+ {6, 12, 1, 0, 5, 1853},
+ {5, 11, 1, 0, 5, 1865},
+ {6, 11, 0, 0, 7, 1876},
+ {6, 12, 0, 0, 7, 1887},
+ {6, 12, 0, 0, 7, 1899},
+ {6, 12, 0, 0, 7, 1911},
+ {6, 12, 0, 0, 7, 1923},
+ {6, 12, 0, 0, 7, 1935},
+ {6, 11, 0, 0, 7, 1947},
+ {6, 8, 0, 0, 7, 1958},
+ {6, 10, 0, 1, 7, 1966},
+ {6, 12, 0, 0, 7, 1976},
+ {6, 12, 0, 0, 7, 1988},
+ {6, 12, 0, 0, 7, 2000},
+ {6, 11, 0, 0, 7, 2012},
+ {6, 15, 0, 3, 7, 2023},
+ {6, 14, 0, 3, 7, 2038},
+ {6, 14, 0, 3, 7, 2052},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_helvb14.cpp b/intern/bmfont/intern/BMF_font_helvb14.cpp
new file mode 100644
index 00000000000..d77697e74a8
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helvb14.cpp
@@ -0,0 +1,623 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELVB14
+
+static unsigned char bitmap_data[]= {
+ 0x00,0xc0,0xc0,0x00,0x00,0x80,0x80,0x80,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0x90,0xd8,0xd8,
+ 0xd8,0x48,0x48,0x48,0xfe,0xfe,0x24,0x24,
+ 0x7f,0x7f,0x12,0x12,0x12,0x10,0x10,0x38,
+ 0x7c,0xd6,0xd6,0x16,0x3c,0x78,0xd0,0xd6,
+ 0xd6,0x7c,0x38,0x10,0x30,0xc0,0x11,0xe0,
+ 0x19,0x20,0x09,0x20,0x0d,0xe0,0x64,0xc0,
+ 0xf6,0x00,0x92,0x00,0x93,0x00,0xf1,0x00,
+ 0x61,0x80,0x71,0x80,0xff,0x00,0xce,0x00,
+ 0xc6,0x00,0xcf,0x00,0x79,0x00,0x30,0x00,
+ 0x38,0x00,0x6c,0x00,0x6c,0x00,0x7c,0x00,
+ 0x38,0x00,0x80,0x40,0xc0,0xc0,0x30,0x20,
+ 0x60,0x40,0x40,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0x40,0x40,0x60,0x20,0x30,0xc0,0x40,0x60,
+ 0x20,0x20,0x30,0x30,0x30,0x30,0x30,0x20,
+ 0x20,0x60,0x40,0xc0,0xd8,0x50,0x20,0xf8,
+ 0x20,0x20,0x30,0x30,0x30,0xfc,0xfc,0x30,
+ 0x30,0x30,0x80,0x40,0x40,0xc0,0xc0,0xfe,
+ 0xfe,0xc0,0xc0,0x80,0x80,0xc0,0x40,0x40,
+ 0x60,0x20,0x20,0x30,0x10,0x10,0x30,0x78,
+ 0x48,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x48,
+ 0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0xf0,0x30,0x10,0xfc,0xfc,
+ 0x60,0x60,0x30,0x18,0x18,0x0c,0xcc,0xcc,
+ 0x78,0x30,0x30,0x78,0xcc,0xcc,0x0c,0x38,
+ 0x38,0x0c,0xcc,0xcc,0x78,0x30,0x18,0x18,
+ 0xfc,0xfc,0x98,0x58,0x58,0x38,0x38,0x38,
+ 0x18,0x18,0x70,0xf8,0xcc,0x0c,0x0c,0xcc,
+ 0xfc,0xd8,0x60,0x60,0x7c,0x7c,0x30,0x78,
+ 0xcc,0xcc,0xcc,0xcc,0xfc,0xd8,0xc0,0x4c,
+ 0x7c,0x38,0x60,0x60,0x60,0x20,0x30,0x30,
+ 0x10,0x18,0x08,0x0c,0xfc,0xfc,0x70,0xf8,
+ 0xcc,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,
+ 0x7c,0x38,0x70,0xf8,0xc8,0x0c,0x6c,0xfc,
+ 0xcc,0xcc,0xcc,0xcc,0x78,0x30,0xc0,0xc0,
+ 0x00,0x00,0x00,0x00,0xc0,0xc0,0x80,0x40,
+ 0x40,0xc0,0xc0,0x00,0x00,0x00,0x00,0xc0,
+ 0xc0,0x02,0x0e,0x3c,0xf0,0xf0,0x3c,0x0e,
+ 0x02,0xfc,0xfc,0x00,0x00,0xfc,0xfc,0x80,
+ 0xe0,0x78,0x1e,0x1e,0x78,0xe0,0x80,0x30,
+ 0x30,0x00,0x30,0x30,0x18,0x18,0x0c,0xcc,
+ 0xcc,0x7c,0x38,0x0f,0x80,0x38,0x60,0x60,
+ 0x00,0x4d,0xc0,0xd3,0x20,0x93,0x30,0x91,
+ 0x10,0x91,0x90,0xc9,0x90,0x46,0x90,0x60,
+ 0x30,0x30,0x20,0x1c,0xc0,0x07,0x80,0xe1,
+ 0xc0,0x61,0x80,0x7f,0x80,0x7f,0x80,0x33,
+ 0x00,0x33,0x00,0x33,0x00,0x1e,0x00,0x1e,
+ 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0xfc,
+ 0xfe,0xc7,0xc3,0xc7,0xfe,0xfc,0xc6,0xc3,
+ 0xc7,0xfe,0xfc,0x3c,0x7e,0x63,0xc3,0xc0,
+ 0xc0,0xc0,0xc0,0xc3,0x63,0x7e,0x3c,0xfc,
+ 0xfe,0xc6,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,
+ 0xc6,0xfe,0xfc,0xfe,0xfe,0xc0,0xc0,0xc0,
+ 0xfe,0xfe,0xc0,0xc0,0xc0,0xfe,0xfe,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xfc,0xfc,0xc0,0xc0,
+ 0xc0,0xfe,0xfe,0x3e,0x80,0x7f,0x80,0x63,
+ 0x80,0xc1,0x80,0xc7,0x80,0xc7,0x80,0xc0,
+ 0x00,0xc0,0x00,0xc1,0x80,0x63,0x80,0x7f,
+ 0x00,0x3e,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,
+ 0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0x78,0xfc,0xcc,0xcc,0xcc,
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xc3,
+ 0x80,0xc7,0x00,0xc6,0x00,0xcc,0x00,0xdc,
+ 0x00,0xf8,0x00,0xf0,0x00,0xd8,0x00,0xcc,
+ 0x00,0xce,0x00,0xc7,0x00,0xc3,0x00,0xfe,
+ 0xfe,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc,
+ 0xc0,0xde,0xc0,0xde,0xc0,0xd2,0xc0,0xd2,
+ 0xc0,0xf3,0xc0,0xf3,0xc0,0xe1,0xc0,0xe1,
+ 0xc0,0xe1,0xc0,0xc3,0xc7,0xc7,0xcf,0xcf,
+ 0xdb,0xdb,0xf3,0xf3,0xe3,0xe3,0xc3,0x3e,
+ 0x00,0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1,
+ 0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,
+ 0x80,0x63,0x00,0x7f,0x00,0x3e,0x00,0xc0,
+ 0xc0,0xc0,0xc0,0xf8,0xfc,0xce,0xc6,0xc6,
+ 0xce,0xfc,0xf8,0x01,0x80,0x3d,0x80,0x7f,
+ 0x00,0x67,0x00,0xcd,0x80,0xcd,0x80,0xc1,
+ 0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63,
+ 0x00,0x7f,0x00,0x3e,0x00,0xc3,0xc3,0xc3,
+ 0xc3,0xc7,0xfe,0xfe,0xc7,0xc3,0xc7,0xfe,
+ 0xfc,0x3c,0x7e,0xe7,0xc3,0x07,0x1e,0x78,
+ 0xe0,0xc3,0xe7,0x7e,0x3c,0x18,0x18,0x18,
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,
+ 0xff,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,
+ 0xc3,0xc3,0xc3,0xc3,0xc3,0x18,0x18,0x18,
+ 0x3c,0x3c,0x24,0x66,0x66,0x66,0xc3,0xc3,
+ 0xc3,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x39,
+ 0xc0,0x79,0xe0,0x69,0x60,0x6f,0x60,0x6f,
+ 0x60,0xc6,0x30,0xc6,0x30,0xc6,0x30,0xc6,
+ 0x30,0xe3,0x80,0x63,0x00,0x63,0x00,0x36,
+ 0x00,0x36,0x00,0x1c,0x00,0x1c,0x00,0x36,
+ 0x00,0x36,0x00,0x63,0x00,0x63,0x00,0xe3,
+ 0x80,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,
+ 0x00,0x0c,0x00,0x1e,0x00,0x1e,0x00,0x33,
+ 0x00,0x33,0x00,0x61,0x80,0x61,0x80,0xe1,
+ 0xc0,0xff,0xff,0x60,0x70,0x30,0x18,0x18,
+ 0x0c,0x0e,0x06,0xff,0xff,0xe0,0xe0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xe0,0xe0,0x10,0x10,0x30,0x20,
+ 0x20,0x60,0x40,0x40,0xc0,0x80,0x80,0xe0,
+ 0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0xe0,0xe0,0xcc,0xcc,
+ 0x48,0x78,0x78,0x30,0x30,0xfe,0xc0,0xc0,
+ 0x80,0x40,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c,
+ 0xcc,0xfc,0x78,0xd8,0xfc,0xee,0xc6,0xc6,
+ 0xc6,0xee,0xfc,0xd8,0xc0,0xc0,0xc0,0x38,
+ 0x7c,0xec,0xc0,0xc0,0xc0,0xec,0x7c,0x38,
+ 0x36,0x7e,0xee,0xc6,0xc6,0xc6,0xee,0x7e,
+ 0x36,0x06,0x06,0x06,0x38,0x7c,0xcc,0xc0,
+ 0xfc,0xcc,0xcc,0x78,0x30,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0xf0,0xf0,0x60,0x70,
+ 0x30,0x78,0xfc,0xc6,0x36,0x7e,0xee,0xc6,
+ 0xc6,0xc6,0xee,0x7e,0x36,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xe0,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x00,0x60,0x60,0xce,0xcc,0xd8,0xd8,
+ 0xf0,0xf0,0xd8,0xd8,0xcc,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xcc,0xc0,0xcc,0xc0,
+ 0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,0xcc,0xc0,
+ 0xcc,0xc0,0xff,0xc0,0xdb,0x80,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0x38,
+ 0x7c,0xee,0xc6,0xc6,0xc6,0xee,0x7c,0x38,
+ 0xc0,0xc0,0xc0,0xd8,0xfc,0xee,0xc6,0xc6,
+ 0xc6,0xee,0xfc,0xd8,0x06,0x06,0x06,0x36,
+ 0x7e,0xee,0xc6,0xc6,0xc6,0xee,0x7e,0x36,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xe0,0xf8,
+ 0xd0,0x78,0xfc,0xcc,0x1c,0x78,0xe0,0xcc,
+ 0xfc,0x78,0x30,0x70,0x60,0x60,0x60,0x60,
+ 0x60,0xf0,0xf0,0x60,0x60,0x76,0xfe,0xce,
+ 0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x30,0x30,
+ 0x30,0x78,0x78,0x48,0xcc,0xcc,0xcc,0x33,
+ 0x00,0x33,0x00,0x33,0x00,0x73,0x80,0x7f,
+ 0x80,0x4c,0x80,0x4c,0x80,0xcc,0xc0,0xcc,
+ 0xc0,0xc6,0xee,0x6c,0x38,0x38,0x38,0x6c,
+ 0xee,0xc6,0x60,0x70,0x10,0x18,0x38,0x38,
+ 0x2c,0x6c,0x6c,0xc6,0xc6,0xc6,0xfc,0xfc,
+ 0x60,0x60,0x30,0x18,0x18,0xfc,0xfc,0x30,
+ 0x70,0x60,0x60,0x60,0x60,0x60,0xc0,0x60,
+ 0x60,0x60,0x60,0x60,0x70,0x30,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0xc0,0xe0,0x60,
+ 0x60,0x60,0x60,0x60,0x30,0x60,0x60,0x60,
+ 0x60,0x60,0xe0,0xc0,0x98,0xfc,0x64,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0x80,0x80,0x80,0x00,
+ 0x00,0xc0,0xc0,0x20,0x20,0x38,0x7c,0xec,
+ 0xe0,0xd0,0xd0,0xdc,0x7c,0x38,0x08,0x08,
+ 0xcc,0xfe,0x70,0x30,0x30,0xf8,0x60,0xc0,
+ 0xcc,0xcc,0x7c,0x38,0xcc,0x78,0xcc,0xcc,
+ 0xcc,0xcc,0x78,0xcc,0x18,0x18,0x18,0x7e,
+ 0x18,0x7e,0x18,0x3c,0x24,0x66,0x42,0xc3,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,
+ 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x38,
+ 0x7c,0x6c,0x0c,0x18,0x7c,0xe6,0xc6,0xce,
+ 0x7c,0x30,0x60,0x6c,0x7c,0x38,0xd8,0xd8,
+ 0x1e,0x00,0x33,0x00,0x40,0x80,0xde,0xc0,
+ 0xb3,0x40,0xa0,0x40,0xa0,0x40,0xb3,0x40,
+ 0xde,0xc0,0x40,0x80,0x33,0x00,0x1e,0x00,
+ 0xf0,0x00,0xd0,0xb0,0x70,0xb0,0x60,0x24,
+ 0x6c,0xd8,0xd8,0x6c,0x24,0x06,0x06,0x06,
+ 0xfe,0xfe,0xe0,0xe0,0x1e,0x00,0x33,0x00,
+ 0x40,0x80,0xd2,0xc0,0x96,0x40,0x9c,0x40,
+ 0x92,0x40,0x92,0x40,0xdc,0xc0,0x40,0x80,
+ 0x33,0x00,0x1e,0x00,0xf0,0x60,0x90,0x90,
+ 0x90,0x60,0xfc,0xfc,0x00,0x30,0x30,0x30,
+ 0xfc,0xfc,0x30,0x30,0x30,0xf0,0x80,0x40,
+ 0x20,0x90,0xb0,0x60,0x60,0xb0,0x10,0x60,
+ 0x30,0x90,0x60,0xc0,0x60,0xc0,0xc0,0xc0,
+ 0xf6,0xfe,0xce,0xc6,0xc6,0xc6,0xc6,0xc6,
+ 0xc6,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
+ 0x14,0x74,0xf4,0xf4,0xf4,0xf4,0x74,0x3e,
+ 0xc0,0xc0,0xc0,0x60,0x40,0x20,0x20,0x20,
+ 0x20,0x20,0xe0,0x20,0xf0,0x00,0x60,0x90,
+ 0x90,0x90,0x60,0x90,0xd8,0x6c,0x6c,0xd8,
+ 0x90,0x20,0x40,0x10,0x40,0x13,0xe0,0x0a,
+ 0x40,0x09,0x40,0x24,0xc0,0x24,0x40,0x22,
+ 0x00,0x22,0x00,0x21,0x00,0xe1,0x00,0x20,
+ 0x80,0x21,0xe0,0x11,0x00,0x10,0x80,0x08,
+ 0x40,0x09,0x20,0x25,0x60,0x24,0xc0,0x22,
+ 0x00,0x22,0x00,0x21,0x00,0xe1,0x00,0x20,
+ 0x80,0x20,0x40,0x10,0x40,0x13,0xe0,0x0a,
+ 0x40,0x09,0x40,0x64,0xc0,0xb4,0x40,0x12,
+ 0x00,0x62,0x00,0x31,0x00,0x91,0x00,0x60,
+ 0x80,0x70,0xf8,0xcc,0xcc,0xc0,0x60,0x60,
+ 0x30,0x30,0x00,0x30,0x30,0xe1,0xc0,0x61,
+ 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33,
+ 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c,
+ 0x00,0x0c,0x00,0x00,0x00,0x0c,0x00,0x18,
+ 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f,
+ 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e,
+ 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x00,
+ 0x00,0x0c,0x00,0x06,0x00,0xe1,0xc0,0x61,
+ 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33,
+ 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c,
+ 0x00,0x0c,0x00,0x00,0x00,0x36,0x00,0x1c,
+ 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f,
+ 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e,
+ 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x00,
+ 0x00,0x16,0x00,0x0d,0x00,0xe1,0xc0,0x61,
+ 0x80,0x7f,0x80,0x3f,0x00,0x33,0x00,0x33,
+ 0x00,0x12,0x00,0x1e,0x00,0x1e,0x00,0x0c,
+ 0x00,0x0c,0x00,0x00,0x00,0x36,0x00,0x36,
+ 0x00,0xe1,0xc0,0x61,0x80,0x7f,0x80,0x3f,
+ 0x00,0x33,0x00,0x33,0x00,0x12,0x00,0x1e,
+ 0x00,0x1e,0x00,0x0c,0x00,0x0c,0x00,0x0c,
+ 0x00,0x0a,0x00,0x06,0x00,0xe3,0xf8,0x63,
+ 0xf8,0x7f,0x00,0x7f,0x00,0x33,0x00,0x33,
+ 0xf8,0x3b,0xf8,0x1b,0x00,0x1b,0x00,0x1f,
+ 0x00,0x0f,0xf8,0x0f,0xf8,0x18,0x0c,0x08,
+ 0x3c,0x7e,0x63,0xc3,0xc0,0xc0,0xc0,0xc0,
+ 0xc3,0x63,0x7e,0x3c,0xfe,0xfe,0xc0,0xc0,
+ 0xc0,0xfe,0xfe,0xc0,0xc0,0xfe,0xfe,0x00,
+ 0x18,0x30,0xfe,0xfe,0xc0,0xc0,0xc0,0xfe,
+ 0xfe,0xc0,0xc0,0xfe,0xfe,0x00,0x18,0x0c,
+ 0xfe,0xfe,0xc0,0xc0,0xc0,0xfe,0xfe,0xc0,
+ 0xc0,0xfe,0xfe,0x00,0x6c,0x38,0xfe,0xfe,
+ 0xc0,0xc0,0xc0,0xfe,0xfe,0xc0,0xc0,0xfe,
+ 0xfe,0x00,0x6c,0x6c,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,
+ 0x60,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0x60,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0x00,0xd8,0x70,0x30,0x30,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x00,0xd8,0xd8,0x7e,0x00,0x7f,0x00,
+ 0x63,0x00,0x61,0x80,0x61,0x80,0xf9,0x80,
+ 0xf9,0x80,0x61,0x80,0x61,0x80,0x63,0x00,
+ 0x7f,0x00,0x7e,0x00,0xc3,0xc7,0xc7,0xcf,
+ 0xcb,0xdb,0xd3,0xf3,0xe3,0xe3,0xc3,0x00,
+ 0x2c,0x1a,0x3e,0x00,0x7f,0x00,0x63,0x00,
+ 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,
+ 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00,
+ 0x00,0x00,0x0c,0x00,0x18,0x00,0x3e,0x00,
+ 0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1,0x80,
+ 0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63,0x00,
+ 0x7f,0x00,0x3e,0x00,0x00,0x00,0x18,0x00,
+ 0x0c,0x00,0x3e,0x00,0x7f,0x00,0x63,0x00,
+ 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,
+ 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00,
+ 0x00,0x00,0x36,0x00,0x1c,0x00,0x3e,0x00,
+ 0x7f,0x00,0x63,0x00,0xc1,0x80,0xc1,0x80,
+ 0xc1,0x80,0xc1,0x80,0xc1,0x80,0x63,0x00,
+ 0x7f,0x00,0x3e,0x00,0x00,0x00,0x2c,0x00,
+ 0x1a,0x00,0x3e,0x00,0x7f,0x00,0x63,0x00,
+ 0xc1,0x80,0xc1,0x80,0xc1,0x80,0xc1,0x80,
+ 0xc1,0x80,0x63,0x00,0x7f,0x00,0x3e,0x00,
+ 0x00,0x00,0x36,0x00,0x36,0x00,0x84,0xcc,
+ 0x78,0x30,0x30,0x78,0xcc,0x84,0xbe,0x00,
+ 0xff,0x00,0x63,0x00,0xf1,0x80,0xd1,0x80,
+ 0xc9,0x80,0xc9,0x80,0xc5,0x80,0xc7,0x80,
+ 0x63,0x00,0x7f,0x80,0x3e,0x80,0x3c,0x7e,
+ 0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,
+ 0xc3,0x00,0x18,0x30,0x3c,0x7e,0xe7,0xc3,
+ 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,
+ 0x18,0x0c,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,
+ 0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x6c,0x38,
+ 0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,
+ 0xc3,0xc3,0xc3,0x00,0x6c,0x6c,0x0c,0x00,
+ 0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,
+ 0x1e,0x00,0x1e,0x00,0x33,0x00,0x33,0x00,
+ 0x61,0x80,0xe1,0xc0,0x00,0x00,0x0c,0x00,
+ 0x06,0x00,0xc0,0xc0,0xf8,0xfc,0xce,0xc6,
+ 0xc6,0xce,0xfc,0xf8,0xc0,0xc0,0xd8,0xdc,
+ 0xc6,0xc6,0xc6,0xdc,0xd8,0xcc,0xcc,0xcc,
+ 0x7c,0x38,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c,
+ 0xcc,0xfc,0x78,0x00,0x30,0x60,0x6c,0xfc,
+ 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00,
+ 0x30,0x18,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c,
+ 0xcc,0xfc,0x78,0x00,0xd8,0x70,0x6c,0xfc,
+ 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00,
+ 0x58,0x34,0x6c,0xfc,0xcc,0xcc,0x7c,0x1c,
+ 0xcc,0xfc,0x78,0x00,0xd8,0xd8,0x6c,0xfc,
+ 0xcc,0xcc,0x7c,0x1c,0xcc,0xfc,0x78,0x00,
+ 0x30,0x28,0x18,0x73,0x80,0xff,0xc0,0xcc,
+ 0xc0,0xcc,0x00,0x7f,0xc0,0x1c,0xc0,0xcc,
+ 0xc0,0xff,0xc0,0x73,0x80,0x30,0x18,0x10,
+ 0x38,0x7c,0xec,0xc0,0xc0,0xc0,0xec,0x7c,
+ 0x38,0x38,0x7c,0xcc,0xc0,0xfc,0xcc,0xcc,
+ 0x78,0x30,0x00,0x30,0x60,0x38,0x7c,0xcc,
+ 0xc0,0xfc,0xcc,0xcc,0x78,0x30,0x00,0x30,
+ 0x18,0x38,0x7c,0xcc,0xc0,0xfc,0xcc,0xcc,
+ 0x78,0x30,0x00,0x6c,0x38,0x38,0x7c,0xcc,
+ 0xc0,0xfc,0xcc,0xcc,0x78,0x30,0x00,0xd8,
+ 0xd8,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
+ 0x60,0x60,0x00,0x60,0xc0,0xc0,0xc0,0xc0,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0xc0,
+ 0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+ 0x30,0x30,0x00,0xd8,0x70,0x30,0x30,0x30,
+ 0x30,0x30,0x30,0x30,0x30,0x30,0x00,0xd8,
+ 0xd8,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee,
+ 0x7c,0x3c,0xf8,0x38,0x6c,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0xe6,0xfe,0xdc,0x00,0x58,
+ 0x34,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee,
+ 0x7c,0x38,0x00,0x18,0x30,0x38,0x7c,0xee,
+ 0xc6,0xc6,0xc6,0xee,0x7c,0x38,0x00,0x30,
+ 0x18,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee,
+ 0x7c,0x38,0x00,0x6c,0x38,0x38,0x7c,0xee,
+ 0xc6,0xc6,0xc6,0xee,0x7c,0x38,0x00,0x58,
+ 0x34,0x38,0x7c,0xee,0xc6,0xc6,0xc6,0xee,
+ 0x7c,0x38,0x00,0x6c,0x6c,0x30,0x30,0x00,
+ 0xfc,0xfc,0x00,0x30,0x30,0xb8,0x7c,0xee,
+ 0xe6,0xd6,0xce,0xee,0x7c,0x3a,0x76,0xfe,
+ 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,
+ 0x18,0x30,0x76,0xfe,0xce,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0x00,0x30,0x18,0x76,0xfe,
+ 0xce,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,
+ 0x6c,0x38,0x76,0xfe,0xce,0xc6,0xc6,0xc6,
+ 0xc6,0xc6,0xc6,0x00,0x6c,0x6c,0x60,0x70,
+ 0x10,0x18,0x38,0x38,0x2c,0x6c,0x6c,0xc6,
+ 0xc6,0xc6,0x00,0x30,0x18,0xc0,0xc0,0xc0,
+ 0xd8,0xfc,0xee,0xc6,0xc6,0xc6,0xee,0xfc,
+ 0xd8,0xc0,0xc0,0xc0,0x60,0x70,0x10,0x18,
+ 0x38,0x38,0x2c,0x6c,0x6c,0xc6,0xc6,0xc6,
+ 0x00,0x6c,0x6c,
+};
+
+BMF_FontData BMF_font_helvb14 = {
+ -2, -3,
+ 12, 14,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 12, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 3, 0},
+ {2, 12, -1, 0, 4, 1},
+ {5, 4, 0, -8, 6, 13},
+ {8, 12, 1, 0, 7, 17},
+ {7, 15, 0, 2, 7, 29},
+ {11, 11, 0, 0, 12, 44},
+ {9, 12, 0, 0, 9, 66},
+ {2, 4, -1, -8, 4, 90},
+ {4, 15, 0, 3, 4, 94},
+ {4, 15, 1, 3, 4, 109},
+ {5, 6, 0, -6, 5, 124},
+ {6, 8, -1, 0, 8, 130},
+ {2, 5, 0, 3, 3, 138},
+ {7, 2, 0, -3, 8, 143},
+ {2, 2, 0, 0, 3, 145},
+ {4, 11, 0, 0, 4, 147},
+ {6, 12, 0, 0, 7, 158},
+ {4, 12, 0, 0, 7, 170},
+ {6, 12, 0, 0, 7, 182},
+ {6, 12, 0, 0, 7, 194},
+ {6, 12, 0, 0, 7, 206},
+ {6, 12, 0, 0, 7, 218},
+ {6, 12, 0, 0, 7, 230},
+ {6, 12, 0, 0, 7, 242},
+ {6, 12, 0, 0, 7, 254},
+ {6, 12, 0, 0, 7, 266},
+ {2, 8, -1, 0, 4, 278},
+ {2, 11, -1, 3, 4, 286},
+ {7, 8, 0, 0, 8, 297},
+ {6, 6, -1, -1, 8, 305},
+ {7, 8, 0, 0, 8, 311},
+ {6, 12, -1, 0, 8, 319},
+ {12, 14, 0, 2, 13, 331},
+ {10, 12, 1, 0, 9, 359},
+ {8, 12, 0, 0, 9, 383},
+ {8, 12, 0, 0, 9, 395},
+ {8, 12, 0, 0, 9, 407},
+ {7, 12, 0, 0, 8, 419},
+ {7, 12, -1, 0, 8, 431},
+ {9, 12, 0, 0, 10, 443},
+ {8, 12, 0, 0, 9, 467},
+ {2, 12, -1, 0, 5, 479},
+ {6, 12, 0, 0, 7, 491},
+ {9, 12, -1, 0, 10, 503},
+ {7, 12, -1, 0, 8, 527},
+ {10, 12, 0, 0, 11, 539},
+ {8, 12, 0, 0, 9, 563},
+ {9, 12, 0, 0, 10, 575},
+ {7, 12, -1, 0, 9, 599},
+ {9, 13, 0, 1, 10, 611},
+ {8, 12, 0, 0, 9, 637},
+ {8, 12, 0, 0, 9, 649},
+ {8, 12, 0, 0, 9, 661},
+ {8, 12, 0, 0, 9, 673},
+ {8, 12, 0, 0, 9, 685},
+ {12, 12, 0, 0, 13, 697},
+ {9, 12, 0, 0, 10, 721},
+ {10, 12, 1, 0, 9, 745},
+ {8, 12, 0, 0, 9, 769},
+ {3, 15, 0, 3, 4, 781},
+ {4, 11, 0, 0, 4, 796},
+ {3, 15, 0, 3, 4, 807},
+ {6, 7, -1, -4, 8, 822},
+ {7, 1, 0, 3, 7, 829},
+ {2, 4, -1, -8, 4, 830},
+ {6, 9, 0, 0, 7, 834},
+ {7, 12, 0, 0, 8, 843},
+ {6, 9, 0, 0, 7, 855},
+ {7, 12, 0, 0, 8, 864},
+ {6, 9, 0, 0, 7, 876},
+ {4, 12, 0, 0, 5, 885},
+ {7, 12, 0, 3, 8, 897},
+ {7, 12, 0, 0, 8, 909},
+ {2, 12, 0, 0, 3, 921},
+ {3, 15, 1, 3, 3, 933},
+ {7, 12, 0, 0, 7, 948},
+ {2, 12, 0, 0, 3, 960},
+ {10, 9, 0, 0, 11, 972},
+ {7, 9, 0, 0, 8, 990},
+ {7, 9, 0, 0, 8, 999},
+ {7, 12, 0, 3, 8, 1008},
+ {7, 12, 0, 3, 8, 1020},
+ {5, 9, 0, 0, 5, 1032},
+ {6, 9, 0, 0, 7, 1041},
+ {4, 11, 0, 0, 5, 1050},
+ {7, 9, 0, 0, 8, 1061},
+ {6, 9, 0, 0, 7, 1070},
+ {10, 9, 0, 0, 11, 1079},
+ {7, 9, 0, 0, 8, 1097},
+ {7, 12, 0, 3, 8, 1106},
+ {6, 9, 0, 0, 7, 1118},
+ {4, 15, 0, 3, 5, 1127},
+ {1, 15, -1, 3, 4, 1142},
+ {4, 15, 0, 3, 5, 1157},
+ {6, 3, -1, -3, 8, 1172},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {2, 12, -1, 3, 4, 1175},
+ {6, 13, 0, 2, 7, 1187},
+ {7, 12, 0, 0, 7, 1200},
+ {6, 8, 0, -2, 7, 1212},
+ {8, 12, 1, 0, 7, 1220},
+ {1, 15, -1, 3, 4, 1232},
+ {7, 15, 0, 3, 7, 1247},
+ {5, 2, 1, -10, 4, 1262},
+ {10, 12, 0, 0, 10, 1264},
+ {4, 7, 0, -5, 5, 1288},
+ {6, 6, 0, -1, 7, 1295},
+ {7, 5, 0, -2, 8, 1301},
+ {3, 2, 0, -3, 4, 1306},
+ {10, 12, 0, 0, 10, 1308},
+ {4, 1, 0, -11, 4, 1332},
+ {4, 5, 0, -7, 5, 1333},
+ {6, 11, -1, 0, 8, 1338},
+ {4, 7, 0, -5, 4, 1349},
+ {4, 7, 0, -5, 4, 1356},
+ {3, 2, -1, -10, 4, 1363},
+ {7, 12, 0, 3, 8, 1365},
+ {7, 15, 0, 3, 7, 1377},
+ {2, 2, 0, -5, 3, 1392},
+ {3, 3, 0, 3, 4, 1394},
+ {3, 7, 0, -5, 4, 1397},
+ {4, 7, 0, -5, 5, 1404},
+ {6, 6, 0, -1, 7, 1411},
+ {11, 12, 1, 0, 11, 1417},
+ {11, 12, 1, 0, 11, 1441},
+ {11, 12, 0, 0, 11, 1465},
+ {6, 12, -1, 3, 8, 1489},
+ {10, 14, 1, 0, 9, 1501},
+ {10, 14, 1, 0, 9, 1529},
+ {10, 14, 1, 0, 9, 1557},
+ {10, 14, 1, 0, 9, 1585},
+ {10, 14, 1, 0, 9, 1613},
+ {10, 14, 1, 0, 9, 1641},
+ {13, 12, 1, 0, 13, 1669},
+ {8, 15, 0, 3, 9, 1693},
+ {7, 14, 0, 0, 8, 1708},
+ {7, 14, 0, 0, 8, 1722},
+ {7, 14, 0, 0, 8, 1736},
+ {7, 14, 0, 0, 8, 1750},
+ {3, 14, 0, 0, 5, 1764},
+ {3, 14, -1, 0, 5, 1778},
+ {5, 14, 1, 0, 5, 1792},
+ {5, 14, 1, 0, 5, 1806},
+ {9, 12, 1, 0, 9, 1820},
+ {8, 14, 0, 0, 9, 1844},
+ {9, 14, 0, 0, 10, 1858},
+ {9, 14, 0, 0, 10, 1886},
+ {9, 14, 0, 0, 10, 1914},
+ {9, 14, 0, 0, 10, 1942},
+ {9, 14, 0, 0, 10, 1970},
+ {6, 8, -1, 0, 8, 1998},
+ {9, 12, 0, 0, 10, 2006},
+ {8, 14, 0, 0, 9, 2030},
+ {8, 14, 0, 0, 9, 2044},
+ {8, 14, 0, 0, 9, 2058},
+ {8, 14, 0, 0, 9, 2072},
+ {10, 14, 1, 0, 9, 2086},
+ {7, 12, -1, 0, 9, 2114},
+ {7, 12, 0, 0, 8, 2126},
+ {6, 12, 0, 0, 7, 2138},
+ {6, 12, 0, 0, 7, 2150},
+ {6, 12, 0, 0, 7, 2162},
+ {6, 12, 0, 0, 7, 2174},
+ {6, 12, 0, 0, 7, 2186},
+ {6, 13, 0, 0, 7, 2198},
+ {10, 9, 0, 0, 11, 2211},
+ {6, 12, 0, 3, 7, 2229},
+ {6, 12, 0, 0, 7, 2241},
+ {6, 12, 0, 0, 7, 2253},
+ {6, 12, 0, 0, 7, 2265},
+ {6, 12, 0, 0, 7, 2277},
+ {3, 12, 1, 0, 3, 2289},
+ {3, 12, 0, 0, 3, 2301},
+ {5, 12, 2, 0, 3, 2313},
+ {5, 12, 2, 0, 3, 2325},
+ {7, 12, 0, 0, 8, 2337},
+ {7, 12, 0, 0, 8, 2349},
+ {7, 12, 0, 0, 8, 2361},
+ {7, 12, 0, 0, 8, 2373},
+ {7, 12, 0, 0, 8, 2385},
+ {7, 12, 0, 0, 8, 2397},
+ {7, 12, 0, 0, 8, 2409},
+ {6, 8, -1, 0, 8, 2421},
+ {7, 9, 0, 0, 8, 2429},
+ {7, 12, 0, 0, 8, 2438},
+ {7, 12, 0, 0, 8, 2450},
+ {7, 12, 0, 0, 8, 2462},
+ {7, 12, 0, 0, 8, 2474},
+ {7, 15, 0, 3, 8, 2486},
+ {7, 15, 0, 3, 8, 2501},
+ {7, 15, 0, 3, 8, 2516},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_helvb8.cpp b/intern/bmfont/intern/BMF_font_helvb8.cpp
new file mode 100644
index 00000000000..0dfefbeda95
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_helvb8.cpp
@@ -0,0 +1,455 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_HELVB8
+
+static unsigned char bitmap_data[]= {
+ 0x00,0x80,0x00,0x80,0x80,0x80,0x80,0xa0,
+ 0xa0,0xa0,0x50,0xf8,0x50,0xf8,0x50,0x40,
+ 0xe0,0x10,0x60,0x80,0x70,0x20,0x5c,0x54,
+ 0x2c,0xd0,0xa8,0xe8,0x58,0xb0,0xa8,0x48,
+ 0xa0,0x40,0x80,0x80,0x80,0x40,0x80,0x80,
+ 0x80,0x80,0x80,0x40,0x80,0x40,0x40,0x40,
+ 0x40,0x40,0x80,0x40,0xe0,0x40,0x20,0x20,
+ 0xf8,0x20,0x20,0x80,0x40,0x40,0xf0,0x80,
+ 0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x60,
+ 0x90,0x90,0x90,0x90,0x60,0x40,0x40,0x40,
+ 0x40,0xc0,0x40,0xf0,0x40,0x20,0x10,0x90,
+ 0x60,0xc0,0x20,0x20,0xc0,0x20,0xc0,0x20,
+ 0x20,0xf0,0x60,0x20,0x20,0xc0,0x20,0x20,
+ 0xc0,0x80,0xe0,0x60,0x90,0x90,0xe0,0x80,
+ 0x70,0x40,0x40,0x40,0x20,0x10,0xf0,0x60,
+ 0x90,0x90,0x60,0x90,0x60,0x60,0x10,0x70,
+ 0x90,0x90,0x60,0x80,0x00,0x00,0x80,0x80,
+ 0x40,0x40,0x00,0x00,0x40,0x20,0x40,0x80,
+ 0x40,0x20,0xe0,0x00,0xe0,0x80,0x40,0x20,
+ 0x40,0x80,0x40,0x00,0x40,0x20,0xc0,0x78,
+ 0x80,0x9e,0xa5,0x99,0x41,0x3e,0x88,0x88,
+ 0x70,0x50,0x20,0x20,0xe0,0x90,0x90,0xe0,
+ 0x90,0xe0,0x70,0x88,0x80,0x80,0x88,0x70,
+ 0xf0,0x88,0x88,0x88,0x88,0xf0,0xf0,0x80,
+ 0x80,0xe0,0x80,0xf0,0x80,0x80,0x80,0xe0,
+ 0x80,0xf0,0x70,0x88,0x88,0x98,0x80,0x70,
+ 0x88,0x88,0x88,0xf8,0x88,0x88,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x40,0xa0,0x20,0x20,
+ 0x20,0x20,0x90,0x90,0xe0,0xc0,0xa0,0x90,
+ 0xe0,0x80,0x80,0x80,0x80,0x80,0xa8,0xa8,
+ 0xa8,0xa8,0xd8,0x88,0x88,0x98,0xa8,0xa8,
+ 0xc8,0x88,0x70,0x88,0x88,0x88,0x88,0x70,
+ 0x80,0x80,0xe0,0x90,0x90,0xe0,0x10,0x20,
+ 0x70,0x88,0x88,0x88,0x88,0x70,0x90,0x90,
+ 0xe0,0x90,0x90,0xe0,0xe0,0x10,0x10,0xe0,
+ 0x80,0x70,0x40,0x40,0x40,0x40,0x40,0xe0,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x40,0xa0,
+ 0x90,0x90,0x90,0x90,0x48,0x48,0x6c,0x92,
+ 0x92,0x92,0x90,0x90,0x60,0x60,0x90,0x90,
+ 0x20,0x20,0x30,0x48,0x48,0xc8,0xf0,0x80,
+ 0x40,0x20,0x10,0xf0,0xc0,0x80,0x80,0x80,
+ 0x80,0x80,0xc0,0x40,0x40,0x40,0x40,0x80,
+ 0x80,0x80,0xc0,0x40,0x40,0x40,0x40,0x40,
+ 0xc0,0x88,0x50,0x20,0xf8,0x80,0x80,0x80,
+ 0xd0,0xa0,0xe0,0x20,0xc0,0xe0,0x90,0x90,
+ 0x90,0xe0,0x80,0x80,0x60,0x80,0x80,0x80,
+ 0x60,0x70,0x90,0x90,0x90,0x70,0x10,0x10,
+ 0x60,0x80,0xe0,0xa0,0x40,0x40,0x40,0x40,
+ 0x40,0xe0,0x40,0x20,0x60,0x10,0x70,0x90,
+ 0x90,0x70,0x90,0x90,0x90,0x90,0xe0,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80,
+ 0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
+ 0x40,0xa0,0xa0,0xc0,0xc0,0xa0,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xa8,
+ 0xa8,0xa8,0xa8,0xf0,0x90,0x90,0x90,0x90,
+ 0xe0,0x60,0x90,0x90,0x90,0x60,0x80,0xe0,
+ 0x90,0x90,0x90,0xe0,0x10,0x70,0x90,0x90,
+ 0x90,0x70,0x80,0x80,0x80,0xc0,0xa0,0xc0,
+ 0x20,0x60,0x80,0x60,0x40,0x40,0x40,0x40,
+ 0xe0,0x40,0x40,0x60,0xa0,0xa0,0xa0,0xa0,
+ 0x40,0xa0,0x90,0x90,0x90,0x50,0x50,0xa8,
+ 0xa8,0xa8,0x90,0x90,0x60,0x90,0x90,0x80,
+ 0x40,0x60,0x90,0x90,0x90,0xe0,0x80,0x40,
+ 0x20,0xe0,0x20,0x40,0x40,0xc0,0x40,0x40,
+ 0x20,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x40,0x40,0x60,0x40,0x40,0x80,0xb0,
+ 0x48,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
+ 0x80,0x40,0x40,0xa0,0x80,0xa0,0x40,0x40,
+ 0xf0,0x40,0x40,0xe0,0x40,0x30,0x88,0x70,
+ 0x50,0x70,0x88,0x20,0x20,0xf8,0x50,0x88,
+ 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0xe0,
+ 0x10,0x30,0x60,0x90,0x60,0x80,0x70,0x90,
+ 0x78,0x84,0xb4,0xa4,0xb4,0x84,0x78,0xe0,
+ 0x00,0xe0,0x20,0xc0,0x50,0xa0,0x50,0x10,
+ 0x10,0xf0,0xc0,0x78,0x84,0xac,0xb4,0xb4,
+ 0x84,0x78,0xe0,0x40,0xa0,0x40,0xf0,0x00,
+ 0x20,0xf0,0x20,0xc0,0x80,0x40,0x80,0xc0,
+ 0x20,0x60,0xe0,0x80,0x40,0x80,0x80,0xe0,
+ 0xa0,0xa0,0xa0,0x50,0x50,0x50,0x50,0xd0,
+ 0xd0,0xd0,0x78,0x80,0x80,0x80,0x40,0x40,
+ 0x40,0xc0,0x40,0xe0,0x00,0xe0,0xa0,0xe0,
+ 0xa0,0x50,0xa0,0x04,0x5e,0x2c,0x54,0x48,
+ 0xc4,0x40,0x0e,0x44,0x22,0x5c,0x48,0xc4,
+ 0x40,0x04,0x5e,0x2c,0xd4,0x28,0x64,0xe0,
+ 0x60,0x90,0x40,0x20,0x00,0x20,0x88,0x88,
+ 0x70,0x50,0x20,0x20,0x00,0x20,0x40,0x88,
+ 0x88,0x70,0x50,0x20,0x20,0x00,0x20,0x10,
+ 0x88,0x88,0x70,0x50,0x20,0x20,0x00,0x50,
+ 0x20,0x88,0x88,0x70,0x50,0x20,0x20,0x00,
+ 0x50,0x28,0x88,0x88,0x70,0x50,0x20,0x20,
+ 0x00,0x50,0x88,0x88,0x70,0x50,0x20,0x20,
+ 0x20,0x50,0x20,0x9e,0x90,0x7c,0x50,0x30,
+ 0x3e,0x80,0x40,0x70,0x88,0x80,0x88,0x88,
+ 0x70,0xf0,0x80,0x80,0xe0,0x80,0xf0,0x00,
+ 0x20,0x40,0xf0,0x80,0x80,0xe0,0x80,0xf0,
+ 0x00,0x40,0x20,0xf0,0x80,0x80,0xe0,0x80,
+ 0xf0,0x00,0xa0,0x40,0xf0,0x80,0x80,0xe0,
+ 0x80,0xf0,0x00,0xa0,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x00,0x40,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x00,0x80,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x00,0xa0,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x00,0xa0,0x70,
+ 0x48,0x48,0xe8,0x48,0x70,0x88,0x98,0xa8,
+ 0xa8,0xc8,0x88,0x00,0x50,0x28,0x70,0x88,
+ 0x88,0x88,0x88,0x70,0x00,0x20,0x40,0x70,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x10,
+ 0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x50,
+ 0x20,0x70,0x88,0x88,0x88,0x88,0x70,0x00,
+ 0x50,0x28,0x70,0x88,0x88,0x88,0x88,0x70,
+ 0x00,0x50,0x90,0x60,0x60,0x90,0x80,0xf0,
+ 0xc8,0xa8,0x98,0x88,0x78,0x08,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x70,
+ 0x88,0x88,0x88,0x88,0x88,0x00,0x20,0x10,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x00,0x50,
+ 0x20,0x70,0x88,0x88,0x88,0x88,0x88,0x00,
+ 0x50,0x20,0x20,0x30,0x48,0x48,0xc8,0x00,
+ 0x10,0x08,0x80,0xf0,0x88,0x88,0xf0,0x80,
+ 0x80,0xa0,0x90,0x90,0xa0,0x90,0x60,0xd0,
+ 0xa0,0xe0,0x20,0xc0,0x00,0x40,0x80,0xd0,
+ 0xa0,0xe0,0x20,0xc0,0x00,0x40,0x20,0xd0,
+ 0xa0,0xe0,0x20,0xc0,0x00,0xa0,0x40,0x68,
+ 0x50,0x70,0x10,0x60,0x00,0xb0,0x68,0xd0,
+ 0xa0,0xe0,0x20,0xc0,0x00,0xa0,0xd0,0xa0,
+ 0xe0,0x20,0xc0,0x40,0xa0,0x40,0xd8,0xa0,
+ 0xf8,0x28,0xd0,0x80,0x40,0x60,0x80,0x80,
+ 0x80,0x60,0x60,0x80,0xe0,0xa0,0x40,0x00,
+ 0x20,0x40,0x60,0x80,0xe0,0xa0,0x40,0x00,
+ 0x40,0x20,0x60,0x80,0xe0,0xa0,0x40,0x00,
+ 0xa0,0x40,0x60,0x80,0xe0,0xa0,0x40,0x00,
+ 0xa0,0x40,0x40,0x40,0x40,0x40,0x00,0x40,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x80,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x00,0xa0,
+ 0x60,0x90,0x90,0x90,0x70,0xa0,0x60,0x90,
+ 0x90,0x90,0x90,0x90,0xe0,0x00,0xa0,0x50,
+ 0x60,0x90,0x90,0x90,0x60,0x00,0x20,0x40,
+ 0x60,0x90,0x90,0x90,0x60,0x00,0x20,0x10,
+ 0x60,0x90,0x90,0x90,0x60,0x00,0xa0,0x40,
+ 0x60,0x90,0x90,0x90,0x60,0x00,0xa0,0x50,
+ 0x60,0x90,0x90,0x90,0x60,0x00,0x90,0x20,
+ 0x00,0xf0,0x00,0x20,0x80,0x70,0x68,0x58,
+ 0x48,0x3c,0x02,0x60,0xa0,0xa0,0xa0,0xa0,
+ 0x00,0x40,0x80,0x60,0xa0,0xa0,0xa0,0xa0,
+ 0x00,0x40,0x20,0x60,0xa0,0xa0,0xa0,0xa0,
+ 0x00,0xa0,0x40,0x60,0xa0,0xa0,0xa0,0xa0,
+ 0x00,0xa0,0x80,0x40,0x60,0x90,0x90,0x90,
+ 0x00,0x20,0x10,0x80,0xe0,0x90,0x90,0x90,
+ 0xe0,0x80,0x80,0x40,0x60,0x90,0x90,0x90,
+ 0x00,0x50,
+};
+
+BMF_FontData BMF_font_helvb8 = {
+ 0, -2,
+ 9, 9,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 8, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 2, 0},
+ {1, 6, -1, 0, 2, 1},
+ {3, 3, -1, -3, 3, 7},
+ {5, 5, 0, 0, 5, 10},
+ {4, 7, -1, 1, 5, 15},
+ {6, 6, -1, 0, 7, 22},
+ {5, 6, -1, 0, 6, 28},
+ {1, 3, -1, -3, 2, 34},
+ {2, 7, -1, 1, 3, 37},
+ {2, 7, -1, 1, 3, 44},
+ {3, 3, -1, -2, 3, 51},
+ {5, 5, -1, 0, 5, 54},
+ {2, 3, 0, 2, 2, 59},
+ {4, 1, -2, -2, 6, 62},
+ {1, 1, -1, 0, 2, 63},
+ {2, 7, -1, 1, 2, 64},
+ {4, 6, -1, 0, 5, 71},
+ {2, 6, -2, 0, 5, 77},
+ {4, 6, -1, 0, 5, 83},
+ {3, 6, -2, 0, 5, 89},
+ {4, 6, -1, 0, 5, 95},
+ {3, 6, -2, 0, 5, 101},
+ {4, 6, -1, 0, 5, 107},
+ {4, 6, -1, 0, 5, 113},
+ {4, 6, -1, 0, 5, 119},
+ {4, 6, -1, 0, 5, 125},
+ {1, 4, -1, 0, 2, 131},
+ {2, 6, 0, 2, 2, 135},
+ {3, 5, -1, 0, 5, 141},
+ {3, 3, -1, -1, 4, 146},
+ {3, 5, -2, 0, 5, 149},
+ {3, 5, -2, 0, 5, 154},
+ {8, 7, -1, 1, 9, 159},
+ {5, 6, -1, 0, 6, 166},
+ {4, 6, -2, 0, 6, 172},
+ {5, 6, -1, 0, 6, 178},
+ {5, 6, -1, 0, 6, 184},
+ {4, 6, -2, 0, 6, 190},
+ {4, 6, -2, 0, 5, 196},
+ {5, 6, -1, 0, 6, 202},
+ {5, 6, -1, 0, 6, 208},
+ {1, 6, -1, 0, 2, 214},
+ {3, 6, -1, 0, 4, 220},
+ {4, 6, -2, 0, 6, 226},
+ {3, 6, -2, 0, 5, 232},
+ {5, 6, -2, 0, 7, 238},
+ {5, 6, -1, 0, 6, 244},
+ {5, 6, -1, 0, 6, 250},
+ {4, 6, -2, 0, 6, 256},
+ {5, 8, -1, 2, 6, 262},
+ {4, 6, -2, 0, 6, 270},
+ {4, 6, -2, 0, 6, 276},
+ {3, 6, -1, 0, 4, 282},
+ {5, 6, -1, 0, 6, 288},
+ {4, 6, -2, 0, 6, 294},
+ {7, 6, -1, 0, 7, 300},
+ {4, 6, -2, 0, 6, 306},
+ {5, 6, -1, 0, 6, 312},
+ {4, 6, -2, 0, 6, 318},
+ {2, 7, -1, 1, 2, 324},
+ {2, 7, 0, 1, 2, 331},
+ {2, 7, 0, 1, 2, 338},
+ {5, 3, 0, -2, 5, 345},
+ {5, 1, 0, 1, 5, 348},
+ {1, 3, -1, -3, 2, 349},
+ {4, 5, -1, 0, 4, 352},
+ {4, 7, -1, 0, 5, 357},
+ {3, 5, -1, 0, 4, 364},
+ {4, 7, -1, 0, 5, 369},
+ {3, 5, -1, 0, 4, 376},
+ {3, 7, -1, 0, 3, 381},
+ {4, 6, -1, 1, 5, 388},
+ {4, 7, -1, 0, 5, 394},
+ {1, 7, -1, 0, 2, 401},
+ {2, 9, 0, 2, 2, 408},
+ {3, 7, -1, 0, 4, 417},
+ {1, 7, -1, 0, 2, 424},
+ {5, 5, -1, 0, 6, 431},
+ {4, 5, -1, 0, 5, 436},
+ {4, 5, -1, 0, 5, 441},
+ {4, 6, -1, 1, 5, 446},
+ {4, 6, -1, 1, 5, 452},
+ {3, 5, -1, 0, 3, 458},
+ {3, 5, -1, 0, 4, 463},
+ {3, 7, -1, 0, 3, 468},
+ {3, 5, -1, 0, 4, 475},
+ {4, 5, -1, 0, 5, 480},
+ {5, 5, -1, 0, 6, 485},
+ {4, 5, -1, 0, 5, 490},
+ {4, 6, -1, 1, 4, 495},
+ {3, 5, -1, 0, 4, 501},
+ {3, 7, 0, 1, 2, 506},
+ {1, 7, -1, 1, 2, 513},
+ {3, 7, 0, 1, 2, 520},
+ {5, 2, -1, -2, 6, 527},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 1, 0, 0, 2, 529},
+ {1, 7, -1, 2, 2, 530},
+ {3, 7, -1, 1, 5, 537},
+ {4, 6, -1, 0, 5, 544},
+ {5, 5, 0, 0, 4, 550},
+ {5, 5, -1, 0, 6, 555},
+ {1, 7, -1, 1, 2, 560},
+ {4, 8, -1, 2, 5, 567},
+ {4, 1, 0, -5, 2, 575},
+ {6, 7, -1, 1, 7, 576},
+ {3, 5, 0, -1, 3, 583},
+ {4, 3, -1, -1, 5, 588},
+ {4, 3, -1, -1, 6, 591},
+ {2, 1, 0, -2, 3, 594},
+ {6, 7, -1, 1, 7, 595},
+ {3, 1, 0, -5, 2, 602},
+ {3, 3, -1, -3, 3, 603},
+ {4, 5, -1, 0, 5, 606},
+ {2, 4, -1, -2, 2, 611},
+ {3, 4, 0, -2, 2, 615},
+ {2, 2, 0, -4, 2, 619},
+ {3, 6, -1, 2, 4, 621},
+ {5, 8, 0, 2, 5, 627},
+ {1, 2, -1, -1, 2, 635},
+ {2, 2, 0, 2, 2, 637},
+ {2, 4, 0, -2, 2, 639},
+ {3, 5, 0, -1, 3, 643},
+ {4, 3, -1, -1, 5, 648},
+ {7, 7, 0, 1, 7, 651},
+ {7, 7, 0, 1, 7, 658},
+ {7, 7, 0, 1, 7, 665},
+ {4, 6, -1, 1, 5, 672},
+ {5, 9, -1, 0, 6, 678},
+ {5, 9, -1, 0, 6, 687},
+ {5, 9, -1, 0, 6, 696},
+ {5, 9, -1, 0, 6, 705},
+ {5, 8, -1, 0, 6, 714},
+ {5, 9, -1, 0, 6, 722},
+ {7, 6, -1, 0, 8, 731},
+ {5, 8, -1, 2, 6, 737},
+ {4, 9, -2, 0, 6, 745},
+ {4, 9, -2, 0, 6, 754},
+ {4, 9, -2, 0, 6, 763},
+ {4, 8, -2, 0, 6, 772},
+ {2, 9, 0, 0, 2, 780},
+ {2, 9, -1, 0, 2, 789},
+ {3, 9, 0, 0, 2, 798},
+ {3, 8, 0, 0, 2, 807},
+ {5, 6, -1, 0, 6, 815},
+ {5, 9, -1, 0, 6, 821},
+ {5, 9, -1, 0, 6, 830},
+ {5, 9, -1, 0, 6, 839},
+ {5, 9, -1, 0, 6, 848},
+ {5, 9, -1, 0, 6, 857},
+ {5, 8, -1, 0, 6, 866},
+ {4, 4, -1, 0, 5, 874},
+ {5, 8, -1, 1, 6, 878},
+ {5, 9, -1, 0, 6, 886},
+ {5, 9, -1, 0, 6, 895},
+ {5, 9, -1, 0, 6, 904},
+ {5, 8, -1, 0, 6, 913},
+ {5, 9, -1, 0, 6, 921},
+ {5, 6, -1, 0, 6, 930},
+ {4, 7, -2, 1, 6, 936},
+ {4, 8, -1, 0, 4, 943},
+ {4, 8, -1, 0, 4, 951},
+ {4, 8, -1, 0, 4, 959},
+ {5, 8, 0, 0, 4, 967},
+ {4, 7, -1, 0, 4, 975},
+ {4, 8, -1, 0, 4, 982},
+ {5, 5, -1, 0, 6, 990},
+ {3, 7, -1, 2, 4, 995},
+ {3, 8, -1, 0, 4, 1002},
+ {3, 8, -1, 0, 4, 1010},
+ {3, 8, -1, 0, 4, 1018},
+ {3, 7, -1, 0, 4, 1026},
+ {2, 8, 0, 0, 2, 1033},
+ {2, 8, -1, 0, 2, 1041},
+ {3, 8, 0, 0, 2, 1049},
+ {3, 7, 0, 0, 2, 1057},
+ {4, 8, -1, 0, 5, 1064},
+ {4, 8, -1, 0, 5, 1072},
+ {4, 8, -1, 0, 5, 1080},
+ {4, 8, -1, 0, 5, 1088},
+ {4, 8, -1, 0, 5, 1096},
+ {4, 8, -1, 0, 5, 1104},
+ {4, 7, -1, 0, 5, 1112},
+ {4, 5, -1, 0, 5, 1119},
+ {7, 7, 0, 1, 5, 1124},
+ {3, 8, -1, 0, 4, 1131},
+ {3, 8, -1, 0, 4, 1139},
+ {3, 8, -1, 0, 4, 1147},
+ {3, 7, -1, 0, 4, 1155},
+ {4, 9, -1, 1, 4, 1162},
+ {4, 7, -1, 1, 5, 1171},
+ {4, 8, -1, 1, 4, 1178},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_scr12.cpp b/intern/bmfont/intern/BMF_font_scr12.cpp
new file mode 100644
index 00000000000..a870ea91763
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_scr12.cpp
@@ -0,0 +1,484 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_SCR12
+
+static unsigned char bitmap_data[]= {
+ 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,
+ 0xa0,0xa0,0xa0,0xa0,0x50,0x50,0xfc,0x28,
+ 0x28,0x7e,0x14,0x14,0x20,0x70,0xa8,0x28,
+ 0x70,0xa0,0xa8,0x70,0x20,0x98,0x54,0x54,
+ 0x2c,0xd0,0xa8,0xa8,0x64,0x74,0x88,0x8c,
+ 0x50,0x20,0x50,0x48,0x30,0x80,0x40,0x20,
+ 0x20,0x20,0x40,0x40,0x80,0x80,0x80,0x80,
+ 0x40,0x40,0x20,0x80,0x40,0x40,0x20,0x20,
+ 0x20,0x20,0x40,0x40,0x80,0x20,0xa8,0x70,
+ 0xa8,0x20,0x20,0x20,0xf8,0x20,0x20,0x80,
+ 0x40,0x40,0xc0,0xf8,0x80,0x80,0x80,0x80,
+ 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,
+ 0x70,0x88,0x88,0xc8,0xa8,0x98,0x88,0x70,
+ 0xe0,0x40,0x40,0x40,0x40,0x40,0xc0,0x40,
+ 0xf8,0x80,0x40,0x20,0x10,0x08,0x88,0x70,
+ 0x70,0x88,0x08,0x08,0x70,0x08,0x88,0x70,
+ 0x10,0x10,0x10,0xf8,0x90,0x50,0x30,0x10,
+ 0x70,0x88,0x08,0x08,0xf0,0x80,0x80,0xf8,
+ 0x70,0x88,0x88,0x88,0xf0,0x80,0x88,0x70,
+ 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0xf8,
+ 0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x70,
+ 0x70,0x88,0x08,0x78,0x88,0x88,0x88,0x70,
+ 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x40,
+ 0x40,0xc0,0x00,0x00,0x40,0x40,0x08,0x10,
+ 0x20,0x40,0x80,0x40,0x20,0x10,0x08,0xf8,
+ 0x00,0xf8,0x80,0x40,0x20,0x10,0x08,0x10,
+ 0x20,0x40,0x80,0x20,0x00,0x20,0x20,0x10,
+ 0x88,0x88,0x70,0x38,0x40,0x98,0xa8,0xa8,
+ 0x98,0x48,0x30,0x88,0x88,0xf8,0x88,0x50,
+ 0x50,0x20,0x20,0xf0,0x88,0x88,0x88,0xf0,
+ 0x88,0x88,0xf0,0x70,0x88,0x80,0x80,0x80,
+ 0x80,0x88,0x70,0xf0,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0xf0,0xf8,0x80,0x80,0x80,0xf0,
+ 0x80,0x80,0xf8,0x80,0x80,0x80,0x80,0xf0,
+ 0x80,0x80,0xf8,0x68,0x98,0x88,0x88,0x98,
+ 0x80,0x88,0x70,0x88,0x88,0x88,0x88,0xf8,
+ 0x88,0x88,0x88,0xe0,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0xe0,0x70,0x88,0x88,0x08,0x08,
+ 0x08,0x08,0x08,0x88,0x88,0x90,0xa0,0xc0,
+ 0xa0,0x90,0x88,0xf8,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x88,0x88,0xa8,0xa8,0xd8,
+ 0xd8,0x88,0x88,0x88,0x98,0x98,0xa8,0xa8,
+ 0xc8,0xc8,0x88,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x70,0x80,0x80,0x80,0x80,0xf0,
+ 0x88,0x88,0xf0,0x08,0x10,0x70,0xa8,0x88,
+ 0x88,0x88,0x88,0x88,0x70,0x88,0x90,0x90,
+ 0xa0,0xf0,0x88,0x88,0xf0,0x70,0x88,0x88,
+ 0x08,0x70,0x80,0x88,0x70,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xf8,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x20,0x20,0x50,
+ 0x50,0x50,0x88,0x88,0x88,0x50,0x50,0xf8,
+ 0xa8,0xa8,0xa8,0x88,0x88,0x88,0x88,0x50,
+ 0x20,0x20,0x50,0x88,0x88,0x20,0x20,0x20,
+ 0x20,0x50,0x50,0x88,0x88,0xf8,0x80,0x40,
+ 0x40,0x20,0x10,0x08,0xf8,0xe0,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0xe0,0x08,0x08,
+ 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,
+ 0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0xe0,0x88,0x50,0x20,0xfe,0x20,0x40,0x80,
+ 0x80,0x68,0x98,0x88,0x78,0x08,0x70,0xb0,
+ 0xc8,0x88,0x88,0xc8,0xb0,0x80,0x80,0x70,
+ 0x88,0x80,0x80,0x88,0x70,0x68,0x98,0x88,
+ 0x88,0x98,0x68,0x08,0x08,0x70,0x88,0x80,
+ 0xf8,0x88,0x70,0x40,0x40,0x40,0x40,0x40,
+ 0xf0,0x40,0x38,0xf0,0x08,0x68,0x98,0x88,
+ 0x88,0x98,0x68,0x88,0x88,0x88,0x88,0xc8,
+ 0xb0,0x80,0x80,0x20,0x20,0x20,0x20,0x20,
+ 0xe0,0x00,0x20,0x60,0x90,0x10,0x10,0x10,
+ 0x10,0x10,0x70,0x00,0x10,0x88,0x90,0xa0,
+ 0xc0,0xa0,0x90,0x80,0x80,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0xa8,0xa8,0xa8,
+ 0xa8,0xa8,0xd0,0x88,0x88,0x88,0x88,0xc8,
+ 0xb0,0x70,0x88,0x88,0x88,0x88,0x70,0x80,
+ 0x80,0xb0,0xc8,0x88,0x88,0xc8,0xb0,0x08,
+ 0x08,0x68,0x98,0x88,0x88,0x98,0x68,0x80,
+ 0x80,0x80,0x80,0xc8,0xb0,0x70,0x88,0x10,
+ 0x60,0x88,0x70,0x30,0x40,0x40,0x40,0x40,
+ 0xf0,0x40,0x68,0x98,0x88,0x88,0x88,0x88,
+ 0x20,0x20,0x50,0x50,0x88,0x88,0x50,0xa8,
+ 0xa8,0xa8,0x88,0x88,0x88,0x88,0x50,0x20,
+ 0x50,0x88,0xf0,0x08,0x68,0x98,0x88,0x88,
+ 0x88,0x88,0xf8,0x80,0x40,0x20,0x10,0xf8,
+ 0x18,0x20,0x20,0x20,0x20,0xc0,0x20,0x20,
+ 0x20,0x18,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0xc0,0x20,0x20,0x20,
+ 0x20,0x18,0x20,0x20,0x20,0xc0,0x98,0xb4,
+ 0x64,0x80,0x80,0x80,0x80,0x80,0x00,0x80,
+ 0x80,0x20,0x20,0x70,0x88,0x80,0x88,0x70,
+ 0x20,0x20,0xb0,0x48,0x40,0xf0,0x40,0x40,
+ 0x48,0x30,0x90,0x60,0x90,0x90,0x60,0x90,
+ 0x20,0x70,0x20,0x70,0x20,0x50,0x88,0x88,
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,
+ 0x80,0x80,0x70,0x88,0x10,0x28,0x48,0x90,
+ 0xa0,0x40,0x88,0x70,0xa0,0x78,0x84,0xb4,
+ 0xa4,0xb4,0x84,0x78,0xf0,0x90,0x70,0x10,
+ 0x60,0x14,0x28,0x50,0xa0,0x50,0x28,0x14,
+ 0x08,0xf8,0xf0,0x78,0x84,0xac,0xb4,0xb4,
+ 0x84,0x78,0xe0,0x60,0x90,0x60,0xf8,0x00,
+ 0x20,0x20,0xf8,0x20,0x20,0xe0,0x40,0x20,
+ 0xa0,0x40,0xc0,0x20,0x40,0x20,0xc0,0x80,
+ 0x40,0x80,0xe8,0x90,0x90,0x90,0x90,0x28,
+ 0x28,0x28,0x28,0x68,0xa8,0xa8,0xa8,0x7c,
+ 0x80,0x80,0xc0,0x40,0xe0,0x40,0x40,0xc0,
+ 0x40,0xf0,0x60,0x90,0x90,0x60,0xa0,0x50,
+ 0x28,0x14,0x28,0x50,0xa0,0x08,0x38,0xa8,
+ 0x58,0x28,0xf0,0x48,0x40,0xc0,0x40,0x38,
+ 0x10,0x88,0x68,0x30,0xf0,0x48,0x40,0xc0,
+ 0x40,0x08,0x38,0xa8,0x58,0x28,0xd0,0x28,
+ 0x40,0x20,0xc0,0x70,0x88,0x88,0x40,0x20,
+ 0x20,0x00,0x20,0x88,0x88,0xf8,0x88,0x50,
+ 0x50,0x20,0x00,0x20,0x40,0x88,0x88,0xf8,
+ 0x50,0x50,0x20,0x20,0x00,0x20,0x10,0x88,
+ 0x88,0xf8,0x50,0x50,0x20,0x20,0x00,0x50,
+ 0x20,0x88,0x88,0xf8,0x50,0x50,0x20,0x20,
+ 0x00,0xb0,0x68,0x88,0x88,0xf8,0x50,0x50,
+ 0x20,0x20,0x00,0x50,0x88,0x88,0xf8,0x50,
+ 0x50,0x20,0x20,0x20,0x50,0x20,0x9c,0x90,
+ 0xf0,0x50,0x5c,0x30,0x30,0x1c,0x60,0x20,
+ 0x70,0x88,0x80,0x80,0x80,0x80,0x88,0x70,
+ 0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,
+ 0x20,0x40,0xf8,0x80,0x80,0xf0,0x80,0x80,
+ 0xf8,0x00,0x20,0x10,0xf8,0x80,0x80,0xf0,
+ 0x80,0x80,0xf8,0x00,0x50,0x20,0xf8,0x80,
+ 0x80,0xf0,0x80,0x80,0xf8,0x00,0x50,0xe0,
+ 0x40,0x40,0x40,0x40,0x40,0xe0,0x00,0x40,
+ 0x80,0xe0,0x40,0x40,0x40,0x40,0x40,0xe0,
+ 0x00,0x40,0x20,0xe0,0x40,0x40,0x40,0x40,
+ 0x40,0xe0,0x00,0xa0,0x40,0xe0,0x40,0x40,
+ 0x40,0x40,0x40,0xe0,0x00,0xa0,0x78,0x44,
+ 0x44,0xf4,0x44,0x44,0x44,0x78,0x88,0x98,
+ 0x98,0xa8,0xc8,0xc8,0x88,0x00,0xb0,0x68,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,
+ 0x20,0x40,0x70,0x88,0x88,0x88,0x88,0x88,
+ 0x70,0x00,0x20,0x10,0x70,0x88,0x88,0x88,
+ 0x88,0x88,0x70,0x00,0x50,0x20,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0xb0,0x68,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,
+ 0x50,0x88,0x50,0x20,0x50,0x88,0xb8,0x44,
+ 0x64,0x54,0x4c,0x44,0x3a,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x70,
+ 0x88,0x88,0x88,0x88,0x88,0x88,0x00,0x20,
+ 0x10,0x70,0x88,0x88,0x88,0x88,0x88,0x88,
+ 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x00,0x50,0x20,0x20,0x20,0x50,
+ 0x50,0x88,0x88,0x00,0x20,0x10,0x80,0x80,
+ 0xf0,0x88,0x88,0x88,0xf0,0x80,0x80,0xb0,
+ 0x88,0x88,0x88,0x90,0xa0,0x90,0x60,0x78,
+ 0x88,0x78,0x08,0x70,0x00,0x20,0x40,0x78,
+ 0x88,0x78,0x08,0x70,0x00,0x20,0x10,0x78,
+ 0x88,0x78,0x08,0x70,0x00,0x50,0x20,0x78,
+ 0x88,0x78,0x08,0x70,0x00,0xb0,0x68,0x78,
+ 0x88,0x78,0x08,0x70,0x00,0x50,0x78,0x88,
+ 0x78,0x08,0x70,0x00,0x20,0x50,0x20,0x6c,
+ 0x90,0x7c,0x12,0x6c,0x60,0x20,0x70,0x88,
+ 0x80,0x80,0x88,0x70,0x78,0x80,0xf8,0x88,
+ 0x70,0x00,0x20,0x40,0x78,0x80,0xf8,0x88,
+ 0x70,0x00,0x20,0x10,0x78,0x80,0xf8,0x88,
+ 0x70,0x00,0x50,0x20,0x78,0x80,0xf8,0x88,
+ 0x70,0x00,0x50,0x20,0x20,0x20,0x20,0xe0,
+ 0x00,0x40,0x80,0x20,0x20,0x20,0x20,0xe0,
+ 0x00,0x40,0x20,0x20,0x20,0x20,0x20,0xe0,
+ 0x00,0xa0,0x40,0x20,0x20,0x20,0x20,0xe0,
+ 0x00,0xa0,0x70,0x88,0x88,0x88,0x78,0x08,
+ 0x90,0x60,0xd0,0x88,0x88,0x88,0xc8,0xb0,
+ 0x00,0xb0,0x68,0x70,0x88,0x88,0x88,0x70,
+ 0x00,0x20,0x40,0x70,0x88,0x88,0x88,0x70,
+ 0x00,0x20,0x10,0x70,0x88,0x88,0x88,0x70,
+ 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x70,
+ 0x00,0xb0,0x68,0x70,0x88,0x88,0x88,0x70,
+ 0x00,0x50,0x20,0x00,0xf8,0x00,0x20,0xb8,
+ 0x64,0x54,0x4c,0x3a,0x68,0x98,0x88,0x88,
+ 0x88,0x00,0x20,0x40,0x68,0x98,0x88,0x88,
+ 0x88,0x00,0x20,0x10,0x68,0x98,0x88,0x88,
+ 0x88,0x00,0x50,0x20,0x68,0x98,0x88,0x88,
+ 0x88,0x00,0x50,0xf0,0x08,0x68,0x98,0x88,
+ 0x88,0x88,0x00,0x20,0x10,0x80,0x80,0xb0,
+ 0xc8,0x88,0x88,0xc8,0xb0,0x80,0x80,0xf0,
+ 0x08,0x68,0x98,0x88,0x88,0x88,0x00,0xd8,
+};
+
+BMF_FontData BMF_font_scr12 = {
+ 0, -2,
+ 7, 10,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 16, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 7, -1},
+ {1, 8, -3, 0, 7, 0},
+ {3, 4, -2, -5, 7, 8},
+ {7, 8, 0, 0, 7, 12},
+ {5, 9, -1, 1, 7, 20},
+ {6, 8, 0, 0, 7, 29},
+ {6, 8, 0, 0, 7, 37},
+ {3, 4, -2, -5, 7, 45},
+ {3, 10, -2, 2, 7, 49},
+ {3, 10, -2, 2, 7, 59},
+ {5, 5, -1, -3, 7, 69},
+ {5, 5, -1, -1, 7, 74},
+ {2, 4, -2, 2, 7, 79},
+ {5, 1, -1, -3, 7, 83},
+ {1, 2, -3, 0, 7, 84},
+ {5, 10, -1, 1, 7, 86},
+ {5, 8, -1, 0, 7, 96},
+ {3, 8, -2, 0, 7, 104},
+ {5, 8, -1, 0, 7, 112},
+ {5, 8, -1, 0, 7, 120},
+ {5, 8, -1, 0, 7, 128},
+ {5, 8, -1, 0, 7, 136},
+ {5, 8, -1, 0, 7, 144},
+ {5, 8, -1, 0, 7, 152},
+ {5, 8, -1, 0, 7, 160},
+ {5, 8, -1, 0, 7, 168},
+ {1, 6, -3, 0, 7, 176},
+ {2, 8, -2, 2, 7, 182},
+ {5, 9, -1, 1, 7, 190},
+ {5, 3, -1, -2, 7, 199},
+ {5, 9, -1, 1, 7, 202},
+ {5, 8, -1, 0, 7, 211},
+ {5, 8, -1, 0, 7, 219},
+ {5, 8, -1, 0, 7, 227},
+ {5, 8, -1, 0, 7, 235},
+ {5, 8, -1, 0, 7, 243},
+ {5, 8, -1, 0, 7, 251},
+ {5, 8, -1, 0, 7, 259},
+ {5, 8, -1, 0, 7, 267},
+ {5, 8, -1, 0, 7, 275},
+ {5, 8, -1, 0, 7, 283},
+ {3, 8, -2, 0, 7, 291},
+ {5, 8, -1, 0, 7, 299},
+ {5, 8, -1, 0, 7, 307},
+ {5, 8, -1, 0, 7, 315},
+ {5, 8, -1, 0, 7, 323},
+ {5, 8, -1, 0, 7, 331},
+ {5, 8, -1, 0, 7, 339},
+ {5, 8, -1, 0, 7, 347},
+ {5, 10, -1, 2, 7, 355},
+ {5, 8, -1, 0, 7, 365},
+ {5, 8, -1, 0, 7, 373},
+ {5, 8, -1, 0, 7, 381},
+ {5, 8, -1, 0, 7, 389},
+ {5, 8, -1, 0, 7, 397},
+ {5, 8, -1, 0, 7, 405},
+ {5, 8, -1, 0, 7, 413},
+ {5, 8, -1, 0, 7, 421},
+ {5, 8, -1, 0, 7, 429},
+ {3, 9, -2, 1, 7, 437},
+ {5, 10, -1, 1, 7, 446},
+ {3, 9, -2, 1, 7, 456},
+ {5, 3, -1, -5, 7, 465},
+ {7, 1, 0, 1, 7, 468},
+ {3, 4, -2, -5, 7, 469},
+ {5, 6, -1, 0, 7, 473},
+ {5, 8, -1, 0, 7, 479},
+ {5, 6, -1, 0, 7, 487},
+ {5, 8, -1, 0, 7, 493},
+ {5, 6, -1, 0, 7, 501},
+ {5, 8, -1, 0, 7, 507},
+ {5, 8, -1, 2, 7, 515},
+ {5, 8, -1, 0, 7, 523},
+ {3, 8, -2, 0, 7, 531},
+ {4, 10, -1, 2, 7, 539},
+ {5, 8, -1, 0, 7, 549},
+ {3, 8, -2, 0, 7, 557},
+ {5, 6, -1, 0, 7, 565},
+ {5, 6, -1, 0, 7, 571},
+ {5, 6, -1, 0, 7, 577},
+ {5, 8, -1, 2, 7, 583},
+ {5, 8, -1, 2, 7, 591},
+ {5, 6, -1, 0, 7, 599},
+ {5, 6, -1, 0, 7, 605},
+ {4, 7, -1, 0, 7, 611},
+ {5, 6, -1, 0, 7, 618},
+ {5, 6, -1, 0, 7, 624},
+ {5, 6, -1, 0, 7, 630},
+ {5, 6, -1, 0, 7, 636},
+ {5, 8, -1, 2, 7, 642},
+ {5, 6, -1, 0, 7, 650},
+ {5, 10, -1, 2, 7, 656},
+ {1, 10, -3, 1, 7, 666},
+ {5, 10, -1, 2, 7, 676},
+ {6, 3, 0, -2, 7, 686},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 8, -3, 2, 7, 689},
+ {5, 9, -1, 0, 7, 697},
+ {5, 8, -1, 0, 7, 706},
+ {4, 6, -1, -2, 7, 714},
+ {5, 8, -1, 0, 7, 720},
+ {1, 10, -3, 1, 7, 728},
+ {5, 10, -1, 1, 7, 738},
+ {3, 1, -2, -7, 7, 748},
+ {6, 7, 0, 0, 7, 749},
+ {4, 5, -1, -4, 7, 756},
+ {6, 7, 0, 0, 7, 761},
+ {5, 2, -1, -3, 7, 768},
+ {4, 1, -1, -3, 7, 770},
+ {6, 7, 0, 0, 7, 771},
+ {3, 1, -2, -7, 7, 778},
+ {4, 3, -1, -4, 7, 779},
+ {5, 7, -1, 0, 7, 782},
+ {3, 5, -2, -4, 7, 789},
+ {3, 5, -2, -4, 7, 794},
+ {2, 2, -2, -7, 7, 799},
+ {5, 6, -1, 1, 7, 801},
+ {6, 9, 0, 1, 7, 807},
+ {1, 2, -3, -3, 7, 816},
+ {2, 2, -2, 2, 7, 818},
+ {3, 5, -2, -4, 7, 820},
+ {4, 5, -1, -4, 7, 825},
+ {6, 7, 0, 0, 7, 830},
+ {5, 10, -1, 1, 7, 837},
+ {5, 10, -1, 1, 7, 847},
+ {5, 10, -1, 1, 7, 857},
+ {5, 8, -1, 2, 7, 867},
+ {5, 10, -1, 0, 7, 875},
+ {5, 10, -1, 0, 7, 885},
+ {5, 10, -1, 0, 7, 895},
+ {5, 10, -1, 0, 7, 905},
+ {5, 9, -1, 0, 7, 915},
+ {5, 10, -1, 0, 7, 924},
+ {6, 8, 0, 0, 7, 934},
+ {5, 10, -1, 2, 7, 942},
+ {5, 10, -1, 0, 7, 952},
+ {5, 10, -1, 0, 7, 962},
+ {5, 10, -1, 0, 7, 972},
+ {5, 9, -1, 0, 7, 982},
+ {3, 10, -2, 0, 7, 991},
+ {3, 10, -2, 0, 7, 1001},
+ {3, 10, -2, 0, 7, 1011},
+ {3, 9, -2, 0, 7, 1021},
+ {6, 8, 0, 0, 7, 1030},
+ {5, 10, -1, 0, 7, 1038},
+ {5, 10, -1, 0, 7, 1048},
+ {5, 10, -1, 0, 7, 1058},
+ {5, 10, -1, 0, 7, 1068},
+ {5, 10, -1, 0, 7, 1078},
+ {5, 9, -1, 0, 7, 1088},
+ {5, 5, -1, -1, 7, 1097},
+ {7, 7, 0, 0, 7, 1102},
+ {5, 10, -1, 0, 7, 1109},
+ {5, 10, -1, 0, 7, 1119},
+ {5, 10, -1, 0, 7, 1129},
+ {5, 9, -1, 0, 7, 1139},
+ {5, 10, -1, 0, 7, 1148},
+ {5, 9, -1, 0, 7, 1158},
+ {5, 8, -1, 0, 7, 1167},
+ {5, 8, -1, 0, 7, 1175},
+ {5, 8, -1, 0, 7, 1183},
+ {5, 8, -1, 0, 7, 1191},
+ {5, 8, -1, 0, 7, 1199},
+ {5, 7, -1, 0, 7, 1207},
+ {5, 9, -1, 0, 7, 1214},
+ {7, 5, 0, 0, 7, 1223},
+ {5, 8, -1, 2, 7, 1228},
+ {5, 8, -1, 0, 7, 1236},
+ {5, 8, -1, 0, 7, 1244},
+ {5, 8, -1, 0, 7, 1252},
+ {5, 7, -1, 0, 7, 1260},
+ {3, 8, -2, 0, 7, 1267},
+ {3, 8, -2, 0, 7, 1275},
+ {3, 8, -2, 0, 7, 1283},
+ {3, 7, -2, 0, 7, 1291},
+ {5, 9, -1, 0, 7, 1298},
+ {5, 8, -1, 0, 7, 1307},
+ {5, 8, -1, 0, 7, 1315},
+ {5, 8, -1, 0, 7, 1323},
+ {5, 8, -1, 0, 7, 1331},
+ {5, 8, -1, 0, 7, 1339},
+ {5, 7, -1, 0, 7, 1347},
+ {5, 5, -1, -1, 7, 1354},
+ {7, 5, 0, 0, 7, 1359},
+ {5, 8, -1, 0, 7, 1364},
+ {5, 8, -1, 0, 7, 1372},
+ {5, 8, -1, 0, 7, 1380},
+ {5, 7, -1, 0, 7, 1388},
+ {5, 10, -1, 2, 7, 1395},
+ {5, 10, -1, 2, 7, 1405},
+ {5, 9, -1, 2, 7, 1415},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_scr14.cpp b/intern/bmfont/intern/BMF_font_scr14.cpp
new file mode 100644
index 00000000000..c060556c7e0
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_scr14.cpp
@@ -0,0 +1,510 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_SCR14
+
+static unsigned char bitmap_data[]= {
+ 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0xa0,0xa0,0xa0,0xa0,0x50,0x50,0xfc,
+ 0x28,0x28,0x28,0x7e,0x14,0x14,0x20,0x70,
+ 0xa8,0x28,0x30,0x60,0xa0,0xa8,0x70,0x20,
+ 0x98,0x54,0x54,0x2c,0x10,0x68,0x54,0x54,
+ 0x32,0x74,0x88,0x8c,0x90,0x60,0x20,0x50,
+ 0x48,0x30,0x80,0x40,0x20,0x20,0x20,0x40,
+ 0x40,0x80,0x80,0x80,0x80,0x80,0x40,0x40,
+ 0x20,0x80,0x40,0x40,0x20,0x20,0x20,0x20,
+ 0x20,0x40,0x40,0x80,0x20,0xa8,0x70,0x70,
+ 0xa8,0x20,0x20,0x20,0xf8,0x20,0x20,0x80,
+ 0x40,0x40,0xc0,0xf8,0x80,0x80,0x80,0x80,
+ 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,
+ 0x70,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,
+ 0x70,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0xc0,0x40,0xf8,0x80,0x40,0x20,0x10,0x08,
+ 0x88,0x88,0x70,0x70,0x88,0x08,0x08,0x70,
+ 0x08,0x08,0x88,0x70,0x10,0x10,0x10,0xf8,
+ 0x90,0x50,0x50,0x30,0x10,0x70,0x88,0x08,
+ 0x08,0x08,0xf0,0x80,0x80,0xf8,0x70,0x88,
+ 0x88,0x88,0x88,0xf0,0x80,0x88,0x70,0x40,
+ 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0xf8,
+ 0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,
+ 0x70,0x70,0x88,0x08,0x08,0x78,0x88,0x88,
+ 0x88,0x70,0x80,0x80,0x00,0x00,0x80,0x80,
+ 0x80,0x40,0x40,0xc0,0x00,0x00,0x40,0x40,
+ 0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,
+ 0x08,0xf8,0x00,0xf8,0x80,0x40,0x20,0x10,
+ 0x08,0x10,0x20,0x40,0x80,0x20,0x20,0x00,
+ 0x20,0x20,0x10,0x88,0x88,0x70,0x38,0x40,
+ 0x98,0xa8,0xa8,0x98,0x88,0x48,0x30,0x88,
+ 0x88,0xf8,0x88,0x50,0x50,0x50,0x20,0x20,
+ 0xf0,0x88,0x88,0x88,0xf0,0x88,0x88,0x88,
+ 0xf0,0x70,0x88,0x80,0x80,0x80,0x80,0x80,
+ 0x88,0x70,0xf0,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0xf0,0xf8,0x80,0x80,0x80,0xf0,
+ 0x80,0x80,0x80,0xf8,0x80,0x80,0x80,0x80,
+ 0xf0,0x80,0x80,0x80,0xf8,0x68,0x98,0x88,
+ 0x88,0x98,0x80,0x80,0x88,0x70,0x88,0x88,
+ 0x88,0x88,0xf8,0x88,0x88,0x88,0x88,0xe0,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xe0,
+ 0x70,0x88,0x88,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x88,0x88,0x90,0xa0,0xc0,0xa0,0x90,
+ 0x88,0x88,0xf8,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x88,0x88,0x88,0xa8,0xa8,
+ 0xd8,0xd8,0x88,0x88,0x88,0x98,0x98,0xa8,
+ 0xa8,0xc8,0xc8,0x88,0x88,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x70,0x80,0x80,
+ 0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x08,
+ 0x10,0x70,0xa8,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x70,0x88,0x88,0x90,0xa0,0xf0,0x88,
+ 0x88,0x88,0xf0,0x70,0x88,0x08,0x08,0x70,
+ 0x80,0x80,0x88,0x70,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xf8,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x88,0x20,0x20,
+ 0x50,0x50,0x50,0x88,0x88,0x88,0x88,0x50,
+ 0x50,0xf8,0xa8,0xa8,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x50,0x50,0x20,0x50,0x50,0x88,
+ 0x88,0x20,0x20,0x20,0x20,0x20,0x50,0x50,
+ 0x88,0x88,0xf8,0x80,0x40,0x40,0x20,0x10,
+ 0x10,0x08,0xf8,0xf0,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0xf0,0x08,0x08,
+ 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,
+ 0xf0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0xf0,0x88,0x50,0x20,0xfe,0x20,
+ 0x40,0x80,0x80,0x68,0x98,0x88,0x78,0x08,
+ 0x88,0x70,0xb0,0xc8,0x88,0x88,0x88,0xc8,
+ 0xb0,0x80,0x80,0x70,0x88,0x80,0x80,0x80,
+ 0x88,0x70,0x68,0x98,0x88,0x88,0x88,0x98,
+ 0x68,0x08,0x08,0x70,0x88,0x80,0xf8,0x88,
+ 0x88,0x70,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0xf0,0x40,0x38,0x70,0x88,0x08,0x68,0x98,
+ 0x88,0x88,0x88,0x98,0x68,0x88,0x88,0x88,
+ 0x88,0x88,0xc8,0xb0,0x80,0x80,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0x00,0x20,0x60,
+ 0x90,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x70,0x00,0x10,0x88,0x88,0x90,0xe0,0xa0,
+ 0x90,0x88,0x80,0x80,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0xa8,0xa8,0xa8,
+ 0xa8,0xa8,0xa8,0xd0,0x88,0x88,0x88,0x88,
+ 0x88,0xc8,0xb0,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x70,0x80,0x80,0x80,0xb0,0xc8,0x88,
+ 0x88,0x88,0xc8,0xb0,0x08,0x08,0x08,0x68,
+ 0x98,0x88,0x88,0x88,0x98,0x68,0x80,0x80,
+ 0x80,0x80,0x80,0xc8,0xb0,0x70,0x88,0x08,
+ 0x70,0x80,0x88,0x70,0x30,0x40,0x40,0x40,
+ 0x40,0x40,0xf0,0x40,0x40,0x68,0x98,0x88,
+ 0x88,0x88,0x88,0x88,0x20,0x20,0x50,0x50,
+ 0x88,0x88,0x88,0x50,0xa8,0xa8,0xa8,0xa8,
+ 0x88,0x88,0x88,0x88,0x50,0x20,0x50,0x88,
+ 0x88,0x70,0x88,0x08,0x68,0x98,0x88,0x88,
+ 0x88,0x88,0x88,0xf8,0x80,0x40,0x20,0x10,
+ 0x08,0xf8,0x18,0x20,0x20,0x20,0x20,0x20,
+ 0xc0,0x20,0x20,0x20,0x20,0x18,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0xc0,0x20,0x20,0x20,0x20,0x20,
+ 0x18,0x20,0x20,0x20,0x20,0xc0,0x98,0xb4,
+ 0x64,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
+ 0x80,0x80,0x20,0x20,0x70,0x88,0x80,0x80,
+ 0x88,0x70,0x20,0x20,0xb0,0x48,0x40,0x40,
+ 0xf0,0x40,0x40,0x48,0x30,0x88,0x70,0x88,
+ 0x88,0x70,0x88,0x70,0x20,0xf8,0x20,0xf8,
+ 0x50,0x50,0x88,0x88,0x80,0x80,0x80,0x80,
+ 0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,
+ 0x70,0x88,0x10,0x28,0x48,0x88,0x90,0xa0,
+ 0x40,0x88,0x70,0xd8,0x38,0x44,0x92,0xaa,
+ 0xa2,0xaa,0x92,0x44,0x38,0xf8,0x00,0x68,
+ 0x90,0x70,0x10,0x60,0x12,0x24,0x48,0x90,
+ 0x48,0x24,0x12,0x08,0x08,0xf8,0xf0,0x38,
+ 0x44,0xaa,0xaa,0xb2,0xaa,0xb2,0x44,0x38,
+ 0xe0,0x60,0x90,0x90,0x60,0xf8,0x00,0x20,
+ 0x20,0xf8,0x20,0x20,0xe0,0x40,0x20,0xa0,
+ 0x40,0xc0,0x20,0x40,0x20,0xc0,0x80,0x40,
+ 0x80,0x80,0xb4,0xc8,0x88,0x88,0x88,0x88,
+ 0x28,0x28,0x28,0x28,0x28,0x68,0xa8,0xa8,
+ 0xa8,0x7c,0x80,0x80,0xc0,0x20,0x40,0xe0,
+ 0x40,0x40,0xc0,0x40,0xf8,0x00,0x70,0x88,
+ 0x88,0x88,0x70,0x90,0x48,0x24,0x12,0x24,
+ 0x48,0x90,0x04,0x9e,0x54,0x2c,0x14,0xe8,
+ 0x44,0x40,0xc0,0x40,0x1c,0x08,0x84,0x54,
+ 0x28,0x10,0xe8,0x44,0x40,0xc0,0x40,0x04,
+ 0x9e,0x54,0x2c,0xd4,0x28,0x44,0x20,0xc0,
+ 0x70,0x88,0x80,0x40,0x20,0x20,0x00,0x00,
+ 0x20,0x20,0x88,0x88,0xf8,0x88,0x50,0x50,
+ 0x20,0x20,0x00,0x20,0x40,0x88,0x88,0xf8,
+ 0x88,0x50,0x50,0x20,0x20,0x00,0x20,0x10,
+ 0x88,0x88,0xf8,0x88,0x50,0x50,0x20,0x20,
+ 0x00,0x50,0x20,0x88,0x88,0xf8,0x88,0x50,
+ 0x50,0x20,0x20,0x00,0xb0,0x68,0x88,0x88,
+ 0xf8,0x88,0x50,0x50,0x20,0x20,0x00,0xd8,
+ 0x88,0x88,0xf8,0x88,0x50,0x50,0x20,0x20,
+ 0x20,0x50,0x20,0x9c,0x90,0xf0,0x90,0x5c,
+ 0x50,0x30,0x30,0x1c,0x60,0x10,0x20,0x70,
+ 0x88,0x80,0x80,0x80,0x80,0x80,0x88,0x70,
+ 0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0xf8,
+ 0x00,0x20,0x40,0xf8,0x80,0x80,0x80,0xf0,
+ 0x80,0x80,0xf8,0x00,0x20,0x10,0xf8,0x80,
+ 0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0x50,
+ 0x20,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,
+ 0xf8,0x00,0xd8,0xe0,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0xe0,0x00,0x40,0x80,0xe0,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0xe0,0x00,0x40,
+ 0x20,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0xe0,0x00,0xa0,0x40,0x70,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x70,0x00,0xd8,0x78,0x44,
+ 0x44,0x44,0xf4,0x44,0x44,0x44,0x78,0x88,
+ 0x98,0x98,0xa8,0xa8,0xc8,0xc8,0x88,0x00,
+ 0xb0,0x68,0x70,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x10,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,
+ 0x00,0x50,0x20,0x70,0x88,0x88,0x88,0x88,
+ 0x88,0x88,0x70,0x00,0xb0,0x68,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x70,0x00,0xd8,
+ 0x88,0x50,0x20,0x50,0x88,0xb8,0x44,0x64,
+ 0x64,0x54,0x4c,0x4c,0x44,0x3a,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x88,0x88,0x00,0x20,
+ 0x40,0x70,0x88,0x88,0x88,0x88,0x88,0x88,
+ 0x88,0x00,0x20,0x10,0x70,0x88,0x88,0x88,
+ 0x88,0x88,0x88,0x88,0x00,0x50,0x20,0x70,
+ 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x00,
+ 0xd8,0x20,0x20,0x20,0x20,0x50,0x50,0x88,
+ 0x88,0x00,0x20,0x10,0xe0,0x40,0x78,0x44,
+ 0x44,0x44,0x78,0x40,0xe0,0xb0,0x88,0x88,
+ 0x88,0x90,0xa0,0x90,0x90,0x60,0x68,0x98,
+ 0x88,0x78,0x08,0x88,0x70,0x00,0x20,0x40,
+ 0x68,0x98,0x88,0x78,0x08,0x88,0x70,0x00,
+ 0x20,0x10,0x68,0x98,0x88,0x78,0x08,0x88,
+ 0x70,0x00,0x50,0x20,0x68,0x98,0x88,0x78,
+ 0x08,0x88,0x70,0x00,0xb0,0x68,0x68,0x98,
+ 0x88,0x78,0x08,0x88,0x70,0x00,0xd8,0x68,
+ 0x98,0x88,0x78,0x08,0x88,0x70,0x00,0x20,
+ 0x50,0x20,0x6c,0x92,0x90,0x7e,0x12,0x92,
+ 0x6c,0x60,0x10,0x20,0x70,0x88,0x80,0x80,
+ 0x80,0x88,0x70,0x70,0x88,0x80,0xf8,0x88,
+ 0x88,0x70,0x00,0x20,0x40,0x70,0x88,0x80,
+ 0xf8,0x88,0x88,0x70,0x00,0x20,0x10,0x70,
+ 0x88,0x80,0xf8,0x88,0x88,0x70,0x00,0x50,
+ 0x20,0x70,0x88,0x80,0xf8,0x88,0x88,0x70,
+ 0x00,0xd8,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0xe0,0x00,0x20,0x40,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0xe0,0x00,0x20,0x10,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0x00,0xa0,0x40,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00,
+ 0xd8,0x70,0x88,0x88,0x88,0x88,0x88,0x78,
+ 0x10,0xd0,0x20,0xd0,0x88,0x88,0x88,0x88,
+ 0x88,0xc8,0xb0,0x00,0xb0,0x68,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x40,
+ 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,
+ 0x20,0x10,0x70,0x88,0x88,0x88,0x88,0x88,
+ 0x70,0x00,0x50,0x20,0x70,0x88,0x88,0x88,
+ 0x88,0x88,0x70,0x00,0xb0,0x68,0x70,0x88,
+ 0x88,0x88,0x88,0x88,0x70,0x00,0xd8,0x10,
+ 0x10,0x00,0xfe,0x00,0x10,0x10,0xb8,0x44,
+ 0x64,0x54,0x4c,0x44,0x3a,0x68,0x98,0x88,
+ 0x88,0x88,0x88,0x88,0x00,0x20,0x40,0x68,
+ 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0x20,
+ 0x10,0x68,0x98,0x88,0x88,0x88,0x88,0x88,
+ 0x00,0x50,0x20,0x68,0x98,0x88,0x88,0x88,
+ 0x88,0x88,0x00,0xd8,0x70,0x88,0x08,0x68,
+ 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0x20,
+ 0x10,0xe0,0x40,0x58,0x64,0x44,0x44,0x44,
+ 0x64,0x58,0x40,0xc0,0x70,0x88,0x08,0x68,
+ 0x98,0x88,0x88,0x88,0x88,0x88,0x00,0xd8,
+};
+
+BMF_FontData BMF_font_scr14 = {
+ 0, -3,
+ 7, 11,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 16, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 7, -1},
+ {1, 9, -3, 0, 7, 0},
+ {3, 4, -2, -5, 7, 9},
+ {7, 9, 0, 0, 7, 13},
+ {5, 10, -1, 1, 7, 22},
+ {7, 9, 0, 0, 7, 32},
+ {6, 9, 0, 0, 7, 41},
+ {3, 4, -2, -5, 7, 50},
+ {3, 11, -2, 1, 7, 54},
+ {3, 11, -2, 1, 7, 65},
+ {5, 6, -1, -2, 7, 76},
+ {5, 5, -1, -2, 7, 82},
+ {2, 4, -2, 2, 7, 87},
+ {5, 1, -1, -4, 7, 91},
+ {1, 2, -3, 0, 7, 92},
+ {5, 10, -1, 0, 7, 94},
+ {5, 9, -1, 0, 7, 104},
+ {3, 9, -2, 0, 7, 113},
+ {5, 9, -1, 0, 7, 122},
+ {5, 9, -1, 0, 7, 131},
+ {5, 9, -1, 0, 7, 140},
+ {5, 9, -1, 0, 7, 149},
+ {5, 9, -1, 0, 7, 158},
+ {5, 9, -1, 0, 7, 167},
+ {5, 9, -1, 0, 7, 176},
+ {5, 9, -1, 0, 7, 185},
+ {1, 6, -3, 0, 7, 194},
+ {2, 8, -2, 1, 7, 200},
+ {5, 9, -1, 0, 7, 208},
+ {5, 3, -1, -3, 7, 217},
+ {5, 9, -1, 0, 7, 220},
+ {5, 9, -1, 0, 7, 229},
+ {5, 9, -1, 0, 7, 238},
+ {5, 9, -1, 0, 7, 247},
+ {5, 9, -1, 0, 7, 256},
+ {5, 9, -1, 0, 7, 265},
+ {5, 9, -1, 0, 7, 274},
+ {5, 9, -1, 0, 7, 283},
+ {5, 9, -1, 0, 7, 292},
+ {5, 9, -1, 0, 7, 301},
+ {5, 9, -1, 0, 7, 310},
+ {3, 9, -2, 0, 7, 319},
+ {5, 9, -1, 0, 7, 328},
+ {5, 9, -1, 0, 7, 337},
+ {5, 9, -1, 0, 7, 346},
+ {5, 9, -1, 0, 7, 355},
+ {5, 9, -1, 0, 7, 364},
+ {5, 9, -1, 0, 7, 373},
+ {5, 9, -1, 0, 7, 382},
+ {5, 11, -1, 2, 7, 391},
+ {5, 9, -1, 0, 7, 402},
+ {5, 9, -1, 0, 7, 411},
+ {5, 9, -1, 0, 7, 420},
+ {5, 9, -1, 0, 7, 429},
+ {5, 9, -1, 0, 7, 438},
+ {5, 9, -1, 0, 7, 447},
+ {5, 9, -1, 0, 7, 456},
+ {5, 9, -1, 0, 7, 465},
+ {5, 9, -1, 0, 7, 474},
+ {4, 11, -2, 1, 7, 483},
+ {5, 10, -1, 0, 7, 494},
+ {4, 11, -1, 1, 7, 504},
+ {5, 3, -1, -6, 7, 515},
+ {7, 1, 0, 2, 7, 518},
+ {3, 4, -2, -5, 7, 519},
+ {5, 7, -1, 0, 7, 523},
+ {5, 9, -1, 0, 7, 530},
+ {5, 7, -1, 0, 7, 539},
+ {5, 9, -1, 0, 7, 546},
+ {5, 7, -1, 0, 7, 555},
+ {5, 9, -1, 0, 7, 562},
+ {5, 10, -1, 3, 7, 571},
+ {5, 9, -1, 0, 7, 581},
+ {3, 9, -2, 0, 7, 590},
+ {4, 12, -1, 3, 7, 599},
+ {5, 9, -1, 0, 7, 611},
+ {3, 9, -2, 0, 7, 620},
+ {5, 7, -1, 0, 7, 629},
+ {5, 7, -1, 0, 7, 636},
+ {5, 7, -1, 0, 7, 643},
+ {5, 10, -1, 3, 7, 650},
+ {5, 10, -1, 3, 7, 660},
+ {5, 7, -1, 0, 7, 670},
+ {5, 7, -1, 0, 7, 677},
+ {4, 9, -1, 0, 7, 684},
+ {5, 7, -1, 0, 7, 693},
+ {5, 7, -1, 0, 7, 700},
+ {5, 7, -1, 0, 7, 707},
+ {5, 7, -1, 0, 7, 714},
+ {5, 10, -1, 3, 7, 721},
+ {5, 7, -1, 0, 7, 731},
+ {5, 12, -1, 2, 7, 738},
+ {1, 12, -3, 2, 7, 750},
+ {5, 12, -1, 2, 7, 762},
+ {6, 3, 0, -3, 7, 774},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 9, -3, 2, 7, 777},
+ {5, 10, -1, 0, 7, 786},
+ {5, 9, -1, 0, 7, 796},
+ {5, 6, -1, -3, 7, 805},
+ {5, 9, -1, 0, 7, 811},
+ {1, 12, -3, 2, 7, 820},
+ {5, 11, -1, 2, 7, 832},
+ {5, 1, -1, -8, 7, 843},
+ {7, 9, 0, 0, 7, 844},
+ {5, 7, -1, -2, 7, 853},
+ {7, 7, 0, 0, 7, 860},
+ {5, 3, -1, -3, 7, 867},
+ {4, 1, -1, -4, 7, 870},
+ {7, 9, 0, 0, 7, 871},
+ {3, 1, -2, -8, 7, 880},
+ {4, 4, -1, -4, 7, 881},
+ {5, 7, -1, 0, 7, 885},
+ {3, 5, -2, -5, 7, 892},
+ {3, 5, -2, -5, 7, 897},
+ {2, 2, -3, -8, 7, 902},
+ {6, 8, -1, 2, 7, 904},
+ {6, 10, 0, 1, 7, 912},
+ {1, 2, -3, -3, 7, 922},
+ {3, 3, -2, 3, 7, 924},
+ {3, 5, -2, -5, 7, 927},
+ {5, 7, -1, -2, 7, 932},
+ {7, 7, 0, 0, 7, 939},
+ {7, 10, 0, 0, 7, 946},
+ {6, 11, 0, 1, 7, 956},
+ {7, 9, 0, -1, 7, 967},
+ {5, 10, -1, 3, 7, 976},
+ {5, 11, -1, 0, 7, 986},
+ {5, 11, -1, 0, 7, 997},
+ {5, 11, -1, 0, 7, 1008},
+ {5, 11, -1, 0, 7, 1019},
+ {5, 10, -1, 0, 7, 1030},
+ {5, 11, -1, 0, 7, 1040},
+ {6, 9, 0, 0, 7, 1051},
+ {5, 12, -1, 3, 7, 1060},
+ {5, 11, -1, 0, 7, 1072},
+ {5, 11, -1, 0, 7, 1083},
+ {5, 11, -1, 0, 7, 1094},
+ {5, 10, -1, 0, 7, 1105},
+ {3, 11, -2, 0, 7, 1115},
+ {3, 11, -2, 0, 7, 1126},
+ {3, 11, -2, 0, 7, 1137},
+ {5, 10, -1, 0, 7, 1148},
+ {6, 9, 0, 0, 7, 1158},
+ {5, 11, -1, 0, 7, 1167},
+ {5, 11, -1, 0, 7, 1178},
+ {5, 11, -1, 0, 7, 1189},
+ {5, 11, -1, 0, 7, 1200},
+ {5, 11, -1, 0, 7, 1211},
+ {5, 10, -1, 0, 7, 1222},
+ {5, 5, -1, -1, 7, 1232},
+ {7, 9, 0, 0, 7, 1237},
+ {5, 11, -1, 0, 7, 1246},
+ {5, 11, -1, 0, 7, 1257},
+ {5, 11, -1, 0, 7, 1268},
+ {5, 10, -1, 0, 7, 1279},
+ {5, 11, -1, 0, 7, 1289},
+ {6, 9, 0, 0, 7, 1300},
+ {5, 9, -1, 0, 7, 1309},
+ {5, 10, -1, 0, 7, 1318},
+ {5, 10, -1, 0, 7, 1328},
+ {5, 10, -1, 0, 7, 1338},
+ {5, 10, -1, 0, 7, 1348},
+ {5, 9, -1, 0, 7, 1358},
+ {5, 11, -1, 0, 7, 1367},
+ {7, 7, 0, 0, 7, 1378},
+ {5, 10, -1, 3, 7, 1385},
+ {5, 10, -1, 0, 7, 1395},
+ {5, 10, -1, 0, 7, 1405},
+ {5, 10, -1, 0, 7, 1415},
+ {5, 9, -1, 0, 7, 1425},
+ {3, 10, -2, 0, 7, 1434},
+ {4, 10, -2, 0, 7, 1444},
+ {3, 10, -2, 0, 7, 1454},
+ {5, 9, -2, 0, 7, 1464},
+ {5, 11, -1, 0, 7, 1473},
+ {5, 10, -1, 0, 7, 1484},
+ {5, 10, -1, 0, 7, 1494},
+ {5, 10, -1, 0, 7, 1504},
+ {5, 10, -1, 0, 7, 1514},
+ {5, 10, -1, 0, 7, 1524},
+ {5, 9, -1, 0, 7, 1534},
+ {7, 7, 0, 0, 7, 1543},
+ {7, 7, 0, 0, 7, 1550},
+ {5, 10, -1, 0, 7, 1557},
+ {5, 10, -1, 0, 7, 1567},
+ {5, 10, -1, 0, 7, 1577},
+ {5, 9, -1, 0, 7, 1587},
+ {5, 13, -1, 3, 7, 1596},
+ {6, 11, 0, 2, 7, 1609},
+ {5, 12, -1, 3, 7, 1620},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/BMF_font_scr15.cpp b/intern/bmfont/intern/BMF_font_scr15.cpp
new file mode 100644
index 00000000000..708420410c6
--- /dev/null
+++ b/intern/bmfont/intern/BMF_font_scr15.cpp
@@ -0,0 +1,525 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BMF_FontData.h"
+
+#include "BMF_Settings.h"
+
+#if BMF_INCLUDE_SCR15
+
+static unsigned char bitmap_data[]= {
+ 0x80,0x80,0x00,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x90,0x90,0x90,0x90,0x48,0x48,
+ 0x48,0xfe,0x24,0x24,0x24,0x7f,0x12,0x12,
+ 0x20,0x70,0xa8,0xa8,0x28,0x30,0x60,0xa0,
+ 0xa8,0xa8,0x70,0x20,0x8c,0x52,0x52,0x2c,
+ 0x10,0x10,0x68,0x94,0x94,0x62,0x72,0x8c,
+ 0x84,0x8a,0x50,0x20,0x30,0x48,0x48,0x30,
+ 0x80,0x40,0x60,0x60,0x10,0x20,0x40,0x40,
+ 0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x20,
+ 0x10,0x80,0x40,0x20,0x20,0x10,0x10,0x10,
+ 0x10,0x10,0x20,0x20,0x40,0x80,0x20,0xa8,
+ 0x70,0x70,0xa8,0x20,0x10,0x10,0x10,0xfe,
+ 0x10,0x10,0x10,0x80,0x40,0x20,0x60,0x60,
+ 0xfc,0xc0,0xc0,0x80,0x80,0x40,0x40,0x20,
+ 0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x78,
+ 0x84,0x84,0xc4,0xa4,0x94,0x8c,0x84,0x84,
+ 0x78,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0xc0,0x40,0xfc,0x80,0x40,0x20,0x10,
+ 0x08,0x04,0x84,0x84,0x78,0x78,0x84,0x04,
+ 0x04,0x04,0x38,0x04,0x04,0x84,0x78,0x08,
+ 0x08,0x08,0xfc,0x88,0x48,0x48,0x28,0x18,
+ 0x08,0x78,0x84,0x04,0x04,0x04,0xf8,0x80,
+ 0x80,0x80,0xfc,0x78,0x84,0x84,0x84,0x84,
+ 0xf8,0x80,0x80,0x84,0x78,0x20,0x20,0x20,
+ 0x10,0x10,0x08,0x08,0x04,0x04,0xfc,0x78,
+ 0x84,0x84,0x84,0x84,0x78,0x84,0x84,0x84,
+ 0x78,0x78,0x84,0x04,0x04,0x7c,0x84,0x84,
+ 0x84,0x84,0x78,0xc0,0xc0,0x00,0x00,0x00,
+ 0xc0,0xc0,0x80,0x40,0xc0,0xc0,0x00,0x00,
+ 0x00,0xc0,0xc0,0x04,0x08,0x10,0x20,0x40,
+ 0x80,0x40,0x20,0x10,0x08,0x04,0xfc,0x00,
+ 0x00,0xfc,0x80,0x40,0x20,0x10,0x08,0x04,
+ 0x08,0x10,0x20,0x40,0x80,0x10,0x10,0x00,
+ 0x10,0x10,0x08,0x04,0x84,0x84,0x78,0x38,
+ 0x44,0x80,0x98,0xa4,0xa4,0x9c,0x84,0x48,
+ 0x30,0x84,0x84,0xfc,0x84,0x48,0x48,0x48,
+ 0x30,0x30,0x30,0xf8,0x84,0x84,0x84,0x84,
+ 0xf8,0x84,0x84,0x84,0xf8,0x78,0x84,0x84,
+ 0x80,0x80,0x80,0x80,0x84,0x84,0x78,0xf0,
+ 0x88,0x84,0x84,0x84,0x84,0x84,0x84,0x88,
+ 0xf0,0xfc,0x80,0x80,0x80,0x80,0xf8,0x80,
+ 0x80,0x80,0xfc,0x80,0x80,0x80,0x80,0x80,
+ 0xf8,0x80,0x80,0x80,0xfc,0x74,0x8c,0x84,
+ 0x84,0x84,0x9c,0x80,0x80,0x84,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0xfc,0x84,0x84,0x84,
+ 0x84,0xe0,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0xe0,0x70,0x88,0x88,0x08,0x08,
+ 0x08,0x08,0x08,0x08,0x08,0x84,0x84,0x88,
+ 0x90,0xa0,0xc0,0xa0,0x90,0x88,0x84,0xfc,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x82,0x82,0x92,0x92,0xaa,0xaa,0xc6,
+ 0xc6,0x82,0x82,0x84,0x8c,0x8c,0x94,0x94,
+ 0xa4,0xa4,0xc4,0xc4,0x84,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x78,0x80,
+ 0x80,0x80,0x80,0xf8,0x84,0x84,0x84,0x84,
+ 0xf8,0x04,0x08,0x10,0x78,0xa4,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x78,0x84,0x84,
+ 0x88,0x90,0xf8,0x84,0x84,0x84,0x84,0xf8,
+ 0x78,0x84,0x84,0x04,0x18,0x60,0x80,0x84,
+ 0x84,0x78,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0xfe,0x78,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x30,0x30,
+ 0x30,0x48,0x48,0x48,0x84,0x84,0x84,0x84,
+ 0x44,0x44,0x44,0xaa,0xaa,0xaa,0x92,0x92,
+ 0x92,0x82,0x84,0x84,0x48,0x48,0x30,0x30,
+ 0x48,0x48,0x84,0x84,0x10,0x10,0x10,0x10,
+ 0x10,0x28,0x44,0x44,0x82,0x82,0xfc,0x80,
+ 0x40,0x40,0x20,0x10,0x08,0x08,0x04,0xfc,
+ 0xf0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0xf0,0x04,0x04,0x08,
+ 0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,
+ 0x80,0xf0,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x10,0x10,0x10,0xf0,0x88,0x50,
+ 0x20,0xff,0x20,0x40,0xc0,0xc0,0x74,0x88,
+ 0x88,0x78,0x08,0x88,0x70,0xb8,0xc4,0x84,
+ 0x84,0x84,0xc4,0xb8,0x80,0x80,0x80,0x78,
+ 0x84,0x80,0x80,0x80,0x84,0x78,0x74,0x8c,
+ 0x84,0x84,0x84,0x8c,0x74,0x04,0x04,0x04,
+ 0x78,0x84,0x80,0xfc,0x84,0x84,0x78,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0xf8,0x20,0x20,
+ 0x1c,0x78,0x84,0x04,0x04,0x74,0x8c,0x84,
+ 0x84,0x84,0x8c,0x74,0x84,0x84,0x84,0x84,
+ 0x84,0xc4,0xb8,0x80,0x80,0x80,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0x00,0x20,0x20,
+ 0x70,0x88,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x08,0x08,0x38,0x00,0x08,0x08,0x84,0x88,
+ 0x90,0xe0,0xa0,0x90,0x88,0x80,0x80,0x80,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0xe0,0x92,0x92,0x92,0x92,0x92,0x92,
+ 0xec,0x84,0x84,0x84,0x84,0x84,0xc4,0xb8,
+ 0x78,0x84,0x84,0x84,0x84,0x84,0x78,0x80,
+ 0x80,0x80,0x80,0xb8,0xc4,0x84,0x84,0x84,
+ 0xc4,0xb8,0x04,0x04,0x04,0x04,0x74,0x8c,
+ 0x84,0x84,0x84,0x8c,0x74,0x80,0x80,0x80,
+ 0x80,0x80,0xc4,0xb8,0x78,0x84,0x04,0x78,
+ 0x80,0x84,0x78,0x1c,0x20,0x20,0x20,0x20,
+ 0x20,0xf8,0x20,0x20,0x74,0x8c,0x84,0x84,
+ 0x84,0x84,0x84,0x30,0x30,0x48,0x48,0x84,
+ 0x84,0x84,0x6c,0x92,0x92,0x92,0x92,0x82,
+ 0x82,0x84,0x84,0x48,0x30,0x48,0x84,0x84,
+ 0x78,0x84,0x04,0x04,0x74,0x8c,0x84,0x84,
+ 0x84,0x84,0x84,0xfc,0x80,0x40,0x20,0x10,
+ 0x08,0xfc,0x1c,0x20,0x20,0x20,0x20,0x20,
+ 0xc0,0x20,0x20,0x20,0x20,0x20,0x1c,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0xe0,0x10,0x10,
+ 0x10,0x10,0x10,0x0c,0x10,0x10,0x10,0x10,
+ 0x10,0xe0,0x98,0xb4,0x64,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x00,0x80,0x80,0x20,
+ 0x20,0x70,0x88,0x80,0x80,0x88,0x70,0x20,
+ 0x20,0xb8,0x44,0x40,0x40,0xf0,0x40,0x40,
+ 0x40,0x48,0x30,0x84,0x78,0x84,0x84,0x84,
+ 0x78,0x84,0x38,0x10,0x7c,0x10,0x7c,0x28,
+ 0x44,0x44,0x82,0x82,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x78,0x84,0x04,0x18,0x24,0x44,
+ 0x84,0x88,0x90,0x60,0x80,0x84,0x78,0xd8,
+ 0x38,0x44,0x92,0xaa,0xa2,0xaa,0x92,0x44,
+ 0x38,0xf8,0x00,0x68,0x90,0x70,0x10,0x60,
+ 0x09,0x12,0x24,0x48,0x90,0x48,0x24,0x12,
+ 0x09,0x04,0x04,0xfc,0xfc,0x38,0x44,0xaa,
+ 0xaa,0xb2,0xaa,0xb2,0x44,0x38,0xf0,0x60,
+ 0x90,0x90,0x60,0xfe,0x00,0x10,0x10,0x10,
+ 0xfe,0x10,0x10,0x10,0xf0,0x40,0x20,0x90,
+ 0x60,0xe0,0x10,0x60,0x10,0xe0,0x80,0x40,
+ 0x80,0x80,0x80,0xb4,0xc8,0x88,0x88,0x88,
+ 0x88,0x88,0x24,0x24,0x24,0x24,0x24,0x24,
+ 0x64,0xa4,0xa4,0xa4,0xa4,0x7e,0xc0,0xc0,
+ 0x20,0x40,0xe0,0x40,0x40,0xc0,0x40,0xf8,
+ 0x00,0x70,0x88,0x88,0x88,0x70,0x90,0x48,
+ 0x24,0x12,0x09,0x12,0x24,0x48,0x90,0x04,
+ 0x9e,0x54,0x2c,0x14,0xe8,0x44,0x42,0xc0,
+ 0x40,0x1e,0x08,0x84,0x52,0x2c,0x10,0xe8,
+ 0x44,0x42,0xc0,0x40,0x04,0x9e,0x54,0x2c,
+ 0xd4,0x28,0x44,0x22,0xc0,0x78,0x84,0x84,
+ 0x80,0x40,0x20,0x20,0x00,0x20,0x20,0x84,
+ 0x84,0xfc,0x84,0x48,0x48,0x30,0x30,0x00,
+ 0x20,0x40,0x84,0x84,0xfc,0x84,0x48,0x48,
+ 0x30,0x30,0x00,0x10,0x08,0x84,0x84,0xfc,
+ 0x84,0x48,0x48,0x30,0x30,0x00,0x48,0x30,
+ 0x84,0x84,0xfc,0x84,0x48,0x48,0x30,0x30,
+ 0x00,0x98,0x64,0x84,0x84,0xfc,0x84,0x48,
+ 0x48,0x30,0x30,0x00,0x6c,0x84,0x84,0xfc,
+ 0x84,0x48,0x48,0x30,0x30,0x30,0x48,0x30,
+ 0x9e,0x90,0x90,0xf0,0x90,0x5c,0x50,0x50,
+ 0x30,0x1e,0x30,0x08,0x10,0x78,0x84,0x84,
+ 0x80,0x80,0x80,0x80,0x84,0x84,0x78,0xfc,
+ 0x80,0x80,0x80,0xf8,0x80,0x80,0xfc,0x00,
+ 0x20,0x40,0xfc,0x80,0x80,0x80,0xf8,0x80,
+ 0x80,0xfc,0x00,0x10,0x08,0xfc,0x80,0x80,
+ 0x80,0xf8,0x80,0x80,0xfc,0x00,0x48,0x30,
+ 0xfc,0x80,0x80,0x80,0xf8,0x80,0x80,0xfc,
+ 0x00,0x6c,0xe0,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0xe0,0x00,0x40,0x80,0xe0,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0xe0,0x00,0x40,0x20,
+ 0xe0,0x40,0x40,0x40,0x40,0x40,0x40,0xe0,
+ 0x00,0x90,0x60,0x70,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x70,0x00,0xd8,0x78,0x44,0x42,
+ 0x42,0x42,0xf2,0x42,0x42,0x44,0x78,0x84,
+ 0x8c,0x94,0x94,0xa4,0xa4,0xc4,0x84,0x00,
+ 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x78,0x00,0x20,0x40,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x78,0x00,0x10,0x08,
+ 0x78,0x84,0x84,0x84,0x84,0x84,0x84,0x78,
+ 0x00,0x48,0x30,0x78,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x78,0x00,0x98,0x64,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x78,0x00,0x6c,
+ 0x84,0x48,0x30,0x30,0x48,0x84,0xbc,0x42,
+ 0x62,0x52,0x52,0x4a,0x4a,0x46,0x42,0x3d,
+ 0x78,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x00,0x20,0x40,0x78,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x00,0x10,0x08,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x48,
+ 0x30,0x78,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x00,0x6c,0x10,0x10,0x10,0x10,0x28,
+ 0x44,0x44,0x82,0x00,0x10,0x08,0xe0,0x40,
+ 0x7c,0x42,0x42,0x42,0x42,0x7c,0x40,0xe0,
+ 0x98,0xa4,0x84,0x84,0x84,0x88,0xb0,0x88,
+ 0x88,0x70,0x74,0x88,0x88,0x78,0x08,0x88,
+ 0x70,0x00,0x20,0x40,0x74,0x88,0x88,0x78,
+ 0x08,0x88,0x70,0x00,0x20,0x10,0x74,0x88,
+ 0x88,0x78,0x08,0x88,0x70,0x00,0x48,0x30,
+ 0x74,0x88,0x88,0x78,0x08,0x88,0x70,0x00,
+ 0x98,0x64,0x74,0x88,0x88,0x78,0x08,0x88,
+ 0x70,0x00,0xd8,0x74,0x88,0x88,0x78,0x08,
+ 0x88,0x70,0x00,0x30,0x48,0x30,0x6c,0x92,
+ 0x90,0x7e,0x12,0x92,0x6c,0x30,0x08,0x10,
+ 0x78,0x84,0x80,0x80,0x80,0x84,0x78,0x78,
+ 0x84,0x80,0xfc,0x84,0x84,0x78,0x00,0x20,
+ 0x40,0x78,0x84,0x80,0xfc,0x84,0x84,0x78,
+ 0x00,0x10,0x08,0x78,0x84,0x80,0xfc,0x84,
+ 0x84,0x78,0x00,0x48,0x30,0x78,0x84,0x80,
+ 0xfc,0x84,0x84,0x78,0x00,0x6c,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0xe0,0x00,0x40,0x80,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00,
+ 0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0xe0,0x00,0x90,0x60,0x10,0x10,0x10,0x10,
+ 0x10,0x10,0x70,0x00,0xd8,0x78,0x84,0x84,
+ 0x84,0x84,0x84,0x7c,0x04,0xc8,0x30,0xc8,
+ 0x84,0x84,0x84,0x84,0x84,0xc4,0xb8,0x00,
+ 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84,
+ 0x78,0x00,0x20,0x40,0x78,0x84,0x84,0x84,
+ 0x84,0x84,0x78,0x00,0x10,0x08,0x78,0x84,
+ 0x84,0x84,0x84,0x84,0x78,0x00,0x48,0x30,
+ 0x78,0x84,0x84,0x84,0x84,0x84,0x78,0x00,
+ 0x98,0x64,0x78,0x84,0x84,0x84,0x84,0x84,
+ 0x78,0x00,0x00,0x6c,0x30,0x00,0x00,0xfc,
+ 0x00,0x00,0x30,0xbc,0x62,0x52,0x4a,0x46,
+ 0x42,0x3d,0x74,0x8c,0x84,0x84,0x84,0x84,
+ 0x84,0x00,0x20,0x40,0x74,0x8c,0x84,0x84,
+ 0x84,0x84,0x84,0x00,0x20,0x10,0x74,0x8c,
+ 0x84,0x84,0x84,0x84,0x84,0x00,0x48,0x30,
+ 0x74,0x8c,0x84,0x84,0x84,0x84,0x84,0x00,
+ 0x00,0x6c,0x78,0x84,0x04,0x04,0x74,0x8c,
+ 0x84,0x84,0x84,0x84,0x84,0x00,0x20,0x10,
+ 0xe0,0x40,0x40,0x5c,0x62,0x42,0x42,0x42,
+ 0x62,0x5c,0x40,0x40,0xc0,0x78,0x84,0x04,
+ 0x04,0x74,0x8c,0x84,0x84,0x84,0x84,0x84,
+ 0x00,0x00,0x6c,
+};
+
+BMF_FontData BMF_font_scr15 = {
+ 0, -4,
+ 8, 11,
+ {
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0, 0, 0, 0, 8, -1},
+ {1, 10, -3, 0, 8, 0},
+ {4, 4, -2, -6, 8, 10},
+ {8, 10, 0, 0, 8, 14},
+ {5, 12, -1, 1, 8, 24},
+ {7, 10, 0, 0, 8, 36},
+ {7, 10, 0, 0, 8, 46},
+ {3, 4, -2, -6, 8, 56},
+ {4, 13, -2, 2, 8, 60},
+ {4, 13, -2, 2, 8, 73},
+ {5, 6, -1, -2, 8, 86},
+ {7, 7, 0, -1, 8, 92},
+ {3, 5, -2, 3, 8, 99},
+ {6, 1, -1, -4, 8, 104},
+ {2, 2, -3, 0, 8, 105},
+ {6, 12, -1, 1, 8, 107},
+ {6, 10, -1, 0, 8, 119},
+ {3, 10, -3, 0, 8, 129},
+ {6, 10, -1, 0, 8, 139},
+ {6, 10, -1, 0, 8, 149},
+ {6, 10, -1, 0, 8, 159},
+ {6, 10, -1, 0, 8, 169},
+ {6, 10, -1, 0, 8, 179},
+ {6, 10, -1, 0, 8, 189},
+ {6, 10, -1, 0, 8, 199},
+ {6, 10, -1, 0, 8, 209},
+ {2, 7, -3, 0, 8, 219},
+ {2, 9, -3, 2, 8, 226},
+ {6, 11, -1, 1, 8, 235},
+ {6, 4, -1, -3, 8, 246},
+ {6, 11, -1, 1, 8, 250},
+ {6, 10, -1, 0, 8, 261},
+ {6, 10, -1, 0, 8, 271},
+ {6, 10, -1, 0, 8, 281},
+ {6, 10, -1, 0, 8, 291},
+ {6, 10, -1, 0, 8, 301},
+ {6, 10, -1, 0, 8, 311},
+ {6, 10, -1, 0, 8, 321},
+ {6, 10, -1, 0, 8, 331},
+ {6, 10, -1, 0, 8, 341},
+ {6, 10, -1, 0, 8, 351},
+ {3, 10, -2, 0, 8, 361},
+ {5, 10, -1, 0, 8, 371},
+ {6, 10, -1, 0, 8, 381},
+ {6, 10, -1, 0, 8, 391},
+ {7, 10, 0, 0, 8, 401},
+ {6, 10, -1, 0, 8, 411},
+ {6, 10, -1, 0, 8, 421},
+ {6, 10, -1, 0, 8, 431},
+ {6, 13, -1, 3, 8, 441},
+ {6, 10, -1, 0, 8, 454},
+ {6, 10, -1, 0, 8, 464},
+ {7, 10, 0, 0, 8, 474},
+ {6, 10, -1, 0, 8, 484},
+ {6, 10, -1, 0, 8, 494},
+ {7, 10, 0, 0, 8, 504},
+ {6, 10, -1, 0, 8, 514},
+ {7, 10, 0, 0, 8, 524},
+ {6, 10, -1, 0, 8, 534},
+ {4, 13, -2, 2, 8, 544},
+ {6, 12, -1, 1, 8, 557},
+ {4, 13, -2, 2, 8, 569},
+ {5, 3, -1, -6, 8, 582},
+ {8, 1, 0, 3, 8, 585},
+ {3, 4, -2, -6, 8, 586},
+ {6, 7, -1, 0, 8, 590},
+ {6, 10, -1, 0, 8, 597},
+ {6, 7, -1, 0, 8, 607},
+ {6, 10, -1, 0, 8, 614},
+ {6, 7, -1, 0, 8, 624},
+ {6, 10, -1, 0, 8, 631},
+ {6, 11, -1, 4, 8, 641},
+ {6, 10, -1, 0, 8, 652},
+ {3, 10, -2, 0, 8, 662},
+ {5, 14, -1, 4, 8, 672},
+ {6, 10, -1, 0, 8, 686},
+ {3, 10, -2, 0, 8, 696},
+ {7, 7, 0, 0, 8, 706},
+ {6, 7, -1, 0, 8, 713},
+ {6, 7, -1, 0, 8, 720},
+ {6, 11, -1, 4, 8, 727},
+ {6, 11, -1, 4, 8, 738},
+ {6, 7, -1, 0, 8, 749},
+ {6, 7, -1, 0, 8, 756},
+ {6, 9, -1, 0, 8, 763},
+ {6, 7, -1, 0, 8, 772},
+ {6, 7, -1, 0, 8, 779},
+ {7, 7, 0, 0, 8, 786},
+ {6, 7, -1, 0, 8, 793},
+ {6, 11, -1, 4, 8, 800},
+ {6, 7, -1, 0, 8, 811},
+ {6, 13, -1, 2, 8, 818},
+ {1, 14, -3, 3, 8, 831},
+ {6, 13, -1, 2, 8, 845},
+ {6, 3, -1, -3, 8, 858},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {0,0,0,0,0, -1},
+ {1, 10, -3, 3, 8, 861},
+ {5, 10, -1, 0, 8, 871},
+ {6, 10, -1, 0, 8, 881},
+ {6, 7, -1, -2, 8, 891},
+ {7, 10, 0, 0, 8, 898},
+ {1, 14, -3, 3, 8, 908},
+ {6, 13, -1, 3, 8, 922},
+ {5, 1, -1, -9, 8, 935},
+ {7, 9, 0, 0, 8, 936},
+ {5, 7, -1, -3, 8, 945},
+ {8, 9, 0, 0, 8, 952},
+ {6, 3, -1, -3, 8, 961},
+ {6, 1, -1, -4, 8, 964},
+ {7, 9, 0, 0, 8, 965},
+ {4, 1, -2, -9, 8, 974},
+ {4, 4, -2, -4, 8, 975},
+ {7, 9, 0, 0, 8, 979},
+ {4, 5, -2, -5, 8, 988},
+ {4, 5, -2, -5, 8, 993},
+ {2, 2, -3, -9, 8, 998},
+ {6, 10, -1, 3, 8, 1000},
+ {7, 12, 0, 2, 8, 1010},
+ {2, 1, -3, -4, 8, 1022},
+ {3, 3, -3, 3, 8, 1023},
+ {3, 5, -3, -5, 8, 1026},
+ {5, 7, -1, -3, 8, 1031},
+ {8, 9, 0, 0, 8, 1038},
+ {7, 10, 0, 0, 8, 1047},
+ {7, 11, 0, 1, 8, 1057},
+ {7, 9, 0, -1, 8, 1068},
+ {6, 10, -1, 2, 8, 1077},
+ {6, 11, -1, 0, 8, 1087},
+ {6, 11, -1, 0, 8, 1098},
+ {6, 11, -1, 0, 8, 1109},
+ {6, 11, -1, 0, 8, 1120},
+ {6, 10, -1, 0, 8, 1131},
+ {6, 11, -1, 0, 8, 1141},
+ {7, 10, 0, 0, 8, 1152},
+ {6, 13, -1, 3, 8, 1162},
+ {6, 11, -1, 0, 8, 1175},
+ {6, 11, -1, 0, 8, 1186},
+ {6, 11, -1, 0, 8, 1197},
+ {6, 10, -1, 0, 8, 1208},
+ {3, 11, -2, 0, 8, 1218},
+ {3, 11, -2, 0, 8, 1229},
+ {4, 11, -2, 0, 8, 1240},
+ {5, 10, -1, 0, 8, 1251},
+ {7, 10, 0, 0, 8, 1261},
+ {6, 11, -1, 0, 8, 1271},
+ {6, 11, -1, 0, 8, 1282},
+ {6, 11, -1, 0, 8, 1293},
+ {6, 11, -1, 0, 8, 1304},
+ {6, 11, -1, 0, 8, 1315},
+ {6, 10, -1, 0, 8, 1326},
+ {6, 6, -1, -1, 8, 1336},
+ {8, 10, 0, 0, 8, 1342},
+ {6, 11, -1, 0, 8, 1352},
+ {6, 11, -1, 0, 8, 1363},
+ {6, 11, -1, 0, 8, 1374},
+ {6, 10, -1, 0, 8, 1385},
+ {7, 11, 0, 0, 8, 1395},
+ {7, 10, 0, 0, 8, 1406},
+ {6, 10, -1, 0, 8, 1416},
+ {6, 10, -1, 0, 8, 1426},
+ {6, 10, -1, 0, 8, 1436},
+ {6, 10, -1, 0, 8, 1446},
+ {6, 10, -1, 0, 8, 1456},
+ {6, 9, -1, 0, 8, 1466},
+ {6, 11, -1, 0, 8, 1475},
+ {7, 7, 0, 0, 8, 1486},
+ {6, 10, -1, 3, 8, 1493},
+ {6, 10, -1, 0, 8, 1503},
+ {6, 10, -1, 0, 8, 1513},
+ {6, 10, -1, 0, 8, 1523},
+ {6, 9, -1, 0, 8, 1533},
+ {3, 10, -2, 0, 8, 1542},
+ {3, 10, -2, 0, 8, 1552},
+ {4, 10, -2, 0, 8, 1562},
+ {5, 9, -1, 0, 8, 1572},
+ {6, 11, -1, 0, 8, 1581},
+ {6, 10, -1, 0, 8, 1592},
+ {6, 10, -1, 0, 8, 1602},
+ {6, 10, -1, 0, 8, 1612},
+ {6, 10, -1, 0, 8, 1622},
+ {6, 10, -1, 0, 8, 1632},
+ {6, 10, -1, 0, 8, 1642},
+ {6, 7, -1, 0, 8, 1652},
+ {8, 7, 0, 0, 8, 1659},
+ {6, 10, -1, 0, 8, 1666},
+ {6, 10, -1, 0, 8, 1676},
+ {6, 10, -1, 0, 8, 1686},
+ {6, 10, -1, 0, 8, 1696},
+ {6, 14, -1, 4, 8, 1706},
+ {7, 13, 0, 3, 8, 1720},
+ {6, 14, -1, 4, 8, 1733},
+ },
+ bitmap_data
+};
+
+#endif
+
diff --git a/intern/bmfont/intern/Makefile b/intern/bmfont/intern/Makefile
new file mode 100644
index 00000000000..cd02eaa31bd
--- /dev/null
+++ b/intern/bmfont/intern/Makefile
@@ -0,0 +1,44 @@
+#
+# $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.
+#
+# 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 *****
+# bmfont intern Makefile
+#
+
+LIBNAME = bmfont
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I.
+CPPFLAGS += -I..
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
diff --git a/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp
new file mode 100644
index 00000000000..dba5b13bb92
--- /dev/null
+++ b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsp
@@ -0,0 +1,174 @@
+# Microsoft Developer Studio Project File - Name="BMF_bmfont" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=BMF_bmfont - 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 "BMF_bmfont.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 "BMF_bmfont.mak" CFG="BMF_bmfont - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BMF_bmfont - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "BMF_bmfont - 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)" == "BMF_bmfont - 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/BMF_bmfont/"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/BMF_bmfont/"
+# PROP Target_Dir ""
+# 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 "../../intern" /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
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copying BMFONT files library (release target) to lib tree.
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\bmfont\include\" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\BMF_bmfont\BMF_bmfont.lib" "..\..\..\..\..\develop\lib\windows\bmfont\lib\libbmfont.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "BMF_bmfont - 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/BMF_bmfont/debug"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/BMF_bmfont/debug"
+# PROP Target_Dir ""
+# 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 "../../intern" /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
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copying BMFONT files library (debug target) to lib tree.
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\bmfont\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\BMF_bmfont\debug\BMF_bmfont.lib" "..\..\..\..\..\develop\lib\windows\bmfont\lib\debug\libbmfont.a" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "BMF_bmfont - Win32 Release"
+# Name "BMF_bmfont - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_Api.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_BitmapFont.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helv10.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helv12.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helvb10.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helvb12.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helvb14.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_helvb8.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_scr12.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_scr14.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_font_scr15.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_BitmapFont.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BMF_FontData.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\BMF_Api.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\BMF_Fonts.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\BMF_Settings.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw
new file mode 100644
index 00000000000..729f4ac5cb2
--- /dev/null
+++ b/intern/bmfont/make/msvc_6_0/BMF_bmfont.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BMF_bmfont"=.\BMF_bmfont.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/bmfont/test/BMF_Test.cpp b/intern/bmfont/test/BMF_Test.cpp
new file mode 100644
index 00000000000..37d2f45d164
--- /dev/null
+++ b/intern/bmfont/test/BMF_Test.cpp
@@ -0,0 +1,225 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Simple test file for the bitmap font library using GHOST.
+ * @author Maarten Gribnau
+ * @date November 15, 2001
+ */
+
+#include <iostream>
+
+#if defined(WIN32) || defined(__APPLE__)
+#ifdef WIN32
+#include <windows.h>
+#include <GL/gl.h>
+#else // WIN32
+// __APPLE__ is defined
+#include <AGL/gl.h>
+#endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+#include <GL/gl.h>
+#endif // defined(WIN32) || defined(__APPLE__)
+
+
+#include "STR_String.h"
+#include "GHOST_Rect.h"
+
+#include "GHOST_ISystem.h"
+#include "GHOST_IEvent.h"
+#include "GHOST_IEventConsumer.h"
+
+#include "BMF_Api.h"
+
+static class Application* fApp;
+static GHOST_ISystem* fSystem = 0;
+
+
+static void drawGL()
+{
+ GLint x = 10, y = 10;
+
+ ::glRasterPos2i(x, y);
+ BMF_FontPtr font = BMF_GetFont(BMF_kHelvetica10);
+ BMF_DrawString(font, "Helvetica 10 point");
+ y += 14;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kHelvetica12);
+ BMF_DrawString(font, "Helvetica 12 point");
+ y += 16;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kHelveticaBold8);
+ BMF_DrawString(font, "Helvetica Bold 8 point");
+ y += 12;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kHelveticaBold10);
+ BMF_DrawString(font, "Helvetica Bold 10 point");
+ y += 14;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kHelveticaBold12);
+ BMF_DrawString(font, "Helvetica Bold 12 point");
+ y += 16;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kHelveticaBold14);
+ BMF_DrawString(font, "Helvetica Bold 14 point");
+ y += 18;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kScreen12);
+ BMF_DrawString(font, "Screen 12 point");
+ y += 16;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kScreen14);
+ BMF_DrawString(font, "Screen 14 point");
+ y += 18;
+ ::glRasterPos2i(x, y);
+ font = BMF_GetFont(BMF_kScreen15);
+ BMF_DrawString(font, "Screen 15 point");
+}
+
+
+static void setViewPortGL(GHOST_IWindow* window)
+{
+ window->activateDrawingContext();
+ GHOST_Rect bnds;
+ window->getClientBounds(bnds);
+
+ ::glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
+
+ ::glMatrixMode(GL_PROJECTION);
+ ::glLoadIdentity();
+ ::glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10);
+
+ ::glClearColor(.2f,0.0f,0.0f,0.0f);
+ ::glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+
+class Application : public GHOST_IEventConsumer {
+public:
+ Application(GHOST_ISystem* system);
+ virtual bool processEvent(GHOST_IEvent* event);
+
+ GHOST_ISystem* m_system;
+ GHOST_IWindow* m_mainWindow;
+ bool m_exitRequested;
+};
+
+
+Application::Application(GHOST_ISystem* system)
+ : m_system(system), m_mainWindow(0), m_exitRequested(false)
+{
+ fApp = this;
+
+ // Create the main window
+ STR_String title1 ("gears - main window");
+ m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL);
+ if (!m_mainWindow) {
+ std::cout << "could not create main window\n";
+ exit(-1);
+ }
+}
+
+
+bool Application::processEvent(GHOST_IEvent* event)
+{
+ bool handled = true;
+
+ switch (event->getType()) {
+ case GHOST_kEventWindowClose:
+ {
+ GHOST_TEventWindowData* windowData = (GHOST_TEventWindowData*)((GHOST_IEvent*)event)->getData();
+ GHOST_IWindow* window = windowData->window;
+ if (window == m_mainWindow) {
+ exit(0);
+ }
+ else {
+ m_system->disposeWindow(window);
+ }
+ }
+ break;
+
+ case GHOST_kEventWindowActivate:
+ handled = false;
+ break;
+ case GHOST_kEventWindowDeactivate:
+ handled = false;
+ break;
+ case GHOST_kEventWindowUpdate:
+ {
+ GHOST_TEventWindowData* windowData = (GHOST_TEventWindowData*)((GHOST_IEvent*)event)->getData();
+ GHOST_IWindow* window = windowData->window;
+ if (!m_system->validWindow(window)) break;
+ {
+ setViewPortGL(window);
+ drawGL();
+ window->swapBuffers();
+ }
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+ return handled;
+}
+
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ // Create the system
+ GHOST_ISystem::createSystem();
+ fSystem = GHOST_ISystem::getSystem();
+
+ if (fSystem) {
+ // Create an application object
+ Application app (fSystem);
+
+ // Add the application as event consumer
+ fSystem->addEventConsumer(&app);
+
+ // Enter main loop
+ while (!app.m_exitRequested) {
+ fSystem->processEvents();
+ fSystem->dispatchEvents();
+ }
+ }
+
+ // Dispose the system
+ GHOST_ISystem::disposeSystem();
+
+ return 0;
+}
+
diff --git a/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp
new file mode 100644
index 00000000000..13e6e65f706
--- /dev/null
+++ b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsp
@@ -0,0 +1,109 @@
+# Microsoft Developer Studio Project File - Name="BMF_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=BMF_Test - 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 "BMF_Test.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 "BMF_Test.mak" CFG="BMF_Test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BMF_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "BMF_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BMF_Test - 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/BMF_bmfont/test"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/ghost/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libstring.a libghost.a glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../../../lib/windows/string/lib" /libpath:"../../../../../lib/windows/ghost/lib"
+
+!ELSEIF "$(CFG)" == "BMF_Test - 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/BMF_bmfont/test/debug"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/BMF_bmfont/test/debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../" /I "../../../../../lib/windows/string/include" /I "../../../../../lib/windows/ghost/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 glu32.lib opengl32.lib libstring.a libghost.a user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../../../lib/windows/string/lib" /libpath:"../../../../../lib/windows/ghost/lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BMF_Test - Win32 Release"
+# Name "BMF_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\..\intern\BMF_glut_helb8.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\intern\BMF_glut_helb8.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\BMF_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw
new file mode 100644
index 00000000000..5baacb9adf7
--- /dev/null
+++ b/intern/bmfont/test/make/msvc_6_0/BMF_Test.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BMF_Test"=.\BMF_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name BMF_bmfont
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "BMF_bmfont"=..\..\..\make\msvc_6_0\BMF_bmfont.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/bsp/Makefile b/intern/bsp/Makefile
new file mode 100644
index 00000000000..371c43c848a
--- /dev/null
+++ b/intern/bsp/Makefile
@@ -0,0 +1,55 @@
+#
+# $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.
+#
+# 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 *****
+# bsp main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = bsp
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+# not yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_BSP) ] || mkdir $(NAN_BSP)
+ @[ -d $(NAN_BSP)/include ] || mkdir $(NAN_BSP)/include
+ @[ -d $(NAN_BSP)/lib ] || mkdir $(NAN_BSP)/lib
+ @[ -d $(NAN_BSP)/lib/debug ] || mkdir $(NAN_BSP)/lib/debug
+ cp -f $(DIR)/libbsp.a $(NAN_BSP)/lib/
+ cp -f $(DIR)/debug/libbsp.a $(NAN_BSP)/lib/debug/
+ cp -f extern/*.h $(NAN_BSP)/include/
+
+
+
+
diff --git a/intern/bsp/extern/CSG_BooleanOps.h b/intern/bsp/extern/CSG_BooleanOps.h
new file mode 100755
index 00000000000..0a348fdc05e
--- /dev/null
+++ b/intern/bsp/extern/CSG_BooleanOps.h
@@ -0,0 +1,428 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef CSG_BOOLEANOPS_H
+
+#define CSG_BOOLEANOPS_H
+
+/**
+ * @section Interface structures for CSG module.
+ * This interface falls into 2 categories.
+ * The first section deals with an abstract mesh description
+ * between blender and this module. The second deals with
+ * the module functions.
+ * The CSG module needs to know about the following entities:
+ */
+
+/**
+ * CSG_IFace -- an interface polygon structure.
+ * vertex_index is a fixed size array of 4 elements containing indices into
+ * an abstract vertex container. 3 or 4 of these elements may be used to
+ * describe either quads or triangles.
+ * vertex_number is the number of vertices in this face - either 3 or 4.
+ * vertex_colors is an array of {r,g,b} triplets one for each vertex index.
+ * tex_coords is an array of {u,v} triplets one for each vertex index.
+ * user_data is a pointer to arbitary data of fixed width ,
+ * this data is copied around with the face, and duplicated if a face is
+ * split. Contains things like material index.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ int vertex_index[4];
+ int vertex_number;
+
+ void *user_face_vertex_data[4];
+ void *user_face_data;
+} CSG_IFace;
+
+/**
+ * CSG_IVertex -- an interface vertex structure.
+ * position is the location of the vertex in 3d space.
+ */
+
+typedef struct {
+ float position[3];
+} CSG_IVertex;
+
+/**
+ * The actual useful data contained in a group of faces is
+ * described by the following struct
+ */
+
+/**
+ * Descibes the data stored in a mesh available through the
+ * CSG_IFace interface.
+ * user_data_size is the number of bytes of user_data associated with each CSG_IFace
+ * user_face_vertex_data size is the number of bytes of user data associated with
+ * every face vertex tuple.
+ * .
+ */
+
+typedef struct CSG_MeshPropertyDescriptor{
+ unsigned int user_face_vertex_data_size;
+ unsigned int user_data_size;
+} CSG_MeshPropertyDescriptor;
+
+
+
+/**
+ * @section Iterator abstraction.
+ *
+ * The CSG module asks blender to fill in an instance of the above
+ * structure, and requests blender to move up and down (iterate) through
+ * it's face and vertex containers.
+ *
+ * An iterator supports the following functions.
+ * int IsDone(iterator *it) -- returns true if the iterator has reached
+ * the end of it's container.
+ *
+ * void Fill(iterator *it,DataType *data) -- Return the contents of the
+ * container at the current iterator position.
+ *
+ * void Step(iterator *it) -- increment the iterator to the next position
+ * in the container.
+ *
+ * The iterator is used in the following manner.
+ *
+ * MyIterator * iterator = ...
+ * DataType data;
+ *
+ * while (!IsDone(iterator)) {
+ * Fill(iterator,&data);
+ * //process information pointed to by data
+ * ...
+ * Step(iterator);
+ * }
+ *
+ * The CSG module does not want to know about the implementation of these
+ * functions so we use the c function ptr mechanism to hide them. Our
+ * iterator descriptor now looks like this.
+ */
+
+typedef void* CSG_IteratorPtr;
+
+typedef int (*CSG_FaceItDoneFunc)(CSG_IteratorPtr it);
+typedef void (*CSG_FaceItFillFunc)(CSG_IteratorPtr it,CSG_IFace *face);
+typedef void (*CSG_FaceItStepFunc)(CSG_IteratorPtr it);
+typedef void (*CSG_FaceItResetFunc)(CSG_IteratorPtr it);
+
+typedef struct CSG_FaceIteratorDescriptor {
+ CSG_IteratorPtr it;
+ CSG_FaceItDoneFunc Done;
+ CSG_FaceItFillFunc Fill;
+ CSG_FaceItStepFunc Step;
+ CSG_FaceItResetFunc Reset;
+ unsigned int num_elements;
+} CSG_FaceIteratorDescriptor;
+
+/**
+ * Similarly to walk through the vertex arrays we have.
+ */
+typedef int (*CSG_VertexItDoneFunc)(CSG_IteratorPtr it);
+typedef void (*CSG_VertexItFillFunc)(CSG_IteratorPtr it,CSG_IVertex *face);
+typedef void (*CSG_VertexItStepFunc)(CSG_IteratorPtr it);
+typedef void (*CSG_VertexItResetFunc)(CSG_IteratorPtr it);
+
+typedef struct CSG_VertexIteratorDescriptor {
+ CSG_IteratorPtr it;
+ CSG_VertexItDoneFunc Done;
+ CSG_VertexItFillFunc Fill;
+ CSG_VertexItStepFunc Step;
+ CSG_VertexItResetFunc Reset;
+ unsigned int num_elements;
+} CSG_VertexIteratorDescriptor;
+
+/**
+ * The actual iterator structures are not exposed to the CSG module, they
+ * will contain datatypes specific to blender.
+ */
+
+/**
+ * @section CSG Module interface functions.
+ *
+ * The functions below are to be used in the following way:
+ *
+ * // Create a boolean operation handle
+ * CSG_BooleanOperation *operation = CSG_NewBooleanFunction();
+ * if (operation == NULL) {
+ * // deal with low memory exception
+ * }
+ *
+ * // Describe each mesh operand to the module.
+ * // NOTE: example properties!
+ * CSG_MeshPropertyDescriptor propA,propB;
+ * propA.user_data_size = 0;
+ * propA.user_face_vertex_data = 0;
+ * propB.user_face_vertex_data = 0;
+ * propB.user_data_size = 0;
+ *
+ * // Get the output properties of the mesh.
+ * CSG_MeshPropertyDescriptor output_properties;
+ * output_properties = CSG_DescibeOperands(
+ * operation,
+ * propA,
+ * propB
+ * );
+ *
+ * // Report to the user if they will loose any data!
+ * ...
+ *
+ * // Get some mesh iterators for your mesh data structures
+ * CSG_FaceIteratorDescriptor obA_faces = ...
+ * CSG_VertexIteratorDescriptor obA_verts = ...
+ *
+ * // same for object B
+ * CSG_FaceIteratorDescriptor obB_faces = ...
+ * CSG_VertexIteratorDescriptor obB_verts = ...
+ *
+ * // perform the operation...!
+ *
+ * int success = CSG_PerformBooleanOperation(
+ * operation,
+ * e_csg_intersection,
+ * obA_faces,
+ * obA_vertices,
+ * obB_faces,
+ * obB_vertices
+ * );
+ *
+ * // if the operation failes report miserable faiulre to user
+ * // and clear up data structures.
+ * if (!success) {
+ * ...
+ * CSG_FreeBooleanOperation(operation);
+ * return;
+ * }
+ *
+ * // read the new mesh vertices back from the module
+ * // and assign to your own mesh structure.
+ *
+ * // First we need to create a CSG_IVertex so the module can fill it in.
+ * CSG_IVertex vertex;
+ * CSG_VertexIteratorDescriptor * verts_it = CSG_OutputVertexDescriptor(operation);
+ *
+ * // initialize your vertex container with the number of verts (verts_it->num_elements)
+ *
+ * while (!verts_it->Done(verts_it->it)) {
+ * verts_it->Fill(verts_it->it,&vertex);
+ *
+ * // create a new vertex of your own type and add it
+ * // to your mesh structure.
+ * verts_it->Step(verts_it->it);
+ * }
+ * // Free the vertex iterator
+ * CSG_FreeVertexDescriptor(verts_it);
+ *
+ * // similarly for faces.
+ * CSG_IFace face;
+ *
+ * // you may need to reserve some memory in face->user_data here.
+ *
+ * // initialize your face container with the number of faces (faces_it->num_elements)
+ *
+ * CSG_FaceIteratorDescriptor * faces_it = CSG_OutputFaceDescriptor(operation);
+ *
+ * while (!faces_it->Done(faces_it->it)) {
+ * faces_it->Fill(faces_it->it,&face);
+ *
+ * // create a new face of your own type and add it
+ * // to your mesh structure.
+ * faces_it->Step(&faces_it->it);
+ * }
+ *
+ * // Free the face iterator
+ * CSG_FreeVertexDescriptor(faces_it);
+ *
+ * // that's it free the operation.
+ *
+ * CSG_FreeBooleanOperation(operation);
+ * return;
+ *
+ */
+
+/**
+ * Description of boolean operation type.
+ */
+
+typedef enum {
+ e_csg_union,
+ e_csg_intersection,
+ e_csg_difference,
+ e_csg_classify
+} CSG_OperationType;
+
+/**
+ * 'Handle' into the CSG module that identifies a particular CSG operation.
+ * the pointer CSG_info containers module specific data, and should not
+ * be touched in anyway outside of the module.
+ */
+
+typedef struct {
+ void *CSG_info;
+} CSG_BooleanOperation;
+
+/**
+ * Return a ptr to a CSG_BooleanOperation object allocated
+ * on the heap. The CSG module owns the memory associated with
+ * the returned ptr, use CSG_FreeBooleanOperation() to free this memory.
+ */
+ CSG_BooleanOperation *
+CSG_NewBooleanFunction(
+ void
+);
+
+/**
+ * Describe the operands of a boolean function to the module.
+ * The description takes the form of a pair of CSG_MeshPropertyDescriptors
+ * one for each input mesh. The operands do not have to have the same
+ * properties, for example operandA may have vertex colours but operandB none.
+ * In this case the CSG module will choose the lowest common denominator in
+ * mesh properies. The function returns a description of
+ * the output mesh. You can use this to warn the user that certain properties
+ * will be lost. Of course it also describes what fields in the output mesh
+ * will contain valid data.
+ */
+ CSG_MeshPropertyDescriptor
+CSG_DescibeOperands(
+ CSG_BooleanOperation * operation,
+ CSG_MeshPropertyDescriptor operandA_desciption,
+ CSG_MeshPropertyDescriptor operandB_desciption
+);
+
+/**
+ * The user data is handled by the BSP modules through
+ * the following function which is called whenever the
+ * module needs new face vertex properties (when a face is split).
+ * d1,d2 are pointers to existing vertex face data. dnew is
+ * a pointer to an allocated but unfilled area of user data of
+ * size user_face_vertex_data_size in the CSG_MeshPropertyDescriptor
+ * returned by a call to the above function. Epsilon is the relative
+ * distance (between [0,1]) of the new vertex and the vertex associated
+ * with d1. Use epsilon to interpolate the face vertex data in d1 and d2
+ * and fill dnew
+ */
+
+typedef int (*CSG_InterpolateUserFaceVertexDataFunc)(void *d1, void * d2, void *dnew, float epsilon);
+
+
+/**
+ * Attempt to perform a boolean operation between the 2 objects of the
+ * desired type. This may fail due to an internal error or lack of memory.
+ * In this case 0 is returned, otehrwise 1 is returned indicating success.
+ * @param operation is a 'handle' into the CSG_Module created by CSG_NewBooleanFunction()
+ * @param op_type is the operation to perform.
+ * @param obAFaces is an iterator over the faces of objectA,
+ * @param obAVertices is an iterator over the vertices of objectA
+ * @param obAFaces is an iterator over the faces of objectB,
+ * @param obAVertices is an iterator over the vertices of objectB
+ * @param interp_func the face_vertex data interpolation function.(see above)
+ *
+ * All iterators must be valid and pointing to the first element in their
+ * respective containers.
+ */
+ int
+CSG_PerformBooleanOperation(
+ CSG_BooleanOperation * operation,
+ CSG_OperationType op_type,
+ CSG_FaceIteratorDescriptor obAFaces,
+ CSG_VertexIteratorDescriptor obAVertices,
+ CSG_FaceIteratorDescriptor obBFaces,
+ CSG_VertexIteratorDescriptor obBVertices,
+ CSG_InterpolateUserFaceVertexDataFunc interp_func
+);
+
+/**
+ * If the a boolean operation was successful, you may access the results
+ * through the following functions.
+ *
+ * CSG_OuputFaceDescriptor() returns a ptr to a CSG_FaceIteratorDesciptor
+ * allocated on the heap and owned by the CSG module. The iterator is
+ * positioned at the start of the internal face container.
+ * CSG_OutputVertexDescriptor() returns a ptr to a CSG_VertexIteratorDescriptor
+ * allocated on the heap and owned by the CSG module. The iterator is
+ * positioned at the start of the internal vertex container.
+ * There is no function to rewind an iterator but you may obtain more
+ * than one
+ * iterator at a time. Please use the function CSG_FreeFaceIterator()
+ * and CSG_FreeVertexIterator to free internal memory allocated for these
+ * iterators.
+ *
+ * If the last operation was not successful, these functions return NULL.
+ */
+ int
+CSG_OutputFaceDescriptor(
+ CSG_BooleanOperation * operation,
+ CSG_FaceIteratorDescriptor * output
+);
+
+ int
+CSG_OutputVertexDescriptor(
+ CSG_BooleanOperation * operation,
+ CSG_VertexIteratorDescriptor *output
+);
+
+/**
+ * Clean up functions.
+ * Free internal memory associated with CSG interface structures. You must
+ * call these functions on any structures created by the module, even if
+ * subsequent operations did not succeed.
+ */
+ void
+CSG_FreeVertexDescriptor(
+ CSG_VertexIteratorDescriptor * v_descriptor
+);
+
+ void
+CSG_FreeFaceDescriptor(
+ CSG_FaceIteratorDescriptor * f_descriptor
+);
+
+/**
+ * Free the memory associated with a boolean operation.
+ * NOTE any iterator descriptor describing the output will become
+ * invalid after this call and should be freed immediately.
+ */
+ void
+CSG_FreeBooleanOperation(
+ CSG_BooleanOperation *operation
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/intern/BSP_CSGException.h b/intern/bsp/intern/BSP_CSGException.h
new file mode 100755
index 00000000000..7224d8b0910
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGException.h
@@ -0,0 +1,58 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_CSGException_h
+
+#define NAN_INCLUDED_CSGException_h
+
+// stick in more error types as you think of them
+
+enum BSP_ExceptionType{
+ e_split_error,
+ e_mesh_error,
+ e_mesh_input_error,
+ e_param_error,
+ e_tree_build_error
+};
+
+
+class BSP_CSGException {
+public :
+ BSP_ExceptionType m_e_type;
+
+ BSP_CSGException (
+ BSP_ExceptionType type
+ ) : m_e_type (type)
+ {
+ }
+};
+
+#endif
diff --git a/intern/bsp/intern/BSP_CSGHelper.cpp b/intern/bsp/intern/BSP_CSGHelper.cpp
new file mode 100644
index 00000000000..72ad30b6f0f
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGHelper.cpp
@@ -0,0 +1,430 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGHelper.h"
+
+#include "BSP_CSGMesh.h"
+#include "BSP_MeshFragment.h"
+#include "BSP_FragTree.h"
+#include "BSP_CSGMeshSplitter.h"
+#include "BSP_CSGNCMeshSplitter.h"
+#include "BSP_Triangulate.h"
+
+#include "MEM_SmartPtr.h"
+
+using namespace std;
+
+BSP_CSGHelper::
+BSP_CSGHelper(
+)
+{
+ // nothing to do
+}
+
+ bool
+BSP_CSGHelper::
+ComputeOp(
+ BSP_CSGMesh * obA,
+ BSP_CSGMesh * obB,
+ BSP_OperationType op_type,
+ BSP_CSGMesh & output,
+ CSG_InterpolateUserFaceVertexDataFunc fv_func
+){
+ // First work out which parts of polygons we want to keep as we pass stuff
+ // down the tree.
+
+ BSP_Classification e_ATreeB,e_BTreeA;
+ bool invertA(false),invertB(false);
+
+ switch (op_type) {
+ case e_intern_csg_union :
+ e_ATreeB = e_classified_out;
+ e_BTreeA = e_classified_out;
+ break;
+ case e_intern_csg_intersection :
+ e_ATreeB = e_classified_in;
+ e_BTreeA = e_classified_in;
+ break;
+ case e_intern_csg_difference :
+ invertA = true;
+ e_ATreeB = e_classified_in;
+ e_BTreeA = e_classified_in;
+ break;
+ default :
+ return false;
+ }
+
+ if (invertA) {
+ obA->Invert();
+ }
+
+ if (invertB) {
+ obB->Invert();
+ }
+
+ MEM_SmartPtr<BSP_CSGMesh> obA_copy = obA->NewCopy();
+ MEM_SmartPtr<BSP_CSGMesh> obB_copy = obB->NewCopy();
+
+ // ok we need yet another copy...
+
+ MEM_SmartPtr<BSP_CSGMesh> obA_copy2 = obA->NewCopy();
+ MEM_SmartPtr<BSP_CSGMesh> obB_copy2 = obB->NewCopy();
+
+ obA_copy->BuildEdges();
+ obB_copy->BuildEdges();
+
+ // Create a splitter to help chop up the mesh and preserrve.
+ // mesh connectivity
+
+ MEM_SmartPtr<BSP_CSGMeshSplitter> splitter = new BSP_CSGMeshSplitter(fv_func);
+ if (splitter == NULL) return false;
+
+ // Create a splitter to help chop the mesh for tree building.
+ MEM_SmartPtr<BSP_CSGNCMeshSplitter> nc_splitter = new BSP_CSGNCMeshSplitter();
+
+ if (splitter == NULL || nc_splitter == NULL) return false;
+
+ // Create a tree for both meshes.
+
+ MEM_SmartPtr<BSP_FragTree> treeA = treeA->New(obA,nc_splitter.Ref());
+ MEM_SmartPtr<BSP_FragTree> treeB = treeB->New(obB,nc_splitter.Ref());
+
+ if (treeA == NULL || treeB == NULL) {
+ return false;
+ }
+
+ // Classify each object wrt the other tree.
+
+ MEM_SmartPtr<BSP_MeshFragment> AinB = new BSP_MeshFragment(obA_copy2,e_classified_in);
+ MEM_SmartPtr<BSP_MeshFragment> AoutB = new BSP_MeshFragment(obA_copy2,e_classified_out);
+ MEM_SmartPtr<BSP_MeshFragment> AonB = new BSP_MeshFragment(obA_copy2,e_classified_on);
+
+ treeB->Classify(obA_copy2,AinB,AoutB,AonB,nc_splitter.Ref());
+
+ MEM_SmartPtr<BSP_MeshFragment> BinA = new BSP_MeshFragment(obB_copy2,e_classified_in);
+ MEM_SmartPtr<BSP_MeshFragment> BoutA = new BSP_MeshFragment(obB_copy2,e_classified_out);
+ MEM_SmartPtr<BSP_MeshFragment> BonA = new BSP_MeshFragment(obB_copy2,e_classified_on);
+
+ treeA->Classify(obB_copy2,BinA,BoutA,BonA,nc_splitter.Ref());
+
+ // Now we need to work what were the spanning polygons from the original mesh.
+ // Build a spanning fragment from them and pass split those mothers.
+
+ MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA2 = new BSP_MeshFragment(obA_copy,e_BTreeA);
+ MEM_SmartPtr<BSP_MeshFragment> AspanningB = new BSP_MeshFragment(obA_copy,e_classified_spanning);
+
+ TranslateSplitFragments(AinB.Ref(),AoutB.Ref(),AonB.Ref(),e_BTreeA,AspanningB.Ref(),frag_BTreeA2.Ref());
+
+ MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB2 = new BSP_MeshFragment(obB_copy,e_ATreeB);
+ MEM_SmartPtr<BSP_MeshFragment> BspanningA = new BSP_MeshFragment(obB_copy,e_classified_spanning);
+
+ TranslateSplitFragments(BinA.Ref(),BoutA.Ref(),BonA.Ref(),e_ATreeB,BspanningA.Ref(),frag_ATreeB2.Ref());
+
+
+ MEM_SmartPtr<BSP_MeshFragment> frag_ATreeB = new BSP_MeshFragment(obB_copy,e_ATreeB);
+ MEM_SmartPtr<BSP_MeshFragment> frag_BTreeA = new BSP_MeshFragment(obA_copy,e_BTreeA);
+
+ if (frag_ATreeB == NULL || frag_BTreeA == NULL) return false;
+
+ // Pass the spanning polygons of copyB through the tree of copyA.
+ treeA->Push(BspanningA,frag_ATreeB,e_ATreeB,e_classified_spanning,true,splitter.Ref());
+
+ // Add the result of the push to the fragments we are interested in.
+ MergeFrags(frag_ATreeB2.Ref(),frag_ATreeB.Ref());
+
+ // Pass the spanning polygons of copyA through the tree of copyB
+ treeB->Push(AspanningB,frag_BTreeA,e_BTreeA,e_classified_spanning,false,splitter.Ref());
+ MergeFrags(frag_BTreeA2.Ref(),frag_BTreeA.Ref());
+
+ // Copy the fragments into a new mesh.
+ DuplicateMesh(frag_ATreeB.Ref(),output);
+ DuplicateMesh(frag_BTreeA.Ref(),output);
+
+ return true;
+
+};
+
+ void
+BSP_CSGHelper::
+TranslateSplitFragments(
+ const BSP_MeshFragment & in_frag,
+ const BSP_MeshFragment & out_frag,
+ const BSP_MeshFragment & on_frag,
+ BSP_Classification keep,
+ BSP_MeshFragment & spanning_frag,
+ BSP_MeshFragment & output
+){
+
+ // iterate through the 3 input fragments
+ // tag the polygons in the output fragments according to
+ // the classification of the input frags.
+
+ const BSP_CSGMesh *i_mesh = in_frag.Mesh();
+ BSP_CSGMesh *o_mesh = output.Mesh();
+
+ const vector<BSP_MFace> &i_faces = i_mesh->FaceSet();
+ vector<BSP_MFace> &o_faces = o_mesh->FaceSet();
+
+ vector<BSP_FaceInd>::const_iterator if_it = in_frag.FaceSet().begin();
+ vector<BSP_FaceInd>::const_iterator if_end = in_frag.FaceSet().end();
+
+ for (;if_it != if_end; ++if_it) {
+ int original_index = i_faces[*if_it].OpenTag();
+ if (original_index == -1) {
+ // then this face was never split and the original_index is
+ // the actual face index.
+ original_index = *if_it;
+ }
+ // tag the output faces with the in flag.
+ if (o_faces[original_index].OpenTag() == -1) {
+ o_faces[original_index].SetOpenTag(0);
+ }
+ o_faces[original_index].SetOpenTag(
+ o_faces[original_index].OpenTag() | e_classified_in
+ );
+ }
+
+ // same for out fragments.
+ if_it = out_frag.FaceSet().begin();
+ if_end = out_frag.FaceSet().end();
+
+ for (;if_it != if_end; ++if_it) {
+ int original_index = i_faces[*if_it].OpenTag();
+ if (original_index == -1) {
+ // then this face was never split and the original_index is
+ // the actual face index.
+ original_index = *if_it;
+ }
+ // tag the output faces with the in flag.
+ if (o_faces[original_index].OpenTag() == -1) {
+ o_faces[original_index].SetOpenTag(0);
+ }
+ o_faces[original_index].SetOpenTag(
+ o_faces[original_index].OpenTag() | e_classified_out
+ );
+ }
+
+ // on fragments just get set as spanning for now.
+
+ if_it = on_frag.FaceSet().begin();
+ if_end = on_frag.FaceSet().end();
+
+ for (;if_it != if_end; ++if_it) {
+ int original_index = i_faces[*if_it].OpenTag();
+ if (original_index == -1) {
+ // then this face was never split and the original_index is
+ // the actual face index.
+ original_index = *if_it;
+ }
+ // tag the output faces with the in flag.
+ if (o_faces[original_index].OpenTag() == -1) {
+ o_faces[original_index].SetOpenTag(0);
+ }
+ o_faces[original_index].SetOpenTag(
+ o_faces[original_index].OpenTag() | e_classified_spanning
+ );
+ }
+ // now run through the output faces.
+ // collect the ones we are interested in into output
+ // and collect the spanning faces.
+
+ int of_it = 0;
+ int of_size = o_faces.size();
+
+ for (;of_it < of_size; ++of_it) {
+
+ int p_class = o_faces[of_it].OpenTag();
+
+ if (p_class == int(keep)) {
+ output.FaceSet().push_back(BSP_FaceInd(of_it));
+ } else
+ if (
+ (p_class == (e_classified_in | e_classified_out)) ||
+ p_class == e_classified_spanning
+ ) {
+ spanning_frag.FaceSet().push_back(BSP_FaceInd(of_it));
+ }
+ }
+}
+
+
+ void
+BSP_CSGHelper::
+MergeFrags(
+ const BSP_MeshFragment & in,
+ BSP_MeshFragment & out
+){
+
+ // Add the 2 frags together.
+
+ out.FaceSet().insert(
+ out.FaceSet().end(),
+ in.FaceSet().begin(),
+ in.FaceSet().end()
+ );
+}
+
+
+
+BSP_CSGHelper::
+~BSP_CSGHelper(
+){
+ // nothing to do
+}
+
+ void
+BSP_CSGHelper::
+DuplicateMesh(
+ const BSP_MeshFragment & frag,
+ BSP_CSGMesh & output
+){
+
+ // This stuff is a real waste of time.
+ // much better to create an output iterator based upon
+ // the 2 mesh fragments alone.
+
+ vector<BSP_MVertex> & o_verts = output.VertexSet();
+ BSP_CSGUserData & o_fv_data = output.FaceVertexData();
+ BSP_CSGUserData & o_f_data = output.FaceData();
+
+ // A temporary buffer containing the triangulated
+ // vertex indices.
+
+ vector<int> triangle_indices;
+
+ BSP_CSGMesh * i_mesh = frag.Mesh();
+
+ if (i_mesh == NULL) return;
+
+ vector<BSP_MVertex> & i_verts = i_mesh->VertexSet();
+ const vector<BSP_MFace> & i_faces = i_mesh->FaceSet();
+ BSP_CSGUserData & i_fv_data = i_mesh->FaceVertexData();
+ BSP_CSGUserData & i_f_data = i_mesh->FaceData();
+
+ // iterate through the fragment's face set
+ const vector<BSP_FaceInd> & frag_faces = frag.FaceSet();
+
+ vector<BSP_FaceInd>::const_iterator f_faces_it = frag_faces.begin();
+ vector<BSP_FaceInd>::const_iterator f_faces_end = frag_faces.end();
+
+ // We need to keep track of which vertices we are selecting.
+ vector<int> selected_vi;
+
+ BSP_Triangulate triangulator;
+
+ for (; f_faces_it != f_faces_end; ++f_faces_it) {
+
+ BSP_FaceInd fi = *f_faces_it;
+ const BSP_MFace &face = i_faces[fi];
+
+ // duplicate the face
+ BSP_MFace dup_face(face);
+
+ // iterate through the face's vertex indices.
+ vector<BSP_VertexInd>::iterator dup_f_verts_it = dup_face.m_verts.begin();
+ vector<BSP_VertexInd>::const_iterator dup_f_verts_end = dup_face.m_verts.end();
+
+ for (; dup_f_verts_it != dup_f_verts_end; ++dup_f_verts_it) {
+
+ if (i_verts[*dup_f_verts_it].SelectTag() == false) {
+ // copy this vertex onto the output mesh vertex array.
+
+ BSP_VertexInd new_vi(o_verts.size());
+ o_verts.push_back(i_verts[*dup_f_verts_it]);
+
+ // should kill the old vertices edge ptrs.
+ o_verts[new_vi].m_edges.clear();
+
+ // set the open tag in the old vert to the new one.
+ i_verts[*dup_f_verts_it].SetOpenTag(new_vi);
+
+ // select the old vertex
+ i_verts[*dup_f_verts_it].SetSelectTag(true);
+ selected_vi.push_back(*dup_f_verts_it);
+ }
+
+ // we have been to this vertex before and there should be
+ // a corresponding vertex in the new mesh vertex set.
+ *dup_f_verts_it = i_verts[*dup_f_verts_it].OpenTag();
+ }
+
+ // duplicate the face vertex data for this polygon.
+
+ vector<BSP_UserFVInd>::iterator dup_fv_it = dup_face.m_fv_data.begin();
+ vector<BSP_UserFVInd>::const_iterator dup_fv_end = dup_face.m_fv_data.end();
+
+ for (;dup_fv_it != dup_fv_end; ++dup_fv_it) {
+ *dup_fv_it = o_fv_data.Duplicate(i_fv_data[int(*dup_fv_it)]);
+ }
+
+ triangle_indices.clear();
+
+ // Now triangulate the polygon.
+ if (!triangulator.Process(
+ o_verts,
+ dup_face.m_verts,
+ dup_face.m_plane,
+ triangle_indices
+ )) {
+ // Sometimes the triangulator can fail for very small
+ // polygons or very thing polygons. This should be
+ // handled more elegantly but for now we just leave out the
+ // polygon from the mesh.
+ continue;
+ }
+
+ // Run through the result and add in the triangle faces.
+
+ int i;
+ for (i = 0; i < triangle_indices.size(); i+=3) {
+ // duplicate the face data for this face.
+ o_f_data.Duplicate(i_f_data[*f_faces_it]);
+
+ output.AddSubTriangle(dup_face,triangle_indices.begin() + i);
+ }
+ }
+
+ // of course we have to deselect the vertices again.
+
+ vector<int>::const_iterator selected_vi_it = selected_vi.begin();
+ vector<int>::const_iterator selected_vi_end = selected_vi.end();
+
+ for (; selected_vi_it != selected_vi_end; ++selected_vi_it) {
+ i_verts[*selected_vi_it].SetSelectTag(false);
+ }
+}
+
+
+
+
+
+
+
diff --git a/intern/bsp/intern/BSP_CSGHelper.h b/intern/bsp/intern/BSP_CSGHelper.h
new file mode 100644
index 00000000000..f122fc3cf31
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGHelper.h
@@ -0,0 +1,99 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGHELPER_H
+
+#define BSP_CSGHELPER_H
+
+class BSP_CSGMesh;
+class BSP_MeshFragment;
+
+#include "../extern/CSG_BooleanOps.h"
+#include "BSP_MeshPrimitives.h"
+
+enum BSP_OperationType{
+ e_intern_csg_union,
+ e_intern_csg_intersection,
+ e_intern_csg_difference
+};
+
+class BSP_CSGHelper {
+public :
+
+ BSP_CSGHelper(
+ );
+
+ bool
+ ComputeOp(
+ BSP_CSGMesh * obA,
+ BSP_CSGMesh * obB,
+ BSP_OperationType op_type,
+ BSP_CSGMesh & output,
+ CSG_InterpolateUserFaceVertexDataFunc fv_func
+ );
+
+
+ ~BSP_CSGHelper(
+ );
+
+private:
+
+ // Iterate through the fragment,
+ // add new vertices to output,
+ // map polygons to new vertices.
+
+ void
+ DuplicateMesh(
+ const BSP_MeshFragment & frag,
+ BSP_CSGMesh & output
+ );
+
+ void
+ TranslateSplitFragments(
+ const BSP_MeshFragment & in_frag,
+ const BSP_MeshFragment & out_frag,
+ const BSP_MeshFragment & on_frag,
+ BSP_Classification keep,
+ BSP_MeshFragment & spanning_frag,
+ BSP_MeshFragment & output
+ );
+
+ void
+ MergeFrags(
+ const BSP_MeshFragment & in,
+ BSP_MeshFragment & out
+ );
+
+
+
+};
+
+#endif
diff --git a/intern/bsp/intern/BSP_CSGISplitter.h b/intern/bsp/intern/BSP_CSGISplitter.h
new file mode 100755
index 00000000000..c88a04a7932
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGISplitter.h
@@ -0,0 +1,118 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGISplitter_h
+
+#define BSP_CSGISplitter_h
+
+class BSP_MeshFragment;
+class BSP_CSGMesh;
+
+class MT_Plane3;
+
+/**
+ * This class defines a mesh splitter interface.
+ * It embodies the action of splitting a mesh by a plane.
+ * Depending on the context of the operation subclasses
+ * may wish to define different implementations. For example
+ * with building a BSP tree from a mesh, the mesh does not
+ * need to be kept consistent, it doesn't matter if the edges
+ * are maintained etc. However when pushing polygons through
+ * a BSP tree (say for CSG operations)it is important to
+ * try and maintain mesh connectivity and thus a different
+ * splitter implementation may be needed.
+ *
+ * This is an abstract interface class.
+ */
+
+class BSP_CSGISplitter
+{
+
+public:
+
+ /**
+ * Split the incoming mesh fragment (frag)
+ * by the plane, put the output into (in,out and on)
+ * Subclasses should clear the contents of the
+ * in_coming fragment.
+ */
+
+ virtual
+ void
+ Split(
+ const MT_Plane3& plane,
+ BSP_MeshFragment *frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ )= 0;
+
+ /**
+ * Split the entire mesh with respect to the plane.
+ * and place ouput into (in,out and on).
+ * Subclasses should clear the contents of the
+ * in_coming fragment.
+ */
+ virtual
+ void
+ Split(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ )=0;
+
+ virtual
+ ~BSP_CSGISplitter(
+ ){
+ };
+
+protected :
+
+ BSP_CSGISplitter(
+ ) {
+ //nothing to do
+ }
+
+ BSP_CSGISplitter(
+ const BSP_CSGISplitter &
+ ) {
+ //nothing to do
+ }
+};
+
+
+
+#endif
+
diff --git a/intern/bsp/intern/BSP_CSGMesh.cpp b/intern/bsp/intern/BSP_CSGMesh.cpp
new file mode 100755
index 00000000000..d1721cb692b
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMesh.cpp
@@ -0,0 +1,883 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+
+#include "BSP_CSGMesh.h"
+#include "MT_assert.h"
+#include "CTR_TaggedSetOps.h"
+#include "BSP_MeshFragment.h"
+#include "MT_Plane3.h"
+#include "BSP_CSGException.h"
+
+// for vector reverse
+#include <algorithm>
+using namespace std;
+
+BSP_CSGMesh::
+BSP_CSGMesh(
+) :
+ MEM_RefCountable()
+{
+ // nothing to do
+}
+
+ BSP_CSGMesh *
+BSP_CSGMesh::
+New(
+){
+ return new BSP_CSGMesh();
+}
+
+ BSP_CSGMesh *
+BSP_CSGMesh::
+NewCopy(
+) const {
+
+ MEM_SmartPtr<BSP_CSGMesh> mesh = New();
+ if (mesh == NULL) return NULL;
+
+ mesh->m_bbox_max = m_bbox_max;
+ mesh->m_bbox_min = m_bbox_min;
+
+ if (m_edges != NULL) {
+ mesh->m_edges = new vector<BSP_MEdge>(m_edges.Ref());
+ if (mesh->m_edges == NULL) return NULL;
+ }
+ if (m_verts != NULL) {
+ mesh->m_verts = new vector<BSP_MVertex>(m_verts.Ref());
+ if (mesh->m_verts == NULL) return NULL;
+ }
+ if (m_faces != NULL) {
+ mesh->m_faces = new vector<BSP_MFace>(m_faces.Ref());
+ if (mesh->m_faces == NULL) return NULL;
+ }
+ if (m_fv_data != NULL) {
+ mesh->m_fv_data = new BSP_CSGUserData(m_fv_data.Ref());
+ if (mesh->m_fv_data == NULL) return NULL;
+ }
+ if (m_face_data != NULL) {
+ mesh->m_face_data = new BSP_CSGUserData(m_face_data.Ref());
+ if (mesh->m_face_data == NULL) return NULL;
+ }
+
+ return mesh.Release();
+}
+
+ void
+BSP_CSGMesh::
+Invert(
+){
+
+ vector<BSP_MFace> & faces = FaceSet();
+
+ vector<BSP_MFace>::const_iterator faces_end = faces.end();
+ vector<BSP_MFace>::iterator faces_it = faces.begin();
+
+ for (; faces_it != faces_end; ++faces_it) {
+ faces_it->Invert();
+ }
+}
+
+ bool
+BSP_CSGMesh::
+SetVertices(
+ MEM_SmartPtr<vector<BSP_MVertex> > verts
+){
+ if (verts == NULL) return false;
+
+ // create polygon and edge arrays and reserve some space.
+ m_faces = new vector<BSP_MFace>;
+ if (!m_faces) return false;
+
+ m_faces->reserve(verts->size()/2);
+
+ // previous verts get deleted here.
+ m_verts = verts;
+ return true;
+}
+
+ void
+BSP_CSGMesh::
+SetFaceVertexData(
+ MEM_SmartPtr<BSP_CSGUserData> fv_data
+){
+ m_fv_data = fv_data;
+}
+
+ void
+BSP_CSGMesh::
+SetFaceData(
+ MEM_SmartPtr<BSP_CSGUserData> f_data
+) {
+ m_face_data = f_data;
+}
+
+
+ void
+BSP_CSGMesh::
+AddPolygon(
+ const int * verts,
+ int num_verts
+){
+ MT_assert(verts != NULL);
+ MT_assert(num_verts >=3);
+
+ if (verts == NULL || num_verts <3) return;
+
+ const int vertex_num = m_verts->size();
+
+ // make a polyscone from these vertex indices.
+
+ const BSP_FaceInd fi = m_faces->size();
+ m_faces->push_back(BSP_MFace());
+ BSP_MFace & face = m_faces->back();
+
+ insert_iterator<vector<BSP_VertexInd> > insert_point(face.m_verts,face.m_verts.end());
+ copy (verts,verts + num_verts,insert_point);
+
+ // compute and store the plane equation for this face.
+
+ MT_Plane3 face_plane = FacePlane(fi);
+ face.m_plane = face_plane;
+};
+
+ void
+BSP_CSGMesh::
+AddPolygon(
+ const int * verts,
+ const int * fv_indices,
+ int num_verts
+){
+ // This creates a new polygon on the end of the face list.
+ AddPolygon(verts,num_verts);
+
+ BSP_MFace & face = m_faces->back();
+ // now we just fill in the fv indices
+
+ if (fv_indices) {
+ insert_iterator<vector<BSP_UserFVInd> > insert_point(face.m_fv_data,face.m_fv_data.end());
+ copy(fv_indices,fv_indices + num_verts,insert_point);
+ } else {
+ face.m_fv_data.insert(face.m_fv_data.end(),num_verts,BSP_UserFVInd::Empty());
+ }
+}
+
+
+ void
+BSP_CSGMesh::
+AddSubTriangle(
+ const BSP_MFace &iface,
+ const int * index_info
+){
+ // This creates a new polygon on the end of the face list.
+
+ const BSP_FaceInd fi = m_faces->size();
+ m_faces->push_back(BSP_MFace());
+ BSP_MFace & face = m_faces->back();
+
+ face.m_verts.push_back(iface.m_verts[index_info[0]]);
+ face.m_verts.push_back(iface.m_verts[index_info[1]]);
+ face.m_verts.push_back(iface.m_verts[index_info[2]]);
+
+ face.m_fv_data.push_back(iface.m_fv_data[index_info[0]]);
+ face.m_fv_data.push_back(iface.m_fv_data[index_info[1]]);
+ face.m_fv_data.push_back(iface.m_fv_data[index_info[2]]);
+
+ face.m_plane = iface.m_plane;
+}
+
+
+// assumes that the face already has a plane equation
+ void
+BSP_CSGMesh::
+AddPolygon(
+ const BSP_MFace &face
+){
+ m_faces->push_back(face);
+};
+
+
+ bool
+BSP_CSGMesh::
+BuildEdges(
+){
+
+ if (m_faces == NULL) return false;
+
+ if (m_edges != NULL) {
+ DestroyEdges();
+ }
+
+ m_edges = new vector<BSP_MEdge>;
+
+ if (m_edges == NULL) {
+ return false;
+ }
+
+
+ //iterate through the face set and add edges for all polygon
+ //edges
+
+ vector<BSP_MFace>::const_iterator f_it_end = FaceSet().end();
+ vector<BSP_MFace>::const_iterator f_it_begin = FaceSet().begin();
+ vector<BSP_MFace>::iterator f_it = FaceSet().begin();
+
+ vector<BSP_MVertex> & vertex_set = VertexSet();
+
+ vector<BSP_EdgeInd> dummy;
+
+ for (;f_it != f_it_end; ++f_it) {
+
+ BSP_MFace & face = *f_it;
+
+ int vertex_num = face.m_verts.size();
+ BSP_VertexInd prev_vi(face.m_verts[vertex_num-1]);
+
+ for (int vert = 0; vert < vertex_num; ++vert) {
+
+ BSP_FaceInd fi(f_it - f_it_begin);
+ InsertEdge(prev_vi,face.m_verts[vert],fi,dummy);
+ prev_vi = face.m_verts[vert];
+ }
+
+ }
+ dummy.clear();
+ return true;
+}
+
+ void
+BSP_CSGMesh::
+DestroyEdges(
+){
+ m_edges.Delete();
+
+ // Run through the vertices
+ // and clear their edge arrays.
+
+ if (m_verts){
+
+ vector<BSP_MVertex>::const_iterator vertex_end = VertexSet().end();
+ vector<BSP_MVertex>::iterator vertex_it = VertexSet().begin();
+
+ for (; vertex_it != vertex_end; ++vertex_it) {
+ vertex_it->m_edges.clear();
+ }
+ }
+}
+
+
+ BSP_EdgeInd
+BSP_CSGMesh::
+FindEdge(
+ const BSP_VertexInd & v1,
+ const BSP_VertexInd & v2
+) const {
+
+ vector<BSP_MVertex> &verts = VertexSet();
+ vector<BSP_MEdge> &edges = EdgeSet();
+
+ BSP_MEdge e;
+ e.m_verts[0] = v1;
+ e.m_verts[1] = v2;
+
+ vector<BSP_EdgeInd> &v1_edges = verts[v1].m_edges;
+ vector<BSP_EdgeInd>::const_iterator v1_end = v1_edges.end();
+ vector<BSP_EdgeInd>::const_iterator v1_begin = v1_edges.begin();
+
+ for (; v1_begin != v1_end; ++v1_begin) {
+ if (edges[*v1_begin] == e) return *v1_begin;
+ }
+
+ return BSP_EdgeInd::Empty();
+}
+
+ void
+BSP_CSGMesh::
+InsertEdge(
+ const BSP_VertexInd & v1,
+ const BSP_VertexInd & v2,
+ const BSP_FaceInd & f,
+ vector<BSP_EdgeInd> &new_edges
+){
+
+ MT_assert(!v1.IsEmpty());
+ MT_assert(!v2.IsEmpty());
+ MT_assert(!f.IsEmpty());
+
+ if (v1.IsEmpty() || v2.IsEmpty() || f.IsEmpty()) {
+ BSP_CSGException e(e_mesh_error);
+ throw (e);
+ }
+
+ vector<BSP_MVertex> &verts = VertexSet();
+ vector<BSP_MEdge> &edges = EdgeSet();
+
+ BSP_EdgeInd e;
+
+ e = FindEdge(v1,v2);
+ if (e.IsEmpty()) {
+ // This edge does not exist -- make a new one
+
+ BSP_MEdge temp_e;
+ temp_e.m_verts[0] = v1;
+ temp_e.m_verts[1] = v2;
+
+ e = m_edges->size();
+ // set the face index from the edge back to this polygon.
+ temp_e.m_faces.push_back(f);
+
+ m_edges->push_back(temp_e);
+
+ // add the edge index to it's vertices
+ verts[v1].AddEdge(e);
+ verts[v2].AddEdge(e);
+
+ new_edges.push_back(e);
+
+ } else {
+
+ // edge already exists
+ // insure that there is no polygon already
+ // attached to the other side of this edge
+ // swap the empty face pointer in edge with f
+
+ BSP_MEdge &edge = edges[e];
+
+ // set the face index from the edge back to this polygon.
+ edge.m_faces.push_back(f);
+ }
+}
+
+
+// geometry access
+//////////////////
+
+ vector<BSP_MVertex> &
+BSP_CSGMesh::
+VertexSet(
+) const {
+ return m_verts.Ref();
+}
+
+ vector<BSP_MFace> &
+BSP_CSGMesh::
+FaceSet(
+) const {
+ return m_faces.Ref();
+}
+
+ vector<BSP_MEdge> &
+BSP_CSGMesh::
+EdgeSet(
+) const {
+ return m_edges.Ref();
+}
+
+ BSP_CSGUserData &
+BSP_CSGMesh::
+FaceVertexData(
+) const {
+ return m_fv_data.Ref();
+}
+
+ BSP_CSGUserData &
+BSP_CSGMesh::
+FaceData(
+) const {
+ return m_face_data.Ref();
+}
+
+
+BSP_CSGMesh::
+~BSP_CSGMesh(
+){
+ // member deletion handled by smart ptr;
+}
+
+// local geometry queries.
+/////////////////////////
+
+// face queries
+///////////////
+
+ void
+BSP_CSGMesh::
+FaceVertices(
+ const BSP_FaceInd & f,
+ vector<BSP_VertexInd> &output
+){
+ vector<BSP_MFace> & face_set = FaceSet();
+ output.insert(
+ output.end(),
+ face_set[f].m_verts.begin(),
+ face_set[f].m_verts.end()
+ );
+}
+
+
+ void
+BSP_CSGMesh::
+FaceEdges(
+ const BSP_FaceInd & fi,
+ vector<BSP_EdgeInd> &output
+){
+ // take intersection of the edges emminating from all the vertices
+ // of this polygon;
+
+ vector<BSP_MFace> &faces = FaceSet();
+ vector<BSP_MEdge> &edges = EdgeSet();
+
+ const BSP_MFace & f = faces[fi];
+
+ // collect vertex edges;
+
+ vector<BSP_VertexInd>::const_iterator face_verts_it = f.m_verts.begin();
+ vector<BSP_VertexInd>::const_iterator face_verts_end = f.m_verts.end();
+
+ vector< vector<BSP_EdgeInd> > vertex_edges(f.m_verts.size());
+
+ int vector_slot = 0;
+
+ for (;face_verts_it != face_verts_end; ++face_verts_it, ++vector_slot) {
+ VertexEdges(*face_verts_it,vertex_edges[vector_slot]);
+ }
+
+ int prev = vector_slot - 1;
+
+ // intersect pairs of edge sets
+
+ for (int i = 0; i < vector_slot;i++) {
+ CTR_TaggedSetOps<BSP_EdgeInd,BSP_MEdge>::IntersectPair(vertex_edges[prev],vertex_edges[i],edges,output);
+ prev = i;
+ }
+
+ // should always have 3 or more unique edges per face.
+ MT_assert(output.size() >=3);
+
+ if (output.size() < 3) {
+ BSP_CSGException e(e_mesh_error);
+ throw(e);
+ }
+};
+
+// edge queries
+///////////////
+
+ void
+BSP_CSGMesh::
+EdgeVertices(
+ const BSP_EdgeInd & e,
+ vector<BSP_VertexInd> &output
+){
+ const vector<BSP_MEdge> &edges = EdgeSet();
+ output.push_back(edges[e].m_verts[0]);
+ output.push_back(edges[e].m_verts[1]);
+}
+
+ void
+BSP_CSGMesh::
+EdgeFaces(
+ const BSP_EdgeInd & e,
+ vector<BSP_FaceInd> &output
+){
+
+ vector<BSP_MEdge> & edge_set = EdgeSet();
+ output.insert(
+ output.end(),
+ edge_set[e].m_faces.begin(),
+ edge_set[e].m_faces.end()
+ );
+
+}
+
+// vertex queries
+/////////////////
+
+ void
+BSP_CSGMesh::
+VertexEdges(
+ const BSP_VertexInd &v,
+ vector<BSP_EdgeInd> &output
+){
+
+ vector<BSP_MVertex> & vertex_set = VertexSet();
+ output.insert(
+ output.end(),
+ vertex_set[v].m_edges.begin(),
+ vertex_set[v].m_edges.end()
+ );
+}
+
+ void
+BSP_CSGMesh::
+VertexFaces(
+ const BSP_VertexInd &vi,
+ vector<BSP_FaceInd> &output
+) {
+
+ vector<BSP_MEdge> &edges = EdgeSet();
+ vector<BSP_MFace> &faces = FaceSet();
+ vector<BSP_MVertex> &verts = VertexSet();
+
+ const vector<BSP_EdgeInd> &v_edges = verts[vi].m_edges;
+ vector<BSP_EdgeInd>::const_iterator e_it = v_edges.begin();
+
+ for (; e_it != v_edges.end(); ++e_it) {
+
+ BSP_MEdge &e = edges[*e_it];
+
+ // iterate through the faces of this edge - push unselected
+ // edges to ouput and then select the edge
+
+ vector<BSP_FaceInd>::const_iterator e_faces_end = e.m_faces.end();
+ vector<BSP_FaceInd>::iterator e_faces_it = e.m_faces.begin();
+
+ for (;e_faces_it != e_faces_end; ++e_faces_it) {
+
+ if (!faces[*e_faces_it].SelectTag()) {
+ output.push_back(*e_faces_it);
+ faces[*e_faces_it].SetSelectTag(true);
+ }
+ }
+ }
+
+ // deselect selected faces.
+ vector<BSP_FaceInd>::iterator f_it = output.begin();
+
+ for (; f_it != output.end(); ++f_it) {
+ faces[*f_it].SetSelectTag(false);
+ }
+}
+
+ void
+BSP_CSGMesh::
+InsertVertexIntoFace(
+ BSP_MFace & face,
+ const BSP_VertexInd & v1,
+ const BSP_VertexInd & v2,
+ const BSP_VertexInd & vi,
+ CSG_InterpolateUserFaceVertexDataFunc fv_split_func,
+ MT_Scalar epsilon
+){
+ // We assume that the face vertex data indices
+ // are consistent with the vertex inidex data.
+
+ // look for v1
+ vector<BSP_VertexInd>::iterator result =
+ find(face.m_verts.begin(),face.m_verts.end(),v1);
+
+ MT_assert(result != face.m_verts.end());
+
+ BSP_CSGUserData & fv_data = m_fv_data.Ref();
+
+ // now we have to check on either side of the result for the
+ // other vertex
+
+ vector<BSP_VertexInd>::iterator prev = result - 1;
+ if (prev < face.m_verts.begin()) {
+ prev = face.m_verts.end() -1;
+ }
+ if (*prev == v2) {
+
+ // so result <=> v2 and prev <=> v1
+
+ // create space for new face vertex data
+
+ int vf_i = fv_data.Size();
+ fv_data.IncSize();
+
+ int vf_i2 = prev - face.m_verts.begin();
+ int vf_i1 = result - face.m_verts.begin();
+
+ (*fv_split_func)(
+ fv_data[int(face.m_fv_data[vf_i1])],
+ fv_data[int(face.m_fv_data[vf_i2])],
+ fv_data[vf_i],
+ epsilon
+ );
+
+ // insert vertex data index.
+ face.m_fv_data.insert(face.m_fv_data.begin() + vf_i1,vf_i);
+ face.m_verts.insert(result,vi);
+
+ return;
+ }
+
+ vector<BSP_VertexInd>::iterator next = result + 1;
+ if (next >= face.m_verts.end()) {
+ next = face.m_verts.begin();
+ }
+ if (*next == v2) {
+
+ // so result <=> v1 and next <=> v2
+
+ int vf_i = fv_data.Size();
+ fv_data.IncSize();
+
+ int vf_i2 = int(next - face.m_verts.begin());
+ int vf_i1 = int(result - face.m_verts.begin());
+
+ (*fv_split_func)(
+ fv_data[int(face.m_fv_data[vf_i1])],
+ fv_data[int(face.m_fv_data[vf_i2])],
+ fv_data[vf_i],
+ epsilon
+ );
+
+ // insert vertex data index.
+ face.m_fv_data.insert(face.m_fv_data.begin() + vf_i2,vf_i);
+ face.m_verts.insert(next,vi);
+
+ return;
+ }
+
+ // if we get here we are in trouble.
+ MT_assert(false);
+ BSP_CSGException e(e_mesh_error);
+ throw(e);
+}
+
+ void
+BSP_CSGMesh::
+SetBBox(
+ const MT_Vector3 & min,
+ const MT_Vector3 & max
+){
+ m_bbox_min = min;
+ m_bbox_max = max;
+}
+
+
+ void
+BSP_CSGMesh::
+BBox(
+ MT_Vector3 &min,
+ MT_Vector3 &max
+) const {
+ min = m_bbox_min;
+ max = m_bbox_max;
+}
+
+
+// Update the BBox
+//////////////////
+
+ void
+BSP_CSGMesh::
+UpdateBBox(
+){
+ // TODO
+};
+
+ void
+BSP_CSGMesh::
+SC_Classification(
+ BSP_FaceInd f,
+ const MT_Plane3& plane
+){
+ const BSP_MFace & face = FaceSet()[f];
+
+ vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin();
+ vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end();
+
+ for (;f_verts_it != f_verts_end; ++f_verts_it) {
+
+ const BSP_MVertex & vert = VertexSet()[*f_verts_it];
+
+ MT_Scalar dist = plane.signedDistance(
+ vert.m_pos
+ );
+
+ if (fabs(dist) <= BSP_SPLIT_EPSILON ){
+ MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_on);
+ } else
+ if (dist > BSP_SPLIT_EPSILON) {
+ MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_out);
+ } else
+ if (dist < BSP_SPLIT_EPSILON) {
+ MT_assert(BSP_Classification(vert.OpenTag()) == e_classified_in);
+ }
+ }
+}
+
+
+ bool
+BSP_CSGMesh::
+SC_Face(
+ BSP_FaceInd f
+){
+
+
+
+#if 0
+ {
+ // check area is greater than zero.
+
+ vector<BSP_MVertex> & verts = VertexSet();
+
+ vector<BSP_VertexInd> f_verts;
+ FaceVertices(f,f_verts);
+
+ MT_assert(f_verts.size() >= 3);
+
+ BSP_VertexInd root = f_verts[0];
+
+ MT_Scalar area = 0;
+
+ for (int i=2; i < f_verts.size(); i++) {
+ MT_Vector3 a = verts[root].m_pos;
+ MT_Vector3 b = verts[f_verts[i-1]].m_pos;
+ MT_Vector3 c = verts[f_verts[i]].m_pos;
+
+ MT_Vector3 l1 = b-a;
+ MT_Vector3 l2 = c-b;
+
+ area += (l1.cross(l2)).length()/2;
+ }
+
+ MT_assert(!MT_fuzzyZero(area));
+ }
+#endif
+ // Check coplanarity
+#if 0
+ MT_Plane3 plane = FacePlane(f);
+
+ const BSP_MFace & face = FaceSet()[f];
+ vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin();
+ vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end();
+
+ for (;f_verts_it != f_verts_end; ++f_verts_it) {
+ MT_Scalar dist = plane.signedDistance(
+ VertexSet()[*f_verts_it].m_pos
+ );
+
+ MT_assert(fabs(dist) < BSP_SPLIT_EPSILON);
+ }
+#endif
+
+
+ // Check connectivity
+
+ vector<BSP_EdgeInd> f_edges;
+ FaceEdges(f,f_edges);
+
+ MT_assert(f_edges.size() == FaceSet()[f].m_verts.size());
+
+ unsigned int i;
+ for (i = 0; i < f_edges.size(); ++i) {
+
+ int matches = 0;
+ for (unsigned int j = 0; j < EdgeSet()[f_edges[i]].m_faces.size(); j++) {
+
+ if (EdgeSet()[f_edges[i]].m_faces[j] == f) matches++;
+ }
+
+ MT_assert(matches == 1);
+
+ }
+ return true;
+}
+
+ MT_Plane3
+BSP_CSGMesh::
+FacePlane(
+ const BSP_FaceInd & fi
+) const{
+
+ const BSP_MFace & f0 = FaceSet()[fi];
+
+ // Have to be a bit careful here coz the poly may have
+ // a lot of parallel edges. Should walk round the polygon
+ // and check length of cross product.
+
+ const MT_Vector3 & p1 = VertexSet()[f0.m_verts[0]].m_pos;
+ const MT_Vector3 & p2 = VertexSet()[f0.m_verts[1]].m_pos;
+
+ int face_size = f0.m_verts.size();
+ MT_Vector3 n;
+
+ for (int i = 2 ; i <face_size; i++) {
+ const MT_Vector3 & pi = VertexSet()[f0.m_verts[i]].m_pos;
+
+ MT_Vector3 l1 = p2-p1;
+ MT_Vector3 l2 = pi-p2;
+ n = l1.cross(l2);
+ MT_Scalar length = n.length();
+
+ if (!MT_fuzzyZero(length)) {
+ n = n * (1/length);
+ break;
+ }
+ }
+ return MT_Plane3(n,p1);
+}
+
+ void
+BSP_CSGMesh::
+ComputeFacePlanes(
+){
+
+ int fsize = FaceSet().size();
+ int i=0;
+ for (i = 0; i < fsize; i++) {
+
+ FaceSet()[i].m_plane = FacePlane(i);
+ }
+};
+
+
+ int
+BSP_CSGMesh::
+CountTriangles(
+) const {
+
+ // Each polygon of n sides can be partitioned into n-3 triangles.
+ // So we just go through and sum this function of polygon size.
+
+ vector<BSP_MFace> & face_set = FaceSet();
+
+ vector<BSP_MFace>::const_iterator face_it = face_set.begin();
+ vector<BSP_MFace>::const_iterator face_end = face_set.end();
+
+ int sum = 0;
+
+ for (;face_it != face_end; face_it++) {
+
+ // Should be careful about degenerate faces here.
+ sum += face_it->m_verts.size() - 2;
+ }
+
+ return sum;
+}
+
+
+
diff --git a/intern/bsp/intern/BSP_CSGMesh.h b/intern/bsp/intern/BSP_CSGMesh.h
new file mode 100755
index 00000000000..1b56ca7a3e5
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMesh.h
@@ -0,0 +1,345 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_BSP_CSGMesh_h
+
+#define NAN_INCLUDED_BSP_CSGMesh_h
+
+#include "BSP_MeshPrimitives.h"
+#include "MEM_SmartPtr.h"
+#include "MEM_RefCountPtr.h"
+#include "MEM_NonCopyable.h"
+#include "BSP_CSGUserData.h"
+#include "../extern/CSG_BooleanOps.h"
+
+
+class MT_Plane3;
+class BSP_MeshFragment;
+
+class BSP_CSGMesh :
+ public MEM_NonCopyable,
+ public MEM_RefCountable
+{
+
+public :
+
+ static
+ BSP_CSGMesh *
+ New(
+ );
+
+ bool
+ SetVertices(
+ MEM_SmartPtr<std::vector<BSP_MVertex> > verts
+ );
+
+ void
+ SetFaceVertexData(
+ MEM_SmartPtr<BSP_CSGUserData> fv_data
+ );
+
+ void
+ SetFaceData(
+ MEM_SmartPtr<BSP_CSGUserData> f_data
+ );
+
+ void
+ AddPolygon(
+ const int * verts,
+ int num_verts
+ );
+
+ void
+ AddPolygon(
+ const int * verts,
+ const int * fv_indices,
+ int num_verts
+ );
+
+ void
+ AddSubTriangle(
+ const BSP_MFace &iface,
+ const int * index_info
+ );
+
+ // assumes that the face already has a plane equation
+ void
+ AddPolygon(
+ const BSP_MFace &face
+ );
+
+
+ // Allocate and build the mesh edges.
+ ////////////////////////////////////
+
+ bool
+ BuildEdges(
+ );
+
+ // Clean the mesh of edges. and edge pointers
+ // This removes the circular connectivity information
+ /////////////////////////////////////////////
+
+ void
+ DestroyEdges(
+ );
+
+ // return a new seperate copy of the
+ // mesh allocated on the heap.
+
+ BSP_CSGMesh *
+ NewCopy(
+ ) const;
+
+
+ // Reverse the winding order of every polygon
+ // in the mesh and swap the planes around.
+
+ void
+ Invert(
+ );
+
+
+ // geometry access
+ //////////////////
+
+ std::vector<BSP_MVertex> &
+ VertexSet(
+ ) const ;
+
+ std::vector<BSP_MFace> &
+ FaceSet(
+ ) const ;
+
+ std::vector<BSP_MEdge> &
+ EdgeSet(
+ ) const;
+
+ BSP_CSGUserData &
+ FaceVertexData(
+ ) const;
+
+ BSP_CSGUserData &
+ FaceData(
+ ) const;
+
+ ~BSP_CSGMesh(
+ );
+
+ // local geometry queries.
+ /////////////////////////
+
+ // face queries
+ ///////////////
+
+ void
+ FaceVertices(
+ const BSP_FaceInd & f,
+ std::vector<BSP_VertexInd> &output
+ );
+
+ void
+ FaceEdges(
+ const BSP_FaceInd & f,
+ std::vector<BSP_EdgeInd> &output
+ );
+
+ // edge queries
+ ///////////////
+
+ void
+ EdgeVertices(
+ const BSP_EdgeInd & e,
+ std::vector<BSP_VertexInd> &output
+ );
+
+ void
+ EdgeFaces(
+ const BSP_EdgeInd & e,
+ std::vector<BSP_FaceInd> &output
+ );
+
+ // vertex queries
+ /////////////////
+
+ void
+ VertexEdges(
+ const BSP_VertexInd & v,
+ std::vector<BSP_EdgeInd> &output
+ );
+
+ void
+ VertexFaces(
+ const BSP_VertexInd & v,
+ std::vector<BSP_FaceInd> &output
+ );
+
+ // Returns the edge index of the edge from v1 to v2.
+ // Does this by searching the edge sets of v1 - but not v2.
+ // If you are paranoid you should check both and make sure the
+ // indices are the same. If the edge doe not exist edgeInd is empty.
+
+ BSP_EdgeInd
+ FindEdge(
+ const BSP_VertexInd &v1,
+ const BSP_VertexInd &v2
+ ) const;
+
+
+ // Bounding box methods
+ ///////////////////////
+
+ void
+ SetBBox(
+ const MT_Vector3 & min,
+ const MT_Vector3 & max
+ );
+
+ void
+ BBox(
+ MT_Vector3 &min,
+ MT_Vector3 &max
+ ) const ;
+
+ // Update the BBox
+ //////////////////
+
+ void
+ UpdateBBox(
+ );
+
+
+ /**
+ * Sanity checkers
+ */
+
+ // make sure the edge faces have a pointer to f
+
+ bool
+ SC_Face(
+ BSP_FaceInd f
+ );
+
+ /**
+ * Make sure the polygons vertex classification is correct
+ */
+
+ void
+ SC_Classification(
+ BSP_FaceInd f,
+ const MT_Plane3&plane
+ );
+
+ /**
+ * Return the face plane equation
+ */
+
+ MT_Plane3
+ FacePlane(
+ const BSP_FaceInd &fi
+ )const;
+
+
+ /**
+ * Recompute Face plane equations.
+ * essential if you have been messing with the object.
+ */
+
+ void
+ ComputeFacePlanes(
+ );
+
+ /**
+ * Count the number of trinagles in the mesh.
+ * This is not the same as the number of polygons.
+ */
+
+ int
+ CountTriangles(
+ ) const;
+
+ /**
+ * Insert a vertex index into a polygon
+ * and call the external splitting function to
+ * generate a new face vertex property.
+ */
+
+ void
+ InsertVertexIntoFace(
+ BSP_MFace & face,
+ const BSP_VertexInd & v1,
+ const BSP_VertexInd & v2,
+ const BSP_VertexInd & vi,
+ CSG_InterpolateUserFaceVertexDataFunc fv_split_func,
+ MT_Scalar epsilon
+ );
+
+
+private :
+
+ void
+ InsertEdge(
+ const BSP_VertexInd &v1,
+ const BSP_VertexInd &v2,
+ const BSP_FaceInd &f,
+ std::vector<BSP_EdgeInd> &new_edges
+ );
+
+
+ // Private to insure heap instantiation.
+
+ BSP_CSGMesh(
+ );
+
+
+ MEM_SmartPtr< std::vector<BSP_MVertex> > m_verts;
+ MEM_SmartPtr< std::vector<BSP_MFace> > m_faces;
+ MEM_SmartPtr< std::vector<BSP_MEdge> > m_edges;
+
+ // The face_vertex user data associated with this mesh
+
+ MEM_SmartPtr<BSP_CSGUserData> m_fv_data;
+
+ // The face user data associated with this mesh -
+ // This is a buffer that maps directly to the face buffer.
+ // An index into the faces is alos an index into m_face_data
+ // for that face
+
+ MEM_SmartPtr<BSP_CSGUserData> m_face_data;
+
+
+ MT_Vector3 m_bbox_min;
+ MT_Vector3 m_bbox_max;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.cpp b/intern/bsp/intern/BSP_CSGMeshBuilder.cpp
new file mode 100755
index 00000000000..cbe4bfc920d
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMeshBuilder.cpp
@@ -0,0 +1,152 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGMeshBuilder.h"
+
+
+using namespace std;
+
+ MEM_SmartPtr<BSP_CSGMesh>
+BSP_CSGMeshBuilder::
+NewMesh(
+ CSG_MeshPropertyDescriptor &props,
+ CSG_FaceIteratorDescriptor &face_it,
+ CSG_VertexIteratorDescriptor &vertex_it
+) {
+
+ MEM_SmartPtr<BSP_CSGMesh> mesh = BSP_CSGMesh::New();
+ if (mesh == NULL) return NULL;
+
+ MEM_SmartPtr<BSP_CSGUserData> fv_data = new BSP_CSGUserData(props.user_face_vertex_data_size);
+ MEM_SmartPtr<BSP_CSGUserData> face_data = new BSP_CSGUserData(props.user_data_size);
+
+
+ MEM_SmartPtr<vector<BSP_MVertex> > vertices(new vector<BSP_MVertex>);
+ if (vertices == NULL || fv_data == NULL || face_data == NULL) return NULL;
+
+ // The size of the vertex data array will be at least the number of faces.
+
+ fv_data->Reserve(face_it.num_elements);
+ face_data->Reserve(face_it.num_elements);
+
+ vertices->reserve(vertex_it.num_elements);
+
+ CSG_IVertex vertex;
+
+ while (!vertex_it.Done(vertex_it.it)) {
+ vertex_it.Fill(vertex_it.it,&vertex);
+
+ MT_Point3 pos(vertex.position);
+ vertices->push_back(BSP_MVertex(pos));
+
+ vertex_it.Step(vertex_it.it);
+ }
+
+ // pass ownership of the vertices to the mesh.
+ mesh->SetVertices(vertices);
+
+ // now for the polygons.
+
+ CSG_IFace face;
+ // we may need to decalare some memory for user defined face properties.
+
+ if (props.user_data_size) {
+ face.user_face_data = new char[props.user_data_size];
+ } else {
+ face.user_face_data = NULL;
+ }
+
+ if (props.user_face_vertex_data_size) {
+ char * fv_data = NULL;
+ fv_data = new char[4 * props.user_face_vertex_data_size];
+
+ face.user_face_vertex_data[0] = fv_data;
+ face.user_face_vertex_data[1] = fv_data + props.user_face_vertex_data_size;
+ face.user_face_vertex_data[2] = fv_data + 2*props.user_face_vertex_data_size;
+ face.user_face_vertex_data[3] = fv_data + 3*props.user_face_vertex_data_size;
+ } else {
+ face.user_face_vertex_data[0] = NULL;
+ face.user_face_vertex_data[1] = NULL;
+ face.user_face_vertex_data[2] = NULL;
+ face.user_face_vertex_data[3] = NULL;
+ }
+
+
+ int tri_index[3];
+ int fv_index[3];
+
+ while (!face_it.Done(face_it.it)) {
+ face_it.Fill(face_it.it,&face);
+
+ // Let's not rely on quads being coplanar - especially if they
+ // are coming out of that soup of code from blender...
+ if (face.vertex_number == 4) {
+ tri_index[0] = face.vertex_index[2];
+ tri_index[1] = face.vertex_index[3];
+ tri_index[2] = face.vertex_index[0];
+
+ fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[2]);
+ fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[3]);
+ fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[0]);
+
+ mesh->AddPolygon(tri_index,fv_index,3);
+
+ // bit of an unspoken relationship between mesh face buffer
+ // and the face data which I guess should be changed.
+ face_data->Duplicate(face.user_face_data);
+
+ }
+
+ fv_index[0] = fv_data->Duplicate(face.user_face_vertex_data[0]);
+ fv_index[1] = fv_data->Duplicate(face.user_face_vertex_data[1]);
+ fv_index[2] = fv_data->Duplicate(face.user_face_vertex_data[2]);
+
+ mesh->AddPolygon(face.vertex_index,fv_index,3);
+ // bit of an unspoken relationship between mesh face buffer
+ // and the face data which I guess should be changed.
+ face_data->Duplicate(face.user_face_data);
+
+
+ face_it.Step(face_it.it);
+ }
+
+ // give the user face vertex data over to the mesh.
+
+ mesh->SetFaceVertexData(fv_data);
+ mesh->SetFaceData(face_data);
+
+ // that's it
+
+ delete[] static_cast<char *>(face.user_face_data);
+ delete[] static_cast<char *>(face.user_face_vertex_data[0]);
+ return mesh;
+}
+
diff --git a/intern/bsp/intern/BSP_CSGMeshBuilder.h b/intern/bsp/intern/BSP_CSGMeshBuilder.h
new file mode 100755
index 00000000000..b79b65ba55b
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMeshBuilder.h
@@ -0,0 +1,74 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGMeshBuilder_h
+
+#define BSP_CSGMeshBuilder_h
+
+#include "../extern/CSG_BooleanOps.h"
+#include "BSP_CSGMesh.h"
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+/**
+ * This class helps you to build a mesh from 2 seperate vertex/face
+ * iterators defined in the external interface of the bsp module.
+ * This code should really become party of a generic C++ mesh interface
+ * but later...
+ */
+
+class BSP_CSGMeshBuilder : public MEM_NonCopyable{
+
+public :
+
+ /**
+ * Return a new BSP_CSGMesh with the desired props
+ * built from the given face and vertex iterators.
+ * The iterators are exhausted by this action.
+ */
+
+ static
+ MEM_SmartPtr<BSP_CSGMesh>
+ NewMesh(
+ CSG_MeshPropertyDescriptor &props,
+ CSG_FaceIteratorDescriptor &face_it,
+ CSG_VertexIteratorDescriptor &vertex_it
+ );
+
+private :
+
+ BSP_CSGMeshBuilder(
+ );
+
+};
+
+
+#endif
diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGMeshSplitter.cpp
new file mode 100755
index 00000000000..eac926085ef
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMeshSplitter.cpp
@@ -0,0 +1,715 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGMeshSplitter.h"
+
+#include "BSP_CSGMesh.h"
+#include "BSP_MeshFragment.h"
+#include "BSP_CSGException.h"
+#include "MT_MinMax.h"
+#include "MT_assert.h"
+
+using namespace std;
+
+
+BSP_CSGMeshSplitter::
+BSP_CSGMeshSplitter(
+ CSG_InterpolateUserFaceVertexDataFunc fv_split_func
+) : m_fv_func(fv_split_func)
+{
+ // nothing to do
+};
+
+ void
+BSP_CSGMeshSplitter::
+Split(
+ const MT_Plane3& plane,
+ BSP_MeshFragment *frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+){
+ // First classify the vertices and the polygons of the
+ // incoming fragment.
+ frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts);
+
+ SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts);
+
+ m_spanning_faces.clear();
+ m_tagged_verts.clear();
+
+}
+
+ void
+BSP_CSGMeshSplitter::
+Split(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+){
+ BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts);
+
+ SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts);
+ m_spanning_faces.clear();
+ m_tagged_verts.clear();
+}
+
+BSP_CSGMeshSplitter::
+~BSP_CSGMeshSplitter(
+){
+ // nothing to do
+}
+
+ void
+BSP_CSGMeshSplitter::
+SplitImp(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ const std::vector<BSP_FaceInd> & spanning_faces,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ std::vector<BSP_VertexInd> & classified_verts
+){
+ // Assumes you have already classified the vertices.
+ // and generated a set of spanning faces.
+
+ vector<BSP_MEdge> & edge_set = mesh.EdgeSet();
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ // Now identify the spanning edges.
+ // These can be computed in many ways but probably the most
+ // efficient is to select all edges from the vertices of the
+ // spanning polygons that cross the plane.
+
+ vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end();
+ vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin();
+
+ for (;sface_it != sface_end; ++sface_it) {
+
+ BSP_MFace & sface = face_set[*sface_it];
+
+ vector<BSP_VertexInd>::const_iterator sf_vert_end = sface.m_verts.end();
+ vector<BSP_VertexInd>::iterator sf_vert_it = sface.m_verts.begin();
+
+ for (;sf_vert_it != sf_vert_end; ++sf_vert_it) {
+ BSP_MVertex & vert = vertex_set[*sf_vert_it];
+
+ if (!vert.SelectTag()) {
+ // what classification does this vertex have?
+
+ BSP_Classification root_vert_class = BSP_Classification(vert.OpenTag());
+
+ // we are only interested in edges whose vertices are in and out.
+ if (root_vert_class != e_classified_on) {
+
+ BSP_Classification opp_class = e_classified_out;
+ if (root_vert_class == e_classified_out) {
+ opp_class = e_classified_in;
+ }
+ // we haven't visited this vertex before so lets
+ // analyse it's edges.
+
+ vector<BSP_EdgeInd>::const_iterator v_edge_end = vert.m_edges.end();
+ vector<BSP_EdgeInd>::iterator v_edge_it = vert.m_edges.begin();
+
+ for (; v_edge_it != v_edge_end; ++v_edge_it) {
+ BSP_MEdge & edge = edge_set[*v_edge_it];
+
+ if (!edge.SelectTag()) {
+ // we haven't visited this edge before so check it's
+ // end points
+
+ // we know that a spanning polygon can have at most
+ // 2 on vertices (even at this point where we haven't
+ // yet split the edge!) We are interested in edges whose
+ // vertices are in and out the plane.
+
+ BSP_VertexInd opp_vi = edge.OpVertex(*sf_vert_it);
+ if (vertex_set[opp_vi].OpenTag() == opp_class) {
+ // we have found an edge !!!!
+ m_spanning_edges.push_back(*v_edge_it);
+ }
+ edge.SetSelectTag(true);
+ m_visited_edges.push_back(*v_edge_it);
+ }
+ }
+ }
+
+ vert.SetSelectTag(true);
+ m_visited_verts.push_back(*sf_vert_it);
+ }
+ }
+ }
+
+ // clear the tags we used in the above
+
+ unsigned int i;
+
+ for (i = 0; i < m_visited_edges.size(); ++i) {
+ edge_set[m_visited_edges[i]].SetSelectTag(false);
+ }
+ for (i=0;i < m_visited_verts.size(); ++i) {
+ vertex_set[m_visited_verts[i]].SetSelectTag(false);
+ }
+ for (i=0; i < m_spanning_faces.size(); ++i) {
+ face_set[m_spanning_faces[i]].SetSelectTag(false);
+ }
+
+ // The spanning edge set constains unique edges. Next we run
+ // through the edge set and compute the intersection with the
+ // plane --- the edge is guarenteed not to be parallel to the plane!
+ // we then split the edge with the new vertex.
+
+ // We identify the polygons affected by the split
+
+ vector<BSP_EdgeInd>::const_iterator s_edge_end = m_spanning_edges.end();
+ vector<BSP_EdgeInd>::iterator s_edge_it = m_spanning_edges.begin();
+
+ for (;s_edge_it != s_edge_end; ++s_edge_it) {
+
+ const BSP_MEdge & edge = edge_set[*s_edge_it];
+
+ const BSP_MVertex &v1 = vertex_set[edge.m_verts[0]];
+ const BSP_MVertex &v2 = vertex_set[edge.m_verts[1]];
+
+ const MT_Vector3 & ptA = v1.m_pos;
+ const MT_Vector3 & ptB = v2.m_pos;
+
+ // compute the intersection point of plane and ptA->ptB
+ MT_Vector3 v = ptB - ptA;
+ MT_Scalar sideA = plane.signedDistance(ptA);
+
+ MT_Scalar epsilon = -sideA/plane.Normal().dot(v);
+ MT_Vector3 new_p = ptA + (v * epsilon);
+
+ // so new_p is the intersection of the plane and the edge.
+ // split the edge at new_p
+
+ BSP_MVertex new_vert;
+ new_vert.m_pos = new_p;
+
+ BSP_VertexInd new_vi = SplitEdge(mesh,*s_edge_it,new_vert,epsilon);
+
+ // tag the new vertex as 'on' the plane - we use this information
+ // to split the affected polygons below.
+ vertex_set[new_vi].SetOpenTag(e_classified_on);
+
+ // We add it to the tagged verts so we can remove the tag later.
+ classified_verts.push_back(new_vi);
+ }
+
+ // We start with the spanning polygons...
+ // not forgetting to add the new polygon fragments to the correct fragment bins.
+
+ sface_end = m_spanning_faces.end();
+ sface_it = m_spanning_faces.begin();
+
+ for (;sface_it != sface_end; ++sface_it) {
+
+ BSP_FaceInd f_in,f_out;
+
+ SplitPolygon(mesh,*sface_it,f_in,f_out);
+ in_frag->FaceSet().push_back(f_in);
+ out_frag->FaceSet().push_back(f_out);
+ }
+
+ // Finally we have to clean up the vertex tags we set on all the vertices
+ // There will be some overlap between the vertex sets, so this operation
+ // is a tiny bit inefficient.
+
+ vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end();
+ vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin();
+
+ for (; v_it != v_end; ++v_it) {
+ vertex_set[*v_it].SetOpenTag(e_unclassified);
+ }
+
+ // tidy up the cached arrays.
+
+ m_spanning_edges.clear();
+ m_visited_edges.clear();
+ m_visited_verts.clear();
+
+
+ // le fin.
+
+}
+
+
+ BSP_VertexInd
+BSP_CSGMeshSplitter::
+SplitEdge(
+ BSP_CSGMesh & mesh,
+ BSP_EdgeInd ei,
+ BSP_MVertex &vertex,
+ MT_Scalar epsilon
+){
+ vector<BSP_MEdge> & edge_set = mesh.EdgeSet();
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ MT_assert(edge_set.size() > (unsigned int)(ei));
+
+ if (edge_set.size() <= (unsigned int)(ei)) {
+ BSP_CSGException e(e_param_error);
+ throw(e);
+ }
+
+ // push the vertex onto the vertex array
+ BSP_VertexInd new_vi = vertex_set.size();
+ vertex_set.push_back(vertex);
+ BSP_MVertex & new_v = vertex_set[new_vi];
+
+ // copy the edge because the new edge will have
+ // exactly the same face set.
+
+ BSP_EdgeInd new_ei = edge_set.size();
+
+ // Note never use set.push_back(set[i])
+ // coz push_back excepts a reference which may become
+ // invalid if the set is resized
+
+ edge_set.push_back(BSP_MEdge());
+ edge_set[new_ei] = edge_set[ei];
+ BSP_MEdge & new_e = edge_set[new_ei];
+
+ BSP_MEdge &e = edge_set[ei];
+
+ // get the edge vertices.
+ BSP_MVertex & e_v2 = vertex_set[e.m_verts[1]];
+
+ // Remove the split edge from vertex 2.
+ // Let's hope that the vertex isn't using this edge for
+ // its' open tag!!
+
+ BSP_Classification v2_class = BSP_Classification(e_v2.OpenTag());
+
+ e_v2.RemoveEdge(ei);
+
+ // add the split edge to the new vertex.
+ new_v.AddEdge(ei);
+
+ // add the new edge to the new vertex.
+ new_v.AddEdge(new_ei);
+
+ // add the new edge to vertex 2
+ e_v2.AddEdge(new_ei);
+
+ // Reset the tags for modified vertex.
+
+ e_v2.SetOpenTag(v2_class);
+
+
+ // Replace the old vertex indices in the new edge.
+ new_e.m_verts[0] = new_vi;
+ e.m_verts[1] = new_vi;
+
+ // Finally add the vertex in the correct position to the
+ // neighbouring polygons.
+
+ vector<BSP_FaceInd>::iterator neighbour_face_it = e.m_faces.begin();
+ vector<BSP_FaceInd>::const_iterator neighbour_face_end = e.m_faces.end();
+
+ for (; neighbour_face_it != neighbour_face_end; ++neighbour_face_it) {
+
+ mesh.InsertVertexIntoFace(
+ face_set[*neighbour_face_it],
+ new_e.m_verts[1],
+ e.m_verts[0],
+ new_vi,
+ m_fv_func,
+ epsilon
+ );
+ }
+
+ // That should be it (cough)
+ return new_vi;
+
+}
+
+ void
+BSP_CSGMeshSplitter::
+SplitPolygon(
+ BSP_CSGMesh & mesh,
+ BSP_FaceInd fi,
+ BSP_FaceInd &fin,
+ BSP_FaceInd &fout
+){
+ vector<BSP_MEdge> & edge_set = mesh.EdgeSet();
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ MT_assert(face_set.size() > (unsigned int)(fi));
+ if (face_set.size() <= (unsigned int)(fi)) {
+ BSP_CSGException e(e_param_error);
+ throw(e);
+ }
+
+ BSP_MFace & face = face_set[fi];
+
+ // Walk throught the vertices of this polygon.
+ // generate inside and outside loops.
+
+ vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end();
+ vector<BSP_VertexInd>::iterator f_verts_it = face.m_verts.begin();
+
+ vector<BSP_UserFVInd>::const_iterator f_fv_data_it = face.m_fv_data.begin();
+
+ // NOTE we don't actually duplicate fv data for this face
+ // we just duplicate the indices, so both on vertices
+ // will share the fv data.
+
+ for (;f_verts_it != f_verts_end; ++f_verts_it, ++f_fv_data_it) {
+
+ BSP_MVertex & vert = vertex_set[*f_verts_it];
+ BSP_Classification v_class = BSP_Classification(vert.OpenTag());
+
+ if (v_class == e_classified_in) {
+ m_in_loop.push_back(*f_verts_it);
+ m_fv_in_loop.push_back(*f_fv_data_it);
+ } else
+ if (v_class == e_classified_out) {
+ m_out_loop.push_back(*f_verts_it);
+ m_fv_out_loop.push_back(*f_fv_data_it);
+
+ } else
+ if (v_class == e_classified_on) {
+ m_in_loop.push_back(*f_verts_it);
+ m_out_loop.push_back(*f_verts_it);
+ m_on_loop.push_back(*f_verts_it);
+ m_fv_in_loop.push_back(*f_fv_data_it);
+ m_fv_out_loop.push_back(*f_fv_data_it);
+ } else {
+ // The vertex is unclassified this is an error!
+ MT_assert(false);
+ BSP_CSGException e(e_split_error);
+ throw(e);
+ }
+ }
+
+ if ((m_in_loop.size() == 1) || (m_out_loop.size() == 1)) {
+ // Then there was only 1 tagged vertex I guess this is fine
+ // but should be reviewed!
+
+ // NOT fine - we only ever split spanning polygons.
+ MT_assert(false);
+ BSP_CSGException e(e_split_error);
+ throw(e);
+ }
+
+ MT_assert(m_in_loop.size() >=3 && m_out_loop.size() >=3 && m_on_loop.size() == 2);
+
+ if (m_in_loop.size() <3 || m_out_loop.size() <3 || m_on_loop.size() !=2) {
+ BSP_CSGException e(e_split_error);
+ throw(e);
+ }
+ // Now we have 2 seperate vertex loops representing the polygon
+ // halves.
+
+ // create a new polygon for the out_loop of vertices.
+ ////////////////////////////////////////////////////
+
+ // Duplicate face data.
+
+ mesh.FaceData().Duplicate(fi);
+
+ BSP_FaceInd new_fi = face_set.size();
+ face_set.push_back(BSP_MFace());
+ BSP_MFace & new_f = face_set[new_fi];
+
+ // assign plane equation for new face - this is the same as the
+ // original of course.
+
+ new_f.m_plane = face_set[fi].m_plane;
+
+ // note that face may have become invalid because we just been adding
+ // more polygons to the array. We can't assign a new reference to the old
+ // invlaid one! It will call try and call the assignment operator on
+ // the original face!!!! The joys of references! We just use face_set[fi]
+ // from now on to be safe
+
+ // We need to insert an edge between m_on_loop[0] and m_on_loop[1]
+
+ // Make sure the edge does not already exist between these 2 vertices!
+ // This can happen if the original mesh has duplicate polygons.
+ // We still wire up the new polygons to this edge, which will
+ // lead to duplicate polygons in the output -- but algorithm
+ // should still work.
+ BSP_EdgeInd new_ei = mesh.FindEdge(m_on_loop[0],m_on_loop[1]);
+
+ if (new_ei.IsEmpty()) {
+
+ // create a new edge.
+
+ new_ei = edge_set.size();
+ edge_set.push_back(BSP_MEdge());
+ BSP_MEdge & new_e = edge_set[new_ei];
+
+ new_e.m_verts[0] = m_on_loop[0];
+ new_e.m_verts[1] = m_on_loop[1];
+
+ // Now tie the edge to it's vertices.
+
+ vertex_set[m_on_loop[0]].AddEdge(new_ei);
+ vertex_set[m_on_loop[1]].AddEdge(new_ei);
+ }
+
+ edge_set[new_ei].m_faces.push_back(fi);
+ // This next line is a trick we are going to replace it in a moment
+ // with new_fi. It means that all the edges of the new polygon have
+ // pointers to the old polygon which we can replace.
+ edge_set[new_ei].m_faces.push_back(fi);
+
+
+ // Replace the old polygons vertex loop with the in_loop of vertices.
+
+ face_set[fi].m_verts = m_in_loop;
+ new_f.m_verts = m_out_loop;
+
+ // Replace the olf fv loops.
+ face_set[fi].m_fv_data = m_fv_in_loop;
+ new_f.m_fv_data = m_fv_out_loop;
+
+
+ // That should be it for the old polygon;
+ // For the new polygon we just need to iterate around it's
+ // edges and replace pointers to the old polygon with pointers
+ // to the new one.
+
+ f_verts_end = new_f.m_verts.end();
+ f_verts_it = new_f.m_verts.begin();
+
+ BSP_VertexInd prev = new_f.m_verts.back();
+
+ for (;f_verts_it != f_verts_end; ++f_verts_it) {
+ BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it);
+
+ MT_assert(!new_f_ei.IsEmpty());
+
+ if (new_f_ei.IsEmpty()) {
+ BSP_CSGException e(e_split_error);
+ throw(e);
+ }
+
+ edge_set[new_f_ei].SwapFace(fi,new_fi);
+ prev = *f_verts_it;
+
+ }
+
+ // That should be everything.
+
+ fin = fi;
+ fout = new_fi;
+
+ // clear up cached helpers.
+ m_in_loop.clear();
+ m_on_loop.clear();
+ m_out_loop.clear();
+
+ m_fv_in_loop.clear();
+ m_fv_out_loop.clear();
+
+}
+
+ BSP_FaceInd
+BSP_CSGMeshSplitter::
+TriangulateConvexQuad(
+ BSP_CSGMesh & mesh,
+ const BSP_FaceInd fi
+){
+
+ // we assume that the fi points to a face with
+ // exactly 4 vertices.
+
+
+ // We are definately going to create a new face
+ // so lets make space for it in the face array.
+
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MEdge> & edge_set = mesh.EdgeSet();
+
+ if (face_set[fi].m_verts.size() == 3) {
+ return BSP_FaceInd::Empty();
+ }
+
+ // duplicate face data
+ mesh.FaceData().Duplicate(fi);
+
+ const BSP_FaceInd new_fi = face_set.size();
+ face_set.push_back(BSP_MFace());
+ BSP_MFace & new_face = face_set[new_fi];
+ BSP_MFace & face = face_set[fi];
+
+ new_face.m_plane = face.m_plane;
+
+ // The internal edges are [0,2] and [1,3]
+ // these split the quad into the triangles
+ // [0,1,2],[2,3,0] and [0,1,3],[1,2,3] respectively
+
+ const MT_Point3 & p0 = vertex_set[face.m_verts[0]].m_pos;
+ const MT_Point3 & p1 = vertex_set[face.m_verts[1]].m_pos;
+ const MT_Point3 & p2 = vertex_set[face.m_verts[2]].m_pos;
+ const MT_Point3 & p3 = vertex_set[face.m_verts[3]].m_pos;
+
+ MT_Vector3 e0 = p1 - p0;
+ MT_Vector3 e1 = p2 - p1;
+ MT_Vector3 e2 = p3 - p2;
+ MT_Vector3 e3 = p0 - p3;
+
+ MT_Scalar A = (e0.cross(e1)).length2();
+ MT_Scalar B = (e2.cross(e3)).length2();
+ MT_Scalar C = (e3.cross(e0)).length2();
+ MT_Scalar D = (e1.cross(e2)).length2();
+
+ MT_Scalar minab = MT_min(A,B);
+ MT_Scalar maxab = MT_max(A,B);
+
+ MT_Scalar mincd = MT_min(C,D);
+ MT_Scalar maxcd = MT_max(C,D);
+
+ MT_Scalar ratioab = minab/maxab;
+ MT_Scalar ratiocd = mincd/maxcd;
+
+ ratioab = MT_abs(1-ratioab);
+ ratiocd = MT_abs(1-ratiocd);
+
+ vector<BSP_VertexInd> loop1(3),loop2(3);
+ vector<BSP_UserFVInd> fv_loop1(3),fv_loop2(3);
+
+ if (ratioab < ratiocd) {
+ // then use [0,2] as splitting edge.
+ loop1[0] = face.m_verts[1];
+ loop1[1] = face.m_verts[2];
+ loop1[2] = face.m_verts[0];
+
+ loop2[0] = face.m_verts[2];
+ loop2[1] = face.m_verts[3];
+ loop2[2] = face.m_verts[0];
+
+ // same for fv indices.
+ fv_loop1[0] = face.m_fv_data[1];
+ fv_loop1[1] = face.m_fv_data[2];
+ fv_loop1[2] = face.m_fv_data[0];
+
+ fv_loop2[0] = face.m_fv_data[2];
+ fv_loop2[1] = face.m_fv_data[3];
+ fv_loop2[2] = face.m_fv_data[0];
+
+
+ } else {
+ // use [1,3] as splitting edge
+ loop1[0] = face.m_verts[0];
+ loop1[1] = face.m_verts[1];
+ loop1[2] = face.m_verts[3];
+
+ loop2[0] = face.m_verts[1];
+ loop2[1] = face.m_verts[2];
+ loop2[2] = face.m_verts[3];
+
+ // same for fv indices.
+ fv_loop1[0] = face.m_fv_data[0];
+ fv_loop1[1] = face.m_fv_data[1];
+ fv_loop1[2] = face.m_fv_data[3];
+
+ fv_loop2[0] = face.m_fv_data[1];
+ fv_loop2[1] = face.m_fv_data[2];
+ fv_loop2[2] = face.m_fv_data[3];
+
+ }
+
+ // TODO factor out commmon code between here and SplitPolygon.
+
+ BSP_EdgeInd new_ei = mesh.FindEdge(loop1[1],loop1[2]);
+
+ if (new_ei.IsEmpty()) {
+
+ // create a new edge.
+
+ new_ei = edge_set.size();
+ edge_set.push_back(BSP_MEdge());
+ BSP_MEdge & new_e = edge_set[new_ei];
+
+ new_e.m_verts[0] = loop1[1];
+ new_e.m_verts[1] = loop1[2];
+
+ // Now tie the edge to it's vertices.
+
+ vertex_set[loop1[1]].AddEdge(new_ei);
+ vertex_set[loop1[2]].AddEdge(new_ei);
+ }
+
+ edge_set[new_ei].m_faces.push_back(fi);
+ // This next line is a trick we are going to replace it in a moment
+ // with new_fi. It means that all the edges of the new polygon have
+ // pointers to the old polygon which we can replace.
+ edge_set[new_ei].m_faces.push_back(fi);
+
+
+ // Replace the old polygons vertex loop with the in_loop of vertices.
+
+ face.m_verts = loop1;
+ face.m_fv_data = fv_loop1;
+ new_face.m_verts = loop2;
+ new_face.m_fv_data = fv_loop2;
+
+ // That should be it for the old polygon;
+ // For the new polygon we just need to iterate around it's
+ // edges and replace pointers to the old polygon with pointers
+ // to the new one.
+
+ vector<BSP_VertexInd>::const_iterator f_verts_end = new_face.m_verts.end();
+ vector<BSP_VertexInd>::const_iterator f_verts_it = new_face.m_verts.begin();
+
+ BSP_VertexInd prev = new_face.m_verts.back();
+
+ for (;f_verts_it != f_verts_end; ++f_verts_it) {
+ BSP_EdgeInd new_f_ei = mesh.FindEdge(prev,*f_verts_it);
+
+ MT_assert(!new_f_ei.IsEmpty());
+
+ if (new_f_ei.IsEmpty()) {
+ BSP_CSGException e(e_split_error);
+ throw(e);
+ }
+
+ edge_set[new_f_ei].SwapFace(fi,new_fi);
+ prev = *f_verts_it;
+
+ }
+ return new_fi;
+}
diff --git a/intern/bsp/intern/BSP_CSGMeshSplitter.h b/intern/bsp/intern/BSP_CSGMeshSplitter.h
new file mode 100755
index 00000000000..8216082d007
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMeshSplitter.h
@@ -0,0 +1,208 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGMeshSplitter_h
+
+#define BSP_CSGMeshSplitter_h
+
+class BSP_MeshFragment;
+class MT_Plane3;
+class BSP_CSGMesh;
+
+#include "BSP_MeshPrimitives.h"
+#include "../extern/CSG_BooleanOps.h"
+#include "BSP_CSGISplitter.h"
+
+
+/**
+ * This class contains splitting functions for a CSGMesh.
+ * The atomic operation of a bsp CSG algorithm is to split
+ * a mesh fragment (connected collection of polygons contained
+ * in a convex cell) by a plane. It is vital to leave the
+ * CSGMesh in a valid state after each such operation
+ * this class insures this (or tries it's best!).
+ */
+
+
+class BSP_CSGMeshSplitter : public BSP_CSGISplitter
+{
+public :
+
+ /// construction
+
+ BSP_CSGMeshSplitter(
+ CSG_InterpolateUserFaceVertexDataFunc fv_split_func
+ );
+
+ BSP_CSGMeshSplitter(
+ const BSP_CSGMeshSplitter & other
+ );
+
+ /**
+ * @section BSP specific mesh operations.
+ * Inherited from BSP_CSGISplitter
+ */
+
+ /**
+ * Split a mesh fragment wrt plane. Generates 3 mesh fragments,
+ * in, out and on. Makes sure the mesh is coherent after the
+ * operation. The contents of frag are consumed by this oepration.
+ */
+
+ void
+ Split(
+ const MT_Plane3& plane,
+ BSP_MeshFragment *frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ );
+
+ /// Split the entire mesh with respect to the plane.
+
+ void
+ Split(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ );
+
+ ~BSP_CSGMeshSplitter(
+ );
+
+private :
+
+ void
+ SplitImp(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ const std::vector<BSP_FaceInd> & spanning_faces,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ std::vector<BSP_VertexInd> & classified_verts
+ );
+
+
+ /**
+ * @section Atomic mesh operations.
+ */
+
+ /**
+ * Add a vertex to the mesh, along
+ * a given edge. Leaves the mesh in a valid state.
+ * The vertex gets copied onto the back of the
+ * current vertex array. It's upto you to insure
+ * that the vertex actually lies on the edge and leaves
+ * the neighbouring faces convex. Returns the vertex index
+ * of the new vertex.
+ *
+ * epsilon is the relative distance [0,1] of the new
+ * vertex from the first vertex of the edge. This is
+ * used to intepolate face properties.
+ */
+
+ BSP_VertexInd
+ SplitEdge(
+ BSP_CSGMesh & mesh,
+ BSP_EdgeInd ei,
+ BSP_MVertex &vertex,
+ MT_Scalar epsilon
+ );
+
+ /**
+ * Split a polygon along an edge connecting the
+ * two tagged (on) vertices of the polygon. It assumes
+ * that you have already introduced two new vertex indices
+ * into the polygon that point to vertices tagged with
+ * {in,out,on} information. It creates a new edge from the
+ * 2 on vertices that must be present. It then splits up
+ * the polygon into 2 fragments on the inside and outside.
+ * It returns 2 indices into the face list. 1 for the inside
+ * polygon and 1 for the outside polygon.
+ */
+
+ void
+ SplitPolygon(
+ BSP_CSGMesh & mesh,
+ BSP_FaceInd fi,
+ BSP_FaceInd &fin,
+ BSP_FaceInd &fout
+ );
+
+ /**
+ * Triangulate a convex quad (the maximum size polygon
+ * resulting from splitting a triangle). This can create up
+ * to one new face - which is added to the mesh. Note
+ * that this method does not preserve references. It uses
+ * the edge which divides the quad into roughly equal triangular
+ * areas as the splitting edge. - This should avoid creating
+ * degenerate triangles.
+ */
+
+ BSP_FaceInd
+ TriangulateConvexQuad(
+ BSP_CSGMesh & mesh,
+ const BSP_FaceInd fi
+ );
+
+private :
+
+ // The function pointer used to split face vertex properties.
+
+ CSG_InterpolateUserFaceVertexDataFunc m_fv_func;
+
+ /// Cached helpers
+
+ /// Split function responsibe for:
+ std::vector<BSP_FaceInd> m_spanning_faces;
+ std::vector<BSP_VertexInd> m_tagged_verts;
+
+ /// SplitImp responsible for:
+ std::vector<BSP_EdgeInd> m_spanning_edges;
+ // The list of faces affected by splitting the spanning edge set.
+ std::vector<BSP_EdgeInd> m_visited_edges;
+ std::vector<BSP_VertexInd> m_visited_verts;
+
+ /// SplitPolygon responsible for:
+ std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop;
+ std::vector<BSP_UserFVInd> m_fv_in_loop,m_fv_out_loop;
+
+};
+
+#endif
+
+
+
diff --git a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h
new file mode 100755
index 00000000000..5d4e28e4647
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h
@@ -0,0 +1,272 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGMesh_CFIterator_h
+
+#define BSP_CSGMesh_CFIterator_h
+
+#include "BSP_CSGMesh.h"
+#include "../extern/CSG_BooleanOps.h"
+/**
+ * This class defines 2 C style iterators over a CSG mesh, one for
+ * vertices and 1 for faces. They conform to the iterator interface
+ * defined in CSG_BooleanOps.h
+ */
+
+struct BSP_CSGMesh_VertexIt {
+ MEM_RefCountPtr<BSP_CSGMesh> mesh;
+ BSP_MVertex * pos;
+};
+
+
+static
+ void
+BSP_CSGMesh_VertexIt_Destruct(
+ CSG_VertexIteratorDescriptor * iterator
+) {
+ delete ((BSP_CSGMesh_VertexIt *)(iterator->it));
+ iterator->it = NULL;
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+};
+
+
+static
+ int
+BSP_CSGMesh_VertexIt_Done(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it;
+
+ if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0;
+ return 1;
+};
+
+static
+ void
+BSP_CSGMesh_VertexIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IVertex *vert
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it;
+
+ vertex_it->pos->m_pos.getValue(vert->position);
+};
+
+static
+ void
+BSP_CSGMesh_VertexIt_Step(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it;
+
+ ++(vertex_it->pos);
+};
+
+static
+ void
+BSP_CSGMesh_VertexIt_Reset(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_VertexIt * vertex_it = (BSP_CSGMesh_VertexIt *)it;
+ vertex_it->pos = vertex_it->mesh->VertexSet().begin();
+};
+
+static
+ void
+BSP_CSGMeshVertexIt_Construct(
+ BSP_CSGMesh *mesh,
+ CSG_VertexIteratorDescriptor *output
+){
+ // user should have insured mesh is not equal to NULL.
+
+ output->Done = BSP_CSGMesh_VertexIt_Done;
+ output->Fill = BSP_CSGMesh_VertexIt_Fill;
+ output->Step = BSP_CSGMesh_VertexIt_Step;
+ output->Reset = BSP_CSGMesh_VertexIt_Reset;
+ output->num_elements = mesh->VertexSet().size();
+
+ BSP_CSGMesh_VertexIt * v_it = new BSP_CSGMesh_VertexIt;
+ v_it->mesh = mesh;
+ v_it->pos = mesh->VertexSet().begin();
+ output->it = v_it;
+};
+
+
+/**
+ * Face iterator.
+ */
+
+struct BSP_CSGMesh_FaceIt {
+ MEM_RefCountPtr<BSP_CSGMesh> mesh;
+ BSP_MFace *pos;
+ int face_triangle;
+};
+
+
+static
+ void
+BSP_CSGMesh_FaceIt_Destruct(
+ CSG_FaceIteratorDescriptor *iterator
+) {
+ delete ((BSP_CSGMesh_FaceIt *)(iterator->it));
+ iterator->it = NULL;
+ iterator->Done = NULL;
+ iterator->Fill = NULL;
+ iterator->Reset = NULL;
+ iterator->Step = NULL;
+ iterator->num_elements = 0;
+};
+
+
+static
+ int
+BSP_CSGMesh_FaceIt_Done(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it;
+
+ if (face_it->pos < face_it->mesh->FaceSet().end()) {
+ if (face_it->face_triangle + 3 <= face_it->pos->m_verts.size()) {
+ return 0;
+ }
+ }
+ return 1;
+};
+
+static
+ void
+BSP_CSGMesh_FaceIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IFace *face
+){
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it;
+ // essentially iterating through a triangle fan here.
+ const int tri_index = face_it->face_triangle;
+
+ face->vertex_index[0] = int(face_it->pos->m_verts[0]);
+ face->vertex_index[1] = int(face_it->pos->m_verts[tri_index + 1]);
+ face->vertex_index[2] = int(face_it->pos->m_verts[tri_index + 2]);
+
+ // Copy the user face data across - this does nothing
+ // if there was no mesh user data.
+
+ // time to change the iterator type to an integer...
+ face_it->mesh->FaceData().Copy(
+ face->user_face_data,
+ int(face_it->pos - face_it->mesh->FaceSet().begin())
+ );
+
+ // Copy face vertex data across...
+
+ face_it->mesh->FaceVertexData().Copy(
+ face->user_face_vertex_data[0],
+ face_it->pos->m_fv_data[0]
+ );
+
+ face_it->mesh->FaceVertexData().Copy(
+ face->user_face_vertex_data[1],
+ face_it->pos->m_fv_data[tri_index + 1]
+ );
+
+ face_it->mesh->FaceVertexData().Copy(
+ face->user_face_vertex_data[2],
+ face_it->pos->m_fv_data[tri_index + 2]
+ );
+
+ face->vertex_number = 3;
+};
+
+static
+ void
+BSP_CSGMesh_FaceIt_Step(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_FaceIt * face_it = (BSP_CSGMesh_FaceIt *)it;
+
+ // safety guard
+ if (face_it->pos < face_it->mesh->FaceSet().end()) {
+
+ if (face_it->face_triangle + 3 < face_it->pos->m_verts.size()) {
+ (face_it->face_triangle)++;
+ } else {
+ face_it->face_triangle = 0;
+ (face_it->pos) ++;
+ }
+ }
+};
+
+static
+ void
+BSP_CSGMesh_FaceIt_Reset(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ BSP_CSGMesh_FaceIt * f_it = (BSP_CSGMesh_FaceIt *)it;
+ f_it->pos = f_it->mesh->FaceSet().begin();
+ f_it->face_triangle = 0;
+};
+
+static
+ void
+BSP_CSGMesh_FaceIt_Construct(
+ BSP_CSGMesh * mesh,
+ CSG_FaceIteratorDescriptor *output
+) {
+
+ output->Done = BSP_CSGMesh_FaceIt_Done;
+ output->Fill = BSP_CSGMesh_FaceIt_Fill;
+ output->Step = BSP_CSGMesh_FaceIt_Step;
+ output->Reset = BSP_CSGMesh_FaceIt_Reset;
+
+ output->num_elements = mesh->CountTriangles();
+
+ BSP_CSGMesh_FaceIt * f_it = new BSP_CSGMesh_FaceIt;
+ f_it->mesh = mesh;
+ f_it->pos = mesh->FaceSet().begin();
+ f_it->face_triangle = 0;
+
+ output->it = f_it;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp b/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp
new file mode 100755
index 00000000000..4ffe5c73e47
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGNCMeshSplitter.cpp
@@ -0,0 +1,241 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGNCMeshSplitter.h"
+
+#include "BSP_CSGMesh.h"
+#include "BSP_MeshFragment.h"
+#include "BSP_CSGException.h"
+#include "MT_MinMax.h"
+#include "MT_assert.h"
+#include <vector>
+
+using namespace std;
+
+BSP_CSGNCMeshSplitter::
+BSP_CSGNCMeshSplitter(
+){
+ //nothing to do
+}
+
+BSP_CSGNCMeshSplitter::
+BSP_CSGNCMeshSplitter(
+ const BSP_CSGNCMeshSplitter & other
+){
+ //nothing to do
+};
+
+
+ void
+BSP_CSGNCMeshSplitter::
+Split(
+ const MT_Plane3& plane,
+ BSP_MeshFragment *frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+){
+ // First classify the vertices and the polygons of the
+ // incoming fragment.
+ frag->Classify(plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts);
+
+ SplitImp(*(frag->Mesh()),plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts);
+
+ m_spanning_faces.clear();
+ m_tagged_verts.clear();
+}
+
+/// Split the entire mesh with respect to the plane.
+
+ void
+BSP_CSGNCMeshSplitter::
+Split(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+){
+ BSP_MeshFragment::Classify(mesh, plane,in_frag,out_frag,on_frag,m_spanning_faces,m_tagged_verts);
+
+ SplitImp(mesh,plane,m_spanning_faces,in_frag,out_frag,on_frag,m_tagged_verts);
+ m_spanning_faces.clear();
+ m_tagged_verts.clear();
+}
+
+
+BSP_CSGNCMeshSplitter::
+~BSP_CSGNCMeshSplitter(
+){
+ //nothing to do
+}
+
+ void
+BSP_CSGNCMeshSplitter::
+SplitImp(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ const std::vector<BSP_FaceInd> & spanning_faces,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ std::vector<BSP_VertexInd> & classified_verts
+){
+
+ // Just iterate through the spanning faces.
+ // Identify the spanning 'edges' and create new vertices
+ // and split the polygons. We make no attempt to share
+ // vertices or preserve edge connectivity or maintain any
+ // face properties etc.
+
+ // Assumes you have already classified the vertices.
+ // and generated a set of spanning faces.
+
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ vector<BSP_FaceInd>::const_iterator sface_end = m_spanning_faces.end();
+ vector<BSP_FaceInd>::const_iterator sface_it = m_spanning_faces.begin();
+
+ for (;sface_it != sface_end; ++sface_it) {
+ BSP_FaceInd f_in,f_out;
+ SplitPolygon(plane,mesh,*sface_it,f_in,f_out);
+
+ // Use the open tag to store the original index of the face.
+ // This is originally -1.
+
+ if (face_set[*sface_it].OpenTag() == -1) {
+ face_set[f_in].SetOpenTag(*sface_it);
+ face_set[f_out].SetOpenTag(*sface_it);
+ } else {
+ face_set[f_in].SetOpenTag(face_set[*sface_it].OpenTag());
+ face_set[f_out].SetOpenTag(face_set[*sface_it].OpenTag());
+ }
+
+ in_frag->FaceSet().push_back(f_in);
+ out_frag->FaceSet().push_back(f_out);
+ }
+
+ vector<BSP_VertexInd>::const_iterator v_end = classified_verts.end();
+ vector<BSP_VertexInd>::const_iterator v_it = classified_verts.begin();
+
+ for (; v_it != v_end; ++v_it) {
+ vertex_set[*v_it].SetOpenTag(e_unclassified);
+ }
+}
+
+ void
+BSP_CSGNCMeshSplitter::
+SplitPolygon(
+ const MT_Plane3& plane,
+ BSP_CSGMesh & mesh,
+ BSP_FaceInd fi,
+ BSP_FaceInd &fin,
+ BSP_FaceInd &fout
+){
+
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ BSP_FaceInd new_fi = face_set.size();
+ face_set.push_back(BSP_MFace());
+
+ BSP_MFace & face = face_set[fi];
+ BSP_MFace &new_face = face_set[new_fi];
+
+ vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin();
+ vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end();
+
+ MT_Point3 ptA = vertex_set[face.m_verts.back()].m_pos;
+ BSP_Classification prev_class = BSP_Classification(vertex_set[face.m_verts.back()].OpenTag());
+
+ for (; f_verts_it != f_verts_end;++f_verts_it) {
+
+ BSP_Classification v_class = BSP_Classification(vertex_set[*f_verts_it].OpenTag());
+
+ if (v_class == e_classified_on) {
+ m_in_loop.push_back(*f_verts_it);
+ m_out_loop.push_back(*f_verts_it);
+ prev_class = e_classified_on;
+ continue;
+ } else
+ if (v_class == e_classified_in) {
+ m_in_loop.push_back(*f_verts_it);
+ } else
+ if (v_class == e_classified_out) {
+ m_out_loop.push_back(*f_verts_it);
+ }
+
+ if ((prev_class != e_classified_on) &&
+ (prev_class != v_class)) {
+ // spanning edge
+
+ const MT_Point3 & ptB = vertex_set[*f_verts_it].m_pos;
+
+ // compute the intersection point of plane and ptA->ptB
+ MT_Vector3 v = ptB - ptA;
+ MT_Scalar sideA = plane.signedDistance(ptA);
+
+ MT_Scalar epsilon = -sideA/plane.Normal().dot(v);
+ MT_Point3 new_p = ptA + (v * epsilon);
+
+ BSP_VertexInd new_vi(vertex_set.size());
+ vertex_set.push_back(BSP_MVertex(new_p));
+
+ m_in_loop.push_back(new_vi);
+ m_out_loop.push_back(new_vi);
+ }
+
+ ptA = vertex_set[*f_verts_it].m_pos;
+ prev_class = v_class;
+ }
+
+ // Ok should have 2 loops 1 representing the in_loop and
+ // 1 for the out_loop
+
+ new_face.m_verts = m_out_loop;
+ face.m_verts = m_in_loop;
+
+ new_face.m_plane = face.m_plane;
+
+ // we don't bother maintaining any of the other
+ // properties.
+
+ fin = fi;
+ fout = new_fi;
+
+ m_in_loop.clear();
+ m_out_loop.clear();
+};
+
+
diff --git a/intern/bsp/intern/BSP_CSGNCMeshSplitter.h b/intern/bsp/intern/BSP_CSGNCMeshSplitter.h
new file mode 100755
index 00000000000..56c1258f5c4
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGNCMeshSplitter.h
@@ -0,0 +1,139 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGNCMeshSplitter_h
+
+#define BSP_CSGNCMeshSplitter_h
+
+class BSP_MeshFragment;
+class MT_Plane3;
+class BSP_CSGMesh;
+
+#include "BSP_MeshPrimitives.h"
+#include "../extern/CSG_BooleanOps.h"
+#include "BSP_CSGISplitter.h"
+
+
+/**
+ * This class contains splitting functions for a CSGMesh.
+ * The atomic operation of a bsp CSG algorithm is to split
+ * a mesh fragment (connected collection of polygons contained
+ * in a convex cell) by a plane. This class makes no attempt
+ * to maintain edge connectivity in the mesh. It just rips
+ * up the polygons. This is fine for tree building.
+ */
+
+
+class BSP_CSGNCMeshSplitter : public BSP_CSGISplitter
+{
+public :
+
+ /// construction
+
+ BSP_CSGNCMeshSplitter(
+ );
+
+ BSP_CSGNCMeshSplitter(
+ const BSP_CSGNCMeshSplitter & other
+ );
+
+ /**
+ * @section BSP specific mesh operations.
+ * Inherited from BSP_CSGISplitter
+ */
+
+ /**
+ * Split a mesh fragment wrt plane. Generates 3 mesh fragments,
+ * in, out and on. Only splits polygons - not edges, does not maintain
+ * connectivity information. The contents of frag are consumed by this oepration.
+ */
+ void
+ Split(
+ const MT_Plane3& plane,
+ BSP_MeshFragment *frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ );
+
+ /// Split the entire mesh with respect to the plane.
+
+ void
+ Split(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_MeshFragment *spanning_frag
+ );
+
+ ~BSP_CSGNCMeshSplitter(
+ );
+
+private :
+
+ void
+ SplitImp(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3& plane,
+ const std::vector<BSP_FaceInd> & spanning_faces,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ std::vector<BSP_VertexInd> & classified_verts
+
+ );
+
+ void
+ SplitPolygon(
+ const MT_Plane3 &plane,
+ BSP_CSGMesh & mesh,
+ BSP_FaceInd fi,
+ BSP_FaceInd &fin,
+ BSP_FaceInd &fout
+ );
+
+ /// Cached helpers
+
+ /// Split function responsibe for:
+ std::vector<BSP_FaceInd> m_spanning_faces;
+ std::vector<BSP_VertexInd> m_tagged_verts;
+
+ /// SplitPolygon responsible for:
+ std::vector<BSP_FaceInd> m_in_loop,m_out_loop,m_on_loop;
+
+};
+
+
+#endif
+
diff --git a/intern/bsp/intern/BSP_CSGUserData.cpp b/intern/bsp/intern/BSP_CSGUserData.cpp
new file mode 100755
index 00000000000..a630c9fc25d
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGUserData.cpp
@@ -0,0 +1,133 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGUserData.h"
+
+
+
+BSP_CSGUserData::
+BSP_CSGUserData(
+ const int width
+):
+ m_width (width)
+{
+}
+
+/**
+ * Add a new uninitialized record to the end of the
+ * array
+ */
+
+ void
+BSP_CSGUserData::
+IncSize(
+){
+ m_data.insert(m_data.end(),m_width,char(0));
+}
+
+ int
+BSP_CSGUserData::
+Duplicate(
+ void *record
+){
+ if (m_width) {
+ int output = Size();
+ IncSize();
+
+ memcpy(m_data.end() - m_width,record,m_width);
+
+ return output;
+ }
+ return 0;
+}
+
+ void
+BSP_CSGUserData::
+Duplicate(
+ int record_index
+){
+ if (m_width) {
+ int output = Size();
+ IncSize();
+ memcpy(m_data.end() - m_width,m_data.begin() + record_index * m_width,m_width);
+ }
+}
+
+
+ void
+BSP_CSGUserData::
+Copy(
+ void *output,
+ int pos
+){
+ if (m_width) {
+ memcpy(output,m_data.begin() + m_width*pos,m_width);
+ }
+}
+ void
+BSP_CSGUserData::
+Reserve(
+ int size
+){
+ m_data.reserve(size * m_width);
+}
+
+
+/// Return the width of an individual record
+
+ int
+BSP_CSGUserData::
+Width(
+) const{
+ return m_width;
+}
+
+
+/// return the current number of records stored in the array.
+ int
+BSP_CSGUserData::
+Size(
+) const {
+ if (m_width == 0) return 0;
+ return m_data.size() / m_width;
+}
+
+
+/// return a pointer to the start of the nth record in the array.
+
+ void *
+BSP_CSGUserData::
+operator [] (
+ const int pos
+){
+ return m_data.begin() + m_width*pos;
+}
+
diff --git a/intern/bsp/intern/BSP_CSGUserData.h b/intern/bsp/intern/BSP_CSGUserData.h
new file mode 100755
index 00000000000..86d86cdd0b1
--- /dev/null
+++ b/intern/bsp/intern/BSP_CSGUserData.h
@@ -0,0 +1,136 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_CSGUserData_h
+
+#define BSP_CSGUserData_h
+
+#include <vector>
+
+/**
+ * This data represents a continuous block of
+ * data of unknown type. This holds the user
+ * data during a BSP operation.
+ */
+
+class BSP_CSGUserData
+{
+public :
+
+ /**
+ * width defines the size in bytes of a
+ * single element (record) of user data
+ */
+
+ BSP_CSGUserData(
+ const int width
+ );
+
+ /**
+ * Reserve some space in the array
+ */
+ void
+ Reserve(
+ int size
+ );
+
+ /**
+ * Add a new uninitialized record to the end of the
+ * array
+ */
+
+ void
+ IncSize(
+ );
+
+ /**
+ * duplicate a recod and insert it into the end of the array
+ * returns the index of the new record. Make sure that the
+ * record does not belong to this buffer as this can cause errors.
+ */
+
+ int
+ Duplicate(
+ void *
+ );
+
+ void
+ Duplicate(
+ int record_index
+ );
+
+ /**
+ * Copies the record at position pos in the array to the
+ * memory pointed to by output
+ */
+
+ void
+ Copy(
+ void *output,
+ int pos
+ );
+
+ /// Return the width of an individual record
+
+ int
+ Width(
+ ) const;
+
+
+ /// return the current number of records stored in the array.
+ int
+ Size(
+ ) const;
+
+
+ /// return a pointer to the start of the nth record in the array.
+
+ void *
+ operator [] (
+ const int pos
+ );
+
+private :
+
+ /// Private - force use of public constructor only.
+
+ BSP_CSGUserData(
+ );
+
+
+ /// The block of data.
+ std::vector<char> m_data;
+ /// The width of a record in this array.
+ int m_width;
+};
+
+
+#endif
diff --git a/intern/bsp/intern/BSP_FragNode.cpp b/intern/bsp/intern/BSP_FragNode.cpp
new file mode 100755
index 00000000000..e23fdd835c7
--- /dev/null
+++ b/intern/bsp/intern/BSP_FragNode.cpp
@@ -0,0 +1,313 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_CSGMesh.h"
+
+#include "BSP_FragNode.h"
+#include "BSP_CSGISplitter.h"
+
+
+BSP_FragNode::
+BSP_FragNode(
+ const MT_Plane3 & plane,
+ BSP_CSGMesh *mesh
+):
+ m_plane(plane),
+ m_in_tree(mesh),
+ m_out_tree(mesh)
+{
+}
+
+/**
+ * Public methods
+ * Should only be called by BSP_FragTree
+ */
+
+BSP_FragNode::
+~BSP_FragNode(
+){
+ // nothing to do
+}
+
+ MEM_SmartPtr<BSP_FragNode>
+BSP_FragNode::
+New(
+ const MT_Plane3 & plane,
+ BSP_CSGMesh *mesh
+){
+ return new BSP_FragNode(plane,mesh);
+}
+
+
+ void
+BSP_FragNode::
+Build(
+ BSP_MeshFragment *frag,
+ BSP_CSGISplitter & splitter
+){
+ // we know there must be some polygons still in
+ // the fragment otherwise this node would not hve been
+ // constructed.
+
+ BSP_CSGMesh *mesh = frag->Mesh();
+
+ // split the incoming fragment by the plane
+ // generating in,out,on fragments which are
+ // passed down the in and out trees.
+
+ BSP_MeshFragment in_frag(mesh,e_classified_in),out_frag(mesh,e_classified_out);
+ MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on);
+ splitter.Split(m_plane,frag,&in_frag,&out_frag,on_frag,NULL);
+
+ // We are not interested in the on fragments.
+ on_frag.Delete();
+
+ m_in_tree.Build(&in_frag,splitter);
+ m_out_tree.Build(&out_frag,splitter);
+}
+
+ void
+BSP_FragNode::
+Push(
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *output,
+ const BSP_Classification keep,
+ const bool dominant,
+ BSP_CSGISplitter & splitter
+){
+ BSP_CSGMesh *mesh = in_frag->Mesh();
+
+
+ MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in);
+ MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out);
+ MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on);
+
+ // deal with memory exceptions here.
+
+ splitter.Split(m_plane,in_frag,inside_frag,outside_frag,on_frag,NULL);
+
+ // deal with the on_fragments.
+
+ if (on_frag->FaceSet().size()) {
+
+ // The on fragment contains polygons that are outside both subtrees and polygons
+ // that are inside one or more sub trees. If we are taking the union then we can
+ // immediately add that first set of polygons to the ouput. We must then decide what
+ // to do with potenially overlapping polygons from both objects. If we assume both
+ // objects are closed then we can identify the conflict zones as
+ // polygons outside B- and inside B+
+ // polygons outside B+ and inside B-
+
+ // In these conflict zones we must choose a dominant object this is indicated
+ // by the bool parameter to this function. If the object is not dominant then
+ // we do nothing inside these conflict zones.
+ // The first set should correspond with on polygons from object B with the same
+ // orientation as this node. The second corresponding with polygons with opposite
+ // orientation.
+ // We don't want to replace polygons from A with polygons of opposite orientation
+ // from B. So we split up the on polygons of A into 2 sets according to their orientation.
+ // We add to output (A- out B-) in B+ and (A+ out B+) in B-
+
+
+#if 1
+
+ if (keep == e_classified_out) {
+ // we are doing a union operation.
+ // Make sure that this is not a leaf node.
+ if(m_in_tree.m_node != NULL || m_out_tree.m_node != NULL) {
+ BSP_MeshFragment frag_outBneg_outBpos(mesh,e_classified_on);
+ BSP_MeshFragment temp1(on_frag.Ref());
+ m_in_tree.Push(
+ &temp1,&frag_outBneg_outBpos,
+ e_classified_out,e_classified_on,
+ false,splitter
+ );
+
+ m_out_tree.Push(
+ &frag_outBneg_outBpos,output,e_classified_out,e_classified_on,
+ false,splitter
+ );
+ }
+#if 1
+ if (dominant) {
+
+ // Here we compute the intersection zones.
+ BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on);
+ on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg);
+
+ BSP_MeshFragment temp1(mesh,e_classified_in);
+
+ // push -ve fragments down inside tree, push result down outside
+ m_in_tree.Push(&frag_on_neg,&temp1,e_classified_out,e_classified_on,false,splitter);
+ m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter);
+ temp1.FaceSet().clear();
+
+ // push +ve fragments down outside tree, push result down inside.
+ m_out_tree.Push(&frag_on_pos,&temp1,e_classified_out,e_classified_on,false,splitter);
+ m_in_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter);
+ }
+#endif
+ } else if (keep == e_classified_in) {
+
+ // we are doing an intersection
+
+ // A = on_frag in X+ out X-
+ // B = on_frag in X- out X+
+ // C = on_frag in X- in X+
+
+ // If X+ is NULL then A = F out X-, B = 0, C = F in X-
+ // If X- is NULLL then A = 0, B = F out X+ , C = F in X+
+ // If both NULL then A = C = 0, B = F
+
+ // Conflicts only happen in A and B.
+ // negative fragments only in A, positive fragments only in B, anything in C.
+ // First compute F in C an add to ouput.
+
+ BSP_MeshFragment frag_on_pos(mesh,e_classified_on),frag_on_neg(mesh,e_classified_on);
+ on_frag->ClassifyOnFragments(m_plane,&frag_on_pos,&frag_on_neg);
+
+ if (m_in_tree.m_node == NULL) {
+ if (m_out_tree.m_node == NULL) {
+ // pick stuff that points in the same direction as this node
+ // only if priority.
+ if (dominant) {
+ // pass +ve frags into B = F.
+ // trick just pass down in tree... just adds to output.
+ m_in_tree.Push(&frag_on_pos,output,e_classified_in,e_classified_on,false,splitter);
+ }
+ } else {
+ // A = 0, B= F out X+ , C = F in X+
+ if (dominant) {
+ // m_out_tree.Push(&frag_on_pos,output,e_classified_out,e_classified_on,false,splitter);
+ m_out_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter);
+ }
+ }
+ } else {
+ if (m_out_tree.m_node == NULL) {
+ // A = F out X-, B=0, C = F in X-
+ if (dominant) {
+ // m_in_tree.Push(&frag_on_neg,output,e_classified_out,e_classified_on,false,splitter);
+ m_in_tree.Push(on_frag,output,e_classified_in,e_classified_on,false,splitter);
+ }
+ } else {
+ // The normals case
+ if (dominant) {
+ BSP_MeshFragment temp1(mesh,e_classified_on);
+ m_out_tree.Push(&frag_on_neg,&temp1,e_classified_in,e_classified_on,false,splitter);
+ m_in_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter);
+ temp1.FaceSet().clear();
+
+ m_in_tree.Push(&frag_on_pos,&temp1,e_classified_in,e_classified_on,false,splitter);
+ m_out_tree.Push(&temp1,output,e_classified_out,e_classified_on,false,splitter);
+ }
+ BSP_MeshFragment temp1(mesh,e_classified_on);
+ m_in_tree.Push(on_frag,&temp1,e_classified_in,e_classified_on,false,splitter);
+ m_out_tree.Push(&temp1,output,e_classified_in,e_classified_on,false,splitter);
+ }
+ }
+ }
+
+
+#endif
+ on_frag.Delete();
+ }
+
+ m_in_tree.Push(inside_frag,output,keep,e_classified_in,dominant,splitter);
+ m_out_tree.Push(outside_frag,output,keep,e_classified_out,dominant,splitter);
+};
+
+ void
+BSP_FragNode::
+Classify(
+ BSP_MeshFragment * frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_CSGISplitter & splitter
+){
+
+ BSP_CSGMesh *mesh = frag->Mesh();
+
+ MEM_SmartPtr<BSP_MeshFragment> inside_frag = new BSP_MeshFragment(mesh,e_classified_in);
+ MEM_SmartPtr<BSP_MeshFragment> outside_frag = new BSP_MeshFragment(mesh,e_classified_out);
+ MEM_SmartPtr<BSP_MeshFragment> frag_on = new BSP_MeshFragment(mesh,e_classified_on);
+
+ splitter.Split(m_plane,frag,inside_frag,outside_frag,frag_on,NULL);
+
+ // copy the on fragments into the on_frag output.
+
+ if (frag_on->FaceSet().size()) {
+
+ on_frag->FaceSet().insert(
+ on_frag->FaceSet().end(),
+ frag_on->FaceSet().begin(),
+ frag_on->FaceSet().end()
+ );
+ }
+
+ frag_on.Delete();
+
+ // pass everything else down the tree.
+
+ m_in_tree.Classify(inside_frag,in_frag,out_frag,on_frag,e_classified_in,splitter);
+ m_out_tree.Classify(outside_frag,in_frag,out_frag,on_frag,e_classified_out,splitter);
+}
+
+
+/**
+ * Accessor methods
+ */
+
+ BSP_FragTree &
+BSP_FragNode::
+InTree(
+){
+ return m_in_tree;
+}
+
+ BSP_FragTree &
+BSP_FragNode::
+OutTree(
+){
+ return m_out_tree;
+}
+
+ MT_Plane3&
+BSP_FragNode::
+Plane(
+){
+ return m_plane;
+}
+
+
+
+
+
diff --git a/intern/bsp/intern/BSP_FragNode.h b/intern/bsp/intern/BSP_FragNode.h
new file mode 100755
index 00000000000..f289419950b
--- /dev/null
+++ b/intern/bsp/intern/BSP_FragNode.h
@@ -0,0 +1,127 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_FragNode_h
+
+#define BSP_FragNode_h
+
+#include "BSP_FragTree.h"
+#include "BSP_MeshFragment.h"
+#include "MT_Plane3.h"
+
+class BSP_CSGISplitter;
+
+class BSP_FragNode : public MEM_NonCopyable
+{
+private:
+
+ /**
+ * The plane defining this node.
+ */
+
+ MT_Plane3 m_plane;
+
+ /**
+ * Children of this node.
+ */
+
+ BSP_FragTree m_in_tree;
+ BSP_FragTree m_out_tree;
+
+private :
+
+ BSP_FragNode(
+ const MT_Plane3 & plane,
+ BSP_CSGMesh *mesh
+ );
+
+public :
+
+ /**
+ * Public methods
+ * Should only be called by BSP_FragTree
+ */
+
+ ~BSP_FragNode(
+ );
+
+ static
+ MEM_SmartPtr<BSP_FragNode>
+ New(
+ const MT_Plane3 & plane,
+ BSP_CSGMesh *mesh
+ );
+
+ void
+ Build(
+ BSP_MeshFragment *frag,
+ BSP_CSGISplitter & splitter
+ );
+
+ void
+ Push(
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *output,
+ const BSP_Classification keep,
+ const bool dominant,
+ BSP_CSGISplitter & splitter
+ );
+
+ void
+ Classify(
+ BSP_MeshFragment * frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_CSGISplitter & splitter
+ );
+
+ /**
+ * Accessor methods
+ */
+
+ BSP_FragTree &
+ InTree(
+ );
+
+ BSP_FragTree &
+ OutTree(
+ );
+
+ MT_Plane3&
+ Plane(
+ );
+
+};
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/intern/BSP_FragTree.cpp b/intern/bsp/intern/BSP_FragTree.cpp
new file mode 100755
index 00000000000..3668db6cf7c
--- /dev/null
+++ b/intern/bsp/intern/BSP_FragTree.cpp
@@ -0,0 +1,319 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_FragTree.h"
+
+#include "BSP_FragNode.h"
+#include "BSP_CSGMesh.h"
+#include "BSP_MeshFragment.h"
+#include "MT_Plane3.h"
+#include "BSP_CSGException.h"
+#include <vector>
+#include "BSP_CSGISplitter.h"
+
+using namespace std;
+
+ MEM_SmartPtr<BSP_FragTree>
+BSP_FragTree::
+New(
+ BSP_CSGMesh *mesh,
+ BSP_CSGISplitter & splitter
+){
+ if (mesh == NULL) return NULL;
+ if (mesh->FaceSet().size() == 0) return NULL;
+
+ // This is the external tree construction method
+ // (not the internal method!)
+ // We need to build a tree root with an initial
+ // node based on the mesh rather than a mesh fragment.
+
+ // For now we pick an arbitrary polygon for the initial
+ // plane.
+
+ vector<BSP_MVertex> verts = mesh->VertexSet();
+ const BSP_MFace & f0 = mesh->FaceSet()[0];
+
+ const MT_Vector3 & p1 = verts[f0.m_verts[0]].m_pos;
+ const MT_Vector3 & p2 = verts[f0.m_verts[1]].m_pos;
+ const MT_Vector3 & p3 = verts[f0.m_verts[2]].m_pos;
+
+ MT_Plane3 plane = f0.m_plane;
+
+ MEM_SmartPtr<BSP_FragTree> output(new BSP_FragTree(mesh));
+ MEM_SmartPtr<BSP_FragNode> node(BSP_FragNode::New(plane,mesh));
+
+ if (output == NULL || node == NULL) return NULL;
+
+ // Generate initial mesh fragments for this plane pass into
+ // first node.
+
+ BSP_MeshFragment frag_in(mesh,e_classified_in),frag_out(mesh,e_classified_out);
+
+ MEM_SmartPtr<BSP_MeshFragment> on_frag = new BSP_MeshFragment(mesh,e_classified_on);
+
+ splitter.Split(*mesh,plane,&frag_in,&frag_out,on_frag,NULL);
+
+ // We are not interested in the on_frag.
+ on_frag.Delete();
+
+ // Build the in_tree of the first node(recursive)
+ node->InTree().Build(&frag_in,splitter);
+
+ // Build the out tree of the first node(recursive)
+ node->OutTree().Build(&frag_out,splitter);
+
+ output->m_node = node;
+
+ return output;
+}
+
+ void
+BSP_FragTree::
+Classify(
+ BSP_CSGMesh *mesh,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_CSGISplitter & splitter
+){
+
+ if (mesh == NULL) return;
+ if (mesh->FaceSet().size() == 0) return;
+ if (m_node == NULL) return;
+
+ BSP_MeshFragment frag_in(mesh,e_classified_in);
+ BSP_MeshFragment frag_out(mesh,e_classified_out);
+ BSP_MeshFragment frag_on(mesh,e_classified_on);
+ BSP_MeshFragment frag_spanning(mesh,e_classified_spanning);
+
+ splitter.Split(*mesh,m_node->Plane(),&frag_in,&frag_out,&frag_on,NULL);
+
+ if (frag_on.FaceSet().size()) {
+
+ on_frag->FaceSet().insert(
+ on_frag->FaceSet().end(),
+ frag_on.FaceSet().begin(),
+ frag_on.FaceSet().end()
+ );
+
+ frag_on.FaceSet().clear();
+ }
+
+ // recurse into subtrees.
+ m_node->InTree().Classify(&frag_in,in_frag,out_frag,on_frag,e_classified_in,splitter);
+ m_node->OutTree().Classify(&frag_out,in_frag,out_frag,on_frag,e_classified_out,splitter);
+
+}
+
+
+
+
+
+BSP_FragTree::
+~BSP_FragTree(
+){
+ // nothing to do
+}
+
+BSP_FragTree::
+BSP_FragTree(
+ BSP_CSGMesh * mesh
+):
+ m_mesh(mesh)
+{
+ //nothing to do
+}
+
+BSP_FragTree::
+BSP_FragTree(
+){
+ // nothing to do
+}
+
+ void
+BSP_FragTree::
+Build(
+ BSP_MeshFragment * frag,
+ BSP_CSGISplitter & splitter
+){
+
+ // Node must be NULL because we are building the tree.
+
+ MT_assert(m_node == NULL);
+
+ if (frag->FaceSet().size()) {
+
+ // choose a plane for the node. The first index in this
+ // mesh fragment will do for now.
+ vector<BSP_MVertex> & verts = m_mesh->VertexSet();
+
+ // choose a random splitting plane
+
+ MT_Plane3 plane;
+ {
+ int rand_index;
+#if 1
+ if (frag->FaceSet().size() > 1) {
+ rand_index = rand() % frag->FaceSet().size();
+ } else {
+ rand_index = 0;
+ }
+#else
+ rand_index = 0;
+#endif
+
+ const BSP_MFace & f0 = m_mesh->FaceSet()[frag->FaceSet()[rand_index]];
+ plane = f0.m_plane;
+ }
+
+ // build the node.
+ m_node = BSP_FragNode::New(plane,frag->Mesh());
+
+ if (m_node == NULL) {
+ BSP_CSGException e(e_tree_build_error);
+ throw(e);
+ }
+
+ m_node->Build(frag,splitter);
+ }
+}
+
+
+ void
+BSP_FragTree::
+Push(
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *output,
+ const BSP_Classification keep,
+ const BSP_Classification current,
+ const bool dominant,
+ BSP_CSGISplitter & splitter
+){
+
+ if (in_frag->FaceSet().size()) {
+
+ if (m_node == NULL) {
+
+ // we have reached a leaf node.
+ // if the current classification matches
+ // the classification we want to keep
+ // copy the polygons of the current
+ // fragment onto the output
+ vector<BSP_FaceInd>::const_iterator in_frag_it = in_frag->FaceSet().begin();
+ vector<BSP_FaceInd>::const_iterator in_frag_end = in_frag->FaceSet().end();
+ vector<BSP_MFace>::iterator faces = in_frag->Mesh()->FaceSet().begin();
+
+ if (keep == current || current == e_classified_on) {
+ for (;in_frag_it != in_frag_end; ++ in_frag_it) {
+ output->FaceSet().push_back(*in_frag_it);
+ }
+
+ in_frag->FaceSet().clear();
+ }
+ } else {
+
+ m_node->Push(in_frag,output,keep,dominant,splitter);
+ }
+ }
+}
+
+
+ void
+BSP_FragTree::
+Classify(
+ BSP_MeshFragment * frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ const BSP_Classification current,
+ BSP_CSGISplitter & splitter
+){
+
+ if (frag->FaceSet().size()) {
+
+ if (m_node == NULL) {
+
+ vector<BSP_FaceInd>::const_iterator frag_it = frag->FaceSet().begin();
+ vector<BSP_FaceInd>::const_iterator frag_end = frag->FaceSet().end();
+
+ BSP_MeshFragment *output;
+ if (current == e_classified_in) {
+ output = in_frag;
+ } else {
+ //must be e_classified_out
+ output = out_frag;
+ }
+ // Copy the selected indices into the correct output fragment.
+
+ for (;frag_it != frag_end; ++ frag_it) {
+ output->FaceSet().push_back(*frag_it);
+ }
+
+ frag->FaceSet().clear();
+ } else {
+
+ m_node->Classify(frag,in_frag,out_frag,on_frag,splitter);
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/bsp/intern/BSP_FragTree.h b/intern/bsp/intern/BSP_FragTree.h
new file mode 100755
index 00000000000..7965a055c92
--- /dev/null
+++ b/intern/bsp/intern/BSP_FragTree.h
@@ -0,0 +1,146 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_FragTree_h
+
+#define BSP_FragTree_h
+
+class BSP_FragNode;
+
+#include "MEM_SmartPtr.h"
+#include "MEM_NonCopyable.h"
+#include "BSP_MeshPrimitives.h"
+
+class BSP_CSGMesh;
+class BSP_MeshFragment;
+class BSP_CSGISplitter;
+
+class BSP_FragTree : public MEM_NonCopyable
+{
+public :
+
+ /**
+ * Create a new BSP_FragTree allocated
+ * on the heap for mesh. Note mesh will
+ * be divided up by this operation. If you
+ * want to retain the original mesh make a copy
+ * of it first.
+ */
+
+ static
+ MEM_SmartPtr<BSP_FragTree>
+ New(
+ BSP_CSGMesh *mesh,
+ BSP_CSGISplitter & splitter
+ );
+
+
+ /**
+ * Push a mesh fragment down the tree,
+ * splitting the mesh as it goes.
+ * upon reaching leaves it puts polygons from fragments
+ * of type keep into the output fragment.
+ */
+
+ void
+ Push(
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *output,
+ const BSP_Classification keep,
+ const BSP_Classification current,
+ const bool dominant,
+ BSP_CSGISplitter & splitter
+ );
+
+ void
+ Classify(
+ BSP_CSGMesh *mesh,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ BSP_CSGISplitter & splitter
+ );
+
+
+ ~BSP_FragTree(
+ );
+
+private :
+
+ friend class BSP_FragNode;
+
+ BSP_FragTree(
+ );
+
+ BSP_FragTree(
+ BSP_CSGMesh *mesh
+ );
+
+ void
+ Build(
+ BSP_MeshFragment * frag,
+ BSP_CSGISplitter & splitter
+ );
+
+
+ void
+ Classify(
+ BSP_MeshFragment * frag,
+ BSP_MeshFragment *in_frag,
+ BSP_MeshFragment *out_frag,
+ BSP_MeshFragment *on_frag,
+ const BSP_Classification current,
+ BSP_CSGISplitter & splitter
+ );
+
+private :
+
+ /**
+ * pointer to the mesh for this tree.
+ * Tree is only valid whilst mesh is around.
+ */
+
+ BSP_CSGMesh *m_mesh;
+
+ /**
+ * The node owned by this tree.
+ */
+
+ MEM_SmartPtr<BSP_FragNode> m_node;
+
+};
+
+
+#endif
+
+
+
+
diff --git a/intern/bsp/intern/BSP_MeshFragment.cpp b/intern/bsp/intern/BSP_MeshFragment.cpp
new file mode 100755
index 00000000000..408a13d6cd9
--- /dev/null
+++ b/intern/bsp/intern/BSP_MeshFragment.cpp
@@ -0,0 +1,279 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_MeshFragment.h"
+
+#include "BSP_CSGMesh.h"
+#include "MT_Plane3.h"
+#include <math.h>
+
+using namespace std;
+
+
+BSP_MeshFragment::
+BSP_MeshFragment(
+ BSP_CSGMesh *mesh,
+ BSP_Classification classification
+):
+ m_mesh(mesh),
+ m_classification(classification)
+{
+ MT_assert(m_mesh != NULL);
+ //nothing to do
+}
+
+const
+ vector<BSP_FaceInd> &
+BSP_MeshFragment::
+FaceSet(
+) const {
+ return m_faces;
+}
+
+ vector<BSP_FaceInd> &
+BSP_MeshFragment::
+FaceSet(
+) {
+ return m_faces;
+}
+
+ BSP_CSGMesh *
+BSP_MeshFragment::
+Mesh(
+){
+ return m_mesh;
+}
+
+ BSP_CSGMesh *
+BSP_MeshFragment::
+Mesh(
+) const {
+ return m_mesh;
+}
+
+ BSP_Classification
+BSP_MeshFragment::
+ClassifyPolygon(
+ const MT_Plane3 &plane,
+ const BSP_MFace & face,
+ std::vector<BSP_MVertex>::const_iterator verts,
+ vector<BSP_VertexInd> & visited_verts
+){
+
+ vector<BSP_VertexInd>::const_iterator f_vi_end = face.m_verts.end();
+ vector<BSP_VertexInd>::const_iterator f_vi_it = face.m_verts.begin();
+
+ BSP_Classification p_class = e_unclassified;
+
+ int on_count = 0;
+
+ for (;f_vi_it != f_vi_end; ++f_vi_it) {
+
+ BSP_MVertex & vert = const_cast<BSP_MVertex &>(verts[int(*f_vi_it)]);
+
+ if (BSP_Classification(vert.OpenTag()) == e_unclassified)
+ {
+ MT_Scalar sdistance = plane.signedDistance(vert.m_pos);
+ MT_Scalar fsdistance = fabs(sdistance);
+
+ if (fabs(sdistance) <= BSP_SPLIT_EPSILON) {
+ // this vertex is on
+ vert.SetOpenTag(e_classified_on);
+ } else
+ if (sdistance > MT_Scalar(0)) {
+ vert.SetOpenTag(e_classified_out);
+ } else {
+ vert.SetOpenTag(e_classified_in);
+ }
+ visited_verts.push_back(*f_vi_it);
+ }
+ BSP_Classification v_class = BSP_Classification(vert.OpenTag());
+
+ if (v_class == e_classified_on) on_count++;
+
+
+ if (p_class == e_unclassified || p_class == e_classified_on) {
+ p_class = v_class;
+ } else
+ if (p_class == e_classified_spanning) {
+ } else
+ if (p_class == e_classified_in) {
+ if (v_class == e_classified_out) {
+ p_class = e_classified_spanning;
+ }
+ } else {
+ if (v_class == e_classified_in) {
+ p_class = e_classified_spanning;
+ }
+ }
+ }
+
+ if (on_count > 2) p_class = e_classified_on;
+
+ return p_class;
+}
+
+
+// Classify this mesh fragment with respect
+// to plane. The index sets of this fragment
+// are consumed by this action. Vertices
+// are tagged with a classification enum.
+
+ void
+BSP_MeshFragment::
+Classify(
+ const MT_Plane3 & plane,
+ BSP_MeshFragment * in_frag,
+ BSP_MeshFragment * out_frag,
+ BSP_MeshFragment * on_frag,
+ vector<BSP_FaceInd> & spanning_faces,
+ vector<BSP_VertexInd> & visited_verts
+){
+
+ vector<BSP_MVertex> & vertex_set = m_mesh->VertexSet();
+ vector<BSP_MFace> & face_set = m_mesh->FaceSet();
+
+ // Now iterate through the polygons and classify.
+
+ vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end();
+ vector<BSP_FaceInd>::iterator fi_it = m_faces.begin();
+
+ vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet();
+ vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet();
+ vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet();
+
+ for (;fi_it != fi_end; ++fi_it) {
+
+ BSP_Classification p_class = ClassifyPolygon(
+ plane,
+ face_set[*fi_it],
+ vertex_set.begin(),
+ visited_verts
+ );
+ // p_class now holds the classification for this polygon.
+ // assign to the appropriate bucket.
+
+ if (p_class == e_classified_in) {
+ face_in_set.push_back(*fi_it);
+ } else
+ if (p_class == e_classified_out) {
+ face_out_set.push_back(*fi_it);
+ } else
+ if (p_class == e_classified_on) {
+ face_on_set.push_back(*fi_it);
+ } else {
+ spanning_faces.push_back(*fi_it);
+ // This is assigned later when we split the polygons in two.
+ }
+ }
+
+ m_faces.clear();
+
+}
+
+ void
+BSP_MeshFragment::
+Classify(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3 & plane,
+ BSP_MeshFragment * in_frag,
+ BSP_MeshFragment * out_frag,
+ BSP_MeshFragment * on_frag,
+ vector<BSP_FaceInd> & spanning_faces,
+ vector<BSP_VertexInd> & visited_verts
+){
+
+ vector<BSP_MVertex> & vertex_set = mesh.VertexSet();
+ vector<BSP_MFace> & face_set = mesh.FaceSet();
+
+ // Now iterate through the polygons and classify.
+
+ int fi_end = mesh.FaceSet().size();
+ int fi_it = 0;
+
+ vector<BSP_FaceInd> & face_in_set = in_frag->FaceSet();
+ vector<BSP_FaceInd> & face_out_set = out_frag->FaceSet();
+ vector<BSP_FaceInd> & face_on_set = on_frag->FaceSet();
+
+ for (;fi_it != fi_end; ++fi_it) {
+
+ BSP_Classification p_class = ClassifyPolygon(
+ plane,
+ face_set[fi_it],
+ vertex_set.begin(),
+ visited_verts
+ );
+ // p_class now holds the classification for this polygon.
+ // assign to the appropriate bucket.
+
+ if (p_class == e_classified_in) {
+ face_in_set.push_back(fi_it);
+ } else
+ if (p_class == e_classified_out) {
+ face_out_set.push_back(fi_it);
+ } else
+ if (p_class == e_classified_on) {
+ face_on_set.push_back(fi_it);
+ } else {
+ spanning_faces.push_back(fi_it);
+ }
+ }
+
+}
+ void
+BSP_MeshFragment::
+ClassifyOnFragments(
+ const MT_Plane3 &plane,
+ BSP_MeshFragment *pos_frag,
+ BSP_MeshFragment *neg_frag
+){
+
+ vector<BSP_MFace> & face_set = m_mesh->FaceSet();
+ vector<BSP_FaceInd>::const_iterator fi_end = m_faces.end();
+ vector<BSP_FaceInd>::iterator fi_it = m_faces.begin();
+
+ MT_Scalar d = plane.Scalar();
+
+ for (;fi_it != fi_end; ++fi_it) {
+ if (fabs(d + face_set[*fi_it].m_plane.Scalar()) > BSP_SPLIT_EPSILON) {
+ pos_frag->FaceSet().push_back(*fi_it);
+ } else {
+ neg_frag->FaceSet().push_back(*fi_it);
+ }
+ }
+}
+
+BSP_MeshFragment::
+~BSP_MeshFragment(
+){
+}
+
+
diff --git a/intern/bsp/intern/BSP_MeshFragment.h b/intern/bsp/intern/BSP_MeshFragment.h
new file mode 100755
index 00000000000..e0068d1c9e7
--- /dev/null
+++ b/intern/bsp/intern/BSP_MeshFragment.h
@@ -0,0 +1,152 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_BSP_MeshFragment_h
+
+#define NAN_INCLUDED_BSP_MeshFragment_h
+
+#define BSP_SPLIT_EPSILON MT_Scalar(1e-5)
+
+#include <vector>
+#include "BSP_MeshPrimitives.h"
+
+
+class BSP_CSGMesh;
+class MT_Plane3;
+/**
+ * This class encodes a collection of polygons from a mesh.
+ * This class only remains valid when mesh indices do not change
+ * internally and of course whilst the mesh is still around.
+ *
+ * Polygons in the mesh point back to the unique mesh fragment
+ * containing them.
+ */
+
+
+class BSP_MeshFragment {
+public:
+
+ BSP_MeshFragment(
+ BSP_CSGMesh *mesh,
+ BSP_Classification classification
+ );
+
+ std::vector<BSP_FaceInd> &
+ FaceSet(
+ ) ;
+
+ const
+ std::vector<BSP_FaceInd> &
+ FaceSet(
+ ) const ;
+
+ BSP_CSGMesh *
+ Mesh(
+ );
+
+ BSP_CSGMesh *
+ Mesh(
+ ) const;
+
+
+ // Classify this mesh fragment with respect
+ // to plane. The index sets of this fragment
+ // are consumed by this action. Vertices
+ // are tagged with a classification enum.
+
+ void
+ Classify(
+ const MT_Plane3 & plane,
+ BSP_MeshFragment * in_frag,
+ BSP_MeshFragment * out_frag,
+ BSP_MeshFragment * on_frag,
+ std::vector<BSP_FaceInd> & spanning_faces,
+ std::vector<BSP_VertexInd> & visited_verts
+ );
+
+ // Classify all the vertices and faces of mesh, generate
+ // in,out and on mesh fragments.
+
+ static
+ void
+ Classify(
+ BSP_CSGMesh & mesh,
+ const MT_Plane3 & plane,
+ BSP_MeshFragment * in_frag,
+ BSP_MeshFragment * out_frag,
+ BSP_MeshFragment * on_frag,
+ std::vector<BSP_FaceInd> & spanning_faces,
+ std::vector<BSP_VertexInd> & visited_verts
+ );
+
+ // Classify the on fragment into
+ // 2 sets, the +ve on frags those whose polygon
+ // normals point in the same direction as the plane,
+ // and the -ve frag whose normals point in the other direction.
+
+ void
+ ClassifyOnFragments(
+ const MT_Plane3 &plane,
+ BSP_MeshFragment *pos_frag,
+ BSP_MeshFragment *neg_frag
+ );
+
+
+ ~BSP_MeshFragment(
+ );
+
+ /**
+ * Sanity checkers.
+ */
+
+
+private:
+
+ // Classify the polygon wrt to the plane
+ static
+ BSP_Classification
+ ClassifyPolygon(
+ const MT_Plane3 &plane,
+ const BSP_MFace & face,
+ std::vector<BSP_MVertex>::const_iterator verts,
+ std::vector<BSP_VertexInd> & visited_verts
+ );
+
+private :
+
+
+ BSP_CSGMesh * m_mesh;
+ BSP_Classification m_classification;
+ std::vector<BSP_FaceInd> m_faces;
+};
+
+
+#endif
diff --git a/intern/bsp/intern/BSP_MeshPrimitives.cpp b/intern/bsp/intern/BSP_MeshPrimitives.cpp
new file mode 100755
index 00000000000..7425510b6a4
--- /dev/null
+++ b/intern/bsp/intern/BSP_MeshPrimitives.cpp
@@ -0,0 +1,301 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_MeshPrimitives.h"
+
+#include "MT_assert.h"
+#include "BSP_CSGException.h"
+#include <algorithm>
+
+using namespace std;
+
+BSP_MVertex::
+BSP_MVertex(
+) :
+ m_pos (MT_Point3()),
+ m_select_tag (false),
+ m_open_tag (0)
+{
+};
+
+BSP_MVertex::
+BSP_MVertex(
+ const MT_Point3 & pos
+) :
+ m_pos(pos),
+ m_select_tag (false),
+ m_open_tag (0)
+{
+};
+
+
+ bool
+BSP_MVertex::
+RemoveEdge(
+ BSP_EdgeInd e
+){
+ vector<BSP_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e);
+ if (result == m_edges.end()) {
+ return false;
+ }
+ BSP_EdgeInd last = m_edges.back();
+ m_edges.pop_back();
+ if (m_edges.empty()) return true;
+
+ *result = last;
+ return true;
+}
+
+ void
+BSP_MVertex::
+AddEdge(
+ BSP_EdgeInd e
+){
+ m_edges.push_back(e);
+}
+
+ void
+BSP_MVertex::
+SwapEdge(
+ BSP_EdgeInd e_old,
+ BSP_EdgeInd e_new
+){
+ vector<BSP_EdgeInd>::iterator result =
+ find(m_edges.begin(),m_edges.end(),e_old);
+ if (result == m_edges.end()) {
+ BSP_CSGException e(e_mesh_error);
+ throw(e);
+ MT_assert(false);
+ }
+
+ *result = e_new;
+}
+
+ bool
+BSP_MVertex::
+SelectTag(
+) const{
+ return m_select_tag;
+}
+
+ void
+BSP_MVertex::
+SetSelectTag(
+ bool tag
+){
+ m_select_tag = tag;
+}
+
+ int
+BSP_MVertex::
+OpenTag(
+) const {
+ return m_open_tag;
+}
+
+ void
+BSP_MVertex::
+SetOpenTag(
+ int tag
+){
+ m_open_tag = tag;
+}
+
+
+/**
+ * Edge Primitive Methods.
+ */
+
+BSP_MEdge::
+BSP_MEdge(
+){
+ m_verts[0] = m_verts[1] = BSP_VertexInd::Empty();
+}
+
+ bool
+BSP_MEdge::
+operator == (
+ BSP_MEdge & rhs
+){
+ // edges are the same if their vertex indices are the
+ // same!!! Other properties are not checked
+
+ int matches = 0;
+
+ if (this->m_verts[0] == rhs.m_verts[0]) {
+ ++matches;
+ }
+ if (this->m_verts[1] == rhs.m_verts[0]) {
+ ++matches;
+ }
+ if (this->m_verts[0] == rhs.m_verts[1]) {
+ ++matches;
+ }
+ if (this->m_verts[1] == rhs.m_verts[1]) {
+ ++matches;
+ }
+
+ if (matches >= 2) {
+ return true;
+ }
+ return false;
+}
+
+ void
+BSP_MEdge::
+SwapFace(
+ BSP_FaceInd old_f,
+ BSP_FaceInd new_f
+){
+ vector<BSP_FaceInd>::iterator result =
+ find(m_faces.begin(),m_faces.end(),old_f);
+ if (result == m_faces.end()) {
+ BSP_CSGException e(e_mesh_error);
+ throw(e);
+ MT_assert(false);
+ }
+
+ *result = new_f;
+}
+
+ BSP_VertexInd
+BSP_MEdge::
+OpVertex(
+ BSP_VertexInd vi
+) const {
+ if (vi == m_verts[0]) return m_verts[1];
+ if (vi == m_verts[1]) return m_verts[0];
+ MT_assert(false);
+ BSP_CSGException e(e_mesh_error);
+ throw(e);
+
+ return BSP_VertexInd::Empty();
+}
+
+ bool
+BSP_MEdge::
+SelectTag(
+) const {
+ return bool(m_verts[1].Tag() & 0x1);
+}
+ void
+BSP_MEdge::
+SetSelectTag(
+ bool tag
+){
+ m_verts[1].SetTag(int(tag));
+}
+
+ int
+BSP_MEdge::
+OpenTag(
+) const {
+ return m_verts[0].Tag();
+}
+
+ void
+BSP_MEdge::
+SetOpenTag(
+ int tag
+) {
+ // Note conversion from int to unsigned int!!!!!
+ m_verts[0].SetTag(tag);
+}
+
+
+/**
+ * Face primitive methods
+ */
+
+
+BSP_MFace::
+BSP_MFace(
+):
+ m_open_tag(-1)
+{
+ // nothing to do
+}
+
+ void
+BSP_MFace::
+Invert(
+){
+
+ // TODO replace reverse as I think some compilers
+ // do not support the STL routines employed.
+
+ reverse(
+ m_verts.begin(),
+ m_verts.end()
+ );
+
+ reverse(
+ m_fv_data.begin(),
+ m_fv_data.end()
+ );
+
+ // invert the normal
+ m_plane.Invert();
+}
+
+ bool
+BSP_MFace::
+SelectTag(
+) const {
+ return bool(m_verts[1].Tag() & 0x1);
+}
+
+ void
+BSP_MFace::
+SetSelectTag(
+ bool tag
+){
+ m_verts[1].SetTag(int(tag));
+};
+
+ int
+BSP_MFace::
+OpenTag(
+) const {
+ return m_open_tag;
+}
+
+ void
+BSP_MFace::
+SetOpenTag(
+ int tag
+){
+ // Note conversion from int to unsigned int!!!!!
+ m_open_tag = tag;
+}
+
+
+
diff --git a/intern/bsp/intern/BSP_MeshPrimitives.h b/intern/bsp/intern/BSP_MeshPrimitives.h
new file mode 100644
index 00000000000..8ba9cc6b83e
--- /dev/null
+++ b/intern/bsp/intern/BSP_MeshPrimitives.h
@@ -0,0 +1,289 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_BSP_MeshPrimitives
+
+#define NAN_INCLUDED_BSP_MeshPrimitives
+
+#include "CTR_TaggedIndex.h"
+#include "MT_Vector3.h"
+#include "MT_Plane3.h"
+
+class BSP_MeshFragment;
+
+#include <vector>
+
+typedef CTR_TaggedIndex<24,0x00ffffff> BSP_VertexInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> BSP_EdgeInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FaceInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> BSP_FragInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> BSP_UserFVInd;
+
+
+typedef std::vector<BSP_VertexInd> BSP_VertexList;
+typedef std::vector<BSP_EdgeInd> BSP_EdgeList;
+typedef std::vector<BSP_FaceInd> BSP_FaceList;
+typedef std::vector<BSP_UserFVInd> BSP_UserFVDataList;
+
+/**
+ * Enum representing classification of primitives
+ * with respect to a hyperplane.
+ */
+
+enum BSP_Classification{
+ e_unclassified = 0,
+ e_classified_in = 1,
+ e_classified_out = 2,
+ e_classified_on = 4,
+ e_classified_spanning = 7
+};
+
+/**
+ * @section Mesh linkage
+ * The mesh is linked in a similar way to the decimation mesh,
+ * although the primitives are a little more general and not
+ * limited to manifold meshes.
+ * Vertices -> (2+)Edges
+ * Edges -> (1+)Polygons
+ * Edges -> (2)Vertices.
+ * Polygons -> (3+)Vertices.
+ *
+ * this structure allows for arbitrary polygons (assumed to be convex).
+ * Edges can point to more than 2 polygons (non-manifold)
+ *
+ * We also define 2 different link types between edges and their
+ * neighbouring polygons. A weak link and a strong link.
+ * A weak link means the polygon is in a different mesh fragment
+ * to the other polygon. A strong link means the polygon is in the
+ * same fragment.
+ * This is not entirely consistent as it means edges have to be associated
+ * with fragments, in reality only polygons will be - edges and vertices
+ * will live in global pools. I guess we should mark edges as being on plane
+ * boundaries. This leaves a problem with non-manifold edges because for example
+ * 3 of 4 possible edges could lie in 1 fragment and the remaining edge lie in
+ * another, there is no way to work out then from one polygon which neighbouring
+ * polygons are in the same/different mesh fragment.
+ *
+ * By definition an edge will only ever lie on 1 hyperplane. We can then just
+ * tag neighbouring polygons with one of 3 tags to group them.
+ */
+
+class BSP_MVertex {
+public :
+ MT_Point3 m_pos;
+ BSP_EdgeList m_edges;
+
+ /**
+ * TODO
+ * Is this boolean necessary or can we nick a few bits of m_edges[0]
+ * for example?
+ * The only problem with this is that if the vertex is degenerate then
+ * m_edges[0] may not exist. If the algorithm guarentees that this is
+ * not the case then it should be changed.
+ */
+
+ bool m_select_tag;
+ int m_open_tag;
+
+ BSP_MVertex(
+ );
+
+ BSP_MVertex(
+ const MT_Point3 & pos
+ );
+
+ BSP_MVertex &
+ operator = (
+ const BSP_MVertex & other
+ ) {
+ m_pos = other.m_pos;
+ m_edges = other.m_edges;
+ m_select_tag = other.m_select_tag;
+ m_open_tag = other.m_open_tag;
+ return (*this);
+ };
+
+ bool
+ RemoveEdge(
+ BSP_EdgeInd e
+ );
+
+ void
+ AddEdge(
+ BSP_EdgeInd e
+ );
+
+ void
+ SwapEdge(
+ BSP_EdgeInd e_old,
+ BSP_EdgeInd e_new
+ );
+
+ /**
+ * These operations are ONLY valid when the
+ * vertex has some edges associated with it.
+ * This is left to the user to guarentee.
+ * Also note that these tag's are not guarenteed
+ * to survive after a call to RemoveEdge(),
+ * because we use edges for the open tag.
+ */
+
+ int
+ OpenTag(
+ ) const;
+
+ void
+ SetOpenTag(
+ int tag
+ );
+
+ bool
+ SelectTag(
+ ) const;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+};
+
+class BSP_MEdge {
+public :
+ BSP_VertexInd m_verts[2];
+ BSP_FaceList m_faces;
+
+ BSP_MEdge(
+ );
+
+ bool operator == (
+ BSP_MEdge & rhs
+ );
+
+ void
+ SwapFace(
+ BSP_FaceInd old_f,
+ BSP_FaceInd new_f
+ );
+
+ BSP_VertexInd
+ OpVertex(
+ BSP_VertexInd vi
+ ) const;
+
+ bool
+ SelectTag(
+ ) const;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+
+ /**
+ * We use one of the vertex indices for tag informtaion.
+ * This means these tags will not survive if you change
+ * the vertex indices.
+ */
+
+ int
+ OpenTag(
+ ) const;
+
+ void
+ SetOpenTag(
+ int tag
+ ) ;
+};
+
+class BSP_MFace {
+public :
+
+ BSP_VertexList m_verts;
+
+ // This is a list of face vertex data indices.
+ // Each vertex index in the list has an equivalent
+ // index into an array of face vertex data. This data
+ // is stored externally - the mesh does not know about it's
+ // contents.
+
+ BSP_UserFVDataList m_fv_data;
+ // We also store the plane equation of this
+ // face. Generating on the fly during tree
+ // construction can lead to a lot of numerical errors.
+ // because the polygon size can get very small.
+
+ MT_Plane3 m_plane;
+
+ int m_open_tag;
+
+ BSP_MFace(
+ );
+
+ // Invert the face , done by reversing the vertex order
+ // and inverting the face normal.
+
+ void
+ Invert(
+ );
+
+ /**
+ * Tagging
+ * We use the tag from m_verts[1] for the select tag
+ * and the the tag from m_verts[0] for the open tag.
+ * There is always a chance that the polygon contains
+ * no vertices but this should be checked at construction
+ * time.
+ * Also note that changing the vertex indices of this polygon
+ * will likely remove tagging information.
+ *
+ */
+
+ bool
+ SelectTag(
+ ) const;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+
+ int
+ OpenTag(
+ ) const;
+
+ void
+ SetOpenTag(
+ int tag
+ ) ;
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/intern/BSP_Triangulate.cpp b/intern/bsp/intern/BSP_Triangulate.cpp
new file mode 100755
index 00000000000..a78b8ff0a92
--- /dev/null
+++ b/intern/bsp/intern/BSP_Triangulate.cpp
@@ -0,0 +1,249 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include "MT_Plane3.h"
+#include "BSP_Triangulate.h"
+#include "MT_assert.h"
+
+static const MT_Scalar EPSILON = MT_Scalar(1e-10);
+
+using namespace std;
+
+BSP_Triangulate::
+BSP_Triangulate(
+):
+ m_xi(0),
+ m_yi(1)
+{
+}
+
+BSP_Triangulate::
+~BSP_Triangulate(
+){
+}
+
+
+ MT_Scalar
+BSP_Triangulate::
+Area(
+ const vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour
+){
+
+ int n = contour.size();
+
+ MT_Scalar A(0.0);
+
+ for(int p=n-1,q=0; q<n; p=q++)
+ {
+ A+= verts[contour[p]].m_pos[m_xi]*verts[contour[q]].m_pos[m_yi] -
+ verts[contour[q]].m_pos[m_xi]*verts[contour[p]].m_pos[m_yi];
+ }
+ return A*MT_Scalar(0.5);
+}
+
+/*
+ InsideTriangle decides if a point P is Inside of the triangle
+ defined by A, B, C.
+ Or within an epsilon of it.
+*/
+
+ bool
+BSP_Triangulate::
+InsideTriangle(
+ MT_Scalar Ax, MT_Scalar Ay,
+ MT_Scalar Bx, MT_Scalar By,
+ MT_Scalar Cx, MT_Scalar Cy,
+ MT_Scalar Px, MT_Scalar Py
+){
+ MT_Scalar ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ MT_Scalar cCROSSap, bCROSScp, aCROSSbp;
+
+ ax = Cx - Bx; ay = Cy - By;
+ bx = Ax - Cx; by = Ay - Cy;
+ cx = Bx - Ax; cy = By - Ay;
+ apx= Px - Ax; apy= Py - Ay;
+ bpx= Px - Bx; bpy= Py - By;
+ cpx= Px - Cx; cpy= Py - Cy;
+
+ aCROSSbp = ax*bpy - ay*bpx;
+ cCROSSap = cx*apy - cy*apx;
+ bCROSScp = bx*cpy - by*cpx;
+
+ return ((aCROSSbp >= -EPSILON) && (bCROSScp >= -EPSILON) && (cCROSSap >= -EPSILON));
+};
+
+ bool
+BSP_Triangulate::
+Snip(
+ const vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour,
+ int u,int v,
+ int w,int n,
+ int *V
+){
+ int p;
+ MT_Scalar Ax, Ay, Bx, By, Cx, Cy, Px, Py;
+
+ Ax = verts[contour[V[u]]].m_pos[m_xi];
+ Ay = verts[contour[V[u]]].m_pos[m_yi];
+
+ Bx = verts[contour[V[v]]].m_pos[m_xi];
+ By = verts[contour[V[v]]].m_pos[m_yi];
+
+ Cx = verts[contour[V[w]]].m_pos[m_xi];
+ Cy = verts[contour[V[w]]].m_pos[m_yi];
+
+ // Snip is passes if the area of the candidate triangle is
+ // greater than 2*epsilon
+ // And if none of the remaining vertices are inside the polygon
+ // or within an epsilon of the boundary,
+
+ if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false;
+
+ for (p=0;p<n;p++)
+ {
+ if( (p == u) || (p == v) || (p == w) ) continue;
+ Px = verts[contour[V[p]]].m_pos[m_xi];
+ Py = verts[contour[V[p]]].m_pos[m_yi];
+ if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
+ }
+
+ return true;
+}
+
+ bool
+BSP_Triangulate::
+Process(
+ const vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour,
+ const MT_Plane3 &normal,
+ std::vector<int> &result
+){
+
+ // Choose major axis of normal and assign
+ // 'projection' indices m_xi,m_yi;
+
+ int maj_axis = normal.Normal().closestAxis();
+
+ if (maj_axis == 0) {
+ m_xi = 1; m_yi = 2;
+ } else
+ if (maj_axis == 1) {
+ m_xi = 0; m_yi = 2;
+ } else {
+ m_xi = 0; m_yi = 1;
+ }
+
+ /* initialize list of Vertices in polygon */
+
+ int n = contour.size();
+ if ( n < 3 ) return false;
+
+ /* we want a counter-clockwise polygon in V */
+ /* to true but we also nead to preserve the winding order
+ of polygons going into the routine. We keep track of what
+ we did with a little bool */
+ bool is_flipped = false;
+
+ if ( 0.0f < Area(verts,contour) ) {
+ for (int v=0; v<n; v++) m_V.push_back(v);
+ } else {
+ for(int v=0; v<n; v++) m_V.push_back((n-1)-v);
+ is_flipped = true;
+ }
+
+ int nv = n;
+
+ /* remove nv-2 Vertices, creating 1 triangle every time */
+ int count = 2*nv; /* error detection */
+
+ for(int m=0, v=nv-1; nv>2; )
+ {
+ /* if we loop, it is probably a non-simple polygon */
+ if (0 >= (count--))
+ {
+#if 0
+ int deb = 0;
+ for (deb= 0; deb < contour.size(); deb++) {
+ cout << verts[contour[deb]].m_pos << "\n";
+ }
+ cout.flush();
+#endif
+ //** Triangulate: ERROR - probable bad polygon!
+ m_V.clear();
+ return false;
+ }
+
+ /* three consecutive vertices in current polygon, <u,v,w> */
+ int u = v ; if (nv <= u) u = 0; /* previous */
+ v = u+1; if (nv <= v) v = 0; /* new v */
+ int w = v+1; if (nv <= w) w = 0; /* next */
+
+ /* Try and snip this triangle off from the
+ current polygon.*/
+
+ if ( Snip(verts,contour,u,v,w,nv,m_V.begin()) )
+ {
+ int a,b,c,s,t;
+
+ /* true names of the vertices */
+ a = m_V[u]; b = m_V[v]; c = m_V[w];
+
+ /* output Triangle indices*/
+ if (is_flipped) {
+ result.push_back( c );
+ result.push_back( b );
+ result.push_back( a );
+ } else {
+ result.push_back( a );
+ result.push_back( b );
+ result.push_back( c );
+ }
+
+ m++;
+
+ /* remove v from remaining polygon */
+ for(s=v,t=v+1;t<nv;s++,t++) m_V[s] = m_V[t]; nv--;
+
+ /* resest error detection counter */
+ count = 2*nv;
+ }
+ }
+
+ m_V.clear();
+ return true;
+}
+
+
diff --git a/intern/bsp/intern/BSP_Triangulate.h b/intern/bsp/intern/BSP_Triangulate.h
new file mode 100755
index 00000000000..bee8e9711a9
--- /dev/null
+++ b/intern/bsp/intern/BSP_Triangulate.h
@@ -0,0 +1,132 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef TRIANGULATE_H
+
+
+#define TRIANGULATE_H
+
+/*****************************************************************/
+/** Static class to triangulate any contour/polygon efficiently **/
+/** You should replace Vector2d with whatever your own Vector **/
+/** class might be. Does not support polygons with holes. **/
+/** Uses STL vectors to represent a dynamic array of vertices. **/
+/** This code snippet was submitted to FlipCode.com by **/
+/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000 **/
+/** I did not write the original code/algorithm for this **/
+/** this triangulator, in fact, I can't even remember where I **/
+/** found it in the first place. However, I did rework it into **/
+/** the following black-box static class so you can make easy **/
+/** use of it in your own code. Simply replace Vector2d with **/
+/** whatever your own Vector implementation might be. **/
+/*****************************************************************/
+
+
+#include <vector> // Include STL vector class.
+#include "MT_Point3.h"
+#include "BSP_MeshPrimitives.h"
+
+class MT_Plane3;
+
+class BSP_Triangulate
+{
+public:
+
+ BSP_Triangulate(
+ );
+
+ // triangulate a contour/polygon, places results in STL vector
+ // as series of triangles. IT uses the major axis of the normal
+ // to turn it into a 2d problem.
+
+ // Should chaange this to accept a point array and a list of
+ // indices into that point array. Result should be indices of those
+ // indices.
+ //
+ // MT_Point3 global_array
+ // vector<BSP_VertexInd> polygon
+ // result is vector<int> into polygon.
+
+ bool
+ Process(
+ const std::vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour,
+ const MT_Plane3 &normal,
+ std::vector<int> &result
+ );
+
+ // compute area of a contour/polygon
+ MT_Scalar
+ Area(
+ const std::vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour
+ );
+
+ // decide if point Px/Py is inside triangle defined by
+ // (Ax,Ay) (Bx,By) (Cx,Cy)
+
+ bool
+ InsideTriangle(
+ MT_Scalar Ax, MT_Scalar Ay,
+ MT_Scalar Bx, MT_Scalar By,
+ MT_Scalar Cx, MT_Scalar Cy,
+ MT_Scalar Px, MT_Scalar Py
+ );
+
+ ~BSP_Triangulate(
+ );
+
+private:
+
+ bool
+ Snip(
+ const std::vector<BSP_MVertex> &verts,
+ const BSP_VertexList &contour,
+ int u,
+ int v,
+ int w,
+ int n,
+ int *V
+ );
+
+ int m_xi;
+ int m_yi;
+
+ // Temporary storage
+
+ std::vector<int> m_V;
+
+};
+
+
+#endif
+
+
diff --git a/intern/bsp/intern/CSG_BooleanOps.cpp b/intern/bsp/intern/CSG_BooleanOps.cpp
new file mode 100755
index 00000000000..01b8bfc0b68
--- /dev/null
+++ b/intern/bsp/intern/CSG_BooleanOps.cpp
@@ -0,0 +1,255 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * Implementation of external api for CSG part of BSP lib interface.
+ */
+
+#include "../extern/CSG_BooleanOps.h"
+#include "BSP_CSGMesh_CFIterator.h"
+#include "BSP_CSGMeshBuilder.h"
+#include "BSP_CSGHelper.h"
+#include "BSP_CSGUserData.h"
+#include "MEM_RefCountPtr.h"
+
+struct BSP_MeshInfo {
+ MEM_RefCountPtr<BSP_CSGMesh> output_mesh;
+ CSG_MeshPropertyDescriptor obA_descriptor;
+ CSG_MeshPropertyDescriptor obB_descriptor;
+ CSG_MeshPropertyDescriptor output_descriptor;
+};
+
+using namespace std;
+
+ CSG_BooleanOperation *
+CSG_NewBooleanFunction(
+ void
+){
+ BSP_MeshInfo * mesh_info = new BSP_MeshInfo;
+ CSG_BooleanOperation * output = new CSG_BooleanOperation;
+
+ if (mesh_info==NULL || output==NULL) return NULL;
+
+ mesh_info->output_mesh = NULL;
+ output->CSG_info = mesh_info;
+
+ return output;
+}
+
+ CSG_MeshPropertyDescriptor
+CSG_DescibeOperands(
+ CSG_BooleanOperation * operation,
+ CSG_MeshPropertyDescriptor operandA_desciption,
+ CSG_MeshPropertyDescriptor operandB_desciption
+){
+ BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
+
+ mesh_info->obA_descriptor = operandA_desciption;
+ mesh_info->obB_descriptor = operandB_desciption;
+
+ if (
+ (operandA_desciption.user_data_size == operandB_desciption.user_data_size) &&
+ (operandA_desciption.user_face_vertex_data_size == operandB_desciption.user_face_vertex_data_size)
+ ) {
+ // Then both operands have the same sets of data we can cope with this!
+ mesh_info->output_descriptor.user_data_size = operandA_desciption.user_data_size;
+ mesh_info->output_descriptor.user_face_vertex_data_size = operandA_desciption.user_face_vertex_data_size;
+ } else {
+ // There maybe some common subset of data we can seperate out but for now we just use the
+ // default
+ mesh_info->output_descriptor.user_data_size = 0;
+ mesh_info->output_descriptor.user_face_vertex_data_size = 0;
+ }
+ return mesh_info->output_descriptor;
+}
+
+ int
+CSG_PerformBooleanOperation(
+ CSG_BooleanOperation * operation,
+ CSG_OperationType op_type,
+ CSG_FaceIteratorDescriptor obAFaces,
+ CSG_VertexIteratorDescriptor obAVertices,
+ CSG_FaceIteratorDescriptor obBFaces,
+ CSG_VertexIteratorDescriptor obBVertices,
+ CSG_InterpolateUserFaceVertexDataFunc interp_func
+){
+
+ if (operation == NULL) return 0;
+ BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
+ if (mesh_info == NULL) return 0;
+
+ bool success = 0;
+
+ obAFaces.Reset(obAFaces.it);
+ obBFaces.Reset(obBFaces.it);
+ obAVertices.Reset(obAVertices.it);
+ obBVertices.Reset(obBVertices.it);
+
+
+ try {
+ // Build the individual meshes
+
+ MEM_SmartPtr<BSP_CSGMesh> obA =
+ BSP_CSGMeshBuilder::NewMesh(mesh_info->obA_descriptor,obAFaces,obAVertices);
+
+ MEM_SmartPtr<BSP_CSGMesh> obB =
+ BSP_CSGMeshBuilder::NewMesh(mesh_info->obB_descriptor,obBFaces,obBVertices);
+
+ // create an empty vertex array for the output mesh
+ MEM_SmartPtr<vector<BSP_MVertex> > output_verts(new vector<BSP_MVertex>);
+ // and some user data arrays matching the output descriptor
+
+ MEM_SmartPtr<BSP_CSGUserData> output_f_data = new BSP_CSGUserData(
+ mesh_info->output_descriptor.user_data_size
+ );
+ MEM_SmartPtr<BSP_CSGUserData> output_fv_data = new BSP_CSGUserData(
+ mesh_info->output_descriptor.user_face_vertex_data_size
+ );
+
+ // create the output mesh!
+ mesh_info->output_mesh = BSP_CSGMesh::New();
+
+ if (
+ obA == NULL ||
+ obB == NULL ||
+ output_verts == NULL ||
+ mesh_info->output_mesh == NULL ||
+ output_f_data == NULL ||
+ output_fv_data == NULL
+ ) {
+ return 0;
+ }
+
+ mesh_info->output_mesh->SetVertices(output_verts);
+ mesh_info->output_mesh->SetFaceData(output_f_data);
+ mesh_info->output_mesh->SetFaceVertexData(output_fv_data);
+
+ BSP_CSGHelper helper;
+ // translate enums!
+
+ switch(op_type) {
+ case e_csg_union :
+ case e_csg_classify :
+ success = helper.ComputeOp(obA,obB,e_intern_csg_union,
+ mesh_info->output_mesh.Ref(),interp_func
+ );
+ break;
+ case e_csg_intersection :
+ success = helper.ComputeOp(obA,obB,e_intern_csg_intersection,
+ mesh_info->output_mesh.Ref(),interp_func
+ );
+ break;
+ case e_csg_difference :
+ success = helper.ComputeOp(obA,obB,e_intern_csg_difference,
+ mesh_info->output_mesh.Ref(),interp_func
+ );
+ break;
+ default :
+ success = 0;
+ }
+ }
+ catch(...) {
+ return 0;
+ }
+
+ return success;
+}
+
+ int
+CSG_OutputFaceDescriptor(
+ CSG_BooleanOperation * operation,
+ CSG_FaceIteratorDescriptor * output
+){
+ if (operation == NULL) return 0;
+ BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
+
+ if (mesh_info == NULL) return 0;
+ if (mesh_info->output_mesh == NULL) return 0;
+
+ BSP_CSGMesh_FaceIt_Construct(mesh_info->output_mesh,output);
+ return 1;
+}
+
+
+ int
+CSG_OutputVertexDescriptor(
+ CSG_BooleanOperation * operation,
+ CSG_VertexIteratorDescriptor *output
+){
+ if (operation == NULL) return 0;
+ BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
+
+ if (mesh_info == NULL) return 0;
+ if (mesh_info->output_mesh == NULL) return 0;
+
+ BSP_CSGMeshVertexIt_Construct(mesh_info->output_mesh,output);
+ return 1;
+}
+
+ void
+CSG_FreeVertexDescriptor(
+ CSG_VertexIteratorDescriptor * v_descriptor
+){
+ BSP_CSGMesh_VertexIt_Destruct(v_descriptor);
+}
+
+
+ void
+CSG_FreeFaceDescriptor(
+ CSG_FaceIteratorDescriptor * f_descriptor
+){
+ BSP_CSGMesh_FaceIt_Destruct(f_descriptor);
+}
+
+
+ void
+CSG_FreeBooleanOperation(
+ CSG_BooleanOperation *operation
+){
+ if (operation != NULL) {
+ BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
+ delete(mesh_info);
+ delete(operation);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/bsp/intern/Makefile b/intern/bsp/intern/Makefile
new file mode 100644
index 00000000000..a5e8565a6ff
--- /dev/null
+++ b/intern/bsp/intern/Makefile
@@ -0,0 +1,48 @@
+#
+# $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.
+#
+# 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 *****
+# string intern Makefile
+#
+
+LIBNAME = bsp
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+DIRS = common
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I../extern
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+CPPFLAGS += -I$(NAN_CONTAINER)/include
+CPPFLAGS += -Icommon
+
+
diff --git a/intern/bsp/make/msvc6_0/bsplib.dsp b/intern/bsp/make/msvc6_0/bsplib.dsp
new file mode 100644
index 00000000000..8e161dcd30e
--- /dev/null
+++ b/intern/bsp/make/msvc6_0/bsplib.dsp
@@ -0,0 +1,211 @@
+# Microsoft Developer Studio Project File - Name="bsplib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=bsplib - 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 "bsplib.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 "bsplib.mak" CFG="bsplib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bsplib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "bsplib - 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)" == "bsplib - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# 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 /Ob2 /I "../../../../lib/windows/memutil/include" /I "../.." /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\libbsp.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\bsp\include\" ECHO Copying lib COPY "Release\libbsp.lib" "..\..\..\..\lib\windows\bsp\lib\libbsp.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "bsplib - 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 "Debug"
+# PROP Intermediate_Dir "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 "../../../../lib/windows/memutil" /I "../.." /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/container/include" /I "../../../../lib/windows/memutil/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\libbsp.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\bsp\include\" ECHO Copying lib COPY "Debug\libbsp.lib" "..\..\..\..\lib\windows\bsp\lib\debug\libbsp.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\bsp\lib\debug\" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "bsplib - Win32 Release"
+# Name "bsplib - Win32 Debug"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGException.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGHelper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGHelper.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGISplitter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMesh.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMesh.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMesh_CFIterator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMeshBuilder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMeshBuilder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMeshSplitter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGMeshSplitter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGNCMeshSplitter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGNCMeshSplitter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGUserData.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_CSGUserData.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_FragNode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_FragNode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_FragTree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_FragTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_MeshFragment.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_MeshFragment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_MeshPrimitives.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_MeshPrimitives.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_Triangulate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\BSP_Triangulate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\CSG_BooleanOps.cpp
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\extern\CSG_BooleanOps.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/bsp/make/msvc6_0/bsplib.dsw b/intern/bsp/make/msvc6_0/bsplib.dsw
new file mode 100644
index 00000000000..1827dc3746e
--- /dev/null
+++ b/intern/bsp/make/msvc6_0/bsplib.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bsplib"=.\bsplib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp
new file mode 100755
index 00000000000..1e913289824
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="BSP_GhostTest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=BSP_GhostTest - 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 "BSP_GhostTest.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 "BSP_GhostTest.mak" CFG="BSP_GhostTest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BSP_GhostTest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "BSP_GhostTest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BSP_GhostTest - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Ob2 /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
+
+!ELSEIF "$(CFG)" == "BSP_GhostTest - 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 "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BSP_GhostTest - Win32 Release"
+# Name "BSP_GhostTest - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\BSP_GhostTest3D.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_GhostTest3D.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_MeshDrawer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_MeshDrawer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_PlyLoader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_PlyLoader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_TMesh.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BSP_TMesh.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ply.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\plyfile.c
+# End Source File
+# End Target
+# End Project
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw
new file mode 100755
index 00000000000..802fba84bef
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest.dsw
@@ -0,0 +1,125 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BSP_GhostTest"=.\BSP_GhostTest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name bsplib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ghost
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name string
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name MoTo
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "MoTo"=..\..\..\moto\make\msvc_6_0\MoTo.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "bsplib"=..\..\make\msvc6_0\bsplib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name container
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name memutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name MoTo
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "container"=..\..\..\container\make\msvc_6_0\container.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name memutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ghost"=..\..\..\ghost\make\msvc\ghost.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "memutil"=..\..\..\memutil\make\msvc_60\memutil.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "string"=..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp
new file mode 100755
index 00000000000..92e5198f139
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp
@@ -0,0 +1,656 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+* $Id$
+* Copyright (C) 2001 NaN Technologies B.V.
+*/
+
+#if defined(WIN32) || defined(__APPLE__)
+# ifdef WIN32
+# include <windows.h>
+# include <GL/gl.h>
+# include <GL/glu.h>
+# else // WIN32
+# include <AGL/gl.h>
+# endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+# include <GL/gl.h>
+# include <GL/glu.h>
+#endif // defined(WIN32) || defined(__APPLE__)
+
+
+#include "BSP_GhostTest3D.h"
+#include "BSP_MeshDrawer.h"
+
+#include "GHOST_ISystem.h"
+#include "GHOST_IWindow.h"
+
+#include "MT_Quaternion.h"
+#include "MT_Transform.h"
+#include "CSG_BooleanOps.h"
+
+#include <iostream>
+
+
+using namespace std;
+
+
+BSP_GhostTestApp3D::
+BSP_GhostTestApp3D(
+) :
+ m_window(NULL),
+ m_system(NULL),
+ m_finish_me_off(false),
+ m_current_object(0)
+{
+ //nothing to do;
+}
+
+ void
+BSP_GhostTestApp3D::
+SetMesh(
+ MEM_SmartPtr<BSP_TMesh> mesh
+){
+ m_meshes.push_back(mesh);
+
+ BSP_RotationSetting rotation_setting;
+ BSP_TranslationSetting translation_setting;
+
+ rotation_setting.m_angle_x = MT_Scalar(0);
+ rotation_setting.m_angle_y = MT_Scalar(0);
+ rotation_setting.m_moving = false;
+ rotation_setting.x_old = 0;
+ rotation_setting.y_old = 0;
+
+ translation_setting.m_t_x = MT_Scalar(0);
+ translation_setting.m_t_y = MT_Scalar(0);
+ translation_setting.m_t_z = MT_Scalar(0);
+ translation_setting.m_moving = false;
+ translation_setting.x_old = 0;
+ translation_setting.y_old = 0;
+
+ m_rotation_settings.push_back(rotation_setting);
+ m_translation_settings.push_back(translation_setting);
+ m_render_modes.push_back(e_wireframe_shaded);
+ m_scale_settings.push_back(MT_Scalar(1));
+
+}
+
+ void
+BSP_GhostTestApp3D::
+Swap(
+ int i
+){
+
+ if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) {
+ swap(m_meshes[i],m_meshes.back());
+ swap(m_rotation_settings[i],m_rotation_settings.back());
+ swap(m_translation_settings[i],m_translation_settings.back());
+ swap(m_scale_settings[i],m_scale_settings.back());
+ swap(m_render_modes[i],m_render_modes.back());
+ }
+}
+
+
+
+
+
+
+ MT_Transform
+BSP_GhostTestApp3D::
+GetTransform(
+ int i
+){
+
+ MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x);
+ MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y);
+
+ MT_Point3 tr(
+ m_translation_settings[i].m_t_x,
+ m_translation_settings[i].m_t_y,
+ m_translation_settings[i].m_t_z
+ );
+
+
+ MT_Matrix3x3 rotx(q_ax);
+ MT_Matrix3x3 roty(q_ay);
+
+ MT_Matrix3x3 rot = rotx * roty;
+
+ MT_Transform trans(tr,rot);
+
+ MT_Transform scalet;
+ scalet.setIdentity();
+ scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]);
+
+ return trans * scalet;
+}
+
+ void
+BSP_GhostTestApp3D::
+Operate(
+ int type
+){
+
+ CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0));
+ CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]);
+
+ CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1));
+ CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]);
+
+ // describe properties.
+
+ CSG_MeshPropertyDescriptor props;
+ props.mesh_property_flags = 0;
+ props.user_data_size = 0;
+
+ CSG_BooleanOperation * op = CSG_NewBooleanFunction();
+ props = CSG_DescibeOperands(op,props,props);
+
+ CSG_PerformBooleanOperation(op,CSG_OperationType(type),
+ *fA,*vA,*fB,*vB
+ );
+
+ CSG_FaceIteratorDescriptor * out_f = CSG_OutputFaceDescriptor(op);
+ CSG_VertexIteratorDescriptor * out_v = CSG_OutputVertexDescriptor(op);
+
+ MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,*out_f,*out_v));
+
+ // free stuff
+
+ CSG_FreeVertexDescriptor(out_v);
+ CSG_FreeFaceDescriptor(out_f);
+ CSG_FreeBooleanOperation(op);
+
+ op = NULL;
+ SetMesh(new_mesh);
+}
+
+
+ void
+BSP_GhostTestApp3D::
+UpdateFrame(
+){
+if (m_window) {
+
+ GHOST_Rect v_rect;
+ m_window->getClientBounds(v_rect);
+
+ glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
+
+}
+}
+
+
+MT_Vector3
+BSP_GhostTestApp3D::
+UnProject(
+ const MT_Vector3 & vec
+) {
+
+ GLint viewport[4];
+ GLdouble mvmatrix[16],projmatrix[16];
+
+ glGetIntegerv(GL_VIEWPORT,viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
+
+ GLdouble realy = viewport[3] - vec.y() - 1;
+ GLdouble outx,outy,outz;
+
+ gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz);
+
+ return MT_Vector3(outx,outy,outz);
+}
+
+
+ bool
+BSP_GhostTestApp3D::
+InitApp(
+){
+
+ // create a system and window with opengl
+ // rendering context.
+
+ GHOST_TSuccess success = GHOST_ISystem::createSystem();
+ if (success == GHOST_kFailure) return false;
+
+ m_system = GHOST_ISystem::getSystem();
+ if (m_system == NULL) return false;
+
+ m_system->addEventConsumer(this);
+
+ m_window = m_system->createWindow(
+ "GHOST crud3D!",
+ 100,100,640,480,GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL
+ );
+
+ if (
+ m_window == NULL
+ ) {
+ m_system = NULL;
+ GHOST_ISystem::disposeSystem();
+ return false;
+ }
+
+ // make an opengl frustum for this wind
+
+ MT_Vector3 min,max;
+
+ min = m_meshes[0]->m_min;
+ max = m_meshes[0]->m_max;
+ InitOpenGl(min,max);
+
+ return true;
+}
+
+ void
+BSP_GhostTestApp3D::
+Run(
+){
+ if (m_system == NULL) {
+ return;
+ }
+
+ while (!m_finish_me_off) {
+ m_system->processEvents(true);
+ m_system->dispatchEvents();
+ };
+}
+
+ bool
+BSP_GhostTestApp3D::
+processEvent(
+ GHOST_IEvent* event
+){
+
+ bool handled = false;
+
+ switch(event->getType()) {
+ case GHOST_kEventWindowSize:
+ case GHOST_kEventWindowActivate:
+ UpdateFrame();
+ case GHOST_kEventWindowUpdate:
+ DrawPolies();
+ handled = true;
+ break;
+ case GHOST_kEventButtonDown:
+ {
+ int x,y;
+ m_system->getCursorPosition(x,y);
+
+ int wx,wy;
+ m_window->screenToClient(x,y,wx,wy);
+
+ GHOST_TButtonMask button =
+ static_cast<GHOST_TEventButtonData *>(event->getData())->button;
+
+ if (button == GHOST_kButtonMaskLeft) {
+ m_rotation_settings[m_current_object].m_moving = true;
+ m_rotation_settings[m_current_object].x_old = x;
+ m_rotation_settings[m_current_object].y_old = y;
+ } else
+ if (button == GHOST_kButtonMaskRight) {
+ m_translation_settings[m_current_object].m_moving = true;
+ m_translation_settings[m_current_object].x_old = x;
+ m_translation_settings[m_current_object].y_old = y;
+ } else
+
+ m_window->invalidate();
+ handled = true;
+ break;
+
+ }
+
+ case GHOST_kEventButtonUp:
+ {
+
+ GHOST_TButtonMask button =
+ static_cast<GHOST_TEventButtonData *>(event->getData())->button;
+
+ if (button == GHOST_kButtonMaskLeft) {
+ m_rotation_settings[m_current_object].m_moving = false;
+ m_rotation_settings[m_current_object].x_old = 0;
+ m_rotation_settings[m_current_object].y_old = 0;
+ } else
+ if (button == GHOST_kButtonMaskRight) {
+ m_translation_settings[m_current_object].m_moving = false;
+ m_translation_settings[m_current_object].x_old;
+ m_translation_settings[m_current_object].y_old;
+
+ }
+ m_window->invalidate();
+ handled = true;
+ break;
+
+ }
+
+ case GHOST_kEventCursorMove:
+ {
+ int x,y;
+ m_system->getCursorPosition(x,y);
+ int wx,wy;
+ m_window->screenToClient(x,y,wx,wy);
+
+ if (m_rotation_settings[m_current_object].m_moving) {
+ m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20;
+ m_rotation_settings[m_current_object].x_old = wx;
+ m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20;
+ m_rotation_settings[m_current_object].y_old = wy;
+
+ m_window->invalidate();
+ }
+ if (m_translation_settings[m_current_object].m_moving) {
+
+ // project current objects bounding box centre into screen space.
+ // unproject mouse point into object space using z-value from
+ // projected bounding box centre.
+
+ GHOST_Rect bounds;
+ m_window->getClientBounds(bounds);
+
+ int w_h = bounds.getWidth();
+
+ y = w_h - wy;
+
+ double mvmatrix[16];
+ double projmatrix[16];
+ GLint viewport[4];
+
+ double px, py, pz,sz;
+
+ /* Get the matrices needed for gluUnProject */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
+
+ // work out the position of the end effector in screen space
+
+ GLdouble ex,ey,ez;
+
+ MT_Vector3 bbox_min, bbox_max;
+
+ bbox_min = m_meshes[0]->m_min;
+ bbox_max = m_meshes[0]->m_max;
+
+ MT_Vector3 bbox_centre = (bbox_min + bbox_max)/2;
+
+ ex = bbox_centre.x();
+ ey = bbox_centre.y();
+ ez = bbox_centre.z();
+
+ gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
+ gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+
+ m_translation_settings[m_current_object].m_t_x = px;
+ m_translation_settings[m_current_object].m_t_y = py;
+ m_translation_settings[m_current_object].m_t_z = pz;
+ m_window->invalidate();
+
+ }
+
+ handled = true;
+ break;
+ }
+
+ case GHOST_kEventKeyDown :
+ {
+ GHOST_TEventKeyData *kd =
+ static_cast<GHOST_TEventKeyData *>(event->getData());
+
+
+ switch(kd->key) {
+ case GHOST_kKeyI:
+ {
+ // now intersect meshes.
+ Operate(e_csg_intersection);
+ handled = true;
+ m_window->invalidate();
+ break;
+ }
+ case GHOST_kKeyU:
+ {
+ Operate(e_csg_union);
+ handled = true;
+ m_window->invalidate();
+ break;
+ }
+ case GHOST_kKeyD:
+ {
+ Operate(e_csg_difference);
+ handled = true;
+ m_window->invalidate();
+ break;
+ }
+
+ case GHOST_kKeyA:
+ {
+
+ m_scale_settings[m_current_object] *= 1.1;
+ handled = true;
+ m_window->invalidate();
+ break;
+ }
+ case GHOST_kKeyZ:
+ {
+ m_scale_settings[m_current_object] *= 0.8;
+
+ handled = true;
+ m_window->invalidate();
+ break;
+ }
+
+ case GHOST_kKeyR:
+
+ m_render_modes[m_current_object]++;
+
+ if (m_render_modes[m_current_object] > e_last_render_mode) {
+ m_render_modes[m_current_object] = e_first_render_mode;
+ }
+
+ handled = true;
+ m_window->invalidate();
+ break;
+
+
+
+ case GHOST_kKeyB:
+ handled = true;
+ m_window->invalidate();
+ break;
+
+ case GHOST_kKeyQ:
+ m_finish_me_off = true;
+ handled = true;
+ break;
+
+ case GHOST_kKeyS:
+ Swap(m_current_object);
+ m_window->invalidate();
+ handled = true;
+ break;
+
+ case GHOST_kKeySpace:
+
+ // increment the current object only if the object is not being
+ // manipulated.
+ if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) {
+ m_current_object ++;
+ if (m_current_object >= m_meshes.size()) {
+ m_current_object = 0;
+ }
+ }
+ m_window->invalidate();
+
+
+ handled = true;
+ break;
+ default :
+ break;
+ }
+ }
+
+ default :
+ break;
+ }
+
+ return handled;
+
+};
+
+BSP_GhostTestApp3D::
+~BSP_GhostTestApp3D(
+){
+
+ if (m_window) {
+ m_system->disposeWindow(m_window);
+ m_window = NULL;
+ GHOST_ISystem::disposeSystem();
+ m_system = NULL;
+ }
+};
+
+ void
+BSP_GhostTestApp3D::
+DrawPolies(
+){
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ for (int i = 0; i < m_meshes.size(); ++i) {
+
+ MT_Transform trans = GetTransform(i);
+
+ float opengl_mat[16];
+ trans.getValue(opengl_mat);
+
+ opengl_mat[14] -= 30;
+
+ glPushMatrix();
+ glLoadMatrixf(opengl_mat);
+
+ MT_Vector3 color(1.0,1.0,1.0);
+
+ if (i == m_current_object) {
+ color = MT_Vector3(1.0,0,0);
+ }
+
+ BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]);
+
+ glPopMatrix();
+ }
+
+ m_window->swapBuffers();
+}
+
+ void
+BSP_GhostTestApp3D::
+InitOpenGl(
+ const MT_Vector3 &min,
+ const MT_Vector3 &max
+){
+
+ GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */
+ GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
+
+ GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */
+ GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
+
+ /* Enable a single OpenGL light. */
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHTING);
+
+ // make sure there is no back face culling.
+// glDisable(GL_CULL_FACE);
+
+
+ // use two sided lighting model
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+
+ /* Use depth buffering for hidden surface elimination. */
+ glEnable(GL_DEPTH_TEST);
+
+ /* Setup the view of the cube. */
+ glMatrixMode(GL_PROJECTION);
+
+ // centre of the box + 3* depth of box
+
+ MT_Vector3 centre = (min + max) * 0.5;
+ MT_Vector3 diag = max - min;
+
+ float depth = diag.length();
+ float distance = 5;
+
+ gluPerspective(
+ /* field of view in degree */ 40.0,
+ /* aspect ratio */ 1.0,
+ /* Z near */ 1.0,
+ /* Z far */ distance * depth * 2
+ );
+ glMatrixMode(GL_MODELVIEW);
+
+ gluLookAt(
+ centre.x(), centre.y(), centre.z() + distance*depth, //eye
+ centre.x(), centre.y(), centre.z(), //centre
+ 0.0, 1.0, 0.); /* up is in positive Y direction */
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h
new file mode 100755
index 00000000000..086ee42b903
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.h
@@ -0,0 +1,165 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_GhostTest_h
+
+#define BSP_GhostTest_h
+
+
+
+#include "GHOST_IEventConsumer.h"
+#include "MT_Vector3.h"
+#include "BSP_TMesh.h"
+#include "BSP_MeshDrawer.h"
+
+#include <vector>
+
+class GHOST_IWindow;
+class GHOST_ISystem;
+
+
+class BSP_GhostTestApp3D :
+public GHOST_IEventConsumer
+{
+public :
+ // Construct an instance of the application;
+
+ BSP_GhostTestApp3D(
+ );
+
+ // initialize the applicaton
+
+ bool
+ InitApp(
+ );
+
+ // Run the application untill internal return.
+ void
+ Run(
+ );
+
+ ~BSP_GhostTestApp3D(
+ );
+
+ void
+ SetMesh(
+ MEM_SmartPtr<BSP_TMesh> mesh
+ );
+
+private :
+
+ struct BSP_RotationSetting {
+ MT_Scalar m_angle_x;
+ MT_Scalar m_angle_y;
+ int x_old;
+ int y_old;
+ bool m_moving;
+ };
+
+ struct BSP_TranslationSetting {
+ MT_Scalar m_t_x;
+ MT_Scalar m_t_y;
+ MT_Scalar m_t_z;
+ int x_old;
+ int y_old;
+ bool m_moving;
+ };
+
+ // Return the transform of object i
+
+ MT_Transform
+ GetTransform(
+ int active_object
+ );
+
+ // Perform an operation between the first two objects in the
+ // list
+
+ void
+ Operate(
+ int type
+ );
+
+ // Swap mesh i and settings with the last mesh in list.
+
+ void
+ Swap(
+ int i
+ );
+
+ void
+ DrawPolies(
+ );
+
+ void
+ UpdateFrame(
+ );
+
+ MT_Vector3
+ UnProject(
+ const MT_Vector3 & vec
+ );
+
+ // Create a frustum and projection matrix to
+ // look at the bounding box
+
+ void
+ InitOpenGl(
+ const MT_Vector3 &min,
+ const MT_Vector3 &max
+ );
+
+
+ // inherited from GHOST_IEventConsumer
+ bool
+ processEvent(
+ GHOST_IEvent* event
+ );
+
+ GHOST_IWindow *m_window;
+ GHOST_ISystem *m_system;
+
+ bool m_finish_me_off;
+
+ // List of current meshes.
+ std::vector< MEM_SmartPtr<BSP_TMesh> > m_meshes;
+
+ std::vector< BSP_RotationSetting> m_rotation_settings;
+ std::vector< BSP_TranslationSetting> m_translation_settings;
+ std::vector< MT_Scalar> m_scale_settings;
+ std::vector< int> m_render_modes;
+
+ int m_current_object;
+
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp
new file mode 100755
index 00000000000..9df6d166263
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.cpp
@@ -0,0 +1,160 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_MeshDrawer.h"
+
+#include "BSP_TMesh.h"
+
+#if defined(WIN32) || defined(__APPLE__)
+# ifdef WIN32
+# include <windows.h>
+# include <GL/gl.h>
+# include <GL/glu.h>
+# else // WIN32
+# include <AGL/gl.h>
+# endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+# include <GL/gl.h>
+# include <GL/glu.h>
+#endif // defined(WIN32) || defined(__APPLE__)
+
+#include <vector>
+
+using namespace std;
+
+ void
+BSP_MeshDrawer::
+DrawMesh(
+ BSP_TMesh &mesh,
+ int render_mode
+){
+
+
+ if (render_mode == e_none) return;
+
+ // decompose polygons into triangles.
+
+ glEnable(GL_LIGHTING);
+
+
+ if (render_mode == e_wireframe || render_mode == e_wireframe_shaded) {
+
+ glColor3f(0.0, 0.0, 0.0);
+
+ if (render_mode == e_wireframe) {
+ glDisable(GL_LIGHTING);
+ } else {
+ glEnable(GL_LIGHTING);
+ }
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(1.0,1.0);
+
+ glBegin(GL_TRIANGLES);
+ DrawPolies(mesh);
+ glEnd();
+
+ glColor3f(1.0, 1.0, 1.0);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glBegin(GL_TRIANGLES);
+ DrawPolies(mesh);
+ glEnd();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ } else {
+
+ glEnable(GL_LIGHTING);
+
+ glBegin(GL_TRIANGLES);
+ DrawPolies(mesh);
+ glEnd();
+ }
+
+
+}
+
+
+ void
+BSP_MeshDrawer::
+DrawPolies(
+ BSP_TMesh &mesh
+){
+
+ const vector<BSP_TVertex> & verts = mesh.VertexSet();
+ const vector<BSP_TFace> &faces = mesh.FaceSet();
+
+ // just draw the edges for now.
+
+ vector<BSP_TVertex>::const_iterator vertex_it = verts.begin();
+
+
+ vector<BSP_TFace>::const_iterator faces_it = faces.begin();
+ vector<BSP_TFace>::const_iterator faces_end = faces.end();
+
+ for (;faces_it != faces_end; ++faces_it ){
+
+ glNormal3f(
+ faces_it->m_normal.x(),
+ faces_it->m_normal.y(),
+ faces_it->m_normal.z()
+ );
+
+ glVertex3f(
+ verts[faces_it->m_verts[0]].m_pos.x(),
+ verts[faces_it->m_verts[0]].m_pos.y(),
+ verts[faces_it->m_verts[0]].m_pos.z()
+ );
+ glVertex3f(
+ verts[faces_it->m_verts[1]].m_pos.x(),
+ verts[faces_it->m_verts[1]].m_pos.y(),
+ verts[faces_it->m_verts[1]].m_pos.z()
+ );
+ glVertex3f(
+ verts[faces_it->m_verts[2]].m_pos.x(),
+ verts[faces_it->m_verts[2]].m_pos.y(),
+ verts[faces_it->m_verts[2]].m_pos.z()
+ );
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h
new file mode 100755
index 00000000000..427c6a34f4d
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_MeshDrawer.h
@@ -0,0 +1,77 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_MeshDrawer_h
+
+#define BSP_MeshDrawer_h
+
+
+
+class BSP_TMesh;
+class MT_Vector3;
+
+enum BSP_TRenderMode {
+ e_shaded,
+ e_none,
+ e_wireframe,
+ e_wireframe_shaded,
+ e_first_render_mode = e_shaded,
+ e_last_render_mode = e_wireframe_shaded
+};
+
+class BSP_MeshDrawer
+{
+public :
+ static
+ void
+ DrawMesh(
+ BSP_TMesh &mesh,
+ int render_mode
+ );
+
+private :
+
+ static
+ void
+ DrawPolies(
+ BSP_TMesh &mesh
+ );
+
+
+ BSP_MeshDrawer(
+ );
+
+ ~BSP_MeshDrawer(
+ );
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp
new file mode 100755
index 00000000000..aa7dfbc3818
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.cpp
@@ -0,0 +1,196 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_PlyLoader.h"
+
+#include "MT_Vector3.h"
+#include "ply.h"
+
+struct LoadVertex {
+ float x,y,z; /* the usual 3-space position of a vertex */
+};
+
+struct LoadFace {
+ unsigned char intensity; /* this user attaches intensity to faces */
+ unsigned char nverts; /* number of vertex indices in list */
+ int *verts; /* vertex index list */
+};
+
+
+ MEM_SmartPtr<BSP_TMesh>
+BSP_PlyLoader::
+NewMeshFromFile(
+ char * file_name,
+ MT_Vector3 &min,
+ MT_Vector3 &max
+
+) {
+
+ min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY);
+ max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY);
+
+ PlyProperty vert_props[] = { /* list of property information for a vertex */
+ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0},
+ {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0},
+ {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0},
+ };
+
+ PlyProperty face_props[] = { /* list of property information for a vertex */
+ {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts),
+ 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)},
+ };
+
+ MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh;
+
+ if (mesh == NULL) return NULL;
+
+ int i,j;
+ PlyFile *ply;
+ int nelems;
+ char **elist;
+ int file_type;
+ float version;
+ int nprops;
+ int num_elems;
+ PlyProperty **plist;
+
+ char *elem_name;
+
+ LoadVertex load_vertex;
+ LoadFace load_face;
+
+ /* open a PLY file for reading */
+ ply = ply_open_for_reading(
+ file_name,
+ &nelems,
+ &elist,
+ &file_type,
+ &version
+ );
+
+ if (ply == NULL) return NULL;
+
+ /* go through each kind of element that we learned is in the file */
+ /* and read them */
+
+ for (i = 0; i < nelems; i++) {
+
+ /* get the description of the first element */
+
+ elem_name = elist[i];
+ plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
+
+ /* print the name of the element, for debugging */
+
+ /* if we're on vertex elements, read them in */
+
+ if (equal_strings ("vertex", elem_name)) {
+
+ /* set up for getting vertex elements */
+
+ ply_get_property (ply, elem_name, &vert_props[0]);
+ ply_get_property (ply, elem_name, &vert_props[1]);
+ ply_get_property (ply, elem_name, &vert_props[2]);
+
+ // make some memory for the vertices
+ mesh->VertexSet().reserve(num_elems);
+
+ /* grab all the vertex elements */
+ for (j = 0; j < num_elems; j++) {
+
+ /* grab and element from the file */
+ ply_get_element (ply, (void *)&load_vertex);
+ // pass the vertex into the mesh builder.
+
+ if (load_vertex.x < min.x()) {
+ min.x() = load_vertex.x;
+ } else
+ if (load_vertex.x > max.x()) {
+ max.x()= load_vertex.x;
+ }
+
+ if (load_vertex.y < min.y()) {
+ min.y() = load_vertex.y;
+ } else
+ if (load_vertex.y > max.y()) {
+ max.y()= load_vertex.y;
+ }
+
+ if (load_vertex.z < min.z()) {
+ min.z() = load_vertex.z;
+ } else
+ if (load_vertex.z > max.z()) {
+ max.z()= load_vertex.z;
+ }
+
+ BSP_TVertex my_vert;
+ my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z);
+ mesh->VertexSet().push_back(my_vert);
+ }
+
+
+ }
+
+ /* if we're on face elements, read them in */
+ if (equal_strings ("face", elem_name)) {
+
+ /* set up for getting face elements */
+
+ ply_get_property (ply, elem_name, &face_props[0]);
+
+ /* grab all the face elements */
+ for (j = 0; j < num_elems; j++) {
+
+ ply_get_element (ply, (void *)&load_face);
+
+ int v;
+ for (v = 2; v< load_face.nverts; v++) {
+
+ BSP_TFace f;
+
+ f.m_verts[0] = load_face.verts[0];
+ f.m_verts[1] = load_face.verts[v-1];
+ f.m_verts[2] = load_face.verts[v];
+
+ mesh->BuildNormal(f);
+ mesh->FaceSet().push_back(f);
+ }
+ // free up the memory this pile of shit used to allocate the polygon's vertices
+ free (load_face.verts);
+ }
+
+ }
+ }
+ /* close the PLY file */
+ ply_close (ply);
+
+ return mesh;
+} \ No newline at end of file
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h
new file mode 100755
index 00000000000..5f7a793267e
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_PlyLoader.h
@@ -0,0 +1,64 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_PlyLoader_h
+
+#define BSP_PlyLoader_h
+
+#include "MEM_SmartPtr.h"
+#include "BSP_TMesh.h"
+
+class BSP_PlyLoader {
+public :
+
+ static
+ MEM_SmartPtr<BSP_TMesh>
+ NewMeshFromFile(
+ char * file_name,
+ MT_Vector3 &min,
+ MT_Vector3 &max
+ );
+
+
+private :
+
+ // unimplemented - not for instantiation.
+
+ BSP_PlyLoader(
+ );
+
+ ~BSP_PlyLoader(
+ );
+};
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h b/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h
new file mode 100755
index 00000000000..d2429cd3330
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/BSP_TMesh.h
@@ -0,0 +1,354 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef BSP_TMesh_h
+
+#define BSP_TMesh_h
+
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+
+#include "MEM_SmartPtr.h"
+
+#include <vector>
+
+#include "CSG_BooleanOps.h"
+
+/**
+ * A very basic test mesh.
+ */
+
+struct BSP_TVertex {
+ MT_Point3 m_pos;
+};
+
+struct BSP_TFace {
+ int m_verts[3];
+ MT_Vector3 m_normal;
+};
+
+
+class BSP_TMesh {
+public :
+
+ std::vector<BSP_TVertex> m_verts;
+ std::vector<BSP_TFace> m_faces;
+
+ MT_Vector3 m_min,m_max;
+
+ std::vector<BSP_TVertex> &
+ VertexSet(
+ ){
+ return m_verts;
+ }
+
+ std::vector<BSP_TFace> &
+ FaceSet(
+ ) {
+ return m_faces;
+ }
+
+ void
+ AddFace(
+ int *verts,
+ int num_verts
+ );
+
+ void
+ BuildNormal(
+ BSP_TFace & f
+ ) const ;
+
+};
+
+
+
+/**
+ * some iterator functions to describe the mesh to the BSP module.
+ */
+
+/**
+ * This class defines 2 C style iterators over a CSG mesh, one for
+ * vertices and 1 for faces. They conform to the iterator interface
+ * defined in CSG_BooleanOps.h
+ */
+
+struct VertexIt {
+ BSP_TMesh * mesh;
+ BSP_TVertex * pos;
+ MT_Transform trans;
+};
+
+
+static
+ void
+VertexIt_Destruct(
+ CSG_VertexIteratorDescriptor * iterator
+) {
+ delete ((VertexIt *)(iterator->it));
+ iterator->it = NULL;
+ delete(iterator);
+};
+
+
+static
+ int
+VertexIt_Done(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ VertexIt * vertex_it = (VertexIt *)it;
+
+ if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0;
+ return 1;
+};
+
+static
+ void
+VertexIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IVertex *vert
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ VertexIt * vertex_it = (VertexIt *)it;
+
+ MT_Point3 p = vertex_it->pos->m_pos;
+ p = vertex_it->trans * p;
+
+ p.getValue(vert->position);
+};
+
+static
+ void
+VertexIt_Step(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ VertexIt * vertex_it = (VertexIt *)it;
+
+ ++(vertex_it->pos);
+};
+
+static
+ CSG_VertexIteratorDescriptor *
+VertexIt_Construct(
+ BSP_TMesh *mesh,
+ MT_Transform trans
+){
+ // user should have insured mesh is not equal to NULL.
+
+ CSG_VertexIteratorDescriptor * output = new CSG_VertexIteratorDescriptor;
+ if (output == NULL) return NULL;
+ output->Done = VertexIt_Done;
+ output->Fill = VertexIt_Fill;
+ output->Step = VertexIt_Step;
+ output->num_elements = mesh->VertexSet().size();
+
+ VertexIt * v_it = new VertexIt;
+ v_it->mesh = mesh;
+ v_it->pos = mesh->VertexSet().begin();
+ v_it->trans = trans;
+ output->it = v_it;
+ return output;
+};
+
+
+/**
+ * Face iterator.
+ */
+
+struct FaceIt {
+ BSP_TMesh * mesh;
+ BSP_TFace *pos;
+};
+
+
+static
+ void
+FaceIt_Destruct(
+ CSG_FaceIteratorDescriptor * iterator
+) {
+ delete ((FaceIt *)(iterator->it));
+ iterator->it = NULL;
+ delete(iterator);
+};
+
+
+static
+ int
+FaceIt_Done(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * face_it = (FaceIt *)it;
+
+ if (face_it->pos < face_it->mesh->FaceSet().end()) {
+ return 0;
+ }
+ return 1;
+};
+
+static
+ void
+FaceIt_Fill(
+ CSG_IteratorPtr it,
+ CSG_IFace *face
+){
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * face_it = (FaceIt *)it;
+ // essentially iterating through a triangle fan here.
+
+ face->vertex_index[0] = int(face_it->pos->m_verts[0]);
+ face->vertex_index[1] = int(face_it->pos->m_verts[1]);
+ face->vertex_index[2] = int(face_it->pos->m_verts[2]);
+
+ face->vertex_number = 3;
+};
+
+static
+ void
+FaceIt_Step(
+ CSG_IteratorPtr it
+) {
+ // assume CSG_IteratorPtr is of the correct type.
+ FaceIt * face_it = (FaceIt *)it;
+
+ face_it->pos ++;
+};
+
+static
+ CSG_FaceIteratorDescriptor *
+FaceIt_Construct(
+ BSP_TMesh * mesh
+) {
+ CSG_FaceIteratorDescriptor * output = new CSG_FaceIteratorDescriptor;
+ if (output == NULL) return NULL;
+
+ output->Done = FaceIt_Done;
+ output->Fill = FaceIt_Fill;
+ output->Step = FaceIt_Step;
+
+ output->num_elements = mesh->FaceSet().size();
+
+ FaceIt * f_it = new FaceIt;
+ f_it->mesh = mesh;
+ f_it->pos = mesh->FaceSet().begin();
+
+ output->it = f_it;
+
+ return output;
+};
+
+/**
+ * Some Build functions.
+ */
+
+static
+ MEM_SmartPtr<BSP_TMesh>
+BuildMesh(
+ CSG_MeshPropertyDescriptor &props,
+ CSG_FaceIteratorDescriptor &face_it,
+ CSG_VertexIteratorDescriptor &vertex_it
+) {
+ MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh();
+
+ CSG_IVertex vert;
+
+ while (!vertex_it.Done(vertex_it.it)) {
+
+ vertex_it.Fill(vertex_it.it,&vert);
+
+ BSP_TVertex v;
+ v.m_pos = MT_Point3(vert.position);
+ mesh->VertexSet().push_back(v);
+
+ vertex_it.Step(vertex_it.it);
+ }
+
+
+ CSG_IFace face;
+
+ while (!face_it.Done(face_it.it)) {
+ face_it.Fill(face_it.it,&face);
+
+ BSP_TFace f;
+
+ f.m_verts[0] = face.vertex_index[0],
+ f.m_verts[1] = face.vertex_index[1],
+ f.m_verts[2] = face.vertex_index[2],
+
+ mesh->BuildNormal(f);
+
+ mesh->FaceSet().push_back(f);
+
+ face_it.Step(face_it.it);
+ }
+
+ return mesh;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/bsp/test/BSP_GhostTest/Makefile b/intern/bsp/test/BSP_GhostTest/Makefile
new file mode 100644
index 00000000000..06dded40a17
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/Makefile
@@ -0,0 +1,56 @@
+#
+# $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.
+#
+# 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 *****
+# BSP_GhostTest Makefile
+#
+
+LIBNAME = BSP_GhostTest
+SOURCEDIR = intern/bsp/test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_BSP)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+CPPFLAGS += -I$(NAN_CONTAINER)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_GHOST)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I../../extern/
+
+ifeq ($(OS),windows)
+ CPPFLAGS += -I$(NAN_LIBDIR)/windows/glut-3.7/include
+endif
+
+
+
diff --git a/intern/bsp/test/BSP_GhostTest/main.cpp b/intern/bsp/test/BSP_GhostTest/main.cpp
new file mode 100755
index 00000000000..e7875047651
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/main.cpp
@@ -0,0 +1,147 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "BSP_GhostTest3D.h"
+
+#include "BSP_TMesh.h"
+#include "MEM_SmartPtr.h"
+#include "BSP_PlyLoader.h"
+
+#include <iostream>
+
+using namespace std;
+#if 1
+ MEM_SmartPtr<BSP_TMesh>
+NewTestMesh(
+ int x,
+ int y,
+ MT_Scalar fx,
+ MT_Scalar fy,
+ MT_Scalar ampx,
+ MT_Scalar ampy,
+ MT_Scalar sx,
+ MT_Scalar sy
+) {
+
+ MEM_SmartPtr<BSP_TMesh> output = new BSP_TMesh;
+
+ std::vector<BSP_TVertex> &verts = output->VertexSet();
+
+ int i,j;
+
+ MT_Scalar x_scale = fx*MT_PI/x;
+ MT_Scalar y_scale = fy*MT_PI/y;
+
+ MT_Scalar fsx = sx/x;
+ MT_Scalar fsy = sy/y;
+
+ for (j = 0; j < y; j++) {
+ for (i = 0; i < x; i++) {
+ float z = ampx*sin(x_scale * i) + ampy*sin(y_scale * j);
+
+ MT_Vector3 val(i*fsx - sx/2,j*fsy - sy/2,z);
+
+ BSP_TVertex chuff;
+ chuff.m_pos = val;
+ verts.push_back(chuff);
+ }
+ }
+
+ int poly[4];
+
+ for (j = 0; j < (y-1); j++) {
+ for (i = 0; i < (x-1); i++) {
+
+ poly[0] = j*x + i;
+ poly[1] = poly[0] + 1;
+ poly[2] = poly[1] + y;
+ poly[3] = poly[2] -1;
+
+ output->AddFace(poly,4);
+ }
+ }
+
+ output->m_min = MT_Vector3(-sx/2,-sy/2,-ampx -ampy);
+ output->m_max = MT_Vector3(sx/2,sy/2,ampx + ampy);
+
+ return output;
+}
+#endif
+
+
+int main() {
+
+ MT_Vector3 min,max;
+ MT_Vector3 min2,max2;
+
+#if 1
+ MEM_SmartPtr<BSP_TMesh> mesh1 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min,max);
+ MEM_SmartPtr<BSP_TMesh> mesh2 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min2,max2);
+
+ mesh1->m_min = min;
+ mesh1->m_max = max;
+ mesh2->m_min = min2;
+ mesh1->m_max = max2;
+
+#else
+ MEM_SmartPtr<BSP_TMesh> mesh1 = NewTestMesh(10,10,2,2,4,4,20,20);
+ MEM_SmartPtr<BSP_TMesh> mesh2 = NewTestMesh(10,10,2,2,4,4,20,20);
+#endif
+
+ if (!mesh1) {
+ cout << "could not load mesh!";
+ return 0;
+ }
+
+
+
+// MEM_SmartPtr<BSP_TMesh> mesh2 = new BSP_TMesh(mesh1.Ref());
+
+ BSP_GhostTestApp3D app;
+
+ cout << "Mesh polygons :" << mesh1->FaceSet().size() << "\n";
+ cout << "Mesh vertices :" << mesh1->VertexSet().size() << "\n";
+
+ app.SetMesh(mesh1);
+ app.SetMesh(mesh2);
+
+
+ app.InitApp();
+
+ app.Run();
+
+ return 0;
+
+}
+
+
+
+
diff --git a/intern/bsp/test/BSP_GhostTest/ply.h b/intern/bsp/test/BSP_GhostTest/ply.h
new file mode 100755
index 00000000000..7947d224c5f
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/ply.h
@@ -0,0 +1,200 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+Header for PLY polygon files.
+
+- Greg Turk, March 1994
+
+A PLY file contains a single polygonal _object_.
+
+An object is composed of lists of _elements_. Typical elements are
+vertices, faces, edges and materials.
+
+Each type of element for a given object has one or more _properties_
+associated with the element type. For instance, a vertex element may
+have as properties three floating-point values x,y,z and three unsigned
+chars for red, green and blue.
+
+---------------------------------------------------------------
+
+Copyright (c) 1994 The Board of Trustees of The Leland Stanford
+Junior University. All rights reserved.
+
+Permission to use, copy, modify and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided
+that the above copyright notice and this permission notice appear in
+all copies of this software and that you do not sell the software.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+*/
+
+#ifndef __PLY_H__
+#define __PLY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+
+#define PLY_ASCII 1 /* ascii PLY file */
+#define PLY_BINARY_BE 2 /* binary PLY file, big endian */
+#define PLY_BINARY_LE 3 /* binary PLY file, little endian */
+
+#define PLY_OKAY 0 /* ply routine worked okay */
+#define PLY_ERROR -1 /* error in ply routine */
+
+/* scalar data types supported by PLY format */
+
+#define PLY_START_TYPE 0
+#define PLY_CHAR 1
+#define PLY_SHORT 2
+#define PLY_INT 3
+#define PLY_UCHAR 4
+#define PLY_USHORT 5
+#define PLY_UINT 6
+#define PLY_FLOAT 7
+#define PLY_DOUBLE 8
+#define PLY_END_TYPE 9
+
+#define PLY_SCALAR 0
+#define PLY_LIST 1
+
+
+typedef struct PlyProperty { /* description of a property */
+
+ char *name; /* property name */
+ int external_type; /* file's data type */
+ int internal_type; /* program's data type */
+ int offset; /* offset bytes of prop in a struct */
+
+ int is_list; /* 1 = list, 0 = scalar */
+ int count_external; /* file's count type */
+ int count_internal; /* program's count type */
+ int count_offset; /* offset byte for list count */
+
+} PlyProperty;
+
+typedef struct PlyElement { /* description of an element */
+ char *name; /* element name */
+ int num; /* number of elements in this object */
+ int size; /* size of element (bytes) or -1 if variable */
+ int nprops; /* number of properties for this element */
+ PlyProperty **props; /* list of properties in the file */
+ char *store_prop; /* flags: property wanted by user? */
+ int other_offset; /* offset to un-asked-for props, or -1 if none*/
+ int other_size; /* size of other_props structure */
+} PlyElement;
+
+typedef struct PlyOtherProp { /* describes other properties in an element */
+ char *name; /* element name */
+ int size; /* size of other_props */
+ int nprops; /* number of properties in other_props */
+ PlyProperty **props; /* list of properties in other_props */
+} PlyOtherProp;
+
+typedef struct OtherData { /* for storing other_props for an other element */
+ void *other_props;
+} OtherData;
+
+typedef struct OtherElem { /* data for one "other" element */
+ char *elem_name; /* names of other elements */
+ int elem_count; /* count of instances of each element */
+ OtherData **other_data; /* actual property data for the elements */
+ PlyOtherProp *other_props; /* description of the property data */
+} OtherElem;
+
+typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
+ int num_elems; /* number of other elements */
+ OtherElem *other_list; /* list of data for other elements */
+} PlyOtherElems;
+
+typedef struct PlyFile { /* description of PLY file */
+ FILE *fp; /* file pointer */
+ int file_type; /* ascii or binary */
+ float version; /* version number of file */
+ int nelems; /* number of elements of object */
+ PlyElement **elems; /* list of elements */
+ int num_comments; /* number of comments */
+ char **comments; /* list of comments */
+ int num_obj_info; /* number of items of object information */
+ char **obj_info; /* list of object info items */
+ PlyElement *which_elem; /* which element we're currently writing */
+ PlyOtherElems *other_elems; /* "other" elements from a PLY file */
+} PlyFile;
+
+/* memory allocation */
+static char *my_alloc();
+#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
+
+
+/*** delcaration of routines ***/
+
+extern PlyFile *ply_write(FILE *, int, char **, int);
+extern PlyFile *ply_open_for_writing(char *, int, char **, int, float *);
+extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *);
+extern void ply_describe_property(PlyFile *, char *, PlyProperty *);
+extern void ply_element_count(PlyFile *, char *, int);
+extern void ply_header_complete(PlyFile *);
+extern void ply_put_element_setup(PlyFile *, char *);
+extern void ply_put_element(PlyFile *, void *);
+extern void ply_put_comment(PlyFile *, char *);
+extern void ply_put_obj_info(PlyFile *, char *);
+extern PlyFile *ply_read(FILE *, int *, char ***);
+extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *);
+extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*);
+extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *);
+extern void ply_get_property(PlyFile *, char *, PlyProperty *);
+extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int);
+extern void ply_get_element(PlyFile *, void *);
+extern char **ply_get_comments(PlyFile *, int *);
+extern char **ply_get_obj_info(PlyFile *, int *);
+extern void ply_close(PlyFile *);
+extern void ply_get_info(PlyFile *, float *, int *);
+extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int);
+extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
+extern void ply_put_other_elements (PlyFile *);
+extern void ply_free_other_elements (PlyOtherElems *);
+
+extern int equal_strings(char *, char *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !__PLY_H__ */
+
diff --git a/intern/bsp/test/BSP_GhostTest/plyfile.c b/intern/bsp/test/BSP_GhostTest/plyfile.c
new file mode 100755
index 00000000000..1fda4c77454
--- /dev/null
+++ b/intern/bsp/test/BSP_GhostTest/plyfile.c
@@ -0,0 +1,2548 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+
+The interface routines for reading and writing PLY polygon files.
+
+Greg Turk, February 1994
+
+---------------------------------------------------------------
+
+A PLY file contains a single polygonal _object_.
+
+An object is composed of lists of _elements_. Typical elements are
+vertices, faces, edges and materials.
+
+Each type of element for a given object has one or more _properties_
+associated with the element type. For instance, a vertex element may
+have as properties the floating-point values x,y,z and the three unsigned
+chars representing red, green and blue.
+
+---------------------------------------------------------------
+
+Copyright (c) 1994 The Board of Trustees of The Leland Stanford
+Junior University. All rights reserved.
+
+Permission to use, copy, modify and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided
+that the above copyright notice and this permission notice appear in
+all copies of this software and that you do not sell the software.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "ply.h"
+
+char *type_names[] = {
+"invalid",
+"char", "short", "int",
+"uchar", "ushort", "uint",
+"float", "double",
+};
+
+int ply_type_size[] = {
+ 0, 1, 2, 4, 1, 2, 4, 4, 8
+};
+
+#define NO_OTHER_PROPS -1
+
+#define DONT_STORE_PROP 0
+#define STORE_PROP 1
+
+#define OTHER_PROP 0
+#define NAMED_PROP 1
+
+
+/* returns 1 if strings are equal, 0 if not */
+int equal_strings(char *, char *);
+
+/* find an element in a plyfile's list */
+PlyElement *find_element(PlyFile *, char *);
+
+/* find a property in an element's list */
+PlyProperty *find_property(PlyElement *, char *, int *);
+
+/* write to a file the word describing a PLY file data type */
+void write_scalar_type (FILE *, int);
+
+/* read a line from a file and break it up into separate words */
+char **get_words(FILE *, int *, char **);
+char **old_get_words(FILE *, int *);
+
+/* write an item to a file */
+void write_binary_item(FILE *, int, unsigned int, double, int);
+void write_ascii_item(FILE *, int, unsigned int, double, int);
+double old_write_ascii_item(FILE *, char *, int);
+
+/* add information to a PLY file descriptor */
+void add_element(PlyFile *, char **);
+void add_property(PlyFile *, char **);
+void add_comment(PlyFile *, char *);
+void add_obj_info(PlyFile *, char *);
+
+/* copy a property */
+void copy_property(PlyProperty *, PlyProperty *);
+
+/* store a value into where a pointer and a type specify */
+void store_item(char *, int, int, unsigned int, double);
+
+/* return the value of a stored item */
+void get_stored_item( void *, int, int *, unsigned int *, double *);
+
+/* return the value stored in an item, given ptr to it and its type */
+double get_item_value(char *, int);
+
+/* get binary or ascii item and store it according to ptr and type */
+void get_ascii_item(char *, int, int *, unsigned int *, double *);
+void get_binary_item(FILE *, int, int *, unsigned int *, double *);
+
+/* get a bunch of elements from a file */
+void ascii_get_element(PlyFile *, char *);
+void binary_get_element(PlyFile *, char *);
+
+/* memory allocation */
+char *my_alloc(int, int, char *);
+
+
+/*************/
+/* Writing */
+/*************/
+
+
+/******************************************************************************
+Given a file pointer, get ready to write PLY data to the file.
+
+Entry:
+ fp - the given file pointer
+ nelems - number of elements in object
+ elem_names - list of element names
+ file_type - file type, either ascii or binary
+
+Exit:
+ returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_write(
+ FILE *fp,
+ int nelems,
+ char **elem_names,
+ int file_type
+)
+{
+ int i;
+ PlyFile *plyfile;
+ PlyElement *elem;
+
+ /* check for NULL file pointer */
+ if (fp == NULL)
+ return (NULL);
+
+ /* create a record for this object */
+
+ plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
+ plyfile->file_type = file_type;
+ plyfile->num_comments = 0;
+ plyfile->num_obj_info = 0;
+ plyfile->nelems = nelems;
+ plyfile->version = 1.0;
+ plyfile->fp = fp;
+ plyfile->other_elems = NULL;
+
+ /* tuck aside the names of the elements */
+
+ plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
+ for (i = 0; i < nelems; i++) {
+ elem = (PlyElement *) myalloc (sizeof (PlyElement));
+ plyfile->elems[i] = elem;
+ elem->name = strdup (elem_names[i]);
+ elem->num = 0;
+ elem->nprops = 0;
+ }
+
+ /* return pointer to the file descriptor */
+ return (plyfile);
+}
+
+
+/******************************************************************************
+Open a polygon file for writing.
+
+Entry:
+ filename - name of file to read from
+ nelems - number of elements in object
+ elem_names - list of element names
+ file_type - file type, either ascii or binary
+
+Exit:
+ version - version number of PLY file
+ returns a file identifier, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_open_for_writing(
+ char *filename,
+ int nelems,
+ char **elem_names,
+ int file_type,
+ float *version
+)
+{
+ PlyFile *plyfile;
+ char *name;
+ FILE *fp;
+
+ /* tack on the extension .ply, if necessary */
+
+ name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
+ strcpy (name, filename);
+ if (strlen (name) < 4 ||
+ strcmp (name + strlen (name) - 4, ".ply") != 0)
+ strcat (name, ".ply");
+
+ /* open the file for writing */
+
+ fp = fopen (name, "w");
+ if (fp == NULL) {
+ return (NULL);
+ }
+
+ /* create the actual PlyFile structure */
+
+ plyfile = ply_write (fp, nelems, elem_names, file_type);
+ if (plyfile == NULL)
+ return (NULL);
+
+ /* say what PLY file version number we're writing */
+ *version = plyfile->version;
+
+ /* return pointer to the file descriptor */
+ return (plyfile);
+}
+
+
+/******************************************************************************
+Describe an element, including its properties and how many will be written
+to the file.
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element that information is being specified about
+ nelems - number of elements of this type to be written
+ nprops - number of properties contained in the element
+ prop_list - list of properties
+******************************************************************************/
+
+void ply_describe_element(
+ PlyFile *plyfile,
+ char *elem_name,
+ int nelems,
+ int nprops,
+ PlyProperty *prop_list
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyProperty *prop;
+
+ /* look for appropriate element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
+ exit (-1);
+ }
+
+ elem->num = nelems;
+
+ /* copy the list of properties */
+
+ elem->nprops = nprops;
+ elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
+ elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
+
+ for (i = 0; i < nprops; i++) {
+ prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+ elem->props[i] = prop;
+ elem->store_prop[i] = NAMED_PROP;
+ copy_property (prop, &prop_list[i]);
+ }
+}
+
+
+/******************************************************************************
+Describe a property of an element.
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element that information is being specified about
+ prop - the new property
+******************************************************************************/
+
+void ply_describe_property(
+ PlyFile *plyfile,
+ char *elem_name,
+ PlyProperty *prop
+)
+{
+ PlyElement *elem;
+ PlyProperty *elem_prop;
+
+ /* look for appropriate element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
+ elem_name);
+ return;
+ }
+
+ /* create room for new property */
+
+ if (elem->nprops == 0) {
+ elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
+ elem->store_prop = (char *) myalloc (sizeof (char));
+ elem->nprops = 1;
+ }
+ else {
+ elem->nprops++;
+ elem->props = (PlyProperty **)
+ realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
+ elem->store_prop = (char *)
+ realloc (elem->store_prop, sizeof (char) * elem->nprops);
+ }
+
+ /* copy the new property */
+
+ elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+ elem->props[elem->nprops - 1] = elem_prop;
+ elem->store_prop[elem->nprops - 1] = NAMED_PROP;
+ copy_property (elem_prop, prop);
+}
+
+
+/******************************************************************************
+Describe what the "other" properties are that are to be stored, and where
+they are in an element.
+******************************************************************************/
+
+void ply_describe_other_properties(
+ PlyFile *plyfile,
+ PlyOtherProp *other,
+ int offset
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyProperty *prop;
+
+ /* look for appropriate element */
+ elem = find_element (plyfile, other->name);
+ if (elem == NULL) {
+ fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
+ other->name);
+ return;
+ }
+
+ /* create room for other properties */
+
+ if (elem->nprops == 0) {
+ elem->props = (PlyProperty **)
+ myalloc (sizeof (PlyProperty *) * other->nprops);
+ elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
+ elem->nprops = 0;
+ }
+ else {
+ int newsize;
+ newsize = elem->nprops + other->nprops;
+ elem->props = (PlyProperty **)
+ realloc (elem->props, sizeof (PlyProperty *) * newsize);
+ elem->store_prop = (char *)
+ realloc (elem->store_prop, sizeof (char) * newsize);
+ }
+
+ /* copy the other properties */
+
+ for (i = 0; i < other->nprops; i++) {
+ prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+ copy_property (prop, other->props[i]);
+ elem->props[elem->nprops] = prop;
+ elem->store_prop[elem->nprops] = OTHER_PROP;
+ elem->nprops++;
+ }
+
+ /* save other info about other properties */
+ elem->other_size = other->size;
+ elem->other_offset = offset;
+}
+
+
+/******************************************************************************
+State how many of a given element will be written.
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element that information is being specified about
+ nelems - number of elements of this type to be written
+******************************************************************************/
+
+void ply_element_count(
+ PlyFile *plyfile,
+ char *elem_name,
+ int nelems
+)
+{
+ PlyElement *elem;
+
+ /* look for appropriate element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
+ exit (-1);
+ }
+
+ elem->num = nelems;
+}
+
+
+/******************************************************************************
+Signal that we've described everything a PLY file's header and that the
+header should be written to the file.
+
+Entry:
+ plyfile - file identifier
+******************************************************************************/
+
+void ply_header_complete(PlyFile *plyfile)
+{
+ int i,j;
+ FILE *fp = plyfile->fp;
+ PlyElement *elem;
+ PlyProperty *prop;
+
+ fprintf (fp, "ply\n");
+
+ switch (plyfile->file_type) {
+ case PLY_ASCII:
+ fprintf (fp, "format ascii 1.0\n");
+ break;
+ case PLY_BINARY_BE:
+ fprintf (fp, "format binary_big_endian 1.0\n");
+ break;
+ case PLY_BINARY_LE:
+ fprintf (fp, "format binary_little_endian 1.0\n");
+ break;
+ default:
+ fprintf (stderr, "ply_header_complete: bad file type = %d\n",
+ plyfile->file_type);
+ exit (-1);
+ }
+
+ /* write out the comments */
+
+ for (i = 0; i < plyfile->num_comments; i++)
+ fprintf (fp, "comment %s\n", plyfile->comments[i]);
+
+ /* write out object information */
+
+ for (i = 0; i < plyfile->num_obj_info; i++)
+ fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
+
+ /* write out information about each element */
+
+ for (i = 0; i < plyfile->nelems; i++) {
+
+ elem = plyfile->elems[i];
+ fprintf (fp, "element %s %d\n", elem->name, elem->num);
+
+ /* write out each property */
+ for (j = 0; j < elem->nprops; j++) {
+ prop = elem->props[j];
+ if (prop->is_list) {
+ fprintf (fp, "property list ");
+ write_scalar_type (fp, prop->count_external);
+ fprintf (fp, " ");
+ write_scalar_type (fp, prop->external_type);
+ fprintf (fp, " %s\n", prop->name);
+ }
+ else {
+ fprintf (fp, "property ");
+ write_scalar_type (fp, prop->external_type);
+ fprintf (fp, " %s\n", prop->name);
+ }
+ }
+ }
+
+ fprintf (fp, "end_header\n");
+}
+
+
+/******************************************************************************
+Specify which elements are going to be written. This should be called
+before a call to the routine ply_put_element().
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element we're talking about
+******************************************************************************/
+
+void ply_put_element_setup(PlyFile *plyfile, char *elem_name)
+{
+ PlyElement *elem;
+
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
+ exit (-1);
+ }
+
+ plyfile->which_elem = elem;
+}
+
+
+/******************************************************************************
+Write an element to the file. This routine assumes that we're
+writing the type of element specified in the last call to the routine
+ply_put_element_setup().
+
+Entry:
+ plyfile - file identifier
+ elem_ptr - pointer to the element
+******************************************************************************/
+
+void ply_put_element(PlyFile *plyfile, void *elem_ptr)
+{
+ int j,k;
+ FILE *fp = plyfile->fp;
+ PlyElement *elem;
+ PlyProperty *prop;
+ char *elem_data,*item;
+ char **item_ptr;
+ int list_count;
+ int item_size;
+ int int_val;
+ unsigned int uint_val;
+ double double_val;
+ char **other_ptr;
+
+ elem = plyfile->which_elem;
+ elem_data = elem_ptr;
+ other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
+
+ /* write out either to an ascii or binary file */
+
+ if (plyfile->file_type == PLY_ASCII) {
+
+ /* write an ascii file */
+
+ /* write out each property of the element */
+ for (j = 0; j < elem->nprops; j++) {
+ prop = elem->props[j];
+ if (elem->store_prop[j] == OTHER_PROP)
+ elem_data = *other_ptr;
+ else
+ elem_data = elem_ptr;
+ if (prop->is_list) {
+ item = elem_data + prop->count_offset;
+ get_stored_item ((void *) item, prop->count_internal,
+ &int_val, &uint_val, &double_val);
+ write_ascii_item (fp, int_val, uint_val, double_val,
+ prop->count_external);
+ list_count = uint_val;
+ item_ptr = (char **) (elem_data + prop->offset);
+ item = item_ptr[0];
+ item_size = ply_type_size[prop->internal_type];
+ for (k = 0; k < list_count; k++) {
+ get_stored_item ((void *) item, prop->internal_type,
+ &int_val, &uint_val, &double_val);
+ write_ascii_item (fp, int_val, uint_val, double_val,
+ prop->external_type);
+ item += item_size;
+ }
+ }
+ else {
+ item = elem_data + prop->offset;
+ get_stored_item ((void *) item, prop->internal_type,
+ &int_val, &uint_val, &double_val);
+ write_ascii_item (fp, int_val, uint_val, double_val,
+ prop->external_type);
+ }
+ }
+
+ fprintf (fp, "\n");
+ }
+ else {
+
+ /* write a binary file */
+
+ /* write out each property of the element */
+ for (j = 0; j < elem->nprops; j++) {
+ prop = elem->props[j];
+ if (elem->store_prop[j] == OTHER_PROP)
+ elem_data = *other_ptr;
+ else
+ elem_data = elem_ptr;
+ if (prop->is_list) {
+ item = elem_data + prop->count_offset;
+ item_size = ply_type_size[prop->count_internal];
+ get_stored_item ((void *) item, prop->count_internal,
+ &int_val, &uint_val, &double_val);
+ write_binary_item (fp, int_val, uint_val, double_val,
+ prop->count_external);
+ list_count = uint_val;
+ item_ptr = (char **) (elem_data + prop->offset);
+ item = item_ptr[0];
+ item_size = ply_type_size[prop->internal_type];
+ for (k = 0; k < list_count; k++) {
+ get_stored_item ((void *) item, prop->internal_type,
+ &int_val, &uint_val, &double_val);
+ write_binary_item (fp, int_val, uint_val, double_val,
+ prop->external_type);
+ item += item_size;
+ }
+ }
+ else {
+ item = elem_data + prop->offset;
+ item_size = ply_type_size[prop->internal_type];
+ get_stored_item ((void *) item, prop->internal_type,
+ &int_val, &uint_val, &double_val);
+ write_binary_item (fp, int_val, uint_val, double_val,
+ prop->external_type);
+ }
+ }
+
+ }
+}
+
+
+/******************************************************************************
+Specify a comment that will be written in the header.
+
+Entry:
+ plyfile - file identifier
+ comment - the comment to be written
+******************************************************************************/
+
+void ply_put_comment(PlyFile *plyfile, char *comment)
+{
+ /* (re)allocate space for new comment */
+ if (plyfile->num_comments == 0)
+ plyfile->comments = (char **) myalloc (sizeof (char *));
+ else
+ plyfile->comments = (char **) realloc (plyfile->comments,
+ sizeof (char *) * (plyfile->num_comments + 1));
+
+ /* add comment to list */
+ plyfile->comments[plyfile->num_comments] = strdup (comment);
+ plyfile->num_comments++;
+}
+
+
+/******************************************************************************
+Specify a piece of object information (arbitrary text) that will be written
+in the header.
+
+Entry:
+ plyfile - file identifier
+ obj_info - the text information to be written
+******************************************************************************/
+
+void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
+{
+ /* (re)allocate space for new info */
+ if (plyfile->num_obj_info == 0)
+ plyfile->obj_info = (char **) myalloc (sizeof (char *));
+ else
+ plyfile->obj_info = (char **) realloc (plyfile->obj_info,
+ sizeof (char *) * (plyfile->num_obj_info + 1));
+
+ /* add info to list */
+ plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
+ plyfile->num_obj_info++;
+}
+
+
+
+
+
+
+
+/*************/
+/* Reading */
+/*************/
+
+
+
+/******************************************************************************
+Given a file pointer, get ready to read PLY data from the file.
+
+Entry:
+ fp - the given file pointer
+
+Exit:
+ nelems - number of elements in object
+ elem_names - list of element names
+ returns a pointer to a PlyFile, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
+{
+ int i,j;
+ PlyFile *plyfile;
+ int nwords;
+ char **words;
+ int found_format = 0;
+ char **elist;
+ PlyElement *elem;
+ char *orig_line;
+
+ /* check for NULL file pointer */
+ if (fp == NULL)
+ return (NULL);
+
+ /* create record for this object */
+
+ plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
+ plyfile->nelems = 0;
+ plyfile->comments = NULL;
+ plyfile->num_comments = 0;
+ plyfile->obj_info = NULL;
+ plyfile->num_obj_info = 0;
+ plyfile->fp = fp;
+ plyfile->other_elems = NULL;
+
+ /* read and parse the file's header */
+
+ words = get_words (plyfile->fp, &nwords, &orig_line);
+ if (!words || !equal_strings (words[0], "ply"))
+ return (NULL);
+
+ while (words) {
+
+ /* parse words */
+
+ if (equal_strings (words[0], "format")) {
+ if (nwords != 3)
+ return (NULL);
+ if (equal_strings (words[1], "ascii"))
+ plyfile->file_type = PLY_ASCII;
+ else if (equal_strings (words[1], "binary_big_endian"))
+ plyfile->file_type = PLY_BINARY_BE;
+ else if (equal_strings (words[1], "binary_little_endian"))
+ plyfile->file_type = PLY_BINARY_LE;
+ else
+ return (NULL);
+ plyfile->version = (float)atof (words[2]);
+ found_format = 1;
+ }
+ else if (equal_strings (words[0], "element"))
+ add_element (plyfile, words);
+ else if (equal_strings (words[0], "property"))
+ add_property (plyfile, words);
+ else if (equal_strings (words[0], "comment"))
+ add_comment (plyfile, orig_line);
+ else if (equal_strings (words[0], "obj_info"))
+ add_obj_info (plyfile, orig_line);
+ else if (equal_strings (words[0], "end_header"))
+ break;
+
+ /* free up words space */
+ free (words);
+
+ words = get_words (plyfile->fp, &nwords, &orig_line);
+ }
+
+ /* create tags for each property of each element, to be used */
+ /* later to say whether or not to store each property for the user */
+
+ for (i = 0; i < plyfile->nelems; i++) {
+ elem = plyfile->elems[i];
+ elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
+ for (j = 0; j < elem->nprops; j++)
+ elem->store_prop[j] = DONT_STORE_PROP;
+ elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
+ }
+
+ /* set return values about the elements */
+
+ elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
+ for (i = 0; i < plyfile->nelems; i++)
+ elist[i] = strdup (plyfile->elems[i]->name);
+
+ *elem_names = elist;
+ *nelems = plyfile->nelems;
+
+ /* return a pointer to the file's information */
+
+ return (plyfile);
+}
+
+
+/******************************************************************************
+Open a polygon file for reading.
+
+Entry:
+ filename - name of file to read from
+
+Exit:
+ nelems - number of elements in object
+ elem_names - list of element names
+ file_type - file type, either ascii or binary
+ version - version number of PLY file
+ returns a file identifier, used to refer to this file, or NULL if error
+******************************************************************************/
+
+PlyFile *ply_open_for_reading(
+ char *filename,
+ int *nelems,
+ char ***elem_names,
+ int *file_type,
+ float *version
+)
+{
+ FILE *fp;
+ PlyFile *plyfile;
+ char *name;
+
+ /* tack on the extension .ply, if necessary */
+
+ name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
+ strcpy (name, filename);
+ if (strlen (name) < 4 ||
+ strcmp (name + strlen (name) - 4, ".ply") != 0)
+ strcat (name, ".ply");
+
+ /* open the file for reading */
+
+ fp = fopen (name, "r");
+ if (fp == NULL)
+ return (NULL);
+
+ /* create the PlyFile data structure */
+
+ plyfile = ply_read (fp, nelems, elem_names);
+
+ /* determine the file type and version */
+
+ *file_type = plyfile->file_type;
+ *version = plyfile->version;
+
+ /* return a pointer to the file's information */
+
+ return (plyfile);
+}
+
+
+/******************************************************************************
+Get information about a particular element.
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element to get information about
+
+Exit:
+ nelems - number of elements of this type in the file
+ nprops - number of properties
+ returns a list of properties, or NULL if the file doesn't contain that elem
+******************************************************************************/
+
+PlyProperty **ply_get_element_description(
+ PlyFile *plyfile,
+ char *elem_name,
+ int *nelems,
+ int *nprops
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyProperty *prop;
+ PlyProperty **prop_list;
+
+ /* find information about the element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL)
+ return (NULL);
+
+ *nelems = elem->num;
+ *nprops = elem->nprops;
+
+ /* make a copy of the element's property list */
+ prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
+ for (i = 0; i < elem->nprops; i++) {
+ prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+ copy_property (prop, elem->props[i]);
+ prop_list[i] = prop;
+ }
+
+ /* return this duplicate property list */
+ return (prop_list);
+}
+
+
+/******************************************************************************
+Specify which properties of an element are to be returned. This should be
+called before a call to the routine ply_get_element().
+
+Entry:
+ plyfile - file identifier
+ elem_name - which element we're talking about
+ nprops - number of properties
+ prop_list - list of properties
+******************************************************************************/
+
+void ply_get_element_setup(
+ PlyFile *plyfile,
+ char *elem_name,
+ int nprops,
+ PlyProperty *prop_list
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyProperty *prop;
+ int index;
+
+ /* find information about the element */
+ elem = find_element (plyfile, elem_name);
+ plyfile->which_elem = elem;
+
+ /* deposit the property information into the element's description */
+ for (i = 0; i < nprops; i++) {
+
+ /* look for actual property */
+ prop = find_property (elem, prop_list[i].name, &index);
+ if (prop == NULL) {
+ fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
+ prop_list[i].name, elem_name);
+ continue;
+ }
+
+ /* store its description */
+ prop->internal_type = prop_list[i].internal_type;
+ prop->offset = prop_list[i].offset;
+ prop->count_internal = prop_list[i].count_internal;
+ prop->count_offset = prop_list[i].count_offset;
+
+ /* specify that the user wants this property */
+ elem->store_prop[index] = STORE_PROP;
+ }
+}
+
+
+/******************************************************************************
+Specify a property of an element that is to be returned. This should be
+called (usually multiple times) before a call to the routine ply_get_element().
+This routine should be used in preference to the less flexible old routine
+called ply_get_element_setup().
+
+Entry:
+ plyfile - file identifier
+ elem_name - which element we're talking about
+ prop - property to add to those that will be returned
+******************************************************************************/
+
+void ply_get_property(
+ PlyFile *plyfile,
+ char *elem_name,
+ PlyProperty *prop
+)
+{
+ PlyElement *elem;
+ PlyProperty *prop_ptr;
+ int index;
+
+ /* find information about the element */
+ elem = find_element (plyfile, elem_name);
+ plyfile->which_elem = elem;
+
+ /* deposit the property information into the element's description */
+
+ prop_ptr = find_property (elem, prop->name, &index);
+ if (prop_ptr == NULL) {
+ fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
+ prop->name, elem_name);
+ return;
+ }
+ prop_ptr->internal_type = prop->internal_type;
+ prop_ptr->offset = prop->offset;
+ prop_ptr->count_internal = prop->count_internal;
+ prop_ptr->count_offset = prop->count_offset;
+
+ /* specify that the user wants this property */
+ elem->store_prop[index] = STORE_PROP;
+}
+
+
+/******************************************************************************
+Read one element from the file. This routine assumes that we're reading
+the type of element specified in the last call to the routine
+ply_get_element_setup().
+
+Entry:
+ plyfile - file identifier
+ elem_ptr - pointer to location where the element information should be put
+******************************************************************************/
+
+void ply_get_element(PlyFile *plyfile, void *elem_ptr)
+{
+ if (plyfile->file_type == PLY_ASCII)
+ ascii_get_element (plyfile, (char *) elem_ptr);
+ else
+ binary_get_element (plyfile, (char *) elem_ptr);
+}
+
+
+/******************************************************************************
+Extract the comments from the header information of a PLY file.
+
+Entry:
+ plyfile - file identifier
+
+Exit:
+ num_comments - number of comments returned
+ returns a pointer to a list of comments
+******************************************************************************/
+
+char **ply_get_comments(PlyFile *plyfile, int *num_comments)
+{
+ *num_comments = plyfile->num_comments;
+ return (plyfile->comments);
+}
+
+
+/******************************************************************************
+Extract the object information (arbitrary text) from the header information
+of a PLY file.
+
+Entry:
+ plyfile - file identifier
+
+Exit:
+ num_obj_info - number of lines of text information returned
+ returns a pointer to a list of object info lines
+******************************************************************************/
+
+char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
+{
+ *num_obj_info = plyfile->num_obj_info;
+ return (plyfile->obj_info);
+}
+
+
+/******************************************************************************
+Make ready for "other" properties of an element-- those properties that
+the user has not explicitly asked for, but that are to be stashed away
+in a special structure to be carried along with the element's other
+information.
+
+Entry:
+ plyfile - file identifier
+ elem - element for which we want to save away other properties
+******************************************************************************/
+
+void setup_other_props(PlyElement *elem)
+{
+ int i;
+ PlyProperty *prop;
+ int size = 0;
+ int type_size;
+
+ /* Examine each property in decreasing order of size. */
+ /* We do this so that all data types will be aligned by */
+ /* word, half-word, or whatever within the structure. */
+
+ for (type_size = 8; type_size > 0; type_size /= 2) {
+
+ /* add up the space taken by each property, and save this information */
+ /* away in the property descriptor */
+
+ for (i = 0; i < elem->nprops; i++) {
+
+ /* don't bother with properties we've been asked to store explicitly */
+ if (elem->store_prop[i])
+ continue;
+
+ prop = elem->props[i];
+
+ /* internal types will be same as external */
+ prop->internal_type = prop->external_type;
+ prop->count_internal = prop->count_external;
+
+ /* check list case */
+ if (prop->is_list) {
+
+ /* pointer to list */
+ if (type_size == sizeof (void *)) {
+ prop->offset = size;
+ size += sizeof (void *); /* always use size of a pointer here */
+ }
+
+ /* count of number of list elements */
+ if (type_size == ply_type_size[prop->count_external]) {
+ prop->count_offset = size;
+ size += ply_type_size[prop->count_external];
+ }
+ }
+ /* not list */
+ else if (type_size == ply_type_size[prop->external_type]) {
+ prop->offset = size;
+ size += ply_type_size[prop->external_type];
+ }
+ }
+
+ }
+
+ /* save the size for the other_props structure */
+ elem->other_size = size;
+}
+
+
+/******************************************************************************
+Specify that we want the "other" properties of an element to be tucked
+away within the user's structure. The user needn't be concerned for how
+these properties are stored.
+
+Entry:
+ plyfile - file identifier
+ elem_name - name of element that we want to store other_props in
+ offset - offset to where other_props will be stored inside user's structure
+
+Exit:
+ returns pointer to structure containing description of other_props
+******************************************************************************/
+
+PlyOtherProp *ply_get_other_properties(
+ PlyFile *plyfile,
+ char *elem_name,
+ int offset
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyOtherProp *other;
+ PlyProperty *prop;
+ int nprops;
+
+ /* find information about the element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
+ elem_name);
+ return (NULL);
+ }
+
+ /* remember that this is the "current" element */
+ plyfile->which_elem = elem;
+
+ /* save the offset to where to store the other_props */
+ elem->other_offset = offset;
+
+ /* place the appropriate pointers, etc. in the element's property list */
+ setup_other_props (elem);
+
+ /* create structure for describing other_props */
+ other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
+ other->name = strdup (elem_name);
+#if 0
+ if (elem->other_offset == NO_OTHER_PROPS) {
+ other->size = 0;
+ other->props = NULL;
+ other->nprops = 0;
+ return (other);
+ }
+#endif
+ other->size = elem->other_size;
+ other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
+
+ /* save descriptions of each "other" property */
+ nprops = 0;
+ for (i = 0; i < elem->nprops; i++) {
+ if (elem->store_prop[i])
+ continue;
+ prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+ copy_property (prop, elem->props[i]);
+ other->props[nprops] = prop;
+ nprops++;
+ }
+ other->nprops = nprops;
+
+#if 1
+ /* set other_offset pointer appropriately if there are NO other properties */
+ if (other->nprops == 0) {
+ elem->other_offset = NO_OTHER_PROPS;
+ }
+#endif
+
+ /* return structure */
+ return (other);
+}
+
+
+
+
+/*************************/
+/* Other Element Stuff */
+/*************************/
+
+
+
+
+/******************************************************************************
+Grab all the data for an element that a user does not want to explicitly
+read in.
+
+Entry:
+ plyfile - pointer to file
+ elem_name - name of element whose data is to be read in
+ elem_count - number of instances of this element stored in the file
+
+Exit:
+ returns pointer to ALL the "other" element data for this PLY file
+******************************************************************************/
+
+PlyOtherElems *ply_get_other_element (
+ PlyFile *plyfile,
+ char *elem_name,
+ int elem_count
+)
+{
+ int i;
+ PlyElement *elem;
+ PlyOtherElems *other_elems;
+ OtherElem *other;
+
+ /* look for appropriate element */
+ elem = find_element (plyfile, elem_name);
+ if (elem == NULL) {
+ fprintf (stderr,
+ "ply_get_other_element: can't find element '%s'\n", elem_name);
+ exit (-1);
+ }
+
+ /* create room for the new "other" element, initializing the */
+ /* other data structure if necessary */
+
+ if (plyfile->other_elems == NULL) {
+ plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
+ other_elems = plyfile->other_elems;
+ other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
+ other = &(other_elems->other_list[0]);
+ other_elems->num_elems = 1;
+ }
+ else {
+ other_elems = plyfile->other_elems;
+ other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
+ sizeof (OtherElem) * other_elems->num_elems + 1);
+ other = &(other_elems->other_list[other_elems->num_elems]);
+ other_elems->num_elems++;
+ }
+
+ /* count of element instances in file */
+ other->elem_count = elem_count;
+
+ /* save name of element */
+ other->elem_name = strdup (elem_name);
+
+ /* create a list to hold all the current elements */
+ other->other_data = (OtherData **)
+ malloc (sizeof (OtherData *) * other->elem_count);
+
+ /* set up for getting elements */
+ other->other_props = ply_get_other_properties (plyfile, elem_name,
+ offsetof(OtherData,other_props));
+
+ /* grab all these elements */
+ for (i = 0; i < other->elem_count; i++) {
+ /* grab and element from the file */
+ other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
+ ply_get_element (plyfile, (void *) other->other_data[i]);
+ }
+
+ /* return pointer to the other elements data */
+ return (other_elems);
+}
+
+
+/******************************************************************************
+Pass along a pointer to "other" elements that we want to save in a given
+PLY file. These other elements were presumably read from another PLY file.
+
+Entry:
+ plyfile - file pointer in which to store this other element info
+ other_elems - info about other elements that we want to store
+******************************************************************************/
+
+void ply_describe_other_elements (
+ PlyFile *plyfile,
+ PlyOtherElems *other_elems
+)
+{
+ int i;
+ OtherElem *other;
+
+ /* ignore this call if there is no other element */
+ if (other_elems == NULL)
+ return;
+
+ /* save pointer to this information */
+ plyfile->other_elems = other_elems;
+
+ /* describe the other properties of this element */
+
+ for (i = 0; i < other_elems->num_elems; i++) {
+ other = &(other_elems->other_list[i]);
+ ply_element_count (plyfile, other->elem_name, other->elem_count);
+ ply_describe_other_properties (plyfile, other->other_props,
+ offsetof(OtherData,other_props));
+ }
+}
+
+
+/******************************************************************************
+Write out the "other" elements specified for this PLY file.
+
+Entry:
+ plyfile - pointer to PLY file to write out other elements for
+******************************************************************************/
+
+void ply_put_other_elements (PlyFile *plyfile)
+{
+ int i,j;
+ OtherElem *other;
+
+ /* make sure we have other elements to write */
+ if (plyfile->other_elems == NULL)
+ return;
+
+ /* write out the data for each "other" element */
+
+ for (i = 0; i < plyfile->other_elems->num_elems; i++) {
+
+ other = &(plyfile->other_elems->other_list[i]);
+ ply_put_element_setup (plyfile, other->elem_name);
+
+ /* write out each instance of the current element */
+ for (j = 0; j < other->elem_count; j++)
+ ply_put_element (plyfile, (void *) other->other_data[j]);
+ }
+}
+
+
+/******************************************************************************
+Free up storage used by an "other" elements data structure.
+
+Entry:
+ other_elems - data structure to free up
+******************************************************************************/
+
+
+
+
+/*******************/
+/* Miscellaneous */
+/*******************/
+
+
+
+/******************************************************************************
+Close a PLY file.
+
+Entry:
+ plyfile - identifier of file to close
+******************************************************************************/
+
+void ply_close(PlyFile *plyfile)
+{
+ fclose (plyfile->fp);
+
+ /* free up memory associated with the PLY file */
+ free (plyfile);
+}
+
+
+/******************************************************************************
+Get version number and file type of a PlyFile.
+
+Entry:
+ ply - pointer to PLY file
+
+Exit:
+ version - version of the file
+ file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
+******************************************************************************/
+
+void ply_get_info(PlyFile *ply, float *version, int *file_type)
+{
+ if (ply == NULL)
+ return;
+
+ *version = ply->version;
+ *file_type = ply->file_type;
+}
+
+
+/******************************************************************************
+Compare two strings. Returns 1 if they are the same, 0 if not.
+******************************************************************************/
+
+int equal_strings(char *s1, char *s2)
+{
+
+ while (*s1 && *s2)
+ if (*s1++ != *s2++)
+ return (0);
+
+ if (*s1 != *s2)
+ return (0);
+ else
+ return (1);
+}
+
+
+/******************************************************************************
+Find an element from the element list of a given PLY object.
+
+Entry:
+ plyfile - file id for PLY file
+ element - name of element we're looking for
+
+Exit:
+ returns the element, or NULL if not found
+******************************************************************************/
+
+PlyElement *find_element(PlyFile *plyfile, char *element)
+{
+ int i;
+
+ for (i = 0; i < plyfile->nelems; i++)
+ if (equal_strings (element, plyfile->elems[i]->name))
+ return (plyfile->elems[i]);
+
+ return (NULL);
+}
+
+
+/******************************************************************************
+Find a property in the list of properties of a given element.
+
+Entry:
+ elem - pointer to element in which we want to find the property
+ prop_name - name of property to find
+
+Exit:
+ index - index to position in list
+ returns a pointer to the property, or NULL if not found
+******************************************************************************/
+
+PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index)
+{
+ int i;
+
+ for (i = 0; i < elem->nprops; i++)
+ if (equal_strings (prop_name, elem->props[i]->name)) {
+ *index = i;
+ return (elem->props[i]);
+ }
+
+ *index = -1;
+ return (NULL);
+}
+
+
+/******************************************************************************
+Read an element from an ascii file.
+
+Entry:
+ plyfile - file identifier
+ elem_ptr - pointer to element
+******************************************************************************/
+
+void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
+{
+ int j,k;
+ PlyElement *elem;
+ PlyProperty *prop;
+ char **words;
+ int nwords;
+ int which_word;
+ char *elem_data,*item;
+ char *item_ptr;
+ int item_size;
+ int int_val;
+ unsigned int uint_val;
+ double double_val;
+ int list_count;
+ int store_it;
+ char **store_array;
+ char *orig_line;
+ char *other_data;
+ int other_flag;
+
+ other_flag = 0;
+ other_data = NULL;
+ item = NULL;
+ item_size = 0;
+
+ /* the kind of element we're reading currently */
+ elem = plyfile->which_elem;
+
+ /* do we need to setup for other_props? */
+
+ if (elem->other_offset != NO_OTHER_PROPS) {
+ char **ptr;
+ other_flag = 1;
+ /* make room for other_props */
+ other_data = (char *) myalloc (elem->other_size);
+ /* store pointer in user's structure to the other_props */
+ ptr = (char **) (elem_ptr + elem->other_offset);
+ *ptr = other_data;
+ } else {
+ other_flag = 0;
+ other_data = NULL;
+ item = NULL;
+ item_size = 0;
+ }
+
+ /* read in the element */
+
+ words = get_words (plyfile->fp, &nwords, &orig_line);
+ if (words == NULL) {
+ fprintf (stderr, "ply_get_element: unexpected end of file\n");
+ exit (-1);
+ }
+
+ which_word = 0;
+
+ for (j = 0; j < elem->nprops; j++) {
+
+ prop = elem->props[j];
+ store_it = (elem->store_prop[j] | other_flag);
+
+ /* store either in the user's structure or in other_props */
+ if (elem->store_prop[j])
+ elem_data = elem_ptr;
+ else
+ elem_data = other_data;
+
+ if (prop->is_list) { /* a list */
+
+ /* get and store the number of items in the list */
+ get_ascii_item (words[which_word++], prop->count_external,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ item = elem_data + prop->count_offset;
+ store_item(item, prop->count_internal, int_val, uint_val, double_val);
+ }
+
+ /* allocate space for an array of items and store a ptr to the array */
+ list_count = int_val;
+ item_size = ply_type_size[prop->internal_type];
+ store_array = (char **) (elem_data + prop->offset);
+
+ if (list_count == 0) {
+ if (store_it)
+ *store_array = NULL;
+ }
+ else {
+ if (store_it) {
+ item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
+ item = item_ptr;
+ *store_array = item_ptr;
+ }
+
+ /* read items and store them into the array */
+ for (k = 0; k < list_count; k++) {
+ get_ascii_item (words[which_word++], prop->external_type,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ store_item (item, prop->internal_type,
+ int_val, uint_val, double_val);
+ item += item_size;
+ }
+ }
+ }
+
+ }
+ else { /* not a list */
+ get_ascii_item (words[which_word++], prop->external_type,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ item = elem_data + prop->offset;
+ store_item (item, prop->internal_type, int_val, uint_val, double_val);
+ }
+ }
+
+ }
+
+ free (words);
+}
+
+
+/******************************************************************************
+Read an element from a binary file.
+
+Entry:
+ plyfile - file identifier
+ elem_ptr - pointer to an element
+******************************************************************************/
+
+void binary_get_element(PlyFile *plyfile, char *elem_ptr)
+{
+ int j,k;
+ PlyElement *elem;
+ PlyProperty *prop;
+ FILE *fp = plyfile->fp;
+ char *elem_data,*item;
+ char *item_ptr;
+ int item_size;
+ int int_val;
+ unsigned int uint_val;
+ double double_val;
+ int list_count;
+ int store_it;
+ char **store_array;
+ char *other_data;
+ int other_flag;
+
+
+ other_flag = 0;
+ other_data = NULL;
+ item = NULL;
+ item_size = 0;
+
+ /* the kind of element we're reading currently */
+ elem = plyfile->which_elem;
+
+ /* do we need to setup for other_props? */
+
+ if (elem->other_offset != NO_OTHER_PROPS) {
+ char **ptr;
+ other_flag = 1;
+ /* make room for other_props */
+ other_data = (char *) myalloc (elem->other_size);
+ /* store pointer in user's structure to the other_props */
+ ptr = (char **) (elem_ptr + elem->other_offset);
+ *ptr = other_data;
+ }
+ else {
+ other_flag = 0;
+ other_data = NULL;
+ item = NULL;
+ item_size = 0;
+ }
+ /* read in a number of elements */
+
+ for (j = 0; j < elem->nprops; j++) {
+
+ prop = elem->props[j];
+ store_it = (elem->store_prop[j] | other_flag);
+
+ /* store either in the user's structure or in other_props */
+ if (elem->store_prop[j])
+ elem_data = elem_ptr;
+ else
+ elem_data = other_data;
+
+ if (prop->is_list) { /* a list */
+
+ /* get and store the number of items in the list */
+ get_binary_item (fp, prop->count_external,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ item = elem_data + prop->count_offset;
+ store_item(item, prop->count_internal, int_val, uint_val, double_val);
+ }
+
+ /* allocate space for an array of items and store a ptr to the array */
+ list_count = int_val;
+ /* The "if" was added by Afra Zomorodian 8/22/95
+ * so that zipper won't crash reading plies that have additional
+ * properties.
+ */
+ if (store_it) {
+ item_size = ply_type_size[prop->internal_type];
+ }
+ store_array = (char **) (elem_data + prop->offset);
+ if (list_count == 0) {
+ if (store_it)
+ *store_array = NULL;
+ }
+ else {
+ if (store_it) {
+ item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
+ item = item_ptr;
+ *store_array = item_ptr;
+ }
+
+ /* read items and store them into the array */
+ for (k = 0; k < list_count; k++) {
+ get_binary_item (fp, prop->external_type,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ store_item (item, prop->internal_type,
+ int_val, uint_val, double_val);
+ item += item_size;
+ }
+ }
+ }
+
+ }
+ else { /* not a list */
+ get_binary_item (fp, prop->external_type,
+ &int_val, &uint_val, &double_val);
+ if (store_it) {
+ item = elem_data + prop->offset;
+ store_item (item, prop->internal_type, int_val, uint_val, double_val);
+ }
+ }
+
+ }
+}
+
+
+/******************************************************************************
+Write to a file the word that represents a PLY data type.
+
+Entry:
+ fp - file pointer
+ code - code for type
+******************************************************************************/
+
+void write_scalar_type (FILE *fp, int code)
+{
+ /* make sure this is a valid code */
+
+ if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
+ fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
+ exit (-1);
+ }
+
+ /* write the code to a file */
+
+ fprintf (fp, "%s", type_names[code]);
+}
+
+
+/******************************************************************************
+Get a text line from a file and break it up into words.
+
+IMPORTANT: The calling routine call "free" on the returned pointer once
+finished with it.
+
+Entry:
+ fp - file to read from
+
+Exit:
+ nwords - number of words returned
+ orig_line - the original line of characters
+ returns a list of words from the line, or NULL if end-of-file
+******************************************************************************/
+
+char **get_words(FILE *fp, int *nwords, char **orig_line)
+{
+#define BIG_STRING 4096
+ static char str[BIG_STRING];
+ static char str_copy[BIG_STRING];
+ char **words;
+ int max_words = 10;
+ int num_words = 0;
+ char *ptr,*ptr2;
+ char *result;
+
+ words = (char **) myalloc (sizeof (char *) * max_words);
+
+ /* read in a line */
+ result = fgets (str, BIG_STRING, fp);
+ if (result == NULL) {
+ *nwords = 0;
+ *orig_line = NULL;
+ return (NULL);
+ }
+
+ /* convert line-feed and tabs into spaces */
+ /* (this guarentees that there will be a space before the */
+ /* null character at the end of the string) */
+
+ str[BIG_STRING-2] = ' ';
+ str[BIG_STRING-1] = '\0';
+
+ for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
+ *ptr2 = *ptr;
+ if (*ptr == '\t') {
+ *ptr = ' ';
+ *ptr2 = ' ';
+ }
+ else if (*ptr == '\n') {
+ *ptr = ' ';
+ *ptr2 = '\0';
+ break;
+ }
+ }
+
+ /* find the words in the line */
+
+ ptr = str;
+ while (*ptr != '\0') {
+
+ /* jump over leading spaces */
+ while (*ptr == ' ')
+ ptr++;
+
+ /* break if we reach the end */
+ if (*ptr == '\0')
+ break;
+
+ /* save pointer to beginning of word */
+ if (num_words >= max_words) {
+ max_words += 10;
+ words = (char **) realloc (words, sizeof (char *) * max_words);
+ }
+ words[num_words++] = ptr;
+
+ /* jump over non-spaces */
+ while (*ptr != ' ')
+ ptr++;
+
+ /* place a null character here to mark the end of the word */
+ *ptr++ = '\0';
+ }
+
+ /* return the list of words */
+ *nwords = num_words;
+ *orig_line = str_copy;
+ return (words);
+}
+
+
+/******************************************************************************
+Return the value of an item, given a pointer to it and its type.
+
+Entry:
+ item - pointer to item
+ type - data type that "item" points to
+
+Exit:
+ returns a double-precision float that contains the value of the item
+******************************************************************************/
+
+double get_item_value(char *item, int type)
+{
+ unsigned char *puchar;
+ char *pchar;
+ short int *pshort;
+ unsigned short int *pushort;
+ int *pint;
+ unsigned int *puint;
+ float *pfloat;
+ double *pdouble;
+ int int_value;
+ unsigned int uint_value;
+ double double_value;
+
+ switch (type) {
+ case PLY_CHAR:
+ pchar = (char *) item;
+ int_value = *pchar;
+ return ((double) int_value);
+ case PLY_UCHAR:
+ puchar = (unsigned char *) item;
+ int_value = *puchar;
+ return ((double) int_value);
+ case PLY_SHORT:
+ pshort = (short int *) item;
+ int_value = *pshort;
+ return ((double) int_value);
+ case PLY_USHORT:
+ pushort = (unsigned short int *) item;
+ int_value = *pushort;
+ return ((double) int_value);
+ case PLY_INT:
+ pint = (int *) item;
+ int_value = *pint;
+ return ((double) int_value);
+ case PLY_UINT:
+ puint = (unsigned int *) item;
+ uint_value = *puint;
+ return ((double) uint_value);
+ case PLY_FLOAT:
+ pfloat = (float *) item;
+ double_value = *pfloat;
+ return (double_value);
+ case PLY_DOUBLE:
+ pdouble = (double *) item;
+ double_value = *pdouble;
+ return (double_value);
+ default:
+ fprintf (stderr, "get_item_value: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Write out an item to a file as raw binary bytes.
+
+Entry:
+ fp - file to write to
+ int_val - integer version of item
+ uint_val - unsigned integer version of item
+ double_val - double-precision float version of item
+ type - data type to write out
+******************************************************************************/
+
+void write_binary_item(
+ FILE *fp,
+ int int_val,
+ unsigned int uint_val,
+ double double_val,
+ int type
+)
+{
+ unsigned char uchar_val;
+ char char_val;
+ unsigned short ushort_val;
+ short short_val;
+ float float_val;
+
+ switch (type) {
+ case PLY_CHAR:
+ char_val = (char)int_val;
+ fwrite (&char_val, 1, 1, fp);
+ break;
+ case PLY_SHORT:
+ short_val = (short)int_val;
+ fwrite (&short_val, 2, 1, fp);
+ break;
+ case PLY_INT:
+ fwrite (&int_val, 4, 1, fp);
+ break;
+ case PLY_UCHAR:
+ uchar_val = (unsigned char) uint_val;
+ fwrite (&uchar_val, 1, 1, fp);
+ break;
+ case PLY_USHORT:
+ ushort_val = (unsigned short)uint_val;
+ fwrite (&ushort_val, 2, 1, fp);
+ break;
+ case PLY_UINT:
+ fwrite (&uint_val, 4, 1, fp);
+ break;
+ case PLY_FLOAT:
+ float_val = (float) double_val;
+ fwrite (&float_val, 4, 1, fp);
+ break;
+ case PLY_DOUBLE:
+ fwrite (&double_val, 8, 1, fp);
+ break;
+ default:
+ fprintf (stderr, "write_binary_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Write out an item to a file as ascii characters.
+
+Entry:
+ fp - file to write to
+ int_val - integer version of item
+ uint_val - unsigned integer version of item
+ double_val - double-precision float version of item
+ type - data type to write out
+******************************************************************************/
+
+void write_ascii_item(
+ FILE *fp,
+ int int_val,
+ unsigned int uint_val,
+ double double_val,
+ int type
+)
+{
+ switch (type) {
+ case PLY_CHAR:
+ case PLY_SHORT:
+ case PLY_INT:
+ fprintf (fp, "%d ", int_val);
+ break;
+ case PLY_UCHAR:
+ case PLY_USHORT:
+ case PLY_UINT:
+ fprintf (fp, "%u ", uint_val);
+ break;
+ case PLY_FLOAT:
+ case PLY_DOUBLE:
+ fprintf (fp, "%g ", double_val);
+ break;
+ default:
+ fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Write out an item to a file as ascii characters.
+
+Entry:
+ fp - file to write to
+ item - pointer to item to write
+ type - data type that "item" points to
+
+Exit:
+ returns a double-precision float that contains the value of the written item
+******************************************************************************/
+
+double old_write_ascii_item(FILE *fp, char *item, int type)
+{
+ unsigned char *puchar;
+ char *pchar;
+ short int *pshort;
+ unsigned short int *pushort;
+ int *pint;
+ unsigned int *puint;
+ float *pfloat;
+ double *pdouble;
+ int int_value;
+ unsigned int uint_value;
+ double double_value;
+
+ switch (type) {
+ case PLY_CHAR:
+ pchar = (char *) item;
+ int_value = *pchar;
+ fprintf (fp, "%d ", int_value);
+ return ((double) int_value);
+ case PLY_UCHAR:
+ puchar = (unsigned char *) item;
+ int_value = *puchar;
+ fprintf (fp, "%d ", int_value);
+ return ((double) int_value);
+ case PLY_SHORT:
+ pshort = (short int *) item;
+ int_value = *pshort;
+ fprintf (fp, "%d ", int_value);
+ return ((double) int_value);
+ case PLY_USHORT:
+ pushort = (unsigned short int *) item;
+ int_value = *pushort;
+ fprintf (fp, "%d ", int_value);
+ return ((double) int_value);
+ case PLY_INT:
+ pint = (int *) item;
+ int_value = *pint;
+ fprintf (fp, "%d ", int_value);
+ return ((double) int_value);
+ case PLY_UINT:
+ puint = (unsigned int *) item;
+ uint_value = *puint;
+ fprintf (fp, "%u ", uint_value);
+ return ((double) uint_value);
+ case PLY_FLOAT:
+ pfloat = (float *) item;
+ double_value = *pfloat;
+ fprintf (fp, "%g ", double_value);
+ return (double_value);
+ case PLY_DOUBLE:
+ pdouble = (double *) item;
+ double_value = *pdouble;
+ fprintf (fp, "%g ", double_value);
+ return (double_value);
+ default:
+ fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Get the value of an item that is in memory, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+ ptr - pointer to the item
+ type - data type supposedly in the item
+
+Exit:
+ int_val - integer value
+ uint_val - unsigned integer value
+ double_val - double-precision floating point value
+******************************************************************************/
+
+void get_stored_item(
+ void *ptr,
+ int type,
+ int *int_val,
+ unsigned int *uint_val,
+ double *double_val
+)
+{
+ switch (type) {
+ case PLY_CHAR:
+ *int_val = *((char *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_UCHAR:
+ *uint_val = *((unsigned char *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_SHORT:
+ *int_val = *((short int *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_USHORT:
+ *uint_val = *((unsigned short int *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_INT:
+ *int_val = *((int *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_UINT:
+ *uint_val = *((unsigned int *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_FLOAT:
+ *double_val = *((float *) ptr);
+ *int_val = (int)*double_val;
+ *uint_val = (unsigned int)*double_val;
+ break;
+ case PLY_DOUBLE:
+ *double_val = *((double *) ptr);
+ *int_val = (int)*double_val;
+ *uint_val =(unsigned int) *double_val;
+ break;
+ default:
+ fprintf (stderr, "get_stored_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Get the value of an item from a binary file, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+ fp - file to get item from
+ type - data type supposedly in the word
+
+Exit:
+ int_val - integer value
+ uint_val - unsigned integer value
+ double_val - double-precision floating point value
+******************************************************************************/
+
+void get_binary_item(
+ FILE *fp,
+ int type,
+ int *int_val,
+ unsigned int *uint_val,
+ double *double_val
+)
+{
+ char c[8];
+ void *ptr;
+
+ ptr = (void *) c;
+
+ switch (type) {
+ case PLY_CHAR:
+ fread (ptr, 1, 1, fp);
+ *int_val = *((char *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_UCHAR:
+ fread (ptr, 1, 1, fp);
+ *uint_val = *((unsigned char *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_SHORT:
+ fread (ptr, 2, 1, fp);
+ *int_val = *((short int *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_USHORT:
+ fread (ptr, 2, 1, fp);
+ *uint_val = *((unsigned short int *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_INT:
+ fread (ptr, 4, 1, fp);
+ *int_val = *((int *) ptr);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+ case PLY_UINT:
+ fread (ptr, 4, 1, fp);
+ *uint_val = *((unsigned int *) ptr);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+ case PLY_FLOAT:
+ fread (ptr, 4, 1, fp);
+ *double_val = *((float *) ptr);
+ *int_val = (int)*double_val;
+ *uint_val =(unsigned int) *double_val;
+ break;
+ case PLY_DOUBLE:
+ fread (ptr, 8, 1, fp);
+ *double_val = *((double *) ptr);
+ *int_val = (int)*double_val;
+ *uint_val = (unsigned int)*double_val;
+ break;
+ default:
+ fprintf (stderr, "get_binary_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Extract the value of an item from an ascii word, and place the result
+into an integer, an unsigned integer and a double.
+
+Entry:
+ word - word to extract value from
+ type - data type supposedly in the word
+
+Exit:
+ int_val - integer value
+ uint_val - unsigned integer value
+ double_val - double-precision floating point value
+******************************************************************************/
+
+void get_ascii_item(
+ char *word,
+ int type,
+ int *int_val,
+ unsigned int *uint_val,
+ double *double_val
+)
+{
+ switch (type) {
+ case PLY_CHAR:
+ case PLY_UCHAR:
+ case PLY_SHORT:
+ case PLY_USHORT:
+ case PLY_INT:
+ *int_val = atoi (word);
+ *uint_val = *int_val;
+ *double_val = *int_val;
+ break;
+
+ case PLY_UINT:
+ *uint_val = strtoul (word, (char **) NULL, 10);
+ *int_val = *uint_val;
+ *double_val = *uint_val;
+ break;
+
+ case PLY_FLOAT:
+ case PLY_DOUBLE:
+ *double_val = atof (word);
+ *int_val = (int) *double_val;
+ *uint_val = (unsigned int) *double_val;
+ break;
+
+ default:
+ fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Store a value into a place being pointed to, guided by a data type.
+
+Entry:
+ item - place to store value
+ type - data type
+ int_val - integer version of value
+ uint_val - unsigned integer version of value
+ double_val - double version of value
+
+Exit:
+ item - pointer to stored value
+******************************************************************************/
+
+void store_item (
+ char *item,
+ int type,
+ int int_val,
+ unsigned int uint_val,
+ double double_val
+)
+{
+ unsigned char *puchar;
+ short int *pshort;
+ unsigned short int *pushort;
+ int *pint;
+ unsigned int *puint;
+ float *pfloat;
+ double *pdouble;
+
+ switch (type) {
+ case PLY_CHAR:
+ *item = (char) int_val;
+ break;
+ case PLY_UCHAR:
+ puchar = (unsigned char *) item;
+ *puchar = (unsigned char)uint_val;
+ break;
+ case PLY_SHORT:
+ pshort = (short *) item;
+ *pshort = (short)int_val;
+ break;
+ case PLY_USHORT:
+ pushort = (unsigned short *) item;
+ *pushort = (unsigned short)uint_val;
+ break;
+ case PLY_INT:
+ pint = (int *) item;
+ *pint = int_val;
+ break;
+ case PLY_UINT:
+ puint = (unsigned int *) item;
+ *puint = uint_val;
+ break;
+ case PLY_FLOAT:
+ pfloat = (float *) item;
+ *pfloat = (float)double_val;
+ break;
+ case PLY_DOUBLE:
+ pdouble = (double *) item;
+ *pdouble = double_val;
+ break;
+ default:
+ fprintf (stderr, "store_item: bad type = %d\n", type);
+ exit (-1);
+ }
+}
+
+
+/******************************************************************************
+Add an element to a PLY file descriptor.
+
+Entry:
+ plyfile - PLY file descriptor
+ words - list of words describing the element
+ nwords - number of words in the list
+******************************************************************************/
+
+void add_element (PlyFile *plyfile, char **words)
+{
+ PlyElement *elem;
+
+ /* create the new element */
+ elem = (PlyElement *) myalloc (sizeof (PlyElement));
+ elem->name = strdup (words[1]);
+ elem->num = atoi (words[2]);
+ elem->nprops = 0;
+
+ /* make room for new element in the object's list of elements */
+ if (plyfile->nelems == 0)
+ plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
+ else
+ plyfile->elems = (PlyElement **) realloc (plyfile->elems,
+ sizeof (PlyElement *) * (plyfile->nelems + 1));
+
+ /* add the new element to the object's list */
+ plyfile->elems[plyfile->nelems] = elem;
+ plyfile->nelems++;
+}
+
+
+/******************************************************************************
+Return the type of a property, given the name of the property.
+
+Entry:
+ name - name of property type
+
+Exit:
+ returns integer code for property, or 0 if not found
+******************************************************************************/
+
+int get_prop_type(char *type_name)
+{
+ int i;
+
+ for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
+ if (equal_strings (type_name, type_names[i]))
+ return (i);
+
+ /* if we get here, we didn't find the type */
+ return (0);
+}
+
+
+/******************************************************************************
+Add a property to a PLY file descriptor.
+
+Entry:
+ plyfile - PLY file descriptor
+ words - list of words describing the property
+ nwords - number of words in the list
+******************************************************************************/
+
+void add_property (PlyFile *plyfile, char **words)
+{
+ PlyProperty *prop;
+ PlyElement *elem;
+
+ /* create the new property */
+
+ prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
+
+ if (equal_strings (words[1], "list")) { /* is a list */
+ prop->count_external = get_prop_type (words[2]);
+ prop->external_type = get_prop_type (words[3]);
+ prop->name = strdup (words[4]);
+ prop->is_list = 1;
+ }
+ else { /* not a list */
+ prop->external_type = get_prop_type (words[1]);
+ prop->name = strdup (words[2]);
+ prop->is_list = 0;
+ }
+
+ /* add this property to the list of properties of the current element */
+
+ elem = plyfile->elems[plyfile->nelems - 1];
+
+ if (elem->nprops == 0)
+ elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
+ else
+ elem->props = (PlyProperty **) realloc (elem->props,
+ sizeof (PlyProperty *) * (elem->nprops + 1));
+
+ elem->props[elem->nprops] = prop;
+ elem->nprops++;
+}
+
+
+/******************************************************************************
+Add a comment to a PLY file descriptor.
+
+Entry:
+ plyfile - PLY file descriptor
+ line - line containing comment
+******************************************************************************/
+
+void add_comment (PlyFile *plyfile, char *line)
+{
+ int i;
+
+ /* skip over "comment" and leading spaces and tabs */
+ i = 7;
+ while (line[i] == ' ' || line[i] == '\t')
+ i++;
+
+ ply_put_comment (plyfile, &line[i]);
+}
+
+
+/******************************************************************************
+Add a some object information to a PLY file descriptor.
+
+Entry:
+ plyfile - PLY file descriptor
+ line - line containing text info
+******************************************************************************/
+
+void add_obj_info (PlyFile *plyfile, char *line)
+{
+ int i;
+
+ /* skip over "obj_info" and leading spaces and tabs */
+ i = 8;
+ while (line[i] == ' ' || line[i] == '\t')
+ i++;
+
+ ply_put_obj_info (plyfile, &line[i]);
+}
+
+
+/******************************************************************************
+Copy a property.
+******************************************************************************/
+
+void copy_property(PlyProperty *dest, PlyProperty *src)
+{
+ dest->name = strdup (src->name);
+ dest->external_type = src->external_type;
+ dest->internal_type = src->internal_type;
+ dest->offset = src->offset;
+
+ dest->is_list = src->is_list;
+ dest->count_external = src->count_external;
+ dest->count_internal = src->count_internal;
+ dest->count_offset = src->count_offset;
+}
+
+
+/******************************************************************************
+Allocate some memory.
+
+Entry:
+ size - amount of memory requested (in bytes)
+ lnum - line number from which memory was requested
+ fname - file name from which memory was requested
+******************************************************************************/
+
+static char *my_alloc(int size, int lnum, char *fname)
+{
+ char *ptr;
+
+ ptr = (char *) malloc (size);
+
+ if (ptr == 0) {
+ fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname);
+ }
+
+ return (ptr);
+}
+
diff --git a/intern/bsp/test/Makefile b/intern/bsp/test/Makefile
new file mode 100644
index 00000000000..17ed638d745
--- /dev/null
+++ b/intern/bsp/test/Makefile
@@ -0,0 +1,72 @@
+#
+# $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.
+#
+# 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 *****
+# bsp test makefile.
+#
+
+LIBNAME = bsp
+SOURCEDIR = intern/$(LIBNAME)/test
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+DIRS = BSP_GhostTest
+
+include nan_subdirs.mk
+
+include nan_link.mk
+
+LIBS = $(OCGDIR)/intern/$(LIBNAME)/test/BSP_GhostTest/$(DEBUG_DIR)libBSP_GhostTest.a
+LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libbsp.a
+
+SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
+SLIBS += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
+SLIBS += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
+ LLIBS = -L/usr/X11R6/lib -lglut -pthread -lXi -lXmu
+endif
+
+all debug:: $(LIBS) $(DIR)/$(DEBUG_DIR)BSPGhostTest
+
+$(DIR)/$(DEBUG_DIR)BSPGhostTest:
+ @echo "****> linking $@ in $(DIR)"
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)BSPGhostTest $(LIBS) $(SLIBS) $(LLIBS) $(DADD)
+
+clean::
+ $(RM) $(DIR)/BSPGhostTest $(DIR)/debug/BSPGhostTest
+
+test:: all
+ $(DIR)/BSPGhostTest
+
+
+
+
+
diff --git a/intern/container/CTR_List.h b/intern/container/CTR_List.h
new file mode 100644
index 00000000000..29d7c2f8de1
--- /dev/null
+++ b/intern/container/CTR_List.h
@@ -0,0 +1,144 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#ifndef CTR_LIST_H
+#define CTR_LIST_H
+
+class CTR_Link {
+public:
+ CTR_Link(
+ ) ;
+
+ CTR_Link(
+ CTR_Link *next,
+ CTR_Link *prev
+ ) ;
+
+ CTR_Link *
+ getNext(
+ ) const ;
+
+ CTR_Link *
+ getPrev(
+ ) const ;
+
+ bool
+ isHead(
+ ) const ;
+
+ bool
+ isTail(
+ ) const ;
+
+ void
+ insertBefore(
+ CTR_Link *link
+ ) ;
+
+ void
+ insertAfter(
+ CTR_Link *link
+ ) ;
+
+ void
+ remove(
+ ) ;
+
+private:
+ CTR_Link *m_next;
+ CTR_Link *m_prev;
+};
+
+class CTR_List {
+public:
+
+ CTR_List(
+ ) ;
+
+ CTR_Link *
+ getHead(
+ ) const ;
+
+ CTR_Link *
+ getTail(
+ ) const ;
+
+ void
+ addHead(
+ CTR_Link *link
+ ) ;
+
+ void
+ addTail(
+ CTR_Link *link
+ ) ;
+
+private:
+ CTR_Link m_head;
+ CTR_Link m_tail;
+};
+
+#endif
+
+
+
diff --git a/intern/container/CTR_Map.h b/intern/container/CTR_Map.h
new file mode 100644
index 00000000000..348807212b6
--- /dev/null
+++ b/intern/container/CTR_Map.h
@@ -0,0 +1,152 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef CTR_MAP_H
+
+#define CTR_MAP_H
+
+template <class Key, class Value>
+class CTR_Map {
+private:
+ struct Entry {
+ Entry (Entry *next, Key key, Value value) :
+ m_next(next),
+ m_key(key),
+ m_value(value) {}
+
+ Entry *m_next;
+ Key m_key;
+ Value m_value;
+ };
+
+public:
+ CTR_Map(int num_buckets = 100) : m_num_buckets(num_buckets) {
+ m_buckets = new Entry *[num_buckets];
+ for (int i = 0; i < num_buckets; ++i) {
+ m_buckets[i] = 0;
+ }
+ }
+
+ int size() {
+ int count=0;
+ for (int i=0;i<m_num_buckets;i++)
+ {
+ Entry* bucket = m_buckets[i];
+ while(bucket)
+ {
+ bucket = bucket->m_next;
+ count++;
+ }
+ }
+ return count;
+ }
+
+ Value* at(int index) {
+ int count=0;
+ for (int i=0;i<m_num_buckets;i++)
+ {
+ Entry* bucket = m_buckets[i];
+ while(bucket)
+ {
+ if (count==index)
+ {
+ return &bucket->m_value;
+ }
+ bucket = bucket->m_next;
+ count++;
+ }
+ }
+ return 0;
+ }
+
+ void clear() {
+ for (int i = 0; i < m_num_buckets; ++i) {
+ Entry *entry_ptr = m_buckets[i];
+
+ while (entry_ptr != 0) {
+ Entry *tmp_ptr = entry_ptr->m_next;
+ delete entry_ptr;
+ entry_ptr = tmp_ptr;
+ }
+ m_buckets[i] = 0;
+ }
+ }
+
+ ~CTR_Map() {
+ clear();
+ delete [] m_buckets;
+ }
+
+ void insert(const Key& key, const Value& value) {
+ Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets];
+ while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) {
+ entry_ptr = entry_ptr->m_next;
+ }
+
+ if (entry_ptr != 0) {
+ entry_ptr->m_value = value;
+ }
+ else {
+ Entry **bucket = &m_buckets[key.hash() % m_num_buckets];
+ *bucket = new Entry(*bucket, key, value);
+ }
+ }
+
+ void remove(const Key& key) {
+ Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets];
+ while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) {
+ entry_ptr = &(*entry_ptr)->m_next;
+ }
+
+ if (*entry_ptr != 0) {
+ Entry *tmp_ptr = (*entry_ptr)->m_next;
+ delete *entry_ptr;
+ *entry_ptr = tmp_ptr;
+ }
+ }
+
+ Value *operator[](Key key) {
+ Entry *bucket = m_buckets[key.hash() % m_num_buckets];
+ while ((bucket != 0) && !(key == bucket->m_key)) {
+ bucket = bucket->m_next;
+ }
+ return bucket != 0 ? &bucket->m_value : 0;
+ }
+
+private:
+ int m_num_buckets;
+ Entry **m_buckets;
+};
+
+#endif
+
+
+
diff --git a/intern/container/CTR_TaggedIndex.h b/intern/container/CTR_TaggedIndex.h
new file mode 100644
index 00000000000..026819d465c
--- /dev/null
+++ b/intern/container/CTR_TaggedIndex.h
@@ -0,0 +1,226 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Simple tagged index class.
+ */
+
+#ifndef NAN_INCLUDED_CTR_TaggedIndex_h
+#define NAN_INCLUDED_CTR_TaggedIndex_h
+
+/**
+ * This class is supposed to be a simple tagged index class. If these
+ * were indices into a mesh then we would never need 32 bits for such indices.
+ * It is often handy to have a few extra bits around to mark objects etc. We
+ * steal a few bits of CTR_TaggedIndex objects for this purpose. From the outside
+ * it will behave like a standard unsigned int but just carry the extra tag
+ * information around with it.
+ */
+
+#include <functional>
+
+enum {
+
+ empty_tag = 0x0,
+ empty_index = 0xffffffff
+};
+
+template <
+ int tag_shift,
+ int index_mask
+> class CTR_TaggedIndex {
+public:
+ CTR_TaggedIndex(
+ ) :
+ m_val ((empty_tag << tag_shift) | (empty_index & index_mask))
+ {
+ }
+
+ CTR_TaggedIndex(
+ const int val
+ ) :
+ m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) {
+ }
+
+ CTR_TaggedIndex(
+ const unsigned int val
+ ) :
+ m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) {
+ }
+
+ CTR_TaggedIndex(
+ const long int val
+ ) :
+ m_val ( ((long int) val & index_mask)
+ | ( (empty_tag << tag_shift)
+ & (~index_mask)) ) {
+ }
+
+ CTR_TaggedIndex(
+ const long unsigned int val
+ ) :
+ m_val ( ((long unsigned int)val & index_mask)
+ | ( (empty_tag << tag_shift)
+ & (~index_mask) ) ) {
+ }
+
+
+ CTR_TaggedIndex(
+ const CTR_TaggedIndex &my_index
+ ):
+ m_val(my_index.m_val)
+ {
+ }
+
+ bool
+ operator == (
+ const CTR_TaggedIndex& rhs
+ ) const {
+
+ return ((this->m_val & index_mask) == (rhs.m_val & index_mask));
+ }
+
+ operator unsigned int () const {
+ return m_val & index_mask;
+ }
+
+ operator unsigned long int () const {
+ return (unsigned long int)(m_val & index_mask);
+ }
+
+ operator int () const {
+ return int(m_val & index_mask);
+ }
+
+ operator long int () const {
+ return (long int)(m_val & index_mask);
+ }
+
+ bool
+ IsEmpty(
+ ) const {
+ return ((m_val & index_mask) == (empty_index & index_mask));
+ }
+
+
+ static
+ CTR_TaggedIndex
+ Empty(
+ ) {
+ return CTR_TaggedIndex();
+ }
+
+ void
+ Invalidate(
+ ) {
+ m_val = (empty_tag << tag_shift) | (empty_index & index_mask);
+ }
+
+
+ unsigned int
+ Tag (
+ ) const {
+ return m_val >> tag_shift;
+ }
+
+ void
+ SetTag(
+ unsigned int tag
+ ) {
+ m_val = (m_val & index_mask) | ((tag << tag_shift) & (~index_mask));
+ }
+
+ void
+ EmptyTag(
+ ) {
+ m_val = (m_val & index_mask) | ((empty_tag << tag_shift) & (~index_mask));
+ }
+
+ bool
+ IsEmptyTag(
+ ) const {
+ return (Tag() == Empty().Tag());
+ }
+
+ // functionals
+
+ struct greater : std::binary_function<CTR_TaggedIndex, CTR_TaggedIndex, bool>
+ {
+ bool
+ operator()(
+ const CTR_TaggedIndex& a,
+ const CTR_TaggedIndex& b
+ ) const {
+ return (int(a) > int(b));
+ }
+ };
+
+
+private :
+ CTR_TaggedIndex(
+ const CTR_TaggedIndex *index
+ ) {};
+
+ unsigned int m_val;
+
+
+};
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/container/CTR_TaggedSetOps.h b/intern/container/CTR_TaggedSetOps.h
new file mode 100644
index 00000000000..fc12f6fed04
--- /dev/null
+++ b/intern/container/CTR_TaggedSetOps.h
@@ -0,0 +1,287 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_LOD_TaggedSetOps_h
+
+#define NAN_INCLUDED_LOD_TaggedSetOps_h
+
+#include "MEM_NonCopyable.h"
+#include <vector>
+
+/**
+ * This class contains some utility functions for finding the intersection,
+ * union, and difference of a collection of stl vector of indices into
+ * a set of primitives.
+ *
+ * These are mainly used as helper functions in the decimation and bsp
+ * libraries.
+ *
+ * This template class assumes that each value of type IndexType encountered
+ * in the list is a valid index into an array of primitives. This is not
+ * checked at run-time and is left to the user to insure. Prmitives of
+ * type ObjectType must have the following public methods to be used by
+ * this template class:
+ *
+ * int
+ * OpenTag(void) --- return a persistent tag value for the primitive
+ *
+ * void
+ * SetOpenTag(int bla) --- set the persistent tag value for this primitive to bla.
+ *
+ * bool
+ * SelectTag() --- return a persistent boolean tag for this primitive
+ *
+ * void
+ * SetSelectTag(bool bla) --- set the persistent boolean tag for this primitive to bla.
+ *
+ * Here persistent means that the tag should be associated with the object for the
+ * entire lifetime of the primitive. Again none of this stuff is enforced you have
+ * to make sure that your primitives do the right thing. Often these tags can be
+ * cunningly stowed away inside some of the spare bits in the primitive. See
+ * CTR_TaggedIndex for such a class.
+ *
+ */
+
+template
+<class IndexType, class ObjectType>
+class CTR_TaggedSetOps : public MEM_NonCopyable {
+
+public :
+
+ static
+ void
+ Intersect(
+ const std::vector< std::vector<IndexType> > &index_list,
+ std::vector<ObjectType> &primitives,
+ std::vector<IndexType> &output,
+ unsigned int mask,
+ unsigned int shift
+ ) {
+
+ // iterate through vectors in index_list
+ // iterate through individual members of each vector
+ // mark each obejct that the index points to
+
+ std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end();
+ std::vector< std::vector<IndexType> >::const_iterator start_vector = index_list.begin();
+
+ // FIXME some temporary space
+
+ std::vector<IndexType> temp_union;
+ temp_union.reserve(64);
+
+ int tag_num = 0;
+
+ for (; start_vector != last_vector; ++start_vector) {
+
+ std::vector<IndexType>::const_iterator last_index = start_vector->end();
+ std::vector<IndexType>::const_iterator start_index = start_vector->begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+
+ if (!prim.OpenTag()) {
+ // compute the union
+ temp_union.push_back(*start_index);
+ }
+ int tag = prim.OpenTag();
+ tag = (tag & mask) >> shift;
+ tag += 1;
+ prim.SetOpenTag((prim.OpenTag() & ~mask)| ((tag << shift) & mask));
+ }
+
+ ++tag_num;
+ }
+
+ // now iterate through the union and pull out all those with the right tag
+
+ std::vector<IndexType>::const_iterator last_index = temp_union.end();
+ std::vector<IndexType>::const_iterator start_index = temp_union.begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+
+ if (prim.OpenTag() == tag_num) {
+ //it's part of the intersection!
+
+ output.push_back(*start_index);
+ // because we're iterating through the union
+ // it's safe to remove the tag at this point
+
+ prim.SetOpenTag(prim.OpenTag() & ~mask);
+ }
+ }
+ };
+
+ // note not a strict set intersection!
+ // if x appears twice in b and is part of the intersection
+ // it will appear twice in the intersection
+
+ static
+ void
+ IntersectPair(
+ const std::vector<IndexType> &a,
+ const std::vector<IndexType> &b,
+ std::vector<ObjectType> &primitives,
+ std::vector<IndexType> &output
+ ) {
+
+ std::vector<IndexType>::const_iterator last_index = a.end();
+ std::vector<IndexType>::const_iterator start_index = a.begin();
+
+ for (; start_index != last_index; ++start_index) {
+ ObjectType & prim = primitives[*start_index];
+ prim.SetSelectTag(true);
+ }
+ last_index = b.end();
+ start_index = b.begin();
+
+ for (; start_index != last_index; ++start_index) {
+ ObjectType & prim = primitives[*start_index];
+ if (prim.SelectTag()) {
+ output.push_back(*start_index);
+ }
+ }
+ // deselect
+ last_index = a.end();
+ start_index = a.begin();
+
+ for (; start_index != last_index; ++start_index) {
+ ObjectType & prim = primitives[*start_index];
+ prim.SetSelectTag(false);
+ }
+ };
+
+
+ static
+ void
+ Union(
+ std::vector< std::vector<IndexType> > &index_list,
+ std::vector<ObjectType> &primitives,
+ std::vector<IndexType> &output
+ ) {
+
+ // iterate through vectors in index_list
+ // iterate through individual members of each vector
+ // mark each obejct that the index points to
+
+ std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end();
+ std::vector< std::vector<IndexType> >::iterator start_vector = index_list.begin();
+
+ for (; start_vector != last_vector; ++start_vector) {
+
+ std::vector<IndexType>::const_iterator last_index = start_vector->end();
+ std::vector<IndexType>::iterator start_index = start_vector->begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+
+ if (!prim.SelectTag()) {
+ // compute the union
+ output.push_back(*start_index);
+ prim.SetSelectTag(true);
+ }
+ }
+ }
+
+ // now iterate through the union and reset the tags
+
+ std::vector<IndexType>::const_iterator last_index = output.end();
+ std::vector<IndexType>::iterator start_index = output.begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+ prim.SetSelectTag(false);
+ }
+ }
+
+
+ static
+ void
+ Difference(
+ std::vector< IndexType> &a,
+ std::vector< IndexType> &b,
+ std::vector<ObjectType> &primitives,
+ std::vector< IndexType> &output
+ ) {
+
+ // iterate through b mark all
+ // iterate through a and add to output all unmarked
+
+ std::vector<IndexType>::const_iterator last_index = b.end();
+ std::vector<IndexType>::iterator start_index = b.begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+ prim.SetSelectTag(true);
+ }
+
+ last_index = a.end();
+ start_index = a.begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+ if (!prim.SelectTag()) {
+ output.push_back(*start_index);
+ }
+ }
+
+ // clean up the tags
+
+ last_index = b.end();
+ start_index = b.begin();
+
+ for (; start_index != last_index; ++start_index) {
+
+ ObjectType & prim = primitives[*start_index];
+ prim.SetSelectTag(false);
+ }
+ };
+
+private :
+
+ // private constructor - this class is not meant for
+ // instantiation
+
+ CTR_TaggedSetOps();
+
+};
+
+
+
+#endif
+
diff --git a/intern/container/CTR_UHeap.h b/intern/container/CTR_UHeap.h
new file mode 100644
index 00000000000..251e020aba3
--- /dev/null
+++ b/intern/container/CTR_UHeap.h
@@ -0,0 +1,303 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ * @mainpage CTR_UHeap an updatable heap template class (also
+ * known as an updatable priority queue)
+ *
+ * Todo: Make CTR_UHeapable a template class with m_key the
+ * template parameter, so that arbitrary value types with
+ * operators (=,>) defined can be used.
+ *
+ */
+
+#ifndef NAN_INCLUDED_CTR_UHeap_h
+#define NAN_INCLUDED_CTR_UHeap_h
+
+#include <vector>
+#include "MEM_NonCopyable.h"
+
+class CTR_UHeapable {
+
+public :
+ int &
+ HeapPos(
+ ){
+ return m_ind;
+ };
+ float &
+ HeapKey(
+ ) {
+ return m_key;
+ };
+
+ const
+ float &
+ HeapKey(
+ ) const {
+ return m_key;
+ };
+
+ const
+ int &
+ HeapPos(
+ ) const {
+ return m_ind;
+ };
+
+private :
+
+ float m_key;
+ int m_ind;
+
+protected :
+
+ CTR_UHeapable(
+ ) : m_key (0),
+ m_ind (0)
+ {
+ };
+
+ ~CTR_UHeapable(
+ ){
+ };
+};
+
+template <class HeapType>
+class CTR_UHeap : public MEM_NonCopyable
+{
+
+public:
+
+ static
+ CTR_UHeap *
+ New(
+ ) {
+ return new CTR_UHeap();
+ }
+
+ void
+ MakeHeap(
+ HeapType *base
+ ) {
+ int i;
+ int start = Parent(m_vector.size()-1);
+ for (i = start; i >=0; --i) {
+ DownHeap(base,i);
+ }
+ };
+
+ void
+ Insert(
+ HeapType *base,
+ int elem
+ ) {
+ // add element to vector
+ m_vector.push_back(elem);
+ base[elem].HeapPos() = m_vector.size()-1;
+
+ // push the element up the heap
+ UpHeap(base,m_vector.size()-1);
+ }
+
+ // access to the vector for initial loading of elements
+
+ std::vector<int> &
+ HeapVector(
+ ) {
+ return m_vector;
+ };
+
+
+ void
+ Remove(
+ HeapType *base,
+ int i
+ ) {
+
+ // exchange with last element - pop last
+ // element and move up or down the heap as appropriate
+ if (m_vector.empty()) {
+ assert(false);
+ }
+
+ if (i != int(m_vector.size())-1) {
+
+ Swap(base,i,m_vector.size() - 1);
+ m_vector.pop_back();
+
+ if (!m_vector.empty()) {
+ UpHeap(base,i);
+ DownHeap(base,i);
+ }
+ } else {
+ m_vector.pop_back();
+ }
+ }
+
+ int
+ Top(
+ ) const {
+ if (m_vector.empty()) return -1;
+ return m_vector[0];
+ }
+
+
+ void
+ SC_Heap(
+ HeapType *base
+ ) {
+ int i;
+ for (i = 1; i < int(m_vector.size()) ; i++) {
+
+ CTR_UHeapable * elem = base + m_vector[i];
+ CTR_UHeapable * p_elem = base + m_vector[Parent(i)];
+
+ assert(p_elem->HeapKey() >= elem->HeapKey());
+ assert(elem->HeapPos() == i);
+ }
+
+ };
+
+
+ ~CTR_UHeap(
+ ) {
+ };
+
+
+private:
+
+ CTR_UHeap(
+ ) {
+ };
+
+
+ std::vector<int> m_vector;
+
+private:
+ void
+ Swap(
+ HeapType *base,
+ int i,
+ int j
+ ){
+ std::swap(m_vector[i],m_vector[j]);
+
+ CTR_UHeapable *heap_i = base + m_vector[i];
+ CTR_UHeapable *heap_j = base + m_vector[j];
+
+ // Exchange heap positions
+ heap_i->HeapPos() = i;
+ heap_j->HeapPos() = j;
+ }
+
+ int
+ Parent(
+ unsigned int i
+ ) {
+ return (i-1) >> 1;
+ }
+ int
+ Left(
+ int i
+ ) {
+ return (i<<1)+1;
+ }
+
+ int
+ Right(
+ int i
+ ) {
+ return (i<<1)+2;
+ }
+
+ float
+ HeapVal(
+ HeapType *base,
+ int i
+ ) {
+ return base[m_vector[i]].HeapKey();
+ }
+
+ void
+ DownHeap(
+ HeapType *base,
+ int i
+ ) {
+ int heap_size = m_vector.size();
+
+ int l = Left(i);
+ int r = Right(i);
+
+ int largest;
+ if (l < heap_size && HeapVal(base,l) > HeapVal(base,i)) {
+ largest = l;
+ } else {
+ largest = i;
+ }
+
+ if (r < heap_size && HeapVal(base,r) > HeapVal(base,largest)) {
+ largest = r;
+ }
+
+ if (largest != i) {
+ // exchange i and largest
+ Swap(base,i,largest);
+ DownHeap(base,largest);
+ }
+ }
+
+ void
+ UpHeap(
+ HeapType *base,
+ int i
+ ) {
+
+ // swap parents untill it's found a place in the heap < it's parent or
+ // top of heap
+
+ while (i > 0) {
+ int p = Parent(i);
+ if (HeapVal(base,i) < HeapVal(base,p)) {
+ break;
+ }
+ Swap(base,p,i);
+ i = p;
+ }
+ }
+};
+
+#endif
diff --git a/intern/container/Makefile b/intern/container/Makefile
new file mode 100644
index 00000000000..31ca8e8ae1a
--- /dev/null
+++ b/intern/container/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# container main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = container
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+#not yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_CONTAINER) ] || mkdir $(NAN_CONTAINER)
+ @[ -d $(NAN_CONTAINER)/include ] || mkdir $(NAN_CONTAINER)/include
+ @[ -d $(NAN_CONTAINER)/lib ] || mkdir $(NAN_CONTAINER)/lib
+ @[ -d $(NAN_CONTAINER)/lib/debug ] || mkdir $(NAN_CONTAINER)/lib/debug
+ cp -f $(DIR)/libcontainer.a $(NAN_CONTAINER)/lib/
+ cp -f $(DIR)/debug/libcontainer.a $(NAN_CONTAINER)/lib/debug
+ cp -f *.h $(NAN_CONTAINER)/include/
+
diff --git a/intern/container/intern/CTR_List.cpp b/intern/container/intern/CTR_List.cpp
new file mode 100644
index 00000000000..2e8c1bb13d2
--- /dev/null
+++ b/intern/container/intern/CTR_List.cpp
@@ -0,0 +1,149 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "CTR_List.h"
+
+
+CTR_Link::
+CTR_Link(
+) :
+ m_next(0),
+ m_prev(0)
+{
+}
+
+CTR_Link::
+CTR_Link(
+ CTR_Link *next,
+ CTR_Link *prev
+) :
+ m_next(next),
+ m_prev(prev)
+{
+}
+
+ CTR_Link *
+CTR_Link::
+getNext(
+) const {
+ return m_next;
+}
+
+ CTR_Link *
+CTR_Link::
+getPrev(
+) const {
+ return m_prev;
+}
+
+ bool
+CTR_Link::
+isHead(
+) const {
+ return m_prev == 0;
+}
+
+ bool
+CTR_Link::
+isTail(
+) const {
+ return m_next == 0;
+}
+
+ void
+CTR_Link::
+insertBefore(
+ CTR_Link *link
+) {
+ m_next = link;
+ m_prev = link->m_prev;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+}
+
+ void
+CTR_Link::
+insertAfter(
+ CTR_Link *link
+) {
+ m_next = link->m_next;
+ m_prev = link;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+}
+
+ void
+CTR_Link::
+remove(
+) {
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+}
+
+
+CTR_List::
+CTR_List(
+) :
+ m_head(&m_tail, 0),
+ m_tail(0, &m_head)
+{
+}
+
+ CTR_Link *
+CTR_List::
+getHead(
+) const {
+ return m_head.getNext();
+}
+
+ CTR_Link *
+CTR_List::
+getTail(
+) const {
+ return m_tail.getPrev();
+}
+
+ void
+CTR_List::
+addHead(
+ CTR_Link *link
+) {
+ link->insertAfter(&m_head);
+}
+
+ void
+CTR_List::
+addTail(
+ CTR_Link *link
+) {
+ link->insertBefore(&m_tail);
+}
+
diff --git a/intern/container/intern/Makefile b/intern/container/intern/Makefile
new file mode 100644
index 00000000000..292df5b7cbc
--- /dev/null
+++ b/intern/container/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# container intern Makefile
+#
+
+LIBNAME = container
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I..
+
diff --git a/intern/container/make/msvc_6_0/container.dsp b/intern/container/make/msvc_6_0/container.dsp
new file mode 100644
index 00000000000..05faf85d1d3
--- /dev/null
+++ b/intern/container/make/msvc_6_0/container.dsp
@@ -0,0 +1,133 @@
+# Microsoft Developer Studio Project File - Name="container" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=container - 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 "container.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 "container.mak" CFG="container - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "container - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "container - 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)" == "container - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# 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 /Ob2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\libcontainer.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\container\include\" ECHO Copying lib COPY "Release\libcontainer.lib" "..\..\..\..\lib\windows\container\lib\libcontainer.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "container - 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 "Debug"
+# PROP Intermediate_Dir "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 /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\libcontainer.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\container\include\" ECHO Copying lib COPY "Debug\libcontainer.lib" "..\..\..\..\lib\windows\container\lib\debug\libcontainer.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\container\lib\debug\" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "container - Win32 Release"
+# Name "container - Win32 Debug"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\CTR_List.cpp
+
+!IF "$(CFG)" == "container - Win32 Release"
+
+# ADD CPP /I "../extern" /I "../../"
+
+!ELSEIF "$(CFG)" == "container - Win32 Debug"
+
+# ADD CPP /I "../../"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\CTR_List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CTR_Map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CTR_TaggedIndex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CTR_TaggedSetOps.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CTR_UHeap.h
+# End Source File
+# End Target
+# End Project
diff --git a/intern/container/make/msvc_6_0/container.dsw b/intern/container/make/msvc_6_0/container.dsw
new file mode 100644
index 00000000000..adaf6dd202e
--- /dev/null
+++ b/intern/container/make/msvc_6_0/container.dsw
@@ -0,0 +1,30 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "container"=.\container.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/decimation/Makefile b/intern/decimation/Makefile
new file mode 100644
index 00000000000..f0d9567a618
--- /dev/null
+++ b/intern/decimation/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# decimation main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = decimation
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_DECIMATION) ] || mkdir $(NAN_DECIMATION)
+ @[ -d $(NAN_DECIMATION)/include ] || mkdir $(NAN_DECIMATION)/include
+ @[ -d $(NAN_DECIMATION)/lib ] || mkdir $(NAN_DECIMATION)/lib
+ @[ -d $(NAN_DECIMATION)/lib/debug ] || mkdir $(NAN_DECIMATION)/lib/debug
+ cp -f $(DIR)/libdecimation.a $(NAN_DECIMATION)/lib/
+ cp -f $(DIR)/debug/libdecimation.a $(NAN_DECIMATION)/lib/debug/
+ cp -f extern/*.h $(NAN_DECIMATION)/include/
+
diff --git a/intern/decimation/extern/LOD_decimation.h b/intern/decimation/extern/LOD_decimation.h
new file mode 100644
index 00000000000..7a74dde165a
--- /dev/null
+++ b/intern/decimation/extern/LOD_decimation.h
@@ -0,0 +1,119 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * @author Laurence Bourn
+ * @date 6/7/2001
+ *
+ * This is the external interface for the decimation module.
+ */
+
+#ifndef NAN_INCLUDED_LOD_decimation_h
+#define NAN_INCLUDED_LOD_decimation_h
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * External decimation structure
+ */
+
+typedef struct LOD_Decimation_Info {
+ float * vertex_buffer;
+ float * vertex_normal_buffer;
+ int * triangle_index_buffer;
+ int vertex_num;
+ int face_num;
+ void * intern;
+} LOD_Decimation_Info;
+
+typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr;
+
+/**
+ * Create internal mesh representation from
+ * LOD_Decimation_Info structure.
+ * @return 1 on successful loading
+ * @return 0 on failure
+ * @warning This should be changed to return an enumeration
+ * detailing the error encountered
+ */
+
+extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info);
+
+/**
+ * Allocate and Compute internal data strucures required for
+ * decimation.
+ * @return 1 on successful computation of data
+ * @return 0 on failure
+ * @warning This should be changed to return an enumeration
+ * detailing the error encountered
+ */
+
+extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info);
+
+/**
+ * Once both the stages above have been completed
+ * this function collapses a single edge in the mesh.
+ * The LOD_Decimation_Info structure is updated
+ * to represent the new mesh.
+ * @return 1 if an edge was collapsed.
+ * @return 0 if no suitable edge was found to be collapsable
+ * You should stop calling this method in this case
+ * @warning Do not expect that the order of polygons, vertices or
+ * vertex normals will be preserved by this operation. This function
+ * returns a packed array of polygons and vertices and so necessarily
+ * the order will be different. This means you should not expect to
+ * find the same polygon in the same place in the polygon array after
+ * this function has been called.
+ */
+
+extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info);
+
+/**
+ * Free any memory the decimation process used
+ * during the decimation process
+ * @return 1 if internal data successfully freed
+ * @return 0 if no data was freed
+ */
+
+extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NAN_INCLUDED_LOD_decimation_h
+
+
+
diff --git a/intern/decimation/intern/LOD_DecimationClass.h b/intern/decimation/intern/LOD_DecimationClass.h
new file mode 100644
index 00000000000..7df294daaee
--- /dev/null
+++ b/intern/decimation/intern/LOD_DecimationClass.h
@@ -0,0 +1,118 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_LOD_DecimationClass_h
+
+#define NAN_INCLUDED_LOD_DecimationClass_h
+
+#include "MEM_SmartPtr.h"
+#include "MEM_NonCopyable.h"
+
+#include "LOD_ManMesh2.h"
+#include "LOD_QSDecimator.h"
+#include "LOD_ExternNormalEditor.h"
+#include "../extern/LOD_decimation.h"
+#include "LOD_ExternBufferEditor.h"
+
+
+class LOD_DecimationClass : public MEM_NonCopyable
+{
+public :
+
+ enum {
+ e_not_loaded,
+ e_loaded,
+ e_preprocessed
+ } m_e_decimation_state;
+
+
+ static
+ LOD_DecimationClass *
+ New(
+ LOD_Decimation_InfoPtr extern_info
+ ) {
+ // create everything
+
+ MEM_SmartPtr<LOD_DecimationClass> output(new LOD_DecimationClass());
+ MEM_SmartPtr<LOD_ManMesh2> mesh(LOD_ManMesh2::New());
+ MEM_SmartPtr<LOD_ExternBufferEditor> extern_editor(LOD_ExternBufferEditor::New(extern_info));
+
+ if (mesh == NULL || extern_editor == NULL) return NULL;
+ MEM_SmartPtr<LOD_ExternNormalEditor> normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref()));
+
+ if (normals == NULL) return NULL;
+ MEM_SmartPtr<LOD_QSDecimator> decimator(LOD_QSDecimator::New(
+ mesh.Ref(),
+ normals.Ref(),
+ extern_editor.Ref()
+ ));
+ if (decimator == NULL || output == NULL) return NULL;
+
+ output->m_mesh = mesh.Release();
+ output->m_decimator = decimator.Release();
+ output->m_normals = normals.Release();
+ output->m_extern_editor = extern_editor.Release();
+
+ return output.Release();
+ }
+
+ LOD_ManMesh2 &
+ Mesh(
+ ){
+ return m_mesh.Ref();
+ }
+
+ LOD_QSDecimator &
+ Decimator(
+ ) {
+ return m_decimator.Ref();
+ }
+
+ LOD_ExternNormalEditor &
+ FaceEditor(
+ ){
+ return m_normals.Ref();
+ }
+
+private :
+
+ LOD_DecimationClass(
+ ) : m_e_decimation_state(e_not_loaded) {
+ };
+
+ MEM_SmartPtr<LOD_ManMesh2> m_mesh;
+ MEM_SmartPtr<LOD_QSDecimator> m_decimator;
+ MEM_SmartPtr<LOD_ExternNormalEditor> m_normals;
+ MEM_SmartPtr<LOD_ExternBufferEditor> m_extern_editor;
+};
+
+
+#endif
diff --git a/intern/decimation/intern/LOD_EdgeCollapser.cpp b/intern/decimation/intern/LOD_EdgeCollapser.cpp
new file mode 100644
index 00000000000..4168a2ae371
--- /dev/null
+++ b/intern/decimation/intern/LOD_EdgeCollapser.cpp
@@ -0,0 +1,408 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_EdgeCollapser.h"
+
+#include "LOD_ManMesh2.h"
+#include "CTR_TaggedSetOps.h"
+#include <algorithm>
+#include <functional>
+
+
+using namespace std;
+
+
+ LOD_EdgeCollapser *
+LOD_EdgeCollapser::
+New(
+){
+ return new LOD_EdgeCollapser();
+}
+
+
+ bool
+LOD_EdgeCollapser::
+TJunctionTest(
+ LOD_ManMesh2 &mesh,
+ vector<LOD_EdgeInd> &e_v0v1,
+ LOD_EdgeInd collapse_edge
+){
+
+ // we need to copy the egdes in e_v0v1 from the mesh
+ // into a new buffer -> we are going to modify them
+
+ int original_size = e_v0v1.size();
+ if (original_size == 0) return true;
+
+ vector<LOD_Edge> &edge_set = mesh.EdgeSet();
+
+ LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0];
+ LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1];
+
+ vector<LOD_Edge> temp_edges;
+ temp_edges.reserve(e_v0v1.size());
+
+ vector<LOD_EdgeInd>::iterator edge_it = e_v0v1.begin();
+ vector<LOD_EdgeInd>::const_iterator edge_end = e_v0v1.end();
+
+ for (;edge_it != edge_end; ++edge_it) {
+ temp_edges.push_back(edge_set[*edge_it]);
+ }
+
+ // in the copied edges replace all instances of c_v0 with c_v1
+
+ vector<LOD_Edge>::iterator e_it = temp_edges.begin();
+ vector<LOD_Edge>::const_iterator e_it_end = temp_edges.end();
+
+ for (; e_it != e_it_end; ++e_it) {
+
+ if (e_it->m_verts[0] == c_v0) {
+ e_it->m_verts[0] = c_v1;
+ }
+ if (e_it->m_verts[1] == c_v0) {
+ e_it->m_verts[1] = c_v1;
+ }
+
+ // normalize the edge
+ if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) {
+ LOD_EdgeInd temp = e_it->m_verts[0];
+ e_it->m_verts[0] = e_it->m_verts[1];
+ e_it->m_verts[1] = temp;
+ }
+ }
+
+ // sort the edges using the edge less functional
+
+ sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less());
+ // count the unique edges.
+
+ e_it = temp_edges.begin();
+ e_it_end = temp_edges.end();
+
+ int coincedent_edges = 0;
+
+ vector<LOD_Edge>::const_iterator last_edge = e_it;
+ ++e_it;
+
+ for (; e_it != e_it_end; ++e_it) {
+
+ if ((e_it->m_verts[0] == last_edge->m_verts[0]) &&
+ (e_it->m_verts[1] == last_edge->m_verts[1])
+ ) {
+ ++coincedent_edges;
+ }
+ last_edge = e_it;
+ }
+
+ // now if the collapse edge is a boundary edges
+ // then we are alloved at most one coincedent edge
+
+ // otherwise at most 2 coincedent edges
+
+ if (edge_set[collapse_edge].BoundaryEdge()) {
+ return (coincedent_edges > 1);
+ } else {
+ return (coincedent_edges > 2);
+ }
+
+
+}
+
+
+
+ bool
+LOD_EdgeCollapser::
+CollapseEdge(
+ LOD_EdgeInd ei,
+ LOD_ManMesh2 &mesh,
+ vector<LOD_EdgeInd> & degenerate_edges,
+ vector<LOD_FaceInd> & degenerate_faces,
+ vector<LOD_VertexInd> & degenerate_vertices,
+ vector<LOD_EdgeInd> & new_edges,
+ vector<LOD_FaceInd> & update_faces,
+ vector<LOD_VertexInd> & update_vertices
+){
+
+ vector<LOD_Vertex> &verts = mesh.VertexSet();
+ vector<LOD_Edge> &edges = mesh.EdgeSet();
+ vector<LOD_TriFace> &faces = mesh.FaceSet();
+
+ // shouldn't do this (use mesh interface instead!)
+ LOD_VertexInd v0_ind = edges[ei].m_verts[0];
+ LOD_VertexInd v1_ind = edges[ei].m_verts[1];
+#if 0
+ LOD_Vertex &v0 = verts[v0_ind];
+ LOD_Vertex &v1 = verts[v1_ind];
+#endif
+ vector<vector<LOD_EdgeInd> > e_v01(2);
+ e_v01[0].reserve(32);
+ e_v01[1].reserve(32);
+
+ mesh.VertexEdges(v0_ind,e_v01[0]);
+ mesh.VertexEdges(v1_ind,e_v01[1]);
+
+
+ // compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse
+ // we remove old edges and replace edges inside the collapse zone with new ones
+
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_v01,edges,degenerate_edges);
+
+ vector< vector<LOD_FaceInd> > p_v01(2);
+ p_v01[0].reserve(32);
+ p_v01[1].reserve(32);
+
+ mesh.VertexFaces(v0_ind,p_v01[0]);
+ mesh.VertexFaces(v1_ind,p_v01[1]);
+
+ // compute the union of p_v0 anf p_v1
+ vector<LOD_FaceInd> p_v0v1;
+ p_v0v1.reserve(32);
+
+ CTR_TaggedSetOps<LOD_FaceInd,LOD_TriFace>::Union(p_v01,faces,p_v0v1);
+
+ // compute the union of all the edges in p_v0v1 this is the collapse zone
+
+ vector<vector<LOD_EdgeInd> > e_input_vectors(p_v0v1.size());
+
+ vector<LOD_FaceInd>::iterator p_v0v1_end = p_v0v1.end();
+ vector<LOD_FaceInd>::iterator p_v0v1_start = p_v0v1.begin();
+
+ vector<vector<LOD_FaceInd> >::iterator vector_insert_it = e_input_vectors.begin();
+
+ for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) {
+ mesh.FaceEdges(*p_v0v1_start,*vector_insert_it);
+ }
+
+ vector<LOD_EdgeInd> collapse_zone;
+ collapse_zone.reserve(32);
+
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_input_vectors,edges,collapse_zone);
+
+ // compute the ring edges = collpase_zone - e_v0v1
+
+ vector<LOD_EdgeInd> edge_ring;
+ edge_ring.reserve(32);
+
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Difference(collapse_zone,degenerate_edges,edges,edge_ring);
+
+ // T Junction test
+ //////////////////
+ // At this point we check to see if any of the polygons
+ // in p_v0v1 are coninceddent - this leads
+ // to errors later on if we try and insert a polygon
+ // into the mesh to an edge which already has 2 polygons.
+
+ // not that t junctions occur naturally from edge collapses
+ // and are not just the result of coincedent polygons
+ // for example consider collapsing an edge that forms part
+ // of a triangular bottle neck.
+
+ // Really we need to make sure that we don't create t-junctions.
+
+ // I think that a sufficient test is to check the number of
+ // coincedent edge pairs after a collapse. If it is more than 2
+ // then collapsing the edge may result in an undeleted edge
+ // sharing more than 2 polygons. This test probably is too
+ // restictive though.
+
+ // To perform this test we need to make a copy of the edges
+ // in e_v0v1. We then apply the contraction to these edge
+ // copies. Sort them using a function that places coincedent
+ // edges next to each other. And then count the number
+ // of coincedent pairs.
+
+ // Of course we have to do this test before we change any of the
+ // mesh -> so we can back out safely.
+
+ if (TJunctionTest(mesh,degenerate_edges,ei)) return false;
+
+ // Compute the set of possibly degenerate vertices
+ // this is the union of all the vertices of polygons
+ // of v0 and v1
+
+ vector<LOD_FaceInd>::iterator face_it = p_v0v1.begin();
+ vector<LOD_FaceInd>::const_iterator face_end = p_v0v1.end();
+
+
+ vector<vector<LOD_VertexInd> > p_v0v1_vertices(p_v0v1.size());
+
+ for (int i = 0; face_it != face_end; ++face_it, ++i) {
+ mesh.FaceVertices(*face_it,p_v0v1_vertices[i]);
+ }
+
+ vector<LOD_VertexInd> vertex_ring;
+ vertex_ring.reserve(32);
+
+ CTR_TaggedSetOps<LOD_VertexInd,LOD_Vertex>::Union(p_v0v1_vertices,verts,vertex_ring);
+
+ // remove all the internal edges e_v0v1 from the mesh.
+ // for each edge remove the egde from it's vertices edge lists.
+
+ vector<LOD_EdgeInd>::iterator edge_it = degenerate_edges.begin();
+ vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+
+ LOD_Edge & edge = edges[*edge_it];
+
+ verts[edge.m_verts[0]].RemoveEdge(*edge_it);
+ verts[edge.m_verts[1]].RemoveEdge(*edge_it);
+ }
+
+ // we postpone deletion of the internal edges untill the end
+ // this is because deleting edges invalidates all of the
+ // EdgeInd vectors above.
+
+
+ // now untie all the polygons in p_v0v1 from the edge ring
+
+ // select all polygons in p_v0v1
+
+ face_it = p_v0v1.begin();
+ face_end = p_v0v1.end();
+
+ for (;face_it != face_end; ++face_it) {
+ faces[*face_it].SetSelectTag(true);
+ }
+
+ edge_it = edge_ring.begin();
+ edge_end = edge_ring.end();
+
+ for (;edge_it != edge_end; ++edge_it) {
+ LOD_Edge & edge = edges[*edge_it];
+
+ // presumably all edges in edge_ring point to at least
+ // one polygon from p_v0v1
+
+ if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) {
+ edge.m_faces[0].Invalidate();
+ }
+
+ if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) {
+ edge.m_faces[1].Invalidate();
+ }
+ }
+
+ // deselect the faces
+
+ face_it = p_v0v1.begin();
+ face_end = p_v0v1.end();
+
+ for (;face_it != face_end; ++face_it) {
+ faces[*face_it].SetSelectTag(false);
+ }
+
+ // perform the edge collapse
+ ////////////////////////////
+
+ // iterate through the polygons of p_v0 and replace the vertex
+ // index v0 with v1
+
+ face_it = p_v01[0].begin();
+ face_end = p_v01[0].end();
+
+ for (;face_it != face_end; ++face_it) {
+ faces[*face_it].SwapVertex(v0_ind,v1_ind);
+ }
+
+ face_it = p_v0v1.begin();
+ face_end = p_v0v1.end();
+
+ for (;face_it != face_end; ++face_it) {
+ if (faces[*face_it].Degenerate()) {
+ degenerate_faces.push_back(*face_it);
+ } else {
+ update_faces.push_back(*face_it);
+ }
+ }
+
+ // Add all the non-degenerate faces back into the
+ // mesh. Get a record of the new edges created in
+ // this process.
+
+ face_it = update_faces.begin();
+ face_end = update_faces.end();
+
+ for (;face_it != face_end; ++face_it) {
+ mesh.ConnectTriangle(*face_it,new_edges);
+ }
+
+ // degenerate ring primitives
+ /////////////////////////////
+
+ // we now need to examine each of the edges on the ring
+ // and work out if they are degenerate - if so we attempt
+ // to delete them -> add them to the other edges to delete
+ // in e_v0v1
+
+ edge_it = edge_ring.begin();
+ edge_end = edge_ring.end();
+
+ for (;edge_it != edge_end; ++edge_it) {
+ if (edges[*edge_it].Degenerate()) {
+ degenerate_edges.push_back(*edge_it);
+ }
+ }
+
+ // do the same for the ring vertices.
+
+ vector<LOD_VertexInd>::iterator vertex_it = vertex_ring.begin();
+ vector<LOD_VertexInd>::const_iterator vertex_end = vertex_ring.end();
+
+ for (;vertex_it != vertex_end; ++vertex_it) {
+ if (verts[*vertex_it].Degenerate()) {
+ degenerate_vertices.push_back(*vertex_it);
+ } else {
+ update_vertices.push_back(*vertex_it);
+ }
+ }
+
+ // we now know all the degenerate primitives
+ // and the new primitives we have inserted into the mesh
+
+ // We now delete the mesh primitives, mesh.DeleteXXXXXX() methods
+ // assume that the index vectors are sorted into descending order.
+ // we do that now.
+
+ sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater());
+ sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater());
+ sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater());
+
+
+ return true;
+
+}
+
+LOD_EdgeCollapser::
+LOD_EdgeCollapser(
+){
+ // nothing to do
+}
diff --git a/intern/decimation/intern/LOD_EdgeCollapser.h b/intern/decimation/intern/LOD_EdgeCollapser.h
new file mode 100644
index 00000000000..d500c45e1ba
--- /dev/null
+++ b/intern/decimation/intern/LOD_EdgeCollapser.h
@@ -0,0 +1,118 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLDUED_EgdeCollapser_h
+
+#define NAN_INCLDUED_EgdeCollapser_h
+
+// This is a helper class that collapses edges of a 2 - manifold mesh.
+
+#include "LOD_MeshPrimitives.h"
+#include "MEM_NonCopyable.h"
+#include <vector>
+#include <functional>
+
+class LOD_ManMesh2;
+
+class LOD_EdgeCollapser
+: public MEM_NonCopyable
+{
+
+public :
+
+ static
+ LOD_EdgeCollapser *
+ New(
+ );
+
+ // returns via arguments the set of modified
+ // verts,edges and faces.
+
+ bool
+ CollapseEdge(
+ LOD_EdgeInd ei,
+ LOD_ManMesh2 &mesh,
+ std::vector<LOD_EdgeInd> & degenerate_edges,
+ std::vector<LOD_FaceInd> & degenerate_faces,
+ std::vector<LOD_VertexInd> & degenerate_vertices,
+ std::vector<LOD_EdgeInd> & new_edges,
+ std::vector<LOD_FaceInd> & update_faces,
+ std::vector<LOD_VertexInd> & update_vertices
+ );
+
+private :
+
+ LOD_EdgeCollapser(
+ );
+
+ // Test to see if the result of collapsing the
+ // edge produces 2 junctions in the mesh i.e. where
+ // an edge is shared by more than 2 polygons
+
+ // We count the number of coincedent edge pairs that
+ // result from the collapse of collapse_edge.
+
+ // If collapse edge is a boundary edge then the number of
+ // coincedent pairs should be 1
+ // else it should be 2.
+
+ bool
+ TJunctionTest(
+ LOD_ManMesh2 &mesh,
+ std::vector<LOD_EdgeInd> &e_v0v1,
+ LOD_EdgeInd collapse_edge
+ );
+
+ // here's the definition of the sort function
+ // we use to determine coincedent edges
+
+ // assumes the edges are normalized i.e. m_verts[0] <= m_verts[1]
+
+ struct less : std::binary_function<LOD_Edge, LOD_Edge, bool> {
+ bool
+ operator()(
+ const LOD_Edge& a,
+ const LOD_Edge& b
+ ) const {
+
+ if (int(a.m_verts[0]) == int(b.m_verts[0])) {
+ return (int(a.m_verts[1]) < int(b.m_verts[1]));
+ } else {
+ return (int(a.m_verts[0]) < int(b.m_verts[0]));
+ }
+ }
+ };
+
+};
+
+
+#endif
+
diff --git a/intern/decimation/intern/LOD_ExternBufferEditor.h b/intern/decimation/intern/LOD_ExternBufferEditor.h
new file mode 100644
index 00000000000..9f628c4455b
--- /dev/null
+++ b/intern/decimation/intern/LOD_ExternBufferEditor.h
@@ -0,0 +1,164 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ */
+
+#ifndef NAN_INCLUDED_LOD_ExternBufferEditor_h
+#define NAN_INCLUDED_LOD_ExternBufferEditor_h
+
+#include "LOD_MeshPrimitives.h"
+#include <vector>
+#include "LOD_ManMesh2.h"
+#include "../extern/LOD_decimation.h"
+
+
+// This class syncs external vertex/face buffers
+// with the internal mesh representation during
+// decimation.
+
+class LOD_ExternBufferEditor
+{
+
+public :
+
+ static
+ LOD_ExternBufferEditor *
+ New(
+ LOD_Decimation_InfoPtr extern_info
+ ){
+ if (extern_info == NULL) return NULL;
+ return new LOD_ExternBufferEditor(extern_info);
+ }
+
+ // update the external vertex buffer with vertices
+ // from the mesh
+
+ void
+ CopyModifiedVerts(
+ LOD_ManMesh2 & mesh,
+ const std::vector<LOD_VertexInd> & mod_vertices
+ ){
+
+ std::vector<LOD_VertexInd>::const_iterator v_start = mod_vertices.begin();
+ std::vector<LOD_VertexInd>::const_iterator v_end = mod_vertices.end();
+
+ std::vector<LOD_Vertex> & mesh_verts = mesh.VertexSet();
+
+ float * const extern_vertex_ptr = m_extern_info->vertex_buffer;
+
+ for (; v_start != v_end; ++v_start) {
+ float * mod_vert = extern_vertex_ptr + int(*v_start)*3;
+ mesh_verts[*v_start].CopyPosition(mod_vert);
+ }
+ }
+
+ // update the external face buffer with faces from the mesh
+
+ void
+ CopyModifiedFaces(
+ LOD_ManMesh2 & mesh,
+ const std::vector<LOD_FaceInd> & mod_faces
+ ){
+
+ std::vector<LOD_FaceInd>::const_iterator f_start = mod_faces.begin();
+ std::vector<LOD_FaceInd>::const_iterator f_end = mod_faces.end();
+
+ std::vector<LOD_TriFace> &mesh_faces = mesh.FaceSet();
+
+ int * const extern_face_ptr = m_extern_info->triangle_index_buffer;
+
+ for (; f_start != f_end; ++f_start) {
+ int *mod_face = extern_face_ptr + 3*int(*f_start);
+ mesh_faces[*f_start].CopyVerts(mod_face);
+ }
+ }
+
+
+ // Copy the last vertex over the vertex specified by
+ // vi. Decrement the size of the vertex array
+
+ void
+ CopyBackVertex(
+ LOD_VertexInd vi
+ ){
+
+ float * const extern_vertex_ptr = m_extern_info->vertex_buffer;
+ int * extern_vertex_num = &(m_extern_info->vertex_num);
+
+ float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1);
+ float * external_vert = extern_vertex_ptr + 3*int(vi);
+
+ external_vert[0] = last_external_vert[0];
+ external_vert[1] = last_external_vert[1];
+ external_vert[2] = last_external_vert[2];
+
+ *extern_vertex_num -=1;
+ }
+
+ // Copy the last face over the face specified by fi
+ // Decrement the size of the face array
+
+ void
+ CopyBackFace(
+ LOD_FaceInd fi
+ ) {
+ int * const extern_face_ptr = m_extern_info->triangle_index_buffer;
+ int * extern_face_num = &(m_extern_info->face_num);
+
+ int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1);
+ int * external_face = extern_face_ptr + 3*int(fi);
+ external_face[0] = last_external_face[0];
+ external_face[1] = last_external_face[1];
+ external_face[2] = last_external_face[2];
+
+ *extern_face_num -=1;
+ }
+
+
+private :
+
+ LOD_ExternBufferEditor(
+ LOD_Decimation_InfoPtr extern_info
+ ) :
+ m_extern_info (extern_info)
+ {
+ }
+
+ LOD_Decimation_InfoPtr const m_extern_info;
+
+};
+
+#endif
+
diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.cpp b/intern/decimation/intern/LOD_ExternNormalEditor.cpp
new file mode 100644
index 00000000000..357aaf56006
--- /dev/null
+++ b/intern/decimation/intern/LOD_ExternNormalEditor.cpp
@@ -0,0 +1,264 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_ExternNormalEditor.h"
+
+#include <vector>
+
+using namespace std;
+
+
+LOD_ExternNormalEditor::
+LOD_ExternNormalEditor(
+ LOD_Decimation_InfoPtr extern_info,
+ LOD_ManMesh2 &mesh
+) :
+ m_extern_info (extern_info),
+ m_mesh(mesh)
+{
+}
+
+ LOD_ExternNormalEditor *
+LOD_ExternNormalEditor::
+New(
+ LOD_Decimation_InfoPtr extern_info,
+ LOD_ManMesh2 &mesh
+){
+ if (extern_info == NULL) return NULL;
+
+ MEM_SmartPtr<LOD_ExternNormalEditor> output(new LOD_ExternNormalEditor(extern_info,mesh));
+
+ int face_num = mesh.FaceSet().size();
+
+ MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>);
+
+ if (output == NULL ||
+ normals == NULL
+ ) {
+ return NULL;
+ }
+
+ normals->reserve(face_num);
+ output->m_normals = normals.Release();
+
+ return output.Release();
+};
+
+
+ void
+LOD_ExternNormalEditor::
+Remove(
+ std::vector<LOD_FaceInd> &sorted_faces
+){
+ // assumes a collection of faces sorted in descending order .
+
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
+ vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
+
+ for (; it_start != it_end; ++it_start) {
+
+ if (normals.size() > 0) {
+ MT_Vector3 temp = normals[*it_start];
+
+ normals[*it_start] = normals.back();
+ normals.back() = temp;
+
+ normals.pop_back();
+ }
+
+ // FIXME - throw exception
+ }
+}
+
+
+ void
+LOD_ExternNormalEditor::
+Add(
+){
+ MT_Vector3 zero(0.0f,0.0f,0.0f);
+ m_normals->push_back(zero);
+};
+
+ void
+LOD_ExternNormalEditor::
+Update(
+ std::vector<LOD_FaceInd> &sorted_faces
+){
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
+ vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
+
+ const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
+
+ for (; it_start != it_end; ++it_start) {
+ normals[*it_start] = ComputeNormal(faces[*it_start]);
+ }
+};
+
+
+
+
+// vertex normals
+/////////////////
+
+ void
+LOD_ExternNormalEditor::
+RemoveVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+){
+
+ float * vertex_normals = m_extern_info->vertex_normal_buffer;
+
+ // assumption here that the vertexs normal number corresponds with
+ // the number of vertices !
+
+ int vertex_normal_num = m_extern_info->vertex_num;
+
+ vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
+ vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
+
+ for (; it_start != it_end; ++it_start) {
+
+ if (vertex_normal_num > 0) {
+ float * vertex_normal = vertex_normals + int(*it_start)*3;
+ float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3);
+
+ MT_Vector3 last_v(last_vertex);
+ last_v.getValue(vertex_normal);
+ vertex_normal_num--;
+ }
+
+ // FIXME - through exception
+ }
+};
+
+
+
+ void
+LOD_ExternNormalEditor::
+UpdateVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+){
+ float * vertex_normals = m_extern_info->vertex_normal_buffer;
+
+ vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
+ vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
+
+ for (; it_start != it_end; ++it_start) {
+ MT_Vector3 temp = ComputeVertexNormal(*it_start);
+ float * vertex_normal = vertex_normals + int(*it_start)*3;
+ temp.getValue(vertex_normal);
+ }
+}
+
+// Editor specific methods
+//////////////////////////
+
+ void
+LOD_ExternNormalEditor::
+BuildNormals(
+) {
+ const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ int face_num = faces.size();
+ int cur_face = 0;
+
+ for (; cur_face < face_num; ++cur_face) {
+
+ MT_Vector3 new_normal = ComputeNormal(faces[cur_face]);
+ normals.push_back(new_normal);
+ }
+}
+
+const
+ MT_Vector3
+LOD_ExternNormalEditor::
+ComputeNormal(
+ const LOD_TriFace &face
+) const {
+
+ const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+
+ MT_Vector3 vec1 =
+ verts[face.m_verts[1]].pos -
+ verts[face.m_verts[0]].pos;
+
+ MT_Vector3 vec2 =
+ verts[face.m_verts[2]].pos -
+ verts[face.m_verts[1]].pos;
+
+ vec1 = vec1.cross(vec2);
+
+ if (!vec1.fuzzyZero()) {
+ vec1.normalize();
+ return (vec1);
+ } else {
+ return (MT_Vector3(1.0,0,0));
+ }
+}
+
+const
+ MT_Vector3
+LOD_ExternNormalEditor::
+ComputeVertexNormal(
+ const LOD_VertexInd v
+) const {
+
+ // average the face normals surrounding this
+ // vertex and normalize
+ vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+ const vector<MT_Vector3> & face_normals = m_normals.Ref();
+
+ vector<LOD_FaceInd> vertex_faces;
+ vertex_faces.reserve(32);
+
+ m_mesh.VertexFaces(v,vertex_faces);
+
+ MT_Vector3 normal(0,0,0);
+
+ vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin();
+ vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end();
+
+ for (; face_it != face_end; ++face_it) {
+ normal += face_normals[*face_it];
+ }
+
+ if (!normal.fuzzyZero()) {
+ normal.normalize();
+ return (normal);
+ } else {
+ return (MT_Vector3(1.0,0,0));
+ }
+}
diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.h b/intern/decimation/intern/LOD_ExternNormalEditor.h
new file mode 100644
index 00000000000..c32b3d5a0b3
--- /dev/null
+++ b/intern/decimation/intern/LOD_ExternNormalEditor.h
@@ -0,0 +1,134 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_ExternNormalEditor_h
+
+#define NAN_INCLUDED_ExternNormalEditor_h
+
+#include "MEM_NonCopyable.h"
+#include "LOD_ManMesh2.h"
+#include "MT_Vector3.h"
+#include "../extern/LOD_decimation.h"
+
+class LOD_ExternNormalEditor : public MEM_NonCopyable
+{
+
+public :
+
+ // Creation
+ ///////////
+
+ static
+ LOD_ExternNormalEditor *
+ New(
+ LOD_Decimation_InfoPtr,
+ LOD_ManMesh2 &mesh
+ );
+
+ // Property editor interface
+ ////////////////////////////
+
+
+ // Faces
+ ////////
+ void
+ Remove(
+ std::vector<LOD_FaceInd> &sorted_faces
+ );
+
+ void
+ Add(
+ );
+
+ void
+ Update(
+ std::vector<LOD_FaceInd> &sorted_faces
+ );
+
+ const
+ std::vector<MT_Vector3> &
+ Normals(
+ ) const {
+ return m_normals.Ref();
+ };
+
+
+ // vertex normals
+ /////////////////
+
+ void
+ RemoveVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+ );
+
+
+ void
+ UpdateVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+ );
+
+ // Editor specific methods
+ //////////////////////////
+
+ void
+ BuildNormals(
+ );
+
+
+private :
+
+ MEM_SmartPtr<std::vector<MT_Vector3> > m_normals;
+
+ LOD_ManMesh2 &m_mesh;
+ LOD_Decimation_InfoPtr m_extern_info;
+
+private :
+
+
+ LOD_ExternNormalEditor(
+ LOD_Decimation_InfoPtr extern_info,
+ LOD_ManMesh2 &mesh
+ );
+
+ const
+ MT_Vector3
+ ComputeNormal(
+ const LOD_TriFace &face
+ ) const ;
+
+ const
+ MT_Vector3
+ ComputeVertexNormal (
+ const LOD_VertexInd vi
+ ) const;
+};
+
+#endif
diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.cpp b/intern/decimation/intern/LOD_FaceNormalEditor.cpp
new file mode 100644
index 00000000000..ef6bc0d252e
--- /dev/null
+++ b/intern/decimation/intern/LOD_FaceNormalEditor.cpp
@@ -0,0 +1,291 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+// implementation of LOD_FaceNormalEditor.h
+
+///////////////////////////////////////
+
+#include "LOD_FaceNormalEditor.h"
+
+using namespace std;
+
+LOD_FaceNormalEditor::
+LOD_FaceNormalEditor(
+ LOD_ManMesh2 & mesh
+) : m_mesh(mesh) {
+};
+
+ LOD_FaceNormalEditor *
+LOD_FaceNormalEditor::
+New(
+ LOD_ManMesh2 &mesh
+){
+ // build a set of normals of the same size
+ // as the number of polys in the mesh
+
+ MEM_SmartPtr<LOD_FaceNormalEditor> output(new LOD_FaceNormalEditor(mesh));
+
+ int face_num = mesh.FaceSet().size();
+
+ MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>);
+ MEM_SmartPtr<vector<MT_Vector3> > vertex_normals(new vector<MT_Vector3>);
+
+ if (output == NULL ||
+ normals == NULL
+ ) {
+ return NULL;
+ }
+
+ normals->reserve(face_num);
+ vertex_normals->reserve(mesh.VertexSet().size());
+ output->m_normals = normals.Release();
+ output->m_vertex_normals = vertex_normals.Release();
+
+ return output.Release();
+};
+
+
+// Property editor interface
+////////////////////////////
+
+ void
+LOD_FaceNormalEditor::
+Remove(
+ std::vector<LOD_FaceInd> &sorted_faces
+){
+
+ // assumes a collection of faces sorted in descending order .
+
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
+ vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
+
+ for (; it_start != it_end; ++it_start) {
+
+ if (normals.size() > 0) {
+ MT_Vector3 temp = normals[*it_start];
+
+ normals[*it_start] = normals.back();
+ normals.back() = temp;
+
+ normals.pop_back();
+ }
+
+ // FIXME - through exception
+ }
+}
+
+
+ void
+LOD_FaceNormalEditor::
+Add(
+){
+ MT_Vector3 zero(0.0f,0.0f,0.0f);
+ m_normals->push_back(zero);
+}
+
+ void
+LOD_FaceNormalEditor::
+Update(
+ std::vector<LOD_FaceInd> &sorted_faces
+){
+
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
+ vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
+
+ const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
+
+ for (; it_start != it_end; ++it_start) {
+ normals[*it_start] = ComputeNormal(faces[*it_start]);
+ }
+};
+
+// vertex normals
+/////////////////
+
+
+ void
+LOD_FaceNormalEditor::
+RemoveVertexNormals(
+ vector<LOD_VertexInd> &sorted_verts
+){
+ vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
+
+ vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
+ vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
+
+ for (; it_start != it_end; ++it_start) {
+
+ if (vertex_normals.size() > 0) {
+ MT_Vector3 temp = vertex_normals[*it_start];
+
+ vertex_normals[*it_start] = vertex_normals.back();
+ vertex_normals.back() = temp;
+
+ vertex_normals.pop_back();
+ }
+
+ // FIXME - through exception
+ }
+};
+
+ void
+LOD_FaceNormalEditor::
+UpdateVertexNormals(
+ vector<LOD_VertexInd> &sorted_verts
+){
+ vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
+
+ vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
+ vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
+
+ for (; it_start != it_end; ++it_start) {
+ vertex_normals[*it_start] = ComputeVertexNormal(*it_start);
+ }
+}
+
+
+
+// Editor specific methods
+//////////////////////////
+
+ void
+LOD_FaceNormalEditor::
+BuildNormals(
+){
+
+ const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
+ vector<MT_Vector3> & normals = m_normals.Ref();
+
+ int face_num = faces.size();
+ int cur_face = 0;
+
+ for (; cur_face < face_num; ++cur_face) {
+
+ MT_Vector3 new_normal = ComputeNormal(faces[cur_face]);
+ normals.push_back(new_normal);
+ }
+ // now build the vertex normals
+
+ vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
+ const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+
+ int vertex_num = verts.size();
+ int cur_vertex = 0;
+
+ for (; cur_vertex < vertex_num; ++cur_vertex) {
+ MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex);
+ vertex_normals.push_back(new_normal);
+ }
+}
+
+const
+ MT_Vector3
+LOD_FaceNormalEditor::
+ComputeNormal(
+ const LOD_TriFace &face
+) const {
+
+ const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+
+ MT_Vector3 vec1 =
+ verts[face.m_verts[1]].pos -
+ verts[face.m_verts[0]].pos;
+
+ MT_Vector3 vec2 =
+ verts[face.m_verts[2]].pos -
+ verts[face.m_verts[1]].pos;
+
+ vec1 = vec1.cross(vec2);
+
+ if (!vec1.fuzzyZero()) {
+ vec1.normalize();
+ return (vec1);
+ } else {
+ return (MT_Vector3(1.0,0,0));
+ }
+}
+
+const
+ MT_Vector3
+LOD_FaceNormalEditor::
+ComputeVertexNormal(
+ const LOD_VertexInd v
+) const {
+
+ // average the face normals surrounding this
+ // vertex and normalize
+ const vector<MT_Vector3> & face_normals = m_normals.Ref();
+
+ vector<LOD_FaceInd> vertex_faces;
+ vertex_faces.reserve(32);
+
+ m_mesh.VertexFaces(v,vertex_faces);
+
+ MT_Vector3 normal(0,0,0);
+
+ vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin();
+ vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end();
+
+ for (; face_it != face_end; ++face_it) {
+ normal += face_normals[*face_it];
+ }
+
+ if (!normal.fuzzyZero()) {
+ normal.normalize();
+ return (normal);
+ } else {
+ return (MT_Vector3(1.0,0,0));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.h b/intern/decimation/intern/LOD_FaceNormalEditor.h
new file mode 100644
index 00000000000..345dc4f8246
--- /dev/null
+++ b/intern/decimation/intern/LOD_FaceNormalEditor.h
@@ -0,0 +1,143 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_FaceNormalEditor_h
+
+#define NAN_INCLUDED_FaceNormalEditor_h
+
+#include "MEM_NonCopyable.h"
+#include "LOD_ManMesh2.h"
+#include "MT_Vector3.h"
+
+
+class LOD_FaceNormalEditor : public MEM_NonCopyable
+{
+
+public :
+
+ // Creation
+ ///////////
+
+ static
+ LOD_FaceNormalEditor *
+ New(
+ LOD_ManMesh2 &mesh
+ );
+
+ // Property editor interface
+ ////////////////////////////
+
+
+ // Faces
+ ////////
+ void
+ Remove(
+ std::vector<LOD_FaceInd> &sorted_faces
+ );
+
+ void
+ Add(
+ );
+
+ void
+ Update(
+ std::vector<LOD_FaceInd> &sorted_faces
+ );
+
+
+ // vertex normals
+ /////////////////
+
+ void
+ RemoveVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+ );
+
+
+ void
+ UpdateVertexNormals(
+ std::vector<LOD_VertexInd> &sorted_verts
+ );
+
+
+
+ const
+ std::vector<MT_Vector3> &
+ Normals(
+ ) const {
+ return m_normals.Ref();
+ };
+
+
+ const
+ std::vector<MT_Vector3> &
+ VertexNormals(
+ ) const {
+ return m_vertex_normals.Ref();
+ };
+
+ // Editor specific methods
+ //////////////////////////
+
+ void
+ BuildNormals(
+ );
+
+
+private :
+
+ MEM_SmartPtr<std::vector<MT_Vector3> > m_normals;
+ MEM_SmartPtr<std::vector<MT_Vector3> > m_vertex_normals;
+
+ LOD_ManMesh2 &m_mesh;
+
+private :
+
+
+ LOD_FaceNormalEditor(LOD_ManMesh2 &mesh);
+
+ const
+ MT_Vector3
+ ComputeNormal(
+ const LOD_TriFace &face
+ ) const ;
+
+ const
+ MT_Vector3
+ ComputeVertexNormal (
+ const LOD_VertexInd vi
+ ) const;
+
+
+
+};
+
+#endif
diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp
new file mode 100644
index 00000000000..f0bf40f577c
--- /dev/null
+++ b/intern/decimation/intern/LOD_ManMesh2.cpp
@@ -0,0 +1,617 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_ManMesh2.h"
+
+#include "MT_assert.h"
+#include <algorithm>
+#include "LOD_MeshException.h"
+#include "CTR_TaggedSetOps.h"
+#include "CTR_UHeap.h"
+#include "LOD_ExternBufferEditor.h"
+
+
+using namespace std;
+
+LOD_ManMesh2::
+LOD_ManMesh2(
+) :
+ m_bbox_min(0,0,0),
+ m_bbox_max(0,0,0)
+{
+}
+
+
+ LOD_ManMesh2 *
+LOD_ManMesh2::
+New(
+){
+ MEM_SmartPtr<LOD_ManMesh2> output(new LOD_ManMesh2());
+ if (output == NULL) return NULL;
+
+ // build the vertex, edge and face sets.
+
+ MEM_SmartPtr<vector<LOD_Vertex> > verts(new vector<LOD_Vertex>);
+ MEM_SmartPtr<vector<LOD_TriFace> > faces(new vector<LOD_TriFace>);
+ MEM_SmartPtr<vector<LOD_Edge> > edges(new vector<LOD_Edge>);
+
+ if ((faces == NULL) || (edges == NULL) || (verts == NULL)) {
+ return NULL;
+ }
+
+ output->m_verts = verts.Release();
+ output->m_faces = faces.Release();
+ output->m_edges = edges.Release();
+
+ return output.Release();
+}
+
+// take ownership of the vertices.
+
+ bool
+LOD_ManMesh2::
+SetVertices(
+ MEM_SmartPtr<vector<LOD_Vertex> > verts
+){
+
+
+ // take ownership of vertices
+ m_verts = verts;
+
+ // create a polygon and edge buffer of half the size
+ // and just use the automatic resizing feature of vector<>
+ // to worry about the dynamic array resizing
+
+ m_faces->clear();
+ m_edges->clear();
+
+ m_faces->reserve(m_verts->size()/2);
+ m_edges->reserve(m_verts->size()/2);
+
+ return true;
+
+}
+
+
+// add a triangle to the mesh
+
+ void
+LOD_ManMesh2::
+AddTriangle(
+ int verts[3]
+) {
+
+ MT_assert(verts[0] < int(m_verts->size()));
+ MT_assert(verts[1] < int(m_verts->size()));
+ MT_assert(verts[2] < int(m_verts->size()));
+
+ LOD_TriFace face;
+ face.m_verts[0] = verts[0];
+ face.m_verts[1] = verts[1];
+ face.m_verts[2] = verts[2];
+
+ LOD_FaceInd face_index = m_faces->size();
+
+ m_faces->push_back(face);
+
+ // now work out if any of the directed edges or their
+ // companion edges exist already.
+ // We go through the edges associated with each of the given vertices
+
+ // the safest thing to do is iterate through each of the edge sets
+ // check against each of the 2 other triangle edges to see if they are there
+
+ vector<LOD_EdgeInd> new_edges;
+ new_edges.reserve(3);
+
+ InsertEdge(verts[0],verts[1],face_index,new_edges);
+ InsertEdge(verts[1],verts[2],face_index,new_edges);
+ InsertEdge(verts[2],verts[0],face_index,new_edges);
+
+}
+
+// Adds the index of any created edges to new_edges
+
+ bool
+LOD_ManMesh2::
+InsertEdge(
+ const LOD_VertexInd v1,
+ const LOD_VertexInd v2,
+ const LOD_FaceInd f,
+ vector<LOD_EdgeInd> &new_edges
+){
+
+ MT_assert(!v1.IsEmpty());
+ MT_assert(!v2.IsEmpty());
+ MT_assert(!f.IsEmpty());
+
+ vector<LOD_Vertex> &verts = VertexSet();
+ vector<LOD_Edge> &edges = EdgeSet();
+
+ LOD_EdgeInd e;
+
+ e = FindEdge(v1,v2);
+
+ if (e.IsEmpty()) {
+ // This edge does not exist -- make a new one
+
+ LOD_Edge temp_e;
+ temp_e.m_verts[0] = v1;
+ temp_e.m_verts[1] = v2;
+
+ e = m_edges->size();
+
+ // set the face ptr for this half-edge
+ temp_e.m_faces[0] = f;
+
+ m_edges->push_back(temp_e);
+
+ // add the edge index to it's vertices
+
+ verts[v1].AddEdge(e);
+ verts[v2].AddEdge(e);
+
+ new_edges.push_back(e);
+
+ } else {
+
+ // edge already exists
+ // insure that there is no polygon already
+ // attached to the other side of this edge
+
+ // swap the empty face pointer in edge with f
+
+ LOD_Edge &edge = edges[e];
+
+ edge.SwapFace(LOD_FaceInd::Empty(),f);
+ }
+
+
+ return true;
+
+}
+
+ void
+LOD_ManMesh2::
+ConnectTriangle(
+ LOD_FaceInd fi,
+ std::vector<LOD_EdgeInd> & new_edges
+){
+
+ vector<LOD_TriFace> &faces = FaceSet();
+
+ MT_assert(!faces[fi].Degenerate());
+
+ LOD_TriFace & face = faces[fi];
+
+ InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges);
+ InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges);
+ InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges);
+};
+
+
+
+
+// geometry access
+//////////////////
+
+ vector<LOD_Vertex> &
+LOD_ManMesh2::
+VertexSet(
+) const {
+ return m_verts.Ref();
+}
+
+ vector<LOD_TriFace> &
+LOD_ManMesh2::
+FaceSet(
+) const {
+ return m_faces.Ref();
+}
+
+ vector<LOD_Edge> &
+LOD_ManMesh2::
+EdgeSet(
+) const {
+ return m_edges.Ref();
+};
+
+LOD_ManMesh2::
+~LOD_ManMesh2(
+){
+ //auto ptr takes care of vertex arrays etc.
+}
+
+ LOD_EdgeInd
+LOD_ManMesh2::
+FindEdge(
+ const LOD_VertexInd v1,
+ const LOD_VertexInd v2
+) {
+
+ vector<LOD_Vertex> &verts = VertexSet();
+ vector<LOD_Edge> &edges = EdgeSet();
+
+ LOD_Edge e;
+ e.m_verts[0] = v1;
+ e.m_verts[1] = v2;
+
+ vector<LOD_EdgeInd> &v1_edges = verts[v1].m_edges;
+ vector<LOD_EdgeInd>::const_iterator v1_end = v1_edges.end();
+ vector<LOD_EdgeInd>::iterator v1_begin = v1_edges.begin();
+
+ for (; v1_begin != v1_end; ++v1_begin) {
+ if (edges[*v1_begin] == e) return *v1_begin;
+ }
+
+ return LOD_EdgeInd::Empty();
+}
+
+// face queries
+///////////////
+
+ void
+LOD_ManMesh2::
+FaceVertices(
+ LOD_FaceInd fi,
+ vector<LOD_VertexInd> &output
+){
+ const vector<LOD_TriFace> &faces = FaceSet();
+ const LOD_TriFace & f = faces[fi];
+
+ output.push_back(f.m_verts[0]);
+ output.push_back(f.m_verts[1]);
+ output.push_back(f.m_verts[2]);
+}
+
+ void
+LOD_ManMesh2::
+FaceEdges(
+ LOD_FaceInd fi,
+ vector<LOD_EdgeInd> &output
+){
+ const vector<LOD_TriFace> &faces = FaceSet();
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_Vertex> &verts = VertexSet();
+
+ const LOD_TriFace & f = faces[fi];
+ // intersect vertex edges
+
+ vector<LOD_EdgeInd> & v0_edges = verts[f.m_verts[0]].m_edges;
+ vector<LOD_EdgeInd> & v1_edges = verts[f.m_verts[1]].m_edges;
+ vector<LOD_EdgeInd> & v2_edges = verts[f.m_verts[2]].m_edges;
+
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v0_edges,v1_edges,edges,output);
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v1_edges,v2_edges,edges,output);
+ CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v2_edges,v0_edges,edges,output);
+
+ MT_assert(output.size() == 3);
+ if (output.size() != 3) {
+ LOD_MeshException e(LOD_MeshException::e_non_manifold);
+ throw(e);
+ }
+}
+
+
+// edge queries
+///////////////
+
+ void
+LOD_ManMesh2::
+EdgeVertices(
+ LOD_EdgeInd ei,
+ vector<LOD_VertexInd> &output
+){
+ const vector<LOD_Edge> &edges = EdgeSet();
+ const LOD_Edge & e = edges[ei];
+
+ output.push_back(e.m_verts[0]);
+ output.push_back(e.m_verts[1]);
+}
+
+ void
+LOD_ManMesh2::
+EdgeFaces(
+ LOD_EdgeInd ei,
+ vector<LOD_FaceInd> &output
+){
+ const vector<LOD_Edge> &edges = EdgeSet();
+ const LOD_Edge & e = edges[ei];
+
+ if (!e.m_faces[0].IsEmpty()) {
+ output.push_back(e.m_faces[0]);
+ }
+ if (!e.m_faces[1].IsEmpty()) {
+ output.push_back(e.m_faces[1]);
+ }
+}
+
+// vertex queries
+/////////////////
+
+ void
+LOD_ManMesh2::
+VertexEdges(
+ LOD_VertexInd vi,
+ vector<LOD_EdgeInd> &output
+){
+ // iterate through the edges of v and push them onto the
+ // output
+
+ vector<LOD_Vertex> &verts = VertexSet();
+
+ vector<LOD_EdgeInd> & v_edges = verts[vi].m_edges;
+ vector<LOD_EdgeInd>::iterator v_it = v_edges.begin();
+
+ for (; v_it != v_edges.end(); ++v_it) {
+ output.push_back(*v_it);
+ }
+}
+
+ void
+LOD_ManMesh2::
+VertexFaces(
+ LOD_VertexInd vi,
+ vector<LOD_FaceInd> &output
+){
+ const vector<LOD_Vertex> &verts = VertexSet();
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_TriFace> &faces = FaceSet();
+
+ const vector<LOD_EdgeInd> &v_edges = verts[vi].m_edges;
+ vector<LOD_EdgeInd>::const_iterator e_it = v_edges.begin();
+
+ for (; e_it != v_edges.end(); ++e_it) {
+
+ LOD_Edge &e = edges[*e_it];
+
+ if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) {
+ output.push_back(e.m_faces[0]);
+ faces[e.m_faces[0]].SetSelectTag(true);
+ }
+
+ if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) {
+ output.push_back(e.m_faces[1]);
+ faces[e.m_faces[1]].SetSelectTag(true);
+ }
+ }
+
+ vector<LOD_FaceInd>::iterator f_it = output.begin();
+
+ for (; f_it != output.end(); ++f_it) {
+ faces[*f_it].SetSelectTag(false);
+ }
+};
+
+ void
+LOD_ManMesh2::
+SetBBox(
+ MT_Vector3 bbox_min,
+ MT_Vector3 bbox_max
+){
+ m_bbox_min = bbox_min;
+ m_bbox_max = bbox_max;
+};
+
+ void
+LOD_ManMesh2::
+SC_TriFace(
+ LOD_FaceInd f
+){
+ LOD_TriFace face = (*m_faces)[f];
+
+ // check for unique vertices
+
+ if (
+ (face.m_verts[0] == face.m_verts[1]) ||
+ (face.m_verts[1] == face.m_verts[2]) ||
+ (face.m_verts[2] == face.m_verts[0])
+ ) {
+ MT_assert(false);
+ }
+
+}
+
+
+ void
+LOD_ManMesh2::
+SC_EdgeList(
+ LOD_VertexInd v
+){
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_Vertex> &verts = VertexSet();
+
+ vector<LOD_EdgeInd>::iterator e_it = verts[v].m_edges.begin();
+
+ for (;e_it != verts[v].m_edges.end(); ++e_it) {
+ MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v));
+ }
+
+};
+
+ void
+LOD_ManMesh2::
+DeleteVertex(
+ LOD_ExternBufferEditor & extern_editor,
+ LOD_VertexInd v
+){
+
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_Vertex> &verts = VertexSet();
+ vector<LOD_TriFace> &faces = FaceSet();
+
+ // need to update all the edge and polygons pointing to
+ // the last vertex in m_verts
+
+ if (verts.size() == 1) {
+ verts.clear();
+ return;
+ }
+
+ LOD_VertexInd last = LOD_VertexInd(verts.end() - verts.begin() - 1);
+
+ if (!(last == v)) {
+
+ // we asume that v is already disconnected
+
+ vector<LOD_FaceInd> v_faces;
+ vector<LOD_EdgeInd> v_edges;
+
+ v_faces.reserve(64);
+ v_edges.reserve(64);
+
+ VertexFaces(last,v_faces);
+ VertexEdges(last,v_edges);
+
+ // map the faces and edges to look at v
+
+ vector<LOD_FaceInd>::iterator face_it = v_faces.begin();
+
+ for(; face_it != v_faces.end(); ++face_it) {
+ faces[*face_it].SwapVertex(last,v);
+ }
+ vector<LOD_EdgeInd>::iterator edge_it = v_edges.begin();
+
+ for (; edge_it != v_edges.end(); ++edge_it) {
+ edges[*edge_it].SwapVertex(last,v);
+ }
+
+ // copy the last vertex onto v and pop off the back.
+
+ verts[v] = verts[last];
+
+ // tidy external buffer
+ extern_editor.CopyModifiedFaces(*this,v_faces);
+ }
+
+ verts.pop_back();
+ extern_editor.CopyBackVertex(v);
+
+
+};
+
+ void
+LOD_ManMesh2::
+DeleteEdge(
+ LOD_EdgeInd e,
+ CTR_UHeap<LOD_Edge> * heap
+){
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_Vertex> &verts = VertexSet();
+
+ if (edges.size() == 1) {
+ edges.clear();
+ return;
+ }
+
+ LOD_EdgeInd last = LOD_EdgeInd(edges.end() - edges.begin() - 1);
+
+ if (!(last == e)) {
+ vector<LOD_EdgeInd> e_verts;
+ e_verts.reserve(2);
+ EdgeVertices(last,e_verts);
+ // something is wrong if there arent two!
+
+ verts[e_verts[0]].SwapEdge(last,e);
+ verts[e_verts[1]].SwapEdge(last,e);
+
+ // edges[e] should already have been removed from the heap
+
+ MT_assert(edges[e].HeapPos() == 0xffffffff);
+
+ edges[e] = edges[last];
+ // also have to swap there heap positions.!!!!!
+
+ heap->HeapVector()[edges[e].HeapPos()] = e;
+
+
+ }
+ edges.pop_back();
+};
+
+ void
+LOD_ManMesh2::
+DeleteFace(
+ LOD_ExternBufferEditor & extern_editor,
+ LOD_FaceInd f
+){
+
+ vector<LOD_Edge> &edges = EdgeSet();
+ vector<LOD_TriFace> &faces = FaceSet();
+
+ if (faces.size() == 1) {
+ faces.clear();
+ return;
+ }
+
+ LOD_FaceInd last = LOD_FaceInd(faces.end() - faces.begin() - 1);
+
+ if (!(last == f)) {
+
+ // we have to update the edges which point to the last
+ // face
+
+ vector<LOD_EdgeInd> f_edges;
+ f_edges.reserve(3);
+
+ FaceEdges(last,f_edges);
+
+ vector<LOD_EdgeInd>::iterator edge_it = f_edges.begin();
+ vector<LOD_EdgeInd>::const_iterator edge_end = f_edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+ edges[*edge_it].SwapFace(last,f);
+ }
+
+ faces[f] = faces[last];
+
+ }
+ faces.pop_back();
+
+ // tidy external buffers
+ extern_editor.CopyBackFace(f);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/decimation/intern/LOD_ManMesh2.h b/intern/decimation/intern/LOD_ManMesh2.h
new file mode 100644
index 00000000000..e208155c1f0
--- /dev/null
+++ b/intern/decimation/intern/LOD_ManMesh2.h
@@ -0,0 +1,264 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_ManMesh2_h
+
+#define NAN_INCLUDED_ManMesh2_h
+
+#include "LOD_MeshPrimitives.h"
+#include "MEM_SmartPtr.h"
+#include <vector>
+
+template <class HeapType> class CTR_UHeap;
+
+class LOD_ExternBufferEditor;
+
+class LOD_ManMesh2 // Manifold 2 dimensional mesh
+{
+
+public:
+
+ static
+ LOD_ManMesh2 *
+ New(
+ );
+
+ // take ownership of the vertices.
+
+ bool
+ SetVertices(
+ MEM_SmartPtr<std::vector<LOD_Vertex> > verts
+ );
+
+ // Add a triangle to the mesh
+
+ void
+ AddTriangle(
+ int verts[3]
+ );
+
+ void
+ ConnectTriangle(
+ LOD_FaceInd fi,
+ std::vector<LOD_EdgeInd> & new_edges
+ );
+
+ // geometry access
+ //////////////////
+
+ std::vector<LOD_Vertex> &
+ VertexSet(
+ ) const ;
+
+ std::vector<LOD_TriFace> &
+ FaceSet(
+ ) const ;
+
+ std::vector<LOD_Edge> &
+ EdgeSet(
+ ) const;
+
+ ~LOD_ManMesh2(
+ );
+
+ // local geometry queries
+ /////////////////////////
+
+ // face queries
+ ///////////////
+
+ void
+ FaceVertices(
+ LOD_FaceInd f,
+ std::vector<LOD_VertexInd> &output
+ );
+
+ void
+ FaceEdges(
+ LOD_FaceInd f,
+ std::vector<LOD_EdgeInd> &output
+ );
+
+ // edge queries
+ ///////////////
+
+ void
+ EdgeVertices(
+ LOD_EdgeInd e,
+ std::vector<LOD_VertexInd> &output
+ );
+
+ void
+ EdgeFaces(
+ LOD_EdgeInd e,
+ std::vector<LOD_FaceInd> &output
+ );
+
+ // vertex queries
+ /////////////////
+
+ void
+ VertexEdges(
+ LOD_VertexInd v,
+ std::vector<LOD_EdgeInd> &output
+ );
+
+ void
+ VertexFaces(
+ LOD_VertexInd v,
+ std::vector<LOD_FaceInd> &output
+ );
+
+ void
+ SetBBox(
+ MT_Vector3 bbox_min,
+ MT_Vector3 bbox_max
+ );
+
+ MT_Vector3
+ BBoxMin(
+ ) const {
+ return m_bbox_min;
+ };
+
+ MT_Vector3
+ BBoxMax(
+ ) const {
+ return m_bbox_max;
+ };
+
+ // Remove a primitive from the mesh
+ ///////////////////////////////////
+
+ // These methods assume you have correctly
+ // tidied up the index pointers in other primitives,
+ // so that nothing refers to this object any more
+
+ // These methods exchange the primitive with the
+ // last primitive in the vector. It modifies everything
+ // pointing to the last primitive correctly.
+
+ // FIXME refactor extern editor out of primitive deletion
+ // insead return a vector of primitives that need to be
+ // modified and do this externally
+
+ void
+ DeleteVertex(
+ LOD_ExternBufferEditor & extern_editor,
+ LOD_VertexInd v
+ );
+
+ void
+ DeleteEdge(
+ LOD_EdgeInd e,
+ CTR_UHeap<LOD_Edge> *heap
+ );
+
+ void
+ DeleteFace(
+ LOD_ExternBufferEditor & extern_editor,
+ LOD_FaceInd f
+ );
+
+ // Sanity Check routines
+ ////////////////////////
+
+ // Make sure the edge sets and the vertex sets are
+ // consistent
+
+ void
+ SC_TriFace(
+ LOD_FaceInd f
+ );
+
+ // basic sanity checking of an edge list bails out if there are more than 1024
+ // edges
+
+ void
+ SC_EdgeList(
+ LOD_EdgeInd e
+ );
+
+
+ // Check to see that the edges of v1 and v2 are unique.
+
+ bool
+ SC_UniqueEdge(
+ LOD_EdgeInd e
+ );
+
+
+private :
+
+
+ // Returns the edge index of the edge from v1 to v2.
+ // Does this by searching the edge sets of v1 - but not v2.
+ // If you are paranoid you should check both and make sure the
+ // indices are the same. If the edge doe not exist edgeInd is empty.
+
+ LOD_EdgeInd
+ FindEdge(
+ const LOD_VertexInd v1,
+ const LOD_VertexInd v2
+ );
+
+ // Insert an edge into the mesh
+ // Tie up the ptrs and create space for the edge
+ // returns manifold errors - need to sort out memory edges
+
+ bool
+ InsertEdge(
+ const LOD_VertexInd v1,
+ const LOD_VertexInd v2,
+ const LOD_FaceInd f,
+ std::vector<LOD_EdgeInd> &new_edges
+ );
+
+
+private :
+
+ LOD_ManMesh2(
+ );
+
+ MEM_SmartPtr< std::vector<LOD_Vertex> > m_verts;
+ MEM_SmartPtr< std::vector<LOD_TriFace> > m_faces;
+ MEM_SmartPtr< std::vector<LOD_Edge> > m_edges;
+
+ // not sure of these descrtiptions of the mesh should
+ // reside in this class coz may lead to very bloated interface.
+
+ MT_Vector3 m_bbox_min;
+ MT_Vector3 m_bbox_max;
+
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/decimation/intern/LOD_MeshBounds.h b/intern/decimation/intern/LOD_MeshBounds.h
new file mode 100644
index 00000000000..bb74bdb3945
--- /dev/null
+++ b/intern/decimation/intern/LOD_MeshBounds.h
@@ -0,0 +1,134 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MeshBounds_h
+
+#define NAN_INCLUDED_MeshBounds_h
+
+
+#include "MEM_SmartPtr.h"
+#include "LOD_MeshPrimitives.h"
+#include "LOD_ManMesh2.h"
+#include "MT_assert.h"
+
+// simple class to compute the mesh bounds of a manifold mesh,
+
+class LOD_MeshBounds {
+
+public :
+ static
+ LOD_MeshBounds *
+ New(
+ ){
+
+ MEM_SmartPtr<LOD_MeshBounds> output(new LOD_MeshBounds());
+ return output.Release();
+ }
+
+ void
+ ComputeBounds(
+ const LOD_ManMesh2 * mesh
+ ){
+ MT_assert(mesh!=NULL);
+ MT_assert(mesh->VertexSet().size() > 0);
+
+ const std::vector<LOD_Vertex> &verts = mesh->VertexSet();
+
+ m_min = verts[0].pos;
+ m_max = verts[0].pos;
+
+ // iterate through the verts
+
+ int t;
+ const int size = verts.size();
+
+ for (t=1; t< size ; ++t) {
+
+ UpdateBounds(verts[t].pos,m_min,m_max);
+ }
+ }
+
+ MT_Vector3
+ Min(
+ ) const {
+ return m_min;
+ }
+
+ MT_Vector3
+ Max(
+ ) const {
+ return m_max;
+ }
+
+private :
+
+ void
+ UpdateBounds(
+ MT_Vector3 vertex,
+ MT_Vector3& min,
+ MT_Vector3& max
+ ) {
+ if (vertex.x() < min.x()) {
+ min.x() = vertex.x();
+ } else
+ if (vertex.x() > max.x()) {
+ max.x()= vertex.x();
+ }
+
+ if (vertex.y() < min.y()) {
+ min.y() = vertex.y();
+ } else
+ if (vertex.y() > max.y()) {
+ max.y()= vertex.y();
+ }
+
+ if (vertex.z() < min.z()) {
+ min.z() = vertex.z();
+ } else
+ if (vertex.z() > max.z()) {
+ max.z()= vertex.z();
+ }
+ }
+
+ LOD_MeshBounds(
+ ) :
+ m_min(0,0,0),
+ m_max(0,0,0)
+ {
+ };
+
+ MT_Vector3 m_min;
+ MT_Vector3 m_max;
+
+};
+
+
+#endif
diff --git a/intern/decimation/intern/LOD_MeshException.h b/intern/decimation/intern/LOD_MeshException.h
new file mode 100644
index 00000000000..4f0b8f99c38
--- /dev/null
+++ b/intern/decimation/intern/LOD_MeshException.h
@@ -0,0 +1,55 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MeshExceptions_h
+
+#define NAN_INCLUDED_MeshExceptions_h
+
+
+class LOD_MeshException {
+
+public :
+
+ // stick in more error types as you think of them
+
+ enum ExceptionType{
+ e_non_manifold,
+ e_search_error
+ } m_e_type;
+
+ LOD_MeshException (
+ ExceptionType type
+ ) : m_e_type (type)
+ {
+ }
+};
+
+#endif
diff --git a/intern/decimation/intern/LOD_MeshPrimitives.cpp b/intern/decimation/intern/LOD_MeshPrimitives.cpp
new file mode 100644
index 00000000000..147e107cb4b
--- /dev/null
+++ b/intern/decimation/intern/LOD_MeshPrimitives.cpp
@@ -0,0 +1,407 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_MeshPrimitives.h"
+
+#include "MT_assert.h"
+#include "LOD_MeshException.h"
+#include <algorithm>
+
+using namespace std;
+
+// Vertex Methods
+/////////////////
+
+LOD_Vertex::
+LOD_Vertex(
+) :
+ pos (MT_Vector3()),
+ m_select_tag(false)
+{
+};
+
+ bool
+LOD_Vertex::
+RemoveEdge(
+ LOD_EdgeInd e
+){
+
+ vector<LOD_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e);
+ if (result == m_edges.end()) {
+ return false;
+ }
+ LOD_EdgeInd last = m_edges.back();
+ m_edges.pop_back();
+ if (m_edges.empty()) return true;
+
+ *result = last;
+ return true;
+};
+
+ void
+LOD_Vertex::
+AddEdge(
+ LOD_EdgeInd e
+){
+ m_edges.push_back(e);
+};
+
+ void
+LOD_Vertex::
+SwapEdge(
+ LOD_EdgeInd e_old,
+ LOD_EdgeInd e_new
+){
+
+ vector<LOD_EdgeInd>::iterator result =
+ find(m_edges.begin(),m_edges.end(),e_old);
+ if (result == m_edges.end()) {
+ MT_assert(false);
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+ }
+
+ *result = e_new;
+};
+
+ bool
+LOD_Vertex::
+SelectTag(
+) const {
+ return m_select_tag;
+};
+
+ void
+LOD_Vertex::
+SetSelectTag(
+ bool tag
+){
+ m_select_tag = tag;
+};
+
+ bool
+LOD_Vertex::
+Degenerate(
+){
+ return m_edges.empty();
+}
+
+ void
+LOD_Vertex::
+CopyPosition(
+ float *float_ptr
+){
+ pos.getValue(float_ptr);
+}
+
+
+
+// Edge Methods
+///////////////
+
+LOD_Edge::
+LOD_Edge (
+) {
+ m_verts[0] = m_verts[1] = LOD_VertexInd::Empty();
+ m_faces[0] = m_faces[1] = LOD_FaceInd::Empty();
+}
+
+ bool
+LOD_Edge::
+operator == (
+ LOD_Edge & rhs
+) {
+ // edges are the same if their vertex indices are the
+ // same!!! Other properties are not checked
+
+ int matches = 0;
+
+ if (this->m_verts[0] == rhs.m_verts[0]) {
+ ++matches;
+ }
+ if (this->m_verts[1] == rhs.m_verts[0]) {
+ ++matches;
+ }
+ if (this->m_verts[0] == rhs.m_verts[1]) {
+ ++matches;
+ }
+ if (this->m_verts[1] == rhs.m_verts[1]) {
+ ++matches;
+ }
+
+ if (matches >= 2) {
+ return true;
+ }
+ return false;
+}
+
+// Elementary helper methods
+////////////////////////////
+
+ LOD_FaceInd
+LOD_Edge::
+OpFace(
+ LOD_FaceInd f
+) const {
+ if (f == m_faces[0]) {
+ return m_faces[1];
+ } else
+ if (f == m_faces[1]) {
+ return m_faces[0];
+ } else {
+ MT_assert(false);
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+
+ return LOD_FaceInd::Empty();
+ }
+}
+
+ void
+LOD_Edge::
+SwapFace(
+ LOD_FaceInd old_f,
+ LOD_FaceInd new_f
+) {
+ if (old_f == m_faces[0]) {
+ m_faces[0] = new_f;
+ } else
+ if (old_f == m_faces[1]) {
+ m_faces[1] = new_f;
+ } else {
+ MT_assert(false);
+
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+ }
+}
+
+
+// return the half edge face - the half edge is defined
+// by the {vertex,edge} tuple.
+
+ LOD_FaceInd
+LOD_Edge::
+HalfEdgeFace(
+ LOD_VertexInd vi
+){
+ if (vi == m_verts[0]) return m_faces[0];
+ if (vi == m_verts[1]) return m_faces[1];
+ MT_assert(false);
+
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+
+ return LOD_FaceInd::Empty();
+}
+
+
+ LOD_VertexInd
+LOD_Edge::
+OpVertex(
+ LOD_VertexInd vi
+) {
+ if (vi == m_verts[0]) return m_verts[1];
+ if (vi == m_verts[1]) return m_verts[0];
+ MT_assert(false);
+
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+
+ return LOD_VertexInd::Empty();
+}
+
+// replace the vertex v_old with vertex v_new
+// error if v_old is not one of the original vertices
+
+ void
+LOD_Edge::
+SwapVertex(
+ LOD_VertexInd v_old,
+ LOD_VertexInd v_new
+) {
+ if (v_old == m_verts[0]) {
+ m_verts[0] = v_new;
+ } else
+ if (v_old == m_verts[1]) {
+ m_verts[1] = v_new;
+ } else {
+
+ MT_assert(false);
+
+ LOD_MeshException e(LOD_MeshException::e_search_error);
+ throw(e);
+ }
+ if(m_verts[0] == m_verts[1]) {
+ MT_assert(false);
+
+ LOD_MeshException e(LOD_MeshException::e_non_manifold);
+ throw(e);
+ }
+
+}
+
+ bool
+LOD_Edge::
+SelectTag(
+) const {
+ return bool(m_verts[1].Tag() & 0x1);
+};
+
+ void
+LOD_Edge::
+SetSelectTag(
+ bool tag
+) {
+ m_verts[1].SetTag(int(tag));
+};
+
+ int
+LOD_Edge::
+OpenTag(
+) const {
+ return m_faces[0].Tag();
+}
+
+ void
+LOD_Edge::
+SetOpenTag(
+ int tag
+) {
+ m_faces[0].SetTag(tag);
+}
+
+ bool
+LOD_Edge::
+Degenerate(
+) const {
+ return (
+ (m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) ||
+ (m_verts[0] == m_verts[1])
+ );
+};
+
+// TriFace Methods
+//////////////////
+
+LOD_TriFace::
+LOD_TriFace(
+) {
+ m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty();
+}
+
+// Elementary helper methods
+////////////////////////////
+
+ void
+LOD_TriFace::
+SwapVertex(
+ LOD_VertexInd old_v,
+ LOD_VertexInd new_v
+) {
+ // could save branching here...
+
+ if (m_verts[0] == old_v) {
+ m_verts[0] = new_v;
+ } else
+ if (m_verts[1] == old_v) {
+ m_verts[1] = new_v;
+ } else
+ if (m_verts[2] == old_v) {
+ m_verts[2] = new_v;
+ } else {
+ MT_assert(false);
+
+ LOD_MeshException excep(LOD_MeshException::e_search_error);
+ throw(excep);
+ }
+}
+
+ bool
+LOD_TriFace::
+SelectTag(
+) const {
+ return bool(m_verts[1].Tag() & 0x1);
+};
+
+ void
+LOD_TriFace::
+SetSelectTag(
+ bool tag
+) {
+ m_verts[1].SetTag(int(tag));
+};
+
+ int
+LOD_TriFace::
+OpenTag(
+) {
+ return m_verts[2].Tag();
+}
+
+ void
+LOD_TriFace::
+SetOpenTag(
+ int tag
+) {
+ m_verts[2].SetTag(tag);
+}
+
+ bool
+LOD_TriFace::
+Degenerate(
+) {
+
+ return (
+ (m_verts[0] == m_verts[1]) ||
+ (m_verts[1] == m_verts[2]) ||
+ (m_verts[2] == m_verts[0])
+ );
+}
+
+ void
+LOD_TriFace::
+CopyVerts(
+ int * index_ptr
+){
+ index_ptr[0] = m_verts[0];
+ index_ptr[1] = m_verts[1];
+ index_ptr[2] = m_verts[2];
+};
+
+
+
+
+
+
+
+
+
diff --git a/intern/decimation/intern/LOD_MeshPrimitives.h b/intern/decimation/intern/LOD_MeshPrimitives.h
new file mode 100644
index 00000000000..12214c7528d
--- /dev/null
+++ b/intern/decimation/intern/LOD_MeshPrimitives.h
@@ -0,0 +1,221 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MeshPrimitives_h
+
+#define NAN_INCLUDED_MeshPrimitives_h
+
+#include "MT_Vector3.h"
+#include "CTR_TaggedIndex.h"
+#include "CTR_UHeap.h"
+#include <vector>
+
+typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd;
+typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd;
+
+class LOD_Vertex {
+public :
+ MT_Vector3 pos;
+ std::vector<LOD_EdgeInd> m_edges;
+ bool m_select_tag;
+
+ LOD_Vertex(
+ ) ;
+
+ bool
+ RemoveEdge(
+ LOD_EdgeInd e
+ );
+
+ void
+ AddEdge(
+ LOD_EdgeInd e
+ );
+
+ void
+ SwapEdge(
+ LOD_EdgeInd e_old,
+ LOD_EdgeInd e_new
+ );
+
+ bool
+ SelectTag(
+ ) const;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+
+ bool
+ Degenerate(
+ );
+
+ void
+ CopyPosition(
+ float *float_ptr
+ );
+
+private :
+
+
+};
+
+class LOD_Edge : public CTR_UHeapable {
+public :
+ LOD_VertexInd m_verts[2];
+ LOD_FaceInd m_faces[2];
+
+ LOD_Edge (
+ );
+
+ bool operator == (
+ LOD_Edge & rhs
+ );
+
+ // Elementary helper methods
+ ////////////////////////////
+
+ LOD_FaceInd
+ OpFace(
+ LOD_FaceInd f
+ ) const ;
+
+ void
+ SwapFace(
+ LOD_FaceInd old_f,
+ LOD_FaceInd new_f
+ ) ;
+
+
+ // return the half edge face - the half edge is defined
+ // by the {vertex,edge} tuple.
+
+ LOD_FaceInd
+ HalfEdgeFace(
+ LOD_VertexInd vi
+ );
+
+
+ LOD_VertexInd
+ OpVertex(
+ LOD_VertexInd vi
+ );
+
+ // replace the vertex v_old with vertex v_new
+ // error if v_old is not one of the original vertices
+
+ void
+ SwapVertex(
+ LOD_VertexInd v_old,
+ LOD_VertexInd v_new
+ ) ;
+
+ bool
+ SelectTag(
+ ) const ;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+
+ int
+ OpenTag(
+ ) const;
+
+ void
+ SetOpenTag(
+ int tag
+ ) ;
+
+ bool
+ Degenerate(
+ ) const;
+
+ bool
+ BoundaryEdge(
+ ) const {
+ return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty());
+ };
+
+
+};
+
+class LOD_TriFace {
+public:
+
+ LOD_VertexInd m_verts[3];
+
+ LOD_TriFace(
+ );
+
+ // Elementary helper methods
+ ////////////////////////////
+
+ void
+ SwapVertex(
+ LOD_VertexInd old_v,
+ LOD_VertexInd new_v
+ );
+
+ bool
+ SelectTag(
+ ) const;
+
+ void
+ SetSelectTag(
+ bool tag
+ );
+
+ int
+ OpenTag(
+ );
+ void
+ SetOpenTag(
+ int tag
+ );
+
+ bool
+ Degenerate(
+ );
+
+ void
+ CopyVerts(
+ int * index_ptr
+ );
+
+};
+
+#endif
+
diff --git a/intern/decimation/intern/LOD_QSDecimator.cpp b/intern/decimation/intern/LOD_QSDecimator.cpp
new file mode 100644
index 00000000000..6620fa15ad3
--- /dev/null
+++ b/intern/decimation/intern/LOD_QSDecimator.cpp
@@ -0,0 +1,324 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_QSDecimator.h"
+
+#include "LOD_ExternBufferEditor.h"
+
+using namespace std;
+
+ LOD_QSDecimator *
+LOD_QSDecimator::
+New(
+ LOD_ManMesh2 &mesh,
+ LOD_ExternNormalEditor &face_editor,
+ LOD_ExternBufferEditor &extern_editor
+){
+
+ MEM_SmartPtr<LOD_QSDecimator> output
+ = new LOD_QSDecimator(mesh,face_editor,extern_editor);
+
+ MEM_SmartPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New());
+ MEM_SmartPtr<LOD_QuadricEditor> q_editor(LOD_QuadricEditor::New(mesh));
+
+ if (
+ output == NULL ||
+ collapser == NULL ||
+ q_editor == NULL
+ ) {
+ return NULL;
+ }
+ output->m_collapser = collapser.Release();
+ output->m_quadric_editor = q_editor.Release();
+ return output.Release();
+}
+
+
+
+ bool
+LOD_QSDecimator::
+Arm(
+){
+ MT_assert(!m_is_armed);
+ bool heap_result = BuildHeap();
+ if (!heap_result) {
+ return false;
+ }
+ m_is_armed = true;
+ return true;
+}
+
+ bool
+LOD_QSDecimator::
+Step(
+){
+ return CollapseEdge();
+}
+
+
+LOD_QSDecimator::
+LOD_QSDecimator(
+ LOD_ManMesh2 &mesh,
+ LOD_ExternNormalEditor &face_editor,
+ LOD_ExternBufferEditor &extern_editor
+) :
+ m_mesh(mesh),
+ m_face_editor(face_editor),
+ m_extern_editor(extern_editor),
+ m_is_armed (false)
+{
+ m_deg_edges.reserve(32);
+ m_deg_faces.reserve(32);
+ m_deg_vertices.reserve(32);
+ m_update_faces.reserve(32);
+ m_new_edges.reserve(32);
+ m_update_vertices.reserve(32);
+};
+
+ bool
+LOD_QSDecimator::
+CollapseEdge(
+){
+
+ // find an edge to collapse
+
+ // FIXME force an edge collapse
+ // or return false
+
+ std::vector<LOD_Edge> & edges = m_mesh.EdgeSet();
+ std::vector<LOD_Vertex> & verts = m_mesh.VertexSet();
+ std::vector<LOD_Quadric> & quadrics = m_quadric_editor->Quadrics();
+ int size = edges.size();
+
+ if (size == 0) return false;
+
+ const int heap_top = m_heap->Top();
+
+ if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) {
+ return false;
+ }
+
+ // compute the target position
+ MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]);
+ LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]];
+ LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]];
+
+ LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]];
+ LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]];
+
+ LOD_Quadric sum = q0;
+ sum += q1;
+
+
+ if (m_collapser->CollapseEdge(
+ heap_top,
+ m_mesh,
+ m_deg_edges,
+ m_deg_faces,
+ m_deg_vertices,
+ m_new_edges,
+ m_update_faces,
+ m_update_vertices
+ )) {
+
+ // assign new vertex position
+
+ v0.pos = new_vertex;
+ v1.pos = new_vertex;
+
+ // sum the quadrics of v0 and v1
+ q0 = sum;
+ q1 = sum;
+
+ // ok update the primitive properties
+
+ m_face_editor.Update(m_update_faces);
+ m_face_editor.UpdateVertexNormals(m_update_vertices);
+
+ // update the external vertex buffer
+ m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices);
+
+ // update the external face buffer
+ m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces);
+
+ // update the edge heap
+ UpdateHeap(m_deg_edges,m_new_edges);
+
+ m_quadric_editor->Remove(m_deg_vertices);
+ m_face_editor.Remove(m_deg_faces);
+ m_face_editor.RemoveVertexNormals(m_deg_vertices);
+
+ // delete the primitives
+
+ DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices);
+
+ } else {
+ // the edge could not be collapsed at the moment - so
+ // we adjust it's priority and add it back to the heap.
+ m_heap->Remove(edges.begin(),0);
+ edges[heap_top].HeapKey() = - MT_INFINITY;
+ m_heap->Insert(edges.begin(),heap_top);
+ }
+
+ //clear all the temporary buffers
+
+ m_deg_faces.clear();
+ m_deg_edges.clear();
+ m_deg_vertices.clear();
+
+ m_update_faces.clear();
+ m_update_vertices.clear();
+ m_new_edges.clear();
+
+ return true;
+
+}
+
+ void
+LOD_QSDecimator::
+DeletePrimitives(
+ const vector<LOD_EdgeInd> & degenerate_edges,
+ const vector<LOD_FaceInd> & degenerate_faces,
+ const vector<LOD_VertexInd> & degenerate_vertices
+) {
+
+ // assumes that the 3 vectors are sorted in descending order.
+
+ // Delete Degnerate primitives
+ //////////////////////////////
+
+
+ // delete the old edges - we have to be very careful here
+ // mesh.delete() swaps edges to be deleted with the last edge in
+ // the edge buffer. However the next edge to be deleted may have
+ // been the last edge in the buffer!
+
+ // One way to solve this is to sort degenerate_edges in descending order.
+ // And then delete them in that order.
+
+ // it is also vital that degenerate_edges contains no duplicates
+
+ vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin();
+ vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+ m_mesh.DeleteEdge(*edge_it,m_heap);
+ }
+
+
+
+ vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin();
+ vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end();
+
+ for (;face_it != face_end; ++face_it) {
+ m_mesh.DeleteFace(m_extern_editor,*face_it);
+ }
+
+ vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin();
+ vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end();
+
+ for (;vertex_it != vertex_end; ++vertex_it) {
+ m_mesh.DeleteVertex(m_extern_editor,*vertex_it);
+ }
+}
+
+
+ bool
+LOD_QSDecimator::
+BuildHeap(
+){
+ // build the quadrics
+
+ if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false;
+
+
+ m_heap = CTR_UHeap<LOD_Edge>::New();
+ // load in edge pointers to the heap
+
+ std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet();
+ std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end();
+ std::vector<LOD_Edge>::iterator edge_start = edge_set.begin();
+
+ std::vector<int> & heap_vector = m_heap->HeapVector();
+
+ for (int i = 0; i < edge_set.size(); ++i) {
+ edge_set[i].HeapPos() = i;
+ heap_vector.push_back(i);
+ }
+
+ m_heap->MakeHeap(edge_set.begin());
+
+ return true;
+}
+
+ void
+LOD_QSDecimator::
+UpdateHeap(
+ std::vector<LOD_EdgeInd> &deg_edges,
+ std::vector<LOD_EdgeInd> &new_edges
+){
+ // first of all compute values for the new edges
+ // and bung them on the heap.
+
+ std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet();
+
+ std::vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin();
+ std::vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end();
+
+
+ // insert all the new edges
+ ///////////////////////////
+
+ // compute edge costs ffor the new edges
+
+ m_quadric_editor->ComputeEdgeCosts(new_edges);
+
+ // inser the new elements into the heap
+
+ for (; edge_it != end_it; ++edge_it) {
+ m_heap->Insert(edge_set.begin(),*edge_it);
+ }
+
+
+ // remove all the old values from the heap
+
+ edge_it = deg_edges.begin();
+ end_it = deg_edges.end();
+
+ for (; edge_it != end_it; ++edge_it) {
+ LOD_Edge &e = edge_set[*edge_it];
+ m_heap->Remove(edge_set.begin(),e.HeapPos());
+
+ e.HeapPos() = 0xffffffff;
+
+ }
+}
+
diff --git a/intern/decimation/intern/LOD_QSDecimator.h b/intern/decimation/intern/LOD_QSDecimator.h
new file mode 100644
index 00000000000..c5ae915db29
--- /dev/null
+++ b/intern/decimation/intern/LOD_QSDecimator.h
@@ -0,0 +1,128 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_LOD_QSDecimator_H
+
+#define NAN_INCLUDED_LOD_QSDecimator_H
+
+#include "MEM_NonCopyable.h"
+#include "LOD_ManMesh2.h"
+#include "LOD_ExternNormalEditor.h"
+#include "LOD_EdgeCollapser.h"
+#include "LOD_QuadricEditor.h"
+
+class LOD_ExternBufferEditor;
+
+class LOD_QSDecimator : public MEM_NonCopyable {
+
+public :
+
+ static
+ LOD_QSDecimator *
+ New(
+ LOD_ManMesh2 &mesh,
+ LOD_ExternNormalEditor &face_editor,
+ LOD_ExternBufferEditor &extern_editor
+ );
+
+
+ bool
+ Arm(
+ );
+
+
+ bool
+ Step(
+ );
+
+private :
+
+ LOD_QSDecimator(
+ LOD_ManMesh2 &mesh,
+ LOD_ExternNormalEditor &face_editor,
+ LOD_ExternBufferEditor &extern_editor
+ );
+
+ bool
+ CollapseEdge(
+ );
+
+ bool
+ BuildHeap(
+ );
+
+ void
+ UpdateHeap(
+ std::vector<LOD_EdgeInd> &deg_edges,
+ std::vector<LOD_EdgeInd> &new_edges
+ );
+
+ void
+ DeletePrimitives(
+ const std::vector<LOD_EdgeInd> & degenerate_edges,
+ const std::vector<LOD_FaceInd> & degenerate_faces,
+ const std::vector<LOD_VertexInd> & degenerate_vertices
+ );
+
+
+private :
+
+ // owned by this class
+ //////////////////////
+
+ MEM_SmartPtr<LOD_EdgeCollapser> m_collapser;
+ MEM_SmartPtr<CTR_UHeap<LOD_Edge> > m_heap;
+ MEM_SmartPtr<LOD_QuadricEditor> m_quadric_editor;
+
+ bool m_is_armed;
+
+ // arguments to New(...)
+ ////////////////////////
+
+ LOD_ManMesh2 & m_mesh;
+ LOD_ExternNormalEditor &m_face_editor;
+ LOD_ExternBufferEditor & m_extern_editor;
+
+ // temporary buffers
+ ////////////////////
+
+ std::vector<LOD_FaceInd> m_deg_faces;
+ std::vector<LOD_EdgeInd> m_deg_edges;
+ std::vector<LOD_VertexInd> m_deg_vertices;
+
+ std::vector<LOD_FaceInd> m_update_faces;
+ std::vector<LOD_EdgeInd> m_new_edges;
+ std::vector<LOD_VertexInd> m_update_vertices;
+
+
+};
+#endif
+
diff --git a/intern/decimation/intern/LOD_Quadric.h b/intern/decimation/intern/LOD_Quadric.h
new file mode 100644
index 00000000000..16e7dec17e9
--- /dev/null
+++ b/intern/decimation/intern/LOD_Quadric.h
@@ -0,0 +1,168 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_LOD_Quadric_h
+
+#define NAN_INCLUDED_LOD_Quadric_h
+
+#include "MT_Vector3.h"
+#include "MT_Matrix3x3.h"
+
+
+class LOD_Quadric {
+
+private:
+ MT_Scalar a2, ab, ac, ad;
+ MT_Scalar b2, bc, bd;
+ MT_Scalar c2, cd;
+ MT_Scalar d2;
+
+ void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d);
+
+public:
+
+ LOD_Quadric(
+ ) {
+ Clear();
+ };
+
+ LOD_Quadric(
+ const MT_Vector3 & vec,
+ const MT_Scalar & offset
+ ) {
+ a2 = vec[0] *vec[0];
+ b2 = vec[1] *vec[1];
+ c2 = vec[2] *vec[2];
+
+ ab = vec[0]*vec[1];
+ ac = vec[0]*vec[2];
+ bc = vec[1]*vec[2];
+
+ MT_Vector3 temp = vec*offset;
+ ad = temp[0];
+ bd = temp[1];
+ cd = temp[2];
+
+ d2 = offset*offset;
+ };
+
+ MT_Matrix3x3
+ Tensor(
+ ) const {
+ // return a symmetric matrix
+
+ return MT_Matrix3x3(
+ a2,ab,ac,
+ ab,b2,bc,
+ ac,bc,c2
+ );
+ };
+
+
+ MT_Vector3
+ Vector(
+ ) const {
+ return MT_Vector3(ad, bd, cd);
+ };
+
+ void
+ Clear(
+ MT_Scalar val=0.0
+ ) {
+ a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val;
+ };
+
+ LOD_Quadric &
+ operator=(
+ const LOD_Quadric& Q
+ ) {
+
+ a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad;
+ b2 = Q.b2; bc = Q.bc; bd = Q.bd;
+ c2 = Q.c2; cd = Q.cd;
+ d2 = Q.d2;
+ return *this;
+ };
+
+ LOD_Quadric&
+ operator+=(
+ const LOD_Quadric& Q
+ ) {
+ a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad;
+ b2 += Q.b2; bc += Q.bc; bd += Q.bd;
+ c2 += Q.c2; cd += Q.cd;
+ d2 += Q.d2;
+ return *this;
+ };
+
+ LOD_Quadric&
+ operator*=(
+ const MT_Scalar & s
+ ) {
+ a2 *= s; ab *= s; ac *= s; ad *= s;
+ b2 *= s; bc *= s; bd *= s;
+ c2 *= s; cd *= s;
+ d2 *= s;
+ return *this;
+ };
+
+
+ MT_Scalar
+ Evaluate(
+ const MT_Vector3 &v
+ ) const {
+ // compute the LOD_Quadric error
+
+ return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad
+ +v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd
+ +v[2]*v[2]*c2 + 2*v[2]*cd
+ + d2;
+ };
+
+ bool
+ Optimize(
+ MT_Vector3& v
+ ) const {
+
+ MT_Scalar det = Tensor().determinant();
+ if (MT_fuzzyZero(det)) {
+ return false;
+ }
+
+ v = -((Tensor().inverse()) * Vector());
+ return true;
+ };
+
+};
+
+
+#endif
+
diff --git a/intern/decimation/intern/LOD_QuadricEditor.cpp b/intern/decimation/intern/LOD_QuadricEditor.cpp
new file mode 100644
index 00000000000..751f5d1e7e0
--- /dev/null
+++ b/intern/decimation/intern/LOD_QuadricEditor.cpp
@@ -0,0 +1,279 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "LOD_QuadricEditor.h"
+
+#include "LOD_ExternNormalEditor.h"
+
+// Creation
+///////////
+
+using namespace std;
+
+
+LOD_QuadricEditor::
+LOD_QuadricEditor(
+ LOD_ManMesh2 &mesh
+) :
+ m_quadrics(NULL),
+ m_mesh(mesh)
+{
+};
+
+ LOD_QuadricEditor *
+LOD_QuadricEditor::
+New(
+ LOD_ManMesh2 &mesh
+){
+ //same number of quadrics as vertices in the mesh
+
+ MEM_SmartPtr<LOD_QuadricEditor> output(new LOD_QuadricEditor(mesh));
+
+ if (output == NULL) {
+ return NULL;
+ }
+ return output.Release();
+}
+
+
+// Property editor interface
+////////////////////////////
+
+ void
+LOD_QuadricEditor::
+Remove(
+ std::vector<LOD_VertexInd> &sorted_vertices
+){
+ vector<LOD_Quadric> & quadrics = *m_quadrics;
+
+ vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin();
+ vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end();
+
+ for (; it_start != it_end; ++it_start) {
+
+ if (quadrics.size() > 0) {
+ LOD_Quadric temp = quadrics[*it_start];
+
+ quadrics[*it_start] = quadrics.back();
+ quadrics.back() = temp;
+
+ quadrics.pop_back();
+ }
+ }
+};
+
+
+// Editor specific methods
+//////////////////////////
+
+ bool
+LOD_QuadricEditor::
+BuildQuadrics(
+ LOD_ExternNormalEditor& normal_editor,
+ bool preserve_boundaries
+){
+ if (m_quadrics != NULL) delete(m_quadrics);
+
+ m_quadrics =new vector<LOD_Quadric> (m_mesh.VertexSet().size());
+ if (m_quadrics == NULL) return false;
+
+ // iterate through the face set of the mesh
+ // compute a quadric based upon that face and
+ // add it to each of it's vertices quadrics.
+
+ const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
+ const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+ vector<LOD_Edge> &edges = m_mesh.EdgeSet();
+
+ const vector<MT_Vector3> &normals = normal_editor.Normals();
+ vector<MT_Vector3>::const_iterator normal_it = normals.begin();
+
+ vector<LOD_TriFace>::const_iterator face_it = faces.begin();
+ vector<LOD_TriFace>::const_iterator face_end = faces.end();
+
+ vector<LOD_Quadric> & quadrics = *m_quadrics;
+
+
+ for (; face_it != face_end; ++face_it, ++normal_it) {
+
+ MT_Vector3 normal = *normal_it;
+ MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos);
+
+ LOD_Quadric q(normal,offset);
+
+ quadrics[face_it->m_verts[0]] += q;
+ quadrics[face_it->m_verts[1]] += q;
+ quadrics[face_it->m_verts[2]] += q;
+ }
+
+ if (preserve_boundaries) {
+
+ // iterate through the edge set and add a boundary quadric to
+ // each of the boundary edges vertices.
+
+ vector<LOD_Edge>::const_iterator edge_it = edges.begin();
+ vector<LOD_Edge>::const_iterator edge_end = edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+ if (edge_it->BoundaryEdge()) {
+
+ // compute a plane perpendicular to the edge and the normal
+ // of the edges single polygon.
+ const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos;
+ const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos;
+
+ MT_Vector3 edge_vector = v1 - v0;
+
+ LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty());
+ edge_vector = edge_vector.cross(normals[edge_face]);
+
+ if (!edge_vector.fuzzyZero()) {
+ edge_vector.normalize();
+
+ LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0));
+ boundary_q *= 100;
+
+ quadrics[edge_it->m_verts[0]] += boundary_q;
+ quadrics[edge_it->m_verts[1]] += boundary_q;
+ }
+ }
+ }
+ }
+
+
+ // initiate the heap keys of the edges by computing the edge costs.
+
+ vector<LOD_Edge>::iterator edge_it = edges.begin();
+ vector<LOD_Edge>::const_iterator edge_end = edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+
+ MT_Vector3 target = TargetVertex(*edge_it);
+
+ LOD_Edge &e = *edge_it;
+ LOD_Quadric q0 = quadrics[e.m_verts[0]];
+ const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
+
+ e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
+ }
+
+ return true;
+
+};
+
+ MT_Vector3
+LOD_QuadricEditor::
+TargetVertex(
+ LOD_Edge & e
+){
+
+ // compute an edge contration target for edge ei
+ // this is computed by summing it's vertices quadrics and
+ // optimizing the result.
+ vector<LOD_Vertex> &verts = m_mesh.VertexSet();
+
+ vector<LOD_Quadric> &quadrics = *m_quadrics;
+
+ LOD_VertexInd v0 = e.m_verts[0];
+ LOD_VertexInd v1 = e.m_verts[1];
+
+ LOD_Quadric q0 = quadrics[v0];
+ q0 += quadrics[v1];
+
+ MT_Vector3 result;
+
+ if (q0.Optimize(result)) {
+ return result;
+ } else {
+ // the quadric was degenerate -> just take the average of
+ // v0 and v1
+
+ return ((verts[v0].pos + verts[v1].pos) * 0.5);
+ }
+};
+
+ void
+LOD_QuadricEditor::
+ComputeEdgeCosts(
+ vector<LOD_EdgeInd> &edges
+){
+
+ // for each we compute the target vertex and then compute
+ // the quadric error e = Q1(v') + Q2(v')
+ vector<LOD_Edge> &edge_set = m_mesh.EdgeSet();
+
+ vector<LOD_Quadric> &quadrics = *m_quadrics;
+
+ vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin();
+ vector<LOD_EdgeInd>::const_iterator edge_end = edges.end();
+
+ for (; edge_it != edge_end; ++edge_it) {
+
+ MT_Vector3 target = TargetVertex(edge_set[*edge_it]);
+
+ LOD_Edge &e = edge_set[*edge_it];
+ LOD_Quadric q0 = quadrics[e.m_verts[0]];
+ const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
+
+ e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
+ }
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/decimation/intern/LOD_QuadricEditor.h b/intern/decimation/intern/LOD_QuadricEditor.h
new file mode 100644
index 00000000000..bb3a5e957b9
--- /dev/null
+++ b/intern/decimation/intern/LOD_QuadricEditor.h
@@ -0,0 +1,119 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_LOD_QuadricEditor_h
+
+#define NAN_INCLUDED_LOD_QuadricEditor_h
+
+#include "MEM_NonCopyable.h"
+#include "LOD_ManMesh2.h"
+#include "MT_Vector3.h"
+#include "LOD_Quadric.h"
+
+class LOD_ExternNormalEditor;
+
+
+class LOD_QuadricEditor : public MEM_NonCopyable
+{
+
+public :
+
+ // Creation
+ ///////////
+
+ static
+ LOD_QuadricEditor *
+ New(
+ LOD_ManMesh2 &mesh
+ );
+
+ // Property editor interface
+ ////////////////////////////
+
+ void
+ Remove(
+ std::vector<LOD_VertexInd> &sorted_vertices
+ );
+
+ void
+ Update(
+ std::vector<LOD_FaceInd> &sorted_vertices
+ );
+
+
+ std::vector<LOD_Quadric> &
+ Quadrics(
+ ) const {
+ return *m_quadrics;
+ };
+
+
+ // Editor specific methods
+ //////////////////////////
+
+ bool
+ BuildQuadrics(
+ LOD_ExternNormalEditor& normal_editor,
+ bool preserve_boundaries
+ );
+
+
+ void
+ ComputeEdgeCosts(
+ std::vector<LOD_EdgeInd> &edges
+ );
+
+ MT_Vector3
+ TargetVertex(
+ LOD_Edge &e
+ );
+
+ ~LOD_QuadricEditor(
+ ){
+ delete(m_quadrics);
+ };
+
+
+private :
+
+ std::vector<LOD_Quadric> * m_quadrics;
+
+ LOD_ManMesh2 &m_mesh;
+
+private :
+
+ LOD_QuadricEditor(LOD_ManMesh2 &mesh);
+
+
+
+};
+
+#endif
diff --git a/intern/decimation/intern/LOD_decimation.cpp b/intern/decimation/intern/LOD_decimation.cpp
new file mode 100644
index 00000000000..7bbc0945424
--- /dev/null
+++ b/intern/decimation/intern/LOD_decimation.cpp
@@ -0,0 +1,156 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+// implementation of external c api
+
+
+#include "../extern/LOD_decimation.h"
+#include "LOD_DecimationClass.h"
+
+using namespace std;
+
+ int
+LOD_LoadMesh(
+ LOD_Decimation_InfoPtr info
+) {
+ if (info == NULL) return 0;
+ if (
+ info->vertex_buffer == NULL ||
+ info->vertex_normal_buffer == NULL ||
+ info->triangle_index_buffer == NULL
+ ) {
+ return 0;
+ }
+
+
+ // create the intern object to hold all
+ // the decimation classes
+
+ MEM_SmartPtr<LOD_DecimationClass> intern(LOD_DecimationClass::New(info));
+
+ if (intern == NULL) return 0;
+
+ MEM_SmartPtr<vector<LOD_Vertex> > intern_vertex_buffer(new vector<LOD_Vertex>(info->vertex_num));
+ if (intern_vertex_buffer == NULL) return 0;
+
+ vector<LOD_Vertex>::iterator intern_vertex_it(intern_vertex_buffer->begin());
+
+ // now load in the vertices to the mesh
+
+ const int vertex_stride = 3;
+
+ float * vertex_ptr = info->vertex_buffer;
+ const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride;
+
+ LOD_ManMesh2 &mesh = intern->Mesh();
+
+ for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) {
+ intern_vertex_it->pos = MT_Vector3(vertex_ptr);
+ }
+
+ mesh.SetVertices(intern_vertex_buffer);
+
+ // load in the triangles
+
+ const int triangle_stride = 3;
+
+ int * triangle_ptr = info->triangle_index_buffer;
+ const int * triangle_end = triangle_ptr + info->face_num*triangle_stride;
+
+ try {
+
+ for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) {
+ mesh.AddTriangle(triangle_ptr);
+ }
+ }
+
+ catch (...) {
+ return 0;
+ }
+
+ // ok we have built the mesh
+
+ intern->m_e_decimation_state = LOD_DecimationClass::e_loaded;
+
+ info->intern = (void *) (intern.Release());
+
+ return 1;
+}
+
+ int
+LOD_PreprocessMesh(
+ LOD_Decimation_InfoPtr info
+) {
+ if (info == NULL) return 0;
+ if (info->intern == NULL) return 0;
+
+ LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
+ if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0;
+
+ // arm the various internal classes so that we are ready to step
+ // through decimation
+
+ intern->FaceEditor().BuildNormals();
+ if (intern->Decimator().Arm() == false) return 0;
+
+ // ok preprocessing done
+ intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed;
+
+ return 1;
+}
+
+ int
+LOD_CollapseEdge(
+ LOD_Decimation_InfoPtr info
+){
+ if (info == NULL) return 0;
+ if (info->intern == NULL) return 0;
+ LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
+ if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0;
+
+ bool step_result = intern->Decimator().Step();
+
+ return step_result == true ? 1 : 0;
+}
+
+
+ int
+LOD_FreeDecimationData(
+ LOD_Decimation_InfoPtr info
+){
+ if (info == NULL) return 0;
+ if (info->intern == NULL) return 0;
+ LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
+ delete(intern);
+ info->intern = NULL;
+ return 1;
+}
+
diff --git a/intern/decimation/intern/Makefile b/intern/decimation/intern/Makefile
new file mode 100644
index 00000000000..d7c9d89d9c7
--- /dev/null
+++ b/intern/decimation/intern/Makefile
@@ -0,0 +1,45 @@
+#
+# $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.
+#
+# 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 *****
+# decimation intern Makefile
+#
+
+LIBNAME = decimation
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(NAN_LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+CPPFLAGS += -I$(NAN_CONTAINER)/include
+
+
diff --git a/intern/decimation/make/msvc_6_0/decimation.dsp b/intern/decimation/make/msvc_6_0/decimation.dsp
new file mode 100644
index 00000000000..32d6928c61a
--- /dev/null
+++ b/intern/decimation/make/msvc_6_0/decimation.dsp
@@ -0,0 +1,188 @@
+# Microsoft Developer Studio Project File - Name="decimation" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=decimation - 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 "decimation.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 "decimation.mak" CFG="decimation - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "decimation - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "decimation - 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)" == "decimation - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# 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 /Ob2 /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\libdecimation.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Release\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\libdecimation.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "decimation - 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 "Debug"
+# PROP Intermediate_Dir "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 /W4 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\libdecimation.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Debug\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\debug\libdecimation.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\decimation\lib\debug\" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "decimation - Win32 Release"
+# Name "decimation - Win32 Debug"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_decimation.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_DecimationClass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_EdgeCollapser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_EdgeCollapser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_ExternBufferEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_ExternNormalEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_ExternNormalEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_FaceNormalEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_FaceNormalEditor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_ManMesh2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_ManMesh2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_MeshBounds.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_MeshException.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_MeshPrimitives.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_MeshPrimitives.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_QSDecimator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_QSDecimator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_Quadric.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_QuadricEditor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\LOD_QuadricEditor.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\extern\LOD_decimation.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/decimation/make/msvc_6_0/decimation.dsw b/intern/decimation/make/msvc_6_0/decimation.dsw
new file mode 100644
index 00000000000..f874b324725
--- /dev/null
+++ b/intern/decimation/make/msvc_6_0/decimation.dsw
@@ -0,0 +1,33 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "decimation"=.\decimation.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
+
+
+
+
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
new file mode 100644
index 00000000000..10b986a55b0
--- /dev/null
+++ b/intern/ghost/GHOST_C-api.h
@@ -0,0 +1,733 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef GHOST_C_API_H
+
+#define GHOST_C_API_H
+
+#include "GHOST_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GHOST_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
+GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
+GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventHandle);
+GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
+
+
+/**
+ * Definition of a callback routine that receives events.
+ * @param event The event received.
+ * @param userdata The callback's user data, supplied to GHOST_CreateSystem.
+ */
+typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata);
+
+
+/**
+ * Creates the one and only system.
+ * @return a handle to the system.
+ */
+extern GHOST_SystemHandle GHOST_CreateSystem(void);
+
+/**
+ * Disposes the one and only system.
+ * @param systemhandle The handle to the system
+ * @return An indication of success.
+ */
+extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle);
+
+
+/**
+ * Creates an event consumer object
+ * @param eventCallback The event callback routine.
+ * @param userdata Pointer to user data returned to the callback routine.
+ */
+extern GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata);
+
+/**
+ * Disposes an event consumer object
+ * @param consumerhandle Handle to the event consumer.
+ * @return An indication of success.
+ */
+extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle);
+
+
+/**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * Based on ANSI clock() routine.
+ * @param systemhandle The handle to the system
+ * @return The number of milliseconds.
+ */
+extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
+
+/**
+ * Installs a timer.
+ * Note that, on most operating systems, messages need to be processed in order
+ * for the timer callbacks to be invoked.
+ * @param systemhandle The handle to the system
+ * @param delay The time to wait for the first call to the timerProc (in milliseconds)
+ * @param interval The interval between calls to the timerProc (in milliseconds)
+ * @param timerProc The callback invoked when the interval expires,
+ * @param userData Placeholder for user data.
+ * @return A timer task (0 if timer task installation failed).
+ */
+extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
+ GHOST_TUns64 delay,
+ GHOST_TUns64 interval,
+ GHOST_TimerProcPtr timerProc,
+ GHOST_TUserDataPtr userData);
+
+/**
+ * Removes a timer.
+ * @param systemhandle The handle to the system
+ * @param timerTask Timer task to be removed.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
+ GHOST_TimerTaskHandle timertaskhandle);
+
+/***************************************************************************************
+ ** Display/window management functionality
+ ***************************************************************************************/
+
+/**
+ * Returns the number of displays on this system.
+ * @param systemhandle The handle to the system
+ * @return The number of displays.
+ */
+extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
+
+/**
+ * Returns the dimensions of the main display on this system.
+ * @param systemhandle The handle to the system
+ * @param width A pointer the width gets put in
+ * @param height A pointer the height gets put in
+ * @return void.
+ */
+extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
+ GHOST_TUns32* width,
+ GHOST_TUns32* height);
+
+/**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param systemhandle The handle to the system
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @return A handle to the new window ( == NULL if creation failed).
+ */
+extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
+ char* title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ const int stereoVisual);
+
+/**
+ * Returns the window user data.
+ * @param windowhandle The handle to the window
+ * @return The window user data.
+ */
+extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle);
+
+/**
+ * Changes the window user data.
+ * @param windowhandle The handle to the window
+ * @param data The window user data.
+ */
+extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle,
+ GHOST_TUserDataPtr userdata);
+
+/**
+ * Dispose a window.
+ * @param systemhandle The handle to the system
+ * @param window Handle to the window to be disposed.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle windowhandle);
+
+/**
+ * Returns whether a window is valid.
+ * @param systemhandle The handle to the system
+ * @param window Handle to the window to be checked.
+ * @return Indication of validity.
+ */
+extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle windowhandle);
+
+/**
+ * Begins full screen mode.
+ * @param systemhandle The handle to the system
+ * @param setting The new setting of the display.
+ * @return A handle to the window displayed in full screen.
+ * This window is invalid after full screen has been ended.
+ */
+extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
+ GHOST_DisplaySetting* setting,
+ const int stereoVisual);
+
+/**
+ * Ends full screen mode.
+ * @param systemhandle The handle to the system
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle);
+
+/**
+ * Returns current full screen mode status.
+ * @param systemhandle The handle to the system
+ * @return The current status.
+ */
+extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
+
+/***************************************************************************************
+ ** Event management functionality
+ ***************************************************************************************/
+
+/**
+ * Retrieves events from the system and stores them in the queue.
+ * @param systemhandle The handle to the system
+ * @param waitForEvent Boolean to indicate that ProcessEvents should
+ * wait (block) until the next event before returning.
+ * @return Indication of the presence of events.
+ */
+extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent);
+
+/**
+ * Retrieves events from the queue and send them to the event consumers.
+ * @param systemhandle The handle to the system
+ * @return Indication of the presence of events.
+ */
+extern int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
+
+/**
+ * Adds the given event consumer to our list.
+ * @param systemhandle The handle to the system
+ * @param consumerhandle The event consumer to add.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle,
+ GHOST_EventConsumerHandle consumerhandle);
+
+
+
+/***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+/**
+ * Returns the current cursor shape.
+ * @param windowhandle The handle to the window
+ * @return The current cursor shape.
+ */
+extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle);
+
+/**
+ * Set the shape of the cursor.
+ * @param windowhandle The handle to the window
+ * @param cursor The new cursor shape type id.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle,
+ GHOST_TStandardCursor cursorshape);
+
+/**
+ * Set the shape of the cursor to a custom cursor.
+ * @param windowhandle The handle to the window
+ * @param bitmap The bitmap data for the cursor.
+ * @param mask The mask data for the cursor.
+ * @param hotX The X coordinate of the cursor hotspot.
+ * @param hotY The Y coordinate of the cursor hotspot.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
+ GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY);
+
+/**
+ * Returns the visibility state of the cursor.
+ * @param windowhandle The handle to the window
+ * @return The visibility state of the cursor.
+ */
+extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle);
+
+/**
+ * Shows or hides the cursor.
+ * @param windowhandle The handle to the window
+ * @param visible The new visibility state of the cursor.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle,
+ int visible);
+
+/**
+ * Returns the current location of the cursor (location in screen coordinates)
+ * @param systemhandle The handle to the system
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
+ GHOST_TInt32* x,
+ GHOST_TInt32* y);
+
+/**
+ * Updates the location of the cursor (location in screen coordinates).
+ * Not all operating systems allow the cursor to be moved (without the input device being moved).
+ * @param systemhandle The handle to the system
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y);
+
+/***************************************************************************************
+ ** Access to mouse button and keyboard states.
+ ***************************************************************************************/
+
+/**
+ * Returns the state of a modifier key (ouside the message queue).
+ * @param systemhandle The handle to the system
+ * @param mask The modifier key state to retrieve.
+ * @param isDown Pointer to return modifier state in.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
+ GHOST_TModifierKeyMask mask,
+ int* isDown);
+
+/**
+ * Returns the state of a mouse button (ouside the message queue).
+ * @param systemhandle The handle to the system
+ * @param mask The button state to retrieve.
+ * @param isDown Pointer to return button state in.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
+ GHOST_TButtonMask mask,
+ int* isDown);
+
+/**
+ * Returns the event type.
+ * @param eventhandle The handle to the event
+ * @return The event type.
+ */
+extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle);
+
+/**
+ * Returns the time this event was generated.
+ * @param eventhandle The handle to the event
+ * @return The event generation time.
+ */
+extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle);
+
+/**
+ * Returns the window this event was generated on,
+ * or NULL if it is a 'system' event.
+ * @param eventhandle The handle to the event
+ * @return The generating window.
+ */
+extern GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle);
+
+/**
+ * Returns the event data.
+ * @param eventhandle The handle to the event
+ * @return The event data.
+ */
+extern GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle);
+
+/**
+ * Returns the timer callback.
+ * @param timertaskhandle The handle to the timertask
+ * @return The timer callback.
+ */
+extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle);
+
+/**
+ * Changes the timer callback.
+ * @param timertaskhandle The handle to the timertask
+ * @param timerProc The timer callback.
+ */
+extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
+ GHOST_TimerProcPtr timerProc);
+
+/**
+ * Returns the timer user data.
+ * @param timertaskhandle The handle to the timertask
+ * @return The timer user data.
+ */
+extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle);
+
+/**
+ * Changes the time user data.
+ * @param timertaskhandle The handle to the timertask
+ * @param data The timer user data.
+ */
+extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
+ GHOST_TUserDataPtr userData);
+
+/**
+ * Returns indication as to whether the window is valid.
+ * @param windowhandle The handle to the window
+ * @return The validity of the window.
+ */
+extern int GHOST_GetValid(GHOST_WindowHandle windowhandle) ;
+
+/**
+ * Returns the type of drawing context used in this window.
+ * @param windowhandle The handle to the window
+ * @return The current type of drawing context.
+ */
+extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle);
+
+/**
+ * Tries to install a rendering context in this window.
+ * @param windowhandle The handle to the window
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
+ GHOST_TDrawingContextType type);
+
+/**
+ * Sets the title displayed in the title bar.
+ * @param windowhandle The handle to the window
+ * @param title The title to display in the title bar.
+ */
+extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle,
+ char* title);
+
+/**
+ * Returns the title displayed in the title bar. The title
+ * should be free'd with free().
+ *
+ * @param windowhandle The handle to the window
+ * @return The title, free with free().
+ */
+extern char* GHOST_GetTitle(GHOST_WindowHandle windowhandle);
+
+/**
+ * Returns the window rectangle dimensions.
+ * These are screen coordinates.
+ * @param windowhandle The handle to the window
+ * @return A handle to the bounding rectangle of the window.
+ */
+extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle);
+
+/**
+ * Returns the client rectangle dimensions.
+ * The left and top members of the rectangle are always zero.
+ * @param windowhandle The handle to the window
+ * @return A handle to the bounding rectangle of the window.
+ */
+extern GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle);
+
+/**
+ * Disposes a rectangle object
+ * @param rectanglehandle Handle to the rectangle.
+ */
+void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle);
+
+/**
+ * Resizes client rectangle width.
+ * @param windowhandle The handle to the window
+ * @param width The new width of the client area of the window.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 width);
+
+/**
+ * Resizes client rectangle height.
+ * @param windowhandle The handle to the window
+ * @param height The new height of the client area of the window.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 height);
+
+/**
+ * Resizes client rectangle.
+ * @param windowhandle The handle to the window
+ * @param width The new width of the client area of the window.
+ * @param height The new height of the client area of the window.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height);
+
+/**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param windowhandle The handle to the window
+ * @param inX The x-coordinate on the screen.
+ * @param inY The y-coordinate on the screen.
+ * @param outX The x-coordinate in the client rectangle.
+ * @param outY The y-coordinate in the client rectangle.
+ */
+extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32* outX,
+ GHOST_TInt32* outY) ;
+
+/**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param windowhandle The handle to the window
+ * @param inX The x-coordinate in the client rectangle.
+ * @param inY The y-coordinate in the client rectangle.
+ * @param outX The x-coordinate on the screen.
+ * @param outY The y-coordinate on the screen.
+ */
+extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32* outX,
+ GHOST_TInt32* outY);
+
+/**
+ * Returns the state of the window (normal, minimized, maximized).
+ * @param windowhandle The handle to the window
+ * @return The state of the window.
+ */
+extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle);
+
+/**
+ * Sets the state of the window (normal, minimized, maximized).
+ * @param windowhandle The handle to the window
+ * @param state The state of the window.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
+ GHOST_TWindowState state);
+
+/**
+ * Sets the order of the window (bottom, top).
+ * @param windowhandle The handle to the window
+ * @param order The order of the window.
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
+ GHOST_TWindowOrder order);
+
+/**
+ * Swaps front and back buffers of a window.
+ * @param windowhandle The handle to the window
+ * @return An intean success indicator.
+ */
+extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
+
+/**
+ * Activates the drawing context of this window.
+ * @param windowhandle The handle to the window
+ * @return An intean success indicator.
+ */
+extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle);
+
+/**
+ * Invalidates the contents of this window.
+ * @param windowhandle The handle to the window
+ * @return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
+
+/**
+ * Access to rectangle width.
+ * @param rectanglehandle The handle to the rectangle
+ * @return width of the rectangle
+ */
+extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle);
+
+/**
+ * Access to rectangle height.
+ * @param rectanglehandle The handle to the rectangle
+ * @return height of the rectangle
+ */
+extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle);
+
+/**
+ * Gets all members of the rectangle.
+ * @param rectanglehandle The handle to the rectangle
+ * @param l Pointer to return left coordinate in.
+ * @param t Pointer to return top coordinate in.
+ * @param r Pointer to return right coordinate in.
+ * @param b Pointer to return bottom coordinate in.
+ */
+extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32* l,
+ GHOST_TInt32* t,
+ GHOST_TInt32* r,
+ GHOST_TInt32* b);
+
+/**
+ * Sets all members of the rectangle.
+ * @param rectanglehandle The handle to the rectangle
+ * @param l requested left coordinate of the rectangle
+ * @param t requested top coordinate of the rectangle
+ * @param r requested right coordinate of the rectangle
+ * @param b requested bottom coordinate of the rectangle
+ */
+extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 l,
+ GHOST_TInt32 t,
+ GHOST_TInt32 r,
+ GHOST_TInt32 b);
+
+/**
+ * Returns whether this rectangle is empty.
+ * Empty rectangles are rectangles that have width==0 and/or height==0.
+ * @param rectanglehandle The handle to the rectangle
+ * @return intean value (true == empty rectangle)
+ */
+extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle);
+
+/**
+ * Returns whether this rectangle is valid.
+ * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
+ * @param rectanglehandle The handle to the rectangle
+ * @return intean value (true==valid rectangle)
+ */
+extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle);
+
+/**
+ * Grows (or shrinks the rectangle).
+ * The method avoids negative insets making the rectangle invalid
+ * @param rectanglehandle The handle to the rectangle
+ * @param i The amount of offset given to each extreme (negative values shrink the rectangle).
+ */
+extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 i);
+
+/**
+ * Does a union of the rectangle given and this rectangle.
+ * The result is stored in this rectangle.
+ * @param rectanglehandle The handle to the rectangle
+ * @param r The rectangle that is input for the union operation.
+ */
+extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle);
+
+/**
+ * Grows the rectangle to included a point.
+ * @param rectanglehandle The handle to the rectangle
+ * @param x The x-coordinate of the point.
+ * @param y The y-coordinate of the point.
+ */
+extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y);
+
+/**
+ * Returns whether the point is inside this rectangle.
+ * Point on the boundary is considered inside.
+ * @param rectanglehandle The handle to the rectangle
+ * @param x x-coordinate of point to test.
+ * @param y y-coordinate of point to test.
+ * @return intean value (true if point is inside).
+ */
+extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y);
+
+/**
+ * Returns whether the rectangle is inside this rectangle.
+ * @param rectanglehandle The handle to the rectangle
+ * @param r rectangle to test.
+ * @return visibility (not, partially or fully visible).
+ */
+extern GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle);
+
+/**
+ * Sets rectangle members.
+ * Sets rectangle members such that it is centered at the given location.
+ * @param rectanglehandle The handle to the rectangle
+ * @param cx requested center x-coordinate of the rectangle
+ * @param cy requested center y-coordinate of the rectangle
+ */
+extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 cx,
+ GHOST_TInt32 cy);
+
+/**
+ * Sets rectangle members.
+ * Sets rectangle members such that it is centered at the given location,
+ * with the width requested.
+ * @param rectanglehandle The handle to the rectangle
+ * @param cx requested center x-coordinate of the rectangle
+ * @param cy requested center y-coordinate of the rectangle
+ * @param w requested width of the rectangle
+ * @param h requested height of the rectangle
+ */
+extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 cx,
+ GHOST_TInt32 cy,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h);
+
+/**
+ * Clips a rectangle.
+ * Updates the rectangle given such that it will fit within this one.
+ * This can result in an empty rectangle.
+ * @param rectanglehandle The handle to the rectangle
+ * @param r the rectangle to clip
+ * @return whether clipping has occurred
+ */
+extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h
new file mode 100644
index 00000000000..ba901708e84
--- /dev/null
+++ b/intern/ghost/GHOST_IEvent.h
@@ -0,0 +1,88 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#ifndef _GHOST_IEVENT_H_
+#define _GHOST_IEVENT_H_
+
+#include "GHOST_Types.h"
+
+class GHOST_IWindow;
+
+/**
+ * Interface class for events received the operating system.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+class GHOST_IEvent
+{
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_IEvent()
+ {
+ }
+
+ /**
+ * Returns the event type.
+ * @return The event type.
+ */
+ virtual GHOST_TEventType getType() = 0;
+
+ /**
+ * Returns the time this event was generated.
+ * @return The event generation time.
+ */
+ virtual GHOST_TUns64 getTime() = 0;
+
+ /**
+ * Returns the window this event was generated on,
+ * or NULL if it is a 'system' event.
+ * @return The generating window.
+ */
+ virtual GHOST_IWindow* getWindow() = 0;
+
+ /**
+ * Returns the event data.
+ * @return The event data.
+ */
+ virtual GHOST_TEventDataPtr getData() = 0;
+};
+
+#endif // _GHOST_IEVENT_H_
diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h
new file mode 100644
index 00000000000..7234beff777
--- /dev/null
+++ b/intern/ghost/GHOST_IEventConsumer.h
@@ -0,0 +1,66 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 14, 2001
+ */
+
+#ifndef _GHOST_IEVENT_CONSUMER_H_
+#define _GHOST_IEVENT_CONSUMER_H_
+
+#include "GHOST_IEvent.h"
+
+/**
+ * Interface class for objects interested in receiving events.
+ */
+class GHOST_IEventConsumer
+{
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_IEventConsumer()
+ {
+ }
+
+ /**
+ * This method is called by an event producer when an event is available.
+ * @param event The event that can be handled or ignored.
+ * @return Indication as to whether the event was handled.
+ */
+ virtual bool processEvent(GHOST_IEvent* event) = 0;
+};
+
+#endif // _GHOST_EVENT_CONSUMER_H_
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
new file mode 100644
index 00000000000..3c3398408f0
--- /dev/null
+++ b/intern/ghost/GHOST_ISystem.h
@@ -0,0 +1,282 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 30, 2001
+ */
+
+#ifndef _GHOST_ISYSTEM_H_
+#define _GHOST_ISYSTEM_H_
+
+#include "GHOST_Types.h"
+#include "GHOST_ITimerTask.h"
+#include "GHOST_IWindow.h"
+
+class GHOST_IEventConsumer;
+
+/**
+ * Interface for classes that provide access to the operating system.
+ * There should be only one system class in an application.
+ * Therefore, the routines to create and dispose the system are static.
+ * Provides:
+ * 1. Time(r) management.
+ * 2. Display/window management (windows are only created on the main display for now).
+ * 3. Event management.
+ * 4. Access to the state of the mouse buttons and the keyboard.
+ * @author Maarten Gribnau
+ * @date May 30, 2001
+ */
+
+class GHOST_ISystem
+{
+public:
+ /**
+ * Creates the one and only system.
+ * @return An indication of success.
+ */
+ static GHOST_TSuccess createSystem();
+
+ /**
+ * Disposes the one and only system.
+ * @return An indication of success.
+ */
+ static GHOST_TSuccess disposeSystem();
+
+ /**
+ * Returns a pointer to the one and only system (nil if it hasn't been created).
+ * @return A pointer to the system.
+ */
+ static GHOST_ISystem* getSystem();
+
+protected:
+ /**
+ * Constructor.
+ * Protected default constructor to force use of static createSystem member.
+ */
+ GHOST_ISystem() {}
+
+ /**
+ * Destructor.
+ * Protected default constructor to force use of static dispose member.
+ */
+ virtual ~GHOST_ISystem() {}
+
+public:
+ /***************************************************************************************
+ ** Time(r) functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * Based on ANSI clock() routine.
+ * @return The number of milliseconds.
+ */
+ virtual GHOST_TUns64 getMilliSeconds() const = 0;
+
+ /**
+ * Installs a timer.
+ * Note that, on most operating systems, messages need to be processed in order
+ * for the timer callbacks to be invoked.
+ * @param delay The time to wait for the first call to the timerProc (in milliseconds)
+ * @param interval The interval between calls to the timerProc (in milliseconds)
+ * @param timerProc The callback invoked when the interval expires,
+ * @param userData Placeholder for user data.
+ * @return A timer task (0 if timer task installation failed).
+ */
+ virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0) = 0;
+
+ /**
+ * Removes a timer.
+ * @param timerTask Timer task to be removed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask) = 0;
+
+ /***************************************************************************************
+ ** Display/window management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the number of displays on this system.
+ * @return The number of displays.
+ */
+ virtual GHOST_TUns8 getNumDisplays() const = 0;
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0;
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Create a stereo visual for quad buffered stereo.
+ * @return The new window (or 0 if creation failed).
+ */
+ virtual GHOST_IWindow* createWindow(
+ 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) = 0;
+
+ /**
+ * Dispose a window.
+ * @param window Pointer to the window to be disposed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window) = 0;
+
+ /**
+ * Returns whether a window is valid.
+ * @param window Pointer to the window to be checked.
+ * @return Indication of validity.
+ */
+ virtual bool validWindow(GHOST_IWindow* window) = 0;
+
+ /**
+ * Begins full screen mode.
+ * @param setting The new setting of the display.
+ * @param window Window displayed in full screen.
+ * This window is invalid after full screen has been ended.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
+ const bool stereoVisual) = 0;
+
+ /**
+ * Ends full screen mode.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess endFullScreen(void) = 0;
+
+ /**
+ * Returns current full screen mode status.
+ * @return The current status.
+ */
+ virtual bool getFullScreen(void) = 0;
+
+ /***************************************************************************************
+ ** Event management functionality
+ ***************************************************************************************/
+
+ /**
+ * Retrieves events from the system and stores them in the queue.
+ * @param waitForEvent Flag to wait for an event (or return immediately).
+ * @return Indication of the presence of events.
+ */
+ virtual bool processEvents(bool waitForEvent) = 0;
+
+ /**
+ * Retrieves events from the queue and send them to the event consumers.
+ * @return Indication of the presence of events.
+ */
+ virtual bool dispatchEvents() = 0;
+
+ /**
+ * Adds the given event consumer to our list.
+ * @param consumer The event consumer to add.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer) = 0;
+
+ /***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the current location of the cursor (location in screen coordinates)
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0;
+
+ /**
+ * Updates the location of the cursor (location in screen coordinates).
+ * Not all operating systems allow the cursor to be moved (without the input device being moved).
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const = 0;
+
+ /***************************************************************************************
+ ** Access to mouse button and keyboard states.
+ ***************************************************************************************/
+
+ /**
+ * Returns the state of a modifier key (ouside the message queue).
+ * @param mask The modifier key state to retrieve.
+ * @param isDown The state of a modifier key (true == pressed).
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0;
+
+ /**
+ * Returns the state of a mouse button (ouside the message queue).
+ * @param mask The button state to retrieve.
+ * @param isDown Button state.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0;
+
+protected:
+ /**
+ * Initialize the system.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess init() = 0;
+
+ /**
+ * Shut the system down.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess exit() = 0;
+
+ /** The one and only system */
+ static GHOST_ISystem* m_system;
+};
+
+#endif // _GHOST_ISYSTEM_H_
diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h
new file mode 100644
index 00000000000..354652017d9
--- /dev/null
+++ b/intern/ghost/GHOST_ITimerTask.h
@@ -0,0 +1,88 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#ifndef _GHOST_ITIMER_TASK_H_
+#define _GHOST_ITIMER_TASK_H_
+
+
+#include "GHOST_Types.h"
+
+
+/**
+ * Interface for a timer task.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+class GHOST_ITimerTask
+{
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_ITimerTask()
+ {
+ }
+
+ /**
+ * Returns the timer callback.
+ * @return The timer callback.
+ */
+ inline virtual GHOST_TimerProcPtr getTimerProc() const = 0;
+
+ /**
+ * Changes the timer callback.
+ * @param timerProc The timer callback.
+ */
+ inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0;
+
+ /**
+ * Returns the timer user data.
+ * @return The timer user data.
+ */
+ inline virtual GHOST_TUserDataPtr getUserData() const = 0;
+
+ /**
+ * Changes the time user data.
+ * @param data The timer user data.
+ */
+ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
+};
+
+
+#endif // _GHOST_ITIMER_TASK_H_
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
new file mode 100644
index 00000000000..8f41345ec5f
--- /dev/null
+++ b/intern/ghost/GHOST_IWindow.h
@@ -0,0 +1,241 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#ifndef _GHOST_IWINDOW_H_
+#define _GHOST_IWINDOW_H_
+
+#include "STR_String.h"
+#include "GHOST_Rect.h"
+#include "GHOST_Types.h"
+
+
+/**
+ * Interface for GHOST windows.
+ * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+class GHOST_IWindow
+{
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_IWindow()
+ {
+ }
+
+ /**
+ * Returns indication as to whether the window is valid.
+ * @return The validity of the window.
+ */
+ virtual bool getValid() const = 0;
+
+ /**
+ * Returns the type of drawing context used in this window.
+ * @return The current type of drawing context.
+ */
+ inline virtual GHOST_TDrawingContextType getDrawingContextType() = 0;
+
+ /**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0;
+
+ /**
+ * Sets the title displayed in the title bar.
+ * @param title The title to display in the title bar.
+ */
+ virtual void setTitle(const STR_String& title) = 0;
+
+ /**
+ * Returns the title displayed in the title bar.
+ * @param title The title displayed in the title bar.
+ */
+ virtual void getTitle(STR_String& title) const = 0;
+
+ /**
+ * Returns the window rectangle dimensions.
+ * These are screen coordinates.
+ * @param bounds The bounding rectangle of the window.
+ */
+ virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
+
+ /**
+ * Returns the client rectangle dimensions.
+ * The left and top members of the rectangle are always zero.
+ * @param bounds The bounding rectangle of the client area of the window.
+ */
+ virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
+
+ /**
+ * Resizes client rectangle width.
+ * @param width The new width of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
+
+ /**
+ * Resizes client rectangle height.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
+
+ /**
+ * Resizes client rectangle.
+ * @param width The new width of the client area of the window.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate on the screen.
+ * @param inY The y-coordinate on the screen.
+ * @param outX The x-coordinate in the client rectangle.
+ * @param outY The y-coordinate in the client rectangle.
+ */
+ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate in the client rectangle.
+ * @param inY The y-coordinate in the client rectangle.
+ * @param outX The x-coordinate on the screen.
+ * @param outY The y-coordinate on the screen.
+ */
+ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+
+ /**
+ * Returns the state of the window (normal, minimized, maximized).
+ * @return The state of the window.
+ */
+ virtual GHOST_TWindowState getState() const = 0;
+
+ /**
+ * Sets the state of the window (normal, minimized, maximized).
+ * @param state The state of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
+
+ /**
+ * Sets the order of the window (bottom, top).
+ * @param order The order of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
+
+ /**
+ * Swaps front and back buffers of a window.
+ * @return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers() = 0;
+
+ /**
+ * Activates the drawing context of this window.
+ * @return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext() = 0;
+
+ /**
+ * Invalidates the contents of this window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess invalidate() = 0;
+
+ /**
+ * Returns the window user data.
+ * @return The window user data.
+ */
+ inline virtual GHOST_TUserDataPtr getUserData() const = 0;
+
+ /**
+ * Changes the window user data.
+ * @param data The window user data.
+ */
+ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
+
+ /***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the current cursor shape.
+ * @return The current cursor shape.
+ */
+ virtual GHOST_TStandardCursor getCursorShape() const = 0;
+
+ /**
+ * Set the shape of the cursor.
+ * @param cursor The new cursor shape type id.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
+
+ /**
+ * Set the shape of the cursor to a custom cursor.
+ * @param bitmap The bitmap data for the cursor.
+ * @param mask The mask data for the cursor.
+ * @param hotX The X coordinate of the cursor hotspot.
+ * @param hotY The Y coordinate of the cursor hotspot.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY) = 0;
+
+ /**
+ * Returns the visibility state of the cursor.
+ * @return The visibility state of the cursor.
+ */
+ virtual bool getCursorVisibility() const = 0;
+
+ /**
+ * Shows or hides the cursor.
+ * @param visible The new visibility state of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0;
+};
+
+#endif // _GHOST_IWINDOW_H_
diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h
new file mode 100644
index 00000000000..c8cfc79ea9d
--- /dev/null
+++ b/intern/ghost/GHOST_Rect.h
@@ -0,0 +1,237 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _H_GHOST_Rect
+#define _H_GHOST_Rect
+
+#include "GHOST_Types.h"
+
+
+/**
+ * Implements rectangle functionality.
+ * The four extreme coordinates are stored as left, top, right and bottom.
+ * To be valid, a rectangle should have a left coordinate smaller than or equal to right.
+ * To be valid, a rectangle should have a top coordinate smaller than or equal to bottom.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+class GHOST_Rect {
+public:
+
+ /**
+ * Constructs a rectangle with the given values.
+ * @param l requested left coordinate of the rectangle
+ * @param t requested top coordinate of the rectangle
+ * @param r requested right coordinate of the rectangle
+ * @param b requested bottom coordinate of the rectangle
+ */
+ GHOST_Rect(GHOST_TInt32 l=0, GHOST_TInt32 t=0, GHOST_TInt32 r=0, GHOST_TInt32 b=0)
+ : m_l(l), m_t(t), m_r(r), m_b(b) {}
+
+ /**
+ * Copy constructor.
+ * @param r rectangle to copy
+ */
+ GHOST_Rect(const GHOST_Rect& r)
+ : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {}
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_Rect() {};
+
+ /**
+ * Access to rectangle width.
+ * @return width of the rectangle
+ */
+ virtual inline GHOST_TInt32 getWidth() const;
+
+ /**
+ * Access to rectangle height.
+ * @return height of the rectangle
+ */
+ virtual inline GHOST_TInt32 getHeight() const;
+
+ /**
+ * Sets all members of the rectangle.
+ * @param l requested left coordinate of the rectangle
+ * @param t requested top coordinate of the rectangle
+ * @param r requested right coordinate of the rectangle
+ * @param b requested bottom coordinate of the rectangle
+ */
+ virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b);
+
+ /**
+ * Returns whether this rectangle is empty.
+ * Empty rectangles are rectangles that have width==0 and/or height==0.
+ * @return boolean value (true==empty rectangle)
+ */
+ virtual inline bool isEmpty() const;
+
+ /**
+ * Returns whether this rectangle is valid.
+ * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
+ * @return boolean value (true==valid rectangle)
+ */
+ virtual inline bool isValid() const;
+
+ /**
+ * Grows (or shrinks the rectangle).
+ * The method avoids negative insets making the rectangle invalid
+ * @param i The amount of offset given to each extreme (negative values shrink the rectangle).
+ */
+ virtual void inset(GHOST_TInt32 i);
+
+ /**
+ * Does a union of the rectangle given and this rectangle.
+ * The result is stored in this rectangle.
+ * @param r The rectangle that is input for the union operation.
+ */
+ virtual inline void unionRect(const GHOST_Rect& r);
+
+ /**
+ * Grows the rectangle to included a point.
+ * @param x The x-coordinate of the point.
+ * @param y The y-coordinate of the point.
+ */
+ virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y);
+
+ /**
+ * Returns whether the point is inside this rectangle.
+ * Point on the boundary is considered inside.
+ * @param x x-coordinate of point to test.
+ * @param y y-coordinate of point to test.
+ * @return boolean value (true if point is inside).
+ */
+ virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const;
+
+ /**
+ * Returns whether the rectangle is inside this rectangle.
+ * @param r rectangle to test.
+ * @return visibility (not, partially or fully visible).
+ */
+ virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const;
+
+ /**
+ * Sets rectangle members.
+ * Sets rectangle members such that it is centered at the given location.
+ * @param cx requested center x-coordinate of the rectangle
+ * @param cy requested center y-coordinate of the rectangle
+ */
+ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy);
+
+ /**
+ * Sets rectangle members.
+ * Sets rectangle members such that it is centered at the given location,
+ * with the width requested.
+ * @param cx requested center x-coordinate of the rectangle
+ * @param cy requested center y-coordinate of the rectangle
+ * @param w requested width of the rectangle
+ * @param h requested height of the rectangle
+ */
+ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h);
+
+ /**
+ * Clips a rectangle.
+ * Updates the rectangle given such that it will fit within this one.
+ * This can result in an empty rectangle.
+ * @param r the rectangle to clip
+ * @return whether clipping has occurred
+ */
+ virtual bool clip(GHOST_Rect& r) const;
+
+ /** Left coordinate of the rectangle */
+ GHOST_TInt32 m_l;
+ /** Top coordinate of the rectangle */
+ GHOST_TInt32 m_t;
+ /** Right coordinate of the rectangle */
+ GHOST_TInt32 m_r;
+ /** Bottom coordinate of the rectangle */
+ GHOST_TInt32 m_b;
+};
+
+
+inline GHOST_TInt32 GHOST_Rect::getWidth() const
+{
+ return m_r - m_l;
+}
+
+inline GHOST_TInt32 GHOST_Rect::getHeight() const
+{
+ return m_b - m_t;
+}
+
+inline void GHOST_Rect::set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b)
+{
+ m_l = l; m_t = t; m_r = r; m_b = b;
+}
+
+inline bool GHOST_Rect::isEmpty() const
+{
+ return (getWidth() == 0) || (getHeight() == 0);
+}
+
+inline bool GHOST_Rect::isValid() const
+{
+ return (m_l <= m_r) && (m_t <= m_b);
+}
+
+inline void GHOST_Rect::unionRect(const GHOST_Rect& r)
+{
+ if (r.m_l < m_l) m_l = r.m_l;
+ if (r.m_r > m_r) m_r = r.m_r;
+ if (r.m_t < m_t) m_t = r.m_t;
+ if (r.m_b > m_b) m_b = r.m_b;
+}
+
+inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y)
+{
+ if (x < m_l) m_l = x;
+ if (x > m_r) m_r = x;
+ if (y < m_t) m_t = y;
+ if (y > m_b) m_b = y;
+}
+
+inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const
+{
+ return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b);
+}
+
+#endif // _H_GHOST_Rect
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
new file mode 100644
index 00000000000..c7b8f3b19e0
--- /dev/null
+++ b/intern/ghost/GHOST_Types.h
@@ -0,0 +1,354 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#ifndef _GHOST_TYPES_H_
+#define _GHOST_TYPES_H_
+
+typedef char GHOST_TInt8;
+typedef unsigned char GHOST_TUns8;
+typedef short GHOST_TInt16;
+typedef unsigned short GHOST_TUns16;
+typedef int GHOST_TInt32;
+typedef unsigned int GHOST_TUns32;
+
+#ifdef WIN32
+typedef __int64 GHOST_TInt64;
+typedef unsigned __int64 GHOST_TUns64;
+#else
+typedef long long GHOST_TInt64;
+typedef unsigned long long GHOST_TUns64;
+#endif
+
+typedef void* GHOST_TUserDataPtr;
+
+typedef enum
+{
+ GHOST_kFailure = 0,
+ GHOST_kSuccess
+} GHOST_TSuccess;
+
+
+typedef enum {
+ GHOST_kNotVisible = 0,
+ GHOST_kPartiallyVisible,
+ GHOST_kFullyVisible
+} GHOST_TVisibility;
+
+
+typedef enum {
+ GHOST_kFireTimeNever = 0xFFFFFFFF
+} GHOST_TFireTimeConstant;
+
+typedef enum {
+ GHOST_kModifierKeyLeftShift = 0,
+ GHOST_kModifierKeyRightShift,
+ GHOST_kModifierKeyLeftAlt,
+ GHOST_kModifierKeyRightAlt,
+ GHOST_kModifierKeyLeftControl,
+ GHOST_kModifierKeyRightControl,
+ GHOST_kModifierKeyCommand, // APPLE only
+ GHOST_kModifierKeyNumMasks
+} GHOST_TModifierKeyMask;
+
+
+typedef enum {
+ GHOST_kWindowStateNormal = 0,
+ GHOST_kWindowStateMaximized,
+ GHOST_kWindowStateMinimized,
+ GHOST_kWindowStateFullScreen
+} GHOST_TWindowState;
+
+
+typedef enum {
+ GHOST_kWindowOrderTop = 0,
+ GHOST_kWindowOrderBottom
+} GHOST_TWindowOrder;
+
+
+typedef enum {
+ GHOST_kDrawingContextTypeNone = 0,
+ GHOST_kDrawingContextTypeOpenGL
+} GHOST_TDrawingContextType;
+
+
+typedef enum {
+ GHOST_kButtonMaskLeft = 0,
+ GHOST_kButtonMaskMiddle,
+ GHOST_kButtonMaskRight,
+ GHOST_kButtonNumMasks
+} GHOST_TButtonMask;
+
+
+typedef enum {
+ GHOST_kEventUnknown = 0,
+
+ GHOST_kEventCursorMove,
+ GHOST_kEventButtonDown,
+ GHOST_kEventButtonUp,
+
+ GHOST_kEventKeyDown,
+ GHOST_kEventKeyUp,
+// GHOST_kEventKeyAuto,
+
+ GHOST_kEventQuit,
+
+ GHOST_kEventWindowClose,
+ GHOST_kEventWindowActivate,
+ GHOST_kEventWindowDeactivate,
+ GHOST_kEventWindowUpdate,
+ GHOST_kEventWindowSize,
+
+ GHOST_kNumEventTypes
+} GHOST_TEventType;
+
+
+typedef enum {
+ GHOST_kStandardCursorFirstCursor = 0,
+ GHOST_kStandardCursorDefault = 0,
+ GHOST_kStandardCursorRightArrow,
+ GHOST_kStandardCursorLeftArrow,
+ GHOST_kStandardCursorInfo,
+ GHOST_kStandardCursorDestroy,
+ GHOST_kStandardCursorHelp,
+ GHOST_kStandardCursorCycle,
+ GHOST_kStandardCursorSpray,
+ GHOST_kStandardCursorWait,
+ GHOST_kStandardCursorText,
+ GHOST_kStandardCursorCrosshair,
+ GHOST_kStandardCursorUpDown,
+ GHOST_kStandardCursorLeftRight,
+ GHOST_kStandardCursorTopSide,
+ GHOST_kStandardCursorBottomSide,
+ GHOST_kStandardCursorLeftSide,
+ GHOST_kStandardCursorRightSide,
+ GHOST_kStandardCursorTopLeftCorner,
+ GHOST_kStandardCursorTopRightCorner,
+ GHOST_kStandardCursorBottomRightCorner,
+ GHOST_kStandardCursorBottomLeftCorner,
+ GHOST_kStandardCursorCustom,
+ GHOST_kStandardCursorNumCursors
+} GHOST_TStandardCursor;
+
+
+typedef enum {
+ GHOST_kKeyUnknown = -1,
+ GHOST_kKeyBackSpace,
+ GHOST_kKeyTab,
+ GHOST_kKeyLinefeed,
+ GHOST_kKeyClear,
+ GHOST_kKeyEnter = 0x0D,
+
+ GHOST_kKeyEsc = 0x1B,
+ GHOST_kKeySpace = ' ',
+ GHOST_kKeyQuote = 0x27,
+ GHOST_kKeyComma = ',',
+ GHOST_kKeyMinus = '-',
+ GHOST_kKeyPeriod = '.',
+ GHOST_kKeySlash = '/',
+
+ // Number keys
+ GHOST_kKey0 = '0',
+ GHOST_kKey1,
+ GHOST_kKey2,
+ GHOST_kKey3,
+ GHOST_kKey4,
+ GHOST_kKey5,
+ GHOST_kKey6,
+ GHOST_kKey7,
+ GHOST_kKey8,
+ GHOST_kKey9,
+
+ GHOST_kKeySemicolon = ';',
+ GHOST_kKeyEqual = '=',
+
+ // Character keys
+ GHOST_kKeyA = 'A',
+ GHOST_kKeyB,
+ GHOST_kKeyC,
+ GHOST_kKeyD,
+ GHOST_kKeyE,
+ GHOST_kKeyF,
+ GHOST_kKeyG,
+ GHOST_kKeyH,
+ GHOST_kKeyI,
+ GHOST_kKeyJ,
+ GHOST_kKeyK,
+ GHOST_kKeyL,
+ GHOST_kKeyM,
+ GHOST_kKeyN,
+ GHOST_kKeyO,
+ GHOST_kKeyP,
+ GHOST_kKeyQ,
+ GHOST_kKeyR,
+ GHOST_kKeyS,
+ GHOST_kKeyT,
+ GHOST_kKeyU,
+ GHOST_kKeyV,
+ GHOST_kKeyW,
+ GHOST_kKeyX,
+ GHOST_kKeyY,
+ GHOST_kKeyZ,
+
+ GHOST_kKeyLeftBracket = '[',
+ GHOST_kKeyRightBracket = ']',
+ GHOST_kKeyBackslash = 0x5C,
+ GHOST_kKeyAccentGrave = '`',
+
+
+ GHOST_kKeyLeftShift = 0x100,
+ GHOST_kKeyRightShift,
+ GHOST_kKeyLeftControl,
+ GHOST_kKeyRightControl,
+ GHOST_kKeyLeftAlt,
+ GHOST_kKeyRightAlt,
+ GHOST_kKeyCommand, // APPLE only!
+
+ GHOST_kKeyCapsLock,
+ GHOST_kKeyNumLock,
+ GHOST_kKeyScrollLock,
+
+ GHOST_kKeyLeftArrow,
+ GHOST_kKeyRightArrow,
+ GHOST_kKeyUpArrow,
+ GHOST_kKeyDownArrow,
+
+ GHOST_kKeyPrintScreen,
+ GHOST_kKeyPause,
+
+ GHOST_kKeyInsert,
+ GHOST_kKeyDelete,
+ GHOST_kKeyHome,
+ GHOST_kKeyEnd,
+ GHOST_kKeyUpPage,
+ GHOST_kKeyDownPage,
+
+ // Numpad keys
+ GHOST_kKeyNumpad0,
+ GHOST_kKeyNumpad1,
+ GHOST_kKeyNumpad2,
+ GHOST_kKeyNumpad3,
+ GHOST_kKeyNumpad4,
+ GHOST_kKeyNumpad5,
+ GHOST_kKeyNumpad6,
+ GHOST_kKeyNumpad7,
+ GHOST_kKeyNumpad8,
+ GHOST_kKeyNumpad9,
+ GHOST_kKeyNumpadPeriod,
+ GHOST_kKeyNumpadEnter,
+ GHOST_kKeyNumpadPlus,
+ GHOST_kKeyNumpadMinus,
+ GHOST_kKeyNumpadAsterisk,
+ GHOST_kKeyNumpadSlash,
+
+ // Function keys
+ GHOST_kKeyF1,
+ GHOST_kKeyF2,
+ GHOST_kKeyF3,
+ GHOST_kKeyF4,
+ GHOST_kKeyF5,
+ GHOST_kKeyF6,
+ GHOST_kKeyF7,
+ GHOST_kKeyF8,
+ GHOST_kKeyF9,
+ GHOST_kKeyF10,
+ GHOST_kKeyF11,
+ GHOST_kKeyF12,
+ GHOST_kKeyF13,
+ GHOST_kKeyF14,
+ GHOST_kKeyF15,
+ GHOST_kKeyF16,
+ GHOST_kKeyF17,
+ GHOST_kKeyF18,
+ GHOST_kKeyF19,
+ GHOST_kKeyF20,
+ GHOST_kKeyF21,
+ GHOST_kKeyF22,
+ GHOST_kKeyF23,
+ GHOST_kKeyF24
+} GHOST_TKey;
+
+
+typedef void* GHOST_TEventDataPtr;
+
+typedef struct {
+ /** The x-coordinate of the cursor position. */
+ GHOST_TInt32 x;
+ /** The y-coordinate of the cursor position. */
+ GHOST_TInt32 y;
+} GHOST_TEventCursorData;
+
+typedef struct {
+ /** The mask of the mouse button. */
+ GHOST_TButtonMask button;
+} GHOST_TEventButtonData;
+
+typedef struct {
+ /** The key code. */
+ GHOST_TKey key;
+ /** The ascii code for the key event ('\0' if none). */
+ char ascii;
+} GHOST_TEventKeyData;
+
+typedef struct {
+ /** Number of pixels on a line. */
+ GHOST_TUns32 xPixels;
+ /** Number of lines. */
+ GHOST_TUns32 yPixels;
+ /** Numberof bits per pixel. */
+ GHOST_TUns32 bpp;
+ /** Refresh rate (in Hertz). */
+ GHOST_TUns32 frequency;
+} GHOST_DisplaySetting;
+
+
+/**
+ * A timer task callback routine.
+ * @param task The timer task object.
+ * @param time The current time.
+ */
+#ifdef __cplusplus
+class GHOST_ITimerTask;
+typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time);
+#else
+struct GHOST_TimerTaskHandle__;
+typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time);
+#endif
+
+
+#endif // _GHOST_TYPES_H_
diff --git a/intern/ghost/Makefile b/intern/ghost/Makefile
new file mode 100644
index 00000000000..5c78bea192c
--- /dev/null
+++ b/intern/ghost/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# ghost main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = ghost
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_GHOST) ] || mkdir $(NAN_GHOST)
+ @[ -d $(NAN_GHOST)/include ] || mkdir $(NAN_GHOST)/include
+ @[ -d $(NAN_GHOST)/lib ] || mkdir $(NAN_GHOST)/lib
+ @[ -d $(NAN_GHOST)/lib/debug ] || mkdir $(NAN_GHOST)/lib/debug
+ cp -f $(DIR)/libghost.a $(NAN_GHOST)/lib/
+ cp -f $(DIR)/debug/libghost.a $(NAN_GHOST)/lib/debug/
+ cp -f *.h $(NAN_GHOST)/include/
+
diff --git a/intern/ghost/doc/Doxyfile.win b/intern/ghost/doc/Doxyfile.win
new file mode 100644
index 00000000000..463da56cc94
--- /dev/null
+++ b/intern/ghost/doc/Doxyfile.win
@@ -0,0 +1,747 @@
+# Doxyfile 1.2.4
+
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "GHOST (Generic Handy Operating System Toolkit)"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 1.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
+# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
+# Polish, Portuguese and Slovene.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+# MAART: changed
+EXTRACT_STATIC = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a class diagram (in Html and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off.
+
+CLASS_DIAGRAMS = YES
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+#MAART: changed
+JAVADOC_AUTOBRIEF = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The ENABLE_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .
+#C:\Documents and Settings\maarten\My Documents\develop\blender\source\blender\img
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Netscape 4.0+
+# or Internet explorer 4.0+).
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+#MAART: changed
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+#MAART: changed
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using a WORD or other.
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+#MAART: changed
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Warning: This feature
+# is still experimental and very incomplete.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other
+# documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented header file showing
+# the documented files that directly or indirectly include this file
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = c:\program files\doxygen\bin
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp
new file mode 100644
index 00000000000..6e0c46e17a0
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Buttons.cpp
@@ -0,0 +1,82 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#include "GHOST_Buttons.h"
+
+
+GHOST_Buttons::GHOST_Buttons()
+{
+ clear();
+}
+
+
+bool GHOST_Buttons::get(GHOST_TButtonMask mask) const
+{
+ switch (mask) {
+ case GHOST_kButtonMaskLeft:
+ return m_ButtonLeft;
+ case GHOST_kButtonMaskMiddle:
+ return m_ButtonMiddle;
+ case GHOST_kButtonMaskRight:
+ return m_ButtonRight;
+ default:
+ return false;
+ }
+}
+
+void GHOST_Buttons::set(GHOST_TButtonMask mask, bool down)
+{
+ switch (mask) {
+ case GHOST_kButtonMaskLeft:
+ m_ButtonLeft = down; break;
+ case GHOST_kButtonMaskMiddle:
+ m_ButtonMiddle = down; break;
+ case GHOST_kButtonMaskRight:
+ m_ButtonRight = down; break;
+ default:
+ break;
+ }
+}
+
+void GHOST_Buttons::clear()
+{
+ m_ButtonLeft = false;
+ m_ButtonMiddle = false;
+ m_ButtonRight = false;
+}
diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h
new file mode 100644
index 00000000000..fdde52f3e8e
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Buttons.h
@@ -0,0 +1,76 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 15, 2001
+ */
+
+#ifndef _GHOST_BUTTONS_H_
+#define _GHOST_BUTTONS_H_
+
+#include "GHOST_Types.h"
+
+
+struct GHOST_Buttons {
+ /**
+ * Constructor.
+ */
+ GHOST_Buttons();
+
+ /**
+ * Returns the state of a single button.
+ * @param mask. Key button to return.
+ * @return The state of the button (pressed == true).
+ */
+ virtual bool get(GHOST_TButtonMask mask) const;
+
+ /**
+ * Updates the state of a single button.
+ * @param mask. Button state to update.
+ * @param down. The new state of the button.
+ */
+ virtual void set(GHOST_TButtonMask mask, bool down);
+
+ /**
+ * Sets the state of all buttons to up.
+ */
+ virtual void clear();
+
+ GHOST_TUns8 m_ButtonLeft : 1;
+ GHOST_TUns8 m_ButtonMiddle : 1;
+ GHOST_TUns8 m_ButtonRight : 1;
+};
+
+#endif // _GHOST_BUTTONS_H_
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
new file mode 100644
index 00000000000..3ab3ce67fe8
--- /dev/null
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -0,0 +1,778 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * GHOST_C-Api.cpp
+ *
+ * C Api for GHOST
+ *
+ * Version: $Id$
+ */
+
+#include <stdlib.h>
+
+#include "intern/GHOST_Debug.h"
+#include "GHOST_C-api.h"
+#include "GHOST_ISystem.h"
+#include "GHOST_IEvent.h"
+#include "GHOST_IEventConsumer.h"
+#include "intern/GHOST_CallbackEventConsumer.h"
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+
+GHOST_SystemHandle GHOST_CreateSystem(void)
+{
+ GHOST_ISystem::createSystem();
+ GHOST_ISystem* system = GHOST_ISystem::getSystem();
+
+ return (GHOST_SystemHandle)system;
+}
+
+
+
+GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->disposeSystem();
+}
+
+
+GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata)
+{
+ return (GHOST_EventConsumerHandle) new GHOST_CallbackEventConsumer (eventCallback, userdata);
+}
+
+
+GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle)
+{
+ delete ((GHOST_CallbackEventConsumer*)consumerhandle);
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->getMilliSeconds();
+}
+
+
+
+GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
+ GHOST_TUns64 delay,
+ GHOST_TUns64 interval,
+ GHOST_TimerProcPtr timerproc,
+ GHOST_TUserDataPtr userdata)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return (GHOST_TimerTaskHandle) system->installTimer(delay, interval, timerproc, userdata);
+}
+
+
+
+GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
+ GHOST_TimerTaskHandle timertaskhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
+
+ return system->removeTimer(timertask);
+}
+
+
+
+GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->getNumDisplays();
+}
+
+
+
+void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
+ GHOST_TUns32* width,
+ GHOST_TUns32* height)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ system->getMainDisplayDimensions(*width, *height);
+}
+
+
+
+GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
+ char* title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ const int stereoVisual)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ bool bstereoVisual;
+
+ if(stereoVisual)
+ bstereoVisual = true;
+ else
+ bstereoVisual = false;
+
+ return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height,
+ state, type, bstereoVisual);
+}
+
+GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->getUserData();
+}
+void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ window->setUserData(userdata);
+}
+
+GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle windowhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return system->disposeWindow(window);
+}
+
+
+
+int GHOST_ValidWindow(GHOST_SystemHandle systemhandle,
+ GHOST_WindowHandle windowhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return (int) system->validWindow(window);
+}
+
+
+
+GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
+ GHOST_DisplaySetting* setting,
+ const int stereoVisual)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_IWindow* window = NULL;
+ bool bstereoVisual;
+
+ if(stereoVisual)
+ bstereoVisual = true;
+ else
+ bstereoVisual = false;
+
+ system->beginFullScreen(*setting, &window, bstereoVisual);
+
+ return (GHOST_WindowHandle)window;
+}
+
+
+
+GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->endFullScreen();
+}
+
+
+
+int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return (int) system->getFullScreen();
+}
+
+
+
+int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return (int) system->processEvents(waitForEvent?true:false);
+}
+
+
+
+int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return (int) system->dispatchEvents();
+}
+
+
+GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, GHOST_EventConsumerHandle consumerhandle)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->addEventConsumer((GHOST_CallbackEventConsumer*)consumerhandle);
+}
+
+
+
+GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->getCursorShape();
+}
+
+
+
+GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle,
+ GHOST_TStandardCursor cursorshape)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setCursorShape(cursorshape);
+}
+
+GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
+ GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setCustomCursorShape(bitmap, mask, hotX, hotY);
+}
+
+int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return (int) window->getCursorVisibility();
+}
+
+
+
+GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle,
+ int visible)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setCursorVisibility(visible?true:false);
+}
+
+
+
+GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
+ GHOST_TInt32* x,
+ GHOST_TInt32* y)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->getCursorPosition(*x, *y);
+}
+
+
+
+GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+
+ return system->setCursorPosition(x, y);
+}
+
+
+
+GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
+ GHOST_TModifierKeyMask mask,
+ int* isDown)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_TSuccess result;
+ bool isdown;
+
+ result = system->getModifierKeyState(mask, isdown);
+ *isDown = (int) isdown;
+
+ return result;
+}
+
+
+
+GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
+ GHOST_TButtonMask mask,
+ int* isDown)
+{
+ GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
+ GHOST_TSuccess result;
+ bool isdown;
+
+ result = system->getButtonState(mask, isdown);
+ *isDown = (int) isdown;
+
+ return result;
+}
+
+
+
+GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle)
+{
+ GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
+
+ return event->getType();
+}
+
+
+
+GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle)
+{
+ GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
+
+ return event->getTime();
+}
+
+
+GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle)
+{
+ GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
+
+ return (GHOST_WindowHandle) event->getWindow();
+}
+
+
+GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle)
+{
+ GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
+
+ return event->getData();
+}
+
+
+
+GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle)
+{
+ GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
+
+ return timertask->getTimerProc();
+}
+
+
+
+void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
+ GHOST_TimerProcPtr timerproc)
+{
+ GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
+
+ timertask->setTimerProc(timerproc);
+}
+
+
+
+GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle)
+{
+ GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
+
+ return timertask->getUserData();
+}
+
+
+
+void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
+ GHOST_TUserDataPtr userdata)
+{
+ GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
+
+ timertask->setUserData(userdata);
+}
+
+
+
+int GHOST_GetValid(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return (int) window->getValid();
+}
+
+
+
+GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->getDrawingContextType();
+}
+
+
+
+GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
+ GHOST_TDrawingContextType type)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setDrawingContextType(type);
+}
+
+
+
+void GHOST_SetTitle(GHOST_WindowHandle windowhandle,
+ char* title)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ window->setTitle(title);
+}
+
+
+char* GHOST_GetTitle(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+ STR_String title;
+
+ window->getTitle(title);
+
+ char *ctitle = (char*) malloc(title.Length() + 1);
+ strcpy(ctitle, title.Ptr());
+
+ return ctitle;
+}
+
+
+
+GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+ GHOST_Rect* rectangle = NULL;
+
+ rectangle = new GHOST_Rect();
+ window->getWindowBounds(*rectangle);
+
+ return (GHOST_RectangleHandle)rectangle;
+}
+
+
+
+GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+ GHOST_Rect* rectangle = NULL;
+
+ rectangle = new GHOST_Rect();
+ window->getClientBounds(*rectangle);
+
+ return (GHOST_RectangleHandle)rectangle;
+}
+
+
+
+void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
+{
+ delete (GHOST_Rect*) rectanglehandle;
+}
+
+
+
+GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 width)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setClientWidth(width);
+}
+
+
+
+GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 height)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setClientHeight(height);
+}
+
+
+
+GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setClientSize(width, height);
+}
+
+
+
+void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32* outX,
+ GHOST_TInt32* outY)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ window->screenToClient(inX, inY, *outX, *outY);
+}
+
+
+
+void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32* outX,
+ GHOST_TInt32* outY)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ window->clientToScreen(inX, inY, *outX, *outY);
+}
+
+
+
+GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->getState();
+}
+
+
+
+GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
+ GHOST_TWindowState state)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setState(state);
+}
+
+
+
+GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
+ GHOST_TWindowOrder order)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->setOrder(order);
+}
+
+
+
+GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->swapBuffers();
+}
+
+
+
+GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->activateDrawingContext();
+}
+
+
+
+GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+ return window->invalidate();
+}
+
+
+
+GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
+{
+ return ((GHOST_Rect*)rectanglehandle)->getWidth();
+}
+
+
+
+GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
+{
+ return ((GHOST_Rect*)rectanglehandle)->getHeight();
+}
+
+
+
+void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32* l,
+ GHOST_TInt32* t,
+ GHOST_TInt32* r,
+ GHOST_TInt32* b)
+{
+ GHOST_Rect *rect= (GHOST_Rect*) rectanglehandle;
+
+ *l= rect->m_l;
+ *t= rect->m_t;
+ *r= rect->m_r;
+ *b= rect->m_b;
+}
+
+
+void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 l,
+ GHOST_TInt32 t,
+ GHOST_TInt32 r,
+ GHOST_TInt32 b)
+{
+ ((GHOST_Rect*)rectanglehandle)->set(l, t, r, b);
+}
+
+
+
+GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle)
+{
+ GHOST_TSuccess result = GHOST_kFailure;
+
+ if (((GHOST_Rect*)rectanglehandle)->isEmpty())
+ result = GHOST_kSuccess;
+
+ return result;
+}
+
+
+
+GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle)
+{
+ GHOST_TSuccess result = GHOST_kFailure;
+
+ if(((GHOST_Rect*)rectanglehandle)->isValid())
+ result = GHOST_kSuccess;
+
+ return result;
+}
+
+
+
+void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 i)
+{
+ ((GHOST_Rect*)rectanglehandle)->inset(i);
+}
+
+
+
+void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle)
+{
+ ((GHOST_Rect*)rectanglehandle)->unionRect(*(GHOST_Rect*)anotherrectanglehandle);
+}
+
+
+
+void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y)
+{
+ ((GHOST_Rect*)rectanglehandle)->unionPoint(x, y);
+}
+
+
+
+GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 x,
+ GHOST_TInt32 y)
+{
+ GHOST_TSuccess result = GHOST_kFailure;
+
+ if (((GHOST_Rect*)rectanglehandle)->isInside(x, y))
+ result = GHOST_kSuccess;
+
+ return result;
+}
+
+
+
+GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle)
+{
+ GHOST_TVisibility visible = GHOST_kNotVisible;
+
+ visible = ((GHOST_Rect*)rectanglehandle)->getVisibility(*(GHOST_Rect*)anotherrectanglehandle);
+
+ return visible;
+}
+
+
+
+void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 cx,
+ GHOST_TInt32 cy)
+{
+ ((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy);
+}
+
+
+
+void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
+ GHOST_TInt32 cx,
+ GHOST_TInt32 cy,
+ GHOST_TInt32 w,
+ GHOST_TInt32 h)
+{
+ ((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy, w, h);
+}
+
+
+
+GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
+ GHOST_RectangleHandle anotherrectanglehandle)
+{
+ GHOST_TSuccess result = GHOST_kFailure;
+
+ if (((GHOST_Rect*)rectanglehandle)->clip(*(GHOST_Rect*)anotherrectanglehandle))
+ result = GHOST_kSuccess;
+
+ return result;
+}
+
+
+
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp
new file mode 100644
index 00000000000..8099bdbd1d5
--- /dev/null
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp
@@ -0,0 +1,55 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date October 25, 2001
+ */
+
+#include "GHOST_Debug.h"
+#include "GHOST_C-api.h"
+#include "GHOST_CallbackEventConsumer.h"
+
+GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
+ GHOST_TUserDataPtr userData)
+{
+ m_eventCallback = eventCallback;
+ m_userData = userData;
+}
+
+
+bool GHOST_CallbackEventConsumer::processEvent(GHOST_IEvent* event)
+{
+ return m_eventCallback((GHOST_EventHandle)event, m_userData) != 0;
+}
diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
new file mode 100644
index 00000000000..28326653b31
--- /dev/null
+++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h
@@ -0,0 +1,77 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date October 25, 2001
+ */
+
+#ifndef _GHOST_CALLBACK_EVENT_CONSUMER_H_
+#define _GHOST_CALLBACK_EVENT_CONSUMER_H_
+
+#include "GHOST_IEventConsumer.h"
+#include "GHOST_C-api.h"
+
+/**
+ * Interface class for objects interested in receiving events.
+ */
+class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
+ GHOST_TUserDataPtr userData);
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_CallbackEventConsumer(void)
+ {
+ }
+
+ /**
+ * This method is called by an event producer when an event is available.
+ * @param event The event that can be handled or ignored.
+ * @return Indication as to whether the event was handled.
+ */
+ virtual bool processEvent(GHOST_IEvent* event);
+
+protected:
+ GHOST_EventCallbackProcPtr m_eventCallback;
+ GHOST_TUserDataPtr m_userData;
+};
+
+#endif // _GHOST_CALLBACK_EVENT_CONSUMER_H_
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
new file mode 100644
index 00000000000..18be85e08b4
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -0,0 +1,74 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date June 1, 2001
+ */
+
+#ifndef _GHOST_DEBUG_H_
+#define _GHOST_DEBUG_H_
+
+#ifdef WIN32
+ #ifdef _DEBUG
+ #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+ #define GHOST_DEBUG
+ #endif // _DEBUG
+#else // WIN32
+ #ifndef NDEBUG
+ #define GHOST_DEBUG
+ #endif // DEBUG
+#endif // WIN32
+
+#ifdef GHOST_DEBUG
+ #include <iostream>
+#endif // GHOST_DEBUG
+
+
+#ifdef GHOST_DEBUG
+ #define GHOST_PRINT(x) { std::cout << x; }
+ //#define GHOST_PRINTF(x) { printf(x); }
+#else // GHOST_DEBUG
+ #define GHOST_PRINT(x)
+ //#define GHOST_PRINTF(x)
+#endif // GHOST_DEBUG
+
+
+#ifdef GHOST_DEBUG
+ #define GHOST_ASSERT(x, info) { if (!(x)) {GHOST_PRINT("assertion failed: "); GHOST_PRINT(info); GHOST_PRINT("\n"); } }
+#else // GHOST_DEBUG
+ #define GHOST_ASSERT(x, info)
+#endif // GHOST_DEBUG
+
+#endif // _GHOST_DEBUG_H_
diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp
new file mode 100644
index 00000000000..dc662634434
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManager.cpp
@@ -0,0 +1,219 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#include "GHOST_DisplayManager.h"
+
+#include "GHOST_Debug.h"
+
+
+GHOST_DisplayManager::GHOST_DisplayManager(
+ void)
+: m_settingsInitialized(false)
+{
+}
+
+
+GHOST_DisplayManager::~GHOST_DisplayManager(void)
+{
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::initialize(
+ void)
+{
+ GHOST_TSuccess success;
+ if (!m_settingsInitialized) {
+ success = initializeSettings();
+ m_settingsInitialized = true;
+ }
+ else {
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::getNumDisplays(
+ GHOST_TUns8& /*numDisplays*/) const
+{
+ // Don't know if we have a display...
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::getNumDisplaySettings(
+ GHOST_TUns8 display,
+ GHOST_TInt32& numSettings) const
+{
+ GHOST_TSuccess success;
+
+ GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
+ GHOST_TUns8 numDisplays;
+ success = getNumDisplays(numDisplays);
+ if (success == GHOST_kSuccess) {
+ if (display < numDisplays) {
+ numSettings = m_settings[display].size();
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ return success;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::getDisplaySetting(
+ GHOST_TUns8 display,
+ GHOST_TInt32 index,
+ GHOST_DisplaySetting& setting) const
+{
+ GHOST_TSuccess success;
+
+ GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
+ GHOST_TUns8 numDisplays;
+ success = getNumDisplays(numDisplays);
+ if (success == GHOST_kSuccess) {
+ if (display < numDisplays && index < m_settings[display].size()) {
+ setting = m_settings[display][index];
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ return success;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::getCurrentDisplaySetting(
+ GHOST_TUns8 /*display*/,
+ GHOST_DisplaySetting& /*setting*/) const
+{
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::setCurrentDisplaySetting(
+ GHOST_TUns8 /*display*/,
+ const GHOST_DisplaySetting& /*setting*/)
+{
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::findMatch(
+ GHOST_TUns8 display,
+ const GHOST_DisplaySetting& setting,
+ GHOST_DisplaySetting& match) const
+{
+ GHOST_TSuccess success = GHOST_kSuccess;
+ GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::findMatch(): m_settingsInitialized=false");
+
+ int criteria[4] = { setting.xPixels, setting.yPixels, setting.bpp, setting.frequency };
+ int capabilities[4];
+ double field, score;
+ double best = 1e12; // A big number
+ int found = 0;
+
+ // Look at all the display modes
+ for (int i = 0; (i < (int)m_settings[display].size()); i++) {
+ // Store the capabilities of the display device
+ capabilities[0] = m_settings[display][i].xPixels;
+ capabilities[1] = m_settings[display][i].yPixels;
+ capabilities[2] = m_settings[display][i].bpp;
+ capabilities[3] = m_settings[display][i].frequency;
+
+ // Match against all the fields of the display settings
+ score = 0;
+ for (int j = 0; j < 4; j++) {
+ field = capabilities[j] - criteria[j];
+ score += field * field;
+ }
+
+ if (score < best) {
+ found = i;
+ best = score;
+ }
+ }
+
+ match = m_settings[display][found];
+
+ GHOST_PRINT("GHOST_DisplayManager::findMatch(): settings of match:\n");
+ GHOST_PRINT(" setting.xPixels=" << match.xPixels << "\n");
+ GHOST_PRINT(" setting.yPixels=" << match.yPixels << "\n");
+ GHOST_PRINT(" setting.bpp=" << match.bpp << "\n");
+ GHOST_PRINT(" setting.frequency=" << match.frequency << "\n");
+
+ return success;
+}
+
+
+GHOST_TSuccess
+GHOST_DisplayManager::initializeSettings(
+ void)
+{
+ GHOST_TUns8 numDisplays;
+ GHOST_TSuccess success = getNumDisplays(numDisplays);
+ if (success == GHOST_kSuccess) {
+ for (GHOST_TUns8 display = 0; (display < numDisplays) && (success == GHOST_kSuccess); display++) {
+ GHOST_DisplaySettings displaySettings;
+ m_settings.push_back(displaySettings);
+ GHOST_TInt32 numSettings;
+ success = getNumDisplaySettings(display, numSettings);
+ if (success == GHOST_kSuccess) {
+ GHOST_TInt32 index;
+ GHOST_DisplaySetting setting;
+ for (index = 0; (index < numSettings) && (success == GHOST_kSuccess); index++) {
+ success = getDisplaySetting(display, index, setting);
+ m_settings[display].push_back(setting);
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ return success;
+}
diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h
new file mode 100644
index 00000000000..efc218a4952
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManager.h
@@ -0,0 +1,142 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#ifndef _GHOST_DISPLAY_MANAGER_H_
+#define _GHOST_DISPLAY_MANAGER_H_
+
+#include "GHOST_Types.h"
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include <vector>
+
+/**
+ * Manages system displays (platform independent implementation).
+ */
+
+class GHOST_DisplayManager
+{
+public:
+ enum { kMainDisplay = 0 };
+ /**
+ * Constructor.
+ */
+ GHOST_DisplayManager(void);
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_DisplayManager(void);
+
+ /**
+ * Initializes the list with devices and settings.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess initialize(void);
+
+ /**
+ * Returns the number of display devices on this system.
+ * @param numDisplays The number of displays on this system.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+
+ /**
+ * Returns the number of display settings for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The number of settings of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param index The setting index to be returned.
+ * @param setting The setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Changes the current setting for this display device.
+ * The setting given to this method is matched againts the available diplay settings.
+ * The best match is activated (@see findMatch()).
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The setting of the display device to be matched and activated.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+
+protected:
+ typedef std::vector<GHOST_DisplaySetting> GHOST_DisplaySettings;
+
+ /**
+ * Finds the best display settings match.
+ * @param display The index of the display device.
+ * @param setting The setting to match.
+ * @param match The optimal display setting.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess findMatch(GHOST_TUns8 display, const GHOST_DisplaySetting& setting, GHOST_DisplaySetting& match) const;
+
+ /**
+ * Retrieves settings for each display device and stores them.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess initializeSettings(void);
+
+ /** Tells whether the list of display modes has been stored already. */
+ bool m_settingsInitialized;
+ /** The list with display settings for the main display. */
+ std::vector<GHOST_DisplaySettings> m_settings;
+};
+
+
+#endif // _GHOST_DISPLAY_MANAGER_H_
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
new file mode 100644
index 00000000000..3220fa1a330
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
@@ -0,0 +1,178 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#include "GHOST_DisplayManagerCarbon.h"
+
+#include "GHOST_Debug.h"
+
+// We do not support multiple monitors at the moment
+
+
+GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(void)
+{
+ if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr)
+ {
+ m_numDisplays = 0;
+ m_displayIDs = NULL;
+ }
+ if (m_numDisplays > 0)
+ {
+ m_displayIDs = new CGDirectDisplayID [m_numDisplays];
+ GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed");
+ ::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays);
+ }
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const
+{
+ numDisplays = (GHOST_TUns8) m_numDisplays;
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getNumDisplaySettings(): only main display is supported");
+
+ CFArrayRef displayModes;
+ displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]);
+ CFIndex numModes = ::CFArrayGetCount(displayModes);
+ numSettings = (GHOST_TInt32)numModes;
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getDisplaySetting(): only main display is supported");
+
+ CFArrayRef displayModes;
+ CGDirectDisplayID d = m_displayIDs[display];
+ displayModes = ::CGDisplayAvailableModes(d);
+ CFIndex numModes = ::CFArrayGetCount(displayModes);
+ GHOST_TInt32 numSettings = (GHOST_TInt32)numModes;
+ CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index);
+
+ setting.xPixels = getValue(displayModeValues, kCGDisplayWidth);
+ setting.yPixels = getValue(displayModeValues, kCGDisplayHeight);
+ setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel);
+ setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate);
+
+#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
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(): only main display is supported");
+
+ CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]);
+
+ setting.xPixels = getValue(displayModeValues, kCGDisplayWidth);
+ setting.yPixels = getValue(displayModeValues, kCGDisplayHeight);
+ setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel);
+ setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate);
+
+#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
+
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported");
+
+#ifdef GHOST_DEBUG
+ printf("GHOST_DisplayManagerCarbon::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
+
+ 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_DisplayManagerCarbon::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;
+}
+
+
+long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const
+{
+ CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key);
+
+ if (!numberValue)
+ {
+ return -1;
+ }
+
+ long intValue;
+
+ if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue))
+ {
+ return -1;
+ }
+
+ return intValue;
+}
+
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h
new file mode 100644
index 00000000000..3374f710f47
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h
@@ -0,0 +1,119 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_
+#define _GHOST_DISPLAY_MANAGER_CARBON_H_
+
+#ifndef __APPLE__
+#error Apple only!
+#endif // __APPLE__
+
+#include "GHOST_DisplayManager.h"
+
+#include <Carbon/Carbon.h>
+
+/**
+ * Manages system displays (Mac OSX/Carbon implementation).
+ */
+
+class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_DisplayManagerCarbon(void);
+
+ /**
+ * Returns the number of display devices on this system.
+ * @param numDisplays The number of displays on this system.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+
+ /**
+ * Returns the number of display settings for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The number of settings of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param index The setting index to be returned.
+ * @param setting The setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Changes the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+
+protected:
+ /**
+ * Returns a value from a dictionary.
+ * @param values Dictionary to return value from.
+ * @param key Key to return value for.
+ * @return The value for this key.
+ */
+ long getValue(CFDictionaryRef values, CFStringRef key) const;
+
+ /** Cached number of displays. */
+ CGDisplayCount m_numDisplays;
+ /** Cached display id's for each display. */
+ CGDirectDisplayID* m_displayIDs;
+};
+
+
+#endif // _GHOST_DISPLAY_MANAGER_CARBON_H_
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
new file mode 100644
index 00000000000..60892ce094e
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -0,0 +1,186 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#include "GHOST_DisplayManagerWin32.h"
+
+#include "GHOST_Debug.h"
+
+// We do not support multiple monitors at the moment
+#include <windows.h>
+#define COMPILE_MULTIMON_STUBS
+#include <multimon.h>
+
+
+GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
+{
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const
+{
+ // We do not support multiple monitors at the moment
+ numDisplays = ::GetSystemMetrics(SM_CMONITORS);
+ return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+/*
+ * When you call EnumDisplaySettings with iModeNum set to zero, the operating system
+ * initializes and caches information about the display device. When you call
+ * EnumDisplaySettings with iModeNum set to a non-zero value, the function returns
+ * the information that was cached the last time the function was called with iModeNum
+ * set to zero.
+ */
+GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getNumDisplaySettings(): only main displlay is supported");
+ numSettings = 0;
+ DEVMODE dm;
+ while (::EnumDisplaySettings(NULL, numSettings, &dm)) {
+ numSettings++;
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getDisplaySetting(): only main display is supported");
+ GHOST_TSuccess success;
+ DEVMODE dm;
+ if (::EnumDisplaySettings(NULL, index, &dm)) {
+#ifdef GHOST_DEBUG
+ printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
+#endif // GHOST_DEBUG
+ setting.xPixels = dm.dmPelsWidth;
+ setting.yPixels = dm.dmPelsHeight;
+ setting.bpp = dm.dmBitsPerPel;
+ /* When you call the EnumDisplaySettings function, the dmDisplayFrequency member
+ * may return with the value 0 or 1. These values represent the display hardware's
+ * default refresh rate. This default rate is typically set by switches on a display
+ * card or computer motherboard, or by a configuration program that does not use
+ * Win32 display functions such as ChangeDisplaySettings.
+ */
+ /* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings
+ * returned 0 or 1 but this doesn't work since later on an exact match will
+ * be searched. And this will never happen if we change it to 60. Now we rely
+ * on the default h/w setting.
+ */
+ setting.frequency = dm.dmDisplayFrequency;
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getCurrentDisplaySetting(): only main display is supported");
+ return getDisplaySetting(kMainDisplay, ENUM_CURRENT_SETTINGS, setting);
+}
+
+
+GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
+{
+ GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::setCurrentDisplaySetting(): only main display is supported");
+
+ GHOST_DisplaySetting match;
+ GHOST_TSuccess success = findMatch(display, setting, match);
+ DEVMODE dm;
+ int i = 0;
+ while (::EnumDisplaySettings(NULL, i++, &dm)) {
+ if ((dm.dmBitsPerPel == match.bpp) &&
+ (dm.dmPelsWidth == match.xPixels) &&
+ (dm.dmPelsHeight == match.yPixels) &&
+ (dm.dmDisplayFrequency == match.frequency)) {
+ break;
+ }
+ }
+ /*
+ dm.dmBitsPerPel = match.bpp;
+ dm.dmPelsWidth = match.xPixels;
+ dm.dmPelsHeight = match.yPixels;
+ dm.dmDisplayFrequency = match.frequency;
+ dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+ dm.dmSize = sizeof(DEVMODE);
+ dm.dmDriverExtra = 0;
+ */
+#ifdef GHOST_DEBUG
+ printf("display change: Requested settings:\n");
+ printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel);
+ printf(" dmPelsWidth=%d\n", dm.dmPelsWidth);
+ printf(" dmPelsHeight=%d\n", dm.dmPelsHeight);
+ printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
+#endif // GHOST_DEBUG
+
+ LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
+#ifdef GHOST_DEBUG
+ switch (status)
+ {
+ case DISP_CHANGE_SUCCESSFUL:
+ printf("display change: The settings change was successful.\n");
+ break;
+ case DISP_CHANGE_RESTART:
+ printf("display change: The computer must be restarted in order for the graphics mode to work.\n");
+ break;
+ case DISP_CHANGE_BADFLAGS:
+ printf("display change: An invalid set of flags was passed in.\n");
+ break;
+ case DISP_CHANGE_BADPARAM:
+ printf("display change: An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n");
+ break;
+ case DISP_CHANGE_FAILED:
+ printf("display change: The display driver failed the specified graphics mode.\n");
+ break;
+ case DISP_CHANGE_BADMODE:
+ printf("display change: The graphics mode is not supported.\n");
+ break;
+ case DISP_CHANGE_NOTUPDATED:
+ printf("display change: Windows NT: Unable to write settings to the registry.\n");
+ break;
+ default:
+ printf("display change: Return value invalid\n");
+ break;
+ }
+#endif // GHOST_DEBUG
+ return status == DISP_CHANGE_SUCCESSFUL? GHOST_kSuccess : GHOST_kFailure;
+}
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
new file mode 100644
index 00000000000..f44ba07ee33
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h
@@ -0,0 +1,106 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#ifndef _GHOST_DISPLAY_MANAGER_WIN32_H_
+#define _GHOST_DISPLAY_MANAGER_WIN32_H_
+
+#ifndef WIN32
+#error WIN32 only!
+#endif // WIN32
+
+#include "GHOST_DisplayManager.h"
+
+
+/**
+ * Manages system displays (WIN32 implementation).
+ */
+
+class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_DisplayManagerWin32(void);
+
+ /**
+ * Returns the number of display devices on this system.
+ * @param numDisplays The number of displays on this system.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
+
+ /**
+ * Returns the number of display settings for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The number of settings of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param index The setting index to be returned.
+ * @param setting The setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
+
+ /**
+ * Changes the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
+
+protected:
+};
+
+
+#endif // _GHOST_DISPLAY_MANAGER_WIN32_H_
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
new file mode 100755
index 00000000000..1eb0e0a10ca
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -0,0 +1,125 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GHOST_DisplayManagerX11.h"
+
+#include "GHOST_SystemX11.h"
+
+
+
+GHOST_DisplayManagerX11::
+GHOST_DisplayManagerX11(
+ GHOST_SystemX11 *system
+) :
+ GHOST_DisplayManager(),
+ m_system(system)
+{
+ //nothing to do.
+}
+
+ GHOST_TSuccess
+GHOST_DisplayManagerX11::
+getNumDisplays(
+ GHOST_TUns8& numDisplays
+) const{
+ numDisplays = m_system->getNumDisplays();
+ return GHOST_kSuccess;
+}
+
+
+ GHOST_TSuccess
+GHOST_DisplayManagerX11::
+getNumDisplaySettings(
+ GHOST_TUns8 display,
+ GHOST_TInt32& numSettings
+) const{
+
+ // We only have one X11 setting at the moment.
+ GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
+ numSettings = GHOST_TInt32(1);
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_DisplayManagerX11::
+getDisplaySetting(
+ GHOST_TUns8 display,
+ GHOST_TInt32 index,
+ GHOST_DisplaySetting& setting
+) const {
+
+ GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
+ GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
+
+ Display * x_display = m_system->getXDisplay();
+
+ if (x_display == NULL) {
+ return GHOST_kFailure;
+ }
+
+ setting.xPixels = DisplayWidth(x_display, DefaultScreen(x_display));
+ setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
+ setting.bpp = DefaultDepth(x_display,DefaultScreen(x_display));
+
+ // Don't think it's possible to get this value from X!
+ // So let's guess!!
+ setting.frequency = 60;
+
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_DisplayManagerX11::
+getCurrentDisplaySetting(
+ GHOST_TUns8 display,
+ GHOST_DisplaySetting& setting
+) const {
+ return getDisplaySetting(display,GHOST_TInt32(0),setting);
+}
+
+
+ GHOST_TSuccess
+GHOST_DisplayManagerX11::
+setCurrentDisplaySetting(
+ GHOST_TUns8 display,
+ const GHOST_DisplaySetting& setting
+){
+ // This is never going to work robustly in X
+ // but it's currently part of the full screen interface
+
+ // we fudge it for now.
+
+ return GHOST_kSuccess;
+}
+
+
+
+
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h
new file mode 100755
index 00000000000..7f4e772ce95
--- /dev/null
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h
@@ -0,0 +1,129 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date September 21, 2001
+ */
+
+#ifndef _GHOST_DISPLAY_MANAGER_X11_H_
+#define _GHOST_DISPLAY_MANAGER_X11_H_
+
+
+#include "GHOST_DisplayManager.h"
+
+
+class GHOST_SystemX11;
+
+/**
+ * Manages system displays (X11 implementation).
+ */
+
+class GHOST_DisplayManagerX11 : public GHOST_DisplayManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_DisplayManagerX11(
+ GHOST_SystemX11 *system
+ );
+
+ /**
+ * Returns the number of display devices on this system.
+ * @param numDisplays The number of displays on this system.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getNumDisplays(
+ GHOST_TUns8& numDisplays
+ ) const;
+
+ /**
+ * Returns the number of display settings for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The number of settings of the display device with this index.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getNumDisplaySettings(
+ GHOST_TUns8 display,
+ GHOST_TInt32& numSettings
+ ) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param index The setting index to be returned.
+ * @param setting The setting of the display device with this index.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getDisplaySetting(
+ GHOST_TUns8 display,
+ GHOST_TInt32 index,
+ GHOST_DisplaySetting& setting
+ ) const;
+
+ /**
+ * Returns the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getCurrentDisplaySetting(
+ GHOST_TUns8 display,
+ GHOST_DisplaySetting& setting
+ ) const;
+
+ /**
+ * Changes the current setting for this display device.
+ * @param display The index of the display to query with 0 <= display < getNumDisplays().
+ * @param setting The current setting of the display device with this index.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ setCurrentDisplaySetting(
+ GHOST_TUns8 display,
+ const GHOST_DisplaySetting& setting
+ );
+
+private :
+
+ GHOST_SystemX11 * m_system;
+};
+
+
+#endif //
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
new file mode 100644
index 00000000000..90b411febf9
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -0,0 +1,114 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#ifndef _GHOST_EVENT_H_
+#define _GHOST_EVENT_H_
+
+#include "GHOST_IEvent.h"
+
+
+/**
+ * Base class for events received the operating system.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+class GHOST_Event : public GHOST_IEvent
+{
+public:
+ /**
+ * Constructor.
+ * @param msec The time this event was generated.
+ * @param type The type of this event.
+ * @param window The generating window (or NULL if system event).
+ */
+ GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window)
+ : m_type(type), m_time(msec), m_window(window), m_data(0)
+ {
+ }
+
+ /**
+ * Returns the event type.
+ * @return The event type.
+ */
+ virtual GHOST_TEventType getType()
+ {
+ return m_type;
+ }
+
+ /**
+ * Returns the time this event was generated.
+ * @return The event generation time.
+ */
+ virtual GHOST_TUns64 getTime()
+ {
+ return m_time;
+ }
+
+ /**
+ * Returns the window this event was generated on,
+ * or NULL if it is a 'system' event.
+ * @return The generating window.
+ */
+ virtual GHOST_IWindow* getWindow()
+ {
+ return m_window;
+ }
+
+ /**
+ * Returns the event data.
+ * @return The event data.
+ */
+ virtual GHOST_TEventDataPtr getData()
+ {
+ return m_data;
+ }
+
+protected:
+ /** Type of this event. */
+ GHOST_TEventType m_type;
+ /** The time this event was generated. */
+ GHOST_TUns64 m_time;
+ /** Pointer to the generating window. */
+ GHOST_IWindow* m_window;
+ /** Pointer to the event data. */
+ GHOST_TEventDataPtr m_data;
+};
+
+#endif // _GHOST_EVENT_H_
diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h
new file mode 100644
index 00000000000..f0718414ced
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventButton.h
@@ -0,0 +1,73 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#ifndef _GHOST_EVENT_BUTTON_H_
+#define _GHOST_EVENT_BUTTON_H_
+
+#include "GHOST_Event.h"
+
+/**
+ * Mouse button event.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+class GHOST_EventButton : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * @param time The time this event was generated.
+ * @param type The type of this event.
+ * @param x The x-coordinate of the location the cursor was at at the time of the event.
+ * @param y The y-coordinate of the location the cursor was at at the time of the event.
+ * @param buttons The state of the buttons was at at the time of the event.
+ */
+ GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TButtonMask button)
+ : GHOST_Event(time, type, window)
+ {
+ m_buttonEventData.button = button;
+ m_data = &m_buttonEventData;
+ }
+
+protected:
+ /** The button event data. */
+ GHOST_TEventButtonData m_buttonEventData;
+};
+
+#endif // _GHOST_EVENT_BUTTON_H_
diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h
new file mode 100644
index 00000000000..9b7d3d3acc7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventCursor.h
@@ -0,0 +1,74 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#ifndef _GHOST_EVENT_CURSOR_H_
+#define _GHOST_EVENT_CURSOR_H_
+
+#include "GHOST_Event.h"
+
+/**
+ * Cursor event.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+class GHOST_EventCursor : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * @param msec The time this event was generated.
+ * @param type The type of this event.
+ * @param x The x-coordinate of the location the cursor was at at the time of the event.
+ * @param y The y-coordinate of the location the cursor was at at the time of the event.
+ */
+ GHOST_EventCursor(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TInt32 x, GHOST_TInt32 y)
+ : GHOST_Event(msec, type, window)
+ {
+ m_cursorEventData.x = x;
+ m_cursorEventData.y = y;
+ m_data = &m_cursorEventData;
+ }
+
+protected:
+ /** The x,y-coordinates of the cursor position. */
+ GHOST_TEventCursorData m_cursorEventData;
+};
+
+
+#endif // _GHOST_EVENT_CURSOR_H_
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
new file mode 100644
index 00000000000..19602736d99
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -0,0 +1,87 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#ifndef _GHOST_EVENT_KEY_H_
+#define _GHOST_EVENT_KEY_H_
+
+#include "GHOST_Event.h"
+
+/**
+ * Key event.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+class GHOST_EventKey : public GHOST_Event
+{
+public:
+ /**
+ * Constructor.
+ * @param msec The time this event was generated.
+ * @param type The type of key event.
+ * @param key The key code of the key.
+ */
+ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key)
+ : GHOST_Event(msec, type, window)
+ {
+ m_keyEventData.key = key;
+ m_keyEventData.ascii = '\0';
+ m_data = &m_keyEventData;
+ }
+
+ /**
+ * Constructor.
+ * @param msec The time this event was generated.
+ * @param type The type of key event.
+ * @param key The key code of the key.
+ * @param ascii The ascii code for the key event.
+ */
+ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key, char ascii)
+ : GHOST_Event(msec, type, window)
+ {
+ m_keyEventData.key = key;
+ m_keyEventData.ascii = ascii;
+ m_data = &m_keyEventData;
+ }
+
+protected:
+ /** The key event data. */
+ GHOST_TEventKeyData m_keyEventData;
+};
+
+#endif // _GHOST_EVENT_KEY_H_
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
new file mode 100644
index 00000000000..f4a8b72db25
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -0,0 +1,215 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 14, 2001
+ */
+
+#include "GHOST_EventManager.h"
+
+#include <algorithm>
+
+#include "GHOST_Debug.h"
+
+
+GHOST_EventManager::GHOST_EventManager()
+{
+}
+
+
+GHOST_EventManager::~GHOST_EventManager()
+{
+ disposeEvents();
+}
+
+
+GHOST_TUns32 GHOST_EventManager::getNumEvents()
+{
+ return (GHOST_TUns32) m_events.size();
+}
+
+
+GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
+{
+ GHOST_TUns32 numEvents = 0;
+ std::deque<GHOST_IEvent*>::iterator p;
+ for (p = m_events.begin(); p != m_events.end(); p++) {
+ if ((*p)->getType() == type) {
+ numEvents++;
+ }
+ }
+ return numEvents;
+}
+
+
+GHOST_IEvent* GHOST_EventManager::peekEvent()
+{
+ GHOST_IEvent* event = 0;
+ if (m_events.size() > 0) {
+ event = m_events.back();
+ }
+ return event;
+}
+
+
+GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event)
+{
+ GHOST_TSuccess success;
+ GHOST_ASSERT(event, "invalid event");
+ if (m_events.size() < m_events.max_size()) {
+ m_events.push_front(event);
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event)
+{
+ bool handled;
+ if (event) {
+ handled = true;
+ /*
+ for (unsigned int i = 0; i < m_consumers.size(); i++) {
+ if (m_consumers[i]->processEvent(event)) {
+ handled = false;
+ }
+ }
+ */
+ TConsumerVector::iterator iter;
+ for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) {
+ if ((*iter)->processEvent(event)) {
+ handled = false;
+ }
+ }
+ }
+ else {
+ handled = false;
+ }
+ return handled;
+}
+
+
+bool GHOST_EventManager::dispatchEvent()
+{
+ GHOST_IEvent* event = popEvent();
+ bool handled = false;
+ if (event) {
+ handled = dispatchEvent(event);
+ delete event;
+ }
+ return handled;
+}
+
+
+bool GHOST_EventManager::dispatchEvents()
+{
+ bool handled;
+ if (getNumEvents()) {
+ handled = true;
+ while (getNumEvents()) {
+ if (!dispatchEvent()) {
+ handled = false;
+ }
+ }
+ }
+ else {
+ handled = false;
+ }
+ return handled;
+}
+
+
+GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer)
+{
+ GHOST_TSuccess success;
+ GHOST_ASSERT(consumer, "invalid consumer");
+
+ // Check to see whether the consumer is already in our list
+ TConsumerVector::const_iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
+
+ if (iter == m_consumers.end()) {
+ // Add the consumer
+ m_consumers.push_back(consumer);
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_EventManager::removeConsumer(GHOST_IEventConsumer* consumer)
+{
+ GHOST_TSuccess success;
+ GHOST_ASSERT(consumer, "invalid consumer");
+
+ // Check to see whether the consumer is in our list
+ TConsumerVector::iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
+
+ if (iter != m_consumers.end()) {
+ // Remove the consumer
+ m_consumers.erase(iter);
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_IEvent* GHOST_EventManager::popEvent()
+{
+ GHOST_IEvent* event = peekEvent();
+ if (event) {
+ m_events.pop_back();
+ }
+ return event;
+}
+
+
+void GHOST_EventManager::disposeEvents()
+{
+ while (m_events.size() > 0) {
+ GHOST_ASSERT(m_events[0], "invalid event");
+ delete m_events[0];
+ m_events.pop_front();
+ }
+}
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
new file mode 100644
index 00000000000..93c009b892d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -0,0 +1,157 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 14, 2001
+ */
+
+#ifndef _GHOST_EVENT_MANAGER_H_
+#define _GHOST_EVENT_MANAGER_H_
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include <deque>
+#include <vector>
+
+#include "GHOST_IEventConsumer.h"
+
+
+/**
+ * Manages an event stack and a list of event consumers.
+ * The stack works on a FIFO (First In First Out) basis.
+ * Events are pushed on the front of the stack and retrieved from the back.
+ * Ownership of the event is transferred to the event manager as soon as an event is pushed.
+ * Ownership of the event is transferred from the event manager as soon as an event is popped.
+ * Events can be dispatched to the event consumers.
+ */
+class GHOST_EventManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_EventManager();
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_EventManager();
+
+ /**
+ * Returns the number of events currently on the stack.
+ * @return The number of events on the stack.
+ */
+ virtual GHOST_TUns32 getNumEvents();
+
+ /**
+ * Returns the number of events of a certain type currently on the stack.
+ * @param type The type of events to be counted.
+ * @return The number of events on the stack of this type.
+ */
+ virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type);
+
+ /**
+ * Return the event at the top of the stack without removal.
+ * Do not delete the event!
+ * @return The event at the top of the stack.
+ */
+ virtual GHOST_IEvent* peekEvent();
+
+ /**
+ * Pushes an event on the stack.
+ * To dispatch it, call dispatchEvent() or dispatchEvents().
+ * Do not delete the event!
+ * @param event The event to push on the stack.
+ */
+ virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event);
+
+ /**
+ * Dispatches the given event directly, bypassing the event stack.
+ * @return Indication as to whether any of the consumers handled the event.
+ */
+ virtual bool dispatchEvent(GHOST_IEvent* event);
+
+ /**
+ * Dispatches the event at the back of the stack.
+ * The event will be removed from the stack.
+ * @return Indication as to whether any of the consumers handled the event.
+ */
+ virtual bool dispatchEvent();
+
+ /**
+ * Dispatches all the events on the stack.
+ * The event stack will be empty afterwards.
+ * @return Indication as to whether any of the consumers handled the events.
+ */
+ virtual bool dispatchEvents();
+
+ /**
+ * Adds a consumer to the list of event consumers.
+ * @param consumer The consumer added to the list.
+ * @return Indication as to whether addition has succeeded.
+ */
+ virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer);
+
+ /**
+ * Removes a consumer from the list of event consumers.
+ * @param consumer The consumer removed from the list.
+ * @return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer);
+
+protected:
+ /**
+ * Returns the event at the top of the stack and removes it.
+ * Delete the event after use!
+ * @return The event at the top of the stack.
+ */
+ virtual GHOST_IEvent* popEvent();
+
+ /**
+ * Removes all events from the stack.
+ */
+ virtual void disposeEvents();
+
+ /** The event stack. */
+ std::deque<GHOST_IEvent*> m_events;
+
+ typedef std::vector<GHOST_IEventConsumer*> TConsumerVector;
+ /** The list with event consumers. */
+ TConsumerVector m_consumers;
+};
+
+#endif // _GHOST_EVENT_MANAGER_H_
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
new file mode 100644
index 00000000000..16576357fbc
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -0,0 +1,259 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 15, 2001
+ */
+
+#include "GHOST_EventPrinter.h"
+
+#include <iostream>
+
+#include "GHOST_EventKey.h"
+#include "GHOST_Debug.h"
+
+bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
+{
+ bool handled = true;
+
+ GHOST_ASSERT(event, "event==0");
+
+ if (event->getType() == GHOST_kEventWindowUpdate) return false;
+
+ std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
+ switch (event->getType()) {
+ case GHOST_kEventUnknown:
+ std::cout << "GHOST_kEventUnknown"; handled = false; break;
+
+ case GHOST_kEventButtonUp:
+ {
+ GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData();
+ std::cout << "GHOST_kEventCursorButtonUp, button: " << buttonData->button;
+ }
+ break;
+ case GHOST_kEventButtonDown:
+ {
+ GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData();
+ std::cout << "GHOST_kEventButtonDown, button: " << buttonData->button;
+ }
+ break;
+
+ case GHOST_kEventCursorMove:
+ {
+ GHOST_TEventCursorData* cursorData = (GHOST_TEventCursorData*)((GHOST_IEvent*)event)->getData();
+ std::cout << "GHOST_kEventCursorMove, (x,y): (" << cursorData->x << "," << cursorData->y << ")";
+ }
+ break;
+
+ case GHOST_kEventKeyUp:
+ {
+ GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData();
+ STR_String str;
+ getKeyString(keyData->key, str);
+ std::cout << "GHOST_kEventKeyUp, key: " << str.Ptr();
+ }
+ break;
+ case GHOST_kEventKeyDown:
+ {
+ GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData();
+ STR_String str;
+ getKeyString(keyData->key, str);
+ std::cout << "GHOST_kEventKeyDown, key: " << str.Ptr();
+ }
+ break;
+
+ case GHOST_kEventQuit:
+ std::cout << "GHOST_kEventQuit"; break;
+ case GHOST_kEventWindowClose:
+ std::cout << "GHOST_kEventWindowClose"; break;
+ case GHOST_kEventWindowActivate:
+ std::cout << "GHOST_kEventWindowActivate"; break;
+ case GHOST_kEventWindowDeactivate:
+ std::cout << "GHOST_kEventWindowDeactivate"; break;
+ case GHOST_kEventWindowUpdate:
+ std::cout << "GHOST_kEventWindowUpdate"; break;
+ case GHOST_kEventWindowSize:
+ std::cout << "GHOST_kEventWindowSize"; break;
+
+ default:
+ std::cout << "not found"; handled = false; break;
+ }
+ std::cout << "\n";
+ return handled;
+}
+
+
+void GHOST_EventPrinter::getKeyString(GHOST_TKey key, STR_String& str) const
+{
+ if ((key >= GHOST_kKeyComma) && (key <= GHOST_kKeyRightBracket)) {
+ str = ((char)key);
+ }
+ else if ((key >= GHOST_kKeyNumpad0) && (key <= GHOST_kKeyNumpad9)) {
+ int number = key - GHOST_kKeyNumpad0;
+ STR_String numberStr (number);
+ str = "Numpad";
+ str += numberStr;
+ }
+ else if ((key >= GHOST_kKeyF1) && (key <= GHOST_kKeyF24)) {
+ int number = key - GHOST_kKeyF1 + 1;
+ STR_String numberStr (number);
+ str = "F";
+ str += numberStr;
+ }
+ else {
+ switch (key)
+ {
+ case GHOST_kKeyBackSpace:
+ str = "BackSpace";
+ break;
+ case GHOST_kKeyTab:
+ str = "Tab";
+ break;
+ case GHOST_kKeyLinefeed:
+ str = "Linefeed";
+ break;
+ case GHOST_kKeyClear:
+ str = "Clear";
+ break;
+ case GHOST_kKeyEnter:
+ str = "Enter";
+ break;
+ case GHOST_kKeyEsc:
+ str = "Esc";
+ break;
+ case GHOST_kKeySpace:
+ str = "Space";
+ break;
+ case GHOST_kKeyQuote:
+ str = "Quote";
+ break;
+ case GHOST_kKeyBackslash:
+ str = "\\";
+ break;
+ case GHOST_kKeyAccentGrave:
+ str = "`";
+ break;
+ case GHOST_kKeyLeftShift:
+ str = "LeftShift";
+ break;
+ case GHOST_kKeyRightShift:
+ str = "RightShift";
+ break;
+ case GHOST_kKeyLeftControl:
+ str = "LeftControl";
+ break;
+ case GHOST_kKeyRightControl:
+ str = "RightControl";
+ break;
+ case GHOST_kKeyLeftAlt:
+ str = "LeftAlt";
+ break;
+ case GHOST_kKeyRightAlt:
+ str = "RightAlt";
+ break;
+ case GHOST_kKeyCommand:
+ // APPLE only!
+ str = "Command";
+ break;
+ case GHOST_kKeyCapsLock:
+ str = "CapsLock";
+ break;
+ case GHOST_kKeyNumLock:
+ str = "NumLock";
+ break;
+ case GHOST_kKeyScrollLock:
+ str = "ScrollLock";
+ break;
+ case GHOST_kKeyLeftArrow:
+ str = "LeftArrow";
+ break;
+ case GHOST_kKeyRightArrow:
+ str = "RightArrow";
+ break;
+ case GHOST_kKeyUpArrow:
+ str = "UpArrow";
+ break;
+ case GHOST_kKeyDownArrow:
+ str = "DownArrow";
+ break;
+ case GHOST_kKeyPrintScreen:
+ str = "PrintScreen";
+ break;
+ case GHOST_kKeyPause:
+ str = "Pause";
+ break;
+ case GHOST_kKeyInsert:
+ str = "Insert";
+ break;
+ case GHOST_kKeyDelete:
+ str = "Delete";
+ break;
+ case GHOST_kKeyHome:
+ str = "Home";
+ break;
+ case GHOST_kKeyEnd:
+ str = "End";
+ break;
+ case GHOST_kKeyUpPage:
+ str = "UpPage";
+ break;
+ case GHOST_kKeyDownPage:
+ str = "DownPage";
+ break;
+ case GHOST_kKeyNumpadPeriod:
+ str = "NumpadPeriod";
+ break;
+ case GHOST_kKeyNumpadEnter:
+ str = "NumpadEnter";
+ break;
+ case GHOST_kKeyNumpadPlus:
+ str = "NumpadPlus";
+ break;
+ case GHOST_kKeyNumpadMinus:
+ str = "NumpadMinus";
+ break;
+ case GHOST_kKeyNumpadAsterisk:
+ str = "NumpadAsterisk";
+ break;
+ case GHOST_kKeyNumpadSlash:
+ str = "NumpadSlash";
+ break;
+ default:
+ str = "unknown";
+ break;
+ }
+ }
+}
+
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
new file mode 100644
index 00000000000..6214e94393d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -0,0 +1,70 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 14, 2001
+ */
+
+#ifndef _GHOST_EVENT_PRINTER_H_
+#define _GHOST_EVENT_PRINTER_H_
+
+#include "GHOST_IEventConsumer.h"
+
+#include "STR_String.h"
+
+/**
+ * An Event consumer that prints all the events to standard out.
+ * Really useful when debugging.
+ */
+class GHOST_EventPrinter : public GHOST_IEventConsumer
+{
+public:
+ /**
+ * Prints all the events received to std out.
+ * @param event The event that can be handled or not.
+ * @return Indication as to whether the event was handled.
+ */
+ virtual bool processEvent(GHOST_IEvent* event);
+
+protected:
+ /**
+ * Converts GHOST key code to a readable string.
+ * @param key The GHOST key code to convert.
+ * @param str The GHOST key code converted to a readable string.
+ */
+ void getKeyString(GHOST_TKey key, STR_String& str) const;
+};
+
+#endif // _GHOST_EVENT_PRINTER_H_
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
new file mode 100644
index 00000000000..6505194645a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -0,0 +1,98 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#include "GHOST_ISystem.h"
+
+#ifdef WIN32
+# include "GHOST_SystemWin32.h"
+#else
+# ifdef __APPLE__
+# include "GHOST_SystemCarbon.h"
+# else
+# include "GHOST_SystemX11.h"
+# endif
+#endif
+
+
+GHOST_ISystem* GHOST_ISystem::m_system = 0;
+
+
+GHOST_TSuccess GHOST_ISystem::createSystem()
+{
+ GHOST_TSuccess success;
+ if (!m_system) {
+#ifdef WIN32
+ m_system = new GHOST_SystemWin32 ();
+#else
+# ifdef __APPLE__
+ m_system = new GHOST_SystemCarbon ();
+# else
+ m_system = new GHOST_SystemX11 ();
+# endif
+#endif
+ success = m_system != 0 ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ if (success) {
+ success = m_system->init();
+ }
+ return success;
+}
+
+GHOST_TSuccess GHOST_ISystem::disposeSystem()
+{
+ GHOST_TSuccess success;
+ if (m_system) {
+ delete m_system;
+ m_system = 0;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_ISystem* GHOST_ISystem::getSystem()
+{
+ return m_system;
+}
+
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.cpp b/intern/ghost/intern/GHOST_ModifierKeys.cpp
new file mode 100644
index 00000000000..930ddf97f9a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ModifierKeys.cpp
@@ -0,0 +1,136 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#include "GHOST_ModifierKeys.h"
+
+
+GHOST_ModifierKeys::GHOST_ModifierKeys()
+{
+ clear();
+}
+
+
+GHOST_TKey GHOST_ModifierKeys::getModifierKeyCode(GHOST_TModifierKeyMask mask)
+{
+ GHOST_TKey key;
+ switch (mask) {
+ case GHOST_kModifierKeyLeftShift: key = GHOST_kKeyLeftShift; break;
+ case GHOST_kModifierKeyRightShift: key = GHOST_kKeyRightShift; break;
+ case GHOST_kModifierKeyLeftAlt: key = GHOST_kKeyLeftAlt; break;
+ case GHOST_kModifierKeyRightAlt: key = GHOST_kKeyRightAlt; break;
+ case GHOST_kModifierKeyLeftControl: key = GHOST_kKeyLeftControl; break;
+ case GHOST_kModifierKeyRightControl: key = GHOST_kKeyRightControl; break;
+ case GHOST_kModifierKeyCommand: key = GHOST_kKeyCommand; break;
+ default:
+ // Should not happen
+ key = GHOST_kKeyUnknown;
+ break;
+ }
+ return key;
+}
+
+
+bool GHOST_ModifierKeys::get(GHOST_TModifierKeyMask mask) const
+{
+ switch (mask) {
+ case GHOST_kModifierKeyLeftShift:
+ return m_LeftShift;
+ case GHOST_kModifierKeyRightShift:
+ return m_RightShift;
+ case GHOST_kModifierKeyLeftAlt:
+ return m_LeftAlt;
+ case GHOST_kModifierKeyRightAlt:
+ return m_RightAlt;
+ case GHOST_kModifierKeyLeftControl:
+ return m_LeftControl;
+ case GHOST_kModifierKeyRightControl:
+ return m_RightControl;
+ case GHOST_kModifierKeyCommand:
+ return m_Command;
+ default:
+ return false;
+ }
+}
+
+
+void GHOST_ModifierKeys::set(GHOST_TModifierKeyMask mask, bool down)
+{
+ switch (mask) {
+ case GHOST_kModifierKeyLeftShift:
+ m_LeftShift = down; break;
+ case GHOST_kModifierKeyRightShift:
+ m_RightShift = down; break;
+ case GHOST_kModifierKeyLeftAlt:
+ m_LeftAlt = down; break;
+ case GHOST_kModifierKeyRightAlt:
+ m_RightAlt = down; break;
+ case GHOST_kModifierKeyLeftControl:
+ m_LeftControl = down; break;
+ case GHOST_kModifierKeyRightControl:
+ m_RightControl = down; break;
+ case GHOST_kModifierKeyCommand:
+ m_Command = down; break;
+ default:
+ break;
+ }
+}
+
+
+void GHOST_ModifierKeys::clear()
+{
+ m_LeftShift = false;
+ m_RightShift = false;
+ m_LeftAlt = false;
+ m_RightAlt = false;
+ m_LeftControl = false;
+ m_RightControl = false;
+ m_Command = false;
+}
+
+
+bool GHOST_ModifierKeys::equals(const GHOST_ModifierKeys& keys) const
+{
+ return (m_LeftShift == keys.m_LeftShift) &&
+ (m_RightShift == keys.m_RightShift) &&
+ (m_LeftAlt == keys.m_LeftAlt) &&
+ (m_RightAlt == keys.m_RightAlt) &&
+ (m_LeftControl == keys.m_LeftControl) &&
+ (m_RightControl == keys.m_RightControl) &&
+ (m_Command == keys.m_Command);
+}
diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h
new file mode 100644
index 00000000000..fc590b9597f
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ModifierKeys.h
@@ -0,0 +1,102 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 17, 2001
+ */
+
+#ifndef _GHOST_MODIFIER_KEYS_H_
+#define _GHOST_MODIFIER_KEYS_H_
+
+#include "GHOST_Types.h"
+
+struct GHOST_ModifierKeys
+{
+ /**
+ * Constructor.
+ */
+ GHOST_ModifierKeys();
+
+ /**
+ * Returns the modifier key's key code from a modifier key mask.
+ * @param mask The mask of the modifier key.
+ * @return The modifier key's key code.
+ */
+ static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask);
+
+
+ /**
+ * Returns the state of a single modifier key.
+ * @param mask. Key state to return.
+ * @return The state of the key (pressed == true).
+ */
+ virtual bool get(GHOST_TModifierKeyMask mask) const;
+
+ /**
+ * Updates the state of a single modifier key.
+ * @param mask. Key state to update.
+ * @param down. The new state of the key.
+ */
+ virtual void set(GHOST_TModifierKeyMask mask, bool down);
+
+ /**
+ * Sets the state of all modifier keys to up.
+ */
+ virtual void clear();
+
+ /**
+ * Determines whether to modifier key states are equal.
+ * @param keys. The modifier key state to compare to.
+ * @return Indication of equality.
+ */
+ virtual bool equals(const GHOST_ModifierKeys& keys) const;
+
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_LeftShift : 1;
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_RightShift : 1;
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_LeftAlt : 1;
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_RightAlt : 1;
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_LeftControl : 1;
+ /** Bitfield that stores the appropriate key state. */
+ GHOST_TUns8 m_RightControl : 1;
+ /** Bitfield that stores the appropriate key state. APPLE only! */
+ GHOST_TUns8 m_Command : 1;
+};
+
+#endif // _GHOST_MODIFIER_KEYS_H_
diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp
new file mode 100644
index 00000000000..cb600815f69
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Rect.cpp
@@ -0,0 +1,140 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GHOST_Rect.h"
+
+
+
+void GHOST_Rect::inset(GHOST_TInt32 i)
+{
+ if (i > 0) {
+ // Grow the rectangle
+ m_l -= i;
+ m_r += i;
+ m_t -= i;
+ m_b += i;
+ }
+ else if (i < 0) {
+ // Shrink the rectangle, check for insets larger than half the size
+ GHOST_TInt32 i2 = i * 2;
+ if (getWidth() > i2) {
+ m_l += i;
+ m_r -= i;
+ }
+ else {
+ m_l = m_l + ((m_r - m_l) / 2);
+ m_r = m_l;
+ }
+ if (getHeight() > i2) {
+ m_t += i;
+ m_b -= i;
+ }
+ else {
+ m_t = m_t + ((m_b - m_t) / 2);
+ m_b = m_t;
+ }
+ }
+}
+
+
+GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect& r) const
+{
+ bool lt = isInside(r.m_l, r.m_t);
+ bool rt = isInside(r.m_r, r.m_t);
+ bool lb = isInside(r.m_l, r.m_b);
+ bool rb = isInside(r.m_r, r.m_b);
+ GHOST_TVisibility v;
+ if (lt && rt && lb && rb) {
+ // All points inside, rectangle is inside this
+ v = GHOST_kFullyVisible;
+ }
+ else if (!(lt || rt || lb || rb)) {
+ // None of the points inside
+ // Check to see whether the rectangle is larger than this one
+ if ((r.m_l < m_l) && (r.m_t < m_t) && (r.m_r > m_r) && (r.m_b > m_b)) {
+ v = GHOST_kPartiallyVisible;
+ }
+ else {
+ v = GHOST_kNotVisible;
+ }
+ }
+ else {
+ // Some of the points inside, rectangle is partially inside
+ v = GHOST_kPartiallyVisible;
+ }
+ return v;
+}
+
+
+void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy)
+{
+ GHOST_TInt32 offset = cx - (m_l + (m_r - m_l)/2);
+ m_l += offset;
+ m_r += offset;
+ offset = cy - (m_t + (m_b - m_t)/2);
+ m_t += offset;
+ m_b += offset;
+}
+
+void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h)
+{
+ long w_2, h_2;
+
+ w_2 = w >> 1;
+ h_2 = h >> 1;
+ m_l = cx - w_2;
+ m_t = cy - h_2;
+ m_r = m_l + w;
+ m_b = m_t + h;
+}
+
+bool GHOST_Rect::clip(GHOST_Rect& r) const
+{
+ bool clipped = false;
+ if (r.m_l < m_l) {
+ r.m_l = m_l;
+ clipped = true;
+ }
+ if (r.m_t < m_t) {
+ r.m_t = m_t;
+ clipped = true;
+ }
+ if (r.m_r > m_r) {
+ r.m_r = m_r;
+ clipped = true;
+ }
+ if (r.m_b > m_b) {
+ r.m_b = m_b;
+ clipped = true;
+ }
+ return clipped;
+}
+
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
new file mode 100644
index 00000000000..5585be62f5a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -0,0 +1,320 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#include "GHOST_System.h"
+
+#include <time.h>
+
+#include "GHOST_DisplayManager.h"
+#include "GHOST_EventManager.h"
+#include "GHOST_TimerTask.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_WindowManager.h"
+
+
+GHOST_System::GHOST_System()
+: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0)
+{
+}
+
+
+GHOST_System::~GHOST_System()
+{
+ exit();
+}
+
+
+GHOST_TUns64 GHOST_System::getMilliSeconds() const
+{
+ GHOST_TUns64 millis = ::clock();
+ if (CLOCKS_PER_SEC != 1000) {
+ millis *= 1000;
+ millis /= CLOCKS_PER_SEC;
+ }
+ return millis;
+}
+
+
+GHOST_ITimerTask* GHOST_System::installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData)
+{
+ GHOST_TUns64 millis = getMilliSeconds();
+ GHOST_TimerTask* timer = new GHOST_TimerTask(millis+delay, interval, timerProc, userData);
+ if (timer) {
+ if (m_timerManager->addTimer(timer) == GHOST_kSuccess) {
+ // Check to see whether we need to fire the timer right away
+ m_timerManager->fireTimers(millis);
+ }
+ else {
+ delete timer;
+ timer = 0;
+ }
+ }
+ return timer;
+}
+
+
+GHOST_TSuccess GHOST_System::removeTimer(GHOST_ITimerTask* timerTask)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ if (timerTask) {
+ success = m_timerManager->removeTimer((GHOST_TimerTask*)timerTask);
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow* window)
+{
+ GHOST_TSuccess success;
+ if (window == m_windowManager->getFullScreenWindow()) {
+ success = endFullScreen();
+ }
+ else {
+ if (m_windowManager->getWindowFound(window)) {
+ success = m_windowManager->removeWindow(window);
+ if (success) {
+ delete window;
+ }
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ return success;
+}
+
+
+bool GHOST_System::validWindow(GHOST_IWindow* window)
+{
+ return m_windowManager->getWindowFound(window);
+}
+
+
+GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
+ bool stereoVisual)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager")
+ if (m_displayManager) {
+ if (!m_windowManager->getFullScreen()) {
+ m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
+
+ //GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n");
+ success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
+ if (success == GHOST_kSuccess) {
+ //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
+ success = createFullScreenWindow((GHOST_Window**)window, stereoVisual);
+ if (success == GHOST_kSuccess) {
+ m_windowManager->beginFullScreen(*window, stereoVisual);
+ }
+ else {
+ m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
+ }
+ }
+ }
+ }
+ if (success == GHOST_kFailure) {
+ GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n");
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::endFullScreen(void)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager")
+ if (m_windowManager->getFullScreen()) {
+ GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
+ //GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n");
+ success = m_windowManager->endFullScreen();
+ GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager")
+ //GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n");
+ success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+bool GHOST_System::getFullScreen(void)
+{
+ bool fullScreen;
+ if (m_windowManager) {
+ fullScreen = m_windowManager->getFullScreen();
+ }
+ else {
+ fullScreen = false;
+ }
+ return fullScreen;
+}
+
+
+bool GHOST_System::dispatchEvents()
+{
+ bool handled;
+ if (m_eventManager) {
+ handled = m_eventManager->dispatchEvents();
+ }
+ else {
+ handled = false;
+ }
+
+ m_timerManager->fireTimers(getMilliSeconds());
+ return handled;
+}
+
+
+GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer* consumer)
+{
+ GHOST_TSuccess success;
+ if (m_eventManager) {
+ success = m_eventManager->addConsumer(consumer);
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event)
+{
+ GHOST_TSuccess success;
+ if (m_eventManager) {
+ success = m_eventManager->pushEvent(event);
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
+{
+ GHOST_ModifierKeys keys;
+ // Get the state of all modifier keys
+ GHOST_TSuccess success = getModifierKeys(keys);
+ if (success) {
+ // Isolate the state of the key requested
+ isDown = keys.get(mask);
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const
+{
+ GHOST_Buttons buttons;
+ // Get the state of all mouse buttons
+ GHOST_TSuccess success = getButtons(buttons);
+ if (success) {
+ // Isolate the state of the mouse button requested
+ isDown = buttons.get(mask);
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_System::init()
+{
+ m_timerManager = new GHOST_TimerManager ();
+ m_windowManager = new GHOST_WindowManager ();
+ m_eventManager = new GHOST_EventManager ();
+#ifdef GHOST_DEBUG
+ if (m_eventManager) {
+ //m_eventManager->addConsumer(&m_eventPrinter);
+ }
+#endif // GHOST_DEBUG
+
+ if (m_timerManager && m_windowManager && m_eventManager) {
+ return GHOST_kSuccess;
+ } else {
+ return GHOST_kFailure;
+ }
+}
+
+
+GHOST_TSuccess GHOST_System::exit()
+{
+ if (getFullScreen()) {
+ endFullScreen();
+ }
+ if (m_displayManager) {
+ delete m_displayManager;
+ m_displayManager = 0;
+ }
+ if (m_windowManager) {
+ delete m_windowManager;
+ m_windowManager = 0;
+ }
+ if (m_timerManager) {
+ delete m_timerManager;
+ m_timerManager = 0;
+ }
+ if (m_eventManager) {
+ delete m_eventManager;
+ m_eventManager = 0;
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, bool stereoVisual)
+{
+ GHOST_TSuccess success;
+ GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager")
+ GHOST_DisplaySetting settings;
+
+ success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings);
+ if (success) {
+ //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
+ *window = (GHOST_Window*)createWindow(
+ STR_String (""),
+ 0, 0, settings.xPixels, settings.yPixels,
+ GHOST_kWindowStateFullScreen,
+ GHOST_kDrawingContextTypeOpenGL,
+ stereoVisual);
+ success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
+ }
+ return success;
+}
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
new file mode 100644
index 00000000000..52d90cab7a7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_System.h
@@ -0,0 +1,328 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#ifndef _GHOST_SYSTEM_H_
+#define _GHOST_SYSTEM_H_
+
+#include "GHOST_ISystem.h"
+
+#include "GHOST_Debug.h"
+#include "GHOST_Buttons.h"
+#include "GHOST_ModifierKeys.h"
+#include "GHOST_EventManager.h"
+#ifdef GHOST_DEBUG
+#include "GHOST_EventPrinter.h"
+#endif // GHOST_DEBUG
+
+class GHOST_DisplayManager;
+class GHOST_Event;
+class GHOST_TimerManager;
+class GHOST_Window;
+class GHOST_WindowManager;
+
+/**
+ * Implementation of platform independent functionality of the GHOST_ISystem interface.
+ * GHOST_System is an abstract base class because not all methods of GHOST_ISystem are implemented.
+ * There should be only one system class in an application.
+ * Therefore, the routines to create and dispose the system are static.
+ * Provides:
+ * 1. Time(r) management.
+ * 2. Display/window management (windows are only created on the main display for now).
+ * 3. Event management.
+ * 4. Cursor shape management (no custom cursors for now).
+ * 5. Access to the state of the mouse buttons and the keyboard.
+ * @see GHOST_ISystem.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+class GHOST_System : public GHOST_ISystem
+{
+protected:
+ /**
+ * Constructor.
+ * Protected default constructor to force use of static createSystem member.
+ */
+ GHOST_System();
+
+ /**
+ * Destructor.
+ * Protected default constructor to force use of static dispose member.
+ */
+ virtual ~GHOST_System();
+
+public:
+ /***************************************************************************************
+ ** Time(r) functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * Based on ANSI clock() routine.
+ * @return The number of milliseconds.
+ */
+ virtual GHOST_TUns64 getMilliSeconds() const;
+
+ /**
+ * Installs a timer.
+ * Note that, on most operating systems, messages need to be processed in order
+ * for the timer callbacks to be invoked.
+ * @param delay The time to wait for the first call to the timerProc (in milliseconds)
+ * @param interval The interval between calls to the timerProc
+ * @param timerProc The callback invoked when the interval expires,
+ * @param userData Placeholder for user data.
+ * @return A timer task (0 if timer task installation failed).
+ */
+ virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0);
+
+ /**
+ * Removes a timer.
+ * @param timerTask Timer task to be removed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask);
+
+ /***************************************************************************************
+ ** Display/window management functionality
+ ***************************************************************************************/
+
+ /**
+ * Inherited from GHOST_ISystem but left pure virtual
+ *
+ * virtual GHOST_TUns8 getNumDisplays() const = 0;
+ * virtual void getMainDisplayDimensions(...) const = 0;
+ * virtual GHOST_IWindow* createWindow(..)
+ */
+
+ /**
+ * Dispose a window.
+ * @param window Pointer to the window to be disposed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window);
+
+ /**
+ * Returns whether a window is valid.
+ * @param window Pointer to the window to be checked.
+ * @return Indication of validity.
+ */
+ virtual bool validWindow(GHOST_IWindow* window);
+
+ /**
+ * Begins full screen mode.
+ * @param setting The new setting of the display.
+ * @param window Window displayed in full screen.
+ * @param stereoVisual Stereo visual for quad buffered stereo.
+ * This window is invalid after full screen has been ended.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
+ const bool stereoVisual);
+
+ /**
+ * Ends full screen mode.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess endFullScreen(void);
+
+ /**
+ * Returns current full screen mode status.
+ * @return The current status.
+ */
+ virtual bool getFullScreen(void);
+
+
+ /***************************************************************************************
+ ** Event management functionality
+ ***************************************************************************************/
+
+ /**
+ * Inherited from GHOST_ISystem but left pure virtual
+ *
+ * virtual bool processEvents(bool waitForEvent) = 0;
+ */
+
+
+
+ /**
+ * Dispatches all the events on the stack.
+ * The event stack will be empty afterwards.
+ * @return Indication as to whether any of the consumers handled the events.
+ */
+ virtual bool dispatchEvents();
+
+ /**
+ * Adds the given event consumer to our list.
+ * @param consumer The event consumer to add.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer);
+
+ /***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+ /** Inherited from GHOST_ISystem but left pure virtual
+ * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0;
+ * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
+ */
+
+ /***************************************************************************************
+ ** Access to mouse button and keyboard states.
+ ***************************************************************************************/
+
+ /**
+ * Returns the state of a modifier key (ouside the message queue).
+ * @param mask The modifier key state to retrieve.
+ * @param isDown The state of a modifier key (true == pressed).
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
+
+ /**
+ * Returns the state of a mouse button (ouside the message queue).
+ * @param mask The button state to retrieve.
+ * @param isDown Button state.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
+
+ /***************************************************************************************
+ ** Other (internal) functionality.
+ ***************************************************************************************/
+
+ /**
+ * Pushes an event on the stack.
+ * To dispatch it, call dispatchEvent() or dispatchEvents().
+ * Do not delete the event!
+ * @param event The event to push on the stack.
+ */
+ virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event);
+
+ /**
+ * Returns the timer manager.
+ * @return The timer manager.
+ */
+ inline virtual GHOST_TimerManager* getTimerManager() const;
+
+ /**
+ * Returns a pointer to our event manager.
+ * @return A pointer to our event manager.
+ */
+ virtual inline GHOST_EventManager* getEventManager() const;
+
+ /**
+ * Returns a pointer to our window manager.
+ * @return A pointer to our window manager.
+ */
+ virtual inline GHOST_WindowManager* getWindowManager() const;
+
+ /**
+ * Returns the state of all modifier keys.
+ * @param keys The state of all modifier keys (true == pressed).
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const = 0;
+
+ /**
+ * Returns the state of the mouse buttons (ouside the message queue).
+ * @param buttons The state of the buttons.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0;
+
+protected:
+ /**
+ * Initialize the system.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess init();
+
+ /**
+ * Shut the system down.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess exit();
+
+ /**
+ * Creates a fullscreen window.
+ * @param window The window created.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window** window,
+ const bool stereoVisual);
+
+ /** The display manager (platform dependant). */
+ GHOST_DisplayManager* m_displayManager;
+
+ /** The timer manager. */
+ GHOST_TimerManager* m_timerManager;
+
+ /** The window manager. */
+ GHOST_WindowManager* m_windowManager;
+
+ /** The event manager. */
+ GHOST_EventManager* m_eventManager;
+
+ /** Prints all the events. */
+#ifdef GHOST_DEBUG
+ GHOST_EventPrinter m_eventPrinter;
+#endif // GHOST_DEBUG
+
+ /** Settings of the display before the display went fullscreen. */
+ GHOST_DisplaySetting m_preFullScreenSetting;
+};
+
+inline GHOST_TimerManager* GHOST_System::getTimerManager() const
+{
+ return m_timerManager;
+}
+
+inline GHOST_EventManager* GHOST_System::getEventManager() const
+{
+ return m_eventManager;
+}
+
+inline GHOST_WindowManager* GHOST_System::getWindowManager() const
+{
+ return m_windowManager;
+}
+
+#endif // _GHOST_SYSTEM_H_
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp
new file mode 100644
index 00000000000..baba1bb4e6c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp
@@ -0,0 +1,735 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#include "GHOST_SystemCarbon.h"
+
+#include "GHOST_DisplayManagerCarbon.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_TimerTask.h"
+#include "GHOST_WindowManager.h"
+#include "GHOST_WindowCarbon.h"
+
+#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; }
+
+const EventTypeSpec kEvents[] =
+{
+ { kEventClassAppleEvent, kEventAppleEvent },
+
+/*
+ { kEventClassApplication, kEventAppActivated },
+ { kEventClassApplication, kEventAppDeactivated },
+*/
+
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged },
+
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+ { kEventClassWindow, kEventWindowUpdate },
+ { kEventClassWindow, kEventWindowBoundsChanged }
+};
+
+static GHOST_TButtonMask convertButton(EventMouseButton button)
+{
+ switch (button) {
+ case kEventMouseButtonPrimary:
+ return GHOST_kButtonMaskLeft;
+ case kEventMouseButtonSecondary:
+ return GHOST_kButtonMaskRight;
+ case kEventMouseButtonTertiary:
+ default:
+ return GHOST_kButtonMaskMiddle;
+ }
+}
+
+static GHOST_TKey convertKey(int rawCode)
+{
+ /* This bit of magic converts the rawCode into a virtual
+ * Mac key based on the current keyboard mapping, but
+ * without regard to the modifiers (so we don't get 'a'
+ * and 'A' for example.
+ */
+ UInt32 dummy= 0;
+ Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache);
+ char vk = KeyTranslate(transData, rawCode, &dummy);
+
+ /* Map numpad based on rawcodes first, otherwise they
+ * look like non-numpad events.
+ */
+ switch (rawCode) {
+ case 82: return GHOST_kKeyNumpad0;
+ case 83: return GHOST_kKeyNumpad1;
+ case 84: return GHOST_kKeyNumpad2;
+ case 85: return GHOST_kKeyNumpad3;
+ case 86: return GHOST_kKeyNumpad4;
+ case 87: return GHOST_kKeyNumpad5;
+ case 88: return GHOST_kKeyNumpad6;
+ case 89: return GHOST_kKeyNumpad7;
+ case 91: return GHOST_kKeyNumpad8;
+ case 92: return GHOST_kKeyNumpad9;
+ case 65: return GHOST_kKeyNumpadPeriod;
+ case 76: return GHOST_kKeyNumpadEnter;
+ case 69: return GHOST_kKeyNumpadPlus;
+ case 78: return GHOST_kKeyNumpadMinus;
+ case 67: return GHOST_kKeyNumpadAsterisk;
+ case 75: return GHOST_kKeyNumpadSlash;
+ }
+
+ if ((vk >= 'a') && (vk <= 'z')) {
+ return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA);
+ } else if ((vk >= '0') && (vk <= '9')) {
+ return (GHOST_TKey) (vk - '0' + GHOST_kKey0);
+ } else if (vk==16) {
+ switch (rawCode) {
+ case 122: return GHOST_kKeyF1;
+ case 120: return GHOST_kKeyF2;
+ case 99: return GHOST_kKeyF3;
+ case 118: return GHOST_kKeyF4;
+ case 96: return GHOST_kKeyF5;
+ case 97: return GHOST_kKeyF6;
+ case 98: return GHOST_kKeyF7;
+ case 100: return GHOST_kKeyF8;
+ case 101: return GHOST_kKeyF9;
+ case 109: return GHOST_kKeyF10;
+ case 103: return GHOST_kKeyF11;
+ case 111: return GHOST_kKeyF12; // Never get, is used for ejecting the CD!
+ }
+ } else {
+ switch (vk) {
+ case kUpArrowCharCode: return GHOST_kKeyUpArrow;
+ case kDownArrowCharCode: return GHOST_kKeyDownArrow;
+ case kLeftArrowCharCode: return GHOST_kKeyLeftArrow;
+ case kRightArrowCharCode: return GHOST_kKeyRightArrow;
+
+ case kReturnCharCode: return GHOST_kKeyEnter;
+ case kBackspaceCharCode: return GHOST_kKeyBackSpace;
+ case kDeleteCharCode: return GHOST_kKeyDelete;
+ case kEscapeCharCode: return GHOST_kKeyEsc;
+ case kTabCharCode: return GHOST_kKeyTab;
+ case kSpaceCharCode: return GHOST_kKeySpace;
+
+ case kHomeCharCode: return GHOST_kKeyHome;
+ case kEndCharCode: return GHOST_kKeyEnd;
+ case kPageUpCharCode: return GHOST_kKeyUpPage;
+ case kPageDownCharCode: return GHOST_kKeyDownPage;
+
+ 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;
+ }
+ }
+
+ printf("GHOST: unknown key: %d %d\n", vk, rawCode);
+
+ return GHOST_kKeyUnknown;
+}
+
+/***/
+
+GHOST_SystemCarbon::GHOST_SystemCarbon() :
+ m_modifierMask(0)
+{
+ m_displayManager = new GHOST_DisplayManagerCarbon ();
+ GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n");
+ m_displayManager->initialize();
+
+ UnsignedWide micros;
+ ::Microseconds(&micros);
+ UInt64 millis;
+ m_start_time = UnsignedWideToUInt64(micros)/1000;
+}
+
+GHOST_SystemCarbon::~GHOST_SystemCarbon()
+{
+}
+
+
+GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const
+{
+ UnsignedWide micros;
+ ::Microseconds(&micros);
+ UInt64 millis;
+ millis = UnsignedWideToUInt64(micros);
+ return (millis / 1000) - m_start_time;
+}
+
+
+GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const
+{
+ // We do not support multiple monitors at the moment
+ return 1;
+}
+
+
+void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ BitMap screenBits;
+ Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds;
+ width = bnds.right - bnds.left;
+ height = bnds.bottom - bnds.top;
+}
+
+
+GHOST_IWindow* GHOST_SystemCarbon::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
+)
+{
+ GHOST_IWindow* window = 0;
+ window = new GHOST_WindowCarbon (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);
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
+ }
+ else {
+ GHOST_PRINT("GHOST_SystemCarbon::createWindow(): window invalid\n");
+ delete window;
+ window = 0;
+ }
+ }
+ else {
+ GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n");
+ }
+ return window;
+}
+
+
+bool GHOST_SystemCarbon::processEvents(bool waitForEvent)
+{
+ bool anyProcessed = false;
+ EventRef event;
+
+ do {
+ GHOST_TimerManager* timerMgr = getTimerManager();
+
+ if (waitForEvent) {
+ GHOST_TUns64 curtime = getMilliSeconds();
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+ double timeOut;
+
+ if (next == GHOST_kFireTimeNever) {
+ timeOut = kEventDurationForever;
+ } else {
+ if (next<=curtime)
+ timeOut = 0.0;
+ else
+ timeOut = (double) (next - getMilliSeconds())/1000.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;
+ }
+ }
+
+ while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) {
+ OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget());
+ if (status==noErr) {
+ anyProcessed = true;
+ } else {
+ UInt32 i= ::GetEventClass(event);
+
+ /* Ignore 'cgs ' class, no documentation on what they
+ * are, but we get a lot of them
+ */
+ if (i!='cgs ') {
+ //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event));
+ }
+ }
+ ::ReleaseEvent(event);
+ }
+ } while (waitForEvent && !anyProcessed);
+
+ return anyProcessed;
+}
+
+
+GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
+{
+ Point mouseLoc;
+ // Get the position of the mouse in the active port
+ ::GetGlobalMouse(&mouseLoc);
+ // Convert the coordinates to screen coordinates
+ x = (GHOST_TInt32)mouseLoc.h;
+ y = (GHOST_TInt32)mouseLoc.v;
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/) const
+{
+ // Not supported in Carbon!
+ return GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const
+{
+ UInt32 modifiers = ::GetCurrentKeyModifiers();
+
+ keys.set(GHOST_kModifierKeyCommand, (modifiers & cmdKey) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false);
+ keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false);
+
+ return GHOST_kSuccess;
+}
+
+ /* XXX, incorrect for multibutton mice */
+GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const
+{
+ Boolean theOnlyButtonIsDown = ::Button();
+ buttons.clear();
+ buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown);
+ return GHOST_kSuccess;
+}
+
+static bool g_hasFirstFile = false;
+static char g_firstFileBuf[512];
+
+extern "C" int GHOST_HACK_getFirstFile(char buf[512]) {
+ if (g_hasFirstFile) {
+ strcpy(buf, g_firstFileBuf);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+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;
+}
+
+
+GHOST_TSuccess GHOST_SystemCarbon::init()
+{
+ GHOST_TSuccess success = GHOST_System::init();
+ if (success) {
+ /*
+ * Initialize the cursor to the standard arrow shape (so that we can change it later on).
+ * This initializes the cursor's visibility counter to 0.
+ */
+ ::InitCursor();
+
+ MenuRef windMenu;
+ ::CreateStandardWindowMenu(0, &windMenu);
+ ::InsertMenu(windMenu, 0);
+ ::DrawMenuBar();
+
+ ::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler);
+
+ ::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false);
+ ::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false);
+ ::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false);
+ ::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false);
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_SystemCarbon::exit()
+{
+ return GHOST_System::exit();
+}
+
+
+OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event)
+{
+ GHOST_WindowCarbon *window;
+
+ if (!getFullScreen()) {
+ WindowRef windowref;
+ ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowref);
+ window = (GHOST_WindowCarbon*) ::GetWRefCon(windowref);
+
+ if (validWindow(window)) {
+ switch(::GetEventKind(event))
+ {
+ case kEventWindowClose:
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
+ break;
+ case kEventWindowActivated:
+ m_windowManager->setActiveWindow(window);
+ window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
+ break;
+ case kEventWindowDeactivated:
+ m_windowManager->setWindowInactive(window);
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
+ break;
+ case kEventWindowUpdate:
+ //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n");
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
+ break;
+ case kEventWindowBoundsChanged:
+ window->updateDrawingContext();
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ break;
+ }
+ }
+ }
+ //else {
+ //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow();
+ //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n");
+ //::RemoveEventFromQueue(::GetMainEventQueue(), event);
+ //}
+
+ return noErr;
+}
+
+OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event)
+{
+ GHOST_IWindow* window = m_windowManager->getActiveWindow();
+ UInt32 kind = ::GetEventKind(event);
+
+ switch (kind)
+ {
+ case kEventMouseDown:
+ case kEventMouseUp:
+ // Handle Mac application responsibilities
+ if ((kind == kEventMouseDown) && handleMouseDown(event)) {
+ ;
+ } else {
+ GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp;
+ EventMouseButton button;
+
+ /* Window still gets mouse up after command-H */
+ if (window) {
+ ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
+ pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button)));
+ }
+ }
+ break;
+
+ case kEventMouseMoved:
+ case kEventMouseDragged:
+ Point mousePos;
+ if (window) {
+ ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
+ pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v));
+ }
+ break;
+ }
+
+ return noErr;
+}
+
+
+OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event)
+{
+ GHOST_IWindow* window = m_windowManager->getActiveWindow();
+ UInt32 kind = ::GetEventKind(event);
+ UInt32 modifiers;
+ UInt32 rawCode;
+ GHOST_TKey key;
+ 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) {
+ ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
+ key = convertKey(rawCode);
+ return noErr;
+ }
+
+ switch (kind) {
+ case kEventRawKeyDown:
+ case kEventRawKeyRepeat:
+ case kEventRawKeyUp:
+ ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
+ ::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii);
+ key = convertKey(rawCode);
+ if (key!=GHOST_kKeyUnknown) {
+ GHOST_TEventType type;
+ if (kind == kEventRawKeyDown) {
+ type = GHOST_kEventKeyDown;
+ } else if (kind == kEventRawKeyRepeat) {
+ type = GHOST_kEventKeyDown; /* XXX, fixme */
+ } else {
+ type = GHOST_kEventKeyUp;
+ }
+ pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) );
+ }
+ break;
+
+ case kEventRawKeyModifiersChanged:
+ /* ugh */
+ ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
+ if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
+ }
+ if ((modifiers & controlKey) != (m_modifierMask & controlKey)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
+ }
+ if ((modifiers & optionKey) != (m_modifierMask & optionKey)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
+ }
+ if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) {
+ pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
+ }
+
+ m_modifierMask = modifiers;
+ break;
+ }
+
+ return noErr;
+}
+
+
+bool GHOST_SystemCarbon::handleMouseDown(EventRef event)
+{
+ WindowPtr window;
+ short part;
+ BitMap screenBits;
+ bool handled = true;
+ GHOST_IWindow* ghostWindow;
+ Point mousePos = {0 , 0};
+
+ ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
+
+ part = ::FindWindow(mousePos, &window);
+ ghostWindow = (GHOST_IWindow*) ::GetWRefCon(window);
+ GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseEvent: invalid window");
+
+ switch (part) {
+ case inMenuBar:
+ handleMenuCommand(::MenuSelect(mousePos));
+ break;
+
+ case inDrag:
+ ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds);
+ break;
+
+ case inContent:
+ if (window != ::FrontWindow()) {
+ ::SelectWindow(window);
+ } else {
+ handled = false;
+ }
+ break;
+
+ case inGoAway:
+ GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
+ if (::TrackGoAway(window, mousePos))
+ {
+ // todo: add option-close, because itÕs in the HIG
+ // if (event.modifiers & optionKey) {
+ // Close the clean documents, others will be confirmed one by one.
+ //}
+ // else {
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow));
+ //}
+ }
+ break;
+
+ case inGrow:
+ GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
+ ::ResizeWindow(window, mousePos, NULL, NULL);
+ break;
+
+ case inZoomIn:
+ case inZoomOut:
+ GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
+ if (::TrackBox(window, mousePos, part)) {
+ ::ZoomWindow(window, part, true);
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+
+ return handled;
+}
+
+
+bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult)
+{
+ short menuID;
+ short menuItem;
+ UInt32 command;
+ bool handled;
+ OSErr err;
+
+ menuID = HiWord(menuResult);
+ menuItem = LoWord(menuResult);
+
+ err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command);
+
+ handled = false;
+
+ if (err || command == 0) {
+ }
+ else {
+ switch(command) {
+ }
+ }
+
+ ::HiliteMenu(0);
+ return handled;
+}
+
+OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData)
+{
+ GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData;
+ OSStatus err = eventNotHandledErr;
+
+ switch (::GetEventClass(event))
+ {
+ case kEventClassAppleEvent:
+ EventRecord eventrec;
+ if (ConvertEventRefToEventRecord(event, &eventrec)) {
+ err = AEProcessAppleEvent(&eventrec);
+ }
+ break;
+ case kEventClassMouse:
+ err = sys->handleMouseEvent(event);
+ break;
+ case kEventClassWindow:
+ err = sys->handleWindowEvent(event);
+ break;
+ case kEventClassKeyboard:
+ err = sys->handleKeyEvent(event);
+ break;
+ }
+
+ return err;
+}
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h
new file mode 100644
index 00000000000..17c09e8e91f
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemCarbon.h
@@ -0,0 +1,251 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _GHOST_SYSTEM_CARBON_H_
+#define _GHOST_SYSTEM_CARBON_H_
+
+#ifndef __APPLE__
+#error Apple OSX only!
+#endif // __APPLE__
+
+#include <Carbon/Carbon.h>
+
+#include "GHOST_System.h"
+
+
+class GHOST_EventCursor;
+class GHOST_EventKey;
+class GHOST_EventWindow;
+
+/**
+ * OSX/Carbon Implementation of GHOST_System class.
+ * @see GHOST_System.
+ * @author Maarten Gribnau
+ * @date May 21, 2001
+ */
+class GHOST_SystemCarbon : public GHOST_System {
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_SystemCarbon::GHOST_SystemCarbon();
+
+ /**
+ * Destructor.
+ */
+ GHOST_SystemCarbon::~GHOST_SystemCarbon();
+
+ /***************************************************************************************
+ ** Time(r) functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * Based on ANSI clock() routine.
+ * @return The number of milliseconds.
+ */
+ virtual GHOST_TUns64 getMilliSeconds() const;
+
+ /***************************************************************************************
+ ** Display/window management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the number of displays on this system.
+ * @return The number of displays.
+ */
+ virtual GHOST_TUns8 getNumDisplays() const;
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @return The new window (or 0 if creation failed).
+ */
+ virtual GHOST_IWindow* createWindow(
+ 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
+ );
+
+ /***************************************************************************************
+ ** Event management functionality
+ ***************************************************************************************/
+
+ /**
+ * Gets events from the system and stores them in the queue.
+ * @param waitForEvent Flag to wait for an event (or return immediately).
+ * @return Indication of the presence of events.
+ */
+ virtual bool processEvents(bool waitForEvent);
+
+ /***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the current location of the cursor (location in screen coordinates)
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+
+ /**
+ * Updates the location of the cursor (location in screen coordinates).
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const;
+
+ /***************************************************************************************
+ ** Access to mouse button and keyboard states.
+ ***************************************************************************************/
+
+ /**
+ * Returns the state of all modifier keys.
+ * @param keys The state of all modifier keys (true == pressed).
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+
+ /**
+ * Returns the state of the mouse buttons (ouside the message queue).
+ * @param buttons The state of the buttons.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+
+protected:
+ /**
+ * Initializes the system.
+ * For now, it justs registers the window class (WNDCLASS).
+ * @return A success value.
+ */
+ virtual GHOST_TSuccess init();
+
+ /**
+ * Closes the system down.
+ * @return A success value.
+ */
+ virtual GHOST_TSuccess exit();
+
+ /**
+ * Handles a mouse event.
+ * @param event A Mac event.
+ * @return Indication whether the event was handled.
+ */
+ OSStatus handleMouseEvent(EventRef event);
+
+ /**
+ * Handles a key event.
+ * @param event A Mac event.
+ * @return Indication whether the event was handled.
+ */
+ OSStatus handleKeyEvent(EventRef event);
+
+ /**
+ * Handles a window event.
+ * @param event A Mac event.
+ * @return Indication whether the event was handled.
+ */
+ OSStatus handleWindowEvent(EventRef event);
+
+ /**
+ * Handles all basic Mac application stuff for a mouse down event.
+ * @param event A Mac event.
+ * @return Indication whether the event was handled.
+ */
+ bool handleMouseDown(EventRef event);
+
+ /**
+ * Handles a Mac menu command.
+ * @param menuResult A Mac menu/item identifier.
+ * @return Indication whether the event was handled.
+ */
+ bool handleMenuCommand(GHOST_TInt32 menuResult);
+
+ /**
+ * Callback for Carbon when it has events.
+ */
+ static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
+
+ /** Apple Event Handlers */
+ static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
+ static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
+ static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
+ static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
+
+ /**
+ * Callback for Mac Timer tasks that expire.
+ * @param tmTask Pointer to the timer task that expired.
+ */
+ //static void s_timerCallback(TMTaskPtr tmTask);
+
+ /** Event handler reference. */
+ EventHandlerRef m_handler;
+
+ /** Start time at initialization. */
+ GHOST_TUns64 m_start_time;
+
+ /** State of the modifiers. */
+ UInt32 m_modifierMask;
+};
+
+#endif // _GHOST_SYSTEM_CARBON_H_
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
new file mode 100644
index 00000000000..099706b7e82
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -0,0 +1,65 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 22, 2001
+ */
+
+#ifndef _GHOST_SYSTEM_CARBON_H_
+#define _GHOST_SYSTEM_CARBON_H_
+
+#ifndef __APPLE__
+#error Apple OSX only!
+#endif // __APPLE__
+
+#include "GHOST_System.h"
+#include "GHOST_Keys.h"
+
+#include <Carbon/Carbon.h>
+
+class GHOST_EventCursor;
+class GHOST_EventKey;
+class GHOST_EventWindow;
+
+/**
+ * OSX/Cocoa Implementation of GHOST_System class.
+ * @see GHOST_System.
+ * @author Maarten Gribnau
+ * @date May 21, 2001
+ */
+class GHOST_SystemCarbon : public GHOST_System {
+};
+
+#endif // _GHOST_SYSTEM_CARBON_H_
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
new file mode 100644
index 00000000000..6dc00bd1847
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -0,0 +1,817 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#include "GHOST_SystemWin32.h"
+
+
+#include "GHOST_Debug.h"
+#include "GHOST_DisplayManagerWin32.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_TimerTask.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_WindowManager.h"
+#include "GHOST_WindowWin32.h"
+
+// Key code values not found in winuser.h
+#ifndef VK_MINUS
+#define VK_MINUS 0xBD
+#endif // VK_MINUS
+#ifndef VK_SEMICOLON
+#define VK_SEMICOLON 0xBA
+#endif // VK_SEMICOLON
+#ifndef VK_PERIOD
+#define VK_PERIOD 0xBE
+#endif // VK_PERIOD
+#ifndef VK_COMMA
+#define VK_COMMA 0xBC
+#endif // VK_COMMA
+#ifndef VK_QUOTE
+#define VK_QUOTE 0xDE
+#endif // VK_QUOTE
+#ifndef VK_BACK_QUOTE
+#define VK_BACK_QUOTE 0xC0
+#endif // VK_BACK_QUOTE
+#ifndef VK_SLASH
+#define VK_SLASH 0xBF
+#endif // VK_SLASH
+#ifndef VK_BACK_SLASH
+#define VK_BACK_SLASH 0xDC
+#endif // VK_BACK_SLASH
+#ifndef VK_EQUALS
+#define VK_EQUALS 0xBB
+#endif // VK_EQUALS
+#ifndef VK_OPEN_BRACKET
+#define VK_OPEN_BRACKET 0xDB
+#endif // VK_OPEN_BRACKET
+#ifndef VK_CLOSE_BRACKET
+#define VK_CLOSE_BRACKET 0xDD
+#endif // VK_CLOSE_BRACKET
+
+
+GHOST_SystemWin32::GHOST_SystemWin32()
+: m_hasPerformanceCounter(false), m_freq(0), m_start(0),
+ m_seperateLeftRight(false),
+ m_seperateLeftRightInitialized(false)
+{
+ m_displayManager = new GHOST_DisplayManagerWin32 ();
+ GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
+ m_displayManager->initialize();
+}
+
+GHOST_SystemWin32::~GHOST_SystemWin32()
+{
+}
+
+
+GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
+{
+ // Hardware does not support high resolution timers. We will use GetTickCount instead then.
+ if (!m_hasPerformanceCounter) {
+ return ::GetTickCount();
+ }
+
+ // Retrieve current count
+ __int64 count = 0;
+ ::QueryPerformanceCounter((LARGE_INTEGER*)&count);
+
+ // Calculate the time passed since system initialization.
+ __int64 delta = 1000*(count-m_start);
+
+ GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq);
+ return t;
+}
+
+
+GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
+{
+ GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
+ GHOST_TUns8 numDisplays;
+ m_displayManager->getNumDisplays(numDisplays);
+ return numDisplays;
+}
+
+
+void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ width = ::GetSystemMetrics(SM_CXSCREEN);
+ height= ::GetSystemMetrics(SM_CYSCREEN);
+}
+
+
+GHOST_IWindow* GHOST_SystemWin32::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)
+{
+ GHOST_Window* window = 0;
+ window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual);
+ if (window) {
+ if (window->getValid()) {
+ // Store the pointer to the window
+ if (state != GHOST_kWindowStateFullScreen) {
+ m_windowManager->addWindow(window);
+ }
+ }
+ else {
+ delete window;
+ window = 0;
+ }
+ }
+ return window;
+}
+
+
+bool GHOST_SystemWin32::processEvents(bool waitForEvent)
+{
+ MSG msg;
+ bool anyProcessed = false;
+
+ do {
+ GHOST_TimerManager* timerMgr = getTimerManager();
+
+ if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
+#if 1
+ ::Sleep(1);
+#else
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+
+ if (next == GHOST_kFireTimeNever) {
+ ::WaitMessage();
+ } else {
+ ::SetTimer(NULL, 0, next - getMilliSeconds(), NULL);
+ ::WaitMessage();
+ ::KillTimer(NULL, 0);
+ }
+#endif
+ }
+
+ if (timerMgr->fireTimers(getMilliSeconds())) {
+ anyProcessed = true;
+ }
+
+ // Process all the events waiting for us
+ while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ anyProcessed = true;
+ }
+ } while (waitForEvent && !anyProcessed);
+
+ return anyProcessed;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
+{
+ POINT point;
+ bool success = ::GetCursorPos(&point) == TRUE;
+ x = point.x;
+ y = point.y;
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
+{
+ return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
+{
+ /*
+ GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4,
+ Terminal Server and Windows 2000.
+ But on WinME it always returns zero. These two functions are simply
+ skipped by Millenium Edition!
+
+ Official explanation from Microsoft:
+ Intentionally disabled.
+ It didn't work all that well on some newer hardware, and worked less
+ well with the passage of time, so it was fully disabled in ME.
+ */
+ if (m_seperateLeftRight && m_seperateLeftRightInitialized) {
+ bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
+ keys.set(GHOST_kModifierKeyLeftShift, down);
+ down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
+ keys.set(GHOST_kModifierKeyRightShift, down);
+ down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
+ keys.set(GHOST_kModifierKeyLeftAlt, down);
+ down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
+ keys.set(GHOST_kModifierKeyRightAlt, down);
+ down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
+ keys.set(GHOST_kModifierKeyLeftControl, down);
+ down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
+ keys.set(GHOST_kModifierKeyRightControl, down);
+ }
+ else {
+ bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
+ keys.set(GHOST_kModifierKeyLeftShift, down);
+ keys.set(GHOST_kModifierKeyRightShift, down);
+ down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
+ keys.set(GHOST_kModifierKeyLeftAlt, down);
+ keys.set(GHOST_kModifierKeyRightAlt, down);
+ down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
+ keys.set(GHOST_kModifierKeyLeftControl, down);
+ keys.set(GHOST_kModifierKeyRightControl, down);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
+{
+ /* Check for swapped buttons (left-handed mouse buttons)
+ * GetAsyncKeyState() will give back the state of the physical mouse buttons.
+ */
+ bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
+
+ bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
+ buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
+
+ down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
+ buttons.set(GHOST_kButtonMaskMiddle, down);
+
+ down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
+ buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::init()
+{
+ GHOST_TSuccess success = GHOST_System::init();
+
+ // Determine whether this system has a high frequency performance counter. */
+ m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
+ if (m_hasPerformanceCounter) {
+ GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
+ ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
+ }
+ else {
+ GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
+ }
+
+ if (success) {
+ WNDCLASS wc;
+ wc.style= CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc= s_wndProc;
+ wc.cbClsExtra= 0;
+ wc.cbWndExtra= 0;
+ wc.hInstance= ::GetModuleHandle(0);
+ wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
+ if (!wc.hIcon) {
+ ::LoadIcon(NULL, IDI_APPLICATION);
+ }
+ wc.hCursor = ::LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
+
+ // Use RegisterClassEx for setting small icon
+ if (::RegisterClass(&wc) == 0) {
+ success = GHOST_kFailure;
+ }
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_SystemWin32::exit()
+{
+ return GHOST_System::exit();
+}
+
+
+GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
+{
+ GHOST_TKey key;
+ bool isExtended = (lParam&(1<<24))?true:false;
+
+ if ((wParam >= '0') && (wParam <= '9')) {
+ // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
+ key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
+ }
+ else if ((wParam >= 'A') && (wParam <= 'Z')) {
+ // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
+ key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
+ }
+ else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
+ key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
+ }
+ else {
+ switch (wParam) {
+ case VK_RETURN:
+ key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
+ break;
+
+ case VK_BACK: key = GHOST_kKeyBackSpace; break;
+ case VK_TAB: key = GHOST_kKeyTab; break;
+ case VK_ESCAPE: key = GHOST_kKeyEsc; break;
+ case VK_SPACE: key = GHOST_kKeySpace; break;
+ case VK_PRIOR: key = GHOST_kKeyUpPage; break;
+ case VK_NEXT: key = GHOST_kKeyDownPage; break;
+ case VK_END: key = GHOST_kKeyEnd; break;
+ case VK_HOME: key = GHOST_kKeyHome; break;
+ case VK_INSERT: key = GHOST_kKeyInsert; break;
+ case VK_DELETE: key = GHOST_kKeyDelete; break;
+ case VK_LEFT: key = GHOST_kKeyLeftArrow; break;
+ case VK_RIGHT: key = GHOST_kKeyRightArrow; break;
+ case VK_UP: key = GHOST_kKeyUpArrow; break;
+ case VK_DOWN: key = GHOST_kKeyDownArrow; break;
+ case VK_NUMPAD0: key = GHOST_kKeyNumpad0; break;
+ case VK_NUMPAD1: key = GHOST_kKeyNumpad1; break;
+ case VK_NUMPAD2: key = GHOST_kKeyNumpad2; break;
+ case VK_NUMPAD3: key = GHOST_kKeyNumpad3; break;
+ case VK_NUMPAD4: key = GHOST_kKeyNumpad4; break;
+ case VK_NUMPAD5: key = GHOST_kKeyNumpad5; break;
+ case VK_NUMPAD6: key = GHOST_kKeyNumpad6; break;
+ case VK_NUMPAD7: key = GHOST_kKeyNumpad7; break;
+ case VK_NUMPAD8: key = GHOST_kKeyNumpad8; break;
+ case VK_NUMPAD9: key = GHOST_kKeyNumpad9; break;
+ case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen; break;
+ case VK_PAUSE: key = GHOST_kKeyPause; break;
+ case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break;
+ case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus; break;
+ case VK_DECIMAL: key = GHOST_kKeyNumpadPeriod; break;
+ case VK_DIVIDE: key = GHOST_kKeyNumpadSlash; break;
+ case VK_ADD: key = GHOST_kKeyNumpadPlus; break;
+
+ case VK_SEMICOLON: key = GHOST_kKeySemicolon; break;
+ case VK_EQUALS: key = GHOST_kKeyEqual; break;
+ case VK_COMMA: key = GHOST_kKeyComma; break;
+ case VK_MINUS: key = GHOST_kKeyMinus; break;
+ case VK_PERIOD: key = GHOST_kKeyPeriod; break;
+ case VK_SLASH: key = GHOST_kKeySlash; break;
+ case VK_BACK_QUOTE: key = GHOST_kKeyAccentGrave; break;
+ case VK_OPEN_BRACKET: key = GHOST_kKeyLeftBracket; break;
+ case VK_BACK_SLASH: key = GHOST_kKeyBackslash; break;
+ case VK_CLOSE_BRACKET: key = GHOST_kKeyRightBracket; break;
+ case VK_QUOTE: key = GHOST_kKeyQuote; break;
+
+ // Process these keys separately because we need to distinguish right from left modifier keys
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_MENU:
+
+ // Ignore these keys
+ case VK_NUMLOCK:
+ case VK_SCROLL:
+ case VK_CAPITAL:
+ default:
+ key = GHOST_kKeyUnknown;
+ break;
+ }
+ }
+ return key;
+}
+
+
+void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
+{
+ GHOST_ModifierKeys oldModifiers, newModifiers;
+ // Retrieve old state of the modifier keys
+ ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
+ // Retrieve current state of the modifier keys
+ ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
+
+ // Compare the old and the new
+ if (!newModifiers.equals(oldModifiers)) {
+ // Create events for the masks that changed
+ for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
+ if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
+ // Convert the mask to a key code
+ GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
+ bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
+ GHOST_EventKey* event;
+ if (key != GHOST_kKeyUnknown) {
+ // Create an event
+ event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
+ pushEvent(event);
+ }
+ }
+ }
+ }
+
+ // Store new modifier keys state
+ ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
+}
+
+
+GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
+{
+ return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
+}
+
+
+GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
+{
+ GHOST_TInt32 x, y;
+ getSystem()->getCursorPosition(x, y);
+ return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
+}
+
+
+GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
+{
+ GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam);
+ GHOST_EventKey* event;
+ if (key != GHOST_kKeyUnknown) {
+ MSG keyMsg;
+ char ascii = '\0';
+
+ /* Eat any character related messages */
+ if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
+ ascii = (char) keyMsg.wParam;
+ }
+
+ event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
+ }
+ else {
+ event = 0;
+ }
+ return event;
+}
+
+
+GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
+{
+ return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
+}
+
+
+LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ GHOST_Event* event = 0;
+ LRESULT lResult;
+ GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
+ GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
+
+ if (hwnd) {
+ GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
+ if (window) {
+ switch (msg) {
+ ////////////////////////////////////////////////////////////////////////
+ // Keyboard events, processed
+ ////////////////////////////////////////////////////////////////////////
+ case WM_KEYDOWN:
+ /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a
+ * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
+ * key is not pressed.
+ */
+ case WM_SYSKEYDOWN:
+ /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when
+ * the user presses the F10 key (which activates the menu bar) or holds down the
+ * alt key and then presses another key. It also occurs when no window currently
+ * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the
+ * active window. The window that receives the message can distinguish between these
+ * two contexts by checking the context code in the lKeyData parameter.
+ */
+ switch (wParam) {
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_MENU:
+ if (!system->m_seperateLeftRightInitialized) {
+ // Check whether this system supports seperate left and right keys
+ switch (wParam) {
+ case VK_SHIFT:
+ system->m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
+ true : false;
+ break;
+ case VK_CONTROL:
+ system->m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
+ true : false;
+ break;
+ case VK_MENU:
+ system->m_seperateLeftRight =
+ (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
+ (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
+ true : false;
+ break;
+ }
+ system->m_seperateLeftRightInitialized = true;
+ }
+ system->processModifierKeys(window);
+ // Bypass call to DefWindowProc
+ return 0;
+ default:
+ event = processKeyEvent(window, true, wParam, lParam);
+ if (!event) {
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
+ GHOST_PRINT(msg)
+ GHOST_PRINT(" key ignored\n")
+ }
+ break;
+ }
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ switch (wParam) {
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_MENU:
+ system->processModifierKeys(window);
+ // Bypass call to DefWindowProc
+ return 0;
+ default:
+ event = processKeyEvent(window, false, wParam, lParam);
+ if (!event) {
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
+ GHOST_PRINT(msg)
+ GHOST_PRINT(" key ignored\n")
+ }
+ break;
+ }
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Keyboard events, ignored
+ ////////////////////////////////////////////////////////////////////////
+ case WM_CHAR:
+ /* The WM_CHAR message is posted to the window with the keyboard focus when
+ * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
+ * contains the character code of the key that was pressed.
+ */
+ case WM_DEADCHAR:
+ /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
+ * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR
+ * specifies a character code generated by a dead key. A dead key is a key that
+ * generates a character, such as the umlaut (double-dot), that is combined with
+ * another character to form a composite character. For example, the umlaut-O
+ * character (Ö) is generated by typing the dead key for the umlaut character, and
+ * then typing the O key.
+ */
+ case WM_SYSDEADCHAR:
+ /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
+ * a WM_SYSKEYDOWN message is translated by the TranslateMessage function.
+ * WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
+ * a dead key that is pressed while holding down the alt key.
+ */
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Mouse events, processed
+ ////////////////////////////////////////////////////////////////////////
+ case WM_LBUTTONDOWN:
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
+ break;
+ case WM_MBUTTONDOWN:
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
+ break;
+ case WM_RBUTTONDOWN:
+ window->registerMouseClickEvent(true);
+ event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
+ break;
+ case WM_LBUTTONUP:
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
+ break;
+ case WM_MBUTTONUP:
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
+ break;
+ case WM_RBUTTONUP:
+ window->registerMouseClickEvent(false);
+ event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
+ break;
+ case WM_MOUSEMOVE:
+ event = processCursorEvent(GHOST_kEventCursorMove, window);
+ break;
+ case WM_SETCURSOR:
+ /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
+ * to move within a window and mouse input is not captured.
+ * This means we have to set the cursor shape every time the mouse moves!
+ * The DefWindowProc function uses this message to set the cursor to an
+ * arrow if it is not in the client area.
+ */
+ if (LOWORD(lParam) == HTCLIENT) {
+ // Load the current cursor
+ window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
+ // Bypass call to DefWindowProc
+ return 0;
+ }
+ else {
+ // Outside of client area show standard cursor
+ window->loadCursor(true, GHOST_kStandardCursorDefault);
+ }
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Mouse events, ignored
+ ////////////////////////////////////////////////////////////////////////
+ case WM_NCMOUSEMOVE:
+ /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
+ * within the nonclient area of the window. This message is posted to the window
+ * that contains the cursor. If a window has captured the mouse, this message is not posted.
+ */
+ case WM_NCHITTEST:
+ /* The WM_NCHITTEST message is sent to a window when the cursor moves, or
+ * when a mouse button is pressed or released. If the mouse is not captured,
+ * the message is sent to the window beneath the cursor. Otherwise, the message
+ * is sent to the window that has captured the mouse.
+ */
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Window events, processed
+ ////////////////////////////////////////////////////////////////////////
+ case WM_CLOSE:
+ /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
+ event = processWindowEvent(GHOST_kEventWindowClose, window);
+ break;
+ case WM_ACTIVATE:
+ /* The WM_ACTIVATE message is sent to both the window being activated and the window being
+ * deactivated. If the windows use the same input queue, the message is sent synchronously,
+ * first to the window procedure of the top-level window being deactivated, then to the window
+ * procedure of the top-level window being activated. If the windows use different input queues,
+ * the message is sent asynchronously, so the window is activated immediately.
+ */
+ event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
+ break;
+ case WM_PAINT:
+ /* An application sends the WM_PAINT message when the system or another application
+ * makes a request to paint a portion of an application's window. The message is sent
+ * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
+ * function when the application obtains a WM_PAINT message by using the GetMessage or
+ * PeekMessage function.
+ */
+ event = processWindowEvent(GHOST_kEventWindowUpdate, window);
+ ::ValidateRect(hwnd, NULL);
+ break;
+ case WM_SIZE:
+ /* The WM_SIZE message is sent to a window after its size has changed.
+ * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
+ * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
+ * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
+ * message without calling DefWindowProc.
+ */
+ event = processWindowEvent(GHOST_kEventWindowSize, window);
+ case WM_CAPTURECHANGED:
+ window->lostMouseCapture();
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Window events, ignored
+ ////////////////////////////////////////////////////////////////////////
+ case WM_WINDOWPOSCHANGED:
+ /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
+ * in the Z order has changed as a result of a call to the SetWindowPos function or
+ * another window-management function.
+ * The WM_SIZE and WM_MOVE messages are not sent if an application handles the
+ * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
+ * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
+ * message without calling DefWindowProc.
+ */
+ case WM_MOVE:
+ /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
+ * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
+ * to perform any move or size change processing during the WM_WINDOWPOSCHANGED
+ * message without calling DefWindowProc.
+ */
+ case WM_ERASEBKGND:
+ /* An application sends the WM_ERASEBKGND message when the window background must be
+ * erased (for example, when a window is resized). The message is sent to prepare an
+ * invalidated portion of a window for painting.
+ */
+ case WM_NCPAINT:
+ /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
+ case WM_NCACTIVATE:
+ /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed
+ * to indicate an active or inactive state.
+ */
+ case WM_DESTROY:
+ /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window
+ * procedure of the window being destroyed after the window is removed from the screen.
+ * This message is sent first to the window being destroyed and then to the child windows
+ * (if any) as they are destroyed. During the processing of the message, it can be assumed
+ * that all child windows still exist.
+ */
+ case WM_NCDESTROY:
+ /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The
+ * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
+ * message. WM_DESTROY is used to free the allocated memory object associated with the window.
+ */
+ case WM_KILLFOCUS:
+ /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
+ case WM_SHOWWINDOW:
+ /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
+ case WM_WINDOWPOSCHANGING:
+ /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in
+ * the Z order is about to change as a result of a call to the SetWindowPos function or
+ * another window-management function.
+ */
+ case WM_SETFOCUS:
+ /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
+ case WM_MOVING:
+ /* The WM_MOVING message is sent to a window that the user is moving. By processing
+ * this message, an application can monitor the size and position of the drag rectangle
+ * and, if needed, change its size or position.
+ */
+ case WM_ENTERSIZEMOVE:
+ /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving
+ * or sizing modal loop. The window enters the moving or sizing modal loop when the user
+ * clicks the window's title bar or sizing border, or when the window passes the
+ * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the
+ * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when
+ * DefWindowProc returns.
+ */
+ break;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Other events
+ ////////////////////////////////////////////////////////////////////////
+ case WM_GETTEXT:
+ /* An application sends a WM_GETTEXT message to copy the text that
+ * corresponds to a window into a buffer provided by the caller.
+ */
+ case WM_ACTIVATEAPP:
+ /* The WM_ACTIVATEAPP message is sent when a window belonging to a
+ * different application than the active window is about to be activated.
+ * The message is sent to the application whose window is being activated
+ * and to the application whose window is being deactivated.
+ */
+ case WM_TIMER:
+ /* The WIN32 docs say:
+ * The WM_TIMER message is posted to the installing thread's message queue
+ * when a timer expires. You can process the message by providing a WM_TIMER
+ * case in the window procedure. Otherwise, the default window procedure will
+ * call the TimerProc callback function specified in the call to the SetTimer
+ * function used to install the timer.
+ *
+ * In GHOST, we let DefWindowProc call the timer callback.
+ */
+ break;
+ }
+ }
+ else {
+ // Event found for a window before the pointer to the class has been set.
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
+ /* These are events we typically miss at this point:
+ WM_GETMINMAXINFO 0x24
+ WM_NCCREATE 0x81
+ WM_NCCALCSIZE 0x83
+ WM_CREATE 0x01
+ We let DefWindowProc do the work.
+ */
+ }
+ }
+ else {
+ // Events without valid hwnd
+ GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
+ }
+
+ if (event) {
+ system->pushEvent(event);
+ lResult = 0;
+ }
+ else {
+ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return lResult;
+}
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
new file mode 100644
index 00000000000..ac1a7eb6ac5
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -0,0 +1,278 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _GHOST_SYSTEM_WIN32_H_
+#define _GHOST_SYSTEM_WIN32_H_
+
+#ifndef WIN32
+#error WIN32 only!
+#endif // WIN32
+
+#include "GHOST_System.h"
+
+#include <windows.h>
+
+#if defined(__CYGWIN32__)
+# define __int64 long long
+#endif
+
+
+class GHOST_EventButton;
+class GHOST_EventCursor;
+class GHOST_EventKey;
+class GHOST_EventWindow;
+
+/**
+ * WIN32 Implementation of GHOST_System class.
+ * @see GHOST_System.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+class GHOST_SystemWin32 : public GHOST_System {
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_SystemWin32();
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_SystemWin32();
+
+ /***************************************************************************************
+ ** Time(r) functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * This overloaded method uses the high frequency timer if available.
+ * @return The number of milliseconds.
+ */
+ virtual GHOST_TUns64 getMilliSeconds() const;
+
+ /***************************************************************************************
+ ** Display/window management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the number of displays on this system.
+ * @return The number of displays.
+ */
+ virtual GHOST_TUns8 getNumDisplays() const;
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @return The new window (or 0 if creation failed).
+ */
+ virtual GHOST_IWindow* createWindow(
+ 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);
+
+ /***************************************************************************************
+ ** Event management functionality
+ ***************************************************************************************/
+
+ /**
+ * Gets events from the system and stores them in the queue.
+ * @param waitForEvent Flag to wait for an event (or return immediately).
+ * @return Indication of the presence of events.
+ */
+ virtual bool processEvents(bool waitForEvent);
+
+
+ /***************************************************************************************
+ ** Cursor management functionality
+ ***************************************************************************************/
+
+ /**
+ * Returns the current location of the cursor (location in screen coordinates)
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
+
+ /**
+ * Updates the location of the cursor (location in screen coordinates).
+ * @param x The x-coordinate of the cursor.
+ * @param y The y-coordinate of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const;
+
+ /***************************************************************************************
+ ** Access to mouse button and keyboard states.
+ ***************************************************************************************/
+
+ /**
+ * Returns the state of all modifier keys.
+ * @param keys The state of all modifier keys (true == pressed).
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
+
+ /**
+ * Returns the state of the mouse buttons (ouside the message queue).
+ * @param buttons The state of the buttons.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
+
+protected:
+ /**
+ * Initializes the system.
+ * For now, it justs registers the window class (WNDCLASS).
+ * @return A success value.
+ */
+ virtual GHOST_TSuccess init();
+
+ /**
+ * Closes the system down.
+ * @return A success value.
+ */
+ virtual GHOST_TSuccess exit();
+
+ /**
+ * Converts raw WIN32 key codes from the wndproc to GHOST keys.
+ * @param wParam The wParam from the wndproc
+ * @param lParam The lParam from the wndproc
+ * @return The GHOST key (GHOST_kKeyUnknown if no match).
+ */
+ virtual GHOST_TKey convertKey(WPARAM wParam, LPARAM lParam) const;
+
+ /**
+ * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
+ * With the modifier keys, we want to distinguish left and right keys.
+ * Sometimes this is not possible (Windows ME for instance). Then, we want
+ * events generated for both keys.
+ */
+ void processModifierKeys(GHOST_IWindow *window);
+
+ /**
+ * Creates mouse button event.
+ * @param type The type of event to create.
+ * @param type The button mask of this event.
+ * @return The event created.
+ */
+ static GHOST_EventButton* processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask);
+
+ /**
+ * Creates cursor event.
+ * @param type The type of event to create.
+ * @return The event created.
+ */
+ static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window);
+
+ /**
+ * Creates a key event and updates the key data stored locally (m_modifierKeys).
+ * In most cases this is a straightforward conversion of key codes.
+ * For the modifier keys however, we want to distinguish left and right keys.
+ */
+ static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam);
+
+ /**
+ * Creates a window event.
+ * @param type The type of event to create.
+ * @param window The window receiving the event.
+ * @return The event created.
+ */
+ static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
+
+ /**
+ * Returns the local state of the modifier keys (from the message queue).
+ * @param keys The state of the keys.
+ */
+ inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
+
+ /**
+ * Stores the state of the modifier keys locally.
+ * For internal use only!
+ * @param keys The new state of the modifier keys.
+ */
+ inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys);
+
+ /**
+ * Windows call back routine for our window class.
+ */
+ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ /** The current state of the modifier keys. */
+ GHOST_ModifierKeys m_modifierKeys;
+ /** State variable set at initialization. */
+ bool m_hasPerformanceCounter;
+ /** High frequency timer variable. */
+ __int64 m_freq;
+ /** High frequency timer variable. */
+ __int64 m_start;
+ /** Stores the capability of this system to distinguish left and right modifier keys. */
+ bool m_seperateLeftRight;
+ /** Stores the initialization state of the member m_leftRightDistinguishable. */
+ bool m_seperateLeftRightInitialized;
+};
+
+inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
+{
+ keys = m_modifierKeys;
+}
+
+inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys)
+{
+ m_modifierKeys = keys;
+}
+
+#endif // _GHOST_SYSTEM_WIN32_H_
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
new file mode 100755
index 00000000000..77c13d66de2
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -0,0 +1,803 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#include "GHOST_SystemX11.h"
+#include "GHOST_WindowX11.h"
+#include "GHOST_WindowManager.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_DisplayManagerX11.h"
+
+#include "GHOST_Debug.h"
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+// For timing
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <vector>
+
+using namespace std;
+
+GHOST_SystemX11::
+GHOST_SystemX11(
+) :
+ GHOST_System(),
+ m_start_time(0)
+{
+ m_display = XOpenDisplay(NULL);
+
+ if (!m_display) return;
+
+ m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
+
+ // compute the initial time
+ timeval tv;
+ if (gettimeofday(&tv,NULL) == -1) {
+ GHOST_ASSERT(false,"Could not instantiate timer!");
+ }
+
+ m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000);
+}
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+init(
+){
+ GHOST_TSuccess success = GHOST_System::init();
+
+ if (success) {
+ m_keyboard_vector = new char[32];
+
+ m_displayManager = new GHOST_DisplayManagerX11(this);
+
+ if (m_keyboard_vector && m_displayManager) {
+ return GHOST_kSuccess;
+ }
+ }
+
+ return GHOST_kFailure;
+}
+
+
+
+ GHOST_TUns64
+GHOST_SystemX11::
+getMilliSeconds(
+) const {
+ timeval tv;
+ if (gettimeofday(&tv,NULL) == -1) {
+ GHOST_ASSERT(false,"Could not compute time!");
+ }
+
+ return GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time;
+}
+
+ GHOST_TUns8
+GHOST_SystemX11::
+getNumDisplays(
+) const {
+ return GHOST_TUns8(1);
+}
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ void
+GHOST_SystemX11::
+getMainDisplayDimensions(
+ GHOST_TUns32& width,
+ GHOST_TUns32& height
+) const {
+ if (m_display) {
+ width = DisplayWidth(m_display, DefaultScreen(m_display));
+ height = DisplayHeight(m_display, DefaultScreen(m_display));
+ }
+}
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @return The new window (or 0 if creation failed).
+ */
+ GHOST_IWindow*
+GHOST_SystemX11::
+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
+){
+ GHOST_WindowX11 * window = 0;
+
+ if (!m_display) return 0;
+
+ window = new GHOST_WindowX11 (
+ this,m_display,title, left, top, width, height, state, type
+ );
+
+ if (window) {
+
+ // Install a new protocol for this window - so we can overide
+ // the default window closure mechanism.
+
+ XSetWMProtocols(m_display, window->getXWindow(), &m_delete_window_atom, 1);
+
+ if (window->getValid()) {
+ // Store the pointer to the window
+ m_windowManager->addWindow(window);
+
+ pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
+ }
+ else {
+ delete window;
+ window = 0;
+ }
+ }
+ return window;
+
+}
+
+ GHOST_WindowX11 *
+GHOST_SystemX11::
+findGhostWindow(
+ Window xwind
+) const {
+
+ if (xwind == 0) return NULL;
+
+ // It is not entirely safe to do this as the backptr may point
+ // to a window that has recently been removed.
+ // We should always check the window manager's list of windows
+ // and only process events on these windows.
+
+ vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
+
+ for (; win_it != win_end; ++win_it) {
+ GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
+ if (window->getXWindow() == xwind) {
+ return window;
+ }
+ }
+ return NULL;
+
+}
+
+static void SleepTillEvent(Display *display, GHOST_TUns64 maxSleep) {
+ int fd = ConnectionNumber(display);
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ if (maxSleep == -1) {
+ select(fd + 1, &fds, NULL, NULL, NULL);
+ } else {
+ timeval tv;
+
+ tv.tv_sec = maxSleep/1000;
+ tv.tv_usec = (maxSleep - tv.tv_sec*1000)*1000;
+
+ select(fd + 1, &fds, NULL, NULL, &tv);
+ }
+}
+
+ bool
+GHOST_SystemX11::
+processEvents(
+ bool waitForEvent
+){
+ // Get all the current events -- translate them into
+ // ghost events and call base class pushEvent() method.
+
+ bool anyProcessed = false;
+
+ do {
+ GHOST_TimerManager* timerMgr = getTimerManager();
+
+ if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
+ GHOST_TUns64 next = timerMgr->nextFireTime();
+
+ if (next==GHOST_kFireTimeNever) {
+ SleepTillEvent(m_display, -1);
+ } else {
+ SleepTillEvent(m_display, next - getMilliSeconds());
+ }
+ }
+
+ if (timerMgr->fireTimers(getMilliSeconds())) {
+ anyProcessed = true;
+ }
+
+ while (XPending(m_display)) {
+ XEvent xevent;
+ XNextEvent(m_display, &xevent);
+ processEvent(&xevent);
+ anyProcessed = true;
+ }
+
+ if (generateWindowExposeEvents()) {
+ anyProcessed = true;
+ }
+ } while (waitForEvent && !anyProcessed);
+
+ return anyProcessed;
+}
+
+ void
+GHOST_SystemX11::
+processEvent(
+ XEvent *xe
+){
+ GHOST_WindowX11 * window = findGhostWindow(xe->xany.window);
+ GHOST_Event * g_event = NULL;
+
+ if (!window) {
+ return;
+ }
+
+ switch (xe->type) {
+ case Expose:
+ {
+ XExposeEvent & xee = xe->xexpose;
+
+ if (xee.count == 0) {
+ // Only generate a single expose event
+ // per read of the event queue.
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowUpdate,
+ window
+ );
+ }
+ break;
+ }
+ case MotionNotify:
+ {
+ XMotionEvent &xme = xe->xmotion;
+
+ g_event = new
+ GHOST_EventCursor(
+ getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ xme.x_root,
+ xme.y_root
+ );
+ break;
+ }
+
+ case KeyPress:
+ case KeyRelease:
+ {
+ XKeyEvent *xke = &(xe->xkey);
+
+ KeySym key_sym = XLookupKeysym(xke,0);
+ char ascii;
+
+ GHOST_TKey gkey = convertXKey(key_sym);
+ GHOST_TEventType type = (xke->type == KeyPress) ?
+ GHOST_kEventKeyDown : GHOST_kEventKeyUp;
+
+ if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
+ ascii = '\0';
+ }
+
+ g_event = new
+ GHOST_EventKey(
+ getMilliSeconds(),
+ type,
+ window,
+ gkey,
+ ascii
+ );
+
+ break;
+ }
+ case ButtonPress:
+ case ButtonRelease:
+ {
+
+ XButtonEvent & xbe = xe->xbutton;
+ GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
+
+ switch (xbe.button) {
+ case Button1 : gbmask = GHOST_kButtonMaskLeft; break;
+ case Button3 : gbmask = GHOST_kButtonMaskRight; break;
+ default:
+ case Button2 : gbmask = GHOST_kButtonMaskMiddle; break;
+ }
+
+ GHOST_TEventType type = (xbe.type == ButtonPress) ?
+ GHOST_kEventButtonDown : GHOST_kEventButtonUp;
+
+ g_event = new
+ GHOST_EventButton(
+ getMilliSeconds(),
+ type,
+ window,
+ gbmask
+ );
+ break;
+ }
+
+ // change of size, border, layer etc.
+ case ConfigureNotify:
+ {
+ /* XConfigureEvent & xce = xe->xconfigure; */
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowSize,
+ window
+ );
+ break;
+ }
+
+ case FocusIn:
+ case FocusOut:
+ {
+ XFocusChangeEvent &xfe = xe->xfocus;
+
+ // May have to look at the type of event and filter some
+ // out.
+
+ GHOST_TEventType gtype = (xfe.type == FocusIn) ?
+ GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
+
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ gtype,
+ window
+ );
+ break;
+
+ }
+ case ClientMessage:
+ {
+ XClientMessageEvent & xcme = xe->xclient;
+
+ if (xcme.data.l[0] == m_delete_window_atom) {
+ g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowClose,
+ window
+ );
+ } else {
+ /* Unknown client message, ignore */
+ }
+
+ break;
+ }
+
+ // We're not interested in the following things.(yet...)
+ case NoExpose :
+ case GraphicsExpose :
+
+ case EnterNotify:
+ case LeaveNotify:
+ // XCrossingEvents pointer leave enter window.
+ break;
+ case MapNotify:
+ case UnmapNotify:
+ break;
+ case MappingNotify:
+ case ReparentNotify:
+ break;
+
+ default:
+ break;
+ }
+
+ if (g_event) {
+ pushEvent(g_event);
+ }
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getModifierKeys(
+ GHOST_ModifierKeys& keys
+) const {
+
+ // analyse the masks retuned from XQueryPointer.
+
+ memset(m_keyboard_vector,32,0);
+
+ XQueryKeymap(m_display,m_keyboard_vector);
+
+ // now translate key symobols into keycodes and
+ // test with vector.
+
+ const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L);
+ const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R);
+ const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L);
+ const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R);
+ const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L);
+ const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R);
+
+ // Shift
+ if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftShift,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftShift,false);
+ }
+ if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) {
+
+ keys.set(GHOST_kModifierKeyRightShift,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightShift,false);
+ }
+
+ // control (weep)
+ if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftControl,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftControl,false);
+ }
+ if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyRightControl,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightControl,false);
+ }
+
+ // Alt (yawn)
+ if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyLeftAlt,true);
+ } else {
+ keys.set(GHOST_kModifierKeyLeftAlt,false);
+ }
+ if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) {
+ keys.set(GHOST_kModifierKeyRightAlt,true);
+ } else {
+ keys.set(GHOST_kModifierKeyRightAlt,false);
+ }
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getButtons(
+ GHOST_Buttons& buttons
+) const {
+
+ Window root_return, child_return;
+ int rx,ry,wx,wy;
+ unsigned int mask_return;
+
+ if (XQueryPointer(
+ m_display,
+ RootWindow(m_display,DefaultScreen(m_display)),
+ &root_return,
+ &child_return,
+ &rx,&ry,
+ &wx,&wy,
+ &mask_return
+ ) == False) {
+ return GHOST_kFailure;
+ } else {
+
+ if (mask_return & Button1Mask) {
+ buttons.set(GHOST_kButtonMaskLeft,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskLeft,false);
+ }
+
+ if (mask_return & Button2Mask) {
+ buttons.set(GHOST_kButtonMaskMiddle,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskMiddle,false);
+ }
+
+ if (mask_return & Button3Mask) {
+ buttons.set(GHOST_kButtonMaskRight,true);
+ } else {
+ buttons.set(GHOST_kButtonMaskRight,false);
+ }
+ }
+
+ return GHOST_kSuccess;
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+getCursorPosition(
+ GHOST_TInt32& x,
+ GHOST_TInt32& y
+) const {
+
+ Window root_return, child_return;
+ int rx,ry,wx,wy;
+ unsigned int mask_return;
+
+ if (XQueryPointer(
+ m_display,
+ RootWindow(m_display,DefaultScreen(m_display)),
+ &root_return,
+ &child_return,
+ &rx,&ry,
+ &wx,&wy,
+ &mask_return
+ ) == False) {
+ return GHOST_kFailure;
+ } else {
+ x = rx;
+ y = ry;
+ }
+ return GHOST_kSuccess;
+}
+
+
+ GHOST_TSuccess
+GHOST_SystemX11::
+setCursorPosition(
+ GHOST_TInt32 x,
+ GHOST_TInt32 y
+) const {
+
+ // This is a brute force move in screen coordinates
+ // XWarpPointer does relative moves so first determine the
+ // current pointer position.
+
+ int cx,cy;
+ if (getCursorPosition(cx,cy) == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
+
+ int relx = x-cx;
+ int rely = y-cy;
+
+ XWarpPointer(m_display,None,None,0,0,0,0,relx,rely);
+ XFlush(m_display);
+
+ return GHOST_kSuccess;
+}
+
+
+ void
+GHOST_SystemX11::
+addDirtyWindow(
+ GHOST_WindowX11 * bad_wind
+){
+
+ GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
+
+ m_dirty_windows.push_back(bad_wind);
+}
+
+
+ bool
+GHOST_SystemX11::
+generateWindowExposeEvents(
+){
+
+ vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
+ vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
+ bool anyProcessed = false;
+
+ for (;w_start != w_end; ++w_start) {
+ GHOST_Event * g_event = new
+ GHOST_Event(
+ getMilliSeconds(),
+ GHOST_kEventWindowUpdate,
+ *w_start
+ );
+
+ (*w_start)->validate();
+
+ if (g_event) {
+ pushEvent(g_event);
+ anyProcessed = true;
+ }
+ }
+
+ m_dirty_windows.clear();
+ return anyProcessed;
+}
+
+#define GXMAP(k,x,y) case x: k = y; break;
+
+ GHOST_TKey
+GHOST_SystemX11::
+convertXKey(
+ unsigned int key
+){
+ GHOST_TKey type;
+
+ if ((key >= XK_A) && (key <= XK_Z)) {
+ type = GHOST_TKey( key - XK_A + int(GHOST_kKeyA));
+ } else if ((key >= XK_a) && (key <= XK_z)) {
+ type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
+ } else if ((key >= XK_0) && (key <= XK_9)) {
+ type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
+ } else if ((key >= XK_F1) && (key <= XK_F24)) {
+ type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
+ } else {
+ switch(key) {
+ GXMAP(type,XK_BackSpace, GHOST_kKeyBackSpace);
+ GXMAP(type,XK_Tab, GHOST_kKeyTab);
+ GXMAP(type,XK_Return, GHOST_kKeyEnter);
+ GXMAP(type,XK_Escape, GHOST_kKeyEsc);
+ GXMAP(type,XK_space, GHOST_kKeySpace);
+
+ GXMAP(type,XK_Linefeed, GHOST_kKeyLinefeed);
+ GXMAP(type,XK_semicolon, GHOST_kKeySemicolon);
+ GXMAP(type,XK_period, GHOST_kKeyPeriod);
+ GXMAP(type,XK_comma, GHOST_kKeyComma);
+ GXMAP(type,XK_quoteright, GHOST_kKeyQuote);
+ GXMAP(type,XK_quoteleft, GHOST_kKeyAccentGrave);
+ GXMAP(type,XK_minus, GHOST_kKeyMinus);
+ GXMAP(type,XK_slash, GHOST_kKeySlash);
+ GXMAP(type,XK_backslash, GHOST_kKeyBackslash);
+ GXMAP(type,XK_equal, GHOST_kKeyEqual);
+ GXMAP(type,XK_bracketleft, GHOST_kKeyLeftBracket);
+ GXMAP(type,XK_bracketright, GHOST_kKeyRightBracket);
+ GXMAP(type,XK_Pause, GHOST_kKeyPause);
+
+ GXMAP(type,XK_Shift_L, GHOST_kKeyLeftShift);
+ GXMAP(type,XK_Shift_R, GHOST_kKeyRightShift);
+ GXMAP(type,XK_Control_L, GHOST_kKeyLeftControl);
+ GXMAP(type,XK_Control_R, GHOST_kKeyRightControl);
+ GXMAP(type,XK_Alt_L, GHOST_kKeyLeftAlt);
+ GXMAP(type,XK_Alt_R, GHOST_kKeyRightAlt);
+
+ GXMAP(type,XK_Insert, GHOST_kKeyInsert);
+ GXMAP(type,XK_Delete, GHOST_kKeyDelete);
+ GXMAP(type,XK_Home, GHOST_kKeyHome);
+ GXMAP(type,XK_End, GHOST_kKeyEnd);
+ GXMAP(type,XK_Page_Up, GHOST_kKeyUpPage);
+ GXMAP(type,XK_Page_Down, GHOST_kKeyDownPage);
+
+ GXMAP(type,XK_Left, GHOST_kKeyLeftArrow);
+ GXMAP(type,XK_Right, GHOST_kKeyRightArrow);
+ GXMAP(type,XK_Up, GHOST_kKeyUpArrow);
+ GXMAP(type,XK_Down, GHOST_kKeyDownArrow);
+
+ GXMAP(type,XK_Caps_Lock, GHOST_kKeyCapsLock);
+ GXMAP(type,XK_Scroll_Lock, GHOST_kKeyScrollLock);
+ GXMAP(type,XK_Num_Lock, GHOST_kKeyNumLock);
+
+ /* keypad events */
+
+ GXMAP(type,XK_KP_0, GHOST_kKeyNumpad0);
+ GXMAP(type,XK_KP_1, GHOST_kKeyNumpad1);
+ GXMAP(type,XK_KP_2, GHOST_kKeyNumpad2);
+ GXMAP(type,XK_KP_3, GHOST_kKeyNumpad3);
+ GXMAP(type,XK_KP_4, GHOST_kKeyNumpad4);
+ GXMAP(type,XK_KP_5, GHOST_kKeyNumpad5);
+ GXMAP(type,XK_KP_6, GHOST_kKeyNumpad6);
+ GXMAP(type,XK_KP_7, GHOST_kKeyNumpad7);
+ GXMAP(type,XK_KP_8, GHOST_kKeyNumpad8);
+ GXMAP(type,XK_KP_9, GHOST_kKeyNumpad9);
+ GXMAP(type,XK_KP_Decimal, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type,XK_KP_Insert, GHOST_kKeyNumpad0);
+ GXMAP(type,XK_KP_End, GHOST_kKeyNumpad1);
+ GXMAP(type,XK_KP_Down, GHOST_kKeyNumpad2);
+ GXMAP(type,XK_KP_Page_Down, GHOST_kKeyNumpad3);
+ GXMAP(type,XK_KP_Left, GHOST_kKeyNumpad4);
+ GXMAP(type,XK_KP_Begin, GHOST_kKeyNumpad5);
+ GXMAP(type,XK_KP_Right, GHOST_kKeyNumpad6);
+ GXMAP(type,XK_KP_Home, GHOST_kKeyNumpad7);
+ GXMAP(type,XK_KP_Up, GHOST_kKeyNumpad8);
+ GXMAP(type,XK_KP_Page_Up, GHOST_kKeyNumpad9);
+ GXMAP(type,XK_KP_Delete, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type,XK_KP_Enter, GHOST_kKeyNumpadEnter);
+ GXMAP(type,XK_KP_Add, GHOST_kKeyNumpadPlus);
+ GXMAP(type,XK_KP_Subtract, GHOST_kKeyNumpadMinus);
+ GXMAP(type,XK_KP_Multiply, GHOST_kKeyNumpadAsterisk);
+ GXMAP(type,XK_KP_Divide, GHOST_kKeyNumpadSlash);
+
+ /* some extra sun cruft (NICE KEYBOARD!) */
+#ifdef __sun__
+ GXMAP(type,0xffde, GHOST_kKeyNumpad1);
+ GXMAP(type,0xffe0, GHOST_kKeyNumpad3);
+ GXMAP(type,0xffdc, GHOST_kKeyNumpad5);
+ GXMAP(type,0xffd8, GHOST_kKeyNumpad7);
+ GXMAP(type,0xffda, GHOST_kKeyNumpad9);
+
+ GXMAP(type,0xffd6, GHOST_kKeyNumpadSlash);
+ GXMAP(type,0xffd7, GHOST_kKeyNumpadAsterisk);
+#endif
+
+ default :
+ type = GHOST_kKeyUnknown;
+ break;
+ }
+ }
+
+ return type;
+}
+
+#undef GXMAP
+
+
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
new file mode 100755
index 00000000000..6dedf1eb457
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -0,0 +1,252 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _GHOST_SYSTEM_X11_H_
+#define _GHOST_SYSTEM_X11_H_
+
+#include "GHOST_System.h"
+#include "../GHOST_Types.h"
+
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+class GHOST_WindowX11;
+
+/**
+ * X11 Implementation of GHOST_System class.
+ * @see GHOST_System.
+ * @author Laurence Bourn
+ * @date October 26, 2001
+ */
+
+class GHOST_SystemX11 : public GHOST_System {
+public:
+
+ /**
+ * Constructor
+ * this class should only be instanciated by GHOST_ISystem.
+ */
+
+ GHOST_SystemX11(
+ );
+
+ GHOST_TSuccess
+ init(
+ );
+
+
+ /**
+ * @section Interface Inherited from GHOST_ISystem
+ */
+
+ /**
+ * Returns the system time.
+ * Returns the number of milliseconds since the start of the system process.
+ * @return The number of milliseconds.
+ */
+ GHOST_TUns64
+ getMilliSeconds(
+ ) const;
+
+
+ /**
+ * Returns the number of displays on this system.
+ * @return The number of displays.
+ */
+ GHOST_TUns8
+ getNumDisplays(
+ ) const;
+
+ /**
+ * Returns the dimensions of the main display on this system.
+ * @return The dimension of the main display.
+ */
+ void
+ getMainDisplayDimensions(
+ GHOST_TUns32& width,
+ GHOST_TUns32& height
+ ) const;
+
+ /**
+ * Create a new window.
+ * The new window is added to the list of windows managed.
+ * Never explicitly delete the window, use disposeWindow() instead.
+ * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state of the window when opened.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Create a stereo visual for quad buffered stereo.
+ * @return The new window (or 0 if creation failed).
+ */
+ GHOST_IWindow*
+ createWindow(
+ 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
+ );
+
+ /**
+ * @section Interface Inherited from GHOST_ISystem
+ */
+
+ /**
+ * Retrieves events from the system and stores them in the queue.
+ * @param waitForEvent Flag to wait for an event (or return immediately).
+ * @return Indication of the presence of events.
+ */
+ bool
+ processEvents(
+ bool waitForEvent
+ );
+
+ /**
+ * @section Interface Inherited from GHOST_System
+ */
+ GHOST_TSuccess
+ getCursorPosition(
+ GHOST_TInt32& x,
+ GHOST_TInt32& y
+ ) const;
+
+ GHOST_TSuccess
+ setCursorPosition(
+ GHOST_TInt32 x,
+ GHOST_TInt32 y
+ ) const;
+
+ /**
+ * Returns the state of all modifier keys.
+ * @param keys The state of all modifier keys (true == pressed).
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getModifierKeys(
+ GHOST_ModifierKeys& keys
+ ) const ;
+
+ /**
+ * Returns the state of the mouse buttons (ouside the message queue).
+ * @param buttons The state of the buttons.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess
+ getButtons(
+ GHOST_Buttons& buttons
+ ) const;
+
+ /**
+ * @section
+ * Flag a window as dirty. This will
+ * generate a GHOST window update event on a call to processEvents()
+ */
+
+ void
+ addDirtyWindow(
+ GHOST_WindowX11 * bad_wind
+ );
+
+
+ /**
+ * return a pointer to the X11 display structure
+ */
+
+ Display *
+ getXDisplay(
+ ) {
+ return m_display;
+ }
+
+
+private :
+
+ Display * m_display;
+
+ /**
+ * Atom used to detect window close events
+ */
+ Atom m_delete_window_atom;
+
+ /// The vector of windows that need to be updated.
+ std::vector<GHOST_WindowX11 *> m_dirty_windows;
+
+ /// Start time at initialization.
+ GHOST_TUns64 m_start_time;
+
+ /// A vector of keyboard key masks
+ char *m_keyboard_vector;
+
+ /**
+ * Return the ghost window associated with the
+ * X11 window xwind
+ */
+
+ GHOST_WindowX11 *
+ findGhostWindow(
+ Window xwind
+ ) const ;
+
+ void
+ processEvent(
+ XEvent *xe
+ );
+
+ bool
+ generateWindowExposeEvents(
+ );
+
+ GHOST_TKey
+ convertXKey(
+ unsigned int key
+ );
+
+};
+
+#endif
+
+
+
+
diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp
new file mode 100644
index 00000000000..e54dfce86f9
--- /dev/null
+++ b/intern/ghost/intern/GHOST_TimerManager.cpp
@@ -0,0 +1,163 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#include "GHOST_TimerManager.h"
+
+#include <algorithm>
+
+#include "GHOST_TimerTask.h"
+
+
+GHOST_TimerManager::GHOST_TimerManager()
+{
+}
+
+
+GHOST_TimerManager::~GHOST_TimerManager()
+{
+ disposeTimers();
+}
+
+
+GHOST_TUns32 GHOST_TimerManager::getNumTimers()
+{
+ return (GHOST_TUns32)m_timers.size();
+}
+
+
+bool GHOST_TimerManager::getTimerFound(GHOST_TimerTask* timer)
+{
+ TTimerVector::const_iterator iter = std::find(m_timers.begin(), m_timers.end(), timer);
+ return iter != m_timers.end();
+}
+
+
+GHOST_TSuccess GHOST_TimerManager::addTimer(GHOST_TimerTask* timer)
+{
+ GHOST_TSuccess success;
+ if (!getTimerFound(timer)) {
+ // Add the timer task
+ m_timers.push_back(timer);
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask* timer)
+{
+ GHOST_TSuccess success;
+ TTimerVector::iterator iter = std::find(m_timers.begin(), m_timers.end(), timer);
+ if (iter != m_timers.end()) {
+ // Remove the timer task
+ m_timers.erase(iter);
+ delete timer;
+ timer = 0;
+ success = GHOST_kSuccess;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+GHOST_TUns64 GHOST_TimerManager::nextFireTime()
+{
+ GHOST_TUns64 smallest = GHOST_kFireTimeNever;
+ TTimerVector::iterator iter;
+
+ for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
+ GHOST_TUns64 next = (*iter)->getNext();
+
+ if (next<smallest)
+ smallest = next;
+ }
+
+ return smallest;
+}
+
+bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time)
+{
+ TTimerVector::iterator iter;
+ bool anyProcessed = false;
+
+ for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
+ if (fireTimer(time, *iter))
+ anyProcessed = true;
+ }
+
+ return anyProcessed;
+}
+
+
+bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task)
+{
+ GHOST_TUns64 next = task->getNext();
+
+ // Check if the timer should be fired
+ if (time > next) {
+ // Fire the timer
+ GHOST_TimerProcPtr timerProc = task->getTimerProc();
+ GHOST_TUns64 start = task->getStart();
+ timerProc(task, time - start);
+
+ // Update the time at which we will fire it again
+ GHOST_TUns64 interval = task->getInterval();
+ GHOST_TUns64 numCalls = (next - start) / interval;
+ numCalls++;
+ next = start + numCalls * interval;
+ task->setNext(next);
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+void GHOST_TimerManager::disposeTimers()
+{
+ while (m_timers.size() > 0) {
+ delete m_timers[0];
+ m_timers.erase(m_timers.begin());
+ }
+}
diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h
new file mode 100644
index 00000000000..ab6d004cba8
--- /dev/null
+++ b/intern/ghost/intern/GHOST_TimerManager.h
@@ -0,0 +1,133 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#ifndef _GHOST_TIMER_MANAGER_H_
+#define _GHOST_TIMER_MANAGER_H_
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include <vector>
+
+#include "GHOST_Types.h"
+
+class GHOST_TimerTask;
+
+
+/**
+ * Manages a list of timer tasks.
+ * Timer tasks added are owned by the manager.
+ * Don't delete timer task objects.
+ */
+class GHOST_TimerManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_TimerManager();
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_TimerManager();
+
+ /**
+ * Returns the number of timer tasks.
+ * @return The number of events on the stack.
+ */
+ virtual GHOST_TUns32 getNumTimers();
+
+ /**
+ * Returns whther this timer task ins in our list.
+ * @return Indication of presence.
+ */
+ virtual bool getTimerFound(GHOST_TimerTask* timer);
+
+ /**
+ * Adds a timer task to the list.
+ * It is only added when it not already present in the list.
+ * @param timer The timer task added to the list.
+ * @return Indication as to whether addition has succeeded.
+ */
+ virtual GHOST_TSuccess addTimer(GHOST_TimerTask* timer);
+
+ /**
+ * Removes a timer task from the list.
+ * It is only removed when it is found in the list.
+ * @param timer The timer task to be removed from the list.
+ * @return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess removeTimer(GHOST_TimerTask* timer);
+
+ /**
+ * Finds the soonest time the next timer would fire.
+ * @return The soonest time the next timer would fire,
+ * or GHOST_kFireTimeNever if no timers exist.
+ */
+ virtual GHOST_TUns64 nextFireTime();
+
+ /**
+ * Checks all timer tasks to see if they are expired and fires them if needed.
+ * @param time The current time.
+ * @return True if any timers were fired.
+ */
+ virtual bool fireTimers(GHOST_TUns64 time);
+
+ /**
+ * Checks this timer task to see if they are expired and fires them if needed.
+ * @param time The current time.
+ * @param task The timer task to check and optionally fire.
+ * @return True if the timer fired.
+ */
+ virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task);
+
+protected:
+ /**
+ * Deletes all timers.
+ */
+ void disposeTimers();
+
+ typedef std::vector<GHOST_TimerTask*> TTimerVector;
+ /** The list with event consumers. */
+ TTimerVector m_timers;
+};
+
+#endif // _GHOST_TIMER_MANAGER_H_
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
new file mode 100644
index 00000000000..4f845a38fa1
--- /dev/null
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -0,0 +1,195 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 28, 2001
+ */
+
+#ifndef _GHOST_TIMER_TASK_H_
+#define _GHOST_TIMER_TASK_H_
+
+#include "GHOST_ITimerTask.h"
+
+
+/**
+ * Implementation of a timer task.
+ * @author Maarten Gribnau
+ * @date May 28, 2001
+ */
+class GHOST_TimerTask : public GHOST_ITimerTask
+{
+public:
+ /**
+ * Constructor.
+ * @param start The timer start time.
+ * @param interval The interval between calls to the timerProc
+ * @param timerProc The callbak invoked when the interval expires.
+ * @param data The timer user data.
+ */
+ GHOST_TimerTask(GHOST_TUns64 start, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0)
+ : m_start(start), m_interval(interval), m_next(start), m_timerProc(timerProc), m_userData(userData), m_auxData(0)
+ {
+ }
+
+ /**
+ * Returns the timer start time.
+ * @return The timer start time.
+ */
+ inline virtual GHOST_TUns64 getStart() const
+ {
+ return m_start;
+ }
+
+ /**
+ * Changes the timer start time.
+ * @param start The timer start time.
+ */
+ virtual void setStart(GHOST_TUns64 start)
+ {
+ m_start = start;
+ }
+
+ /**
+ * Returns the timer interval.
+ * @return The timer interval.
+ */
+ inline virtual GHOST_TUns64 getInterval() const
+ {
+ return m_interval;
+ }
+
+ /**
+ * Changes the timer interval.
+ * @param interval The timer interval.
+ */
+ virtual void setInterval(GHOST_TUns64 interval)
+ {
+ m_interval = interval;
+ }
+
+ /**
+ * Returns the time the timerProc will be called.
+ * @return The time the timerProc will be called.
+ */
+ inline virtual GHOST_TUns64 getNext() const
+ {
+ return m_next;
+ }
+
+ /**
+ * Changes the time the timerProc will be called.
+ * @param next The time the timerProc will be called.
+ */
+ virtual void setNext(GHOST_TUns64 next)
+ {
+ m_next = next;
+ }
+
+ /**
+ * Returns the timer callback.
+ * @return the timer callback.
+ */
+ inline virtual GHOST_TimerProcPtr getTimerProc() const
+ {
+ return m_timerProc;
+ }
+
+ /**
+ * Changes the timer callback.
+ * @param The timer callback.
+ */
+ inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc)
+ {
+ m_timerProc = timerProc;
+ }
+
+ /**
+ * Returns the timer user data.
+ * @return The timer user data.
+ */
+ inline virtual GHOST_TUserDataPtr getUserData() const
+ {
+ return m_userData;
+ }
+
+ /**
+ * Changes the time user data.
+ * @param data The timer user data.
+ */
+ virtual void setUserData(const GHOST_TUserDataPtr userData)
+ {
+ m_userData = userData;
+ }
+
+ /**
+ * Returns the auxiliary storage room.
+ * @return The auxiliary storage room.
+ */
+ inline virtual GHOST_TUns32 getAuxData() const
+ {
+ return m_auxData;
+ }
+
+ /**
+ * Changes the auxiliary storage room.
+ * @param auxData The auxiliary storage room.
+ */
+ virtual void setAuxData(GHOST_TUns32 auxData)
+ {
+ m_auxData = auxData;
+ }
+
+protected:
+ /** The time the timer task was started. */
+ GHOST_TUns64 m_start;
+
+ /** The interval between calls. */
+ GHOST_TUns64 m_interval;
+
+ /** The time the timerProc will be called. */
+ GHOST_TUns64 m_next;
+
+ /** The callback invoked when the timer expires. */
+ GHOST_TimerProcPtr m_timerProc;
+
+ /** The timer task user data. */
+ GHOST_TUserDataPtr m_userData;
+
+ /** Auxiliary storage room. */
+ GHOST_TUns32 m_auxData;
+};
+
+
+#endif // _GHOST_TIMER_TASK_H_
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
new file mode 100644
index 00000000000..daa83eedcf6
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -0,0 +1,116 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#include "GHOST_Window.h"
+
+
+GHOST_Window::GHOST_Window(
+ 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)
+:
+ m_drawingContextType(type),
+ m_cursorVisible(true),
+ m_cursorShape(GHOST_kStandardCursorDefault),
+ m_stereoVisual(stereoVisual)
+{
+ m_fullScreen = state == GHOST_kWindowStateFullScreen;
+ if (m_fullScreen) {
+ m_fullScreenWidth = width;
+ m_fullScreenHeight = height;
+ }
+}
+
+
+GHOST_Window::~GHOST_Window()
+{
+}
+
+
+GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type)
+{
+ GHOST_TSuccess success = GHOST_kSuccess;
+ if (type != m_drawingContextType) {
+ success = removeDrawingContext();
+ if (success) {
+ success = installDrawingContext(type);
+ m_drawingContextType = type;
+ }
+ else {
+ m_drawingContextType = GHOST_kDrawingContextTypeNone;
+ }
+ }
+ return success;
+}
+
+GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
+{
+ if (setWindowCursorVisibility(visible)) {
+ m_cursorVisible = visible;
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape)
+{
+ if (setWindowCursorShape(cursorShape)) {
+ m_cursorShape = cursorShape;
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY)
+{
+ if (setWindowCustomCursorShape(bitmap, mask, hotX, hotY)) {
+ m_cursorShape = GHOST_kStandardCursorCustom;
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
new file mode 100644
index 00000000000..9bb2be7679f
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -0,0 +1,255 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#ifndef _GHOST_WINDOW_H_
+#define _GHOST_WINDOW_H_
+
+
+#include "GHOST_IWindow.h"
+
+class STR_String;
+
+/**
+ * Platform independent implementation of GHOST_IWindow.
+ * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+class GHOST_Window : public GHOST_IWindow
+{
+public:
+ /**
+ * Constructor.
+ * Creates a new window and opens it.
+ * To check if the window was created properly, use the getValid() method.
+ * @param title The text shown in the title bar of the window.
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param heigh The height the window.
+ * @param state The state the window is initially opened with.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Stereo visual for quad buffered stereo.
+ */
+ GHOST_Window(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool stereoVisual = false);
+
+ /**
+ * @section Interface inherited from GHOST_IWindow left for derived class
+ * implementation.
+ * virtual bool getValid() const = 0;
+ * virtual void setTitle(const STR_String& title) = 0;
+ * virtual void getTitle(STR_String& title) const = 0;
+ * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
+ * virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
+ * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
+ * virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
+ * virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
+ * virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+ * virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
+ * virtual GHOST_TWindowState getState() const = 0;
+ * virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
+ * virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
+ * virtual GHOST_TSuccess swapBuffers() = 0;
+ * virtual GHOST_TSuccess activateDrawingContext() = 0;
+ * virtual GHOST_TSuccess invalidate() = 0;
+ */
+
+ /**
+ * Destructor.
+ * Closes the window and disposes resources allocated.
+ */
+ virtual ~GHOST_Window();
+
+ /**
+ * Returns the current cursor shape.
+ * @return The current cursor shape.
+ */
+ inline virtual GHOST_TStandardCursor getCursorShape() const;
+
+ /**
+ * Set the shape of the cursor.
+ * @param cursor The new cursor shape type id.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
+
+ /**
+ * Set the shape of the cursor to a custom cursor.
+ * @param bitmap The bitmap data for the cursor.
+ * @param mask The mask data for the cursor.
+ * @param hotX The X coordinate of the cursor hotspot.
+ * @param hotY The Y coordinate of the cursor hotspot.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY);
+
+ /**
+ * Returns the visibility state of the cursor.
+ * @return The visibility state of the cursor.
+ */
+ inline virtual bool getCursorVisibility() const;
+
+ /**
+ * Shows or hides the cursor.
+ * @param visible The new visibility state of the cursor.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setCursorVisibility(bool visible);
+
+ /**
+ * Returns the type of drawing context used in this window.
+ * @return The current type of drawing context.
+ */
+ inline virtual GHOST_TDrawingContextType getDrawingContextType();
+
+ /**
+ * Tries to install a rendering context in this window.
+ * Child classes do not need to overload this method.
+ * They should overload the installDrawingContext and removeDrawingContext instead.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
+
+ /**
+ * Returns the window user data.
+ * @return The window user data.
+ */
+ inline virtual GHOST_TUserDataPtr getUserData() const
+ {
+ return m_userData;
+ }
+
+ /**
+ * Changes the window user data.
+ * @param data The window user data.
+ */
+ virtual void setUserData(const GHOST_TUserDataPtr userData)
+ {
+ m_userData = userData;
+ }
+
+protected:
+ /**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type) = 0;
+
+ /**
+ * Removes the current drawing context.
+ * @return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess removeDrawingContext() = 0;
+
+ /**
+ * Sets the cursor visibility on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0;
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) = 0;
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) = 0;
+
+ /** The the of drawing context installed in this window. */
+ GHOST_TDrawingContextType m_drawingContextType;
+
+ /** The window user data */
+ GHOST_TUserDataPtr m_userData;
+
+ /** The current visibility of the cursor */
+ bool m_cursorVisible;
+
+ /** The current shape of the cursor */
+ GHOST_TStandardCursor m_cursorShape;
+
+ /** Stores wether this is a full screen window. */
+ bool m_fullScreen;
+
+ /** Stereo visual created. Only necessary for 'real' stereo support,
+ * ie quad buffered stereo. This is not always possible, depends on
+ * the graphics h/w
+ */
+ bool m_stereoVisual;
+
+ /** Full-screen width */
+ GHOST_TUns32 m_fullScreenWidth;
+ /** Full-screen height */
+ GHOST_TUns32 m_fullScreenHeight;
+};
+
+
+inline GHOST_TDrawingContextType GHOST_Window::getDrawingContextType()
+{
+ return m_drawingContextType;
+}
+
+inline bool GHOST_Window::getCursorVisibility() const
+{
+ return m_cursorVisible;
+}
+
+inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const
+{
+ return m_cursorShape;
+}
+
+#endif // _GHOST_WINDOW_H
diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp
new file mode 100644
index 00000000000..0e894a2dd43
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp
@@ -0,0 +1,581 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#include "GHOST_WindowCarbon.h"
+
+#include "GHOST_Debug.h"
+
+AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL;
+
+static const GLint sPreferredFormatWindow[7] = {
+AGL_RGBA, GL_TRUE,
+AGL_DOUBLEBUFFER, GL_TRUE,
+AGL_DEPTH_SIZE, 16,
+AGL_NONE,
+};
+
+static const GLint sPreferredFormatFullScreen[7] = {
+AGL_RGBA,
+AGL_DOUBLEBUFFER,
+AGL_ACCELERATED,
+AGL_FULLSCREEN,
+AGL_DEPTH_SIZE, 16,
+AGL_NONE,
+};
+
+GHOST_WindowCarbon::GHOST_WindowCarbon(
+ 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_windowRef(0),
+ m_grafPtr(0),
+ m_aglCtx(0),
+ m_customCursor(0),
+ m_fullScreenDirty(false)
+{
+ Str255 title255;
+
+ if (state != GHOST_kWindowStateFullScreen) {
+ Rect bnds = { top, left, top+height, left+width };
+ Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized);
+ gen2mac(title, title255);
+
+ m_windowRef = ::NewCWindow(
+ nil, // Storage
+ &bnds, // Bounding rectangle of the window
+ title255, // Title of the window
+ visible, // Window initially visible
+ kWindowFullZoomGrowDocumentProc, //kWindowGrowDocumentProc, // procID
+ (WindowRef)-1L, // Put window before all other windows
+ true, // Window has minimize box
+ (SInt32)this); // Store a pointer to the class in the refCon
+ if (m_windowRef) {
+ m_grafPtr = ::GetWindowPort(m_windowRef);
+ setDrawingContextType(type);
+ updateDrawingContext();
+ activateDrawingContext();
+ }
+ }
+ else {
+ /*
+ Rect bnds = { top, left, top+height, left+width };
+ gen2mac("", title255);
+ m_windowRef = ::NewCWindow(
+ nil, // Storage
+ &bnds, // Bounding rectangle of the window
+ title255, // Title of the window
+ 0, // Window initially visible
+ plainDBox, // procID
+ (WindowRef)-1L, // Put window before all other windows
+ 0, // Window has minimize box
+ (SInt32)this); // Store a pointer to the class in the refCon
+ */
+ //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n");
+ setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);
+ updateDrawingContext();
+ activateDrawingContext();
+ }
+}
+
+
+GHOST_WindowCarbon::~GHOST_WindowCarbon()
+{
+ if (m_customCursor) delete m_customCursor;
+
+ //GHOST_PRINT("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n");
+ setDrawingContextType(GHOST_kDrawingContextTypeNone);
+ if (m_windowRef) {
+ ::DisposeWindow(m_windowRef);
+ m_windowRef = 0;
+ }
+}
+
+bool GHOST_WindowCarbon::getValid() const
+{
+ bool valid;
+ if (!m_fullScreen) {
+ valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
+ }
+ else {
+ valid = true;
+ }
+ return valid;
+}
+
+
+void GHOST_WindowCarbon::setTitle(const STR_String& title)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid")
+ Str255 title255;
+ gen2mac(title, title255);
+ ::SetWTitle(m_windowRef, title255);
+}
+
+
+void GHOST_WindowCarbon::getTitle(STR_String& title) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid")
+ Str255 title255;
+ ::GetWTitle(m_windowRef, title255);
+ mac2gen(title255, title);
+}
+
+
+void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const
+{
+ OSStatus success;
+ Rect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getWindowBounds(): window invalid")
+ success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect);
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+}
+
+
+void GHOST_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const
+{
+ Rect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getClientBounds(): window invalid")
+ ::GetPortBounds(m_grafPtr, &rect);
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setClientWidth(GHOST_TUns32 width)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientWidth(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (((GHOST_TUns32)cBnds.getWidth()) != width) {
+ ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setClientHeight(GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientHeight(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (((GHOST_TUns32)cBnds.getHeight()) != height) {
+ ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientSize(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
+ (((GHOST_TUns32)cBnds.getHeight()) != height)) {
+ ::SizeWindow(m_windowRef, width, height, true);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TWindowState GHOST_WindowCarbon::getState() const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid")
+ GHOST_TWindowState state;
+ if (::IsWindowVisible(m_windowRef)) {
+ state = GHOST_kWindowStateMinimized;
+ }
+ else if (::IsWindowInStandardState(m_windowRef, nil, nil)) {
+ state = GHOST_kWindowStateMaximized;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
+ return state;
+}
+
+
+void GHOST_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::screenToClient(): window invalid")
+ Point point;
+ point.h = inX;
+ point.v = inY;
+ GrafPtr oldPort;
+ ::GetPort(&oldPort);
+ ::SetPort(m_grafPtr);
+ ::GlobalToLocal(&point);
+ ::SetPort(oldPort);
+ outX = point.h;
+ outY = point.v;
+}
+
+
+void GHOST_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::clientToScreen(): window invalid")
+ Point point;
+ point.h = inX;
+ point.v = inY;
+ GrafPtr oldPort;
+ ::GetPort(&oldPort);
+ ::SetPort(m_grafPtr);
+ ::LocalToGlobal(&point);
+ ::SetPort(oldPort);
+ outX = point.h;
+ outY = point.v;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setState(GHOST_TWindowState state)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setState(): window invalid")
+ switch (state) {
+ case GHOST_kWindowStateMinimized:
+ ::HideWindow(m_windowRef);
+ break;
+ case GHOST_kWindowStateMaximized:
+ case GHOST_kWindowStateNormal:
+ default:
+ ::ShowWindow(m_windowRef);
+ break;
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setOrder(GHOST_TWindowOrder order)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setOrder(): window invalid")
+ if (order == GHOST_kWindowOrderTop) {
+ ::BringToFront(m_windowRef);
+ }
+ else {
+ ::SendBehind(m_windowRef, nil);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::swapBuffers()
+{
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglSwapBuffers(m_aglCtx);
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+GHOST_TSuccess GHOST_WindowCarbon::updateDrawingContext()
+{
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglUpdateContext(m_aglCtx);
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+GHOST_TSuccess GHOST_WindowCarbon::activateDrawingContext()
+{
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglSetCurrentContext(m_aglCtx);
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::installDrawingContext(GHOST_TDrawingContextType type)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ {
+ if (!getValid()) break;
+
+ AGLPixelFormat pixelFormat;
+ if (!m_fullScreen) {
+ pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow);
+ m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx);
+ if (!m_aglCtx) break;
+ if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
+ success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL\n");
+ pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatFullScreen);
+ m_aglCtx = ::aglCreateContext(pixelFormat, 0);
+ if (!m_aglCtx) break;
+ if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
+ //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): created OpenGL context\n");
+ //::CGGetActiveDisplayList(0, NULL, &m_numDisplays)
+ success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ /*
+ if (success == GHOST_kSuccess) {
+ GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n");
+ }
+ else {
+ GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n");
+ }
+ */
+ }
+ ::aglDestroyPixelFormat(pixelFormat);
+ }
+ break;
+
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+
+ default:
+ break;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::removeDrawingContext()
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ switch (m_drawingContextType) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ if (m_aglCtx) {
+ aglSetCurrentContext(NULL);
+ aglSetDrawable(m_aglCtx, NULL);
+ //aglDestroyContext(m_aglCtx);
+ if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL;
+ success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ m_aglCtx = 0;
+ }
+ break;
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+ default:
+ break;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::invalidate()
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::invalidate(): window invalid")
+ if (!m_fullScreen) {
+ Rect rect;
+ ::GetPortBounds(m_grafPtr, &rect);
+ ::InvalWindowRect(m_windowRef, &rect);
+ }
+ else {
+ //EventRef event;
+ //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event);
+ //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): created event " << status << " \n");
+ //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this);
+ //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n");
+ //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard);
+ //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget());
+ //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n");
+ m_fullScreenDirty = true;
+ }
+ return GHOST_kSuccess;
+}
+
+
+void GHOST_WindowCarbon::gen2mac(const STR_String& in, Str255 out) const
+{
+ STR_String tempStr = in;
+ int num = tempStr.Length();
+ if (num > 255) num = 255;
+ ::memcpy(out+1, tempStr.Ptr(), num);
+ out[0] = num;
+}
+
+
+void GHOST_WindowCarbon::mac2gen(const Str255 in, STR_String& out) const
+{
+ char tmp[256];
+ ::memcpy(tmp, in+1, in[0]);
+ tmp[in[0]] = '\0';
+ out = tmp;
+}
+
+void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
+{
+ static bool systemCursorVisible = true;
+
+ if (visible != systemCursorVisible) {
+ if (visible) {
+ ::ShowCursor();
+ systemCursorVisible = true;
+ }
+ else {
+ ::HideCursor();
+ systemCursorVisible = false;
+ }
+ }
+
+ if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
+ ::SetCursor( m_customCursor );
+ } else {
+ int carbon_cursor;
+
+#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break
+ switch (cursor) {
+ default:
+ GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorRightArrow, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor);
+ GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor);
+ GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor);
+ GCMAP( GHOST_kStandardCursorUpDown, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorLeftRight, kThemeResizeLeftRightCursor);
+ GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor);
+ GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor);
+ GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor);
+ };
+#undef GCMAP
+
+ ::SetThemeCursor(carbon_cursor);
+ }
+}
+
+
+bool GHOST_WindowCarbon::getFullScreenDirty()
+{
+ return m_fullScreen && m_fullScreenDirty;
+}
+
+
+GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible)
+{
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(visible, getCursorShape());
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor shape)
+{
+ if (m_customCursor) {
+ delete m_customCursor;
+ m_customCursor = 0;
+ }
+
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(getCursorVisibility(), shape);
+ }
+
+ return GHOST_kSuccess;
+}
+
+/** 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_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY)
+{
+ int y;
+
+ if (m_customCursor) {
+ delete m_customCursor;
+ m_customCursor = 0;
+ }
+
+ m_customCursor = new Cursor;
+ if (!m_customCursor) return GHOST_kFailure;
+
+ for (y=0; y<16; y++) {
+ m_customCursor->data[y] = uns16ReverseBits((bitmap[y][0]<<0) | (bitmap[y][1]<<8));
+ m_customCursor->mask[y] = uns16ReverseBits((mask[y][0]<<0) | (mask[y][1]<<8));
+ }
+
+ m_customCursor->hotSpot.h = hotX;
+ m_customCursor->hotSpot.v = hotY;
+
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
+ }
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h
new file mode 100644
index 00000000000..694bb8e9a5d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowCarbon.h
@@ -0,0 +1,273 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _GHOST_WINDOW_CARBON_H_
+#define _GHOST_WINDOW_CARBON_H_
+
+#ifndef __APPLE__
+#error Apple OSX only!
+#endif // __APPLE__
+
+#include "GHOST_Window.h"
+#include "STR_String.h"
+
+#include <Carbon/Carbon.h>
+#include <AGL/agl.h>
+
+
+/**
+ * Window on Mac OSX/Carbon.
+ * @author Maarten Gribnau
+ * @date May 23, 2001
+ */
+
+class GHOST_WindowCarbon : public GHOST_Window {
+public:
+ /**
+ * Constructor.
+ * Creates a new window and opens it.
+ * To check if the window was created properly, use the getValid() method.
+ * @param title The text shown in the title bar of the window.
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state the window is initially opened with.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Stereo visual for quad buffered stereo.
+ */
+ GHOST_WindowCarbon(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool stereoVisual = false
+ );
+
+ /**
+ * Destructor.
+ * Closes the window and disposes resources allocated.
+ */
+ virtual ~GHOST_WindowCarbon();
+
+ /**
+ * Returns indication as to whether the window is valid.
+ * @return The validity of the window.
+ */
+ virtual bool getValid() const;
+
+ /**
+ * Sets the title displayed in the title bar.
+ * @param title The title to display in the title bar.
+ */
+ virtual void setTitle(const STR_String& title);
+
+ /**
+ * Returns the title displayed in the title bar.
+ * @param title The title displayed in the title bar.
+ */
+ virtual void getTitle(STR_String& title) const;
+
+ /**
+ * Returns the window rectangle dimensions.
+ * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
+ * @param bounds The bounding rectangle of the window.
+ */
+ virtual void getWindowBounds(GHOST_Rect& bounds) const;
+
+ /**
+ * Returns the client rectangle dimensions.
+ * The left and top members of the rectangle are always zero.
+ * @param bounds The bounding rectangle of the cleient area of the window.
+ */
+ virtual void getClientBounds(GHOST_Rect& bounds) const;
+
+ /**
+ * Resizes client rectangle width.
+ * @param width The new width of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+
+ /**
+ * Resizes client rectangle height.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+
+ /**
+ * Resizes client rectangle.
+ * @param width The new width of the client area of the window.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+
+ /**
+ * Returns the state of the window (normal, minimized, maximized).
+ * @return The state of the window.
+ */
+ virtual GHOST_TWindowState getState() const;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate on the screen.
+ * @param inY The y-coordinate on the screen.
+ * @param outX The x-coordinate in the client rectangle.
+ * @param outY The y-coordinate in the client rectangle.
+ */
+ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate in the client rectangle.
+ * @param inY The y-coordinate in the client rectangle.
+ * @param outX The x-coordinate on the screen.
+ * @param outY The y-coordinate on the screen.
+ */
+ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+
+ /**
+ * Sets the state of the window (normal, minimized, maximized).
+ * @param state The state of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+
+ /**
+ * Sets the order of the window (bottom, top).
+ * @param order The order of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
+
+ /**
+ * Swaps front and back buffers of a window.
+ * @return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess swapBuffers();
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * @return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext();
+
+ /**
+ * Activates the drawing context of this window.
+ * @return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext();
+
+ virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
+
+ /**
+ * Returns the dirty state of the window when in full-screen mode.
+ * @return Whether it is dirty.
+ */
+ virtual bool getFullScreenDirty();
+
+protected:
+ /**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
+
+ /**
+ * Removes the current drawing context.
+ * @return Indication as to whether removal has succeeded.
+ */
+ virtual GHOST_TSuccess removeDrawingContext();
+
+ /**
+ * Invalidates the contents of this window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess invalidate();
+
+ /**
+ * Sets the cursor visibility on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
+
+ /**
+ * Converts a string object to a Mac Pascal string.
+ * @param in The string object to be converted.
+ * @param out The converted string.
+ */
+ virtual void gen2mac(const STR_String& in, Str255 out) const;
+
+ /**
+ * Converts a Mac Pascal string to a string object.
+ * @param in The string to be converted.
+ * @param out The converted string object.
+ */
+ virtual void mac2gen(const Str255 in, STR_String& out) const;
+
+ WindowRef m_windowRef;
+ CGrafPtr m_grafPtr;
+ AGLContext m_aglCtx;
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static AGLContext s_firstaglCtx;
+
+ Cursor* m_customCursor;
+
+ /** When running in full-screen this tells whether to refresh the window. */
+ bool m_fullScreenDirty;
+};
+
+#endif // _GHOST_WINDOW_CARBON_H_
diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp
new file mode 100644
index 00000000000..a281145ac29
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowManager.cpp
@@ -0,0 +1,190 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#include "GHOST_WindowManager.h"
+
+#include <algorithm>
+
+#include "GHOST_Debug.h"
+#include "GHOST_Window.h"
+
+
+GHOST_WindowManager::GHOST_WindowManager()
+: m_fullScreenWindow(0), m_activeWindow(0)
+{
+}
+
+
+GHOST_WindowManager::~GHOST_WindowManager()
+{
+}
+
+
+GHOST_TSuccess GHOST_WindowManager::addWindow(GHOST_IWindow* window)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ if (window) {
+ if (!getWindowFound(window)) {
+ // Store the pointer to the window
+ m_windows.push_back(window);
+ success = GHOST_kSuccess;
+ }
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowManager::removeWindow(const GHOST_IWindow* window)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ if (window) {
+ if (window == m_fullScreenWindow) {
+ endFullScreen();
+ }
+ else {
+ vector<GHOST_IWindow*>::iterator result = find(m_windows.begin(), m_windows.end(), window);
+ if (result != m_windows.end()) {
+ setWindowInactive(window);
+ m_windows.erase(result);
+ success = GHOST_kSuccess;
+ }
+ }
+ }
+ return success;
+}
+
+
+bool GHOST_WindowManager::getWindowFound(const GHOST_IWindow* window) const
+{
+ bool found = false;
+ if (window) {
+ if (getFullScreen() && (window == m_fullScreenWindow)) {
+ found = true;
+ }
+ else {
+ vector<GHOST_IWindow*>::const_iterator result = find(m_windows.begin(), m_windows.end(), window);
+ if (result != m_windows.end()) {
+ found = true;
+ }
+ }
+ }
+ return found;
+}
+
+
+bool GHOST_WindowManager::getFullScreen(void) const
+{
+ return m_fullScreenWindow != 0;
+}
+
+
+GHOST_IWindow* GHOST_WindowManager::getFullScreenWindow(void) const
+{
+ return m_fullScreenWindow;
+}
+
+
+GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow* window,
+ bool stereoVisual)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window");
+ GHOST_ASSERT(window->getValid(), "GHOST_WindowManager::beginFullScreen(): invalid window");
+ if (!getFullScreen()) {
+ m_fullScreenWindow = window;
+ setActiveWindow(m_fullScreenWindow);
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ if (getFullScreen()) {
+ if (m_fullScreenWindow != 0) {
+ //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): deleting full-screen window\n");
+ setWindowInactive(m_fullScreenWindow);
+ delete m_fullScreenWindow;
+ //GHOST_PRINT("GHOST_WindowManager::endFullScreen(): done\n");
+ m_fullScreenWindow = 0;
+ }
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowManager::setActiveWindow(GHOST_IWindow* window)
+{
+ GHOST_TSuccess success = GHOST_kSuccess;
+ if (window != m_activeWindow) {
+ if (getWindowFound(window)) {
+ m_activeWindow = window;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ return success;
+}
+
+
+GHOST_IWindow* GHOST_WindowManager::getActiveWindow(void) const
+{
+ return m_activeWindow;
+}
+
+
+void GHOST_WindowManager::setWindowInactive(const GHOST_IWindow* window)
+{
+ if (window == m_activeWindow) {
+ m_activeWindow = 0;
+ }
+}
+
+
+ std::vector<GHOST_IWindow *> &
+GHOST_WindowManager::
+getWindows(
+){
+ return m_windows;
+}
+
diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h
new file mode 100644
index 00000000000..7af86a1113c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowManager.h
@@ -0,0 +1,165 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 11, 2001
+ */
+
+#ifndef _GHOST_WINDOW_MANAGER_H_
+#define _GHOST_WINDOW_MANAGER_H_
+
+
+#ifdef WIN32
+#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+#endif // WIN32
+
+#include <vector>
+
+#include "GHOST_Rect.h"
+#include "GHOST_IWindow.h"
+
+//class GHOST_Window;
+
+/**
+ * Manages system windows (platform independent implementation).
+ */
+
+class GHOST_WindowManager
+{
+public:
+ /**
+ * Constructor.
+ */
+ GHOST_WindowManager();
+
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_WindowManager();
+
+ /**
+ * Add a window to our list.
+ * It is only added if it is not already in the list.
+ * @param window Pointer to the window to be added.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess addWindow(GHOST_IWindow* window);
+
+ /**
+ * Remove a window from our list.
+ * @param window Pointer to the window to be removed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess removeWindow(const GHOST_IWindow* window);
+
+ /**
+ * Returns whether the window is in our list.
+ * @param window Pointer to the window to query.
+ * @return A boolean indicator.
+ */
+ virtual bool getWindowFound(const GHOST_IWindow* window) const;
+
+ /**
+ * Returns whether one of the windows is fullscreen.
+ * @return A boolean indicator.
+ */
+ virtual bool getFullScreen(void) const;
+
+ /**
+ * Returns pointer to the full-screen window.
+ * @return The fll-screen window (0 if not in full-screen).
+ */
+ virtual GHOST_IWindow* getFullScreenWindow(void) const;
+
+ /**
+ * Activates fullscreen mode for a window.
+ * @param window The window displayed fullscreen.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow* window, const bool stereoVisual);
+
+ /**
+ * Closes fullscreen mode down.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess endFullScreen(void);
+
+ /**
+ * Sets new window as active window (the window receiving events).
+ * There can be only one window active which should be in the current window list.
+ * @param window The new active window.
+ */
+ virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow* window);
+
+ /**
+ * Returns the active window (the window receiving events).
+ * There can be only one window active which should be in the current window list.
+ * @return window The active window (or NULL if there is none).
+ */
+ virtual GHOST_IWindow* getActiveWindow(void) const;
+
+
+ /**
+ * Set this window to be inactive (not receiving events).
+ * @param window The window to decativate.
+ */
+ virtual void setWindowInactive(const GHOST_IWindow* window);
+
+
+ /**
+ * Return a vector of the windows currently managed by this
+ * class.
+ * @warning It is very dangerous to mess with the contents of
+ * this vector. Please do not destroy or add windows use the
+ * interface above for this,
+ */
+
+ std::vector<GHOST_IWindow *> &
+ getWindows(
+ );
+
+
+protected:
+ /** The list of windows managed */
+ std::vector<GHOST_IWindow*> m_windows;
+
+ /** Window in fullscreen state. There can be only one of this which is not in or window list. */
+ GHOST_IWindow* m_fullScreenWindow;
+
+ /** The active window. */
+ GHOST_IWindow* m_activeWindow;
+};
+
+#endif // _GHOST_WINDOW_MANAGER_H_
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
new file mode 100644
index 00000000000..239a020083b
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -0,0 +1,584 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#include <string.h>
+
+#include "GHOST_WindowWin32.h"
+
+#include <GL/gl.h>
+
+LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass";
+const int GHOST_WindowWin32::s_maxTitleLength = 128;
+HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
+
+/*
+ * Color and depth bit values are not to be trusted.
+ * For instance, on TNT2:
+ * When the screen color depth is set to 16 bit, we get 5 color bits
+ * and 16 depth bits.
+ * When the screen color depth is set to 32 bit, we get 8 color bits
+ * and 24 depth bits.
+ * Just to be safe, we request high waulity settings.
+ */
+static PIXELFORMATDESCRIPTOR sPreferredFormat = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_DOUBLEBUFFER, /* support double-buffering */
+ PFD_TYPE_RGBA, /* color type */
+ 32, /* prefered color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ 0, /* no alpha buffer */
+ 0, /* alpha bits (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 32, /* depth buffer */
+ 0, /* no stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0 /* no layer, visible, damage masks */
+};
+
+GHOST_WindowWin32::GHOST_WindowWin32(
+ 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,
+ stereoVisual),
+ m_hDC(0),
+ m_hGlRc(0),
+ m_hasMouseCaptured(false),
+ m_nPressedButtons(0),
+ m_customCursor(0)
+{
+ if (state != GHOST_kWindowStateFullScreen) {
+ /* Convert client size into window size */
+ width += GetSystemMetrics(SM_CXSIZEFRAME)*2;
+ height += GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYCAPTION);
+
+ m_hWnd = ::CreateWindow(
+ s_windowClassName, // pointer to registered class name
+ title, // pointer to window name
+ WS_OVERLAPPEDWINDOW, // window style
+ left, // horizontal position of window
+ top, // vertical position of window
+ width, // window width
+ height, // window height
+ 0, // handle to parent or owner window
+ 0, // handle to menu or child-window identifier
+ ::GetModuleHandle(0), // handle to application instance
+ 0); // pointer to window-creation data
+ }
+ else {
+ m_hWnd = ::CreateWindow(
+ s_windowClassName, // pointer to registered class name
+ title, // pointer to window name
+ WS_POPUP | WS_MAXIMIZE, // window style
+ left, // horizontal position of window
+ top, // vertical position of window
+ width, // window width
+ height, // window height
+ 0, // handle to parent or owner window
+ 0, // handle to menu or child-window identifier
+ ::GetModuleHandle(0), // handle to application instance
+ 0); // pointer to window-creation data
+ }
+ if (m_hWnd) {
+ // Store a pointer to this class in the window structure
+ LONG result = ::SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
+
+ // Store the device context
+ m_hDC = ::GetDC(m_hWnd);
+
+ // Show the window
+ int nCmdShow;
+ switch (state) {
+ case GHOST_kWindowStateMaximized:
+ nCmdShow = SW_SHOWMAXIMIZED;
+ break;
+ case GHOST_kWindowStateMinimized:
+ nCmdShow = SW_SHOWMINIMIZED;
+ break;
+ case GHOST_kWindowStateNormal:
+ default:
+ nCmdShow = SW_SHOWNORMAL;
+ break;
+ }
+ setDrawingContextType(type);
+ ::ShowWindow(m_hWnd, nCmdShow);
+ // Force an initial paint of the window
+ ::UpdateWindow(m_hWnd);
+ }
+}
+
+
+GHOST_WindowWin32::~GHOST_WindowWin32()
+{
+ if (m_customCursor) {
+ DestroyCursor(m_customCursor);
+ m_customCursor = NULL;
+ }
+
+ setDrawingContextType(GHOST_kDrawingContextTypeNone);
+ if (m_hDC) {
+ ::ReleaseDC(m_hWnd, m_hDC);
+ m_hDC = 0;
+ }
+ if (m_hWnd) {
+ ::DestroyWindow(m_hWnd);
+ m_hWnd = 0;
+ }
+}
+
+bool GHOST_WindowWin32::getValid() const
+{
+ return m_hWnd != 0;
+}
+
+
+void GHOST_WindowWin32::setTitle(const STR_String& title)
+{
+ ::SetWindowText(m_hWnd, title);
+}
+
+
+void GHOST_WindowWin32::getTitle(STR_String& title) const
+{
+ char buf[s_maxTitleLength];
+ ::GetWindowText(m_hWnd, buf, s_maxTitleLength);
+ STR_String temp (buf);
+ title = buf;
+}
+
+
+void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
+{
+ RECT rect;
+ ::GetWindowRect(m_hWnd, &rect);
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+}
+
+
+void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const
+{
+ RECT rect;
+ ::GetClientRect(m_hWnd, &rect);
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width)
+{
+ GHOST_TSuccess success;
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (cBnds.getWidth() != width) {
+ getWindowBounds(wBnds);
+ int cx = wBnds.getWidth() + width - cBnds.getWidth();
+ int cy = wBnds.getHeight();
+ success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
+ GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height)
+{
+ GHOST_TSuccess success;
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (cBnds.getHeight() != height) {
+ getWindowBounds(wBnds);
+ int cx = wBnds.getWidth();
+ int cy = wBnds.getHeight() + height - cBnds.getHeight();
+ success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
+ GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ GHOST_TSuccess success;
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if ((cBnds.getWidth() != width) || (cBnds.getHeight() != height)) {
+ getWindowBounds(wBnds);
+ int cx = wBnds.getWidth() + width - cBnds.getWidth();
+ int cy = wBnds.getHeight() + height - cBnds.getHeight();
+ success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
+ GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TWindowState GHOST_WindowWin32::getState() const
+{
+ GHOST_TWindowState state;
+ if (::IsIconic(m_hWnd)) {
+ state = GHOST_kWindowStateMinimized;
+ }
+ else if (::IsZoomed(m_hWnd)) {
+ state = GHOST_kWindowStateMaximized;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
+ return state;
+}
+
+
+void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ POINT point = { inX, inY };
+ ::ScreenToClient(m_hWnd, &point);
+ outX = point.x;
+ outY = point.y;
+}
+
+
+void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ POINT point = { inX, inY };
+ ::ClientToScreen(m_hWnd, &point);
+ outX = point.x;
+ outY = point.y;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(WINDOWPLACEMENT);
+ ::GetWindowPlacement(m_hWnd, &wp);
+ switch (state) {
+ case GHOST_kWindowStateMinimized: wp.showCmd = SW_SHOWMAXIMIZED; break;
+ case GHOST_kWindowStateMaximized: wp.showCmd = SW_SHOWMINIMIZED; break;
+ case GHOST_kWindowStateNormal: default: wp.showCmd = SW_SHOWNORMAL; break;
+ }
+ return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
+{
+ HWND hWndInsertAfter = order == GHOST_kWindowOrderTop ? HWND_TOP : HWND_BOTTOM;
+ return ::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::swapBuffers()
+{
+ return ::SwapBuffers(m_hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext()
+{
+ GHOST_TSuccess success;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_hDC && m_hGlRc) {
+ success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ else {
+ success = GHOST_kSuccess;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::invalidate()
+{
+ GHOST_TSuccess success;
+ if (m_hWnd) {
+ success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
+{
+ GHOST_TSuccess success;
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ {
+ if(m_stereoVisual)
+ sPreferredFormat.dwFlags |= PFD_STEREO;
+
+ // Attempt to match device context pixel format to the preferred format
+ int iPixelFormat = ::ChoosePixelFormat(m_hDC, &sPreferredFormat);
+ if (iPixelFormat == 0) {
+ success = GHOST_kFailure;
+ break;
+ }
+ if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
+ success = GHOST_kFailure;
+ break;
+ }
+ // For debugging only: retrieve the pixel format chosen
+ PIXELFORMATDESCRIPTOR preferredFormat;
+ ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
+ // Create the context
+ m_hGlRc = ::wglCreateContext(m_hDC);
+ if (m_hGlRc) {
+ if (s_firsthGLRc) {
+ wglShareLists(s_firsthGLRc, m_hGlRc);
+ } else {
+ s_firsthGLRc = m_hGlRc;
+ }
+
+ success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ }
+ break;
+
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+
+ default:
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
+{
+ GHOST_TSuccess success;
+ switch (m_drawingContextType) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ if (m_hGlRc) {
+ success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ if (m_hGlRc == s_firsthGLRc) {
+ s_firsthGLRc = NULL;
+ }
+ m_hGlRc = 0;
+ }
+ else {
+ success = GHOST_kFailure;
+ }
+ break;
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+ default:
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+void GHOST_WindowWin32::lostMouseCapture()
+{
+ if (m_hasMouseCaptured) {
+ m_hasMouseCaptured = false;
+ m_nPressedButtons = 0;
+ }
+}
+
+void GHOST_WindowWin32::registerMouseClickEvent(bool press)
+{
+ if (press) {
+ if (!m_hasMouseCaptured) {
+ ::SetCapture(m_hWnd);
+ m_hasMouseCaptured = true;
+ }
+ m_nPressedButtons++;
+ } else {
+ if (m_nPressedButtons) {
+ m_nPressedButtons--;
+ if (!m_nPressedButtons) {
+ ::ReleaseCapture();
+ m_hasMouseCaptured = false;
+ }
+ }
+ }
+}
+
+
+void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
+{
+ if (!visible) {
+ while (::ShowCursor(FALSE) >= 0);
+ }
+ else {
+ while (::ShowCursor(TRUE) < 0);
+ }
+
+ if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
+ ::SetCursor( m_customCursor );
+ } else {
+ // Convert GHOST cursor to Windows OEM cursor
+ bool success = true;
+ LPCSTR id;
+ switch (cursor) {
+ case GHOST_kStandardCursorDefault: id = IDC_ARROW;
+ case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break;
+ case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break;
+ case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
+ case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle
+ case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark
+ case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle
+ case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
+ case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass
+ case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam
+ case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair
+ case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south
+ case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east
+ case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow
+ case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break;
+ case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break;
+ case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break;
+ case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break;
+ case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break;
+ case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break;
+ default:
+ success = false;
+ }
+
+ if (success) {
+ HCURSOR hCursor = ::SetCursor(::LoadCursor(0, id));
+ }
+ }
+}
+
+GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
+{
+ if (::GetForegroundWindow() == m_hWnd) {
+ loadCursor(visible, getCursorShape());
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
+{
+ if (m_customCursor) {
+ DestroyCursor(m_customCursor);
+ m_customCursor = NULL;
+ }
+
+ if (::GetForegroundWindow() == m_hWnd) {
+ loadCursor(getCursorVisibility(), cursorShape);
+ }
+
+ return GHOST_kSuccess;
+}
+
+/** 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_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY)
+{
+ GHOST_TUns32 andData[32];
+ GHOST_TUns32 xorData[32];
+ int y;
+
+ if (m_customCursor) {
+ DestroyCursor(m_customCursor);
+ m_customCursor = NULL;
+ }
+
+ memset(&andData, 0xFF, sizeof(andData));
+ memset(&xorData, 0, sizeof(xorData));
+
+ for (y=0; y<16; y++) {
+ GHOST_TUns32 fullBitRow = uns16ReverseBits((bitmap[y][0]<<8) | (bitmap[y][1]<<0));
+ GHOST_TUns32 fullMaskRow = uns16ReverseBits((mask[y][0]<<8) | (mask[y][1]<<0));
+
+ xorData[y]= fullBitRow & fullMaskRow;
+ andData[y]= ~fullMaskRow;
+ }
+
+ m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData);
+ if (!m_customCursor) {
+ return GHOST_kFailure;
+ }
+
+ if (::GetForegroundWindow() == m_hWnd) {
+ loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
+ }
+
+ return GHOST_kSuccess;
+}
+
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
new file mode 100644
index 00000000000..c29e61aabbb
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -0,0 +1,276 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifndef _GHOST_WINDOW_WIN32_H_
+#define _GHOST_WINDOW_WIN32_H_
+
+#ifndef WIN32
+#error WIN32 only!
+#endif // WIN32
+
+#include "GHOST_Window.h"
+
+#include <windows.h>
+
+
+/**
+ * GHOST window on M$ Windows OSs.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+class GHOST_WindowWin32 : public GHOST_Window {
+public:
+ /**
+ * Constructor.
+ * Creates a new window and opens it.
+ * To check if the window was created properly, use the getValid() method.
+ * @param title The text shown in the title bar of the window.
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state the window is initially opened with.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Stereo visual for quad buffered stereo.
+ */
+ GHOST_WindowWin32(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool stereoVisual = false
+ );
+
+ /**
+ * Destructor.
+ * Closes the window and disposes resources allocated.
+ */
+ virtual ~GHOST_WindowWin32();
+
+ /**
+ * Returns indication as to whether the window is valid.
+ * @return The validity of the window.
+ */
+ virtual bool getValid() const;
+
+ /**
+ * Sets the title displayed in the title bar.
+ * @param title The title to display in the title bar.
+ */
+ virtual void setTitle(const STR_String& title);
+
+ /**
+ * Returns the title displayed in the title bar.
+ * @param title The title displayed in the title bar.
+ */
+ virtual void getTitle(STR_String& title) const;
+
+ /**
+ * Returns the window rectangle dimensions.
+ * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
+ * @param bounds The bounding rectangle of the window.
+ */
+ virtual void getWindowBounds(GHOST_Rect& bounds) const;
+
+ /**
+ * Returns the client rectangle dimensions.
+ * The left and top members of the rectangle are always zero.
+ * @param bounds The bounding rectangle of the cleient area of the window.
+ */
+ virtual void getClientBounds(GHOST_Rect& bounds) const;
+
+ /**
+ * Resizes client rectangle width.
+ * @param width The new width of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
+
+ /**
+ * Resizes client rectangle height.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
+
+ /**
+ * Resizes client rectangle.
+ * @param width The new width of the client area of the window.
+ * @param height The new height of the client area of the window.
+ */
+ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
+
+ /**
+ * Returns the state of the window (normal, minimized, maximized).
+ * @return The state of the window.
+ */
+ virtual GHOST_TWindowState getState() const;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate on the screen.
+ * @param inY The y-coordinate on the screen.
+ * @param outX The x-coordinate in the client rectangle.
+ * @param outY The y-coordinate in the client rectangle.
+ */
+ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+
+ /**
+ * Converts a point in screen coordinates to client rectangle coordinates
+ * @param inX The x-coordinate in the client rectangle.
+ * @param inY The y-coordinate in the client rectangle.
+ * @param outX The x-coordinate on the screen.
+ * @param outY The y-coordinate on the screen.
+ */
+ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
+
+ /**
+ * Sets the state of the window (normal, minimized, maximized).
+ * @param state The state of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setState(GHOST_TWindowState state);
+
+ /**
+ * Sets the order of the window (bottom, top).
+ * @param order The order of the window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
+
+ /**
+ * Swaps front and back buffers of a window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Invalidates the contents of this window.
+ */
+ virtual GHOST_TSuccess invalidate();
+
+ /**
+ * Returns the name of the window class.
+ * @return The name of the window class.
+ */
+ static LPCSTR getWindowClassName() { return s_windowClassName; }
+
+ /**
+ * Register a mouse click event (should be called
+ * for any real button press, controls mouse
+ * capturing).
+ *
+ * @param press True the event was a button press.
+ */
+ void registerMouseClickEvent(bool press);
+
+ /**
+ * Inform the window that it has lost mouse capture,
+ * called in response to native window system messages.
+ */
+ void lostMouseCapture();
+
+ /**
+ * Loads the windows equivalent of a standard GHOST cursor.
+ * @param visible Flag for cursor visibility.
+ * @param cursorShape The cursor shape.
+ */
+ void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
+
+
+protected:
+ /**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
+
+ /**
+ * Removes the current drawing context.
+ * @return Indication of success.
+ */
+ virtual GHOST_TSuccess removeDrawingContext();
+
+ /**
+ * Sets the cursor visibility on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
+
+ /** Window handle. */
+ HWND m_hWnd;
+ /** Device context handle. */
+ HDC m_hDC;
+ /** OpenGL rendering context. */
+ HGLRC m_hGlRc;
+ /** The first created OpenGL context (for sharing display lists) */
+ static HGLRC s_firsthGLRc;
+ /** Flag for if window has captured the mouse */
+ bool m_hasMouseCaptured;
+ /** Count of number of pressed buttons */
+ int m_nPressedButtons;
+ /** HCURSOR structure of the custom cursor */
+ HCURSOR m_customCursor;
+
+ static LPCSTR s_windowClassName;
+ static const int s_maxTitleLength;
+};
+
+#endif // _GHOST_WINDOW_WIN32_H_
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
new file mode 100755
index 00000000000..81592c1984c
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -0,0 +1,714 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GHOST_WindowX11.h"
+
+#include "GHOST_SystemX11.h"
+#include "STR_String.h"
+#include "GHOST_Debug.h"
+
+// For standard X11 cursors
+#include <X11/cursorfont.h>
+
+// For obscure full screen mode stuuf
+// lifted verbatim from blut.
+
+typedef struct {
+ long flags;
+ long functions;
+ long decorations;
+ long input_mode;
+} MotifWmHints;
+
+#define MWM_HINTS_DECORATIONS (1L << 1)
+
+GLXContext GHOST_WindowX11::s_firstContext = NULL;
+
+GHOST_WindowX11::
+GHOST_WindowX11(
+ GHOST_SystemX11 *system,
+ Display * display,
+ 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,type),
+ m_display(display),
+ m_valid_setup (false),
+ m_system (system),
+ m_invalid_window(false),
+ m_context(NULL),
+ m_empty_cursor(None),
+ m_custom_cursor(None)
+{
+
+ // Set up the minimum atrributes that we require and see if
+ // X can find us a visual matching those requirements.
+
+ int attributes[40], i = 0;
+
+ if(m_stereoVisual)
+ attributes[i++] = GLX_STEREO;
+
+ attributes[i++] = GLX_RGBA;
+ attributes[i++] = GLX_DOUBLEBUFFER;
+ attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1;
+ attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
+ attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
+ attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
+ attributes[i] = None;
+
+ m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes);
+
+ if (m_visual == NULL) {
+ // barf : no visual meeting these requirements could be found.
+ return;
+ }
+
+ // Create a bunch of attributes needed to create an X window.
+
+
+ // First create a colormap for the window and visual.
+ // This seems pretty much a legacy feature as we are in rgba mode anyway.
+
+ XSetWindowAttributes xattributes;
+ memset(&xattributes, 0, sizeof(xattributes));
+
+ xattributes.colormap= XCreateColormap(
+ m_display,
+ RootWindow(m_display, m_visual->screen),
+ m_visual->visual,
+ AllocNone
+ );
+
+ xattributes.border_pixel= 0;
+
+ // Specify which events we are interested in hearing.
+
+ xattributes.event_mask=
+ ExposureMask | StructureNotifyMask |
+ KeyPressMask | KeyReleaseMask |
+ EnterWindowMask | LeaveWindowMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | FocusChangeMask;
+
+ // create the window!
+
+ m_window =
+ XCreateWindow(
+ m_display,
+ RootWindow(m_display, m_visual->screen),
+ left,
+ top,
+ width,
+ height,
+ 0, // no border.
+ m_visual->depth,
+ InputOutput,
+ m_visual->visual,
+ CWBorderPixel|CWColormap|CWEventMask,
+ &xattributes
+ );
+
+ // Are we in fullscreen mode - then include
+ // some obscure blut code to remove decorations.
+
+ if (state == GHOST_kWindowStateFullScreen) {
+
+ MotifWmHints hints;
+ Atom atom;
+
+ atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
+
+ if (atom == None) {
+ GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n");
+ } else {
+ hints.flags = MWM_HINTS_DECORATIONS;
+ hints.decorations = 0; /* Absolutely no decorations. */
+ // other hints.decorations make no sense
+ // you can't select individual decorations
+
+ XChangeProperty(m_display, m_window,
+ atom, atom, 32,
+ PropModeReplace, (unsigned char *) &hints, 4);
+ }
+ }
+
+ // Create some hints for the window manager on how
+ // we want this window treated.
+
+ XSizeHints * xsizehints = XAllocSizeHints();
+ xsizehints->flags = USPosition | USSize;
+ xsizehints->x = left;
+ xsizehints->y = top;
+ xsizehints->width = width;
+ xsizehints->height = height;
+ XSetWMNormalHints(m_display, m_window, xsizehints);
+ XFree(xsizehints);
+
+ setTitle(title);
+
+ // now set up the rendering context.
+ if (installDrawingContext(type) == GHOST_kSuccess) {
+ m_valid_setup = true;
+ GHOST_PRINT("Created window\n");
+ }
+
+ XMapWindow(m_display, m_window);
+ GHOST_PRINT("Mapped window\n");
+
+ XFlush(m_display);
+}
+
+ Window
+GHOST_WindowX11::
+getXWindow(
+){
+ return m_window;
+}
+
+ bool
+GHOST_WindowX11::
+getValid(
+) const {
+ return m_valid_setup;
+}
+
+ void
+GHOST_WindowX11::
+setTitle(
+ const STR_String& title
+){
+ XStoreName(m_display,m_window,title);
+ XFlush(m_display);
+}
+
+ void
+GHOST_WindowX11::
+getTitle(
+ STR_String& title
+) const {
+ char *name = NULL;
+
+ XFetchName(m_display,m_window,&name);
+ title= name?name:"untitled";
+ XFree(name);
+}
+
+ void
+GHOST_WindowX11::
+getWindowBounds(
+ GHOST_Rect& bounds
+) const {
+ // Getting the window bounds under X11 is not
+ // really supported (nor should it be desired).
+ getClientBounds(bounds);
+}
+
+ void
+GHOST_WindowX11::
+getClientBounds(
+ GHOST_Rect& bounds
+) const {
+ Window root_return;
+ int x_return,y_return;
+ unsigned int w_return,h_return,border_w_return,depth_return;
+ GHOST_TInt32 screen_x, screen_y;
+
+ XGetGeometry(m_display,m_window,&root_return,&x_return,&y_return,
+ &w_return,&h_return,&border_w_return,&depth_return);
+
+ clientToScreen(0, 0, screen_x, screen_y);
+
+ bounds.m_l = screen_x;
+ bounds.m_r = bounds.m_l + w_return;
+ bounds.m_t = screen_y;
+ bounds.m_b = bounds.m_t + h_return;
+
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setClientWidth(
+ GHOST_TUns32 width
+){
+ XWindowChanges values;
+ unsigned int value_mask= CWWidth;
+ values.width = width;
+ XConfigureWindow(m_display,m_window,value_mask,&values);
+
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setClientHeight(
+ GHOST_TUns32 height
+){
+ XWindowChanges values;
+ unsigned int value_mask= CWHeight;
+ values.height = height;
+ XConfigureWindow(m_display,m_window,value_mask,&values);
+ return GHOST_kSuccess;
+
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setClientSize(
+ GHOST_TUns32 width,
+ GHOST_TUns32 height
+){
+ XWindowChanges values;
+ unsigned int value_mask= CWWidth | CWHeight;
+ values.width = width;
+ values.height = height;
+ XConfigureWindow(m_display,m_window,value_mask,&values);
+ return GHOST_kSuccess;
+
+}
+
+ void
+GHOST_WindowX11::
+screenToClient(
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32& outX,
+ GHOST_TInt32& outY
+) const {
+ // not sure about this one!
+
+ int ax,ay;
+ Window temp;
+
+ XTranslateCoordinates(
+ m_display,
+ RootWindow(m_display, m_visual->screen),
+ m_window,
+ inX,
+ inY,
+ &ax,
+ &ay,
+ &temp
+ );
+ outX = ax;
+ outY = ay;
+}
+
+ void
+GHOST_WindowX11::
+clientToScreen(
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32& outX,
+ GHOST_TInt32& outY
+) const {
+ int ax,ay;
+ Window temp;
+
+ XTranslateCoordinates(
+ m_display,
+ m_window,
+ RootWindow(m_display, m_visual->screen),
+ inX,
+ inY,
+ &ax,
+ &ay,
+ &temp
+ );
+ outX = ax;
+ outY = ay;
+}
+
+
+ GHOST_TWindowState
+GHOST_WindowX11::
+getState(
+) const {
+ //FIXME
+ return GHOST_kWindowStateNormal;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setState(
+ GHOST_TWindowState state
+){
+ //TODO
+
+ if (state == getState()) {
+ return GHOST_kSuccess;
+ } else {
+ return GHOST_kFailure;
+ }
+
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setOrder(
+ GHOST_TWindowOrder order
+){
+ if (order == GHOST_kWindowOrderTop) {
+ XRaiseWindow(m_display,m_window);
+ XFlush(m_display);
+ } else if (order == GHOST_kWindowOrderBottom) {
+ XLowerWindow(m_display,m_window);
+ XFlush(m_display);
+ } else {
+ return GHOST_kFailure;
+ }
+
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+swapBuffers(
+){
+ if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
+ glXSwapBuffers(m_display,m_window);
+ return GHOST_kSuccess;
+ } else {
+ return GHOST_kFailure;
+ }
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+activateDrawingContext(
+){
+ if (m_context !=NULL) {
+ glXMakeCurrent(m_display, m_window,m_context);
+ return GHOST_kSuccess;
+ }
+ return GHOST_kFailure;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+invalidate(
+){
+
+ // So the idea of this function is to generate an expose event
+ // for the window.
+ // Unfortunately X does not handle expose events for you and
+ // it is the client's job to refresh the dirty part of the window.
+ // We need to queue up invalidate calls and generate GHOST events
+ // for them in the system.
+
+ // We implement this by setting a boolean in this class to concatenate
+ // all such calls into a single event for this window.
+
+ // At the same time we queue the dirty windows in the system class
+ // and generate events for them at the next processEvents call.
+
+ if (m_invalid_window == false) {
+ m_system->addDirtyWindow(this);
+ m_invalid_window = true;
+ }
+
+ return GHOST_kSuccess;
+}
+
+/**
+ * called by the X11 system implementation when expose events
+ * for the window have been pushed onto the GHOST queue
+ */
+
+ void
+GHOST_WindowX11::
+validate(
+){
+ m_invalid_window = false;
+}
+
+
+/**
+ * Destructor.
+ * Closes the window and disposes resources allocated.
+ */
+
+GHOST_WindowX11::
+~GHOST_WindowX11(
+){
+ std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
+ for (; it != m_standard_cursors.end(); it++) {
+ XFreeCursor(m_display, it->second);
+ }
+
+ if (m_empty_cursor) {
+ XFreeCursor(m_display, m_empty_cursor);
+ }
+ if (m_custom_cursor) {
+ XFreeCursor(m_display, m_custom_cursor);
+ }
+
+ XDestroyWindow(m_display, m_window);
+ if (m_context) {
+ if (m_context == s_firstContext) {
+ s_firstContext = NULL;
+ }
+ glXDestroyContext(m_display, m_context);
+ }
+ XFree(m_visual);
+}
+
+
+
+
+/**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ GHOST_TSuccess
+GHOST_WindowX11::
+installDrawingContext(
+ GHOST_TDrawingContextType type
+){
+ // only support openGL for now.
+ GHOST_TSuccess success;
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
+ if (m_context !=NULL) {
+ if (!s_firstContext) {
+ s_firstContext = m_context;
+ }
+ glXMakeCurrent(m_display, m_window,m_context);
+ success = GHOST_kSuccess;
+ } else {
+ success = GHOST_kFailure;
+ }
+
+ break;
+
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+
+ default:
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+
+/**
+ * Removes the current drawing context.
+ * @return Indication as to whether removal has succeeded.
+ */
+ GHOST_TSuccess
+GHOST_WindowX11::
+removeDrawingContext(
+){
+ GHOST_TSuccess success;
+
+ if (m_context != NULL) {
+ glXDestroyContext(m_display, m_context);
+ success = GHOST_kSuccess;
+ } else {
+ success = GHOST_kFailure;
+ }
+ return success;
+}
+
+
+ Cursor
+GHOST_WindowX11::
+getStandardCursor(
+ GHOST_TStandardCursor g_cursor
+){
+ unsigned int xcursor_id;
+
+#define GtoX(gcurs, xcurs) case gcurs: xcursor_id = xcurs
+ switch (g_cursor) {
+ GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
+ GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
+ GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
+ GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
+ GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
+ GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
+ GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
+ GtoX(GHOST_kStandardCursorWait, XC_watch); break;
+ GtoX(GHOST_kStandardCursorText, XC_xterm); break;
+ GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
+ GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
+ GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
+ GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
+ GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
+ GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
+ GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
+ GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
+ GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
+ GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
+ GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
+ default:
+ xcursor_id = 0;
+ }
+#undef GtoX
+
+ if (xcursor_id) {
+ Cursor xcursor = m_standard_cursors[xcursor_id];
+
+ if (!xcursor) {
+ xcursor = XCreateFontCursor(m_display, xcursor_id);
+
+ m_standard_cursors[xcursor_id] = xcursor;
+ }
+
+ return xcursor;
+ } else {
+ return None;
+ }
+}
+
+ Cursor
+GHOST_WindowX11::
+getEmptyCursor(
+) {
+ if (!m_empty_cursor) {
+ Pixmap blank;
+ XColor dummy;
+ char data[1] = {0};
+
+ /* make a blank cursor */
+ blank = XCreateBitmapFromData (
+ m_display,
+ RootWindow(m_display,DefaultScreen(m_display)),
+ data, 1, 1
+ );
+
+ m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
+ XFreePixmap(m_display, blank);
+ }
+
+ return m_empty_cursor;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setWindowCursorVisibility(
+ bool visible
+){
+ Cursor xcursor;
+
+ if (visible) {
+ xcursor = getStandardCursor( getCursorShape() );
+ } else {
+ xcursor = getEmptyCursor();
+ }
+
+ XDefineCursor(m_display, m_window, xcursor);
+ XFlush(m_display);
+
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setWindowCursorShape(
+ GHOST_TStandardCursor shape
+){
+ Cursor xcursor = getStandardCursor( shape );
+
+ XDefineCursor(m_display, m_window, xcursor);
+ XFlush(m_display);
+
+ return GHOST_kSuccess;
+}
+
+ GHOST_TSuccess
+GHOST_WindowX11::
+setWindowCustomCursorShape(
+ GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY
+){
+ Pixmap bitmap_pix, mask_pix;
+ XColor fg, bg;
+
+ if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)),
+ "White", &fg, &fg) == 0) return GHOST_kFailure;
+ if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)),
+ "Red", &bg, &bg) == 0) return GHOST_kFailure;
+
+ if (m_custom_cursor) {
+ XFreeCursor(m_display, m_custom_cursor);
+ }
+
+ bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char*) bitmap, 16, 16);
+ mask_pix = XCreateBitmapFromData(m_display, m_window, (char*) mask, 16, 16);
+
+ m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
+ XDefineCursor(m_display, m_window, m_custom_cursor);
+ XFlush(m_display);
+
+ XFreePixmap(m_display, bitmap_pix);
+ XFreePixmap(m_display, mask_pix);
+
+ return GHOST_kSuccess;
+}
+
+/*
+
+void glutCustomCursor(char *data1, char *data2, int size)
+{
+ Pixmap source, mask;
+ Cursor cursor;
+ XColor fg, bg;
+
+ if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen),
+ "White", &fg, &fg) == 0) return;
+ if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen),
+ "Red", &bg, &bg) == 0) return;
+
+
+ source= XCreateBitmapFromData(__glutDisplay, xdraw, data2, size, size);
+ mask= XCreateBitmapFromData(__glutDisplay, xdraw, data1, size, size);
+
+ cursor= XCreatePixmapCursor(__glutDisplay, source, mask, &fg, &bg, 7, 7);
+
+ XFreePixmap(__glutDisplay, source);
+ XFreePixmap(__glutDisplay, mask);
+
+ XDefineCursor(__glutDisplay, xdraw, cursor);
+}
+
+*/
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
new file mode 100755
index 00000000000..dd38496c903
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -0,0 +1,292 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 7, 2001
+ */
+
+#ifndef _GHOST_WINDOWX11_H_
+#define _GHOST_WINDOWX11_H_
+
+#include "GHOST_Window.h"
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+#include <map>
+
+class STR_String;
+class GHOST_SystemX11;
+
+/**
+ * X11 implementation of GHOST_IWindow.
+ * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
+ * @author Laurence Bourn
+ * @date October 26, 2001
+ */
+
+class GHOST_WindowX11 : public GHOST_Window
+{
+public:
+ /**
+ * Constructor.
+ * Creates a new window and opens it.
+ * To check if the window was created properly, use the getValid() method.
+ * @param title The text shown in the title bar of the window.
+ * @param left The coordinate of the left edge of the window.
+ * @param top The coordinate of the top edge of the window.
+ * @param width The width the window.
+ * @param height The height the window.
+ * @param state The state the window is initially opened with.
+ * @param type The type of drawing context installed in this window.
+ * @param stereoVisual Stereo visual for quad buffered stereo.
+ */
+ GHOST_WindowX11(
+ GHOST_SystemX11 *system,
+ Display * display,
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool stereoVisual = false
+ );
+
+ bool
+ getValid(
+ ) const;
+
+ void
+ setTitle(const STR_String& title);
+
+ void
+ getTitle(
+ STR_String& title
+ ) const;
+
+ void
+ getWindowBounds(
+ GHOST_Rect& bounds
+ ) const;
+
+ void
+ getClientBounds(
+ GHOST_Rect& bounds
+ ) const;
+
+ GHOST_TSuccess
+ setClientWidth(
+ GHOST_TUns32 width
+ );
+
+ GHOST_TSuccess
+ setClientHeight(
+ GHOST_TUns32 height
+ );
+
+ GHOST_TSuccess
+ setClientSize(
+ GHOST_TUns32 width,
+ GHOST_TUns32 height
+ );
+
+ void
+ screenToClient(
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32& outX,
+ GHOST_TInt32& outY
+ ) const;
+
+ void
+ clientToScreen(
+ GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32& outX,
+ GHOST_TInt32& outY
+ ) const;
+
+ GHOST_TWindowState
+ getState(
+ ) const ;
+
+ GHOST_TSuccess
+ setState(
+ GHOST_TWindowState state
+ );
+
+ GHOST_TSuccess
+ setOrder(
+ GHOST_TWindowOrder order
+ );
+
+ GHOST_TSuccess
+ swapBuffers(
+ );
+
+ GHOST_TSuccess
+ activateDrawingContext(
+ );
+ GHOST_TSuccess
+ invalidate(
+ );
+
+ /**
+ * Destructor.
+ * Closes the window and disposes resources allocated.
+ */
+ ~GHOST_WindowX11();
+
+ /**
+ * @section
+ * X11 system specific calls.
+ */
+
+ /**
+ * The reverse of invalidate! Tells this window
+ * that all events for it have been pushed into
+ * the GHOST event queue.
+ */
+
+ void
+ validate(
+ );
+
+ /**
+ * Return a handle to the x11 window type.
+ */
+ Window
+ getXWindow(
+ );
+
+protected:
+ /**
+ * Tries to install a rendering context in this window.
+ * @param type The type of rendering context installed.
+ * @return Indication as to whether installation has succeeded.
+ */
+ GHOST_TSuccess
+ installDrawingContext(
+ GHOST_TDrawingContextType type
+ );
+
+ /**
+ * Removes the current drawing context.
+ * @return Indication as to whether removal has succeeded.
+ */
+ GHOST_TSuccess
+ removeDrawingContext(
+ );
+
+ /**
+ * Sets the cursor visibility on the window using
+ * native window system calls.
+ */
+ GHOST_TSuccess
+ setWindowCursorVisibility(
+ bool visible
+ );
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ GHOST_TSuccess
+ setWindowCursorShape(
+ GHOST_TStandardCursor shape
+ );
+
+ /**
+ * Sets the cursor shape on the window using
+ * native window system calls.
+ */
+ GHOST_TSuccess
+ setWindowCustomCursorShape(
+ GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2],
+ int hotX,
+ int hotY
+ );
+
+private :
+
+ /// Force use of public constructor.
+
+ GHOST_WindowX11(
+ );
+
+ GHOST_WindowX11(
+ const GHOST_WindowX11 &
+ );
+
+ Cursor
+ getStandardCursor(
+ GHOST_TStandardCursor g_cursor
+ );
+
+ Cursor
+ getEmptyCursor(
+ );
+
+ GLXContext m_context;
+ Window m_window;
+ Display *m_display;
+ XVisualInfo *m_visual;
+
+ /** The first created OpenGL context (for sharing display lists) */
+ static GLXContext s_firstContext;
+
+ /// A pointer to the typed system class.
+
+ GHOST_SystemX11 * m_system;
+
+ bool m_valid_setup;
+
+ /** Used to concatenate calls to invalidate() on this window. */
+ bool m_invalid_window;
+
+ /** XCursor structure of an empty (blank) cursor */
+ Cursor m_empty_cursor;
+
+ /** XCursor structure of the custom cursor */
+ Cursor m_custom_cursor;
+
+ /** Cache of XC_* ID's to XCursor structures */
+ std::map<unsigned int, Cursor> m_standard_cursors;
+};
+
+
+#endif // _GHOST_WINDOWX11_H_
diff --git a/intern/ghost/intern/Makefile b/intern/ghost/intern/Makefile
new file mode 100644
index 00000000000..8107a73ce58
--- /dev/null
+++ b/intern/ghost/intern/Makefile
@@ -0,0 +1,65 @@
+#
+# $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.
+#
+# 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 *****
+# ghost intern Makefile
+#
+
+LIBNAME = ghost
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+CCSRCS = GHOST_Buttons.cpp GHOST_System.cpp GHOST_Window.cpp
+CCSRCS += GHOST_EventManager.cpp GHOST_EventPrinter.cpp GHOST_WindowManager.cpp
+CCSRCS += GHOST_ISystem.cpp GHOST_ModifierKeys.cpp GHOST_TimerManager.cpp
+CCSRCS += GHOST_Rect.cpp GHOST_DisplayManager.cpp GHOST_C-api.cpp
+CCSRCS += GHOST_CallbackEventConsumer.cpp
+
+include nan_definitions.mk
+
+ifeq ($(OS),$(findstring $(OS), "darwin"))
+ CCSRCS += $(wildcard *Carbon.cpp)
+endif
+
+ifeq ($(OS),$(findstring $(OS), "windows"))
+ CCSRCS += $(wildcard *Win32.cpp)
+endif
+
+ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris"))
+ CCSRCS += $(wildcard *X11.cpp)
+endif
+
+include nan_compile.mk
+
+#CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+CPPFLAGS += -I..
+CPPFLAGS += -I$(OPENGL_HEADERS)
+
diff --git a/intern/ghost/make/msvc/ghost.dsp b/intern/ghost/make/msvc/ghost.dsp
new file mode 100644
index 00000000000..e58b4e8783e
--- /dev/null
+++ b/intern/ghost/make/msvc/ghost.dsp
@@ -0,0 +1,576 @@
+# Microsoft Developer Studio Project File - Name="ghost" - Package Owner=<4>
+
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+
+# ** DO NOT EDIT **
+
+
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+
+
+CFG=ghost - 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 "ghost.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 "ghost.mak" CFG="ghost - Win32 Debug"
+
+!MESSAGE
+
+!MESSAGE Possible choices for configuration are:
+
+!MESSAGE
+
+!MESSAGE "ghost - Win32 Release" (based on "Win32 (x86) Static Library")
+
+!MESSAGE "ghost - 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)" == "ghost - 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/ghost/"
+
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/"
+
+# 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" /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
+
+# Begin Special Build Tool
+
+SOURCE="$(InputPath)"
+
+PostBuild_Desc=Copying GHOST files library (release target) to lib tree.
+
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include\" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\libghost.a" ECHO Done
+
+# End Special Build Tool
+
+
+
+!ELSEIF "$(CFG)" == "ghost - 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/ghost/debug"
+
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/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" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /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
+
+# Begin Special Build Tool
+
+SOURCE="$(InputPath)"
+
+PostBuild_Desc=Copying GHOST files library (debug target) to lib tree.
+
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\debug\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\debug\libghost.a" ECHO Done
+
+# End Special Build Tool
+
+
+
+!ENDIF
+
+
+
+# Begin Target
+
+
+
+# Name "ghost - Win32 Release"
+
+# Name "ghost - Win32 Debug"
+
+# Begin Group "Header Files"
+
+
+
+# PROP Default_Filter ""
+
+# Begin Group "intern"
+
+
+
+# PROP Default_Filter ""
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Buttons.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Debug.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_DisplayManager.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_DisplayManagerWin32.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Event.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventButton.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventCursor.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventKey.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventManager.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventPrinter.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventWindow.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_ModifierKeys.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_System.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_SystemWin32.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_TimerManager.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_TimerTask.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Window.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_WindowManager.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_WindowWin32.h
+
+# End Source File
+
+# End Group
+
+# Begin Group "extern"
+
+
+
+# PROP Default_Filter ""
+
+# Begin Source File
+
+
+
+SOURCE="..\..\GHOST_C-api.h"
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_IEvent.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_IEventConsumer.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_ISystem.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_ITimerTask.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_IWindow.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_Rect.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\GHOST_Types.h
+
+# End Source File
+
+# End Group
+
+# End Group
+
+# Begin Group "Source Files"
+
+
+
+# PROP Default_Filter ""
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Buttons.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE="..\..\intern\GHOST_C-api.cpp"
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_CallbackEventConsumer.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_CallbackEventConsumer.h
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_DisplayManager.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_DisplayManagerWin32.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventManager.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_EventPrinter.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_ISystem.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_ModifierKeys.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Rect.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_System.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_SystemWin32.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_TimerManager.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_Window.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_WindowManager.cpp
+
+# End Source File
+
+# Begin Source File
+
+
+
+SOURCE=..\..\intern\GHOST_WindowWin32.cpp
+
+# End Source File
+
+# End Group
+
+# End Target
+
+# End Project
+
diff --git a/intern/ghost/make/msvc/ghost.dsw b/intern/ghost/make/msvc/ghost.dsw
new file mode 100644
index 00000000000..7ae428a5fb5
--- /dev/null
+++ b/intern/ghost/make/msvc/ghost.dsw
@@ -0,0 +1,58 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+
+
+###############################################################################
+
+
+
+Project: "ghost"=".\ghost.dsp" - Package Owner=<4>
+
+
+
+Package=<5>
+
+{{{
+
+}}}
+
+
+
+Package=<4>
+
+{{{
+
+}}}
+
+
+
+###############################################################################
+
+
+
+Global:
+
+
+
+Package=<5>
+
+{{{
+
+}}}
+
+
+
+Package=<3>
+
+{{{
+
+}}}
+
+
+
+###############################################################################
+
+
+
diff --git a/intern/ghost/test/Makefile b/intern/ghost/test/Makefile
new file mode 100755
index 00000000000..bbd1988a778
--- /dev/null
+++ b/intern/ghost/test/Makefile
@@ -0,0 +1,86 @@
+#
+# $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.
+#
+# 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 *****
+# GHOST test applications makefile.
+# This bounces to test application directories.
+#
+
+LIBNAME = ghost
+SOURCEDIR = intern/$(LIBNAME)/test
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = gears
+
+include nan_subdirs.mk
+
+include nan_compile.mk
+include nan_link.mk
+
+OCGGHOST = $(OCGDIR)/intern/$(LIBNAME)
+GEARDIR = $(OCGGHOST)/test/$(DEBUG_DIR)gears.app
+
+LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a
+SLIBS += $(LCGDIR)/string/lib/libstring.a
+
+all debug:: $(LIBS)
+ @echo "****> linking $@ in $(SOURCEDIR)"
+ifeq ($(OS),darwin)
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
+ @# set up directory structure for the OSX application bundle
+ @[ -d $(OCGGHOST)/test/ ] || mkdir $(OCGGHOST)/test/
+ @[ -d $(OCGGHOST)/test/debug ] || mkdir $(OCGGHOST)/test/debug
+ @[ -d $(GEARDIR) ] || mkdir $(GEARDIR)
+ @[ -d $(GEARDIR)/Contents ] || mkdir $(GEARDIR)/Contents
+ @[ -d $(GEARDIR)/Contents/MacOS ] || mkdir $(GEARDIR)/Contents/MacOS
+ @[ -d $(GEARDIR)/Contents/Resources ] || mkdir $(GEARDIR)/Contents/Resources
+ @[ -d $(GEARDIR)/Contents/Resources/English.lproj ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj
+ @[ -d $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib
+ @# copy the files into the bundle directory tree
+ cp -f $(DIR)/$(DEBUG_DIR)gears $(GEARDIR)/Contents/MacOS
+ cp -f gears/resources/osx/PkgInfo $(GEARDIR)/Contents/
+ cp -f gears/resources/osx/Info.plist $(GEARDIR)/Contents/
+ cp -f gears/resources/osx/English.lproj/InfoPlist.strings $(GEARDIR)/Contents/Resources/English.lproj
+ cp -f gears/resources/osx/English.lproj/MainMenu.nib/classes.nib $(GEARDIR)/Contents/Resources/English.lproj
+ cp -f gears/resources/osx/English.lproj/MainMenu.nib/info.nib $(GEARDIR)/Contents/Resources/English.lproj
+ cp -f gears/resources/osx/English.lproj/MainMenu.nib/objects.nib $(GEARDIR)/Contents/Resources/English.lproj
+else
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_cpp $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_c $(DIR)/$(DEBUG_DIR)GHOST_C-Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
+endif
+
+clean::
+ @# mac stuff. well ok, only the binary
+ @rm -f $(DIR)/gears $(DIR)/debug/gears
+ @# others
+ @rm -f $(DIR)/gears_c $(DIR)/debug/gears_c
+ @rm -f $(DIR)/gears_cpp $(DIR)/debug/gears_cpp
+
+test:: all
+ $(DIR)/gears_cpp
+ $(DIR)/gears_c
diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c
new file mode 100644
index 00000000000..16d8b421d5b
--- /dev/null
+++ b/intern/ghost/test/gears/GHOST_C-Test.c
@@ -0,0 +1,543 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * Simple test file for the GHOST library.
+ * The OpenGL gear code is taken from the Qt sample code which,
+ * in turn, is probably taken from somewhere as well.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "GHOST_C-api.h"
+
+#if defined(WIN32) || defined(__APPLE__)
+ #ifdef WIN32
+ #include <windows.h>
+ #include <GL/gl.h>
+ #else /* WIN32 */
+ /* __APPLE__ is defined */
+ #include <AGL/gl.h>
+ #endif /* WIN32 */
+#else /* defined(WIN32) || defined(__APPLE__) */
+ #include <GL/gl.h>
+#endif /* defined(WIN32) || defined(__APPLE__) */
+
+
+static void gearsTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time);
+
+static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
+static GLfloat fAngle = 0.0;
+static int sExitRequested = 0;
+static GHOST_SystemHandle shSystem = NULL;
+static GHOST_WindowHandle sMainWindow = NULL;
+static GHOST_WindowHandle sSecondaryWindow = NULL;
+static GHOST_TStandardCursor sCursor = GHOST_kStandardCursorFirstCursor;
+static GHOST_WindowHandle sFullScreenWindow = NULL;
+static GHOST_TimerTaskHandle sTestTimer;
+static GHOST_TimerTaskHandle sGearsTimer;
+
+
+static void testTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time)
+{
+ printf("timer1, time=%d\n", (int)time);
+}
+
+
+static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+ const double pi = 3.14159264;
+
+ r0 = inner_radius;
+ r1 = (float)(outer_radius - tooth_depth/2.0);
+ r2 = (float)(outer_radius + tooth_depth/2.0);
+
+ da = (float)(2.0*pi / teeth / 4.0);
+
+ glShadeModel(GL_FLAT);
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = (float)(2.0*pi / teeth / 4.0);
+ for (i=0;i<teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
+ glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5));
+ glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = (float)(2.0*pi / teeth / 4.0);
+ for (i=0;i<teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
+ glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5));
+ glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5));
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
+ u = (float)(r2*cos(angle+da) - r1*cos(angle));
+ v = (float)(r2*sin(angle+da) - r1*sin(angle));
+ len = (float)(sqrt(u*u + v*v));
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5));
+ glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5));
+ glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0);
+ glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5));
+ glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5));
+ u = (float)(r1*cos(angle+3*da) - r2*cos(angle+2*da));
+ v = (float)(r1*sin(angle+3*da) - r2*sin(angle+2*da));
+ glNormal3f(v, -u, 0.0);
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
+ glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0);
+ }
+ glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(width*0.5));
+ glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(-width*0.5));
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = (float)(i * 2.0*pi / teeth);
+ glNormal3f((float)(-cos(angle)), (float)(-sin(angle)), 0.0);
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
+ glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
+ }
+ glEnd();
+}
+
+
+
+static void drawGearGL(int id)
+{
+ static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
+ static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
+ static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
+ static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ switch (id)
+ {
+ case 1:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
+ gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ break;
+ case 2:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
+ gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ break;
+ case 3:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
+ gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ break;
+ default:
+ break;
+ }
+ glEnable(GL_NORMALIZE);
+}
+
+
+static void drawGL(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(fAngle, 0.0, 0.0, 1.0);
+ drawGearGL(1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1f, -2.0f, 0.0f);
+ glRotatef((float)(-2.0*fAngle-9.0), 0.0, 0.0, 1.0);
+ drawGearGL(2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1f, 2.2f, -1.8f);
+ glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef((float)(2.0*fAngle-2.0), 0.0, 0.0, 1.0);
+ drawGearGL(3);
+ glPopMatrix();
+
+ glPopMatrix();
+}
+
+
+static void setViewPortGL(GHOST_WindowHandle hWindow)
+{
+ GHOST_RectangleHandle hRect = NULL;
+ GLfloat w, h;
+
+ GHOST_ActivateWindowDrawingContext(hWindow);
+ hRect = GHOST_GetClientBounds(hWindow);
+
+ w = (float)GHOST_GetWidthRectangle(hRect) / (float)GHOST_GetHeightRectangle(hRect);
+ h = 1.0;
+
+ glViewport(0, 0, GHOST_GetWidthRectangle(hRect), GHOST_GetHeightRectangle(hRect));
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-w, w, -h, h, 5.0, 60.0);
+ /* glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); */
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ glClearColor(.2f,0.0f,0.0f,0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ GHOST_DisposeRectangle(hRect);
+}
+
+
+
+int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
+{
+ int handled = 1;
+ int cursor;
+ int visibility;
+ GHOST_TEventKeyData* keyData = NULL;
+ GHOST_DisplaySetting setting;
+ GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent);
+
+ switch (GHOST_GetEventType(hEvent))
+ {
+ /*
+ case GHOST_kEventUnknown:
+ break;
+ case GHOST_kEventCursorButton:
+ break;
+ case GHOST_kEventCursorMove:
+ break;
+ */
+ case GHOST_kEventKeyUp:
+ break;
+
+ case GHOST_kEventKeyDown:
+ {
+ keyData = (GHOST_TEventKeyData*)GHOST_GetEventData(hEvent);
+ switch (keyData->key)
+ {
+ case GHOST_kKeyC:
+ {
+ cursor = sCursor;
+ cursor++;
+ if (cursor >= GHOST_kStandardCursorNumCursors)
+ {
+ cursor = GHOST_kStandardCursorFirstCursor;
+ }
+ sCursor = (GHOST_TStandardCursor)cursor;
+ GHOST_SetCursorShape(window, sCursor);
+ }
+ break;
+ case GHOST_kKeyF:
+ if (!GHOST_GetFullScreen(shSystem))
+ {
+ /* Begin fullscreen mode */
+ setting.bpp = 24;
+ setting.frequency = 85;
+ setting.xPixels = 640;
+ setting.yPixels = 480;
+
+ /*
+ setting.bpp = 16;
+ setting.frequency = 75;
+ setting.xPixels = 640;
+ setting.yPixels = 480;
+ */
+
+ sFullScreenWindow = GHOST_BeginFullScreen(shSystem, &setting,
+ false /* stereo flag */);
+ }
+ else
+ {
+ GHOST_EndFullScreen(shSystem);
+ sFullScreenWindow = 0;
+ }
+ break;
+ case GHOST_kKeyH:
+ {
+ visibility = GHOST_GetCursorVisibility(window);
+ GHOST_SetCursorVisibility(window, !visibility);
+ }
+ break;
+ case GHOST_kKeyQ:
+ if (GHOST_GetFullScreen(shSystem))
+ {
+ GHOST_EndFullScreen(shSystem);
+ sFullScreenWindow = 0;
+ }
+ sExitRequested = 1;
+ case GHOST_kKeyT:
+ if (!sTestTimer)
+ {
+ sTestTimer = GHOST_InstallTimer(shSystem, 0, 1000, testTimerProc, NULL);
+ }
+ else
+ {
+ GHOST_RemoveTimer(shSystem, sTestTimer);
+ sTestTimer = 0;
+ }
+ break;
+ case GHOST_kKeyW:
+ {
+ if (sMainWindow)
+ {
+ char *title = GHOST_GetTitle(sMainWindow);
+ char *ntitle = malloc(strlen(title)+2);
+
+ sprintf(ntitle, "%s-", title);
+ GHOST_SetTitle(sMainWindow, ntitle);
+
+ free(ntitle);
+ free(title);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case GHOST_kEventWindowClose:
+ {
+ GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent);
+ if (window == sMainWindow)
+ {
+ sExitRequested = 1;
+ }
+ else
+ {
+ if (sGearsTimer)
+ {
+ GHOST_RemoveTimer(shSystem, sGearsTimer);
+ sGearsTimer = 0;
+ }
+ GHOST_DisposeWindow(shSystem, window);
+ }
+ }
+ break;
+
+ case GHOST_kEventWindowActivate:
+ handled = 0;
+ break;
+ case GHOST_kEventWindowDeactivate:
+ handled = 0;
+ break;
+ case GHOST_kEventWindowUpdate:
+ {
+ GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent);
+ if (!GHOST_ValidWindow(shSystem, window))
+ break;
+ //if (!m_fullScreenWindow)
+ {
+ setViewPortGL(window);
+ drawGL();
+ GHOST_SwapWindowBuffers(window);
+ }
+ }
+ break;
+
+ default:
+ handled = 0;
+ break;
+ }
+ return handled;
+}
+
+
+int main(int argc, char** argv)
+{
+ char* title1 = "gears - main window";
+ char* title2 = "gears - secondary window";
+ GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
+
+ /* Create the system */
+ shSystem = GHOST_CreateSystem();
+ GHOST_AddEventConsumer(shSystem, consumer);
+
+ if (shSystem)
+ {
+ /* Create the main window */
+ sMainWindow = GHOST_CreateWindow(shSystem,
+ title1,
+ 10,
+ 64,
+ 320,
+ 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL);
+ if (!sMainWindow)
+ {
+ printf("could not create main window\n");
+ exit(-1);
+ }
+
+ /* Create a secondary window */
+ sSecondaryWindow = GHOST_CreateWindow(shSystem,
+ title2,
+ 340,
+ 64,
+ 320,
+ 200,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL);
+ if (!sSecondaryWindow)
+ {
+ printf("could not create secondary window\n");
+ exit(-1);
+ }
+
+ /* Install a timer to have the gears running */
+ sGearsTimer = GHOST_InstallTimer(shSystem,
+ 0,
+ 10,
+ gearsTimerProc,
+ sMainWindow);
+
+ /* Enter main loop */
+ while (!sExitRequested)
+ {
+ if (!GHOST_ProcessEvents(shSystem, 0))
+ {
+#ifdef WIN32
+ /* If there were no events, be nice to other applications */
+ Sleep(10);
+#endif
+ }
+ GHOST_DispatchEvents(shSystem);
+ }
+ }
+
+ /* Dispose windows */
+ if (GHOST_ValidWindow(shSystem, sMainWindow))
+ {
+ GHOST_DisposeWindow(shSystem, sMainWindow);
+ }
+ if (GHOST_ValidWindow(shSystem, sSecondaryWindow))
+ {
+ GHOST_DisposeWindow(shSystem, sSecondaryWindow);
+ }
+
+ /* Dispose the system */
+ GHOST_DisposeSystem(shSystem);
+ GHOST_DisposeEventConsumer(consumer);
+
+ return 0;
+}
+
+
+static void gearsTimerProc(GHOST_TimerTaskHandle hTask, GHOST_TUns64 time)
+{
+ GHOST_WindowHandle hWindow = NULL;
+ fAngle += 2.0;
+ view_roty += 1.0;
+ hWindow = (GHOST_WindowHandle)GHOST_GetTimerTaskUserData(hTask);
+ if (GHOST_GetFullScreen(shSystem))
+ {
+ /* Running full screen */
+ GHOST_InvalidateWindow(sFullScreenWindow);
+ }
+ else
+ {
+ if (GHOST_ValidWindow(shSystem, hWindow))
+ {
+ GHOST_InvalidateWindow(hWindow);
+ }
+ }
+}
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
new file mode 100755
index 00000000000..a5459c9da9b
--- /dev/null
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -0,0 +1,745 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Simple test file for the GHOST library.
+ * The OpenGL gear code is taken from the Qt sample code which,
+ * in turn, is probably taken from somewhere as well.
+ * @author Maarten Gribnau
+ * @date May 31, 2001
+ * Stereo code by Raymond de Vries, januari 2002
+ */
+
+#include <iostream>
+#include <math.h>
+
+#if defined(WIN32) || defined(__APPLE__)
+ #ifdef WIN32
+ #include <windows.h>
+ #include <atlbase.h>
+
+ #include <GL/gl.h>
+ #else // WIN32
+ // __APPLE__ is defined
+ #include <AGL/gl.h>
+ #endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+ #include <GL/gl.h>
+#endif // defined(WIN32) || defined(__APPLE__)
+
+#include "STR_String.h"
+#include "GHOST_Rect.h"
+
+#include "GHOST_ISystem.h"
+#include "GHOST_IEvent.h"
+#include "GHOST_IEventConsumer.h"
+
+
+#define LEFT_EYE 0
+#define RIGHT_EYE 1
+
+static bool nVidiaWindows; // very dirty but hey, it's for testing only
+
+static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
+
+static class Application* fApp;
+static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
+static GLfloat fAngle = 0.0;
+static GHOST_ISystem* fSystem = 0;
+
+
+void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
+ float zero_plane, float dist,
+ float eye);
+
+
+static void testTimerProc(GHOST_ITimerTask* /*task*/, GHOST_TUns64 time)
+{
+ std::cout << "timer1, time=" << (int)time << "\n";
+}
+
+
+static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth/2.0;
+ r2 = outer_radius + tooth_depth/2.0;
+
+ const double pi = 3.14159264;
+ da = 2.0*pi / teeth / 4.0;
+
+ glShadeModel(GL_FLAT);
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
+ glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
+ glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
+ glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
+ glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
+ glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
+ glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
+ glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
+ glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
+ glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
+ glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
+ u = r2*cos(angle+da) - r1*cos(angle);
+ v = r2*sin(angle+da) - r1*sin(angle);
+ len = sqrt(u*u + v*v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
+ glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
+ glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
+ u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
+ v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
+ glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ }
+ glVertex3f(r1*cos(0.0), r1*sin(0.0), width*0.5);
+ glVertex3f(r1*cos(0.0), r1*sin(0.0), -width*0.5);
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glNormal3f(-cos(angle), -sin(angle), 0.0);
+ glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
+ glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
+ }
+ glEnd();
+}
+
+
+
+static void drawGearGL(int id)
+{
+ static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
+ static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
+ static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
+ static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ switch (id)
+ {
+ case 1:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
+ gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
+ break;
+ case 2:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
+ gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
+ break;
+ case 3:
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
+ gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
+ break;
+ default:
+ break;
+ }
+ glEnable(GL_NORMALIZE);
+}
+
+
+void RenderCamera()
+{
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+}
+
+
+void RenderScene()
+{
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(fAngle, 0.0, 0.0, 1.0);
+ drawGearGL(1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1f, -2.0f, 0.0f);
+ glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0);
+ drawGearGL(2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1f, 2.2f, -1.8f);
+ glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0);
+ drawGearGL(3);
+ glPopMatrix();
+}
+
+
+static void View(GHOST_IWindow* window, bool stereo, int eye = 0)
+{
+ window->activateDrawingContext();
+ GHOST_Rect bnds;
+ int noOfScanlines = 0, lowerScanline;
+ int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant
+ float left, right, bottom, top;
+ float nearplane, farplane, zeroPlane, distance;
+ float eyeSeparation = 0.62;
+ window->getClientBounds(bnds);
+ GLfloat w = float(bnds.getWidth()) / float(bnds.getHeight());
+ GLfloat h = 1.0;
+
+ // viewport
+ if(stereo)
+ {
+ if(nVidiaWindows)
+ {
+ // handled by nVidia driver so act as normal (explicitly put here since
+ // it -is- stereo)
+ glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
+ }
+ else
+ { // generic cross platform above-below stereo
+ noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2;
+ switch(eye)
+ {
+ case LEFT_EYE:
+ // upper half of window
+ lowerScanline = bnds.getHeight() - noOfScanlines;
+ break;
+ case RIGHT_EYE:
+ // lower half of window
+ lowerScanline = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ noOfScanlines = bnds.getHeight();
+ lowerScanline = 0;
+ }
+
+ glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines);
+
+ // projection
+ left = -6.0;
+ right = 6.0;
+ bottom = -4.8;
+ top = 4.8;
+ nearplane = 5.0;
+ farplane = 60.0;
+
+ if(stereo)
+ {
+ zeroPlane = 0.0;
+ distance = 14.5;
+ switch(eye)
+ {
+ case LEFT_EYE:
+ StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0);
+ break;
+ case RIGHT_EYE:
+ StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0);
+ break;
+ }
+ }
+ else
+ {
+// left = -w;
+// right = w;
+// bottom = -h;
+// top = h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(left, right, bottom, top, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ }
+
+ glClearColor(.2f,0.0f,0.0f,0.0f);
+}
+
+
+void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
+ float zero_plane, float dist,
+ float eye)
+/* Perform the perspective projection for one eye's subfield.
+The projection is in the direction of the negative z axis.
+
+-6.0, 6.0, -4.8, 4.8,
+left, right, bottom, top = the coordinate range, in the plane of zero
+parallax setting, which will be displayed on the screen. The
+ratio between (right-left) and (top-bottom) should equal the aspect
+ratio of the display.
+
+6.0, -6.0,
+near, far = the z-coordinate values of the clipping planes.
+
+0.0,
+zero_plane = the z-coordinate of the plane of zero parallax setting.
+
+14.5,
+dist = the distance from the center of projection to the plane
+of zero parallax.
+
+-0.31
+eye = half the eye separation; positive for the right eye subfield,
+negative for the left eye subfield.
+*/
+{
+ float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw,
+ dx, dy, n_over_d;
+
+ dx = right - left;
+ dy = top - bottom;
+
+ xmid = (right + left) / 2.0;
+ ymid = (top + bottom) / 2.0;
+
+ clip_near = dist + zero_plane - nearplane;
+ clip_far = dist + zero_plane - farplane;
+
+ n_over_d = clip_near / dist;
+
+ topw = n_over_d * dy / 2.0;
+ bottomw = -topw;
+ rightw = n_over_d * (dx / 2.0 - eye);
+ leftw = n_over_d *(-dx / 2.0 - eye);
+
+ /* Need to be in projection mode for this. */
+ glLoadIdentity();
+ glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
+
+ glTranslatef(-xmid - eye, -ymid, -zero_plane - dist);
+ return;
+} /* stereoproj */
+
+
+class Application : public GHOST_IEventConsumer {
+public:
+ Application(GHOST_ISystem* system);
+ ~Application(void);
+ virtual bool processEvent(GHOST_IEvent* event);
+
+ GHOST_ISystem* m_system;
+ GHOST_IWindow* m_mainWindow;
+ GHOST_IWindow* m_secondaryWindow;
+ GHOST_IWindow* m_fullScreenWindow;
+ GHOST_ITimerTask* m_gearsTimer, *m_testTimer;
+ GHOST_TStandardCursor m_cursor;
+ bool m_exitRequested;
+
+ bool stereo;
+};
+
+
+Application::Application(GHOST_ISystem* system)
+ : m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0),
+ m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
+ m_exitRequested(false), stereo(false)
+{
+ fApp = this;
+
+ // Create the main window
+ STR_String title1 ("gears - main window");
+ m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL, true /* stereo flag */);
+
+ if (!m_mainWindow) {
+ std::cout << "could not create main window\n";
+ exit(-1);
+ }
+
+ // Create a secondary window
+ STR_String title2 ("gears - secondary window");
+ m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL, false /* stereo flag */);
+ if (!m_secondaryWindow) {
+ cout << "could not create secondary window\n";
+ exit(-1);
+ }
+
+ // Install a timer to have the gears running
+ m_gearsTimer = system->installTimer(0 /*delay*/, 20/*interval*/, gearsTimerProc, m_mainWindow);
+}
+
+
+Application::~Application(void)
+{
+ // Dispose windows
+ if (m_system->validWindow(m_mainWindow)) {
+ m_system->disposeWindow(m_mainWindow);
+ }
+ if (m_system->validWindow(m_secondaryWindow)) {
+ m_system->disposeWindow(m_secondaryWindow);
+ }
+}
+
+
+bool Application::processEvent(GHOST_IEvent* event)
+{
+ GHOST_IWindow* window = event->getWindow();
+ bool handled = true;
+
+ switch (event->getType()) {
+/* case GHOST_kEventUnknown:
+ break;
+ case GHOST_kEventCursorButton:
+ std::cout << "GHOST_kEventCursorButton"; break;
+ case GHOST_kEventCursorMove:
+ std::cout << "GHOST_kEventCursorMove"; break;
+*/
+ case GHOST_kEventKeyUp:
+ break;
+
+ case GHOST_kEventKeyDown:
+ {
+ GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*) event->getData();
+ switch (keyData->key) {
+ case GHOST_kKeyC:
+ {
+ int cursor = m_cursor;
+ cursor++;
+ if (cursor >= GHOST_kStandardCursorNumCursors) {
+ cursor = GHOST_kStandardCursorFirstCursor;
+ }
+ m_cursor = (GHOST_TStandardCursor)cursor;
+ window->setCursorShape(m_cursor);
+ }
+ break;
+
+ case GHOST_kKeyE:
+ {
+ int x = 200, y= 200;
+ m_system->setCursorPosition(x,y);
+ break;
+ }
+
+ case GHOST_kKeyF:
+ if (!m_system->getFullScreen()) {
+ // Begin fullscreen mode
+ GHOST_DisplaySetting setting;
+
+ setting.bpp = 16;
+ setting.frequency = 50;
+ setting.xPixels = 640;
+ setting.yPixels = 480;
+ m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */);
+ }
+ else {
+ m_system->endFullScreen();
+ m_fullScreenWindow = 0;
+ }
+ break;
+
+ case GHOST_kKeyH:
+ window->setCursorVisibility(!window->getCursorVisibility());
+ break;
+
+ case GHOST_kKeyM:
+ {
+ bool down = false;
+ m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift,down);
+ if (down) {
+ std::cout << "left shift down\n";
+ }
+ m_system->getModifierKeyState(GHOST_kModifierKeyRightShift,down);
+ if (down) {
+ std::cout << "right shift down\n"; }
+ m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt,down);
+ if (down) {
+ std::cout << "left Alt down\n";
+ }
+ m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt,down);
+ if (down) {
+ std::cout << "right Alt down\n";
+ }
+ m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl,down);
+ if (down) {
+ std::cout << "left control down\n";
+ }
+ m_system->getModifierKeyState(GHOST_kModifierKeyRightControl,down);
+ if (down) {
+ std::cout << "right control down\n";
+ }
+ }
+ break;
+
+ case GHOST_kKeyQ:
+ if (m_system->getFullScreen())
+ {
+ m_system->endFullScreen();
+ m_fullScreenWindow = 0;
+ }
+ m_exitRequested = true;
+ break;
+
+ case GHOST_kKeyS: // toggle mono and stereo
+ if(stereo)
+ stereo = false;
+ else
+ stereo = true;
+ break;
+
+ case GHOST_kKeyT:
+ if (!m_testTimer) {
+ m_testTimer = m_system->installTimer(0, 1000, testTimerProc);
+ }
+
+ else {
+ m_system->removeTimer(m_testTimer);
+ m_testTimer = 0;
+ }
+
+ break;
+
+ case GHOST_kKeyW:
+ if (m_mainWindow)
+ {
+ STR_String title;
+ m_mainWindow->getTitle(title);
+ title += "-";
+ m_mainWindow->setTitle(title);
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case GHOST_kEventWindowClose:
+ {
+ GHOST_IWindow* window = event->getWindow();
+ if (window == m_mainWindow) {
+ m_exitRequested = true;
+ }
+ else {
+ m_system->disposeWindow(window);
+ }
+ }
+ break;
+
+ case GHOST_kEventWindowActivate:
+ handled = false;
+ break;
+
+ case GHOST_kEventWindowDeactivate:
+ handled = false;
+ break;
+
+ case GHOST_kEventWindowUpdate:
+ {
+ GHOST_IWindow* window = event->getWindow();
+ if(!m_system->validWindow(window))
+ break;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if(stereo)
+ {
+ View(window, stereo, LEFT_EYE);
+ glPushMatrix();
+ RenderCamera();
+ RenderScene();
+ glPopMatrix();
+
+ View(window, stereo, RIGHT_EYE);
+ glPushMatrix();
+ RenderCamera();
+ RenderScene();
+ glPopMatrix();
+ }
+ else
+ {
+ View(window, stereo);
+ glPushMatrix();
+ RenderCamera();
+ RenderScene();
+ glPopMatrix();
+ }
+ window->swapBuffers();
+ }
+ break;
+
+ default:
+ handled = false;
+ break;
+ }
+ return handled;
+}
+
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ nVidiaWindows = false;
+// nVidiaWindows = true;
+
+#ifdef WIN32
+ /* Set a couple of settings in the registry for the nVidia detonator driver.
+ * So this is very specific...
+ */
+ if(nVidiaWindows)
+ {
+ LONG lresult;
+ HKEY hkey = 0;
+ DWORD dwd = 0;
+ unsigned char buffer[128];
+
+ CRegKey regkey;
+ DWORD keyValue;
+// lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable");
+ lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
+ KEY_ALL_ACCESS );
+
+ if(lresult == ERROR_SUCCESS)
+ printf("Succesfully opened key\n");
+#if 0
+ lresult = regkey.QueryValue(&keyValue, "StereoEnable");
+ if(lresult == ERROR_SUCCESS)
+ printf("Succesfully queried key\n");
+#endif
+ lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
+ "1");
+ if(lresult == ERROR_SUCCESS)
+ printf("Succesfully set value for key\n");
+ regkey.Close();
+ if(lresult == ERROR_SUCCESS)
+ printf("Succesfully closed key\n");
+// regkey.Write("2");
+ }
+#endif // WIN32
+
+ // Create the system
+ GHOST_ISystem::createSystem();
+ fSystem = GHOST_ISystem::getSystem();
+
+ if (fSystem) {
+ // Create an application object
+ Application app (fSystem);
+
+ // Add the application as event consumer
+ fSystem->addEventConsumer(&app);
+
+ // Enter main loop
+ while (!app.m_exitRequested) {
+ //printf("main: loop\n");
+ fSystem->processEvents(true);
+ fSystem->dispatchEvents();
+ }
+ }
+
+ // Dispose the system
+ GHOST_ISystem::disposeSystem();
+
+ return 0;
+}
+
+
+static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 /*time*/)
+{
+ fAngle += 2.0;
+ view_roty += 1.0;
+ GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
+ if (fApp->m_fullScreenWindow) {
+ // Running full screen
+ fApp->m_fullScreenWindow->invalidate();
+ }
+ else {
+ if (fSystem->validWindow(window)) {
+ window->invalidate();
+ }
+ }
+}
diff --git a/intern/ghost/test/gears/Makefile b/intern/ghost/test/gears/Makefile
new file mode 100755
index 00000000000..b7966b4d157
--- /dev/null
+++ b/intern/ghost/test/gears/Makefile
@@ -0,0 +1,48 @@
+#
+# $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.
+#
+# 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 *****
+# GHOST gears test application Makefile
+#
+
+LIBNAME = gearstest
+DIR = $(OCGDIR)/intern/ghost/test
+
+# we don't want a library here, only object files:
+ALLTARGETS = $(OBJS)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_2_C_WARNINGS)
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I../..
+
diff --git a/intern/ghost/test/make/msvc_6_0/gears.dsp b/intern/ghost/test/make/msvc_6_0/gears.dsp
new file mode 100644
index 00000000000..3e809a6b604
--- /dev/null
+++ b/intern/ghost/test/make/msvc_6_0/gears.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="gears" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gears - 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 "gears.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 "gears.mak" CFG="gears - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gears - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gears - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gears - 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/ghost/test/"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "gears - 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/ghost/test/debug"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "gears - Win32 Release"
+# Name "gears - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\gears\GHOST_Test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/intern/ghost/test/make/msvc_6_0/gears_C.dsp b/intern/ghost/test/make/msvc_6_0/gears_C.dsp
new file mode 100644
index 00000000000..5972d123268
--- /dev/null
+++ b/intern/ghost/test/make/msvc_6_0/gears_C.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="gears_C" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gears_C - 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 "gears_C.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 "gears_C.mak" CFG="gears_C - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gears_C - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gears_C - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gears_C - 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/ghost/test/"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "gears_C - 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/ghost/test/debug"
+# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "gears_C - Win32 Release"
+# Name "gears_C - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\gears\GHOST_C-Test.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/intern/ghost/test/make/msvc_6_0/ghost_test.dsw b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw
new file mode 100644
index 00000000000..03bf5eb5c9a
--- /dev/null
+++ b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw
@@ -0,0 +1,77 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gears"=.\gears.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ghost
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name string
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gears_C"=.\gears_C.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name ghost
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name string
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ghost"=..\..\..\make\msvc\ghost.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "string"=..\..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/ghost/test/multitest/Basic.c b/intern/ghost/test/multitest/Basic.c
new file mode 100644
index 00000000000..c26cf7c92ca
--- /dev/null
+++ b/intern/ghost/test/multitest/Basic.c
@@ -0,0 +1,68 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "Basic.h"
+
+
+int min_i(int a, int b) {
+ return (a<b)?a:b;
+}
+int max_i(int a, int b) {
+ return (b<a)?a:b;
+}
+int clamp_i(int val, int min, int max) {
+ return min_i(max_i(val, min), max);
+}
+
+float min_f(float a, float b) {
+ return (a<b)?a:b;
+}
+float max_f(float a, float b) {
+ return (b<a)?a:b;
+}
+float clamp_f(float val, float min, float max) {
+ return min_f(max_f(val, min), max);
+}
+
+void rect_copy(int dst[2][2], int src[2][2]) {
+ dst[0][0]= src[0][0], dst[0][1]= src[0][1];
+ dst[1][0]= src[1][0], dst[1][1]= src[1][1];
+}
+int rect_contains_pt(int rect[2][2], int pt[2]){
+ return ((rect[0][0] <= pt[0] && pt[0] <= rect[1][0]) &&
+ (rect[0][1] <= pt[1] && pt[1] <= rect[1][1]));
+}
+int rect_width(int rect[2][2]) {
+ return (rect[1][0]-rect[0][0]);
+}
+int rect_height(int rect[2][2]) {
+ return (rect[1][1]-rect[0][1]);
+}
diff --git a/intern/ghost/test/multitest/Basic.h b/intern/ghost/test/multitest/Basic.h
new file mode 100644
index 00000000000..f81f4684bcc
--- /dev/null
+++ b/intern/ghost/test/multitest/Basic.h
@@ -0,0 +1,44 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+int min_i (int a, int b);
+
+int max_i (int a, int b);
+int clamp_i (int val, int min, int max);
+
+float min_f (float a, float b);
+float max_f (float a, float b);
+float clamp_f (float val, float min, float max);
+
+void rect_copy (int dst[2][2], int src[2][2]);
+int rect_contains_pt (int rect[2][2], int pt[2]);
+int rect_width (int rect[2][2]);
+int rect_height (int rect[2][2]);
diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c
new file mode 100644
index 00000000000..950d80a2468
--- /dev/null
+++ b/intern/ghost/test/multitest/EventToBuf.c
@@ -0,0 +1,236 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <stdlib.h>
+
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "GHOST_C-api.h"
+#include "EventToBuf.h"
+
+char *eventtype_to_string(GHOST_TEventType type) {
+ switch(type) {
+ case GHOST_kEventCursorMove: return "CursorMove";
+ case GHOST_kEventButtonDown: return "ButtonDown";
+ case GHOST_kEventButtonUp: return "ButtonUp";
+
+ case GHOST_kEventKeyDown: return "KeyDown";
+ case GHOST_kEventKeyUp: return "KeyUp";
+
+ case GHOST_kEventQuit: return "Quit";
+
+ case GHOST_kEventWindowClose: return "WindowClose";
+ case GHOST_kEventWindowActivate: return "WindowActivate";
+ case GHOST_kEventWindowDeactivate: return "WindowDeactivate";
+ case GHOST_kEventWindowUpdate: return "WindowUpdate";
+ case GHOST_kEventWindowSize: return "WindowSize";
+ default:
+ return "<invalid>";
+ }
+}
+
+static char *keytype_to_string(GHOST_TKey key) {
+#define K(key) case GHOST_k##key: return #key;
+ switch (key) {
+ K(KeyBackSpace);
+ K(KeyTab);
+ K(KeyLinefeed);
+ K(KeyClear);
+ K(KeyEnter);
+
+ K(KeyEsc);
+ K(KeySpace);
+ K(KeyQuote);
+ K(KeyComma);
+ K(KeyMinus);
+ K(KeyPeriod);
+ K(KeySlash);
+
+ K(Key0);
+ K(Key1);
+ K(Key2);
+ K(Key3);
+ K(Key4);
+ K(Key5);
+ K(Key6);
+ K(Key7);
+ K(Key8);
+ K(Key9);
+
+ K(KeySemicolon);
+ K(KeyEqual);
+
+ K(KeyA);
+ K(KeyB);
+ K(KeyC);
+ K(KeyD);
+ K(KeyE);
+ K(KeyF);
+ K(KeyG);
+ K(KeyH);
+ K(KeyI);
+ K(KeyJ);
+ K(KeyK);
+ K(KeyL);
+ K(KeyM);
+ K(KeyN);
+ K(KeyO);
+ K(KeyP);
+ K(KeyQ);
+ K(KeyR);
+ K(KeyS);
+ K(KeyT);
+ K(KeyU);
+ K(KeyV);
+ K(KeyW);
+ K(KeyX);
+ K(KeyY);
+ K(KeyZ);
+
+ K(KeyLeftBracket);
+ K(KeyRightBracket);
+ K(KeyBackslash);
+ K(KeyAccentGrave);
+
+ K(KeyLeftShift);
+ K(KeyRightShift);
+ K(KeyLeftControl);
+ K(KeyRightControl);
+ K(KeyLeftAlt);
+ K(KeyRightAlt);
+ K(KeyCommand);
+
+ K(KeyCapsLock);
+ K(KeyNumLock);
+ K(KeyScrollLock);
+
+ K(KeyLeftArrow);
+ K(KeyRightArrow);
+ K(KeyUpArrow);
+ K(KeyDownArrow);
+
+ K(KeyPrintScreen);
+ K(KeyPause);
+
+ K(KeyInsert);
+ K(KeyDelete);
+ K(KeyHome);
+ K(KeyEnd);
+ K(KeyUpPage);
+ K(KeyDownPage);
+
+ K(KeyNumpad0);
+ K(KeyNumpad1);
+ K(KeyNumpad2);
+ K(KeyNumpad3);
+ K(KeyNumpad4);
+ K(KeyNumpad5);
+ K(KeyNumpad6);
+ K(KeyNumpad7);
+ K(KeyNumpad8);
+ K(KeyNumpad9);
+ K(KeyNumpadPeriod);
+ K(KeyNumpadEnter);
+ K(KeyNumpadPlus);
+ K(KeyNumpadMinus);
+ K(KeyNumpadAsterisk);
+ K(KeyNumpadSlash);
+
+ K(KeyF1);
+ K(KeyF2);
+ K(KeyF3);
+ K(KeyF4);
+ K(KeyF5);
+ K(KeyF6);
+ K(KeyF7);
+ K(KeyF8);
+ K(KeyF9);
+ K(KeyF10);
+ K(KeyF11);
+ K(KeyF12);
+ K(KeyF13);
+ K(KeyF14);
+ K(KeyF15);
+ K(KeyF16);
+ K(KeyF17);
+ K(KeyF18);
+ K(KeyF19);
+ K(KeyF20);
+ K(KeyF21);
+ K(KeyF22);
+ K(KeyF23);
+ K(KeyF24);
+
+ default:
+ return "KeyUnknown";
+ }
+#undef K
+}
+
+void event_to_buf(GHOST_EventHandle evt, char buf[128]) {
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+ double time= (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000;
+ GHOST_WindowHandle win= GHOST_GetEventWindow(evt);
+ void *data= GHOST_GetEventData(evt);
+ char *pos= buf;
+
+ pos+= sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type));
+ if (win) {
+ char *s= GHOST_GetTitle(win);
+ pos+= sprintf(pos, " - win: %s", s);
+ free(s);
+ } else {
+ pos+= sprintf(pos, " - sys evt");
+ }
+ switch (type) {
+ case GHOST_kEventCursorMove: {
+ GHOST_TEventCursorData *cd= data;
+ pos+= sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y);
+ break;
+ }
+ case GHOST_kEventButtonDown:
+ case GHOST_kEventButtonUp: {
+ GHOST_TEventButtonData *bd= data;
+ pos+= sprintf(pos, " - but: %d", bd->button);
+ break;
+ }
+
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= data;
+ pos+= sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key);
+ if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii);
+ break;
+ }
+ }
+}
diff --git a/intern/ghost/test/multitest/EventToBuf.h b/intern/ghost/test/multitest/EventToBuf.h
new file mode 100644
index 00000000000..be6f37d869b
--- /dev/null
+++ b/intern/ghost/test/multitest/EventToBuf.h
@@ -0,0 +1,35 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+char *eventtype_to_string(GHOST_TEventType type);
+
+void event_to_buf(GHOST_EventHandle evt, char buf[128]);
+
diff --git a/intern/ghost/test/multitest/GL.h b/intern/ghost/test/multitest/GL.h
new file mode 100644
index 00000000000..b395627d1d8
--- /dev/null
+++ b/intern/ghost/test/multitest/GL.h
@@ -0,0 +1,43 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#if defined(WIN32) || defined(__APPLE__)
+
+ #ifdef WIN32
+ #include <windows.h>
+ #include <GL/gl.h>
+ #else // WIN32
+ // __APPLE__ is defined
+ #include <AGL/gl.h>
+ #endif // WIN32
+#else // defined(WIN32) || defined(__APPLE__)
+ #include <GL/gl.h>
+#endif // defined(WIN32) || defined(__APPLE__)
diff --git a/intern/ghost/test/multitest/Makefile b/intern/ghost/test/multitest/Makefile
new file mode 100644
index 00000000000..a424a397502
--- /dev/null
+++ b/intern/ghost/test/multitest/Makefile
@@ -0,0 +1,60 @@
+#
+# $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.
+#
+# 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 *****
+# GHOST gears test application Makefile
+#
+
+DIR = $(OCGDIR)/intern/ghost/test
+
+# we don't want a library here, only object files:
+ALLTARGETS = $(OBJS)
+
+include nan_compile.mk
+include nan_link.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_BMFONT)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../..
+
+OCGGHOST = $(OCGDIR)/intern/ghost
+
+LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a
+SLIBS += $(LCGDIR)/string/lib/libstring.a
+SLIBS += $(LCGDIR)/bmfont/lib/libbmfont.a
+SLIBS += $(LCGDIR)/guardedalloc/lib/libguardedalloc.a
+
+all::
+ @echo "- link $(DIR)/$(DEBUG_DIR)multitest -"
+ @$(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)multitest $(OBJS) $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c
new file mode 100755
index 00000000000..c78d9045022
--- /dev/null
+++ b/intern/ghost/test/multitest/MultiTest.c
@@ -0,0 +1,855 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifdef WIN32
+
+#pragma warning(disable: 4244 4305)
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "GL.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "GHOST_C-api.h"
+#include "BMF_Api.h"
+
+#include "Util.h"
+#include "Basic.h"
+#include "ScrollBar.h"
+#include "EventToBuf.h"
+
+#include "WindowData.h"
+
+/***/
+
+typedef struct _MultiTestApp MultiTestApp;
+typedef struct _LoggerWindow LoggerWindow;
+
+void loggerwindow_log(LoggerWindow *lw, char *line);
+
+void multitestapp_toggle_extra_window(MultiTestApp *app);
+void multitestapp_free_extrawindow(MultiTestApp *app);
+LoggerWindow *multitestapp_get_logger(MultiTestApp *app);
+GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app);
+void multitestapp_exit(MultiTestApp *app);
+
+/**/
+
+void rect_bevel_side(int rect[2][2], int side, float *lt, float *dk, float *col, int width) {
+ int ltidx= (side/2)%4;
+ int dkidx= (ltidx + 1 + (side&1))%4;
+ int i, corner;
+
+ glBegin(GL_LINES);
+ for (i=0; i<width; i++) {
+ float ltf= pow(lt[i], 1.0/2.2), dkf= pow(dk[i], 1.0/2.2);
+ float stf= (dkidx>ltidx)?dkf:ltf;
+ int lx= rect[1][0]-i-1;
+ int ly= rect[0][1]+i;
+
+ glColor3f(col[0]*stf, col[1]*stf, col[2]*stf);
+ for (corner=0; corner<4; corner++) {
+ int x= (corner==0 || corner==1)?(rect[0][0]+i):(rect[1][0]-i-1);
+ int y= (corner==0 || corner==3)?(rect[0][1]+i):(rect[1][1]-i-1);
+
+ if (ltidx==corner)
+ glColor3f(col[0]*ltf, col[1]*ltf, col[2]*ltf);
+ if (dkidx==corner)
+ glColor3f(col[0]*dkf, col[1]*dkf, col[2]*dkf);
+
+ glVertex2i(lx, ly);
+ glVertex2i(lx= x, ly= y);
+ }
+ }
+ glEnd();
+
+ glColor3fv(col);
+ glRecti(rect[0][0]+width, rect[0][1]+width, rect[1][0]-width, rect[1][1]-width);
+}
+
+void rect_bevel_smooth(int rect[2][2], int width) {
+ float *lt= malloc(sizeof(*lt)*width);
+ float *dk= malloc(sizeof(*dk)*width);
+ float col[4];
+ int i;
+
+ for (i=0; i<width; i++) {
+ float v= width-1?((float) i/(width-1)):0;
+ lt[i]= 1.2 + (1.0-1.2)*v;
+ dk[i]= 0.2 + (1.0-0.2)*v;
+ }
+
+ glGetFloatv(GL_CURRENT_COLOR, col);
+
+ rect_bevel_side(rect, 3, lt, dk, col, width);
+
+ free(lt);
+ free(dk);
+}
+
+ /*
+ * MainWindow
+ */
+
+typedef struct {
+ MultiTestApp *app;
+
+ GHOST_WindowHandle win;
+
+ int size[2];
+
+ int lmouse[2], lmbut[3];
+
+ int tmouse[2];
+} MainWindow;
+
+static void mainwindow_log(MainWindow *mw, char *str) {
+ loggerwindow_log(multitestapp_get_logger(mw->app), str);
+}
+
+static void mainwindow_do_draw(MainWindow *mw) {
+ GHOST_ActivateWindowDrawingContext(mw->win);
+
+ if (mw->lmbut[0]) {
+ glClearColor(0.5, 0.5, 0.5, 1);
+ } else {
+ glClearColor(1, 1, 1, 1);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3f(0.5, 0.6, 0.8);
+ glRecti(mw->tmouse[0]-5, mw->tmouse[1]-5, mw->tmouse[0]+5, mw->tmouse[1]+5);
+
+ GHOST_SwapWindowBuffers(mw->win);
+}
+
+static void mainwindow_do_reshape(MainWindow *mw) {
+ GHOST_RectangleHandle bounds= GHOST_GetClientBounds(mw->win);
+
+ GHOST_ActivateWindowDrawingContext(mw->win);
+
+ mw->size[0]= GHOST_GetWidthRectangle(bounds);
+ mw->size[1]= GHOST_GetHeightRectangle(bounds);
+
+ glViewport(0, 0, mw->size[0], mw->size[1]);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, mw->size[0], 0, mw->size[1], -1, 1);
+ glTranslatef(0.375, 0.375, 0.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press) {
+ switch(key) {
+ case GHOST_kKeyC:
+ if (press)
+ GHOST_SetCursorShape(mw->win, (GHOST_TStandardCursor) (rand()%(GHOST_kStandardCursorNumCursors)));
+ break;
+ case GHOST_kKeyLeftBracket:
+ if (press)
+ GHOST_SetCursorVisibility(mw->win, 0);
+ break;
+ case GHOST_kKeyRightBracket:
+ if (press)
+ GHOST_SetCursorVisibility(mw->win, 1);
+ break;
+ case GHOST_kKeyE:
+ if (press)
+ multitestapp_toggle_extra_window(mw->app);
+ break;
+ case GHOST_kKeyQ:
+ if (press)
+ multitestapp_exit(mw->app);
+ break;
+ case GHOST_kKeyT:
+ if (press)
+ mainwindow_log(mw, "TextTest~|`hello`\"world\",<>/");
+ break;
+ case GHOST_kKeyR:
+ if (press) {
+ int i;
+
+ mainwindow_log(mw, "Invalidating window 10 times");
+ for (i=0; i<10; i++)
+ GHOST_InvalidateWindow(mw->win);
+ }
+ break;
+ case GHOST_kKeyF11:
+ if (press) {
+ GHOST_SetWindowOrder(mw->win, GHOST_kWindowOrderBottom);
+ }
+ break;
+ }
+}
+
+static void mainwindow_do_move(MainWindow *mw, int x, int y) {
+ mw->lmouse[0]= x, mw->lmouse[1]= y;
+
+ if (mw->lmbut[0]) {
+ mw->tmouse[0]= x, mw->tmouse[1]= y;
+ GHOST_InvalidateWindow(mw->win);
+ }
+}
+
+static void mainwindow_do_button(MainWindow *mw, int which, int press) {
+ if (which==GHOST_kButtonMaskLeft) {
+ mw->lmbut[0]= press;
+ mw->tmouse[0]= mw->lmouse[0], mw->tmouse[1]= mw->lmouse[1];
+ GHOST_InvalidateWindow(mw->win);
+ } else if (which==GHOST_kButtonMaskLeft) {
+ mw->lmbut[1]= press;
+ } else if (which==GHOST_kButtonMaskLeft) {
+ mw->lmbut[2]= press;
+ }
+}
+
+static void mainwindow_handle(void *priv, GHOST_EventHandle evt) {
+ MainWindow *mw= priv;
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+ char buf[256];
+
+ event_to_buf(evt, buf);
+ mainwindow_log(mw, buf);
+
+ switch (type) {
+ case GHOST_kEventCursorMove: {
+ GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
+ int x, y;
+ GHOST_ScreenToClient(mw->win, cd->x, cd->y, &x, &y);
+ mainwindow_do_move(mw, x, mw->size[1]-y-1);
+ break;
+ }
+ case GHOST_kEventButtonDown:
+ case GHOST_kEventButtonUp: {
+ GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
+ mainwindow_do_button(mw, bd->button, (type == GHOST_kEventButtonDown));
+ break;
+ }
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
+ mainwindow_do_key(mw, kd->key, (type == GHOST_kEventKeyDown));
+ break;
+ }
+
+ case GHOST_kEventWindowUpdate:
+ mainwindow_do_draw(mw);
+ break;
+ case GHOST_kEventWindowSize:
+ mainwindow_do_reshape(mw);
+ break;
+ }
+}
+
+/**/
+
+static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) {
+ MainWindow *mw= GHOST_GetTimerTaskUserData(task);
+ char buf[64];
+
+ sprintf(buf, "timer: %6.2f", (double) ((GHOST_TInt64) time)/1000);
+ mainwindow_log(mw, buf);
+}
+
+MainWindow *mainwindow_new(MultiTestApp *app) {
+ GHOST_SystemHandle sys= multitestapp_get_system(app);
+ GHOST_WindowHandle win;
+
+ win= GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL);
+
+ if (win) {
+ MainWindow *mw= MEM_callocN(sizeof(*mw), "mainwindow_new");
+ mw->app= app;
+ mw->win= win;
+
+ GHOST_SetWindowUserData(mw->win, windowdata_new(mw, mainwindow_handle));
+
+ GHOST_InstallTimer(sys, 1000, 10000, mainwindow_timer_proc, mw);
+
+ return mw;
+ } else {
+ return NULL;
+ }
+}
+
+void mainwindow_free(MainWindow *mw) {
+ GHOST_SystemHandle sys= multitestapp_get_system(mw->app);
+
+ windowdata_free(GHOST_GetWindowUserData(mw->win));
+ GHOST_DisposeWindow(sys, mw->win);
+ MEM_freeN(mw);
+}
+
+ /*
+ * LoggerWindow
+ */
+
+struct _LoggerWindow {
+ MultiTestApp *app;
+
+ GHOST_WindowHandle win;
+
+ BMF_Font *font;
+ int fonttexid;
+ int fontheight;
+
+ int size[2];
+
+ int ndisplines;
+ int textarea[2][2];
+ ScrollBar *scroll;
+
+ char **loglines;
+ int nloglines, logsize;
+
+ int lmbut[3];
+ int lmouse[2];
+};
+
+#define SCROLLBAR_PAD 2
+#define SCROLLBAR_WIDTH 14
+#define TEXTAREA_PAD 2
+static void loggerwindow_recalc_regions(LoggerWindow *lw) {
+ int nscroll[2][2];
+
+ nscroll[0][0]= SCROLLBAR_PAD;
+ nscroll[0][1]= SCROLLBAR_PAD;
+ nscroll[1][0]= nscroll[0][0] + SCROLLBAR_WIDTH;
+ nscroll[1][1]= lw->size[1] - SCROLLBAR_PAD - 1;
+
+ lw->textarea[0][0]= nscroll[1][0] + TEXTAREA_PAD;
+ lw->textarea[0][1]= TEXTAREA_PAD;
+ lw->textarea[1][0]= lw->size[0] - TEXTAREA_PAD - 1;
+ lw->textarea[1][1]= lw->size[1] - TEXTAREA_PAD - 1;
+
+ lw->ndisplines= (lw->textarea[1][1]-lw->textarea[0][1])/lw->fontheight;
+
+ scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
+ scrollbar_set_rect(lw->scroll, nscroll);
+}
+
+static void loggerwindow_setup_window_gl(LoggerWindow *lw) {
+ glViewport(0, 0, lw->size[0], lw->size[1]);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, lw->size[0], 0, lw->size[1], -1, 1);
+ glTranslatef(0.375, 0.375, 0.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+static void loggerwindow_do_reshape(LoggerWindow *lw) {
+ GHOST_RectangleHandle bounds= GHOST_GetClientBounds(lw->win);
+
+ GHOST_ActivateWindowDrawingContext(lw->win);
+
+ lw->size[0]= GHOST_GetWidthRectangle(bounds);
+ lw->size[1]= GHOST_GetHeightRectangle(bounds);
+
+ loggerwindow_recalc_regions(lw);
+ loggerwindow_setup_window_gl(lw);
+}
+
+static void loggerwindow_do_draw(LoggerWindow *lw) {
+ int i, ndisplines, startline;
+ int sb_rect[2][2], sb_thumb[2][2];
+
+ GHOST_ActivateWindowDrawingContext(lw->win);
+
+ glClearColor(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3f(0.8, 0.8, 0.8);
+ rect_bevel_smooth(lw->textarea, 4);
+
+ scrollbar_get_rect(lw->scroll, sb_rect);
+ scrollbar_get_thumb(lw->scroll, sb_thumb);
+
+ glColor3f(0.6, 0.6, 0.6);
+ rect_bevel_smooth(sb_rect, 1);
+
+ if (scrollbar_is_scrolling(lw->scroll)) {
+ glColor3f(0.6, 0.7, 0.5);
+ } else {
+ glColor3f(0.9, 0.9, 0.92);
+ }
+ rect_bevel_smooth(sb_thumb, 1);
+
+ startline= scrollbar_get_thumbpos(lw->scroll)*(lw->nloglines-1);
+ ndisplines= min_i(lw->ndisplines, lw->nloglines-startline);
+
+ if (lw->fonttexid!=-1) {
+ glBindTexture(GL_TEXTURE_2D, lw->fonttexid);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ }
+ glColor3f(0, 0, 0);
+ for (i=0; i<ndisplines; i++) {
+ /* stored in reverse order */
+ char *line= lw->loglines[(lw->nloglines-1)-(i+startline)];
+ int x_pos= lw->textarea[0][0] + 4;
+ int y_pos= lw->textarea[0][1] + 4 + i*lw->fontheight;
+
+ if (lw->fonttexid==-1) {
+ glRasterPos2i(x_pos, y_pos);
+ BMF_DrawString(lw->font, line);
+ } else {
+ BMF_DrawStringTexture(lw->font, line, x_pos, y_pos, 0.0);
+ }
+ }
+ if (lw->fonttexid!=-1) {
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ }
+
+ GHOST_SwapWindowBuffers(lw->win);
+}
+
+static void loggerwindow_do_move(LoggerWindow *lw, int x, int y) {
+ lw->lmouse[0]= x, lw->lmouse[1]= y;
+
+ if (scrollbar_is_scrolling(lw->scroll)) {
+ scrollbar_keep_scrolling(lw->scroll, y);
+ GHOST_InvalidateWindow(lw->win);
+ }
+}
+
+static void loggerwindow_do_button(LoggerWindow *lw, int which, int press) {
+ if (which==GHOST_kButtonMaskLeft) {
+ lw->lmbut[0]= press;
+
+ if (press) {
+ if (scrollbar_contains_pt(lw->scroll, lw->lmouse)) {
+ scrollbar_start_scrolling(lw->scroll, lw->lmouse[1]);
+ GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorUpDown);
+ GHOST_InvalidateWindow(lw->win);
+ }
+ } else {
+ if (scrollbar_is_scrolling(lw->scroll)) {
+ scrollbar_stop_scrolling(lw->scroll);
+ GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorDefault);
+ GHOST_InvalidateWindow(lw->win);
+ }
+ }
+ } else if (which==GHOST_kButtonMaskMiddle) {
+ lw->lmbut[1]= press;
+ } else if (which==GHOST_kButtonMaskRight) {
+ lw->lmbut[2]= press;
+ }
+}
+
+static void loggerwindow_do_key(LoggerWindow *lw, GHOST_TKey key, int press) {
+ switch (key) {
+ case GHOST_kKeyQ:
+ if (press)
+ multitestapp_exit(lw->app);
+ break;
+ }
+}
+
+static void loggerwindow_handle(void *priv, GHOST_EventHandle evt) {
+ LoggerWindow *lw= priv;
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+
+ switch(type) {
+ case GHOST_kEventCursorMove: {
+ GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
+ int x, y;
+ GHOST_ScreenToClient(lw->win, cd->x, cd->y, &x, &y);
+ loggerwindow_do_move(lw, x, lw->size[1]-y-1);
+ break;
+ }
+ case GHOST_kEventButtonDown:
+ case GHOST_kEventButtonUp: {
+ GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
+ loggerwindow_do_button(lw, bd->button, (type == GHOST_kEventButtonDown));
+ break;
+ }
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
+ loggerwindow_do_key(lw, kd->key, (type == GHOST_kEventKeyDown));
+ break;
+ }
+
+ case GHOST_kEventWindowUpdate:
+ loggerwindow_do_draw(lw);
+ break;
+ case GHOST_kEventWindowSize:
+ loggerwindow_do_reshape(lw);
+ break;
+ }
+}
+
+/**/
+
+LoggerWindow *loggerwindow_new(MultiTestApp *app) {
+ GHOST_SystemHandle sys= multitestapp_get_system(app);
+ GHOST_TUns32 screensize[2];
+ GHOST_WindowHandle win;
+
+ GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]);
+ win= GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1]-432, 800, 300, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL);
+
+ if (win) {
+ LoggerWindow *lw= MEM_callocN(sizeof(*lw), "loggerwindow_new");
+ int bbox[2][2];
+ lw->app= app;
+ lw->win= win;
+
+ lw->font= BMF_GetFont(BMF_kScreen12);
+ lw->fonttexid= BMF_GetFontTexture(lw->font);
+
+ BMF_GetBoundingBox(lw->font, &bbox[0][0], &bbox[0][1], &bbox[1][0], &bbox[1][1]);
+ lw->fontheight= rect_height(bbox);
+
+ lw->nloglines= lw->logsize= 0;
+ lw->loglines= MEM_mallocN(sizeof(*lw->loglines)*lw->nloglines, "loglines");
+
+ lw->scroll= scrollbar_new(2, 40);
+
+ GHOST_SetWindowUserData(lw->win, windowdata_new(lw, loggerwindow_handle));
+
+ loggerwindow_do_reshape(lw);
+
+ return lw;
+ } else {
+ return NULL;
+ }
+}
+
+void loggerwindow_log(LoggerWindow *lw, char *line) {
+ if (lw->nloglines==lw->logsize) {
+ lw->loglines= memdbl(lw->loglines, &lw->logsize, sizeof(*lw->loglines));
+ }
+
+ lw->loglines[lw->nloglines++]= string_dup(line);
+ scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
+
+ GHOST_InvalidateWindow(lw->win);
+}
+
+void loggerwindow_free(LoggerWindow *lw) {
+ GHOST_SystemHandle sys= multitestapp_get_system(lw->app);
+ int i;
+
+ for (i=0; i<lw->nloglines; i++) {
+ MEM_freeN(lw->loglines[i]);
+ }
+ MEM_freeN(lw->loglines);
+
+ windowdata_free(GHOST_GetWindowUserData(lw->win));
+ GHOST_DisposeWindow(sys, lw->win);
+ MEM_freeN(lw);
+}
+
+ /*
+ * ExtraWindow
+ */
+
+
+typedef struct {
+ MultiTestApp *app;
+
+ GHOST_WindowHandle win;
+
+ int size[2];
+} ExtraWindow;
+
+static void extrawindow_do_draw(ExtraWindow *ew) {
+ GHOST_ActivateWindowDrawingContext(ew->win);
+
+ glClearColor(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3f(0.8, 0.8, 0.8);
+ glRecti(10, 10, ew->size[0]-10, ew->size[1]-10);
+
+ GHOST_SwapWindowBuffers(ew->win);
+}
+
+static void extrawindow_do_reshape(ExtraWindow *ew) {
+ GHOST_RectangleHandle bounds= GHOST_GetClientBounds(ew->win);
+
+ GHOST_ActivateWindowDrawingContext(ew->win);
+
+ ew->size[0]= GHOST_GetWidthRectangle(bounds);
+ ew->size[1]= GHOST_GetHeightRectangle(bounds);
+
+ glViewport(0, 0, ew->size[0], ew->size[1]);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, ew->size[0], 0, ew->size[1], -1, 1);
+ glTranslatef(0.375, 0.375, 0.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press) {
+ switch (key) {
+ case GHOST_kKeyE:
+ if (press)
+ multitestapp_toggle_extra_window(ew->app);
+ break;
+ }
+}
+
+static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time) {
+ GHOST_TUns8 bitmap[16][2];
+ GHOST_TUns8 mask[16][2];
+ double ftime= (double) ((GHOST_TInt64) time)/1000;
+ float angle= fmod(ftime, 1.0) * 3.1415*2;
+ int i;
+
+ memset(&bitmap, 0, sizeof(bitmap));
+ memset(&mask, 0, sizeof(mask));
+
+ bitmap[0][0] |= mask[0][0] |= 0xF;
+ bitmap[1][0] |= mask[1][0] |= 0xF;
+ bitmap[2][0] |= mask[2][0] |= 0xF;
+ bitmap[3][0] |= mask[3][0] |= 0xF;
+
+ for (i=0; i<7; i++) {
+ int x = 7 + cos(angle)*i;
+ int y = 7 + sin(angle)*i;
+
+ mask[y][x/8] |= (1 << (x%8));
+ }
+ for (i=0; i<64; i++) {
+ float v= (i/63.0) * 3.1415*2;
+ int x = 7 + cos(v)*7;
+ int y = 7 + sin(v)*7;
+
+ mask[y][x/8] |= (1 << (x%8));
+ }
+
+ GHOST_SetCustomCursorShape(ew->win, bitmap, mask, 0, 0);
+}
+
+static void extrawindow_handle(void *priv, GHOST_EventHandle evt) {
+ ExtraWindow *ew= priv;
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+ char buf[256];
+
+ event_to_buf(evt, buf);
+ loggerwindow_log(multitestapp_get_logger(ew->app), buf);
+
+ switch (type) {
+ case GHOST_kEventKeyDown:
+ case GHOST_kEventKeyUp: {
+ GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
+ extrawindow_do_key(ew, kd->key, (type == GHOST_kEventKeyDown));
+ break;
+ }
+
+ case GHOST_kEventCursorMove: {
+ extrawindow_spin_cursor(ew, GHOST_GetEventTime(evt));
+ break;
+ }
+
+ case GHOST_kEventWindowClose:
+ multitestapp_free_extrawindow(ew->app);
+ break;
+ case GHOST_kEventWindowUpdate:
+ extrawindow_do_draw(ew);
+ break;
+ case GHOST_kEventWindowSize:
+ extrawindow_do_reshape(ew);
+ break;
+ }
+}
+
+/**/
+
+ExtraWindow *extrawindow_new(MultiTestApp *app) {
+ GHOST_SystemHandle sys= multitestapp_get_system(app);
+ GHOST_WindowHandle win;
+
+ win= GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400, GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL);
+
+ if (win) {
+ ExtraWindow *ew= MEM_callocN(sizeof(*ew), "mainwindow_new");
+ ew->app= app;
+ ew->win= win;
+
+ GHOST_SetWindowUserData(ew->win, windowdata_new(ew, extrawindow_handle));
+
+ return ew;
+ } else {
+ return NULL;
+ }
+}
+
+void extrawindow_free(ExtraWindow *ew) {
+ GHOST_SystemHandle sys= multitestapp_get_system(ew->app);
+
+ windowdata_free(GHOST_GetWindowUserData(ew->win));
+ GHOST_DisposeWindow(sys, ew->win);
+ MEM_freeN(ew);
+}
+
+ /*
+ * MultiTestApp
+ */
+
+struct _MultiTestApp {
+ GHOST_SystemHandle sys;
+ MainWindow *main;
+ LoggerWindow *logger;
+ ExtraWindow *extra;
+
+ int exit;
+};
+
+static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) {
+ MultiTestApp *app= data;
+ GHOST_WindowHandle win;
+
+ win= GHOST_GetEventWindow(evt);
+ if (win && !GHOST_ValidWindow(app->sys, win)) {
+ loggerwindow_log(app->logger, "WARNING: bad event, non-valid window\n");
+ return 1;
+ }
+
+ if (win) {
+ WindowData *wb= GHOST_GetWindowUserData(win);
+
+ windowdata_handle(wb, evt);
+ } else {
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+
+ /* GHOST_kEventQuit are the only 'system' events,
+ * that is, events without a window.
+ */
+ switch(type) {
+ case GHOST_kEventQuit:
+ app->exit= 1;
+ break;
+
+ default:
+ fatal("Unhandled system event: %d (%s)\n", type, eventtype_to_string(type));
+ break;
+ }
+ }
+
+ return 1;
+}
+
+/**/
+
+MultiTestApp *multitestapp_new(void) {
+ MultiTestApp *app= MEM_mallocN(sizeof(*app), "multitestapp_new");
+ GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(multitest_event_handler, app);
+
+ app->sys= GHOST_CreateSystem();
+ if (!app->sys)
+ fatal("Unable to create ghost system");
+
+ if (!GHOST_AddEventConsumer(app->sys, consumer))
+ fatal("Unable to add multitest event consumer ");
+
+ app->main= mainwindow_new(app);
+ if (!app->main)
+ fatal("Unable to create main window");
+
+ app->logger= loggerwindow_new(app);
+ if (!app->logger)
+ fatal("Unable to create logger window");
+
+ app->extra= NULL;
+ app->exit= 0;
+
+ return app;
+}
+
+LoggerWindow *multitestapp_get_logger(MultiTestApp *app) {
+ return app->logger;
+}
+
+GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app) {
+ return app->sys;
+}
+
+void multitestapp_free_extrawindow(MultiTestApp *app) {
+ extrawindow_free(app->extra);
+ app->extra= NULL;
+}
+
+void multitestapp_toggle_extra_window(MultiTestApp *app) {
+ if (app->extra) {
+ multitestapp_free_extrawindow(app);
+ } else {
+ app->extra= extrawindow_new(app);
+ }
+}
+
+void multitestapp_exit(MultiTestApp *app) {
+ app->exit= 1;
+}
+
+void multitestapp_run(MultiTestApp *app) {
+ while (!app->exit) {
+ GHOST_ProcessEvents(app->sys, 1);
+ GHOST_DispatchEvents(app->sys);
+ }
+}
+
+void multitestapp_free(MultiTestApp *app) {
+ mainwindow_free(app->main);
+ loggerwindow_free(app->logger);
+ GHOST_DisposeSystem(app->sys);
+ MEM_freeN(app);
+}
+
+ /***/
+
+int main(int argc, char **argv) {
+ MultiTestApp *app= multitestapp_new();
+
+ multitestapp_run(app);
+ multitestapp_free(app);
+
+ return 0;
+}
diff --git a/intern/ghost/test/multitest/ScrollBar.c b/intern/ghost/test/multitest/ScrollBar.c
new file mode 100644
index 00000000000..cd690f6f14e
--- /dev/null
+++ b/intern/ghost/test/multitest/ScrollBar.c
@@ -0,0 +1,145 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <stdlib.h>
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "Basic.h"
+#include "ScrollBar.h"
+
+struct _ScrollBar {
+ int rect[2][2];
+ float thumbpos, thumbpct;
+
+ int inset;
+ int minthumb;
+
+ int scrolling;
+ float scrolloffs;
+};
+
+static int scrollbar_get_thumbH(ScrollBar *sb) {
+ int scrollable_h= rect_height(sb->rect) - 2*sb->inset;
+
+ return clamp_i(sb->thumbpct*scrollable_h, sb->minthumb, scrollable_h);
+}
+static int scrollbar_get_thumbableH(ScrollBar *sb) {
+ int scrollable_h= rect_height(sb->rect) - 2*sb->inset;
+ int thumb_h= scrollbar_get_thumbH(sb);
+
+ return scrollable_h - thumb_h;
+}
+
+static float scrollbar_co_to_pos(ScrollBar *sb, int yco) {
+ int thumb_h= scrollbar_get_thumbH(sb);
+ int thumbable_h= scrollbar_get_thumbableH(sb);
+ int thumbable_y= (sb->rect[0][1]+sb->inset) + thumb_h/2;
+
+ return (float) (yco-thumbable_y)/thumbable_h;
+}
+
+/**/
+
+ScrollBar *scrollbar_new(int inset, int minthumb) {
+ ScrollBar *sb= MEM_callocN(sizeof(*sb), "scrollbar_new");
+ sb->inset= inset;
+ sb->minthumb= minthumb;
+
+ return sb;
+}
+
+void scrollbar_get_thumb(ScrollBar *sb, int thumb_r[2][2]) {
+ int thumb_h= scrollbar_get_thumbH(sb);
+ int thumbable_h= scrollbar_get_thumbableH(sb);
+
+ thumb_r[0][0]= sb->rect[0][0]+sb->inset;
+ thumb_r[1][0]= sb->rect[1][0]-sb->inset;
+
+ thumb_r[0][1]= sb->rect[0][1]+sb->inset + sb->thumbpos*thumbable_h;
+ thumb_r[1][1]= thumb_r[0][1] + thumb_h;
+}
+
+int scrollbar_is_scrolling(ScrollBar *sb) {
+ return sb->scrolling;
+}
+int scrollbar_contains_pt(ScrollBar *sb, int pt[2]) {
+ return rect_contains_pt(sb->rect, pt);
+}
+
+void scrollbar_start_scrolling(ScrollBar *sb, int yco) {
+ int thumb_h_2= scrollbar_get_thumbH(sb)/2;
+ int thumbable_h= scrollbar_get_thumbableH(sb);
+ float npos= scrollbar_co_to_pos(sb, yco);
+
+ sb->scrolloffs= sb->thumbpos - npos;
+ if (fabs(sb->scrolloffs) >= (float) thumb_h_2/thumbable_h) {
+ sb->scrolloffs= 0.0;
+ }
+
+ sb->scrolling= 1;
+ sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0);
+}
+void scrollbar_keep_scrolling(ScrollBar *sb, int yco) {
+ float npos= scrollbar_co_to_pos(sb, yco);
+
+ sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0);
+}
+void scrollbar_stop_scrolling(ScrollBar *sb) {
+ sb->scrolling= 0;
+ sb->scrolloffs= 0.0;
+}
+
+void scrollbar_set_thumbpct(ScrollBar *sb, float pct) {
+ sb->thumbpct= pct;
+}
+void scrollbar_set_thumbpos(ScrollBar *sb, float pos) {
+ sb->thumbpos= clamp_f(pos, 0.0, 1.0);
+}
+void scrollbar_set_rect(ScrollBar *sb, int rect[2][2]) {
+ rect_copy(sb->rect, rect);
+}
+
+float scrollbar_get_thumbpct(ScrollBar *sb) {
+ return sb->thumbpct;
+}
+float scrollbar_get_thumbpos(ScrollBar *sb) {
+ return sb->thumbpos;
+}
+void scrollbar_get_rect(ScrollBar *sb, int rect_r[2][2]) {
+ rect_copy(rect_r, sb->rect);
+}
+
+void scrollbar_free(ScrollBar *sb) {
+ MEM_freeN(sb);
+}
diff --git a/intern/ghost/test/multitest/ScrollBar.h b/intern/ghost/test/multitest/ScrollBar.h
new file mode 100644
index 00000000000..30e49e8b531
--- /dev/null
+++ b/intern/ghost/test/multitest/ScrollBar.h
@@ -0,0 +1,56 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+typedef struct _ScrollBar ScrollBar;
+
+
+ /***/
+
+ScrollBar* scrollbar_new (int inset, int minthumb);
+
+int scrollbar_is_scrolling (ScrollBar *sb);
+int scrollbar_contains_pt (ScrollBar *sb, int pt[2]);
+
+void scrollbar_start_scrolling (ScrollBar *sb, int yco);
+void scrollbar_keep_scrolling (ScrollBar *sb, int yco);
+void scrollbar_stop_scrolling (ScrollBar *sb);
+
+void scrollbar_set_thumbpct (ScrollBar *sb, float pct);
+void scrollbar_set_thumbpos (ScrollBar *sb, float pos);
+void scrollbar_set_rect (ScrollBar *sb, int rect[2][2]);
+
+float scrollbar_get_thumbpct (ScrollBar *sb);
+float scrollbar_get_thumbpos (ScrollBar *sb);
+void scrollbar_get_rect (ScrollBar *sb, int rect_r[2][2]);
+
+void scrollbar_get_thumb (ScrollBar *sb, int thumb_r[2][2]);
+
+void scrollbar_free (ScrollBar *sb);
diff --git a/intern/ghost/test/multitest/Util.c b/intern/ghost/test/multitest/Util.c
new file mode 100644
index 00000000000..31e43f6f5da
--- /dev/null
+++ b/intern/ghost/test/multitest/Util.c
@@ -0,0 +1,73 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <stdlib.h>
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "Util.h"
+
+void* memdbl(void *mem, int *size_pr, int item_size) {
+ int cur_size= *size_pr;
+ int new_size= cur_size?(cur_size*2):1;
+ void *nmem= MEM_mallocN(new_size*item_size, "memdbl");
+
+ memcpy(nmem, mem, cur_size*item_size);
+ MEM_freeN(mem);
+
+ *size_pr= new_size;
+ return nmem;
+}
+
+char* string_dup(char *str) {
+ int len= strlen(str);
+ char *nstr= MEM_mallocN(len + 1, "string_dup");
+
+ memcpy(nstr, str, len+1);
+
+ return nstr;
+}
+
+void fatal(char *fmt, ...) {
+ va_list ap;
+
+ fprintf(stderr, "FATAL: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+
+ exit(1);
+}
diff --git a/intern/ghost/test/multitest/Util.h b/intern/ghost/test/multitest/Util.h
new file mode 100644
index 00000000000..1146112c9c4
--- /dev/null
+++ b/intern/ghost/test/multitest/Util.h
@@ -0,0 +1,35 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+void* memdbl (void *mem, int *size_pr, int item_size);
+
+char* string_dup (char *str);
+void fatal (char *fmt, ...);
diff --git a/intern/ghost/test/multitest/WindowData.c b/intern/ghost/test/multitest/WindowData.c
new file mode 100644
index 00000000000..ee377c98b58
--- /dev/null
+++ b/intern/ghost/test/multitest/WindowData.c
@@ -0,0 +1,60 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <stdlib.h>
+
+
+#include "MEM_guardedalloc.h"
+
+#include "GHOST_C-api.h"
+
+#include "WindowData.h"
+
+struct _WindowData {
+ void *data;
+ WindowDataHandler handler;
+};
+
+WindowData *windowdata_new(void *data, WindowDataHandler handler) {
+ WindowData *wb= MEM_mallocN(sizeof(*wb), "windowdata_new");
+ wb->data= data;
+ wb->handler= handler;
+
+ return wb;
+}
+
+void windowdata_handle(WindowData *wb, GHOST_EventHandle evt) {
+ wb->handler(wb->data, evt);
+}
+
+void windowdata_free(WindowData *wb) {
+ MEM_freeN(wb);
+}
diff --git a/intern/ghost/test/multitest/WindowData.h b/intern/ghost/test/multitest/WindowData.h
new file mode 100644
index 00000000000..a046c41d90c
--- /dev/null
+++ b/intern/ghost/test/multitest/WindowData.h
@@ -0,0 +1,40 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+typedef void (*WindowDataHandler)(void *priv, GHOST_EventHandle evt);
+
+typedef struct _WindowData WindowData;
+
+ /***/
+
+WindowData* windowdata_new (void *data, WindowDataHandler handler);
+void windowdata_handle (WindowData *wb, GHOST_EventHandle evt);
+void windowdata_free (WindowData *wb);
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
new file mode 100644
index 00000000000..0fab1aa0bda
--- /dev/null
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -0,0 +1,114 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Guarded memory (de)allocation
+ *
+ *
+ * @mainpage MEM - c-style guarded memory allocation
+ *
+ * @section about About the MEM module
+ *
+ * MEM provides guarded malloc/calloc calls. All memory is enclosed by
+ * pads, to detect out-of-bound writes. All blocks are placed in a
+ * linked list, so they remain reachable at all times. There is no
+ * back-up in case the linked-list related data is lost.
+ *
+ * @section issues Known issues with MEM
+ *
+ * There are currently no known issues with MEM. Note that there is a
+ * second intern/ module with MEM_ prefix, for use in c++.
+ *
+ * @section dependencies Dependencies
+ *
+ * - stdlib
+ *
+ * - stdio
+ *
+ * */
+
+#ifndef MEM_MALLOCN_H
+#define MEM_MALLOCN_H
+
+/* Needed for FILE* */
+#include "stdio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /** Returns the lenght of the allocated memory segment pointed at
+ * by vmemh. If the pointer was not previously allocated by this
+ * module, the result is undefined.*/
+ int MEM_allocN_len(void *vmemh);
+
+ /**
+ * Release memory previously allocatred by this module.
+ */
+ short MEM_freeN(void *vmemh);
+
+ /**
+ * Duplicates a block of memory, and returns a pointer to the
+ * newly allocated block. */
+ void *MEM_dupallocN(void *vmemh);
+
+ /**
+ * Allocate a block of memory of size len, with tag name str. The
+ * memory is cleared. The name must be static, because only a
+ * pointer to it is stored ! */
+ void *MEM_callocN(unsigned int len, char * str);
+
+ /** Allocate a block of memory of size len, with tag name str. The
+ * name must be a static, because only a pointer to it is stored !
+ * */
+ void *MEM_mallocN(unsigned int len, char * str);
+
+ /** Print a list of the names and sizes of all allocated memory
+ * blocks. */
+ void MEM_printmemlist(void);
+
+ /** Set the stream for error output. */
+ void MEM_set_error_stream(FILE*);
+
+ /**
+ * Are the start/end block markers still correct ?
+ *
+ * @retval 0 for correct memory, 1 for corrupted memory. */
+ int MEM_check_memory_integrity(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/intern/guardedalloc/Makefile b/intern/guardedalloc/Makefile
new file mode 100644
index 00000000000..9957d8aa417
--- /dev/null
+++ b/intern/guardedalloc/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# decimation main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = guardedalloc
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_GUARDEDALLOC) ] || mkdir $(NAN_GUARDEDALLOC)
+ @[ -d $(NAN_GUARDEDALLOC)/include ] || mkdir $(NAN_GUARDEDALLOC)/include
+ @[ -d $(NAN_GUARDEDALLOC)/lib ] || mkdir $(NAN_GUARDEDALLOC)/lib
+ @[ -d $(NAN_GUARDEDALLOC)/lib/debug ] || mkdir $(NAN_GUARDEDALLOC)/lib/debug
+ cp -f $(DIR)/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/
+ cp -f $(DIR)/debug/libguardedalloc.a $(NAN_GUARDEDALLOC)/lib/debug/
+ cp -f *.h $(NAN_GUARDEDALLOC)/include/
+
diff --git a/intern/guardedalloc/intern/Makefile b/intern/guardedalloc/intern/Makefile
new file mode 100644
index 00000000000..bc96ba5f27f
--- /dev/null
+++ b/intern/guardedalloc/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# guardedalloc intern Makefile
+#
+
+LIBNAME = guardedalloc
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(NAN_LEVEL_2_C_WARNINGS)
+
+CPPFLAGS += -I..
+
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
new file mode 100644
index 00000000000..64bfdea9d9a
--- /dev/null
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -0,0 +1,457 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Guarded memory allocation, and boundary-write detection.
+ */
+
+#include <stdlib.h>
+
+#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;
+
+typedef struct MemHead {
+ int tag1;
+ int len;
+ struct MemHead *next,*prev;
+ char * name;
+ char * nextname;
+ /* int level; */ /* historical, can be removed, but check alignment issues - zr */
+ int tag2;
+} MemHead;
+
+typedef struct MemTail {
+ int tag3, pad;
+} MemTail;
+
+/* --------------------------------------------------------------------- */
+/* local functions */
+/* --------------------------------------------------------------------- */
+
+static void addtail(localListBase *listbase, void *vlink);
+static void remlink(localListBase *listbase, void *vlink);
+static void rem_memblock(MemHead *memh);
+static void MemorY_ErroR(char *block, char *error);
+static char *check_memlist(MemHead *memh);
+
+/* --------------------------------------------------------------------- */
+/* locally used defines */
+/* --------------------------------------------------------------------- */
+
+#if defined( __sgi) || defined (__sun__) || defined (__PPC__) || defined (__APPLE__)
+#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
+#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
+#define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
+#define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
+
+#define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next))))
+
+/* --------------------------------------------------------------------- */
+/* vars */
+/* --------------------------------------------------------------------- */
+
+int totblock= 0;
+int mem_in_use= 0;
+
+static struct localListBase _membase;
+static struct localListBase *membase = &_membase;
+static FILE* err_stream = NULL;
+
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef calloc
+#undef calloc
+#endif
+
+#ifdef free
+#undef free
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* implementation */
+/* --------------------------------------------------------------------- */
+
+int MEM_check_memory_integrity()
+{
+ char* err_val = NULL;
+ MemHead* listend;
+ /* check_memlist starts from the front, and runs until it finds
+ * the requested chunk. For this test, that's the last one. */
+ listend = membase->last;
+
+ err_val = check_memlist(listend);
+
+ return (int)err_val;
+}
+
+
+void MEM_set_error_stream(FILE* i)
+{
+ err_stream = i;
+}
+
+
+int MEM_allocN_len(void *vmemh)
+{
+ if (vmemh) {
+ MemHead *memh= vmemh;
+
+ memh--;
+ return memh->len;
+ } else
+ return 0;
+}
+
+void *MEM_dupallocN(void *vmemh)
+{
+ void *newp= NULL;
+
+ if (vmemh) {
+ MemHead *memh= vmemh;
+ memh--;
+
+ if (memh->len) {
+ newp= MEM_mallocN(memh->len, "dupli_alloc");
+ memcpy(newp, vmemh, memh->len);
+ } else
+ if (err_stream) fprintf(err_stream, "error: MEM_dupallocN with len==0 %s\n", memh->name);
+ }
+
+ return newp;
+}
+
+void *MEM_mallocN(unsigned int len, char *str)
+{
+ MemHead *memh;
+ MemTail *memt;
+
+ if(sizeof(long)==8)
+ len = (len + 3 ) & ~3; /* eenheden van 4 */
+ else
+ len = (len + 7 ) & ~7; /* eenheden van 8 */
+
+ memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail));
+
+ if(memh!=0) {
+ memh->tag1 = MEMTAG1;
+ memh->name = str;
+ memh->nextname = 0;
+ memh->len = len;
+/* memh->level = 0; */
+ memh->tag2 = MEMTAG2;
+
+ memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
+ memt->tag3 = MEMTAG3;
+
+ addtail(membase,&memh->next);
+ if (memh->next) memh->nextname = MEMNEXT(memh->next)->name;
+
+ totblock++;
+ mem_in_use += len;
+ return (++memh);
+ }
+ if (err_stream) fprintf(err_stream, "Malloc returns nill: len=%d in %s\n",len,str);
+ return 0;
+}
+
+void *MEM_callocN(unsigned int len, char *str)
+{
+ MemHead *memh;
+ MemTail *memt;
+
+ if(sizeof(long)==8)
+ len = (len + 3 ) & ~3; /* eenheden van 4 */
+ else
+ len = (len + 7 ) & ~7; /* eenheden van 8 */
+
+ memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1);
+
+ if(memh!=0) {
+ memh->tag1 = MEMTAG1;
+ memh->name = str;
+ memh->nextname = 0;
+ memh->len = len;
+/* memh->level = 0; */
+ memh->tag2 = MEMTAG2;
+
+ memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
+ memt->tag3 = MEMTAG3;
+
+ addtail(membase,&memh->next);
+ if (memh->next) memh->nextname = MEMNEXT(memh->next)->name;
+
+ totblock++;
+ mem_in_use += len;
+ return (++memh);
+ }
+ if (err_stream) fprintf(err_stream, "Calloc returns nill: len=%d in %s\n",len,str);
+ return 0;
+}
+
+
+void MEM_printmemlist()
+{
+ MemHead *membl;
+
+ membl = membase->first;
+ if (membl) membl = MEMNEXT(membl);
+ while(membl) {
+ if (err_stream) fprintf(err_stream, "%s len: %d %p\n",membl->name,membl->len, membl+1);
+ if(membl->next)
+ membl= MEMNEXT(membl->next);
+ else break;
+ }
+}
+
+short MEM_freeN(void *vmemh) /* anders compileertie niet meer */
+{
+ short error = 0;
+ MemTail *memt;
+ MemHead *memh= vmemh;
+ char *name;
+
+ if (memh == 0){
+ MemorY_ErroR("free","attempt to free NULL pointer");
+ /* if (err_stream) fprintf(err_stream, "%d\n", (memh+4000)->tag1); */
+ return(-1);
+ }
+
+ if(sizeof(long)==8) {
+ if (((long) memh) & 0x7) {
+ MemorY_ErroR("free","attempt to free illegal pointer");
+ return(-1);
+ }
+ }
+ else {
+ if (((long) memh) & 0x3) {
+ MemorY_ErroR("free","attempt to free illegal pointer");
+ return(-1);
+ }
+ }
+
+ memh--;
+ if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
+ MemorY_ErroR(memh->name,"double free");
+ return(-1);
+ }
+
+ if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) {
+ memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len);
+ if (memt->tag3 == MEMTAG3){
+
+ memh->tag1 = MEMFREE;
+ memh->tag2 = MEMFREE;
+ memt->tag3 = MEMFREE;
+ /* na tags !!! */
+ rem_memblock(memh);
+
+ return(0);
+ }
+ error = 2;
+ MemorY_ErroR(memh->name,"end corrupt");
+ name = check_memlist(memh);
+ if (name != 0){
+ if (name != memh->name) MemorY_ErroR(name,"is also corrupt");
+ }
+ } else{
+ error = -1;
+ name = check_memlist(memh);
+ if (name == 0) MemorY_ErroR("free","pointer not in memlist");
+ else MemorY_ErroR(name,"error in header");
+ }
+
+ totblock--;
+ /* hier moet een DUMP plaatsvinden */
+
+ return(error);
+}
+
+/* --------------------------------------------------------------------- */
+/* local functions */
+/* --------------------------------------------------------------------- */
+
+static void addtail(localListBase *listbase, void *vlink)
+{
+ struct localLink *link= vlink;
+
+ if (link == 0) return;
+ if (listbase == 0) return;
+
+ link->next = 0;
+ link->prev = listbase->last;
+
+ if (listbase->last) ((struct localLink *)listbase->last)->next = link;
+ if (listbase->first == 0) listbase->first = link;
+ listbase->last = link;
+}
+
+static void remlink(localListBase *listbase, void *vlink)
+{
+ struct localLink *link= vlink;
+
+ if (link == 0) return;
+ if (listbase == 0) return;
+
+ if (link->next) link->next->prev = link->prev;
+ if (link->prev) link->prev->next = link->next;
+
+ if (listbase->last == link) listbase->last = link->prev;
+ if (listbase->first == link) listbase->first = link->next;
+}
+
+static void rem_memblock(MemHead *memh)
+{
+ remlink(membase,&memh->next);
+ if (memh->prev){
+ if (memh->next) MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name;
+ else MEMNEXT(memh->prev)->nextname = 0;
+ }
+
+ totblock--;
+ mem_in_use -= memh->len;
+ free(memh);
+}
+
+static void MemorY_ErroR(char *block, char *error)
+{
+ if (err_stream) fprintf(err_stream,"Memoryblock %s: %s\n",block,error);
+}
+
+static char *check_memlist(MemHead *memh)
+{
+ MemHead *forw,*back,*forwok,*backok;
+ char *name;
+
+ forw = membase->first;
+ if (forw) forw = MEMNEXT(forw);
+ forwok = 0;
+ while(forw){
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
+ forwok = forw;
+ if (forw->next) forw = MEMNEXT(forw->next);
+ else forw = 0;
+ }
+
+ back = (MemHead *) membase->last;
+ if (back) back = MEMNEXT(back);
+ backok = 0;
+ while(back){
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
+ backok = back;
+ if (back->prev) back = MEMNEXT(back->prev);
+ else back = 0;
+ }
+
+ if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT");
+
+ if (forw == 0 && back == 0){
+ /* geen foute headers gevonden dan maar op zoek naar memblock*/
+
+ forw = membase->first;
+ if (forw) forw = MEMNEXT(forw);
+ forwok = 0;
+ while(forw){
+ if (forw == memh) break;
+ if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
+ forwok = forw;
+ if (forw->next) forw = MEMNEXT(forw->next);
+ else forw = 0;
+ }
+ if (forw == 0) return (0);
+
+ back = (MemHead *) membase->last;
+ if (back) back = MEMNEXT(back);
+ backok = 0;
+ while(back){
+ if (back == memh) break;
+ if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
+ backok = back;
+ if (back->prev) back = MEMNEXT(back->prev);
+ else back = 0;
+ }
+ }
+
+ if (forwok) name = forwok->nextname;
+ else name = "No name found";
+
+ if (forw == memh){
+ /* voor alle zekerheid wordt dit block maar uit de lijst gehaald */
+ if (forwok){
+ if (backok){
+ forwok->next = (MemHead *)&backok->next;
+ backok->prev = (MemHead *)&forwok->next;
+ forwok->nextname = backok->name;
+ } else{
+ forwok->next = 0;
+ membase->last = (struct localLink *) &forwok->next;
+/* membase->last = (struct Link *) &forwok->next; */
+ }
+ } else{
+ if (backok){
+ backok->prev = 0;
+ membase->first = &backok->next;
+ } else{
+ membase->first = membase->last = 0;
+ }
+ }
+ } else{
+ MemorY_ErroR(name,"Additional error in header");
+ return("Additional error in header");
+ }
+
+ return(name);
+}
+
+/* eof */
diff --git a/intern/guardedalloc/test/Makefile b/intern/guardedalloc/test/Makefile
new file mode 100644
index 00000000000..760695bd19e
--- /dev/null
+++ b/intern/guardedalloc/test/Makefile
@@ -0,0 +1,55 @@
+#
+# $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.
+#
+# 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 *****
+# Test the guarded memory module
+#
+
+LIBNAME = guardedalloc
+SOURCEDIR = intern/$(LIBNAME)/test
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = simpletest
+
+include nan_subdirs.mk
+
+include nan_compile.mk
+include nan_link.mk
+
+TESTLIBS = $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)lib$(LIBNAME).a
+
+all debug::
+ @echo "****> linking $@ in $(SOURCEDIR)"
+ $(CC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)memtest $(DIR)/memtest.o $(TESTLIBS)
+
+clean::
+ $(RM) $(DIR)/memtest $(DIR)/debug/memtest
+
+test:: $(DIR)/memtest
+ $(DIR)/memtest $(NAN_TEST_VERBOSITY)
+
diff --git a/intern/guardedalloc/test/simpletest/Makefile b/intern/guardedalloc/test/simpletest/Makefile
new file mode 100644
index 00000000000..8f1db9c4cac
--- /dev/null
+++ b/intern/guardedalloc/test/simpletest/Makefile
@@ -0,0 +1,44 @@
+#
+# $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.
+#
+# 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 *****
+# Test the guarded memory module
+#
+
+LIBNAME = guardedalloc
+DIR = $(OCGDIR)/intern/$(LIBNAME)/test
+
+# we don't want a library here, only object files:
+ALLTARGETS = $(OBJS)
+
+include nan_compile.mk
+
+# this module's header
+CPPFLAGS = -I../..
+
diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c
new file mode 100644
index 00000000000..f2cdc207958
--- /dev/null
+++ b/intern/guardedalloc/test/simpletest/memtest.c
@@ -0,0 +1,158 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Simple test of memory.
+ */
+
+
+
+/* Number of chunks to test with */
+#define NUM_BLOCKS 10
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
+int main (int argc, char *argv[])
+{
+ int verbose = 0;
+ int error_status = 0;
+ int retval = 0;
+ int *ip;
+
+ void *p[NUM_BLOCKS];
+ int i = 0;
+
+ /* ----------------------------------------------------------------- */
+ switch (argc) {
+ case 2:
+ verbose = atoi(argv[1]);
+ if (verbose < 0) verbose = 0;
+ break;
+ case 1:
+ default:
+ verbose = 0;
+ }
+ if (verbose) {
+ fprintf(stderr,"\n*** Simple memory test\n|\n");
+ }
+
+ /* ----------------------------------------------------------------- */
+ /* Round one, do a normal allocation, and free the blocks again. */
+ /* ----------------------------------------------------------------- */
+ /* flush mem lib output to stderr */
+ MEM_set_error_stream(stderr);
+
+ for (i = 0; i < NUM_BLOCKS; i++) {
+ int blocksize = 10000;
+ char tagstring[1000];
+ if (verbose >1) printf("|--* Allocating block %d\n", i);
+ sprintf(tagstring,"Memblock no. %d : ", i);
+ p[i]= MEM_callocN(blocksize, strdup(tagstring));
+ }
+
+ /* report on that */
+ if (verbose > 1) MEM_printmemlist();
+
+ /* memory is there: test it */
+ error_status = MEM_check_memory_integrity();
+
+ if (verbose) {
+ if (error_status) {
+ fprintf(stderr, "|--* Memory test FAILED\n|\n");
+ } else {
+ fprintf(stderr, "|--* Memory tested as good (as it should be)\n|\n");
+ }
+ }
+
+ for (i = 0; i < NUM_BLOCKS; i++) {
+ MEM_freeN(p[i]);
+ }
+
+ /* ----------------------------------------------------------------- */
+ /* Round two, do a normal allocation, and corrupt some blocks. */
+ /* ----------------------------------------------------------------- */
+ /* switch off, because it will complain about some things. */
+ MEM_set_error_stream(NULL);
+
+ for (i = 0; i < NUM_BLOCKS; i++) {
+ int blocksize = 10000;
+ char tagstring[1000];
+ if (verbose >1) printf("|--* Allocating block %d\n", i);
+ sprintf(tagstring,"Memblock no. %d : ", i);
+ p[i]= MEM_callocN(blocksize, strdup(tagstring));
+ }
+
+ /* now corrupt a few blocks...*/
+ ip = (int*) p[5] - 50 ;
+ for (i = 0; i< 1000; i++,ip++) *ip = i+1;
+ ip = (int*) p[6];
+ *(ip+10005) = 0;
+
+ retval = MEM_check_memory_integrity();
+
+ /* the test should have failed */
+ error_status |= !retval;
+ if (verbose) {
+ if (retval) {
+ fprintf(stderr, "|--* Memory test failed (as it should be)\n");
+ } else {
+ fprintf(stderr, "|--* Memory test FAILED to find corrupted blocks \n");
+ }
+ }
+
+ for (i = 0; i < NUM_BLOCKS; i++) {
+ MEM_freeN(p[i]);
+ }
+
+
+ if (verbose && error_status) {
+ fprintf(stderr,"|--* Memory was corrupted\n");
+ }
+ /* ----------------------------------------------------------------- */
+ if (verbose) {
+ if (error_status) {
+ fprintf(stderr,"|\n|--* Errors were detected\n");
+ } else {
+ fprintf(stderr,"|\n|--* Test exited succesfully\n");
+ }
+
+ fprintf(stderr,"|\n*** Finished test\n\n");
+ }
+ return error_status;
+}
+
+
diff --git a/intern/iksolver/Makefile b/intern/iksolver/Makefile
new file mode 100644
index 00000000000..8cdb81ca780
--- /dev/null
+++ b/intern/iksolver/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = iksolver
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_IKSOLVER) ] || mkdir $(NAN_IKSOLVER)
+ @[ -d $(NAN_IKSOLVER)/include ] || mkdir $(NAN_IKSOLVER)/include
+ @[ -d $(NAN_IKSOLVER)/lib ] || mkdir $(NAN_IKSOLVER)/lib
+ @[ -d $(NAN_IKSOLVER)/lib/debug ] || mkdir $(NAN_IKSOLVER)/lib/debug
+ cp -f $(DIR)/libiksolver.a $(NAN_IKSOLVER)/lib/
+ cp -f $(DIR)/debug/libiksolver.a $(NAN_IKSOLVER)/lib/debug/
+ cp -f extern/*.h $(NAN_IKSOLVER)/include/
+
diff --git a/intern/iksolver/extern/IK_solver.h b/intern/iksolver/extern/IK_solver.h
new file mode 100644
index 00000000000..57d06a3ba32
--- /dev/null
+++ b/intern/iksolver/extern/IK_solver.h
@@ -0,0 +1,207 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ * @mainpage IK - Blender inverse kinematics module.
+ *
+ * @section about About the IK module
+ *
+ * This module allows you to create segments and form them into
+ * chains. You can then define a goal point that the end of the
+ * chain should attempt to reach - an inverse kinematic problem.
+ * This module will then modify the segments in the chain in
+ * order to get the end of the chain as near as possible to the
+ * goal. This solver uses an inverse jacobian method to find
+ * a solution.
+ *
+ * @section issues Known issues with this IK solver.
+ *
+ * - The current solver works with only one type of segment. These
+ * segments always have 3 degress of freedom (DOF). i.e. the solver
+ * uses all these degrees to solve the IK problem. It would be
+ * nice to allow the user to specify different segment types such
+ * as 1 DOF joints in a given plane. 2 DOF joints about given axis.
+ * - There is currently no support for joint constraints in the
+ * solver. This is within the realms of possibility - please ask
+ * if this functionality is required.
+ * - The solver is slow, inverse jacobian methods in general give
+ * 'smooth' solutions and the method is also very flexible, it
+ * does not rely on specific angle parameterization and can be
+ * extended to deal with different joint types and joint
+ * constraints. However it is not suitable for real time use.
+ * Other algorithms exist which are more suitable for real-time
+ * applications, please ask if this functionality is required.
+ *
+ * @section dependencies Dependencies
+ *
+ * This module only depends on Moto.
+ */
+
+#ifndef NAN_INCLUDED_IK_solver_h
+#define NAN_INCLUDED_IK_solver_h
+
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * External segment structure
+ */
+
+
+/**
+ * This structure defines a single segment of an IK chain.
+ * - Individual segments are always defined in local coordinates.
+ * - The segment is assumed to be oriented in the local
+ * y-direction.
+ * - seg_start is the start of the segment relative to the end
+ * of the parent segment.
+ * - basis is a column major matrix defining the rest position
+ * of the bone.
+ * - length is the simply the length of the bone.
+ * - basis_change is a 3x3 matrix representing the change
+ * from the rest position of the segment to the solved position.
+ * In fact it is the transpose of this matrix because blender
+ * does something weird with quaternion conversion. This is
+ * strictly an ouput variable for returning the results of an
+ * an ik solve back to you.
+ * The local transformation specified as a column major matrix
+ * of a segment is then defined as.
+ * translate(seg_start)*basis*transpose(basis_change)*translate(0,length,0)
+ */
+
+typedef struct IK_Segment_Extern {
+ float seg_start[3];
+ float basis[9];
+ float length;
+ float basis_change[9];
+} IK_Segment_Extern;
+
+typedef IK_Segment_Extern* IK_Segment_ExternPtr;
+
+/**
+ * External chain structure.
+ * This structure is filled when you call IK_LoadChain.
+ * The first segment in the chain is the root segment.
+ * The end of the last segment is the end-effector of the chain
+ * this is the point that tries to move to the goal in the ik
+ * solver.
+ * - num_segments is the number of segments in the array pointed
+ * to by the member segments.
+ * - chain_dof is the number of degrees of freedom of the chain
+ * that is the number of independent ways the chain can be changed
+ * to reach the goal.
+ * - segments points to an array of IK_Segment_Extern structs
+ * containing the segments of this chain.
+ * - intern is pointer used by the module to store information
+ * about the chain. Please do not touch the member in any way.
+ */
+
+typedef struct IK_Chain_Extern {
+ int num_segments;
+ int chain_dof;
+ IK_Segment_ExternPtr segments;
+ void * intern;
+} IK_Chain_Extern;
+
+typedef IK_Chain_Extern* IK_Chain_ExternPtr;
+
+
+/**
+ * Create a clean chain structure.
+ * @return A IK_Chain_Extern structure allocated on the heap.
+ * Do not attempt to delete or free this memory yourself please
+ * use the FreeChain(...) function for this.
+ */
+
+extern IK_Chain_ExternPtr IK_CreateChain(void);
+
+/**
+ * Copy segment information into the chain structure.
+ * @param chain A chain to load the segments into.
+ * @param segments a ptr to an array of IK_Input_Segment_Extern structures
+ * @param num_segs the number of segments to load into the chain
+ * @return 1 if the chain was correctly loaded into the structure.
+ * @return 0 if an error occured loading the chain. This will normally
+ * occur when there is not enough memory to allocate internal chain data.
+ * In this case you should not use the chain structure and should call
+ * IK_FreeChain to free the memory associated with the chain.
+ */
+
+extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs);
+
+/**
+ * Compute the solution of an inverse kinematic problem.
+ * @param chain a ptr to an IK_Segment_Extern loaded with the segments
+ * to solve for.
+ * @param goal the goal of the IK problem
+ * @param tolerance .The distance to the solution within which the chain is deemed
+ * to be solved.
+ * @param max_iterations. The maximum number of iterations to use in solving the
+ * problem.
+ * @param max_angle_change. The maximum allowed angular change. 0.1 is a good value here.
+ * @param output. Results of the solution are written to the segments pointed to by output.
+ * Only the basis and basis_change fields are written. You must make sure that you have
+ * allocated enough room for the output segments.
+ * @return 0 if the solved chain did not reach the goal. This occurs when the
+ * goal was unreachable by the chain end effector.
+ * @return 1 if the chain reached the goal.
+ */
+
+extern int IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+);
+
+/**
+ * Free a chain and all it's internal memory.
+ */
+
+extern void IK_FreeChain(IK_Chain_ExternPtr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NAN_INCLUDED_IK_solver_h \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_CGChainSolver.cpp b/intern/iksolver/intern/IK_CGChainSolver.cpp
new file mode 100644
index 00000000000..6af4df2a35b
--- /dev/null
+++ b/intern/iksolver/intern/IK_CGChainSolver.cpp
@@ -0,0 +1,300 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_CGChainSolver.h"
+
+#include "IK_Segment.h"
+
+using namespace std;
+
+ ChainPotential *
+ChainPotential::
+New(
+ IK_Chain &chain
+){
+ return new ChainPotential(chain);
+};
+
+
+
+// End effector goal
+
+ void
+ChainPotential::
+SetGoal(
+ const MT_Vector3 goal
+){
+ m_goal = goal;
+};
+
+// Inherited from DifferentiablePotenialFunctionNd
+//////////////////////////////////////////////////
+
+ MT_Scalar
+ChainPotential::
+Evaluate(
+ MT_Scalar x
+){
+
+ // evaluate the function at postiion x along the line specified
+ // by the vector pair (m_line_pos,m_line_dir)
+
+ m_temp_pos.newsize(m_line_dir.size());
+
+ TNT::vectorscale(m_temp_pos,m_line_dir,x);
+ TNT::vectoradd(m_temp_pos,m_line_pos);
+
+ return Evaluate(m_temp_pos);
+}
+
+ MT_Scalar
+ChainPotential::
+Derivative(
+ MT_Scalar x
+){
+ m_temp_pos.newsize(m_line_dir.size());
+ m_temp_grad.newsize(m_line_dir.size());
+
+ TNT::vectorscale(m_temp_pos,m_line_dir,x);
+ TNT::vectoradd(m_temp_pos,m_line_pos);
+
+ Derivative(m_temp_pos,m_temp_grad);
+
+ return TNT::dot_prod(m_temp_grad,m_line_dir);
+}
+
+
+ MT_Scalar
+ChainPotential::
+Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+){
+
+
+ // set the vector of angles in the backup chain
+
+ vector<IK_Segment> &segs = m_t_chain.Segments();
+ vector<IK_Segment>::iterator seg_it = segs.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin();
+#if 0
+ TNT::Vector<MT_Scalar>::const_iterator a_end = x.end();
+#endif
+ // while we are iterating through the angles and segments
+ // we compute the current angle potenial
+ MT_Scalar angle_potential = 0;
+#if 0
+
+ for (; a_it != a_end; ++a_it, ++seg_it) {
+
+ MT_Scalar dif = (*a_it - seg_it->CentralAngle());
+ dif *= dif * seg_it->Weight();
+ angle_potential += dif;
+ seg_it->SetTheta(*a_it);
+ }
+#endif
+
+ int chain_dof = m_t_chain.DoF();
+ int n;
+
+ for (n=0; n < chain_dof;seg_it ++) {
+ n += seg_it->SetAngles(a_it + n);
+ }
+
+
+ m_t_chain.UpdateGlobalTransformations();
+
+ MT_Scalar output = (DistancePotential(m_t_chain.EndEffector(),m_goal) + angle_potential);
+
+ return output;
+};
+
+ void
+ChainPotential::
+Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+){
+
+ m_distance_grad.newsize(3);
+ // set the vector of angles in the backup chain
+
+ vector<IK_Segment> & segs = m_t_chain.Segments();
+ vector<IK_Segment>::iterator seg_it = segs.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_end = x.end();
+
+ m_angle_grad.newsize(segs.size());
+ m_angle_grad = 0;
+#if 0
+ // FIXME compute angle gradients
+ TNT::Vector<MT_Scalar>::iterator ag_it = m_angle_grad.begin();
+#endif
+
+ const int chain_dof = m_t_chain.DoF();
+ for (int n=0; n < chain_dof;seg_it ++) {
+ n += seg_it->SetAngles(a_it + n);
+ }
+
+ m_t_chain.UpdateGlobalTransformations();
+ m_t_chain.ComputeJacobian();
+
+ DistanceGradient(m_t_chain.EndEffector(),m_goal);
+
+ // use chain rule for calculating derivative
+ // of potenial function
+ TNT::matmult(dy,m_t_chain.TransposedJacobian(),m_distance_grad);
+#if 0
+ TNT::vectoradd(dy,m_angle_grad);
+#endif
+
+};
+
+
+ MT_Scalar
+ChainPotential::
+DistancePotential(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+) const {
+ return (pos - goal).length2();
+}
+
+// update m_distance_gradient
+
+ void
+ChainPotential::
+DistanceGradient(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+){
+
+ MT_Vector3 output = 2*(pos - goal);
+ m_distance_grad.newsize(3);
+
+ m_distance_grad[0] = output.x();
+ m_distance_grad[1] = output.y();
+ m_distance_grad[2] = output.z();
+}
+
+
+ IK_CGChainSolver *
+IK_CGChainSolver::
+New(
+){
+
+ MEM_SmartPtr<IK_CGChainSolver> output (new IK_CGChainSolver());
+ MEM_SmartPtr<IK_ConjugateGradientSolver>solver (IK_ConjugateGradientSolver::New());
+
+ if (output == NULL || solver == NULL) return NULL;
+
+ output->m_grad_solver = solver.Release();
+ return output.Release();
+};
+
+
+ bool
+IK_CGChainSolver::
+Solve(
+ IK_Chain & chain,
+ MT_Vector3 new_position,
+ MT_Scalar tolerance
+){
+
+ // first build a potenial function for the chain
+
+ m_potential = ChainPotential::New(chain);
+ if (m_potential == NULL) return false;
+
+ m_potential->SetGoal(new_position);
+
+ // make a TNT::vector to describe the current
+ // chain state
+
+ TNT::Vector<MT_Scalar> p;
+ p.newsize(chain.DoF());
+
+ TNT::Vector<MT_Scalar>::iterator p_it = p.begin();
+ vector<IK_Segment>::const_iterator seg_it = chain.Segments().begin();
+ vector<IK_Segment>::const_iterator seg_end = chain.Segments().end();
+
+ for (; seg_it != seg_end; seg_it++) {
+
+ int i;
+ int seg_dof = seg_it->DoF();
+ for (i=0; i < seg_dof; ++i,++p_it) {
+ *p_it = seg_it->ActiveAngle(i);
+ }
+ }
+
+ // solve the thing
+ int iterations(0);
+ MT_Scalar return_value(0);
+
+ m_grad_solver->Solve(
+ p,
+ tolerance,
+ iterations,
+ return_value,
+ m_potential.Ref(),
+ 100
+ );
+
+ // update this chain
+
+ vector<IK_Segment>::iterator out_seg_it = chain.Segments().begin();
+ TNT::Vector<MT_Scalar>::const_iterator p_cit = p.begin();
+
+ const int chain_dof = chain.DoF();
+ int n;
+
+ for (n=0; n < chain_dof;out_seg_it ++) {
+ n += out_seg_it->SetAngles(p_cit + n);
+ }
+
+ chain.UpdateGlobalTransformations();
+ chain.ComputeJacobian();
+
+ return true;
+}
+
+IK_CGChainSolver::
+~IK_CGChainSolver(
+){
+ //nothing to do
+};
+
+
+IK_CGChainSolver::
+IK_CGChainSolver(
+){
+ //nothing to do;
+};
+
diff --git a/intern/iksolver/intern/IK_CGChainSolver.h b/intern/iksolver/intern/IK_CGChainSolver.h
new file mode 100644
index 00000000000..f7aeee090a1
--- /dev/null
+++ b/intern/iksolver/intern/IK_CGChainSolver.h
@@ -0,0 +1,178 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef CGChainSolver_h
+
+#define CGChainSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "IK_ConjugateGradientSolver.h"
+#include "IK_Chain.h"
+#include "MT_Scalar.h"
+#include "TNT/vec.h"
+#include "MEM_SmartPtr.h"
+
+
+/**
+ * This class is a concrete differentiable potenial function for
+ * an IK_Chain representing the distance to the goal.
+ * @warning This method of solving IK problems is not as good
+ * as IK_JacobianSolver. I advise you to use that class instead.
+ */
+
+class ChainPotential :
+public DifferentiablePotenialFunctionNd
+{
+public :
+
+ static
+ ChainPotential *
+ New(
+ IK_Chain &chain
+ );
+
+ // End effector goal
+
+ void
+ SetGoal(
+ const MT_Vector3 goal
+ );
+
+ // Inherited from DifferentiablePotenialFunctionNd
+ //////////////////////////////////////////////////
+
+ MT_Scalar
+ Evaluate(
+ const MT_Scalar x
+ );
+
+ MT_Scalar
+ Derivative(
+ const MT_Scalar x
+ );
+
+ MT_Scalar
+ Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+ );
+
+ void
+ Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+ );
+
+ // return the dimension of the domain of the potenial
+ // function
+
+ int
+ Dimension(
+ ) const {
+ return m_dimension;
+ }
+
+ ~ChainPotential(
+ ){
+ };
+
+private :
+
+ MT_Scalar
+ DistancePotential(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+ ) const;
+
+ void
+ DistanceGradient(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+ );
+
+ ChainPotential(
+ IK_Chain & chain
+ ) :
+ DifferentiablePotenialFunctionNd(),
+ m_chain(chain),
+ m_t_chain(chain),
+ m_dimension (chain.Segments().size())
+ {
+ };
+
+ MT_Vector3 m_goal;
+ TNT::Vector<MT_Scalar> m_distance_grad;
+ TNT::Vector<MT_Scalar> m_angle_grad;
+ TNT::Vector<MT_Scalar> m_temp_pos;
+ TNT::Vector<MT_Scalar> m_temp_grad;
+
+ TNT::Vector<MT_Scalar> m_original_pos;
+ int m_dimension;
+
+ IK_Chain &m_chain;
+ IK_Chain m_t_chain; // deep copy
+
+};
+
+
+class IK_CGChainSolver : public MEM_NonCopyable
+{
+public :
+
+
+ static
+ IK_CGChainSolver *
+ New(
+ );
+
+ bool
+ Solve(
+ IK_Chain & chain,
+ MT_Vector3 new_position,
+ MT_Scalar tolerance
+ );
+
+ ~IK_CGChainSolver();
+
+private :
+
+ IK_CGChainSolver(
+ );
+
+ MEM_SmartPtr<ChainPotential> m_potential;
+ MEM_SmartPtr<IK_ConjugateGradientSolver> m_grad_solver;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_Chain.cpp b/intern/iksolver/intern/IK_Chain.cpp
new file mode 100644
index 00000000000..875b8da1405
--- /dev/null
+++ b/intern/iksolver/intern/IK_Chain.cpp
@@ -0,0 +1,208 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_Chain.h"
+
+
+using namespace std;
+
+IK_Chain::
+IK_Chain(
+)
+{
+ // nothing to do;
+};
+
+const
+ vector<IK_Segment> &
+IK_Chain::
+Segments(
+) const {
+ return m_segments;
+};
+
+ vector<IK_Segment> &
+IK_Chain::
+Segments(
+){
+ return m_segments;
+};
+
+ void
+IK_Chain::
+UpdateGlobalTransformations(
+){
+
+ // now iterate through the segment list
+ // compute their local transformations if needed
+
+ // assign their global transformations
+ // (relative to chain origin)
+
+ vector<IK_Segment>::const_iterator s_end = m_segments.end();
+ vector<IK_Segment>::iterator s_it = m_segments.begin();
+
+ MT_Transform global;
+
+ global.setIdentity();
+
+ for (; s_it != s_end; ++s_it) {
+ s_it->UpdateGlobal(global);
+ global = s_it->GlobalTransform();
+ }
+ // compute the position of the end effector and it's pose
+
+ const MT_Transform &last_t = m_segments.back().GlobalTransform();
+ m_end_effector = last_t.getOrigin();
+
+ MT_Matrix3x3 last_basis = last_t.getBasis();
+ last_basis.transpose();
+ MT_Vector3 m_end_pose = last_basis[2];
+
+
+};
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_Chain::
+Jacobian(
+) const {
+ return m_jacobian;
+} ;
+
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_Chain::
+TransposedJacobian(
+) const {
+ return m_t_jacobian;
+};
+
+ void
+IK_Chain::
+ComputeJacobian(
+){
+ // let's assume that the chain's global transfomations
+ // have already been computed.
+
+ int dof = DoF();
+
+ int num_segs = m_segments.size();
+ vector<IK_Segment>::const_iterator segs = m_segments.begin();
+
+ m_t_jacobian.newsize(dof,3);
+ m_jacobian.newsize(3,dof);
+
+ // compute the transposed jacobian first
+
+ int n;
+ int i = 0;
+
+
+ for (n= 0; n < num_segs; n++) {
+
+ const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis();
+ const MT_Vector3 &origin = segs[n].GlobalSegmentStart();
+
+ MT_Vector3 p = origin-m_end_effector;
+
+ // iterate through the active angle vectors of this segment
+
+ int angle_ind =0;
+ int seg_dof = segs[n].DoF();
+
+ const std::vector<MT_Vector3> & angle_vectors = segs[n].AngleVectors();
+
+ for (angle_ind = 0;angle_ind <seg_dof; angle_ind++,i++) {
+
+ MT_Vector3 angle_axis = angle_vectors[angle_ind];
+
+ MT_Vector3 a = basis * angle_axis;
+ MT_Vector3 pca = p.cross(a);
+
+ m_t_jacobian(i + 1,1) = pca.x();
+ m_t_jacobian(i + 1,2) = pca.y();
+ m_t_jacobian(i + 1,3) = pca.z();
+
+ }
+ }
+
+ // get the origina1 jacobain
+
+ TNT::transpose(m_t_jacobian,m_jacobian);
+};
+
+ MT_Vector3
+IK_Chain::
+EndEffector(
+) const {
+ return m_end_effector;
+};
+
+ MT_Vector3
+IK_Chain::
+EndPose(
+) const {
+ return m_end_pose;
+};
+
+
+ int
+IK_Chain::
+DoF(
+) const {
+
+ // iterate through the segs and compute the DOF
+
+ vector<IK_Segment>::const_iterator s_end = m_segments.end();
+ vector<IK_Segment>::const_iterator s_it = m_segments.begin();
+
+ int dof = 0;
+
+ for (;s_it != s_end; ++s_it) {
+ dof += s_it->DoF();
+ }
+
+ return dof;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Chain.h b/intern/iksolver/intern/IK_Chain.h
new file mode 100644
index 00000000000..40496b6087a
--- /dev/null
+++ b/intern/iksolver/intern/IK_Chain.h
@@ -0,0 +1,194 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_Chain_h
+
+#define NAN_INCLUDED_IK_Chain_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "IK_Segment.h"
+#include <vector>
+#include "MT_Scalar.h"
+#include "TNT/cmat.h"
+
+/**
+ * This class is a collection of ordered segments that are used
+ * in an Inverse Kinematic solving routine. An IK solver operating
+ * on the chain, will in general manipulate all the segments of the
+ * chain in order to solve the IK problem.
+ *
+ * To build a chain use the default constructor. Once built it's
+ * then possible to add IK_Segments to the chain by inserting
+ * them into the vector of IK_Segments. Note that segments will be
+ * copied into the chain so chain's cannot share instances of
+ * IK_Segments.
+ *
+ * You have full control of which segments form the chain via the
+ * the std::vector routines.
+ */
+class IK_Chain{
+
+public :
+
+ /**
+ * Construct a IK_Chain with no segments.
+ */
+
+ IK_Chain(
+ );
+
+ // IK_Chains also have the default copy constructors
+ // available.
+
+ /**
+ * Const access to the array of segments
+ * comprising the IK_Chain. Used for rendering
+ * etc
+ * @return a vector of segments
+ */
+
+ const
+ std::vector<IK_Segment> &
+ Segments(
+ ) const ;
+
+
+ /**
+ * Full access to segments used to initialize
+ * the IK_Chain and manipulate the segments.
+ * Use the push_back() method of std::vector to add
+ * segments in order to the chain
+ */
+
+ std::vector<IK_Segment> &
+ Segments(
+ );
+
+
+ /**
+ * Force the IK_Chain to recompute all the local
+ * segment transformations and composite them
+ * to calculate the global transformation for
+ * each segment. Must be called before
+ * ComputeJacobian()
+ */
+
+ void
+ UpdateGlobalTransformations(
+ );
+
+ /**
+ * Return the global position of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndEffector(
+ ) const;
+
+
+ /**
+ * Return the global pose of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndPose(
+ ) const;
+
+
+ /**
+ * Calculate the jacobian matrix for
+ * the current end effector position.
+ * A jacobian is the set of column vectors
+ * of partial derivatives for each active angle.
+ * This method also computes the transposed jacobian.
+ * @pre You must have updated the global transformations
+ * of the chain's segments before a call to this method. Do this
+ * with UpdateGlobalTransformation()
+ */
+
+ void
+ ComputeJacobian(
+ );
+
+
+ /**
+ * @return A reference to the last computed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ Jacobian(
+ ) const ;
+
+ /**
+ * @return A reference to the last computed transposed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ TransposedJacobian(
+ ) const ;
+
+ /**
+ * Count the degrees of freedom in the IK_Chain
+ * @warning store this value rather than using this function
+ * as the termination value of a for loop etc.
+ */
+
+ int
+ DoF(
+ ) const;
+
+
+private :
+
+ /// The vector of segments comprising the chain
+ std::vector<IK_Segment> m_segments;
+
+ /// The jacobain of the IK_Chain
+ TNT::Matrix<MT_Scalar> m_jacobian;
+
+ /// It's transpose
+ TNT::Matrix<MT_Scalar> m_t_jacobian;
+
+ MT_Vector3 m_end_effector;
+ MT_Vector3 m_end_pose;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp
new file mode 100644
index 00000000000..028b7dfe2b0
--- /dev/null
+++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp
@@ -0,0 +1,162 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_ConjugateGradientSolver.h"
+
+
+#define EPS 1.0e-10
+
+ IK_ConjugateGradientSolver *
+IK_ConjugateGradientSolver::
+New(
+){
+ return new IK_ConjugateGradientSolver();
+};
+
+IK_ConjugateGradientSolver::
+~IK_ConjugateGradientSolver(
+){
+ //nothing to do
+};
+
+// Compute the minimum of the potenial function
+// starting at point p. On return p contains the
+// computed minima, iter the number of iterations performed,
+// fret the potenial value at the minima
+
+ void
+IK_ConjugateGradientSolver::
+Solve(
+ TNT::Vector<MT_Scalar> &p,
+ MT_Scalar ftol,
+ int &iter,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial,
+ int max_its
+){
+
+ int j;
+ MT_Scalar gg,gam,fp,dgg;
+
+ int n = potenial.Dimension();
+ ArmVectors(n);
+
+ // initialize --- FIXME we probably have these
+ // values to hand already.
+
+ fp = potenial.Evaluate(p);
+ potenial.Derivative(p,m_xi);
+
+ for (j = 1; j<=n; j++) {
+ m_g(j) = -m_xi(j);
+ m_xi(j) = m_h(j) = m_g(j);
+ }
+ for (iter =1;iter <= max_its; iter++) {
+ LineMinimize(p,m_xi,fret,potenial);
+
+ if (2 *TNT::abs(fret-fp) <= ftol*(TNT::abs(fret) + TNT::abs(fp) + EPS)) {
+ return;
+ }
+ fp = fret;
+ potenial.Derivative(p,m_xi);
+ dgg = gg = 0.0;
+
+ for (j = 1; j<=n;j++) {
+ gg += m_g(j)*m_g(j);
+ //dgg+= xi(j)*xi(j);
+ dgg += (m_xi(j) + m_g(j))*m_xi(j);
+ }
+ if (gg == 0.0) {
+ return;
+ }
+ gam = dgg/gg;
+
+ for (j = 1; j<=n; j++) {
+ m_g(j) = -m_xi(j);
+ m_xi(j) = m_h(j) = m_g(j) + gam*m_h(j);
+ }
+ }
+ // FIXME throw exception
+ //assert(false);
+};
+
+
+IK_ConjugateGradientSolver::
+IK_ConjugateGradientSolver(
+){
+ //nothing to do
+}
+
+ void
+IK_ConjugateGradientSolver::
+ArmVectors(
+ int dimension
+){
+ m_g.newsize(dimension);
+ m_h.newsize(dimension);
+ m_xi.newsize(dimension);
+ m_xi_temp.newsize(dimension);
+};
+
+ void
+IK_ConjugateGradientSolver::
+LineMinimize(
+ TNT::Vector<MT_Scalar> & p,
+ const TNT::Vector<MT_Scalar> & xi,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial
+){
+ MT_Scalar ax(0),bx(1); // initial bracket guess
+ MT_Scalar cx,fa,fb,fc;
+
+ MT_Scalar xmin(0); // the 1d function minima
+
+ potenial.SetLineVector(p,xi);
+ IK_LineMinimizer::InitialBracket1d(ax,bx,cx,fa,fb,fc,potenial);
+ fret = IK_LineMinimizer::DerivativeBrent1d(ax,bx,cx,potenial,xmin,0.001);
+
+ // x_min in minimum along line and corresponds with
+ // p[] + x_min *xi[]
+
+ TNT::vectorscale(m_xi_temp,xi,xmin);
+ TNT::vectoradd(p,m_xi_temp);
+};
+
+
+#undef EPS
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.h b/intern/iksolver/intern/IK_ConjugateGradientSolver.h
new file mode 100644
index 00000000000..e50799a9fa1
--- /dev/null
+++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.h
@@ -0,0 +1,195 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_ConjugateGradientSolver_h
+
+#define NAN_INCLUDED_IK_ConjugateGradientSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include "MT_Scalar.h"
+#include "IK_LineMinimizer.h"
+
+/**
+ * These classes locally minimize n dimensional potenial functions.
+ * See Numerical Recipes in C www.nr.com for more details.
+ * If a n dimensionable potenial function is
+ * differentiable, then it is diferentiable along
+ * any vector x. This can be found by the dot product
+ * of the gradient operator with x.
+ * The conjugate gradient solver boils down to
+ * a collection of line minimizations along various lines
+ * defined by position,direction pairs. There are
+ * methods in this class to set the lines along which
+ * minimizations via the DiffentiablePotenialFunction1d interface
+ * are to be performed.
+ *
+ * @warning I don't like data inheritance but it is the most efficient
+ * wasy to do this here.
+ */
+
+
+class DifferentiablePotenialFunctionNd
+: public DifferentiablePotenialFunction1d
+{
+public :
+
+ /**
+ * Inherited from DiffentiablePotenialFunction1d
+ *
+ * virtual
+ * MT_Scalar
+ * Evaluate1d(
+ * MT_Scalar x
+ * ) = 0;
+ *
+ * virtual
+ * MT_Scalar
+ * Derivative1d(
+ * MT_Scalar x
+ * ) = 0;
+ */
+
+ /// Methods to set the current line in N dimensions
+
+ void
+ SetLineVector(
+ const TNT::Vector<MT_Scalar> &pos,
+ const TNT::Vector<MT_Scalar> &dir
+ ){
+ m_line_pos = pos;
+ m_line_dir = dir;
+ };
+
+ virtual
+ MT_Scalar
+ Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+ ) = 0;
+
+ virtual
+ void
+ Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+ ) = 0;
+
+ /// @return The dimension of the domain of the potenial function
+
+ virtual
+ int
+ Dimension(
+ ) const =0;
+
+ virtual
+ ~DifferentiablePotenialFunctionNd(
+ ){
+ };
+
+protected :
+
+ DifferentiablePotenialFunctionNd(){};
+
+ TNT::Vector<MT_Scalar> m_line_pos;
+ TNT::Vector<MT_Scalar> m_line_dir;
+
+};
+
+
+class IK_ConjugateGradientSolver
+: public MEM_NonCopyable
+{
+public :
+
+ /**
+ * This class necessarily needs some (potenially large)
+ * temporary vectors to aid computation. We therefore
+ * insist creation of these objects on the heap.
+ */
+
+ static
+ IK_ConjugateGradientSolver *
+ New(
+ );
+
+ /**
+ * Compute the minimum of the potenial function
+ * starting at point p. On return p contains the
+ * computed minima, iter the number of iterations performed,
+ * fret the potenial value at the minima
+ */
+
+ void
+ Solve(
+ TNT::Vector<MT_Scalar> &p,
+ MT_Scalar ftol,
+ int &iter,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial,
+ int max_its = 200
+ );
+
+ ~IK_ConjugateGradientSolver(
+ );
+
+private :
+ void
+ LineMinimize(
+ TNT::Vector<MT_Scalar> & p,
+ const TNT::Vector<MT_Scalar> & xi,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial
+ );
+
+ IK_ConjugateGradientSolver(
+ );
+
+ void
+ ArmVectors(
+ int dimension
+ );
+
+
+ TNT::Vector<MT_Scalar> m_g;
+ TNT::Vector<MT_Scalar> m_h;
+ TNT::Vector<MT_Scalar> m_xi;
+
+ TNT::Vector<MT_Scalar> m_xi_temp;
+
+};
+
+#endif
+
+
diff --git a/intern/iksolver/intern/IK_JacobianSolver.cpp b/intern/iksolver/intern/IK_JacobianSolver.cpp
new file mode 100644
index 00000000000..de4531f1677
--- /dev/null
+++ b/intern/iksolver/intern/IK_JacobianSolver.cpp
@@ -0,0 +1,267 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_JacobianSolver.h"
+
+#include "TNT/svd.h"
+
+using namespace std;
+
+ IK_JacobianSolver *
+IK_JacobianSolver::
+New(
+){
+ return new IK_JacobianSolver();
+}
+
+ bool
+IK_JacobianSolver::
+Solve(
+ IK_Chain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+){
+
+ ArmMatrices(chain.DoF());
+
+ for (int iterations = 0; iterations < max_iterations; iterations++) {
+
+
+ MT_Vector3 end_effector = chain.EndEffector();
+
+ MT_Vector3 d_pos = g_position - end_effector;
+ const MT_Scalar x_length = d_pos.length();
+
+ if (x_length < tolerance) {
+ return true;
+ }
+
+ chain.ComputeJacobian();
+ ComputeInverseJacobian(chain,x_length,max_angle_change);
+
+ ComputeBetas(chain,d_pos);
+ UpdateChain(chain);
+ chain.UpdateGlobalTransformations();
+ }
+
+ return false;
+};
+
+IK_JacobianSolver::
+~IK_JacobianSolver(
+){
+ // nothing to do
+}
+
+
+IK_JacobianSolver::
+IK_JacobianSolver(
+){
+ // nothing to do
+};
+
+ void
+IK_JacobianSolver::
+ComputeBetas(
+ IK_Chain &chain,
+ const MT_Vector3 d_pos
+){
+
+ m_beta = 0;
+
+ m_beta[0] = d_pos.x();
+ m_beta[1] = d_pos.y();
+ m_beta[2] = d_pos.z();
+
+ TNT::matmult(m_d_theta,m_svd_inverse,m_beta);
+
+};
+
+
+ int
+IK_JacobianSolver::
+ComputeInverseJacobian(
+ IK_Chain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+) {
+
+ int dimension = 0;
+
+ m_svd_u = 0;
+
+ // copy first 3 rows of jacobian into m_svd_u
+
+ int row, column;
+
+ for (row = 0; row < 3; row ++) {
+ for (column = 0; column < chain.Jacobian().num_cols(); column ++) {
+ m_svd_u[row][column] = chain.Jacobian()[row][column];
+ }
+ }
+
+ m_svd_w = 0;
+ m_svd_v = 0;
+
+ TNT::SVD(m_svd_u,m_svd_w,m_svd_v);
+
+ // invert the SVD and compute inverse
+
+ TNT::transpose(m_svd_v,m_svd_v_t);
+ TNT::transpose(m_svd_u,m_svd_u_t);
+
+ // Compute damped least squares inverse of pseudo inverse
+ // Compute damping term lambda
+
+ // Note when lambda is zero this is equivalent to the
+ // least squares solution. This is fine when the m_jjt is
+ // of full rank. When m_jjt is near to singular the least squares
+ // inverse tries to minimize |J(dtheta) - dX)| and doesn't
+ // try to minimize dTheta. This results in eratic changes in angle.
+ // Damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
+
+ // We don't want to use the damped solution everywhere so we
+ // only increase lamda from zero as we approach a singularity.
+
+ // find the smallest non-zero m_svd_w value
+
+ int i = 0;
+
+ MT_Scalar w_min = MT_INFINITY;
+
+ // anything below epsilon is treated as zero
+
+ MT_Scalar epsilon = 1e-10;
+
+ for ( i = 0; i <m_svd_w.size() ; i++) {
+
+ if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
+ w_min = m_svd_w[i];
+ }
+ }
+ MT_Scalar lambda = 0;
+
+ MT_Scalar d = x_length/max_angle_change;
+
+ if (w_min <= d/2) {
+ lambda = d/2;
+ } else
+ if (w_min < d) {
+ lambda = sqrt(w_min*(d - w_min));
+ } else {
+ lambda = 0;
+ }
+
+ lambda *= lambda;
+
+ for (i= 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] < epsilon) {
+ m_svd_w[i] = 0;
+ } else {
+ m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ }
+ }
+
+ m_svd_w_diag.diagonal(m_svd_w);
+
+ // FIXME optimize these matrix multiplications
+ // using the fact that m_svd_w_diag is diagonal!
+
+ TNT::matmult(m_svd_temp1,m_svd_w_diag,m_svd_u_t);
+ TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1);
+ return dimension;
+
+}
+
+ void
+IK_JacobianSolver::
+UpdateChain(
+ IK_Chain &chain
+){
+
+ // iterate through the set of angles and
+ // update their values from the d_thetas
+
+ int n;
+ vector<IK_Segment> &segs = chain.Segments();
+
+ int chain_dof = chain.DoF();
+ int seg_ind = 0;
+ for (n=0; n < chain_dof;seg_ind ++) {
+ n += segs[seg_ind].IncrementAngles(m_d_theta.begin() + n);
+ }
+};
+
+ void
+IK_JacobianSolver::
+ArmMatrices(
+ int dof
+){
+
+ m_beta.newsize(dof);
+ m_d_theta.newsize(dof);
+
+ m_svd_u.newsize(dof,dof);
+ m_svd_v.newsize(dof,dof);
+ m_svd_w.newsize(dof);
+
+ m_svd_u = 0;
+ m_svd_v = 0;
+ m_svd_w = 0;
+
+ m_svd_u_t.newsize(dof,dof);
+ m_svd_v_t.newsize(dof,dof);
+ m_svd_w_diag.newsize(dof,dof);
+ m_svd_inverse.newsize(dof,dof);
+ m_svd_temp1.newsize(dof,dof);
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_JacobianSolver.h b/intern/iksolver/intern/IK_JacobianSolver.h
new file mode 100644
index 00000000000..3f3372a2cb7
--- /dev/null
+++ b/intern/iksolver/intern/IK_JacobianSolver.h
@@ -0,0 +1,171 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_JacobianSolver_h
+
+#define NAN_INCLUDED_IK_JacobianSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include <vector>
+#include "MT_Vector3.h"
+#include "IK_Chain.h"
+
+class IK_JacobianSolver {
+
+public :
+
+ /**
+ * Create a new IK_JacobianSolver on the heap
+ * @return A newly created IK_JacobianSolver you take ownership of the object
+ * and responsibility for deleting it
+ */
+
+
+ static
+ IK_JacobianSolver *
+ New(
+ );
+
+ /**
+ * Compute a solution for a chain.
+ * @param chain Reference to the chain to modify
+ * @param g_position Reference to the goal position.
+ * @param g_pose -not used- Reference to the goal pose.
+ * @param tolerance The maximum allowed distance between solution
+ * and goal for termination.
+ * @param max_iterations should be in the range (50 - 500)
+ * @param max_angle_change The maximum change in the angle vector
+ * of the chain (0.1 is a good value)
+ *
+ * @return True iff goal position reached.
+ */
+
+ bool
+ Solve(
+ IK_Chain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+ );
+
+ ~IK_JacobianSolver(
+ );
+
+
+private :
+
+ /**
+ * Private constructor to force use of New()
+ */
+
+ IK_JacobianSolver(
+ );
+
+
+ /**
+ * Compute the inverse jacobian matrix of the chain.
+ * Uses a damped least squares solution when the matrix is
+ * is approaching singularity
+ */
+
+ int
+ ComputeInverseJacobian(
+ IK_Chain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+ );
+
+ void
+ ComputeBetas(
+ IK_Chain &chain,
+ const MT_Vector3 d_pos
+ );
+
+ /**
+ * Updates the angles of the chain with the newly
+ * computed values
+ **/
+
+ void
+ UpdateChain(
+ IK_Chain &chain
+ );
+
+ /**
+ * Make sure all the matrices are of the correct size
+ **/
+
+ void
+ ArmMatrices(
+ int dof
+ );
+
+
+private :
+
+ /// the vector of intermediate betas
+ TNT::Vector<MT_Scalar> m_beta;
+
+ /// the vector of computed angle changes
+ TNT::Vector<MT_Scalar> m_d_theta;
+
+ /// the contraint gradients for each angle.
+ TNT::Vector<MT_Scalar> m_dh;
+
+ /// Space required for SVD computation
+
+ TNT::Vector<MT_Scalar> m_svd_w;
+ TNT::Matrix<MT_Scalar> m_svd_v;
+ TNT::Matrix<MT_Scalar> m_svd_u;
+
+ TNT::Matrix<MT_Scalar> m_svd_w_diag;
+ TNT::Matrix<MT_Scalar> m_svd_v_t;
+ TNT::Matrix<MT_Scalar> m_svd_u_t;
+ TNT::Matrix<MT_Scalar> m_svd_inverse;
+ TNT::Matrix<MT_Scalar> m_svd_temp1;
+
+
+};
+
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/IK_LineMinimizer.h b/intern/iksolver/intern/IK_LineMinimizer.h
new file mode 100644
index 00000000000..635a5972c02
--- /dev/null
+++ b/intern/iksolver/intern/IK_LineMinimizer.h
@@ -0,0 +1,298 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_LineMinimizer_h
+
+#define NAN_INCLUDED_IK_LineMinimizer_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "MT_Scalar.h"
+#include <vector>
+#include "TNT/tntmath.h"
+#include "MEM_NonCopyable.h"
+
+
+
+#define GOLD 1.618034
+#define GLIMIT 100.0
+#define TINY 1.0e-20
+#define ZEPS 1.0e-10
+
+/**
+ * Routines for line - minization in n dimensions
+ * these should be templated on the potenial function
+ * p instead of using a virtual class. Please see
+ * numerical recipes in c for more details. www.nr.com
+ */
+
+class DifferentiablePotenialFunction1d {
+public :
+ virtual
+ MT_Scalar
+ Evaluate(
+ const MT_Scalar x
+ ) = 0;
+
+ virtual
+ MT_Scalar
+ Derivative(
+ const MT_Scalar x
+ ) = 0;
+};
+
+
+/**
+ * TODO get rid of this class and make some
+ * template functions in a seperate namespace
+ */
+
+class IK_LineMinimizer : public MEM_NonCopyable {
+
+public :
+
+ /**
+ * Before we proceed with line minimization
+ * we need to construct an initial bracket
+ * of a minima of the PotenialFunction
+ */
+
+ static
+ void
+ InitialBracket1d (
+ MT_Scalar &ax,
+ MT_Scalar &bx,
+ MT_Scalar &cx,
+ MT_Scalar &fa,
+ MT_Scalar &fb,
+ MT_Scalar &fc,
+ DifferentiablePotenialFunction1d &potenial
+ ) {
+ MT_Scalar ulim,u,r,q,fu;
+
+ fa = potenial.Evaluate(ax);
+ fb = potenial.Evaluate(bx);
+
+ if (fb > fa) {
+ std::swap(ax,bx);
+ std::swap(fa,fb);
+ }
+ cx = bx + GOLD*(bx-ax);
+ fc = potenial.Evaluate(cx);
+
+ while (fb > fc) {
+
+ r = (bx - ax) * (fb - fc);
+ q = (bx - cx) * (fb - fa);
+ u = bx - ((bx - cx)*q - (bx - ax) *r)/
+ (2 * TNT::sign(TNT::max(TNT::abs(q-r),TINY),q-r));
+ ulim = bx + GLIMIT*(cx-bx);
+
+ if ((bx-u)*(u-cx) > 0.0) {
+ fu = potenial.Evaluate(u);
+ if (fu < fc) {
+ ax = bx;
+ bx = u;
+ fa = fb;
+ fb = fu;
+ return;
+ } else if (fu > fb) {
+ cx = u;
+ fc = fu;
+ return;
+ }
+ u = cx + GOLD*(cx-bx);
+ fu = potenial.Evaluate(u);
+
+ } else if ((cx - u)*(u - ulim) > 0.0) {
+ fu = potenial.Evaluate(u);
+
+ if (fu < fc) {
+ bx = cx;
+ cx = u;
+ u = cx + GOLD*(cx - bx);
+ fb = fc;
+ fc = fu;
+ fu = potenial.Evaluate(u);
+ }
+ } else if ((u-ulim)*(ulim-cx) >=0.0) {
+ u = ulim;
+ fu = potenial.Evaluate(u);
+ } else {
+ u = cx + GOLD*(cx-bx);
+ fu = potenial.Evaluate(u);
+ }
+ ax = bx;
+ bx = cx;
+ cx = u;
+ fa = fb;
+ fb = fc;
+ fc = fu;
+ }
+ };
+
+ /**
+ * This is a 1 dimensional brent method for
+ * line-minization with derivatives
+ */
+
+
+ static
+ MT_Scalar
+ DerivativeBrent1d(
+ MT_Scalar ax,
+ MT_Scalar bx,
+ MT_Scalar cx,
+ DifferentiablePotenialFunction1d &potenial,
+ MT_Scalar &x_min,
+ const MT_Scalar tol,
+ int max_iter = 100
+ ) {
+ int iter;
+ bool ok1,ok2;
+ MT_Scalar a,b,d,d1,d2,du,dv,dw,dx,e(0);
+ MT_Scalar fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm;
+
+ a = (ax < cx ? ax : cx);
+ b = (ax > cx ? ax : cx);
+ x = w = v = bx;
+ fw = fv = fx = potenial.Evaluate(x);
+ dw = dv = dx = potenial.Derivative(x);
+
+ for (iter = 1; iter <= max_iter; iter++) {
+ xm = 0.5*(a+b);
+ tol1 = tol*fabs(x) + ZEPS;
+ tol2 = 2 * tol1;
+ if (fabs(x - xm) <= (tol2 - 0.5*(b-a))) {
+ x_min = x;
+ return fx;
+ }
+
+ if (fabs(e) > tol1) {
+ d1 = 2*(b-a);
+ d2 = d1;
+ if (dw != dx) {
+ d1 = (w-x)*dx/(dx-dw);
+ }
+ if (dv != dx) {
+ d2 = (v-x)*dx/(dx-dv);
+ }
+
+ u1 = x+d1;
+ u2 = x+d2;
+ ok1 = ((a-u1)*(u1-b) > 0.0) && ((dx*d1) <= 0.0);
+ ok2 = ((a-u2)*(u2-b) > 0.0) && ((dx*d2) <= 0.0);
+ olde = e;
+ e = d;
+
+ if (ok1 || ok2) {
+ if (ok1 && ok2) {
+ d = fabs(d1) < fabs(d2) ? d1 : d2;
+ } else if (ok1) {
+ d = d1;
+ } else {
+ d = d2;
+ }
+ if (fabs(d) <= fabs(0.5*olde)) {
+ u = x+d;
+ if ((u-a < tol2) || (b-u < tol2)) {
+ d = TNT::sign(tol1,xm-x);
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+
+ if (fabs(d) >= tol1) {
+ u = x+d;
+ fu = potenial.Evaluate(u);
+ } else {
+ u = x + TNT::sign(tol1,d);
+ fu = potenial.Evaluate(u);
+ if (fu > fx) {
+ x_min = x;
+ return fx;
+ }
+ }
+ du = potenial.Derivative(u);
+ if (fu <= fx) {
+ if (u >= x) {
+ a = x;
+ } else {
+ b = x;
+ }
+ v = w; fv = fw; dv = dw;
+ w = x; fw = fx; dw = dx;
+ x = u; fx = fu; dx = du;
+ } else {
+ if (u < x) {
+ a = u;
+ } else {
+ b = u;
+ }
+ if (fu <= fw || w == x) {
+ v = w; fv = fw; dv = dw;
+ w = u; fw = fu; dw = du;
+ } else if ( fu < fv || v == x || v == w) {
+ v = u; fv = fu; dv = du;
+ }
+ }
+ }
+ // FIXME throw exception
+
+ assert(false);
+ return MT_Scalar(0);
+ };
+
+private :
+
+ /// This class just contains static helper methods so no instantiation
+
+ IK_LineMinimizer();
+
+};
+
+#undef GOLD
+#undef GLIMIT
+#undef TINY
+#undef ZEPS
+
+
+
+#endif
diff --git a/intern/iksolver/intern/IK_QChain.cpp b/intern/iksolver/intern/IK_QChain.cpp
new file mode 100644
index 00000000000..438729003a9
--- /dev/null
+++ b/intern/iksolver/intern/IK_QChain.cpp
@@ -0,0 +1,280 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "IK_QChain.h"
+
+using namespace std;
+
+IK_QChain::
+IK_QChain(
+)
+{
+ // nothing to do;
+};
+
+const
+ vector<IK_QSegment> &
+IK_QChain::
+Segments(
+) const {
+ return m_segments;
+};
+
+ vector<IK_QSegment> &
+IK_QChain::
+Segments(
+){
+ return m_segments;
+};
+
+ void
+IK_QChain::
+UpdateGlobalTransformations(
+){
+
+ // now iterate through the segment list
+ // compute their local transformations if needed
+
+ // assign their global transformations
+ // (relative to chain origin)
+
+ vector<IK_QSegment>::const_iterator s_end = m_segments.end();
+ vector<IK_QSegment>::iterator s_it = m_segments.begin();
+
+ MT_Transform global;
+ global.setIdentity();
+
+ for (; s_it != s_end; ++s_it) {
+ global = s_it->UpdateGlobal(global);
+ }
+
+ // we also need to compute the accumulated local transforms
+ // for each segment
+
+ MT_Transform acc_local;
+ acc_local.setIdentity();
+
+ vector<IK_QSegment>::reverse_iterator s_rit = m_segments.rbegin();
+ vector<IK_QSegment>::reverse_iterator s_rend = m_segments.rend();
+
+ for (; s_rit != s_rend; ++s_rit) {
+ acc_local = s_rit->UpdateAccumulatedLocal(acc_local);
+ }
+
+ // compute the position of the end effector and it's pose
+
+ const MT_Transform &last_t = m_segments.back().GlobalTransform();
+ m_end_effector = last_t.getOrigin();
+
+#if 0
+
+ // The end pose is not currently used.
+
+ MT_Matrix3x3 last_basis = last_t.getBasis();
+ last_basis.transpose();
+ MT_Vector3 m_end_pose = last_basis[1];
+
+#endif
+
+};
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_QChain::
+Jacobian(
+) const {
+ return m_jacobian;
+} ;
+
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_QChain::
+TransposedJacobian(
+) const {
+ return m_t_jacobian;
+};
+
+ void
+IK_QChain::
+ComputeJacobian(
+){
+ // let's assume that the chain's global transfomations
+ // have already been computed.
+
+ int dof = DoF();
+
+ int num_segs = m_segments.size();
+ vector<IK_QSegment>::const_iterator segs = m_segments.begin();
+
+ m_t_jacobian.newsize(dof,3);
+ m_jacobian.newsize(3,dof);
+
+ // compute the transposed jacobian first
+
+ int n;
+ int i = 0;
+
+ for (n= 0; n < num_segs; n++) {
+#if 0
+
+ // For euler angle computation we can use a slightly quicker method.
+
+ const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis();
+ const MT_Vector3 &origin = segs[n].GlobalSegmentStart();
+
+ const MT_Vector3 p = origin-m_end_effector;
+
+ const MT_Vector3 x_axis(1,0,0);
+ const MT_Vector3 y_axis(0,1,0);
+ const MT_Vector3 z_axis(0,0,1);
+
+ MT_Vector3 a = basis * x_axis;
+ MT_Vector3 pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 1,1) = pca.x();
+ m_t_jacobian(n*3 + 1,2) = pca.y();
+ m_t_jacobian(n*3 + 1,3) = pca.z();
+
+ a = basis * y_axis;
+ pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 2,1) = pca.x();
+ m_t_jacobian(n*3 + 2,2) = pca.y();
+ m_t_jacobian(n*3 + 2,3) = pca.z();
+
+ a = basis * z_axis;
+ pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 3,1) = pca.x();
+ m_t_jacobian(n*3 + 3,2) = pca.y();
+ m_t_jacobian(n*3 + 3,3) = pca.z();
+#else
+ // user slower general jacobian computation method
+
+ MT_Vector3 j1 = segs[n].ComputeJacobianColumn(0);
+
+ m_t_jacobian(n*3 + 1,1) = j1.x();
+ m_t_jacobian(n*3 + 1,2) = j1.y();
+ m_t_jacobian(n*3 + 1,3) = j1.z();
+
+ j1 = segs[n].ComputeJacobianColumn(1);
+
+ m_t_jacobian(n*3 + 2,1) = j1.x();
+ m_t_jacobian(n*3 + 2,2) = j1.y();
+ m_t_jacobian(n*3 + 2,3) = j1.z();
+
+ j1 = segs[n].ComputeJacobianColumn(2);
+
+ m_t_jacobian(n*3 + 3,1) = j1.x();
+ m_t_jacobian(n*3 + 3,2) = j1.y();
+ m_t_jacobian(n*3 + 3,3) = j1.z();
+#endif
+
+
+
+ }
+
+
+ // get the origina1 jacobain
+
+ TNT::transpose(m_t_jacobian,m_jacobian);
+};
+
+ MT_Vector3
+IK_QChain::
+EndEffector(
+) const {
+ return m_end_effector;
+};
+
+ MT_Vector3
+IK_QChain::
+EndPose(
+) const {
+ return m_end_pose;
+};
+
+
+ int
+IK_QChain::
+DoF(
+) const {
+ return 3 * m_segments.size();
+}
+
+const
+ MT_Scalar
+IK_QChain::
+MaxExtension(
+) const {
+
+ vector<IK_QSegment>::const_iterator s_end = m_segments.end();
+ vector<IK_QSegment>::const_iterator s_it = m_segments.begin();
+
+ if (m_segments.size() == 0) return MT_Scalar(0);
+
+ MT_Scalar output = s_it->Length();
+
+ ++s_it ;
+ for (; s_it != s_end; ++s_it) {
+ output += s_it->MaxExtension();
+ }
+ return output;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_QChain.h b/intern/iksolver/intern/IK_QChain.h
new file mode 100644
index 00000000000..ed02bcce53e
--- /dev/null
+++ b/intern/iksolver/intern/IK_QChain.h
@@ -0,0 +1,211 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef NAN_INCLUDED_IK_QChain_h
+#define NAN_INCLUDED_IK_QChain_h
+
+
+#include "IK_QSegment.h"
+#include <vector>
+#include "MT_Scalar.h"
+#include "TNT/cmat.h"
+
+/**
+ * This class is a collection of ordered segments that are used
+ * in an Inverse Kinematic solving routine. An IK solver operating
+ * on the chain, will in general manipulate all the segments of the
+ * chain in order to solve the IK problem.
+ *
+ * To build a chain use the default constructor. Once built it's
+ * then possible to add IK_Segments to the chain by inserting
+ * them into the vector of IK_Segments. Note that segments will be
+ * copied into the chain so chains cannot share instances of
+ * IK_Segments.
+ *
+ * You have full control of which segments form the chain via the
+ * the std::vector routines.
+ */
+
+class IK_QChain{
+
+public :
+
+ /**
+ * Construct a IK_QChain with no segments.
+ */
+
+ IK_QChain(
+ );
+
+ // IK_QChains also have the default copy constructors
+ // available.
+
+ /**
+ * Const access to the array of segments
+ * comprising the IK_QChain. Used for rendering
+ * etc
+ * @return a const reference to a vector of segments
+ */
+
+ const
+ std::vector<IK_QSegment> &
+ Segments(
+ ) const ;
+
+
+ /**
+ * Full access to segments used to initialize
+ * the IK_QChain and manipulate the segments.
+ * Use the push_back() method of std::vector to add
+ * segments in order to the chain
+ * @return a reference to a vector of segments
+ */
+
+ std::vector<IK_QSegment> &
+ Segments(
+ );
+
+
+ /**
+ * Force the IK_QChain to recompute all the local
+ * segment transformations and composite them
+ * to calculate the global transformation for
+ * each segment. Must be called before
+ * ComputeJacobian()
+ */
+
+ void
+ UpdateGlobalTransformations(
+ );
+
+ /**
+ * Return the global position of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndEffector(
+ ) const;
+
+
+ /**
+ * Return the global pose of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndPose(
+ ) const;
+
+
+ /**
+ * Calculate the jacobian matrix for
+ * the current end effector position.
+ * A jacobian is the set of column vectors
+ * of partial derivatives for each active angle.
+ * This method also computes the transposed jacobian.
+ * @pre You must have updated the global transformations
+ * of the chain's segments before a call to this method. Do this
+ * with UpdateGlobalTransformation()
+ */
+
+ void
+ ComputeJacobian(
+ );
+
+
+ /**
+ * @return A const reference to the last computed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ Jacobian(
+ ) const ;
+
+ /**
+ * @return A const reference to the last computed transposed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ TransposedJacobian(
+ ) const ;
+
+ /**
+ * Count the degrees of freedom in the IK_QChain
+ * @warning store this value rather than using this function
+ * as the termination value of a for loop etc.
+ */
+
+ int
+ DoF(
+ ) const;
+
+ /**
+ * Compute the maximum extension of the chain from the
+ * root segment. This is the length of the root segments
+ * + the max extensions of all the other segments
+ */
+
+ const
+ MT_Scalar
+ MaxExtension(
+ ) const;
+
+
+private :
+
+ /// The vector of segments comprising the chain
+ std::vector<IK_QSegment> m_segments;
+
+ /// The jacobain of the IK_QChain
+ TNT::Matrix<MT_Scalar> m_jacobian;
+
+ /// It's transpose
+ TNT::Matrix<MT_Scalar> m_t_jacobian;
+
+ MT_Vector3 m_end_effector;
+ MT_Vector3 m_end_pose;
+
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp
new file mode 100644
index 00000000000..32a703cb94d
--- /dev/null
+++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp
@@ -0,0 +1,327 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_QJacobianSolver.h"
+
+#include "TNT/svd.h"
+
+using namespace std;
+
+ IK_QJacobianSolver *
+IK_QJacobianSolver::
+New(
+){
+ return new IK_QJacobianSolver();
+}
+
+ bool
+IK_QJacobianSolver::
+Solve(
+ IK_QChain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+){
+
+ const vector<IK_QSegment> & segs = chain.Segments();
+ if (segs.size() == 0) return false;
+
+ // compute the goal direction from the base of the chain
+ // in global coordinates
+
+ MT_Vector3 goal_dir = g_position - segs[0].GlobalSegmentStart();
+
+
+ const MT_Scalar chain_max_extension = chain.MaxExtension();
+
+ bool do_parallel_check(false);
+
+ if (chain_max_extension < goal_dir.length()) {
+ do_parallel_check = true;
+ }
+
+ goal_dir.normalize();
+
+
+ ArmMatrices(chain.DoF());
+
+ for (int iterations = 0; iterations < max_iterations; iterations++) {
+
+ // check to see if the chain is pointing in the right direction
+
+ if (iterations%32 && do_parallel_check && ParallelCheck(chain,goal_dir)) {
+
+ return false;
+ }
+
+ MT_Vector3 end_effector = chain.EndEffector();
+ MT_Vector3 d_pos = g_position - end_effector;
+ const MT_Scalar x_length = d_pos.length();
+
+ if (x_length < tolerance) {
+ return true;
+ }
+
+ chain.ComputeJacobian();
+
+ try {
+ ComputeInverseJacobian(chain,x_length,max_angle_change);
+ }
+ catch(...) {
+ return false;
+ }
+
+ ComputeBetas(chain,d_pos);
+ UpdateChain(chain);
+ chain.UpdateGlobalTransformations();
+ }
+
+
+ return false;
+};
+
+IK_QJacobianSolver::
+~IK_QJacobianSolver(
+){
+ // nothing to do
+}
+
+
+IK_QJacobianSolver::
+IK_QJacobianSolver(
+){
+ // nothing to do
+};
+
+ void
+IK_QJacobianSolver::
+ComputeBetas(
+ IK_QChain &chain,
+ const MT_Vector3 d_pos
+){
+
+ m_beta = 0;
+
+ m_beta[0] = d_pos.x();
+ m_beta[1] = d_pos.y();
+ m_beta[2] = d_pos.z();
+
+ TNT::matmult(m_d_theta,m_svd_inverse,m_beta);
+
+};
+
+
+ int
+IK_QJacobianSolver::
+ComputeInverseJacobian(
+ IK_QChain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+) {
+
+ int dimension = 0;
+
+ m_svd_u = MT_Scalar(0);
+
+ // copy first 3 rows of jacobian into m_svd_u
+
+ int row, column;
+
+ for (row = 0; row < 3; row ++) {
+ for (column = 0; column < chain.Jacobian().num_cols(); column ++) {
+ m_svd_u[row][column] = chain.Jacobian()[row][column];
+ }
+ }
+
+ m_svd_w = MT_Scalar(0);
+ m_svd_v = MT_Scalar(0);
+
+ m_svd_work_space = MT_Scalar(0);
+
+ TNT::SVD(m_svd_u,m_svd_w,m_svd_v,m_svd_work_space);
+
+ // invert the SVD and compute inverse
+
+ TNT::transpose(m_svd_v,m_svd_v_t);
+ TNT::transpose(m_svd_u,m_svd_u_t);
+
+ // Compute damped least squares inverse of pseudo inverse
+ // Compute damping term lambda
+
+ // Note when lambda is zero this is equivalent to the
+ // least squares solution. This is fine when the m_jjt is
+ // of full rank. When m_jjt is near to singular the least squares
+ // inverse tries to minimize |J(dtheta) - dX)| and doesn't
+ // try to minimize dTheta. This results in eratic changes in angle.
+ // Damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
+
+ // We don't want to use the damped solution everywhere so we
+ // only increase lamda from zero as we approach a singularity.
+
+ // find the smallest non-zero m_svd_w value
+
+ int i = 0;
+
+ MT_Scalar w_min = MT_INFINITY;
+
+ // anything below epsilon is treated as zero
+
+ MT_Scalar epsilon = MT_Scalar(1e-10);
+
+ for ( i = 0; i <m_svd_w.size() ; i++) {
+
+ if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
+ w_min = m_svd_w[i];
+ }
+ }
+
+ MT_Scalar lambda(0);
+
+ MT_Scalar d = x_length/max_angle_change;
+
+ if (w_min <= d/2) {
+ lambda = d/2;
+ } else
+ if (w_min < d) {
+ lambda = sqrt(w_min*(d - w_min));
+ } else {
+ lambda = MT_Scalar(0);
+ }
+
+
+ lambda *= lambda;
+
+ for (i= 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] < epsilon) {
+ m_svd_w[i] = MT_Scalar(0);
+ } else {
+ m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ }
+ }
+
+
+ TNT::matmultdiag(m_svd_temp1,m_svd_w,m_svd_u_t);
+ TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1);
+
+ return dimension;
+
+}
+
+ void
+IK_QJacobianSolver::
+UpdateChain(
+ IK_QChain &chain
+){
+
+ // iterate through the set of angles and
+ // update their values from the d_thetas
+
+ vector<IK_QSegment> &segs = chain.Segments();
+
+ int seg_ind = 0;
+ for (seg_ind = 0;seg_ind < segs.size(); seg_ind++) {
+
+ MT_Vector3 dq;
+ dq[0] = m_d_theta[3*seg_ind];
+ dq[1] = m_d_theta[3*seg_ind + 1];
+ dq[2] = m_d_theta[3*seg_ind + 2];
+ segs[seg_ind].IncrementAngle(dq);
+ }
+
+};
+
+ void
+IK_QJacobianSolver::
+ArmMatrices(
+ int dof
+){
+
+ m_beta.newsize(dof);
+ m_d_theta.newsize(dof);
+
+ m_svd_u.newsize(dof,dof);
+ m_svd_v.newsize(dof,dof);
+ m_svd_w.newsize(dof);
+
+ m_svd_work_space.newsize(dof);
+
+ m_svd_u = MT_Scalar(0);
+ m_svd_v = MT_Scalar(0);
+ m_svd_w = MT_Scalar(0);
+
+ m_svd_u_t.newsize(dof,dof);
+ m_svd_v_t.newsize(dof,dof);
+ m_svd_w_diag.newsize(dof,dof);
+ m_svd_inverse.newsize(dof,dof);
+ m_svd_temp1.newsize(dof,dof);
+
+};
+
+ bool
+IK_QJacobianSolver::
+ParallelCheck(
+ const IK_QChain &chain,
+ const MT_Vector3 goal_dir
+) const {
+
+ // compute the start of the chain in global coordinates
+ const vector<IK_QSegment> &segs = chain.Segments();
+
+ int num_segs = segs.size();
+
+ if (num_segs == 0) {
+ return false;
+ }
+
+ MT_Scalar crossp_sum = 0;
+
+ int i;
+ for (i = 0; i < num_segs; i++) {
+ MT_Vector3 global_seg_direction = segs[i].GlobalSegmentEnd() -
+ segs[i].GlobalSegmentStart();
+
+ global_seg_direction.normalize();
+
+ MT_Scalar crossp = (global_seg_direction.cross(goal_dir)).length();
+ crossp_sum += MT_Scalar(fabs(crossp));
+ }
+
+ if (crossp_sum < MT_Scalar(0.01)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h
new file mode 100644
index 00000000000..7e2f886d0c4
--- /dev/null
+++ b/intern/iksolver/intern/IK_QJacobianSolver.h
@@ -0,0 +1,184 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_QJacobianSolver_h
+
+#define NAN_INCLUDED_IK_QJacobianSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include <vector>
+#include "MT_Vector3.h"
+#include "IK_QChain.h"
+
+class IK_QJacobianSolver {
+
+public :
+
+ /**
+ * Create a new IK_QJacobianSolver on the heap
+ * @return A newly created IK_QJacobianSolver you take ownership of the object
+ * and responsibility for deleting it
+ */
+
+
+ static
+ IK_QJacobianSolver *
+ New(
+ );
+
+ /**
+ * Compute a solution for a chain.
+ * @param chain Reference to the chain to modify
+ * @param g_position Reference to the goal position.
+ * @param g_pose -not used- Reference to the goal pose.
+ * @param tolerance The maximum allowed distance between solution
+ * and goal for termination.
+ * @param max_iterations should be in the range (50 - 500)
+ * @param max_angle_change The maximum change in the angle vector
+ * of the chain (0.1 is a good value)
+ *
+ * @return True iff goal position reached.
+ */
+
+ bool
+ Solve(
+ IK_QChain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+ );
+
+ ~IK_QJacobianSolver(
+ );
+
+
+private :
+
+ /**
+ * Private constructor to force use of New()
+ */
+
+ IK_QJacobianSolver(
+ );
+
+
+ /**
+ * Compute the inverse jacobian matrix of the chain.
+ * Uses a damped least squares solution when the matrix is
+ * is approaching singularity
+ */
+
+ int
+ ComputeInverseJacobian(
+ IK_QChain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+ );
+
+ void
+ ComputeBetas(
+ IK_QChain &chain,
+ const MT_Vector3 d_pos
+ );
+
+ /**
+ * Updates the angles of the chain with the newly
+ * computed values
+ */
+
+ void
+ UpdateChain(
+ IK_QChain &chain
+ );
+
+ /**
+ * Make sure all the matrices are of the correct size
+ */
+
+ void
+ ArmMatrices(
+ int dof
+ );
+
+ /**
+ * Quick check to see if all the segments are parallel
+ * to the goal direction.
+ */
+
+ bool
+ ParallelCheck(
+ const IK_QChain &chain,
+ const MT_Vector3 goal
+ ) const;
+
+
+
+private :
+
+ /// the vector of intermediate betas
+ TNT::Vector<MT_Scalar> m_beta;
+
+ /// the vector of computed angle changes
+ TNT::Vector<MT_Scalar> m_d_theta;
+
+ /// the constraint gradients for each angle.
+ TNT::Vector<MT_Scalar> m_dh;
+
+ /// Space required for SVD computation
+
+ TNT::Vector<MT_Scalar> m_svd_w;
+ TNT::Vector<MT_Scalar> m_svd_work_space;
+ TNT::Matrix<MT_Scalar> m_svd_v;
+ TNT::Matrix<MT_Scalar> m_svd_u;
+
+ TNT::Matrix<MT_Scalar> m_svd_w_diag;
+ TNT::Matrix<MT_Scalar> m_svd_v_t;
+ TNT::Matrix<MT_Scalar> m_svd_u_t;
+ TNT::Matrix<MT_Scalar> m_svd_inverse;
+ TNT::Matrix<MT_Scalar> m_svd_temp1;
+
+
+};
+
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/IK_QSegment.cpp b/intern/iksolver/intern/IK_QSegment.cpp
new file mode 100644
index 00000000000..2956dd815e2
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSegment.cpp
@@ -0,0 +1,363 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "IK_QSegment.h"
+#include <iostream.h>
+
+IK_QSegment::
+IK_QSegment (
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const MT_ExpMap q
+) :
+ m_length (length),
+ m_q (q)
+{
+
+ m_max_extension = tr1.length() + length;
+
+ m_transform.setOrigin(tr1);
+ m_transform.setBasis(A);
+
+ UpdateLocalTransform();
+};
+
+
+IK_QSegment::
+IK_QSegment (
+) :
+ m_length(0),
+ m_q (0,0,0),
+ m_max_extension(0)
+{
+ // Intentionally empty
+}
+
+
+
+// accessors
+////////////
+
+// The length of the segment
+
+const
+ MT_Scalar
+IK_QSegment::
+Length(
+) const {
+ return m_length;
+}
+
+const
+ MT_Scalar
+IK_QSegment::
+MaxExtension(
+) const {
+ return m_max_extension;
+}
+
+// This is the transform from adjacent
+// coordinate systems in the chain.
+
+const
+ MT_Transform &
+IK_QSegment::
+LocalTransform(
+) const {
+ return m_local_transform;
+}
+
+const
+ MT_ExpMap &
+IK_QSegment::
+LocalJointParameter(
+) const {
+ return m_q;
+}
+
+ MT_Transform
+IK_QSegment::
+UpdateGlobal(
+ const MT_Transform & global
+){
+ // compute the global transform
+ // and the start of the segment in global coordinates.
+
+ m_seg_start = global * m_transform.getOrigin();
+ m_global_transform = global;
+
+ const MT_Transform new_global = GlobalTransform();
+
+ m_seg_end = new_global.getOrigin();
+
+ return new_global;
+}
+
+ MT_Transform
+IK_QSegment::
+GlobalTransform(
+) const {
+ return m_global_transform * m_local_transform;
+}
+
+
+ MT_Transform
+IK_QSegment::
+UpdateAccumulatedLocal(
+ const MT_Transform & acc_local
+){
+ m_accum_local = acc_local;
+ return m_local_transform * m_accum_local;
+}
+
+const
+ MT_Transform &
+IK_QSegment::
+AccumulatedLocal(
+) const {
+ return m_accum_local;
+}
+
+ MT_Vector3
+IK_QSegment::
+ComputeJacobianColumn(
+ int angle
+) const {
+
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+
+ // we can compute the jacobian for one of the
+ // angles of this joint by first computing
+ // the partial derivative of the local transform dR/da
+ // and then computing
+ // dG/da = m_global_transform * dR/da * m_accum_local (0,0,0)
+
+#if 0
+
+ // use euler angles as a test of the matrices and this method.
+
+ MT_Matrix3x3 dRda;
+
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_q[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_q[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_q[2]);
+
+ MT_Matrix3x3 rotx_m(rotx);
+ MT_Matrix3x3 roty_m(roty);
+ MT_Matrix3x3 rotz_m(rotz);
+
+ if (angle == 0) {
+
+ MT_Scalar ci = cos(m_q[0]);
+ MT_Scalar si = sin(m_q[1]);
+
+ dRda = MT_Matrix3x3(
+ 0, 0, 0,
+ 0,-si,-ci,
+ 0, ci,-si
+ );
+
+ dRda = rotz_m * roty_m * dRda;
+ } else
+
+ if (angle == 1) {
+
+ MT_Scalar cj = cos(m_q[1]);
+ MT_Scalar sj = sin(m_q[1]);
+
+ dRda = MT_Matrix3x3(
+ -sj, 0, cj,
+ 0, 0, 0,
+ -cj, 0,-sj
+ );
+
+ dRda = rotz_m * dRda * rotx_m;
+ } else
+
+ if (angle == 2) {
+
+ MT_Scalar ck = cos(m_q[2]);
+ MT_Scalar sk = sin(m_q[2]);
+
+ dRda = MT_Matrix3x3(
+ -sk,-ck, 0,
+ ck,-sk, 0,
+ 0, 0, 0
+ );
+
+ dRda = dRda * roty_m * rotx_m;
+ }
+
+ MT_Transform dRda_t(MT_Point3(0,0,0),dRda);
+
+ // convert to 4x4 matrices coz dRda is singular.
+ MT_Matrix4x4 dRda_m(dRda_t);
+ dRda_m[3][3] = 0;
+
+#else
+
+ // use exponential map derivatives
+ MT_Matrix4x4 dRda_m = m_q.partialDerivatives(angle);
+
+#endif
+
+
+ // Once we have computed the local derivatives we can compute
+ // derivatives of the end effector.
+
+ // Imagine a chain consisting of 5 segments each with local
+ // transformation Li
+ // Then the global transformation G is L1 *L2 *L3 *L4 *L5
+ // If we want to compute the partial derivatives of this expression
+ // w.r.t one of the angles x of L3 we should then compute
+ // dG/dx = d(L1 *L2 *L3 *L4 *L5)/dx
+ // = L1 *L2 * dL3/dx *L4 *L5
+ // but L1 *L2 is the global transformation of the parent of this
+ // bone and L4 *L5 is the accumulated local transform of the children
+ // of this bone (m_accum_local)
+ // so dG/dx = m_global_transform * dL3/dx * m_accum_local
+ //
+ // so now we need to compute dL3/dx
+ // L3 = m_transform * rotation(m_q) * translate(0,m_length,0)
+ // do using the same procedure we get
+ // dL3/dx = m_transform * dR/dx * translate(0,m_length,0)
+ // dR/dx is the partial derivative of the exponential map w.r.t
+ // one of it's parameters. This is computed in MT_ExpMap
+
+ MT_Matrix4x4 translation_m (translation);
+ MT_Matrix4x4 global_m(m_global_transform);
+ MT_Matrix4x4 accum_local_m(m_accum_local);
+ MT_Matrix4x4 transform_m(m_transform);
+
+
+ MT_Matrix4x4 dFda_m = global_m * transform_m * dRda_m * translation_m * accum_local_m;
+
+ MT_Vector4 result = dFda_m * MT_Vector4(0,0,0,1);
+ return MT_Vector3(result[0],result[1],result[2]);
+};
+
+
+
+const
+ MT_Vector3 &
+IK_QSegment::
+GlobalSegmentStart(
+) const{
+ return m_seg_start;
+}
+
+const
+ MT_Vector3 &
+IK_QSegment::
+GlobalSegmentEnd(
+) const {
+ return m_seg_end;
+}
+
+
+ void
+IK_QSegment::
+IncrementAngle(
+ const MT_Vector3 &dq
+){
+ m_q.vector() += dq;
+ MT_Scalar theta(0);
+ m_q.reParameterize(theta);
+
+ UpdateLocalTransform();
+}
+
+
+ void
+IK_QSegment::
+SetAngle(
+ const MT_ExpMap &dq
+){
+ m_q = dq;
+ UpdateLocalTransform();
+}
+
+
+ void
+IK_QSegment::
+UpdateLocalTransform(
+){
+#if 0
+
+ //use euler angles - test
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_q[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_q[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_q[2]);
+
+ MT_Matrix3x3 rotx_m(rotx);
+ MT_Matrix3x3 roty_m(roty);
+ MT_Matrix3x3 rotz_m(rotz);
+
+ MT_Matrix3x3 rot = rotz_m * roty_m * rotx_m;
+#else
+
+ //use exponential map
+ MT_Matrix3x3 rot = m_q.getMatrix();
+
+
+#endif
+
+ MT_Transform rx(MT_Point3(0,0,0),rot);
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+ m_local_transform = m_transform * rx * translation;
+};
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h
new file mode 100644
index 00000000000..0c0e3a7f8bc
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSegment.h
@@ -0,0 +1,290 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+#ifndef NAN_INCLUDED_IK_QSegment_h
+#define NAN_INCLUDED_IK_QSegment_h
+
+
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+#include "MT_Matrix4x4.h"
+#include "MT_ExpMap.h"
+
+#include <vector>
+
+/**
+ * An IK_Qsegment encodes information about a segments
+ * local coordinate system.
+ * In these segments exponential maps are used to parameterize
+ * the 3 DOF joints. Please see the file MT_ExpMap.h for more
+ * information on this parameterization.
+ *
+ * These segments always point along the y-axis.
+ *
+ * Here wee define the local coordinates of a joint as
+ * local_transform =
+ * translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0)
+ * We use the standard moto column ordered matrices. You can read
+ * this as:
+ * - first translate by (0,length,0)
+ * - multiply by the rotation matrix derived from the current
+ * angle parameterization q.
+ * - multiply by the user defined matrix representing the rest
+ * position of the bone.
+ * - translate by the used defined translation (tr1)
+ * The ordering of these transformations is vital, you must
+ * use exactly the same transformations when displaying the segments
+ */
+
+class IK_QSegment {
+
+public :
+
+ /**
+ * Constructor.
+ * @param tr1 a user defined translation
+ * @param a used defined rotation matrix representin
+ * the rest position of the bone.
+ * @param the length of the bone.
+ * @param an exponential map can also be used to
+ * define the bone rest position.
+ */
+
+ IK_QSegment(
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const MT_ExpMap q
+ );
+
+ /**
+ * Default constructor
+ * Defines identity local coordinate system,
+ * with a bone length of 1.
+ */
+
+
+ IK_QSegment(
+ );
+
+
+ /**
+ * @return The length of the segment
+ */
+
+ const
+ MT_Scalar
+ Length(
+ ) const ;
+
+ /**
+ * @return the max distance of the end of this
+ * bone from the local origin.
+ */
+
+ const
+ MT_Scalar
+ MaxExtension(
+ ) const ;
+
+ /**
+ * @return The transform from adjacent
+ * coordinate systems in the chain.
+ */
+
+ const
+ MT_Transform &
+ LocalTransform(
+ ) const ;
+
+ const
+ MT_ExpMap &
+ LocalJointParameter(
+ ) const;
+
+ /**
+ * Update the global coordinates of this segment.
+ * @param global the global coordinates of the
+ * previous bone in the chain
+ * @return the global coordinates of this segment.
+ */
+
+ MT_Transform
+ UpdateGlobal(
+ const MT_Transform & global
+ );
+
+ /**
+ * @return The global transformation
+ */
+
+ MT_Transform
+ GlobalTransform(
+ ) const;
+
+
+ /**
+ * Update the accumulated local transform of this segment
+ * The accumulated local transform is the end effector
+ * transform in the local coordinates of this segment.
+ * @param acc_local the accumulated local transform of
+ * the child of this bone.
+ * @return the accumulated local transorm of this segment
+ */
+
+ MT_Transform
+ UpdateAccumulatedLocal(
+ const MT_Transform & acc_local
+ );
+
+ /**
+ * @return A const reference to accumulated local
+ * transform of this segment.
+ */
+
+ const
+ MT_Transform &
+ AccumulatedLocal(
+ ) const;
+
+ /**
+ * @return A const Reference to start of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentStart(
+ ) const;
+
+ /**
+ * @return A const Reference to end of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentEnd(
+ ) const;
+
+
+ /**
+ * @return the partial derivative of the end effector
+ * with respect to one of the degrees of freedom of this
+ * segment.
+ * @param angle the angle parameter you want to compute
+ * the partial derivatives for. For these segments this
+ * must be in the range [0,2]
+ */
+
+ MT_Vector3
+ ComputeJacobianColumn(
+ int angle
+ ) const ;
+
+ /**
+ * Explicitly set the angle parameterization value.
+ */
+
+ void
+ SetAngle(
+ const MT_ExpMap &q
+ );
+
+ /**
+ * Increment the angle parameterization value.
+ */
+
+ void
+ IncrementAngle(
+ const MT_Vector3 &dq
+ );
+
+
+ /**
+ * Return the parameterization of this angle
+ */
+
+ const
+ MT_ExpMap &
+ ExpMap(
+ ) const {
+ return m_q;
+ };
+
+
+private :
+
+ void
+ UpdateLocalTransform(
+ );
+
+
+private :
+
+ /**
+ * m_transform The user defined transformation, composition of the
+ * translation and rotation from constructor.
+ */
+ MT_Transform m_transform;
+
+ /**
+ * The exponential map parameterization of this joint.
+ */
+
+ MT_ExpMap m_q;
+ MT_Scalar m_length;
+
+ /**
+ * The maximum extension of this segment
+ * This is the magnitude of the user offset + the length of the
+ * chain
+ */
+
+ MT_Scalar m_max_extension;
+
+ MT_Transform m_local_transform;
+ MT_Transform m_global_transform;
+ MT_Transform m_accum_local;
+
+ MT_Vector3 m_seg_start;
+ MT_Vector3 m_seg_end;
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_QSolver_Class.h b/intern/iksolver/intern/IK_QSolver_Class.h
new file mode 100644
index 00000000000..91ad9f9c186
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSolver_Class.h
@@ -0,0 +1,107 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef NAN_INCLUDED_IK_Solver_Class
+#define NAN_INCLUDED_IK_Solver_Class
+
+#include "IK_QChain.h"
+#include "IK_QJacobianSolver.h"
+#include "IK_QSegment.h"
+#include "MEM_SmartPtr.h"
+
+/**
+ * This class just contains all instances of internal data
+ * associated with the external chain structure needed for
+ * an ik solve. A pointer to this class gets hidden in the
+ * external structure as a void pointer.
+ */
+
+class IK_QSolver_Class {
+
+public :
+
+ static
+ IK_QSolver_Class *
+ New(
+ ){
+ MEM_SmartPtr<IK_QSolver_Class> output (new IK_QSolver_Class);
+
+ MEM_SmartPtr<IK_QJacobianSolver> solver (IK_QJacobianSolver::New());
+
+ if (output == NULL ||
+ solver == NULL
+ ) {
+ return NULL;
+ }
+
+ output->m_solver = solver.Release();
+
+ return output.Release();
+ };
+
+ IK_QChain &
+ Chain(
+ ) {
+ return m_chain;
+ };
+
+ IK_QJacobianSolver &
+ Solver(
+ ) {
+ return m_solver.Ref();
+ }
+
+ ~IK_QSolver_Class(
+ ) {
+ // nothing to do
+ }
+
+
+private :
+
+ IK_QSolver_Class(
+ ) {
+ };
+
+ IK_QChain m_chain;
+ MEM_SmartPtr<IK_QJacobianSolver> m_solver;
+
+};
+
+#endif
diff --git a/intern/iksolver/intern/IK_Segment.cpp b/intern/iksolver/intern/IK_Segment.cpp
new file mode 100644
index 00000000000..f955a657dae
--- /dev/null
+++ b/intern/iksolver/intern/IK_Segment.cpp
@@ -0,0 +1,277 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "IK_Segment.h"
+
+
+IK_Segment::
+IK_Segment (
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const bool pitch_on,
+ const bool yaw_on,
+ const bool role_on
+){
+ m_transform.setOrigin(tr1);
+ m_transform.setBasis(A);
+ m_angles[0] =MT_Scalar(0);
+ m_angles[1] =MT_Scalar(0);
+ m_angles[2] =MT_Scalar(0);
+
+ m_active_angles[0] = role_on;
+ m_active_angles[1] = yaw_on;
+ m_active_angles[2] = pitch_on;
+ m_length = length;
+
+ if (role_on) {
+ m_angle_vectors.push_back(MT_Vector3(1,0,0));
+ }
+ if (yaw_on) {
+ m_angle_vectors.push_back(MT_Vector3(0,1,0));
+ }
+ if (pitch_on) {
+ m_angle_vectors.push_back(MT_Vector3(0,0,1));
+ }
+ UpdateLocalTransform();
+
+
+};
+
+
+IK_Segment::
+IK_Segment (
+) {
+ m_transform.setIdentity();
+
+ m_angles[0] =MT_Scalar(0);
+ m_angles[1] =MT_Scalar(0);
+ m_angles[2] =MT_Scalar(0);
+
+ m_active_angles[0] = false;
+ m_active_angles[1] = false;
+ m_active_angles[2] = false;
+ m_length = MT_Scalar(1);
+
+ UpdateLocalTransform();
+}
+
+
+
+// accessors
+////////////
+
+// The length of the segment
+
+const
+ MT_Scalar
+IK_Segment::
+Length(
+) const {
+ return m_length;
+}
+
+
+// This is the transform from adjacent
+// coordinate systems in the chain.
+
+const
+ MT_Transform &
+IK_Segment::
+LocalTransform(
+) const {
+ return m_local_transform;
+}
+
+ void
+IK_Segment::
+UpdateGlobal(
+ const MT_Transform & global
+){
+
+ // compute the global transform
+ // and the start of the segment in global coordinates.
+
+ m_seg_start = global * m_transform.getOrigin();
+ m_global_transform = global * m_local_transform;
+}
+
+const
+ MT_Transform &
+IK_Segment::
+GlobalTransform(
+) const {
+ return m_global_transform;
+}
+
+const
+ MT_Vector3 &
+IK_Segment::
+GlobalSegmentStart(
+) const{
+ return m_seg_start;
+}
+
+
+// Return the number of Degrees of Freedom
+// for this segment
+
+ int
+IK_Segment::
+DoF(
+) const {
+ return
+ (m_active_angles[0] == true) +
+ (m_active_angles[1] == true) +
+ (m_active_angles[2] == true);
+}
+
+
+// suspect interface...
+// Increment the active angles (at most 3) by
+// d_theta. Which angles are incremented depends
+// on which are active. It returns DoF
+
+ int
+IK_Segment::
+IncrementAngles(
+ MT_Scalar *d_theta
+){
+ int i =0;
+ if (m_active_angles[0]) {
+ m_angles[0] += d_theta[i];
+ i++;
+ }
+ if (m_active_angles[1]) {
+ m_angles[1] += d_theta[i];
+ i++;
+ }
+ if (m_active_angles[2]) {
+ m_angles[2] += d_theta[i];
+ i++;
+ }
+ UpdateLocalTransform();
+
+ return i;
+}
+
+
+ int
+IK_Segment::
+SetAngles(
+ const MT_Scalar *angles
+){
+ int i =0;
+ if (m_active_angles[0]) {
+ m_angles[0] = angles[i];
+ i++;
+ }
+ if (m_active_angles[1]) {
+ m_angles[1] = angles[i];
+ i++;
+ }
+ if (m_active_angles[2]) {
+ m_angles[2] = angles[i];
+ i++;
+ }
+ UpdateLocalTransform();
+
+ return i;
+}
+
+
+ void
+IK_Segment::
+UpdateLocalTransform(
+){
+ // The local transformation is defined by
+ // a user defined translation and rotation followed by
+ // rotation by (roll,pitch,yaw) followed by
+ // a translation in x of m_length
+
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_angles[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_angles[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_angles[2]);
+
+ MT_Quaternion rot = rotx * roty *rotz;
+
+ MT_Transform rx(MT_Point3(0,0,0),rot);
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+ m_local_transform = m_transform * rx * translation;
+};
+
+
+const
+ std::vector<MT_Vector3> &
+IK_Segment::
+AngleVectors(
+) const{
+ return m_angle_vectors;
+};
+
+ MT_Scalar
+IK_Segment::
+ActiveAngle(
+ int i
+) const {
+ MT_assert((i >=0) && (i < DoF()));
+
+ // umm want to return the ith active angle
+ // and not the ith angle
+
+ int j;
+ int angles = -1;
+ for (j=0;j < 3;j++) {
+ if (m_active_angles[j]) angles ++;
+ if (i == angles) return m_angles[j];
+ }
+ return m_angles[0];
+}
+
+ MT_Scalar
+IK_Segment::
+Angle(
+ int i
+) const {
+ MT_assert((i >=0) && (i < 3));
+ return m_angles[i];
+}
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Segment.h b/intern/iksolver/intern/IK_Segment.h
new file mode 100644
index 00000000000..35018df7859
--- /dev/null
+++ b/intern/iksolver/intern/IK_Segment.h
@@ -0,0 +1,217 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_Segment_h
+
+#define NAN_INCLUDED_Segment_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+#include <vector>
+
+class IK_Segment {
+
+public :
+
+ /**
+ * Constructor.
+ * @warning This class uses axis angles for it's parameterization.
+ * Axis angles are a poor representation for joints of more than 1 DOF
+ * because they suffer from Gimbal lock. This becomes noticeable in
+ * IK solutions. A better solution is to do use a quaternion to represent
+ * angles with 3 DOF
+ */
+
+ IK_Segment(
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const bool pitch_on,
+ const bool yaw_on,
+ const bool role_on
+ );
+
+
+ IK_Segment(
+ );
+
+
+ /**
+ * @return The length of the segment
+ */
+
+ const
+ MT_Scalar
+ Length(
+ ) const ;
+
+ /**
+ * @return The transform from adjacent
+ * coordinate systems in the chain.
+ */
+
+ const
+ MT_Transform &
+ LocalTransform(
+ ) const ;
+
+
+ /**
+ * Get the segment to compute it's
+ * global transform given the global transform
+ * of the parent. This method also updtes the
+ * global segment start
+ */
+
+ void
+ UpdateGlobal(
+ const MT_Transform & global
+ );
+
+ /**
+ * @return A const reference to the global trnasformation
+ */
+
+ const
+ MT_Transform &
+ GlobalTransform(
+ ) const;
+
+ /**
+ * @return A const Reference to start of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentStart(
+ ) const;
+
+ /**
+ * Computes the number of degrees of freedom of this segment
+ */
+
+ int
+ DoF(
+ ) const;
+
+
+ /**
+ * Increment the active angles (at most DoF()) by
+ * d_theta. Which angles are incremented depends
+ * on which are active.
+ * @return DoF()
+ * @warning Bad interface
+ */
+
+ int
+ IncrementAngles(
+ MT_Scalar *d_theta
+ );
+
+
+ // FIXME - interface bloat
+
+ /**
+ * @return the vectors about which the active
+ * angles operate
+ */
+
+ const
+ std::vector<MT_Vector3> &
+ AngleVectors(
+ ) const;
+
+ /**
+ * @return the ith active angle
+ */
+
+ MT_Scalar
+ ActiveAngle(
+ int i
+ ) const;
+
+ /**
+ * @return the ith angle
+ */
+ MT_Scalar
+ Angle(
+ int i
+ ) const;
+
+
+ /**
+ * Set the active angles from the array
+ * @return the number of active angles
+ */
+
+ int
+ SetAngles(
+ const MT_Scalar *angles
+ );
+
+
+private :
+
+ void
+ UpdateLocalTransform(
+ );
+
+
+
+private :
+
+ /** The user defined transformation, composition of the
+ * translation and rotation from constructor.
+ */
+
+ MT_Transform m_transform;
+ MT_Scalar m_angles[3];
+ MT_Scalar m_length;
+
+ MT_Transform m_local_transform;
+ MT_Transform m_global_transform;
+
+ bool m_active_angles[3];
+
+ MT_Vector3 m_seg_start;
+
+ std::vector<MT_Vector3> m_angle_vectors;
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
new file mode 100644
index 00000000000..11646597d6d
--- /dev/null
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -0,0 +1,196 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#define IK_USE_EXPMAP
+
+
+
+#ifdef IK_USE_EXPMAP
+# include "IK_QSolver_Class.h"
+#else
+# include "IK_Solver_Class.h"
+#endif
+#include "../extern/IK_solver.h"
+
+#include <iostream.h>
+
+ IK_Chain_ExternPtr
+IK_CreateChain(
+ void
+) {
+
+ MEM_SmartPtr<IK_Chain_Extern> output (new IK_Chain_Extern);
+ MEM_SmartPtr<IK_QSolver_Class> output_void (IK_QSolver_Class::New());
+
+
+ if (output == NULL || output_void == NULL) {
+ return NULL;
+ }
+
+ output->chain_dof = 0;
+ output->num_segments = 0;
+ output->segments = NULL;
+ output->intern = output_void.Release();
+ return output.Release();
+};
+
+
+ int
+IK_LoadChain(
+ IK_Chain_ExternPtr chain,
+ IK_Segment_ExternPtr segments,
+ int num_segs
+) {
+
+ if (chain == NULL || segments == NULL) return 0;
+
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+ if (intern_cpp == NULL) return 0;
+
+ std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments();
+ if (segs.size() != num_segs) {
+ segs = std::vector<IK_QSegment>(num_segs);
+ }
+
+ std::vector<IK_QSegment>::const_iterator seg_end= segs.end();
+ std::vector<IK_QSegment>::iterator seg_begin= segs.begin();
+
+ IK_Segment_ExternPtr extern_seg_it = segments;
+
+
+ for (;seg_begin != seg_end; ++seg_begin,++extern_seg_it) {
+
+ MT_Point3 tr1(extern_seg_it->seg_start);
+
+ MT_Matrix3x3 A(
+ extern_seg_it->basis[0],extern_seg_it->basis[1],extern_seg_it->basis[2],
+ extern_seg_it->basis[3],extern_seg_it->basis[4],extern_seg_it->basis[5],
+ extern_seg_it->basis[6],extern_seg_it->basis[7],extern_seg_it->basis[8]
+ );
+
+ MT_Scalar length(extern_seg_it->length);
+
+
+ *seg_begin = IK_QSegment(
+ tr1,A,length,MT_Vector3(0,0,0)
+ );
+
+ }
+
+
+ intern_cpp->Chain().UpdateGlobalTransformations();
+ intern_cpp->Chain().ComputeJacobian();
+
+ chain->num_segments = num_segs;
+ chain->chain_dof = intern_cpp->Chain().DoF();
+ chain->segments = segments;
+
+ return 1;
+};
+
+ int
+IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+){
+ if (chain == NULL || output == NULL) return 0;
+ if (chain->intern == NULL) return 0;
+
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+
+ IK_QJacobianSolver & solver = intern_cpp->Solver();
+
+ bool solve_result = solver.Solve(
+ intern_cpp->Chain(),
+ MT_Vector3(goal),
+ MT_Vector3(0,0,0),
+ MT_Scalar(tolerance),
+ max_iterations,
+ MT_Scalar(max_angle_change)
+ );
+
+ // turn the computed role->pitch->yaw into a quaternion and
+ // return the result in output
+
+ std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments();
+ std::vector<IK_QSegment>::const_iterator seg_end= segs.end();
+ std::vector<IK_QSegment>::iterator seg_begin= segs.begin();
+
+ for (;seg_begin != seg_end; ++seg_begin, ++output) {
+ MT_Matrix3x3 qrot = seg_begin->ExpMap().getMatrix();
+
+ // don't forget to transpose this qrot for use by blender!
+
+ qrot.transpose(); // blender uses transpose here ????
+
+ output->basis_change[0] = float(qrot[0][0]);
+ output->basis_change[1] = float(qrot[0][1]);
+ output->basis_change[2] = float(qrot[0][2]);
+ output->basis_change[3] = float(qrot[1][0]);
+ output->basis_change[4] = float(qrot[1][1]);
+ output->basis_change[5] = float(qrot[1][2]);
+ output->basis_change[6] = float(qrot[2][0]);
+ output->basis_change[7] = float(qrot[2][1]);
+ output->basis_change[8] = float(qrot[2][2]);
+
+ }
+
+
+ return solve_result ? 1 : 0;
+}
+
+ void
+IK_FreeChain(
+ IK_Chain_ExternPtr chain
+){
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+
+ delete(intern_cpp);
+ delete(chain);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Solver_Class.h b/intern/iksolver/intern/IK_Solver_Class.h
new file mode 100644
index 00000000000..1ef6c22f946
--- /dev/null
+++ b/intern/iksolver/intern/IK_Solver_Class.h
@@ -0,0 +1,93 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_IK_Solver_Class
+
+#define NAN_INCLUDED_IK_Solver_Class
+
+#include "IK_Chain.h"
+#include "IK_JacobianSolver.h"
+#include "IK_Segment.h"
+#include "MEM_SmartPtr.h"
+
+class IK_Solver_Class {
+
+public :
+
+ static
+ IK_Solver_Class *
+ New(
+ ){
+ MEM_SmartPtr<IK_Solver_Class> output (new IK_Solver_Class);
+
+ MEM_SmartPtr<IK_JacobianSolver> solver (IK_JacobianSolver::New());
+
+ if (output == NULL ||
+ solver == NULL
+ ) {
+ return NULL;
+ }
+
+ output->m_solver = solver.Release();
+
+ return output.Release();
+ };
+
+ IK_Chain &
+ Chain(
+ ) {
+ return m_chain;
+ };
+
+ IK_JacobianSolver &
+ Solver(
+ ) {
+ return m_solver.Ref();
+ }
+
+ ~IK_Solver_Class(
+ ) {
+ // nothing to do
+ }
+
+
+private :
+
+ IK_Solver_Class(
+ ) {
+ };
+
+ IK_Chain m_chain;
+ MEM_SmartPtr<IK_JacobianSolver> m_solver;
+
+};
+
+#endif
diff --git a/intern/iksolver/intern/MT_ExpMap.cpp b/intern/iksolver/intern/MT_ExpMap.cpp
new file mode 100644
index 00000000000..ea005a42096
--- /dev/null
+++ b/intern/iksolver/intern/MT_ExpMap.cpp
@@ -0,0 +1,268 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "MT_ExpMap.h"
+
+/**
+ * Set the exponential map from a quaternion. The quaternion must be non-zero.
+ */
+
+ void
+MT_ExpMap::
+setRotation(
+ const MT_Quaternion &q
+) {
+ // ok first normailize the quaternion
+ // then compute theta the axis-angle and the normalized axis v
+ // scale v by theta and that's it hopefully!
+
+ MT_Quaternion qt = q.normalized();
+
+ MT_Vector3 axis(qt.x(),qt.y(),qt.z());
+ MT_Scalar cosp = qt.w();
+ MT_Scalar sinp = axis.length();
+ axis /= sinp;
+
+ MT_Scalar theta = atan2(double(sinp),double(cosp));
+
+ axis *= theta;
+ m_v = axis;
+}
+
+/**
+ * Convert from an exponential map to a quaternion
+ * representation
+ */
+
+ MT_Quaternion
+MT_ExpMap::
+getRotation(
+) const {
+ bool rep=0;
+ MT_Scalar cosp, sinp, theta;
+
+ MT_Quaternion q;
+
+ theta = m_v.length();
+
+ cosp = MT_Scalar(cos(.5*theta));
+ sinp = MT_Scalar(sin(.5*theta));
+
+ q.w() = cosp;
+
+ if (theta < MT_EXPMAP_MINANGLE) {
+
+ MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - theta*theta/MT_Scalar(48.0)); /* Taylor Series for sinc */
+ q.x() = temp.x();
+ q.y() = temp.y();
+ q.z() = temp.z();
+ } else {
+ MT_Vector3 temp = m_v * (sinp/theta); /* Taylor Series for sinc */
+ q.x() = temp.x();
+ q.y() = temp.y();
+ q.z() = temp.z();
+ }
+
+ return q;
+}
+
+/**
+ * Convert the exponential map to a 3x3 matrix
+ */
+
+ MT_Matrix3x3
+MT_ExpMap::
+getMatrix(
+) const {
+
+ MT_Quaternion q = getRotation();
+ return MT_Matrix3x3(q);
+}
+
+
+
+
+/**
+ * Force a reparameterization of the exponential
+ * map.
+ */
+
+ bool
+MT_ExpMap::
+reParameterize(
+ MT_Scalar &theta
+){
+ bool rep(false);
+ theta = m_v.length();
+
+ if (theta > MT_PI){
+ MT_Scalar scl = theta;
+ if (theta > MT_2_PI){ /* first get theta into range 0..2PI */
+ theta = MT_Scalar(fmod(theta, MT_2_PI));
+ scl = theta/scl;
+ m_v *= scl;
+ rep = true;
+ }
+ if (theta > MT_PI){
+ scl = theta;
+ theta = MT_2_PI - theta;
+ scl = MT_Scalar(1.0) - MT_2_PI/scl;
+ m_v *= scl;
+ rep = true;
+ }
+ }
+ return rep;
+
+}
+
+/**
+ * Compute the partial derivatives of the exponential
+ * map (dR/de - where R is a 4x4 rotation matrix formed
+ * from the map) and return them as a 4x4 matrix
+ */
+
+ MT_Matrix4x4
+MT_ExpMap::
+partialDerivatives(
+ const int i
+) const {
+
+ MT_Quaternion q = getRotation();
+ MT_Quaternion dQdx;
+
+ MT_Matrix4x4 output;
+
+ compute_dQdVi(i,dQdx);
+ compute_dRdVi(q,dQdx,output);
+
+ return output;
+}
+
+ void
+MT_ExpMap::
+compute_dRdVi(
+ const MT_Quaternion &q,
+ const MT_Quaternion &dQdvi,
+ MT_Matrix4x4 & dRdvi
+) const {
+
+ MT_Scalar prod[9];
+
+ /* This efficient formulation is arrived at by writing out the
+ * entire chain rule product dRdq * dqdv in terms of 'q' and
+ * noticing that all the entries are formed from sums of just
+ * nine products of 'q' and 'dqdv' */
+
+ prod[0] = -MT_Scalar(4)*q.x()*dQdvi.x();
+ prod[1] = -MT_Scalar(4)*q.y()*dQdvi.y();
+ prod[2] = -MT_Scalar(4)*q.z()*dQdvi.z();
+ prod[3] = MT_Scalar(2)*(q.y()*dQdvi.x() + q.x()*dQdvi.y());
+ prod[4] = MT_Scalar(2)*(q.w()*dQdvi.z() + q.z()*dQdvi.w());
+ prod[5] = MT_Scalar(2)*(q.z()*dQdvi.x() + q.x()*dQdvi.z());
+ prod[6] = MT_Scalar(2)*(q.w()*dQdvi.y() + q.y()*dQdvi.w());
+ prod[7] = MT_Scalar(2)*(q.z()*dQdvi.y() + q.y()*dQdvi.z());
+ prod[8] = MT_Scalar(2)*(q.w()*dQdvi.x() + q.x()*dQdvi.w());
+
+ /* first row, followed by second and third */
+ dRdvi[0][0] = prod[1] + prod[2];
+ dRdvi[0][1] = prod[3] - prod[4];
+ dRdvi[0][2] = prod[5] + prod[6];
+
+ dRdvi[1][0] = prod[3] + prod[4];
+ dRdvi[1][1] = prod[0] + prod[2];
+ dRdvi[1][2] = prod[7] - prod[8];
+
+ dRdvi[2][0] = prod[5] - prod[6];
+ dRdvi[2][1] = prod[7] + prod[8];
+ dRdvi[2][2] = prod[0] + prod[1];
+
+ /* the 4th row and column are all zero */
+ int i;
+
+ for (i=0; i<3; i++)
+ dRdvi[3][i] = dRdvi[i][3] = MT_Scalar(0);
+ dRdvi[3][3] = 0;
+}
+
+// compute partial derivatives dQ/dVi
+
+ void
+MT_ExpMap::
+compute_dQdVi(
+ const int i,
+ MT_Quaternion & dQdX
+) const {
+
+ MT_Scalar theta = m_v.length();
+ MT_Scalar cosp(cos(MT_Scalar(.5)*theta)), sinp(sin(MT_Scalar(.5)*theta));
+
+ MT_assert(i>=0 && i<3);
+
+ /* This is an efficient implementation of the derivatives given
+ * in Appendix A of the paper with common subexpressions factored out */
+ if (theta < MT_EXPMAP_MINANGLE){
+ const int i2 = (i+1)%3, i3 = (i+2)%3;
+ MT_Scalar Tsinc = MT_Scalar(0.5) - theta*theta/MT_Scalar(48.0);
+ MT_Scalar vTerm = m_v[i] * (theta*theta/MT_Scalar(40.0) - MT_Scalar(1.0)) / MT_Scalar(24.0);
+
+ dQdX.w() = -.5*m_v[i]*Tsinc;
+ dQdX[i] = m_v[i]* vTerm + Tsinc;
+ dQdX[i2] = m_v[i2]*vTerm;
+ dQdX[i3] = m_v[i3]*vTerm;
+ } else {
+ const int i2 = (i+1)%3, i3 = (i+2)%3;
+ const MT_Scalar ang = 1.0/theta, ang2 = ang*ang*m_v[i], sang = sinp*ang;
+ const MT_Scalar cterm = ang2*(.5*cosp - sang);
+
+ dQdX[i] = cterm*m_v[i] + sang;
+ dQdX[i2] = cterm*m_v[i2];
+ dQdX[i3] = cterm*m_v[i3];
+ dQdX.w() = MT_Scalar(-.5)*m_v[i]*sang;
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h
new file mode 100644
index 00000000000..10cacb59b78
--- /dev/null
+++ b/intern/iksolver/intern/MT_ExpMap.h
@@ -0,0 +1,219 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef MT_ExpMap_H
+#define MT_ExpMap_H
+
+#include <MT_assert.h>
+
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix4x4.h"
+
+const MT_Scalar MT_EXPMAP_MINANGLE (1e-7);
+
+/**
+ * MT_ExpMap an exponential map parameterization of rotations
+ * in 3D. This implementation is derived from the paper
+ * "F. Sebastian Grassia. Practical parameterization of
+ * rotations using the exponential map. Journal of Graphics Tools,
+ * 3(3):29-48, 1998" Please go to http://www.acm.org/jgt/papers/Grassia98/
+ * for a thorough description of the theory and sample code used
+ * to derive this class.
+ *
+ * Basic overview of why this class is used.
+ * In an IK system we need to paramterize the joint angles in some
+ * way. Typically 2 parameterizations are used.
+ * - Euler Angles
+ * These suffer from singularities in the parameterization known
+ * as gimbal lock. They also do not interpolate well. For every
+ * set of euler angles there is exactly 1 corresponding 3d rotation.
+ * - Quaternions.
+ * Great for interpolating. Only unit quaternions are valid rotations
+ * means that in a differential ik solver we often stray outside of
+ * this manifold into invalid rotations. Means we have to do a lot
+ * of nasty normalizations all the time. Does not suffer from
+ * gimbal lock problems. More expensive to compute partial derivatives
+ * as there are 4 of them.
+ *
+ * So exponential map is similar to a quaternion axis/angle
+ * representation but we store the angle as the length of the
+ * axis. So require only 3 parameters. Means that all exponential
+ * maps are valid rotations. Suffers from gimbal lock. But it's
+ * possible to detect when gimbal lock is near and reparameterize
+ * away from it. Also nice for interpolating.
+ * Exponential maps are share some of the useful properties of
+ * euler and quaternion parameterizations. And are very useful
+ * for differential IK solvers.
+ */
+
+class MT_ExpMap {
+public:
+
+ /**
+ * Default constructor
+ * @warning there is no initialization in the
+ * default constructor
+ */
+
+ MT_ExpMap() {}
+ MT_ExpMap(const MT_Vector3& v) : m_v(v) {}
+
+ MT_ExpMap(const float v[3]) : m_v(v) {}
+ MT_ExpMap(const double v[3]) : m_v(v) {}
+
+ MT_ExpMap(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ m_v(x, y, z) {}
+
+ /**
+ * Construct an exponential map from a quaternion
+ */
+
+ MT_ExpMap(
+ const MT_Quaternion &q
+ ) {
+ setRotation(q);
+ };
+
+ /**
+ * Accessors
+ * Decided not to inherit from MT_Vector3 but rather
+ * this class contains an MT_Vector3. This is because
+ * it is very dangerous to use MT_Vector3 functions
+ * on this class and some of them have no direct meaning.
+ */
+
+ MT_Vector3 &
+ vector(
+ ) {
+ return m_v;
+ };
+
+ const
+ MT_Vector3 &
+ vector(
+ ) const {
+ return m_v;
+ };
+
+ /**
+ * Set the exponential map from a quaternion
+ */
+
+ void
+ setRotation(
+ const MT_Quaternion &q
+ );
+
+ /**
+ * Convert from an exponential map to a quaternion
+ * representation
+ */
+
+ MT_Quaternion
+ getRotation(
+ ) const;
+
+ /**
+ * Convert the exponential map to a 3x3 matrix
+ */
+
+ MT_Matrix3x3
+ getMatrix(
+ ) const;
+
+ /**
+ * Force a reparameterization check of the exponential
+ * map.
+ * @param theta returns the new axis-angle.
+ * @return true iff a reParameterization took place.
+ * Use this function whenever you adjust the vector
+ * representing the exponential map.
+ */
+
+ bool
+ reParameterize(
+ MT_Scalar &theta
+ );
+
+ /**
+ * Compute the partial derivatives of the exponential
+ * map (dR/de - where R is a 4x4 matrix formed
+ * from the map) and return them as a 4x4 matrix
+ */
+
+ MT_Matrix4x4
+ partialDerivatives(
+ const int i
+ ) const ;
+
+private :
+
+ MT_Vector3 m_v;
+
+ // private methods
+
+ // Compute partial derivatives dR (3x3 rotation matrix) / dVi (EM vector)
+ // given the partial derivative dQ (Quaternion) / dVi (ith element of EM vector)
+
+
+ void
+ compute_dRdVi(
+ const MT_Quaternion &q,
+ const MT_Quaternion &dQdV,
+ MT_Matrix4x4 & dRdVi
+ ) const;
+
+ // compute partial derivatives dQ/dVi
+
+ void
+ compute_dQdVi(
+ int i,
+ MT_Quaternion & dQdX
+ ) const ;
+
+
+};
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/Makefile b/intern/iksolver/intern/Makefile
new file mode 100644
index 00000000000..af32d816a80
--- /dev/null
+++ b/intern/iksolver/intern/Makefile
@@ -0,0 +1,44 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver intern Makefile
+#
+
+LIBNAME = iksolver
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+CCSRCS = IK_QChain.cpp IK_QJacobianSolver.cpp IK_QSegment.cpp MT_ExpMap.cpp IK_Solver.cpp
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
diff --git a/intern/iksolver/intern/TNT/cholesky.h b/intern/iksolver/intern/TNT/cholesky.h
new file mode 100644
index 00000000000..a3e0118f4e5
--- /dev/null
+++ b/intern/iksolver/intern/TNT/cholesky.h
@@ -0,0 +1,128 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef CHOLESKY_H
+#define CHOLESKY_H
+
+#include <cmath>
+
+// index method
+
+namespace TNT
+{
+
+
+//
+// Only upper part of A is used. Cholesky factor is returned in
+// lower part of L. Returns 0 if successful, 1 otherwise.
+//
+template <class SPDMatrix, class SymmMatrix>
+int Cholesky_upper_factorization(SPDMatrix &A, SymmMatrix &L)
+{
+ Subscript M = A.dim(1);
+ Subscript N = A.dim(2);
+
+ assert(M == N); // make sure A is square
+
+ // readjust size of L, if necessary
+
+ if (M != L.dim(1) || N != L.dim(2))
+ L = SymmMatrix(N,N);
+
+ Subscript i,j,k;
+
+
+ typename SPDMatrix::element_type dot=0;
+
+
+ for (j=1; j<=N; j++) // form column j of L
+ {
+ dot= 0;
+
+ for (i=1; i<j; i++) // for k= 1 TO j-1
+ dot = dot + L(j,i)*L(j,i);
+
+ L(j,j) = A(j,j) - dot;
+
+ for (i=j+1; i<=N; i++)
+ {
+ dot = 0;
+ for (k=1; k<j; k++)
+ dot = dot + L(i,k)*L(j,k);
+ L(i,j) = A(j,i) - dot;
+ }
+
+ if (L(j,j) <= 0.0) return 1;
+
+ L(j,j) = sqrt( L(j,j) );
+
+ for (i=j+1; i<=N; i++)
+ L(i,j) = L(i,j) / L(j,j);
+
+ }
+
+ return 0;
+}
+
+
+
+
+}
+// namespace TNT
+
+#endif
+// CHOLESKY_H
diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h
new file mode 100644
index 00000000000..80a82417e47
--- /dev/null
+++ b/intern/iksolver/intern/TNT/cmat.h
@@ -0,0 +1,661 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
+//
+
+#ifndef CMAT_H
+#define CMAT_H
+
+#include "subscript.h"
+#include "vec.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+#include <strstream>
+#ifdef TNT_USE_REGIONS
+#include "region2d.h"
+#endif
+
+namespace TNT
+{
+
+template <class T>
+class Matrix
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ Subscript m_;
+ Subscript n_;
+ Subscript mn_; // total size
+ T* v_;
+ T** row_;
+ T* vm1_ ; // these point to the same data, but are 1-based
+ T** rowm1_;
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript M, Subscript N)
+ {
+ mn_ = M*N;
+ m_ = M;
+ n_ = N;
+
+ v_ = new T[mn_];
+ row_ = new T*[M];
+ rowm1_ = new T*[M];
+
+ assert(v_ != NULL);
+ assert(row_ != NULL);
+ assert(rowm1_ != NULL);
+
+ T* p = v_;
+ vm1_ = v_ - 1;
+ for (Subscript i=0; i<M; i++)
+ {
+ row_[i] = p;
+ rowm1_[i] = p-1;
+ p += N ;
+
+ }
+
+ rowm1_ -- ; // compensate for 1-based offset
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ if (v_ != NULL) delete [] (v_);
+ if (row_ != NULL) delete [] (row_);
+
+ /* return rowm1_ back to original value */
+ rowm1_ ++;
+ if (rowm1_ != NULL ) delete [] (rowm1_);
+ }
+
+
+ public:
+
+ operator T**(){ return row_; }
+ operator T**() const { return row_; }
+
+
+ Subscript size() const { return mn_; }
+
+ // constructors
+
+ Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
+
+ Matrix(const Matrix<T> &A)
+ {
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ Matrix(Subscript M, Subscript N, const T& value = T())
+ {
+ initialize(M,N);
+ set(value);
+ }
+
+ Matrix(Subscript M, Subscript N, const T* v)
+ {
+ initialize(M,N);
+ copy(v);
+ }
+
+ Matrix(Subscript M, Subscript N, const char *s)
+ {
+ initialize(M,N);
+ std::istrstream ins(s);
+
+ Subscript i, j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ ins >> row_[i][j];
+ }
+
+
+ // destructor
+ //
+ ~Matrix()
+ {
+ destroy();
+ }
+
+
+ // reallocating
+ //
+ Matrix<T>& newsize(Subscript M, Subscript N)
+ {
+ if (num_rows() == M && num_cols() == N)
+ return *this;
+
+ destroy();
+ initialize(M,N);
+
+ return *this;
+ }
+
+ void
+ diagonal(Vector<T> &diag)
+ {
+ int sz = diag.dim();
+ newsize(sz,sz);
+ set(0);
+
+ Subscript i;
+ for (i = 0; i < sz; i++) {
+ row_[i][i] = diag[i];
+ }
+ }
+
+
+
+ // assignments
+ //
+ Matrix<T>& operator=(const Matrix<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Matrix<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+
+ Subscript dim(Subscript d) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( d >= 1);
+ assert( d <= 2);
+#endif
+ return (d==1) ? m_ : ((d==2) ? n_ : 0);
+ }
+
+ Subscript num_rows() const { return m_; }
+ Subscript num_cols() const { return n_; }
+
+
+
+
+ inline T* operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < m_) ;
+#endif
+ return row_[i];
+ }
+
+ inline const T* operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < m_) ;
+#endif
+ return row_[i];
+ }
+
+ inline reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= mn_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline const_reference operator()(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= mn_) ;
+#endif
+ return vm1_[i];
+ }
+
+
+
+ inline reference operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return rowm1_[i][j];
+ }
+
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return rowm1_[i][j];
+ }
+
+
+
+#ifdef TNT_USE_REGIONS
+
+ typedef Region2D<Matrix<T> > Region;
+
+
+ Region operator()(const Index1D &I, const Index1D &J)
+ {
+ return Region(*this, I,J);
+ }
+
+
+ typedef const_Region2D< Matrix<T> > const_Region;
+ const_Region operator()(const Index1D &I, const Index1D &J) const
+ {
+ return const_Region(*this, I,J);
+ }
+
+#endif
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << "\n";
+
+ for (Subscript i=0; i<M; i++)
+ {
+ for (Subscript j=0; j<N; j++)
+ {
+ s << A[i][j] << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class T>
+std::istream& operator>>(std::istream &s, Matrix<T> &A)
+{
+
+ Subscript M, N;
+
+ s >> M >> N;
+
+ if ( !(M == A.num_rows() && N == A.num_cols() ))
+ {
+ A.newsize(M,N);
+ }
+
+
+ for (Subscript i=0; i<M; i++)
+ for (Subscript j=0; j<N; j++)
+ {
+ s >> A[i][j];
+ }
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+template <class T>
+Matrix<T> operator+(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] + B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+Matrix<T> operator-(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] - B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+Matrix<T> mult_element(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] * B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+void transpose(const Matrix<T> &A, Matrix<T> &S)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==S.num_cols());
+ assert(N==S.num_rows());
+
+ Subscript i, j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ S[j][i] = A[i][j];
+
+}
+
+
+template <class T>
+inline void matmult(Matrix<T>& C, const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+
+ assert(A.num_cols() == B.num_rows());
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ C.newsize(M,K);
+
+ T sum;
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=0; i<M; i++)
+ for (Subscript k=0; k<K; k++)
+ {
+ row_i = &(A[i][0]);
+ col_k = &(B[0][k]);
+ sum = 0;
+ for (Subscript j=0; j<N; j++)
+ {
+ sum += *row_i * *col_k;
+ row_i++;
+ col_k += K;
+ }
+ C[i][k] = sum;
+ }
+
+}
+
+template <class T>
+void matmult(Vector<T> &y, const Matrix<T> &A, const Vector<T> &x)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == x.dim());
+ assert(A.num_rows() == y.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ T sum;
+
+ for (Subscript i=0; i<M; i++)
+ {
+ sum = 0;
+ const T* rowi = A[i];
+ for (Subscript j=0; j<N; j++)
+ sum = sum + rowi[j] * x[j];
+
+ y[i] = sum;
+ }
+}
+
+template <class T>
+inline void matmultdiag(
+ Matrix<T>& C,
+ const Matrix<T> &A,
+ const Vector<T> &diag
+){
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() ==A.num_rows()== diag.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript K = diag.dim();
+
+ C.newsize(M,K);
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=0; i<M; i++) {
+ for (Subscript k=0; k<K; k++)
+ {
+ C[i][k] = A[i,k] * diag[k];
+ }
+ }
+}
+
+
+template <class T>
+inline void matmultdiag(
+ Matrix<T>& C,
+ const Vector<T> &diag,
+ const Matrix<T> &A
+){
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() ==A.num_rows()== diag.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript K = diag.dim();
+
+ C.newsize(M,K);
+
+ for (Subscript i=0; i<M; i++) {
+
+ const T diag_element = diag[i];
+
+ for (Subscript k=0; k<K; k++)
+ {
+ C[i][k] = A[i][k] * diag_element;
+ }
+ }
+}
+
+
+
+
+} // namespace TNT
+
+
+
+
+#endif
+// CMAT_H
diff --git a/intern/iksolver/intern/TNT/fcscmat.h b/intern/iksolver/intern/TNT/fcscmat.h
new file mode 100644
index 00000000000..877364ad38c
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fcscmat.h
@@ -0,0 +1,197 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Templated compressed sparse column matrix (Fortran conventions).
+// uses 1-based offsets in storing row indices.
+// Used primarily to interface with Fortran sparse matrix libaries.
+// (CANNOT BE USED AS AN STL CONTAINER.)
+
+
+#ifndef FCSCMAT_H
+#define FCSCMAT_H
+
+#include <iostream>
+#include <cassert>
+#include "tnt.h"
+#include "vec.h"
+
+using namespace std;
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Sparse_Col_Matrix
+{
+
+ protected:
+
+ Vector<T> val_; // data values (nz_ elements)
+ Vector<Subscript> rowind_; // row_ind (nz_ elements)
+ Vector<Subscript> colptr_; // col_ptr (n_+1 elements)
+
+ int nz_; // number of nonzeros
+ Subscript m_; // global dimensions
+ Subscript n_;
+
+ public:
+
+
+ Fortran_Sparse_Col_Matrix(void);
+ Fortran_Sparse_Col_Matrix(const Fortran_Sparse_Col_Matrix<T> &S)
+ : val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_), nz_(S.nz_),
+ m_(S.m_), n_(S.n_) {};
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, const T *val, const Subscript *r,
+ const Subscript *c) : val_(nz, val), rowind_(nz, r),
+ colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
+
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, char *val, char *r,
+ char *c) : val_(nz, val), rowind_(nz, r),
+ colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
+
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, const T *val, Subscript *r, Subscript *c)
+ : val_(nz, val), rowind_(nz, r), colptr_(N+1, c), nz_(nz),
+ m_(M), n_(N) {};
+
+ ~Fortran_Sparse_Col_Matrix() {};
+
+
+ T & val(Subscript i) { return val_(i); }
+ const T & val(Subscript i) const { return val_(i); }
+
+ Subscript & row_ind(Subscript i) { return rowind_(i); }
+ const Subscript & row_ind(Subscript i) const { return rowind_(i); }
+
+ Subscript col_ptr(Subscript i) { return colptr_(i);}
+ const Subscript col_ptr(Subscript i) const { return colptr_(i);}
+
+
+ Subscript num_cols() const { return m_;}
+ Subscript num_rows() const { return n_; }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( 1 <= i );
+ assert( i <= 2 );
+#endif
+ if (i==1) return m_;
+ else if (i==2) return m_;
+ else return 0;
+ }
+
+ Subscript num_nonzeros() const {return nz_;};
+ Subscript lbound() const {return 1;}
+
+
+
+ Fortran_Sparse_Col_Matrix& operator=(const
+ Fortran_Sparse_Col_Matrix &C)
+ {
+ val_ = C.val_;
+ rowind_ = C.rowind_;
+ colptr_ = C.colptr_;
+ nz_ = C.nz_;
+ m_ = C.m_;
+ n_ = C.n_;
+
+ return *this;
+ }
+
+ Fortran_Sparse_Col_Matrix& newsize(Subscript M, Subscript N,
+ Subscript nz)
+ {
+ val_.newsize(nz);
+ rowind_.newsize(nz);
+ colptr_.newsize(N+1);
+ return *this;
+ }
+};
+
+template <class T>
+ostream& operator<<(ostream &s, const Fortran_Sparse_Col_Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << " " << A.num_nonzeros() << endl;
+
+
+ for (Subscript k=1; k<=N; k++)
+ {
+ Subscript start = A.col_ptr(k);
+ Subscript end = A.col_ptr(k+1);
+
+ for (Subscript i= start; i<end; i++)
+ {
+ s << A.row_ind(i) << " " << k << " " << A.val(i) << endl;
+ }
+ }
+
+ return s;
+}
+
+
+
+} // namespace TNT
+
+#endif
+/* FCSCMAT_H */
+
diff --git a/intern/iksolver/intern/TNT/fmat.h b/intern/iksolver/intern/TNT/fmat.h
new file mode 100644
index 00000000000..5de9a63813e
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fmat.h
@@ -0,0 +1,609 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Fortran-compatible matrix: column oriented, 1-based (i,j) indexing
+
+#ifndef FMAT_H
+#define FMAT_H
+
+#include "subscript.h"
+#include "vec.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+#ifdef TNT_USE_REGIONS
+#include "region2d.h"
+#endif
+
+// simple 1-based, column oriented Matrix class
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Matrix
+{
+
+
+ public:
+
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ T* v_; // these are adjusted to simulate 1-offset
+ Subscript m_;
+ Subscript n_;
+ T** col_; // these are adjusted to simulate 1-offset
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript M, Subscript N)
+ {
+ // adjust col_[] pointers so that they are 1-offset:
+ // col_[j][i] is really col_[j-1][i-1];
+ //
+ // v_[] is the internal contiguous array, it is still 0-offset
+ //
+ v_ = new T[M*N];
+ col_ = new T*[N];
+
+ assert(v_ != NULL);
+ assert(col_ != NULL);
+
+
+ m_ = M;
+ n_ = N;
+ T* p = v_ - 1;
+ for (Subscript i=0; i<N; i++)
+ {
+ col_[i] = p;
+ p += M ;
+
+ }
+ col_ --;
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ delete [] (v_);
+ col_ ++; // changed back to 0-offset
+ delete [] (col_);
+ }
+
+
+ public:
+
+ T* begin() { return v_; }
+ const T* begin() const { return v_;}
+
+ T* end() { return v_ + m_*n_; }
+ const T* end() const { return v_ + m_*n_; }
+
+
+ // constructors
+
+ Fortran_Matrix() : v_(0), m_(0), n_(0), col_(0) {};
+ Fortran_Matrix(const Fortran_Matrix<T> &A)
+ {
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ Fortran_Matrix(Subscript M, Subscript N, const T& value = T())
+ {
+ initialize(M,N);
+ set(value);
+ }
+
+ Fortran_Matrix(Subscript M, Subscript N, const T* v)
+ {
+ initialize(M,N);
+ copy(v);
+ }
+
+
+ Fortran_Matrix(Subscript M, Subscript N, char *s)
+ {
+ initialize(M,N);
+ std::istrstream ins(s);
+
+ Subscript i, j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ ins >> (*this)(i,j);
+ }
+
+ // destructor
+ ~Fortran_Matrix()
+ {
+ destroy();
+ }
+
+
+ // assignments
+ //
+ Fortran_Matrix<T>& operator=(const Fortran_Matrix<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Fortran_Matrix<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+
+ Subscript dim(Subscript d) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( d >= 1);
+ assert( d <= 2);
+#endif
+ return (d==1) ? m_ : ((d==2) ? n_ : 0);
+ }
+
+ Subscript num_rows() const { return m_; }
+ Subscript num_cols() const { return n_; }
+
+ Fortran_Matrix<T>& newsize(Subscript M, Subscript N)
+ {
+ if (num_rows() == M && num_cols() == N)
+ return *this;
+
+ destroy();
+ initialize(M,N);
+
+ return *this;
+ }
+
+
+
+ // 1-based element access
+ //
+ inline reference operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return col_[j][i];
+ }
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return col_[j][i];
+ }
+
+
+#ifdef TNT_USE_REGIONS
+
+ typedef Region2D<Fortran_Matrix<T> > Region;
+ typedef const_Region2D< Fortran_Matrix<T> > const_Region;
+
+ Region operator()(const Index1D &I, const Index1D &J)
+ {
+ return Region(*this, I,J);
+ }
+
+ const_Region operator()(const Index1D &I, const Index1D &J) const
+ {
+ return const_Region(*this, I,J);
+ }
+
+#endif
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Fortran_Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << "\n";
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class T>
+std::istream& operator>>(std::istream &s, Fortran_Matrix<T> &A)
+{
+
+ Subscript M, N;
+
+ s >> M >> N;
+
+ if ( !(M == A.num_rows() && N == A.num_cols()))
+ {
+ A.newsize(M,N);
+ }
+
+
+ for (Subscript i=1; i<=M; i++)
+ for (Subscript j=1; j<=N; j++)
+ {
+ s >> A(i,j);
+ }
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Fortran_Matrix<T> operator+(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) + B(i,j);
+
+ return tmp;
+}
+
+template <class T>
+Fortran_Matrix<T> operator-(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) - B(i,j);
+
+ return tmp;
+}
+
+// element-wise multiplication (use matmult() below for matrix
+// multiplication in the linear algebra sense.)
+//
+//
+template <class T>
+Fortran_Matrix<T> mult_element(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) * B(i,j);
+
+ return tmp;
+}
+
+
+template <class T>
+Fortran_Matrix<T> transpose(const Fortran_Matrix<T> &A)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Fortran_Matrix<T> S(N,M);
+ Subscript i, j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ S(j,i) = A(i,j);
+
+ return S;
+}
+
+
+
+template <class T>
+inline Fortran_Matrix<T> matmult(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == B.num_rows());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ Fortran_Matrix<T> tmp(M,K);
+ T sum;
+
+ for (Subscript i=1; i<=M; i++)
+ for (Subscript k=1; k<=K; k++)
+ {
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ sum = sum + A(i,j) * B(j,k);
+
+ tmp(i,k) = sum;
+ }
+
+ return tmp;
+}
+
+template <class T>
+inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ return matmult(A,B);
+}
+
+template <class T>
+inline int matmult(Fortran_Matrix<T>& C, const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+
+ assert(A.num_cols() == B.num_rows());
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ C.newsize(M,K); // adjust shape of C, if necessary
+
+
+ T sum;
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript k=1; k<=K; k++)
+ {
+ row_i = &A(i,1);
+ col_k = &B(1,k);
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ {
+ sum += *row_i * *col_k;
+ row_i += M;
+ col_k ++;
+ }
+
+ C(i,k) = sum;
+ }
+
+ }
+
+ return 0;
+}
+
+
+template <class T>
+Vector<T> matmult(const Fortran_Matrix<T> &A, const Vector<T> &x)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == x.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Vector<T> tmp(M);
+ T sum;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ sum = sum + A(i,j) * x(j);
+
+ tmp(i) = sum;
+ }
+
+ return tmp;
+}
+
+template <class T>
+inline Vector<T> operator*(const Fortran_Matrix<T> &A, const Vector<T> &x)
+{
+ return matmult(A,x);
+}
+
+template <class T>
+inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, const T &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Subscript MN = M*N;
+
+ Fortran_Matrix<T> res(M,N);
+ const T* a = A.begin();
+ T* t = res.begin();
+ T* tend = res.end();
+
+ for (t=res.begin(); t < tend; t++, a++)
+ *t = *a * x;
+
+ return res;
+}
+
+} // namespace TNT
+#endif
+// FMAT_H
diff --git a/intern/iksolver/intern/TNT/fortran.h b/intern/iksolver/intern/TNT/fortran.h
new file mode 100644
index 00000000000..4f513300588
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fortran.h
@@ -0,0 +1,99 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file to define C/Fortran conventions (Platform specific)
+
+#ifndef FORTRAN_H
+#define FORTRAN_H
+
+// help map between C/C++ data types and Fortran types
+
+typedef int Fortran_integer;
+typedef float Fortran_float;
+typedef double Fortran_double;
+
+
+typedef Fortran_double *fda_; // (in/out) double precision array
+typedef const Fortran_double *cfda_; // (in) double precsion array
+
+typedef Fortran_double *fd_; // (in/out) single double precision
+typedef const Fortran_double *cfd_; // (in) single double precision
+
+typedef Fortran_float *ffa_; // (in/out) float precision array
+typedef const Fortran_float *cffa_; // (in) float precsion array
+
+typedef Fortran_float *ff_; // (in/out) single float precision
+typedef const Fortran_float *cff_; // (in) single float precision
+
+typedef Fortran_integer *fia_; // (in/out) single integer array
+typedef const Fortran_integer *cfia_; // (in) single integer array
+
+typedef Fortran_integer *fi_; // (in/out) single integer
+typedef const Fortran_integer *cfi_; // (in) single integer
+
+typedef char *fch_; // (in/out) single character
+typedef char *cfch_; // (in) single character
+
+
+
+#ifndef TNT_SUBSCRIPT_TYPE
+#define TNT_SUBSCRIPT_TYPE TNT::Fortran_integer
+#endif
+
+
+#endif
+// FORTRAN_H
diff --git a/intern/iksolver/intern/TNT/fspvec.h b/intern/iksolver/intern/TNT/fspvec.h
new file mode 100644
index 00000000000..b8dde35b6c6
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fspvec.h
@@ -0,0 +1,200 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// Templated sparse vector (Fortran conventions).
+// Used primarily to interface with Fortran sparse matrix libaries.
+// (CANNOT BE USED AS AN STL CONTAINER.)
+
+#ifndef FSPVEC_H
+#define FSPVEC_H
+
+#include "tnt.h"
+#include "vec.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+
+using namespace std;
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Sparse_Vector
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ Vector<T> val_;
+ Vector<Subscript> index_;
+ Subscript dim_; // prescribed dimension
+
+
+ public:
+
+ // size and shape information
+
+ Subscript dim() const { return dim_; }
+ Subscript num_nonzeros() const { return val_.dim(); }
+
+ // access
+
+ T& val(Subscript i) { return val_(i); }
+ const T& val(Subscript i) const { return val_(i); }
+
+ Subscript &index(Subscript i) { return index_(i); }
+ const Subscript &index(Subscript i) const { return index_(i); }
+
+ // constructors
+
+ Fortran_Sparse_Vector() : val_(), index_(), dim_(0) {};
+ Fortran_Sparse_Vector(Subscript N, Subscript nz) : val_(nz),
+ index_(nz), dim_(N) {};
+ Fortran_Sparse_Vector(Subscript N, Subscript nz, const T *values,
+ const Subscript *indices): val_(nz, values), index_(nz, indices),
+ dim_(N) {}
+
+ Fortran_Sparse_Vector(const Fortran_Sparse_Vector<T> &S):
+ val_(S.val_), index_(S.index_), dim_(S.dim_) {}
+
+ // initialize from string, e.g.
+ //
+ // Fortran_Sparse_Vector<T> A(N, 2, "1.0 2.1", "1 3");
+ //
+ Fortran_Sparse_Vector(Subscript N, Subscript nz, char *v,
+ char *ind) : val_(nz, v), index_(nz, ind), dim_(N) {}
+
+ // assignments
+
+ Fortran_Sparse_Vector<T> & newsize(Subscript N, Subscript nz)
+ {
+ val_.newsize(nz);
+ index_.newsize(nz);
+ dim_ = N;
+ return *this;
+ }
+
+ Fortran_Sparse_Vector<T> & operator=( const Fortran_Sparse_Vector<T> &A)
+ {
+ val_ = A.val_;
+ index_ = A.index_;
+ dim_ = A.dim_;
+
+ return *this;
+ }
+
+ // methods
+
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+ostream& operator<<(ostream &s, const Fortran_Sparse_Vector<T> &A)
+{
+ // output format is : N nz val1 ind1 val2 ind2 ...
+ Subscript nz=A.num_nonzeros();
+
+ s << A.dim() << " " << nz << endl;
+
+ for (Subscript i=1; i<=nz; i++)
+ s << A.val(i) << " " << A.index(i) << endl;
+ s << endl;
+
+ return s;
+}
+
+
+template <class T>
+istream& operator>>(istream &s, Fortran_Sparse_Vector<T> &A)
+{
+ // output format is : N nz val1 ind1 val2 ind2 ...
+
+ Subscript N;
+ Subscript nz;
+
+ s >> N >> nz;
+
+ A.newsize(N, nz);
+
+ for (Subscript i=1; i<=nz; i++)
+ s >> A.val(i) >> A.index(i);
+
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
+// FSPVEC_H
diff --git a/intern/iksolver/intern/TNT/index.h b/intern/iksolver/intern/TNT/index.h
new file mode 100644
index 00000000000..885545d11b5
--- /dev/null
+++ b/intern/iksolver/intern/TNT/index.h
@@ -0,0 +1,115 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Vector/Matrix/Array Index Module
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include "subscript.h"
+
+namespace TNT
+{
+
+class Index1D
+{
+ Subscript lbound_;
+ Subscript ubound_;
+
+ public:
+
+ Subscript lbound() const { return lbound_; }
+ Subscript ubound() const { return ubound_; }
+
+ Index1D(const Index1D &D) : lbound_(D.lbound_), ubound_(D.ubound_) {}
+ Index1D(Subscript i1, Subscript i2) : lbound_(i1), ubound_(i2) {}
+
+ Index1D & operator=(const Index1D &D)
+ {
+ lbound_ = D.lbound_;
+ ubound_ = D.ubound_;
+ return *this;
+ }
+
+};
+
+inline Index1D operator+(const Index1D &D, Subscript i)
+{
+ return Index1D(i+D.lbound(), i+D.ubound());
+}
+
+inline Index1D operator+(Subscript i, const Index1D &D)
+{
+ return Index1D(i+D.lbound(), i+D.ubound());
+}
+
+
+
+inline Index1D operator-(Index1D &D, Subscript i)
+{
+ return Index1D(D.lbound()-i, D.ubound()-i);
+}
+
+inline Index1D operator-(Subscript i, Index1D &D)
+{
+ return Index1D(i-D.lbound(), i-D.ubound());
+}
+
+} // namespace TNT
+
+#endif
+
diff --git a/intern/iksolver/intern/TNT/lapack.h b/intern/iksolver/intern/TNT/lapack.h
new file mode 100644
index 00000000000..d3556a96071
--- /dev/null
+++ b/intern/iksolver/intern/TNT/lapack.h
@@ -0,0 +1,225 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file for Fortran Lapack
+
+#ifndef LAPACK_H
+#define LAPACK_H
+
+// This file incomplete and included here to only demonstrate the
+// basic framework for linking with the Fortran Lapack routines.
+
+#include "fortran.h"
+#include "vec.h"
+#include "fmat.h"
+
+
+#define F77_DGESV dgesv_
+#define F77_DGELS dgels_
+#define F77_DSYEV dsyev_
+#define F77_DGEEV dgeev_
+
+extern "C"
+{
+
+ // linear equations (general) using LU factorizaiton
+ //
+ void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
+ fia_ ipiv, fda_ b, cfi_ ldb, fi_ info);
+
+ // solve linear least squares using QR or LU factorization
+ //
+ void F77_DGELS(cfch_ trans, cfi_ M,
+ cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, fda_ B, cfi_ ldb, fda_ work,
+ cfi_ lwork, fi_ info);
+
+ // solve symmetric eigenvalues
+ //
+ void F77_DSYEV( cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
+ fda_ W, fda_ work, cfi_ lwork, fi_ info);
+
+ // solve unsymmetric eigenvalues
+ //
+ void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
+ fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
+ cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
+
+}
+
+// solve linear equations using LU factorization
+
+using namespace TNT;
+
+Vector<double> Lapack_LU_linear_solve(const Fortran_Matrix<double> &A,
+ const Vector<double> &b)
+{
+ const Fortran_integer one=1;
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Fortran_Matrix<double> Tmp(A);
+ Vector<double> x(b);
+ Vector<Fortran_integer> index(M);
+ Fortran_integer info = 0;
+
+ F77_DGESV(&N, &one, &Tmp(1,1), &M, &index(1), &x(1), &M, &info);
+
+ if (info != 0) return Vector<double>(0);
+ else
+ return x;
+}
+
+// solve linear least squares problem using QR factorization
+//
+Vector<double> Lapack_LLS_QR_linear_solve(const Fortran_Matrix<double> &A,
+ const Vector<double> &b)
+{
+ const Fortran_integer one=1;
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Fortran_Matrix<double> Tmp(A);
+ Vector<double> x(b);
+ Fortran_integer info = 0;
+
+ char transp = 'N';
+ Fortran_integer lwork = 5 * (M+N); // temporary work space
+ Vector<double> work(lwork);
+
+ F77_DGELS(&transp, &M, &N, &one, &Tmp(1,1), &M, &x(1), &M, &work(1),
+ &lwork, &info);
+
+ if (info != 0) return Vector<double>(0);
+ else
+ return x;
+}
+
+// *********************** Eigenvalue problems *******************
+
+// solve symmetric eigenvalue problem (eigenvalues only)
+//
+Vector<double> Upper_symmetric_eigenvalue_solve(const Fortran_Matrix<double> &A)
+{
+ char jobz = 'N';
+ char uplo = 'U';
+ Subscript N = A.num_rows();
+
+ assert(N == A.num_cols());
+
+ Vector<double> eigvals(N);
+ Fortran_integer worksize = 3*N;
+ Fortran_integer info = 0;
+ Vector<double> work(worksize);
+ Fortran_Matrix<double> Tmp = A;
+
+ F77_DSYEV(&jobz, &uplo, &N, &Tmp(1,1), &N, eigvals.begin(), work.begin(),
+ &worksize, &info);
+
+ if (info != 0) return Vector<double>();
+ else
+ return eigvals;
+}
+
+
+// solve unsymmetric eigenvalue problems
+//
+int eigenvalue_solve(const Fortran_Matrix<double> &A,
+ Vector<double> &wr, Vector<double> &wi)
+{
+ char jobvl = 'N';
+ char jobvr = 'N';
+
+ Fortran_integer N = A.num_rows();
+
+
+ assert(N == A.num_cols());
+
+ if (N<1) return 1;
+
+ Fortran_Matrix<double> vl(1,N); /* should be NxN ? **** */
+ Fortran_Matrix<double> vr(1,N);
+ Fortran_integer one = 1;
+
+ Fortran_integer worksize = 5*N;
+ Fortran_integer info = 0;
+ Vector<double> work(worksize, 0.0);
+ Fortran_Matrix<double> Tmp = A;
+
+ wr.newsize(N);
+ wi.newsize(N);
+
+// void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
+// fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
+// cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
+
+ F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(wr(1)),
+ &(wi(1)), &(vl(1,1)), &one, &(vr(1,1)), &one,
+ &(work(1)), &worksize, &info);
+
+ return (info==0 ? 0: 1);
+}
+
+
+
+
+
+#endif
+// LAPACK_H
+
+
+
+
diff --git a/intern/iksolver/intern/TNT/lu.h b/intern/iksolver/intern/TNT/lu.h
new file mode 100644
index 00000000000..b86027aa386
--- /dev/null
+++ b/intern/iksolver/intern/TNT/lu.h
@@ -0,0 +1,236 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef LU_H
+#define LU_H
+
+// Solve system of linear equations Ax = b.
+//
+// Typical usage:
+//
+// Matrix(double) A;
+// Vector(Subscript) ipiv;
+// Vector(double) b;
+//
+// 1) LU_Factor(A,ipiv);
+// 2) LU_Solve(A,ipiv,b);
+//
+// Now b has the solution x. Note that both A and b
+// are overwritten. If these values need to be preserved,
+// one can make temporary copies, as in
+//
+// O) Matrix(double) T = A;
+// 1) LU_Factor(T,ipiv);
+// 1a) Vector(double) x=b;
+// 2) LU_Solve(T,ipiv,x);
+//
+// See details below.
+//
+
+
+// for fabs()
+//
+#include <cmath>
+
+// right-looking LU factorization algorithm (unblocked)
+//
+// Factors matrix A into lower and upper triangular matrices
+// (L and U respectively) in solving the linear equation Ax=b.
+//
+//
+// Args:
+//
+// A (input/output) Matrix(1:n, 1:n) In input, matrix to be
+// factored. On output, overwritten with lower and
+// upper triangular factors.
+//
+// indx (output) Vector(1:n) Pivot vector. Describes how
+// the rows of A were reordered to increase
+// numerical stability.
+//
+// Return value:
+//
+// int (0 if successful, 1 otherwise)
+//
+//
+
+
+namespace TNT
+{
+
+template <class MaTRiX, class VecToRSubscript>
+int LU_factor( MaTRiX &A, VecToRSubscript &indx)
+{
+ assert(A.lbound() == 1); // currently for 1-offset
+ assert(indx.lbound() == 1); // vectors and matrices
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ if (M == 0 || N==0) return 0;
+ if (indx.dim() != M)
+ indx.newsize(M);
+
+ Subscript i=0,j=0,k=0;
+ Subscript jp=0;
+
+ typename MaTRiX::element_type t;
+
+ Subscript minMN = (M < N ? M : N) ; // min(M,N);
+
+ for (j=1; j<= minMN; j++)
+ {
+
+ // find pivot in column j and test for singularity.
+
+ jp = j;
+ t = fabs(A(j,j));
+ for (i=j+1; i<=M; i++)
+ if ( fabs(A(i,j)) > t)
+ {
+ jp = i;
+ t = fabs(A(i,j));
+ }
+
+ indx(j) = jp;
+
+ // jp now has the index of maximum element
+ // of column j, below the diagonal
+
+ if ( A(jp,j) == 0 )
+ return 1; // factorization failed because of zero pivot
+
+
+ if (jp != j) // swap rows j and jp
+ for (k=1; k<=N; k++)
+ {
+ t = A(j,k);
+ A(j,k) = A(jp,k);
+ A(jp,k) =t;
+ }
+
+ if (j<M) // compute elements j+1:M of jth column
+ {
+ // note A(j,j), was A(jp,p) previously which was
+ // guarranteed not to be zero (Label #1)
+ //
+ typename MaTRiX::element_type recp = 1.0 / A(j,j);
+
+ for (k=j+1; k<=M; k++)
+ A(k,j) *= recp;
+ }
+
+
+ if (j < minMN)
+ {
+ // rank-1 update to trailing submatrix: E = E - x*y;
+ //
+ // E is the region A(j+1:M, j+1:N)
+ // x is the column vector A(j+1:M,j)
+ // y is row vector A(j,j+1:N)
+
+ Subscript ii,jj;
+
+ for (ii=j+1; ii<=M; ii++)
+ for (jj=j+1; jj<=N; jj++)
+ A(ii,jj) -= A(ii,j)*A(j,jj);
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+template <class MaTRiX, class VecToR, class VecToRSubscripts>
+int LU_solve(const MaTRiX &A, const VecToRSubscripts &indx, VecToR &b)
+{
+ assert(A.lbound() == 1); // currently for 1-offset
+ assert(indx.lbound() == 1); // vectors and matrices
+ assert(b.lbound() == 1);
+
+ Subscript i,ii=0,ip,j;
+ Subscript n = b.dim();
+ typename MaTRiX::element_type sum = 0.0;
+
+ for (i=1;i<=n;i++)
+ {
+ ip=indx(i);
+ sum=b(ip);
+ b(ip)=b(i);
+ if (ii)
+ for (j=ii;j<=i-1;j++)
+ sum -= A(i,j)*b(j);
+ else if (sum) ii=i;
+ b(i)=sum;
+ }
+ for (i=n;i>=1;i--)
+ {
+ sum=b(i);
+ for (j=i+1;j<=n;j++)
+ sum -= A(i,j)*b(j);
+ b(i)=sum/A(i,i);
+ }
+
+ return 0;
+}
+
+} // namespace TNT
+
+#endif
+// LU_H
diff --git a/intern/iksolver/intern/TNT/qr.h b/intern/iksolver/intern/TNT/qr.h
new file mode 100644
index 00000000000..074551896b9
--- /dev/null
+++ b/intern/iksolver/intern/TNT/qr.h
@@ -0,0 +1,261 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef QR_H
+#define QR_H
+
+// Classical QR factorization example, based on Stewart[1973].
+//
+//
+// This algorithm computes the factorization of a matrix A
+// into a product of an orthognal matrix (Q) and an upper triangular
+// matrix (R), such that QR = A.
+//
+// Parameters:
+//
+// A (in): Matrix(1:N, 1:N)
+//
+// Q (output): Matrix(1:N, 1:N), collection of Householder
+// column vectors Q1, Q2, ... QN
+//
+// R (output): upper triangular Matrix(1:N, 1:N)
+//
+// Returns:
+//
+// 0 if successful, 1 if A is detected to be singular
+//
+
+
+#include <cmath> //for sqrt() & fabs()
+#include "tntmath.h" // for sign()
+
+// Classical QR factorization, based on Stewart[1973].
+//
+//
+// This algorithm computes the factorization of a matrix A
+// into a product of an orthognal matrix (Q) and an upper triangular
+// matrix (R), such that QR = A.
+//
+// Parameters:
+//
+// A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents
+// the matrix to be factored.
+//
+// On output, Q and R is encoded in the same Matrix(1:N,1:N)
+// in the following manner:
+//
+// R is contained in the upper triangular section of A,
+// except that R's main diagonal is in D. The lower
+// triangular section of A represents Q, where each
+// column j is the vector Qj = I - uj*uj'/pi_j.
+//
+// C (output): vector of Pi[j]
+// D (output): main diagonal of R, i.e. D(i) is R(i,i)
+//
+// Returns:
+//
+// 0 if successful, 1 if A is detected to be singular
+//
+
+namespace TNT
+{
+
+template <class MaTRiX, class Vector>
+int QR_factor(MaTRiX &A, Vector& C, Vector &D)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(C.lbound() == 1); // 1-based arrays and vectors
+ assert(D.lbound() == 1);
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M == N); // make sure A is square
+
+ Subscript i,j,k;
+ typename MaTRiX::element_type eta, sigma, sum;
+
+ // adjust the shape of C and D, if needed...
+
+ if (N != C.size()) C.newsize(N);
+ if (N != D.size()) D.newsize(N);
+
+ for (k=1; k<N; k++)
+ {
+ // eta = max |M(i,k)|, for k <= i <= n
+ //
+ eta = 0;
+ for (i=k; i<=N; i++)
+ {
+ double absA = fabs(A(i,k));
+ eta = ( absA > eta ? absA : eta );
+ }
+
+ if (eta == 0) // matrix is singular
+ {
+ cerr << "QR: k=" << k << "\n";
+ return 1;
+ }
+
+ // form Qk and premiltiply M by it
+ //
+ for(i=k; i<=N; i++)
+ A(i,k) = A(i,k) / eta;
+
+ sum = 0;
+ for (i=k; i<=N; i++)
+ sum = sum + A(i,k)*A(i,k);
+ sigma = sign(A(k,k)) * sqrt(sum);
+
+
+ A(k,k) = A(k,k) + sigma;
+ C(k) = sigma * A(k,k);
+ D(k) = -eta * sigma;
+
+ for (j=k+1; j<=N; j++)
+ {
+ sum = 0;
+ for (i=k; i<=N; i++)
+ sum = sum + A(i,k)*A(i,j);
+ sum = sum / C(k);
+
+ for (i=k; i<=N; i++)
+ A(i,j) = A(i,j) - sum * A(i,k);
+ }
+
+ D(N) = A(N,N);
+ }
+
+ return 0;
+}
+
+// modified form of upper triangular solve, except that the main diagonal
+// of R (upper portion of A) is in D.
+//
+template <class MaTRiX, class Vector>
+int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(D.lbound() == 1); // 1-based arrays and vectors
+ assert(b.lbound() == 1);
+
+ Subscript i,j;
+ Subscript N = A.num_rows();
+
+ assert(N == A.num_cols());
+ assert(N == D.dim());
+ assert(N == b.dim());
+
+ typename MaTRiX::element_type sum;
+
+ if (D(N) == 0)
+ return 1;
+
+ b(N) = b(N) /
+ D(N);
+
+ for (i=N-1; i>=1; i--)
+ {
+ if (D(i) == 0)
+ return 1;
+ sum = 0;
+ for (j=i+1; j<=N; j++)
+ sum = sum + A(i,j)*b(j);
+ b(i) = ( b(i) - sum ) /
+ D(i);
+ }
+
+ return 0;
+}
+
+
+template <class MaTRiX, class Vector>
+int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d,
+ Vector &b)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(c.lbound() == 1); // 1-based arrays and vectors
+ assert(d.lbound() == 1);
+
+ Subscript N=A.num_rows();
+
+ assert(N == A.num_cols());
+ assert(N == c.dim());
+ assert(N == d.dim());
+ assert(N == b.dim());
+
+ Subscript i,j;
+ typename MaTRiX::element_type sum, tau;
+
+ for (j=1; j<N; j++)
+ {
+ // form Q'*b
+ sum = 0;
+ for (i=j; i<=N; i++)
+ sum = sum + A(i,j)*b(i);
+ if (c(j) == 0)
+ return 1;
+ tau = sum / c(j);
+ for (i=j; i<=N; i++)
+ b(i) = b(i) - tau * A(i,j);
+ }
+ return R_solve(A, d, b); // solve Rx = Q'b
+}
+
+} // namespace TNT
+
+#endif
+// QR_H
diff --git a/intern/iksolver/intern/TNT/region1d.h b/intern/iksolver/intern/TNT/region1d.h
new file mode 100644
index 00000000000..0307ee02c39
--- /dev/null
+++ b/intern/iksolver/intern/TNT/region1d.h
@@ -0,0 +1,403 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+
+#ifndef REGION1D_H
+#define REGION1D_H
+
+
+#include "subscript.h"
+#include "index.h"
+#include <iostream>
+#include <cassert>
+
+namespace TNT
+{
+
+template <class Array1D>
+class const_Region1D;
+
+template <class Array1D>
+class Region1D
+{
+ protected:
+
+ Array1D & A_;
+ Subscript offset_; // 0-based
+ Subscript dim_;
+
+ typedef typename Array1D::element_type T;
+
+ public:
+ const Array1D & array() const { return A_; }
+
+ Subscript offset() const { return offset_;}
+ Subscript dim() const { return dim_; }
+
+ Subscript offset(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i== TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+
+ Region1D(Array1D &A, Subscript i1, Subscript i2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(i1 <= i2);
+#endif
+ offset_ = i1 - TNT_BASE_OFFSET;
+ dim_ = i2-i1 + 1;
+ }
+
+ Region1D(Array1D &A, const Index1D &I) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <=I.lbound());
+ assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ offset_ = I.lbound() - TNT_BASE_OFFSET;
+ dim_ = I.ubound() - I.lbound() + 1;
+ }
+
+ Region1D(Region1D<Array1D> &A, Subscript i1, Subscript i2) :
+ A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
+ assert(i1 <= i2);
+#endif
+ // (old-offset) (new-offset)
+ //
+ offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
+ dim_ = i2-i1 + 1;
+ }
+
+ Region1D<Array1D> operator()(Subscript i1, Subscript i2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1);
+ assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
+ assert(i1 <= i2);
+#endif
+ // offset_ is 0-based, so no need for
+ // ( - TNT_BASE_OFFSET)
+ //
+ return Region1D<Array1D>(A_, i1+offset_,
+ offset_ + i2);
+ }
+
+
+ Region1D<Array1D> operator()(const Index1D &I)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET<=I.lbound());
+ assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ return Region1D<Array1D>(A_, I.lbound()+offset_,
+ offset_ + I.ubound());
+ }
+
+
+
+
+ T & operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+ const T & operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+
+ Region1D<Array1D> & operator=(const Region1D<Array1D> &R)
+ {
+ // make sure both sides conform
+ assert(dim() == R.dim());
+
+ Subscript N = dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+ }
+
+
+
+ Region1D<Array1D> & operator=(const const_Region1D<Array1D> &R)
+ {
+ // make sure both sides conform
+ assert(dim() == R.dim());
+
+ Subscript N = dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+
+ }
+
+
+ Region1D<Array1D> & operator=(const T& t)
+ {
+ Subscript N=dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<= iend; i++)
+ (*this)(i) = t;
+
+ return *this;
+
+ }
+
+
+ Region1D<Array1D> & operator=(const Array1D &R)
+ {
+ // make sure both sides conform
+ Subscript N = dim();
+ assert(dim() == R.dim());
+
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+
+ }
+
+};
+
+template <class Array1D>
+std::ostream& operator<<(std::ostream &s, Region1D<Array1D> &A)
+{
+ Subscript N=A.dim();
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = N - 1 + TNT_BASE_OFFSET;
+
+ for (Subscript i=istart; i<=iend; i++)
+ s << A(i) << endl;
+
+ return s;
+}
+
+
+/* --------- class const_Region1D ------------ */
+
+template <class Array1D>
+class const_Region1D
+{
+ protected:
+
+ const Array1D & A_;
+ Subscript offset_; // 0-based
+ Subscript dim_;
+ typedef typename Array1D::element_type T;
+
+ public:
+ const Array1D & array() const { return A_; }
+
+ Subscript offset() const { return offset_;}
+ Subscript dim() const { return dim_; }
+
+ Subscript offset(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i== TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+
+ const_Region1D(const Array1D &A, Subscript i1, Subscript i2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(i1 <= i2);
+#endif
+ offset_ = i1 - TNT_BASE_OFFSET;
+ dim_ = i2-i1 + 1;
+ }
+
+ const_Region1D(const Array1D &A, const Index1D &I) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <=I.lbound());
+ assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ offset_ = I.lbound() - TNT_BASE_OFFSET;
+ dim_ = I.ubound() - I.lbound() + 1;
+ }
+
+ const_Region1D(const_Region1D<Array1D> &A, Subscript i1, Subscript i2) :
+ A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
+ assert(i1 <= i2);
+#endif
+ // (old-offset) (new-offset)
+ //
+ offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
+ dim_ = i2-i1 + 1;
+ }
+
+ const_Region1D<Array1D> operator()(Subscript i1, Subscript i2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1);
+ assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
+ assert(i1 <= i2);
+#endif
+ // offset_ is 0-based, so no need for
+ // ( - TNT_BASE_OFFSET)
+ //
+ return const_Region1D<Array1D>(A_, i1+offset_,
+ offset_ + i2);
+ }
+
+
+ const_Region1D<Array1D> operator()(const Index1D &I)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET<=I.lbound());
+ assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ return const_Region1D<Array1D>(A_, I.lbound()+offset_,
+ offset_ + I.ubound());
+ }
+
+
+ const T & operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+
+
+
+};
+
+template <class Array1D>
+std::ostream& operator<<(std::ostream &s, const_Region1D<Array1D> &A)
+{
+ Subscript N=A.dim();
+
+ for (Subscript i=1; i<=N; i++)
+ s << A(i) << endl;
+
+ return s;
+}
+
+
+} // namespace TNT
+
+#endif
+// const_Region1D_H
diff --git a/intern/iksolver/intern/TNT/region2d.h b/intern/iksolver/intern/TNT/region2d.h
new file mode 100644
index 00000000000..d612dfdaa79
--- /dev/null
+++ b/intern/iksolver/intern/TNT/region2d.h
@@ -0,0 +1,499 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// 2D Regions for arrays and matrices
+
+#ifndef REGION2D_H
+#define REGION2D_H
+
+#include "index.h"
+#include <iostream>
+#include <cassert>
+
+namespace TNT
+{
+
+template <class Array2D>
+class const_Region2D;
+
+
+template <class Array2D>
+class Region2D
+{
+ protected:
+
+ Array2D & A_;
+ Subscript offset_[2]; // 0-offset internally
+ Subscript dim_[2];
+
+ public:
+ typedef typename Array2D::value_type T;
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Array2D & array() { return A_; }
+ const Array2D & array() const { return A_; }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return dim_[0]; }
+ Subscript num_cols() const { return dim_[1]; }
+ Subscript offset(Subscript i) const // 1-offset
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+#endif
+ return offset_[i-A_.lbound()];
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+#endif
+ return dim_[i-A_.lbound()];
+ }
+
+
+
+ Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1,
+ Subscript j2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A.lbound() <= i1);
+ assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= j1);
+ assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+
+
+ offset_[0] = i1-A.lbound();
+ offset_[1] = j1-A.lbound();
+ dim_[0] = i2-i1+1;
+ dim_[1] = j2-j1+1;
+ }
+
+ Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( A.lbound() <= I.lbound());
+ assert( I.ubound()<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= J.lbound());
+ assert( J.ubound() <= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+
+ offset_[0] = I.lbound()-A.lbound();
+ offset_[1] = J.lbound()-A.lbound();
+ dim_[0] = I.ubound() - I.lbound() + 1;
+ dim_[1] = J.ubound() - J.lbound() + 1;
+ }
+
+ Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) : A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A.lbound() <= i1);
+ assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= j1);
+ assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+ offset_[0] = (i1 - A.lbound()) + A.offset_[0];
+ offset_[1] = (j1 - A.lbound()) + A.offset_[1];
+ dim_[0] = i2-i1 + 1;
+ dim_[1] = j2-j1+1;
+ }
+
+ Region2D<Array2D> operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A_.lbound() <= i1);
+ assert( i2<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j1);
+ assert( j2<= dim_[1] + A_.lbound()-1 );
+#endif
+ return Region2D<Array2D>(A_,
+ i1+offset_[0], offset_[0] + i2,
+ j1+offset_[1], offset_[1] + j2);
+ }
+
+
+ Region2D<Array2D> operator()(const Index1D &I,
+ const Index1D &J)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( A_.lbound() <= I.lbound());
+ assert( I.ubound()<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= J.lbound());
+ assert( J.ubound() <= dim_[1] + A_.lbound()-1 );
+#endif
+
+ return Region2D<Array2D>(A_, I.lbound()+offset_[0],
+ offset_[0] + I.ubound(), offset_[1]+J.lbound(),
+ offset_[1] + J.ubound());
+ }
+
+ inline T & operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j);
+ assert( j<= dim_[1] + A_.lbound()-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+ inline const T & operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j);
+ assert( j<= dim_[1] + A_.lbound()-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+
+ Region2D<Array2D> & operator=(const Region2D<Array2D> &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const const_Region2D<Array2D> &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const Array2D &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const T &scalar)
+ {
+ Subscript start = lbound();
+ Subscript Mend = lbound() + num_rows() - 1;
+ Subscript Nend = lbound() + num_cols() - 1;
+
+
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = scalar;
+
+ return *this;
+ }
+
+};
+
+//************************
+
+template <class Array2D>
+class const_Region2D
+{
+ protected:
+
+ const Array2D & A_;
+ Subscript offset_[2]; // 0-offset internally
+ Subscript dim_[2];
+
+ public:
+ typedef typename Array2D::value_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ const Array2D & array() const { return A_; }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return dim_[0]; }
+ Subscript num_cols() const { return dim_[1]; }
+ Subscript offset(Subscript i) const // 1-offset
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+#endif
+ return offset_[i-TNT_BASE_OFFSET];
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+#endif
+ return dim_[i-TNT_BASE_OFFSET];
+ }
+
+
+ const_Region2D(const Array2D &A, Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+
+ offset_[0] = i1-TNT_BASE_OFFSET;
+ offset_[1] = j1-TNT_BASE_OFFSET;
+ dim_[0] = i2-i1+1;
+ dim_[1] = j2-j1+1;
+ }
+
+ const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J)
+ : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( TNT_BASE_OFFSET <= I.lbound());
+ assert( I.ubound()<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= J.lbound());
+ assert( J.ubound() <= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+
+ offset_[0] = I.lbound()-TNT_BASE_OFFSET;
+ offset_[1] = J.lbound()-TNT_BASE_OFFSET;
+ dim_[0] = I.ubound() - I.lbound() + 1;
+ dim_[1] = J.ubound() - J.lbound() + 1;
+ }
+
+
+ const_Region2D(const_Region2D<Array2D> &A, Subscript i1,
+ Subscript i2,
+ Subscript j1, Subscript j2) : A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+ offset_[0] = (i1 - TNT_BASE_OFFSET) + A.offset_[0];
+ offset_[1] = (j1 - TNT_BASE_OFFSET) + A.offset_[1];
+ dim_[0] = i2-i1 + 1;
+ dim_[1] = j2-j1+1;
+ }
+
+ const_Region2D<Array2D> operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= dim_[0] + TNT_BASE_OFFSET-1 );
+#endif
+ return const_Region2D<Array2D>(A_,
+ i1+offset_[0], offset_[0] + i2,
+ j1+offset_[1], offset_[1] + j2);
+ }
+
+
+ const_Region2D<Array2D> operator()(const Index1D &I,
+ const Index1D &J)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( TNT_BASE_OFFSET <= I.lbound());
+ assert( I.ubound()<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= J.lbound());
+ assert( J.ubound() <= dim_[1] + TNT_BASE_OFFSET-1 );
+#endif
+
+ return const_Region2D<Array2D>(A_, I.lbound()+offset_[0],
+ offset_[0] + I.ubound(), offset_[1]+J.lbound(),
+ offset_[1] + J.ubound());
+ }
+
+
+ inline const T & operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j);
+ assert( j<= dim_[1] + TNT_BASE_OFFSET-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+};
+
+
+// ************** std::ostream algorithms *******************************
+
+template <class Array2D>
+std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A)
+{
+ Subscript start = A.lbound();
+ Subscript Mend=A.lbound()+ A.num_rows() - 1;
+ Subscript Nend=A.lbound() + A.num_cols() - 1;
+
+
+ s << A.num_rows() << " " << A.num_cols() << "\n";
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class Array2D>
+std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A)
+{
+ Subscript start = A.lbound();
+ Subscript Mend=A.lbound()+ A.num_rows() - 1;
+ Subscript Nend=A.lbound() + A.num_cols() - 1;
+
+
+ s << A.num_rows() << " " << A.num_cols() << "\n";
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+
+}
+
+} // namespace TNT
+
+#endif
+// REGION2D_H
diff --git a/intern/iksolver/intern/TNT/stopwatch.h b/intern/iksolver/intern/TNT/stopwatch.h
new file mode 100644
index 00000000000..6079ec6f1b1
--- /dev/null
+++ b/intern/iksolver/intern/TNT/stopwatch.h
@@ -0,0 +1,115 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef STPWATCH_H
+#define STPWATCH_H
+
+// for clock() and CLOCKS_PER_SEC
+#include <ctime>
+
+namespace TNT
+{
+
+/* Simple stopwatch object:
+
+ void start() : start timing
+ double stop() : stop timing
+ void reset() : set elapsed time to 0.0
+ double read() : read elapsed time (in seconds)
+
+*/
+
+inline double seconds(void)
+{
+ static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+ return ( (double) clock() ) * secs_per_tick;
+}
+
+
+class stopwatch {
+ private:
+ int running;
+ double last_time;
+ double total;
+
+ public:
+ stopwatch() : running(0), last_time(0.0), total(0.0) {}
+ void reset() { running = 0; last_time = 0.0; total=0.0; }
+ void start() { if (!running) { last_time = seconds(); running = 1;}}
+ double stop() { if (running)
+ {
+ total += seconds() - last_time;
+ running = 0;
+ }
+ return total;
+ }
+ double read() { if (running)
+ {
+ total+= seconds() - last_time;
+ last_time = seconds();
+ }
+ return total;
+ }
+
+};
+
+} // namespace TNT
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/TNT/subscript.h b/intern/iksolver/intern/TNT/subscript.h
new file mode 100644
index 00000000000..4728a79a168
--- /dev/null
+++ b/intern/iksolver/intern/TNT/subscript.h
@@ -0,0 +1,90 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef SUBSCRPT_H
+#define SUBSCRPT_H
+
+
+//---------------------------------------------------------------------
+// This definition describes the default TNT data type used for
+// indexing into TNT matrices and vectors. The data type should
+// be wide enough to index into large arrays. It defaults to an
+// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE,
+// e.g.
+//
+// g++ -DTNT_SUBSCRIPT_TYPE='unsigned int' ...
+//
+//---------------------------------------------------------------------
+//
+
+#ifndef TNT_SUBSCRIPT_TYPE
+#define TNT_SUBSCRIPT_TYPE int
+#endif
+
+namespace TNT
+{
+ typedef TNT_SUBSCRIPT_TYPE Subscript;
+}
+
+
+// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the
+// first elements. This offset is left as a macro for future
+// purposes, but should not be changed in the current release.
+//
+//
+#define TNT_BASE_OFFSET (1)
+
+#endif
diff --git a/intern/iksolver/intern/TNT/svd.h b/intern/iksolver/intern/TNT/svd.h
new file mode 100644
index 00000000000..9be2d98bd9f
--- /dev/null
+++ b/intern/iksolver/intern/TNT/svd.h
@@ -0,0 +1,507 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef SVD_H
+
+#define SVD_H
+
+// Compute the Single Value Decomposition of an arbitrary matrix A
+// That is compute the 3 matrices U,W,V with U column orthogonal (m,n)
+// ,W a diagonal matrix and V an orthogonal square matrix s.t.
+// A = U.W.Vt. From this decomposition it is trivial to compute the
+// inverse of A as Ainv = V.Winv.tranpose(U).
+// work_space is a temporary vector used by this class to compute
+// intermediate values during the computation of the SVD. This should
+// be of length a.num_cols. This is not checked
+
+#include "tntmath.h"
+
+namespace TNT
+{
+
+
+template <class MaTRiX, class VecToR >
+void SVD(MaTRiX &a, VecToR &w, MaTRiX &v, VecToR &work_space) {
+
+ int n = a.num_cols();
+ int m = a.num_rows();
+
+ int flag,i,its,j,jj,k,l(0),nm(0);
+ typename MaTRiX::value_type c,f,h,x,y,z;
+ typename MaTRiX::value_type anorm(0),g(0),scale(0);
+ typename MaTRiX::value_type s(0);
+
+ work_space.newsize(n);
+
+ for (i=1;i<=n;i++) {
+ l=i+1;
+ work_space(i)=scale*g;
+
+ g = (typename MaTRiX::value_type)0;
+
+ s = (typename MaTRiX::value_type)0;
+ scale = (typename MaTRiX::value_type)0;
+
+ if (i <= m) {
+ for (k=i;k<=m;k++) scale += TNT::abs(a(k,i));
+ if (scale > (typename MaTRiX::value_type)0) {
+ for (k=i;k<=m;k++) {
+ a(k,i) /= scale;
+ s += a(k,i)*a(k,i);
+ }
+ f=a(i,i);
+ g = -TNT::sign(sqrt(s),f);
+ h=f*g-s;
+ a(i,i)=f-g;
+ if (i != n) {
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=i;k<=m;k++) s += a(k,i)*a(k,j);
+ f=s/h;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ }
+ for (k=i;k<=m;k++) a(k,i) *= scale;
+ }
+ }
+ w(i)=scale*g;
+ g = (typename MaTRiX::value_type)0;
+ s = (typename MaTRiX::value_type)0;
+ scale = (typename MaTRiX::value_type)0;
+ if (i <= m && i != n) {
+ for (k=l;k<=n;k++) scale += TNT::abs(a(i,k));
+ if (scale > (typename MaTRiX::value_type)0) {
+ for (k=l;k<=n;k++) {
+ a(i,k) /= scale;
+ s += a(i,k)*a(i,k);
+ }
+ f=a(i,l);
+ g = -TNT::sign(sqrt(s),f);
+ h=f*g-s;
+ a(i,l)=f-g;
+ for (k=l;k<=n;k++) work_space(k)=a(i,k)/h;
+ if (i != m) {
+ for (j=l;j<=m;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=n;k++) s += a(j,k)*a(i,k);
+ for (k=l;k<=n;k++) a(j,k) += s*work_space(k);
+ }
+ }
+ for (k=l;k<=n;k++) a(i,k) *= scale;
+ }
+ }
+ anorm=TNT::max(anorm,(TNT::abs(w(i))+TNT::abs(work_space(i))));
+ }
+ for (i=n;i>=1;i--) {
+ if (i < n) {
+ if (g != (typename MaTRiX::value_type)0) {
+ for (j=l;j<=n;j++)
+ v(j,i)=(a(i,j)/a(i,l))/g;
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=n;k++) s += a(i,k)*v(k,j);
+ for (k=l;k<=n;k++) v(k,j) += s*v(k,i);
+ }
+ }
+ for (j=l;j<=n;j++) v(i,j)=v(j,i)= (typename MaTRiX::value_type)0;
+ }
+ v(i,i)= (typename MaTRiX::value_type)1;
+ g=work_space(i);
+ l=i;
+ }
+ for (i=n;i>=1;i--) {
+ l=i+1;
+ g=w(i);
+ if (i < n) {
+ for (j=l;j<=n;j++) a(i,j)= (typename MaTRiX::value_type)0;
+ }
+ if (g != (typename MaTRiX::value_type)0) {
+ g= ((typename MaTRiX::value_type)1)/g;
+ if (i != n) {
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=m;k++) s += a(k,i)*a(k,j);
+ f=(s/a(i,i))*g;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ }
+ for (j=i;j<=m;j++) a(j,i) *= g;
+ } else {
+ for (j=i;j<=m;j++) a(j,i)= (typename MaTRiX::value_type)0;
+ }
+ ++a(i,i);
+ }
+ for (k=n;k>=1;k--) {
+ for (its=1;its<=30;its++) {
+ flag=1;
+ for (l=k;l>=1;l--) {
+ nm=l-1;
+ if (TNT::abs(work_space(l))+anorm == anorm) {
+ flag=0;
+ break;
+ }
+ if (TNT::abs(w(nm))+anorm == anorm) break;
+ }
+ if (flag) {
+ c= (typename MaTRiX::value_type)0;
+ s= (typename MaTRiX::value_type)1;
+ for (i=l;i<=k;i++) {
+ f=s*work_space(i);
+ if (TNT::abs(f)+anorm != anorm) {
+ g=w(i);
+ h= (typename MaTRiX::value_type)TNT::pythag(float(f),float(g));
+ w(i)=h;
+ h= ((typename MaTRiX::value_type)1)/h;
+ c=g*h;
+ s=(-f*h);
+ for (j=1;j<=m;j++) {
+ y=a(j,nm);
+ z=a(j,i);
+ a(j,nm)=y*c+z*s;
+ a(j,i)=z*c-y*s;
+ }
+ }
+ }
+ }
+ z=w(k);
+ if (l == k) {
+ if (z < (typename MaTRiX::value_type)0) {
+ w(k) = -z;
+ for (j=1;j<=n;j++) v(j,k)=(-v(j,k));
+ }
+ break;
+ }
+
+
+#if 1
+ if (its == 30)
+ {
+ TNTException an_exception;
+ an_exception.i = 0;
+ throw an_exception;
+
+ return ;
+ assert(false);
+ }
+#endif
+ x=w(l);
+ nm=k-1;
+ y=w(nm);
+ g=work_space(nm);
+ h=work_space(k);
+ f=((y-z)*(y+z)+(g-h)*(g+h))/(((typename MaTRiX::value_type)2)*h*y);
+ g=(typename MaTRiX::value_type)TNT::pythag(float(f), float(1));
+ f=((x-z)*(x+z)+h*((y/(f+TNT::sign(g,f)))-h))/x;
+ c = (typename MaTRiX::value_type)1;
+ s = (typename MaTRiX::value_type)1;
+ for (j=l;j<=nm;j++) {
+ i=j+1;
+ g=work_space(i);
+ y=w(i);
+ h=s*g;
+ g=c*g;
+ z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h));
+ work_space(j)=z;
+ c=f/z;
+ s=h/z;
+ f=x*c+g*s;
+ g=g*c-x*s;
+ h=y*s;
+ y=y*c;
+ for (jj=1;jj<=n;jj++) {
+ x=v(jj,j);
+ z=v(jj,i);
+ v(jj,j)=x*c+z*s;
+ v(jj,i)=z*c-x*s;
+ }
+ z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h));
+ w(j)=z;
+ if (z != (typename MaTRiX::value_type)0) {
+ z= ((typename MaTRiX::value_type)1)/z;
+ c=f*z;
+ s=h*z;
+ }
+ f=(c*g)+(s*y);
+ x=(c*y)-(s*g);
+ for (jj=1;jj<=m;jj++) {
+ y=a(jj,j);
+ z=a(jj,i);
+ a(jj,j)=y*c+z*s;
+ a(jj,i)=z*c-y*s;
+ }
+ }
+ work_space(l)= (typename MaTRiX::value_type)0;
+ work_space(k)=f;
+ w(k)=x;
+ }
+ }
+};
+
+
+
+// A is replaced by the column orthogonal matrix U
+
+
+template <class MaTRiX, class VecToR >
+void SVD_a( MaTRiX &a, VecToR &w, MaTRiX &v) {
+
+ int n = a.num_cols();
+ int m = a.num_rows();
+
+ int flag,i,its,j,jj,k,l,nm;
+ typename MaTRiX::value_type anorm,c,f,g,h,s,scale,x,y,z;
+
+ VecToR work_space;
+ work_space.newsize(n);
+
+ g = scale = anorm = 0.0;
+
+ for (i=1;i <=n;i++) {
+ l = i+1;
+ work_space(i) = scale*g;
+ g = s=scale=0.0;
+
+ if (i <= m) {
+ for(k=i; k<=m; k++) scale += abs(a(k,i));
+
+ if (scale) {
+ for (k = i; k <=m ; k++) {
+ a(k,i) /= scale;
+ s += a(k,i)*a(k,i);
+ }
+ f = a(i,i);
+ g = -sign(sqrt(s),f);
+ h = f*g -s;
+ a(i,i) = f-g;
+
+ for (j = l; j <=n; j++) {
+ for (s = 0.0,k =i;k<=m;k++) s += a(k,i)*a(k,j);
+ f = s/h;
+ for (k = i; k <= m; k++) a(k,j) += f*a(k,i);
+ }
+ for (k = i; k <=m;k++) a(k,i) *= scale;
+ }
+ }
+
+ w(i) = scale*g;
+ g = s = scale = 0.0;
+
+ if (i <=m && i != n) {
+ for (k = l; k <=n;k++) scale += abs(a(i,k));
+ if (scale) {
+ for(k = l;k <=n;k++) {
+ a(i,k) /= scale;
+ s += a(i,k) * a(i,k);
+ }
+
+ f = a(i,l);
+ g = -sign(sqrt(s),f);
+ h= f*g -s;
+ a(i,l) = f-g;
+ for(k=l;k<=n;k++) work_space(k) = a(i,k)/h;
+ for (j=l;j<=m;j++) {
+ for(s = 0.0,k=l;k<=n;k++) s+= a(j,k)*a(i,k);
+ for(k=l;k<=n;k++) a(j,k) += s*work_space(k);
+ }
+ for(k=l;k<=n;k++) a(i,k)*=scale;
+ }
+ }
+ anorm = max(anorm,(abs(w(i)) + abs(work_space(i))));
+ }
+ for (i=n;i>=1;i--) {
+ if (i <n) {
+ if (g) {
+ for(j=l;j<=n;j++) v(j,i) = (a(i,j)/a(i,l))/g;
+ for(j=l;j<=n;j++) {
+ for(s=0.0,k=l;k<=n;k++) s += a(i,k)*v(k,j);
+ for(k=l; k<=n;k++) v(k,j) +=s*v(k,i);
+ }
+ }
+ for(j=l;j <=n;j++) v(i,j) = v(j,i) = 0.0;
+ }
+ v(i,i) = 1.0;
+ g = work_space(i);
+ l = i;
+ }
+
+ for (i = min(m,n);i>=1;i--) {
+ l = i+1;
+ g = w(i);
+ for (j=l;j <=n;j++) a(i,j) = 0.0;
+ if (g) {
+ g = 1.0/g;
+ for (j=l;j<=n;j++) {
+ for (s = 0.0,k=l;k<=m;k++) s += a(k,i)*a(k,j);
+ f = (s/a(i,i))*g;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ for (j=i;j<=m;j++) a(j,i)*=g;
+ } else {
+ for (j=i;j<=m;j++) a(j,i) = 0.0;
+ }
+ ++a(i,i);
+ }
+
+ for (k=n;k>=1;k--) {
+ for (its=1;its<=30;its++) {
+ flag=1;
+ for(l=k;l>=1;l--) {
+ nm = l-1;
+ if (abs(work_space(l)) + anorm == anorm) {
+ flag = 0;
+ break;
+ }
+ if (abs(w(nm)) + anorm == anorm) break;
+ }
+ if (flag) {
+ c = 0.0;
+ s = 1.0;
+ for (i=l;i<=k;i++) {
+ f = s*work_space(i);
+ work_space(i) = c*work_space(i);
+ if (abs(f) +anorm == anorm) break;
+ g = w(i);
+ h = pythag(f,g);
+ w(i) = h;
+ h = 1.0/h;
+ c = g*h;
+ s = -f*h;
+ for (j=1;j<=m;j++) {
+ y= a(j,nm);
+ z=a(j,i);
+ a(j,nm) = y*c + z*s;
+ a(j,i) = z*c - y*s;
+ }
+ }
+ }
+ z=w(k);
+ if (l==k) {
+ if (z <0.0) {
+ w(k) = -z;
+ for (j=1;j<=n;j++) v(j,k) = -v(j,k);
+ }
+ break;
+ }
+
+ if (its == 30) assert(false);
+
+ x=w(l);
+ nm=k-1;
+ y=w(nm);
+ g=work_space(nm);
+ h=work_space(k);
+
+ f= ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y);
+ g = pythag(f,1.0);
+ f= ((x-z)*(x+z) + h*((y/(f + sign(g,f)))-h))/x;
+ c=s=1.0;
+
+ for (j=l;j<=nm;j++) {
+ i=j+1;
+ g = work_space(i);
+ y=w(i);
+ h=s*g;
+ g=c*g;
+ z=pythag(f,h);
+ work_space(j) = z;
+ c=f/z;
+ s=h/z;
+ f=x*c + g*s;
+ g= g*c - x*s;
+ h=y*s;
+ y*=c;
+ for(jj=1;jj<=n;jj++) {
+ x=v(jj,j);
+ z=v(jj,i);
+ v(jj,j) = x*c + z*s;
+ v(jj,i) = z*c- x*s;
+ }
+ z=pythag(f,h);
+ w(j)=z;
+ if(z) {
+ z = 1.0/z;
+ c=f*z;
+ s=h*z;
+ }
+ f=c*g + s*y;
+ x= c*y-s*g;
+
+ for(jj=1;jj<=m;jj++) {
+ y=a(jj,j);
+ z=a(jj,i);
+ a(jj,j) = y*c+z*s;
+ a(jj,i) = z*c - y*s;
+ }
+ }
+
+ work_space(l) = 0.0;
+ work_space(k) = f;
+ w(k) = x;
+ }
+ }
+}
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/TNT/tnt.h b/intern/iksolver/intern/TNT/tnt.h
new file mode 100644
index 00000000000..df27079f87a
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tnt.h
@@ -0,0 +1,127 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef TNT_H
+#define TNT_H
+
+//---------------------------------------------------------------------
+// tnt.h TNT general header file. Defines default types
+// and conventions.
+//---------------------------------------------------------------------
+
+//---------------------------------------------------------------------
+// Include current version
+//---------------------------------------------------------------------
+#include "version.h"
+
+//---------------------------------------------------------------------
+// Define the data type used for matrix and vector Subscripts.
+// This will default to "int", but it can be overriden at compile time,
+// e.g.
+//
+// g++ -DTNT_SUBSCRIPT_TYPE='unsinged long' ...
+//
+// See subscript.h for details.
+//---------------------------------------------------------------------
+
+#include "subscript.h"
+
+
+
+//---------------------------------------------------------------------
+// Define this macro if you want TNT to ensure all refernces
+// are within the bounds of the array. This encurs a run-time
+// overhead, of course, but is recommended while developing
+// code. It can be turned off for production runs.
+//
+// #define TNT_BOUNDS_CHECK
+//---------------------------------------------------------------------
+//
+#define TNT_BOUNDS_CHECK
+#ifdef TNT_NO_BOUNDS_CHECK
+#undef TNT_BOUNDS_CHECK
+#endif
+
+//---------------------------------------------------------------------
+// Define this macro if you want to utilize matrix and vector
+// regions. This is typically on, but you can save some
+// compilation time by turning it off. If you do this and
+// attempt to use regions you will get an error message.
+//
+// #define TNT_USE_REGIONS
+//---------------------------------------------------------------------
+//
+#define TNT_USE_REGIONS
+
+//---------------------------------------------------------------------
+//
+//---------------------------------------------------------------------
+// if your system doesn't have abs() min(), and max() uncoment the following
+//---------------------------------------------------------------------
+//
+//
+//#define __NEED_ABS_MIN_MAX_
+
+#include "tntmath.h"
+
+
+
+
+
+
+
+#endif
+// TNT_H
diff --git a/intern/iksolver/intern/TNT/tntmath.h b/intern/iksolver/intern/TNT/tntmath.h
new file mode 100644
index 00000000000..3342ff7f5c6
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tntmath.h
@@ -0,0 +1,177 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file for scalar math functions
+
+#ifndef TNTMATH_H
+#define TNTMATH_H
+
+// conventional functions required by several matrix algorithms
+
+
+
+namespace TNT
+{
+
+struct TNTException {
+ int i;
+};
+
+
+inline double abs(double t)
+{
+ return ( t > 0 ? t : -t);
+}
+
+inline double min(double a, double b)
+{
+ return (a < b ? a : b);
+}
+
+inline double max(double a, double b)
+{
+ return (a > b ? a : b);
+}
+
+inline float abs(float t)
+{
+ return ( t > 0 ? t : -t);
+}
+
+inline float min(float a, float b)
+{
+ return (a < b ? a : b);
+}
+
+inline int min(int a,int b) {
+ return (a < b ? a : b);
+}
+
+
+inline float max(float a, float b)
+{
+ return (a > b ? a : b);
+}
+
+inline double sign(double a)
+{
+ return (a > 0 ? 1.0 : -1.0);
+}
+
+inline double sign(double a,double b) {
+ return (b >= 0.0 ? TNT::abs(a) : -TNT::abs(a));
+}
+
+inline float sign(float a,float b) {
+ return (b >= 0.0f ? TNT::abs(a) : -TNT::abs(a));
+}
+
+inline float sign(float a)
+{
+ return (a > 0.0 ? 1.0f : -1.0f);
+}
+
+inline float pythag(float a, float b)
+{
+ float absa,absb;
+ absa = abs(a);
+ absb = abs(b);
+
+ if (absa > absb) {
+ float sqr = absb/absa;
+ sqr *= sqr;
+ return absa * float(sqrt(1 + sqr));
+ } else {
+ if (absb > float(0)) {
+ float sqr = absa/absb;
+ sqr *= sqr;
+ return absb * float(sqrt(1 + sqr));
+ } else {
+ return float(0);
+ }
+ }
+}
+
+inline double pythag(double a, double b)
+{
+ double absa,absb;
+ absa = abs(a);
+ absb = abs(b);
+
+ if (absa > absb) {
+ double sqr = absb/absa;
+ sqr *= sqr;
+ return absa * double(sqrt(1 + sqr));
+ } else {
+
+ if (absb > double(0)) {
+ double sqr = absa/absb;
+ sqr *= sqr;
+ return absb * double(sqrt(1 + sqr));
+ } else {
+ return double(0);
+ }
+ }
+}
+
+
+} /* namespace TNT */
+
+
+#endif
+/* TNTMATH_H */
+
diff --git a/intern/iksolver/intern/TNT/tntreqs.h b/intern/iksolver/intern/TNT/tntreqs.h
new file mode 100644
index 00000000000..c935902554e
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tntreqs.h
@@ -0,0 +1,102 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// The requirements for a bare-bones vector class:
+//
+//
+// o) must have 0-based [] indexing for const and
+// non-const objects (i.e. operator[] defined)
+//
+// o) must have size() method to denote the number of
+// elements
+// o) must clean up after itself when destructed
+// (i.e. no memory leaks)
+//
+// -) must have begin() and end() methods (The begin()
+// method is necessary, because relying on
+// &v_[0] may not work on a empty vector (i.e. v_ is NULL.)
+//
+// o) must be templated
+// o) must have X::value_type defined to be the types of elements
+// o) must have X::X(const &x) copy constructor (by *value*)
+// o) must have X::X(int N) constructor to N-length vector
+// (NOTE: this constructor need *NOT* initalize elements)
+//
+// -) must have X::X(int N, T scalar) constructor to initalize
+// elements to value of "scalar".
+//
+// ( removed, because valarray<> class uses (scalar, N) rather
+// than (N, scalar) )
+// -) must have X::X(int N, const T* scalars) constructor to copy from
+// any C linear array
+//
+// ( removed, because of same reverse order of valarray<> )
+//
+// o) must have assignment A=B, by value
+//
+// NOTE: this class is *NOT* meant to be derived from,
+// so its methods (particularly indexing) need not be
+// declared virtual.
+//
+//
+// Some things it *DOES NOT* need to do are
+//
+// o) bounds checking
+// o) array referencing (e.g. reference counting)
+// o) support () indexing
+// o) I/O
+//
diff --git a/intern/iksolver/intern/TNT/transv.h b/intern/iksolver/intern/TNT/transv.h
new file mode 100644
index 00000000000..47730350acc
--- /dev/null
+++ b/intern/iksolver/intern/TNT/transv.h
@@ -0,0 +1,192 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Matrix Transpose Views
+
+#ifndef TRANSV_H
+#define TRANSV_H
+
+#include <iostream>
+#include <cassert>
+#include "vec.h"
+
+namespace TNT
+{
+
+template <class Array2D>
+class Transpose_View
+{
+ protected:
+
+ const Array2D & A_;
+
+ public:
+
+ typedef typename Array2D::element_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+
+ const Array2D & array() const { return A_; }
+ Subscript num_rows() const { return A_.num_cols();}
+ Subscript num_cols() const { return A_.num_rows();}
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= A_.lbound()+1);
+#endif
+ if (i== A_.lbound())
+ return num_rows();
+ else
+ return num_cols();
+ }
+
+
+ Transpose_View(const Transpose_View<Array2D> &A) : A_(A.A_) {};
+ Transpose_View(const Array2D &A) : A_(A) {};
+
+
+ inline const typename Array2D::element_type & operator()(
+ Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_cols() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_rows() + lbound() - 1);
+#endif
+
+ return A_(j,i);
+ }
+
+
+};
+
+template <class Matrix>
+Transpose_View<Matrix> Transpose_view(const Matrix &A)
+{
+ return Transpose_View<Matrix>(A);
+}
+
+template <class Matrix, class T>
+Vector<T> matmult(
+ const Transpose_View<Matrix> & A,
+ const Vector<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(B.dim() == N);
+
+ Vector<T> x(N);
+
+ Subscript i, j;
+ T tmp = 0;
+
+ for (i=1; i<=M; i++)
+ {
+ tmp = 0;
+ for (j=1; j<=N; j++)
+ tmp += A(i,j) * B(j);
+ x(i) = tmp;
+ }
+
+ return x;
+}
+
+template <class Matrix, class T>
+inline Vector<T> operator*(const Transpose_View<Matrix> & A, const Vector<T> &B)
+{
+ return matmult(A,B);
+}
+
+
+template <class Matrix>
+std::ostream& operator<<(std::ostream &s, const Transpose_View<Matrix> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() - 1;
+ Subscript Nend = N + A.lbound() - 1;
+
+ s << M << " " << N << endl;
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
+// TRANSV_H
diff --git a/intern/iksolver/intern/TNT/triang.h b/intern/iksolver/intern/TNT/triang.h
new file mode 100644
index 00000000000..883caf138f7
--- /dev/null
+++ b/intern/iksolver/intern/TNT/triang.h
@@ -0,0 +1,670 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Triangular Matrices (Views and Adpators)
+
+#ifndef TRIANG_H
+#define TRIANG_H
+
+// default to use lower-triangular portions of arrays
+// for symmetric matrices.
+
+namespace TNT
+{
+
+template <class MaTRiX>
+class LowerTriangularView
+{
+ protected:
+
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero_;
+
+ public:
+
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef const typename MaTRiX::element_type element_type;
+ typedef const typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ LowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i<j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i<j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+#ifdef TNT_USE_REGIONS
+
+ typedef const_Region2D< LowerTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(/*const*/ Index1D &I,
+ /*const*/ Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+
+
+
+#endif
+// TNT_USE_REGIONS
+
+};
+
+
+/* *********** Lower_triangular_view() algorithms ****************** */
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename MaTRiX::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=start; j<=i; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum;
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+template <class MaTRiX>
+class UnitLowerTriangularView
+{
+ protected:
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero;
+ const typename MaTRiX::element_type one;
+
+ public:
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef typename MaTRiX::element_type element_type;
+ typedef typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript lbound() const { return 1; }
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UnitLowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+ assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
+#endif
+ if (i>j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+#endif
+ if (i>j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // These are the "index-aware" features
+
+ typedef const_Region2D< UnitLowerTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(/*const*/ Index1D &I,
+ /*const*/ Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+#endif
+// TNT_USE_REGIONS
+};
+
+template <class MaTRiX>
+LowerTriangularView<MaTRiX> Lower_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return LowerTriangularView<MaTRiX>(A);
+}
+
+
+template <class MaTRiX>
+UnitLowerTriangularView<MaTRiX> Unit_lower_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UnitLowerTriangularView<MaTRiX>(A);
+}
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename MaTRiX::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=start; j<i; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum + x(i);
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+
+//********************** Algorithms *************************************
+
+
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s, const LowerTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ const UnitLowerTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+
+
+// ******************* Upper Triangular Section **************************
+
+template <class MaTRiX>
+class UpperTriangularView
+{
+ protected:
+
+
+ /*const*/ MaTRiX &A_;
+ /*const*/ typename MaTRiX::element_type zero_;
+
+ public:
+
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef /*const*/ typename MaTRiX::element_type element_type;
+ typedef /*const*/ typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i>j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i>j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+#ifdef TNT_USE_REGIONS
+
+ typedef const_Region2D< UpperTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(const Index1D &I,
+ const Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+
+
+
+#endif
+// TNT_USE_REGIONS
+
+};
+
+
+/* *********** Upper_triangular_view() algorithms ****************** */
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename VecToR::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=i; j<=N; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum;
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+template <class MaTRiX>
+class UnitUpperTriangularView
+{
+ protected:
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero;
+ const typename MaTRiX::element_type one;
+
+ public:
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef typename MaTRiX::element_type element_type;
+ typedef typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript lbound() const { return 1; }
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UnitUpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+ assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
+#endif
+ if (i<j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+#endif
+ if (i<j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // These are the "index-aware" features
+
+ typedef const_Region2D< UnitUpperTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(const Index1D &I,
+ const Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+#endif
+// TNT_USE_REGIONS
+};
+
+template <class MaTRiX>
+UpperTriangularView<MaTRiX> Upper_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UpperTriangularView<MaTRiX>(A);
+}
+
+
+template <class MaTRiX>
+UnitUpperTriangularView<MaTRiX> Unit_upper_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UnitUpperTriangularView<MaTRiX>(A);
+}
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename VecToR::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = x(i);
+ for (j=i+1; j<=N; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum + x(i);
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+
+//********************** Algorithms *************************************
+
+
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ /*const*/ UpperTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ /*const*/ UnitUpperTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+} // namespace TNT
+
+
+
+
+
+#endif
+//TRIANG_H
+
diff --git a/intern/iksolver/intern/TNT/trisolve.h b/intern/iksolver/intern/TNT/trisolve.h
new file mode 100644
index 00000000000..6a4f6e1a5b3
--- /dev/null
+++ b/intern/iksolver/intern/TNT/trisolve.h
@@ -0,0 +1,216 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Triangular Solves
+
+#ifndef TRISLV_H
+#define TRISLV_H
+
+
+#include "triang.h"
+
+namespace TNT
+{
+
+template <class MaTriX, class VecToR>
+VecToR Lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=1; i<=N; i++)
+ {
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = (b(i) - tmp)/ A(i,i);
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR Unit_lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=1; i<=N; i++)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = b(i) - tmp;
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ LowerTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Lower_triangular_solve(A, b);
+}
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UnitLowerTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Unit_lower_triangular_solve(A, b);
+}
+
+
+
+//********************** Upper triangular section ****************
+
+template <class MaTriX, class VecToR>
+VecToR Upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=N; i>=1; i--)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=i+1; j<=N; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = (b(i) - tmp)/ A(i,i);
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR Unit_upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=N; i>=1; i--)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=i+1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = b(i) - tmp;
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UpperTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Upper_triangular_solve(A, b);
+}
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UnitUpperTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Unit_upper_triangular_solve(A, b);
+}
+
+
+} // namespace TNT
+
+#endif
+// TRISLV_H
diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h
new file mode 100644
index 00000000000..beb034ce315
--- /dev/null
+++ b/intern/iksolver/intern/TNT/vec.h
@@ -0,0 +1,535 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// Basic TNT numerical vector (0-based [i] AND 1-based (i) indexing )
+//
+
+#ifndef VEC_H
+#define VEC_H
+
+#include "subscript.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+#include <strstream>
+
+namespace TNT
+{
+
+template <class T>
+class Vector
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ T* v_;
+ T* vm1_; // pointer adjustment for optimzied 1-offset indexing
+ Subscript n_;
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript N)
+ {
+ // adjust pointers so that they are 1-offset:
+ // v_[] is the internal contiguous array, it is still 0-offset
+ //
+ assert(v_ == NULL);
+ v_ = new T[N];
+ assert(v_ != NULL);
+ vm1_ = v_-1;
+ n_ = N;
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ delete [] (v_);
+
+ v_ = NULL;
+ vm1_ = NULL;
+ }
+
+
+ public:
+
+ // access
+
+ iterator begin() { return v_;}
+ iterator end() { return v_ + n_; }
+ const iterator begin() const { return v_;}
+ const iterator end() const { return v_ + n_; }
+
+ // destructor
+
+ ~Vector()
+ {
+ destroy();
+ }
+
+ // constructors
+
+ Vector() : v_(0), vm1_(0), n_(0) {};
+
+ Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(A.n_);
+ copy(A.v_);
+ }
+
+ Vector(Subscript N, const T& value = T()) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ set(value);
+ }
+
+ Vector(Subscript N, const T* v) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ copy(v);
+ }
+
+ Vector(Subscript N, char *s) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ std::istrstream ins(s);
+
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ ins >> v_[i];
+ }
+
+
+ // methods
+ //
+ Vector<T>& newsize(Subscript N)
+ {
+ if (n_ == N) return *this;
+
+ destroy();
+ initialize(N);
+
+ return *this;
+ }
+
+
+ // assignments
+ //
+ Vector<T>& operator=(const Vector<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Vector<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+ inline Subscript dim() const
+ {
+ return n_;
+ }
+
+ inline Subscript size() const
+ {
+ return n_;
+ }
+
+
+ inline reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= n_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline const_reference operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= n_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline reference operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < n_) ;
+#endif
+ return v_[i];
+ }
+
+ inline const_reference operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i) ;
+ assert(i < n_) ;
+#endif
+ return v_[i];
+ }
+
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Vector<T> &A)
+{
+ Subscript N=A.dim();
+
+ s << N << endl;
+
+ for (Subscript i=0; i<N; i++)
+ s << A[i] << " " << endl;
+ s << endl;
+
+ return s;
+}
+
+template <class T>
+std::istream & operator>>(std::istream &s, Vector<T> &A)
+{
+
+ Subscript N;
+
+ s >> N;
+
+ if ( !(N == A.size() ))
+ {
+ A.newsize(N);
+ }
+
+
+ for (Subscript i=0; i<N; i++)
+ s >> A[i];
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Vector<T> operator+(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] + B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator-(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] - B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator*(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] * B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator*(const Vector<T> &A,
+ const T &B)
+{
+ Subscript N = A.dim();
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] * B;
+
+ return tmp;
+}
+
+
+template <class T>
+T dot_prod(const Vector<T> &A, const Vector<T> &B)
+{
+ Subscript N = A.dim();
+ assert(N == B.dim());
+
+ Subscript i;
+ T sum = 0;
+
+ for (i=0; i<N; i++)
+ sum += A[i] * B[i];
+
+ return sum;
+}
+
+// inplace versions of the above template functions
+
+// A = A + B
+
+template <class T>
+void vectoradd(
+ Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] += B[i];
+}
+
+// same with seperate output vector
+
+template <class T>
+void vectoradd(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] + B[i];
+}
+
+// A = A - B
+
+template <class T>
+void vectorsub(
+ Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] -= B[i];
+}
+
+template <class T>
+void vectorsub(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] - B[i];
+}
+
+template <class T>
+void vectorscale(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const T &B)
+{
+ const Subscript N = A.dim();
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] * B;
+}
+
+template <class T>
+void vectorscale(
+ Vector<T> &A,
+ const T &B)
+{
+ const Subscript N = A.dim();
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] *= B;
+}
+
+
+
+
+
+} /* namespace TNT */
+
+#endif
+// VEC_H
diff --git a/intern/iksolver/intern/TNT/vecadaptor.h b/intern/iksolver/intern/TNT/vecadaptor.h
new file mode 100644
index 00000000000..337748c58bd
--- /dev/null
+++ b/intern/iksolver/intern/TNT/vecadaptor.h
@@ -0,0 +1,321 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef VECADAPTOR_H
+#define VECADAPTOR_H
+
+#include <cstdlib>
+#include <iostream>
+#include <strstream>
+#include <cassert>
+
+#include "subscript.h"
+
+#ifdef TNT_USE_REGIONS
+#include "region1d.h"
+#endif
+
+namespace TNT
+{
+
+// see "tntreq.h" for TNT requirements for underlying vector
+// class. This need NOT be the STL vector<> class, but a subset
+// that provides minimal services.
+//
+// This is a container adaptor that provides the following services.
+//
+// o) adds 1-offset operator() access ([] is always 0 offset)
+// o) adds TNT_BOUNDS_CHECK to () and []
+// o) adds initialization from strings, e.g. "1.0 2.0 3.0";
+// o) adds newsize(N) function (does not preserve previous values)
+// o) adds dim() and dim(1)
+// o) adds free() function to release memory used by vector
+// o) adds regions, e.g. A(Index(1,10)) = ...
+// o) add getVector() method to return adapted container
+// o) adds simple I/O for ostreams
+
+template <class BBVec>
+class Vector_Adaptor
+{
+
+ public:
+ typedef typename BBVec::value_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1; }
+
+ protected:
+ BBVec v_;
+ T* vm1_;
+
+ public:
+
+ Subscript size() const { return v_.size(); }
+
+ // These were removed so that the ANSI C++ valarray class
+ // would work as a possible storage container.
+ //
+ //
+ //iterator begin() { return v_.begin();}
+ //iterator begin() { return &v_[0];}
+ //
+ //iterator end() { return v_.end(); }
+ //iterator end() { return &v_[0] + v_.size(); }
+ //
+ //const_iterator begin() const { return v_.begin();}
+ //const_iterator begin() const { return &v_[0];}
+ //
+ //const_iterator end() const { return v_.end(); }
+ //const_iterator end() const { return &v_[0] + v_.size(); }
+
+ BBVec& getVector() { return v_; }
+ Subscript dim() const { return v_.size(); }
+ Subscript dim(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return (i==TNT_BASE_OFFSET ? v_.size() : 0 );
+ }
+ Vector_Adaptor() : v_() {};
+ Vector_Adaptor(const Vector_Adaptor<BBVec> &A) : v_(A.v_)
+ {
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+
+ }
+
+ Vector_Adaptor(Subscript N, /*const*/ char *s) : v_(N)
+ {
+ istrstream ins(s);
+ for (Subscript i=0; i<N; i++)
+ ins >> v_[i] ;
+
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ };
+
+ Vector_Adaptor(Subscript N, const T& value = T()) : v_(N)
+ {
+ for (Subscript i=0; i<N; i++)
+ v_[i] = value;
+
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+
+ Vector_Adaptor(Subscript N, const T* values) : v_(N)
+ {
+ for (Subscript i=0; i<N; i++)
+ v_[i] = values[i];
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+ Vector_Adaptor(const BBVec & A) : v_(A)
+ {
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+
+ // NOTE: this assumes that BBVec(0) constructor creates an
+ // null vector that does not take up space... It would be
+ // great to require that BBVec have a corresponding free()
+ // function, but in particular STL vectors do not.
+ //
+ Vector_Adaptor<BBVec>& free()
+ {
+ return *this = Vector_Adaptor<BBVec>(0);
+ }
+
+ Vector_Adaptor<BBVec>& operator=(const Vector_Adaptor<BBVec> &A)
+ {
+ v_ = A.v_ ;
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ return *this;
+ }
+
+ Vector_Adaptor<BBVec>& newsize(Subscript N)
+ {
+ // NOTE: this is not as efficient as it could be
+ // but to retain compatiblity with STL interface
+ // we cannot assume underlying implementation
+ // has a newsize() function.
+
+ return *this = Vector_Adaptor<BBVec>(N);
+
+ }
+
+ Vector_Adaptor<BBVec>& operator=(const T &a)
+ {
+ Subscript i;
+ Subscript N = v_.size();
+ for (i=0; i<N; i++)
+ v_[i] = a;
+
+ return *this;
+ }
+
+ Vector_Adaptor<BBVec>& resize(Subscript N)
+ {
+ if (N == size()) return *this;
+
+ Vector_Adaptor<BBVec> tmp(N);
+ Subscript n = (N < size() ? N : size()); // min(N, size());
+ Subscript i;
+
+ for (i=0; i<n; i++)
+ tmp[i] = v_[i];
+
+
+ return (*this = tmp);
+
+ }
+
+
+ reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=dim());
+#endif
+ return vm1_[i];
+ }
+
+ const_reference operator()(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=dim());
+#endif
+ return vm1_[i];
+ }
+
+ reference operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i<dim());
+#endif
+ return v_[i];
+ }
+
+ const_reference operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i<dim());
+#endif
+ return v_[i];
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // "index-aware" features, all of these are 1-based offsets
+
+ typedef Region1D<Vector_Adaptor<BBVec> > Region;
+
+ typedef const_Region1D< Vector_Adaptor<BBVec> > const_Region;
+
+ Region operator()(const Index1D &I)
+ { return Region(*this, I); }
+
+ Region operator()(const Subscript i1, Subscript i2)
+ { return Region(*this, i1, i2); }
+
+ const_Region operator()(const Index1D &I) const
+ { return const_Region(*this, I); }
+
+ const_Region operator()(const Subscript i1, Subscript i2) const
+ { return const_Region(*this, i1, i2); }
+#endif
+// TNT_USE_REGIONS
+
+
+};
+
+#include <iostream>
+
+template <class BBVec>
+std::ostream& operator<<(std::ostream &s, const Vector_Adaptor<BBVec> &A)
+{
+ Subscript M=A.size();
+
+ s << M << endl;
+ for (Subscript i=1; i<=M; i++)
+ s << A(i) << endl;
+ return s;
+}
+
+template <class BBVec>
+std::istream& operator>>(std::istream &s, Vector_Adaptor<BBVec> &A)
+{
+ Subscript N;
+
+ s >> N;
+
+ A.resize(N);
+
+ for (Subscript i=1; i<=N; i++)
+ s >> A(i);
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
diff --git a/intern/iksolver/intern/TNT/version.h b/intern/iksolver/intern/TNT/version.h
new file mode 100644
index 00000000000..c2759e0ce44
--- /dev/null
+++ b/intern/iksolver/intern/TNT/version.h
@@ -0,0 +1,52 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+// Template Numerical Toolkit (TNT) for Linear Algebra
+
+//
+// BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+// Please see http://math.nist.gov/tnt for updates
+//
+// R. Pozo
+// Mathematical and Computational Sciences Division
+// National Institute of Standards and Technology
+
+
+#ifndef TNT_VERSION_H
+#define TNT_VERSION_H
+
+
+#define TNT_MAJOR_VERSION '0'
+#define TNT_MINOR_VERSION '9'
+#define TNT_SUBMINOR_VERSION '4'
+#define TNT_VERSION_STRING "0.9.4"
+
+#endif
diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsp b/intern/iksolver/make/msvc_6_0/iksolver.dsp
new file mode 100644
index 00000000000..fb12812b7a7
--- /dev/null
+++ b/intern/iksolver/make/msvc_6_0/iksolver.dsp
@@ -0,0 +1,244 @@
+# Microsoft Developer Studio Project File - Name="iksolver" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=iksolver - 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 "iksolver.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 "iksolver.mak" CFG="iksolver - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "iksolver - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "iksolver - 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)" == "iksolver - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# 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 /Ob2 /I "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\lib\windows\release\iksolver_rmtd.lib"
+
+!ELSEIF "$(CFG)" == "iksolver - 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 "Debug"
+# PROP Intermediate_Dir "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 "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\lib\windows\debug\iksolver_dmtd.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "iksolver - Win32 Release"
+# Name "iksolver - Win32 Debug"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "TNT"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\cholesky.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\cmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fcscmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fortran.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fspvec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\index.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\lapack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\lu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\qr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\region1d.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\region2d.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\stopwatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\subscript.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\svd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tnt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tntmath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tntreqs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\transv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\triang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\trisolve.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\vec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\vecadaptor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\version.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QChain.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QChain.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QJacobianSolver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QJacobianSolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSegment.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSegment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSolver_Class.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_Solver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_ExpMap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_ExpMap.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\extern\IK_solver.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsw b/intern/iksolver/make/msvc_6_0/iksolver.dsw
new file mode 100644
index 00000000000..90a123d9ce8
--- /dev/null
+++ b/intern/iksolver/make/msvc_6_0/iksolver.dsw
@@ -0,0 +1,35 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "iksolver"=.\iksolver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
+
+
+
+
+
+
diff --git a/intern/iksolver/test/Makefile b/intern/iksolver/test/Makefile
new file mode 100644
index 00000000000..f59e487add0
--- /dev/null
+++ b/intern/iksolver/test/Makefile
@@ -0,0 +1,67 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver test makefile.
+#
+
+LIBNAME = iksolver
+SOURCEDIR = intern/$(LIBNAME)/test
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+DIRS = ik_glut_test
+
+include nan_subdirs.mk
+
+include nan_link.mk
+
+LIBS = $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/intern/$(DEBUG_DIR)libintern.a
+LIBS += $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/common/$(DEBUG_DIR)libcommon.a
+LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libiksolver.a
+
+SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
+ LLIBS = -L/usr/X11R6/lib -lglut -pthread
+endif
+
+all debug:: $(LIBS) $(DIR)/$(DEBUG_DIR)iksolvertest
+
+$(DIR)/$(DEBUG_DIR)iksolvertest:
+ @echo "****> linking $@ in $(DIR)"
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)iksolvertest $(LIBS) $(SLIBS) $(LLIBS) $(DADD)
+
+clean::
+ $(RM) $(DIR)/iksolvertest $(DIR)/debug/iksolvertest
+
+test:: all
+ $(DIR)/iksolvertest
+
diff --git a/intern/iksolver/test/ik_glut_test/Makefile b/intern/iksolver/test/ik_glut_test/Makefile
new file mode 100644
index 00000000000..4b47af16599
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver subdir bouncer. Pure waste.
+#
+
+include nan_definitions.mk
+
+LIBNAME = ik_glut_test
+SOURCEDIR = intern/iksolver/test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = common intern
+
+include nan_subdirs.mk
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
new file mode 100644
index 00000000000..40c6a4a95c9
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
@@ -0,0 +1,95 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GlutDrawer.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutDrawManager> GlutDrawManager::m_s_instance = MEM_SmartPtr<GlutDrawManager>();
+
+ GlutDrawManager *
+GlutDrawManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutDrawManager();
+ }
+
+ return m_s_instance;
+}
+
+
+// this is the function you should pass to glut
+
+ void
+GlutDrawManager::
+Draw(
+){
+ GlutDrawManager *manager = GlutDrawManager::Instance();
+
+ if (manager->m_drawer != NULL) {
+ manager->m_drawer->Draw();
+ }
+}
+
+ void
+GlutDrawManager::
+InstallDrawer(
+ GlutDrawer * drawer
+){
+
+ MT_assert(m_drawer == NULL);
+ m_drawer = drawer;
+}
+
+ void
+GlutDrawManager::
+ReleaseDrawer(
+){
+ m_drawer = NULL;
+}
+
+
+GlutDrawManager::
+~GlutDrawManager(
+){
+
+ delete(m_drawer);
+}
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
new file mode 100644
index 00000000000..7e56a02dd47
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
@@ -0,0 +1,100 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_GlutDrawer
+
+#define NAN_INCLUDED_GlutDrawer
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+// So pissed off with Glut callback stuff
+// that is impossible to call objects unless they are global
+
+// inherit from GlutDrawer and installl the drawer in the singleton
+// class GlutDrawManager.
+
+class GlutDrawer {
+public :
+
+ virtual
+ void
+ Draw(
+ )= 0;
+
+ virtual
+ ~GlutDrawer(
+ ){};
+};
+
+class GlutDrawManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutDrawManager *
+ Instance(
+ );
+
+ // this is the function you should pass to glut
+
+ static
+ void
+ Draw(
+ );
+
+ void
+ InstallDrawer(
+ GlutDrawer *
+ );
+
+ void
+ ReleaseDrawer(
+ );
+
+ ~GlutDrawManager(
+ );
+
+private :
+
+ GlutDrawManager (
+ ) :
+ m_drawer (0)
+ {
+ };
+
+ GlutDrawer * m_drawer;
+
+ static MEM_SmartPtr<GlutDrawManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
new file mode 100644
index 00000000000..0d1d52b542d
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
@@ -0,0 +1,89 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GlutKeyboardManager.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutKeyboardManager> GlutKeyboardManager::m_s_instance = MEM_SmartPtr<GlutKeyboardManager>();
+
+ GlutKeyboardManager *
+GlutKeyboardManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutKeyboardManager();
+ }
+
+ return m_s_instance;
+}
+
+
+// this is the function you should pass to glut
+
+ void
+GlutKeyboardManager::
+HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+){
+ GlutKeyboardManager *manager = GlutKeyboardManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->HandleKeyboard(key,x,y);
+ }
+}
+
+ void
+GlutKeyboardManager::
+InstallHandler(
+ GlutKeyboardHandler * handler
+){
+
+ MT_assert(m_handler == NULL);
+ m_handler = handler;
+}
+
+ void
+GlutKeyboardManager::
+ReleaseHandler(
+){
+ m_handler = NULL;
+}
+
+
+GlutKeyboardManager::
+~GlutKeyboardManager(
+){
+
+ delete(m_handler);
+} \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
new file mode 100644
index 00000000000..39174b5ff1a
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
@@ -0,0 +1,106 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_GlutKeyboardManager
+
+#define NAN_INCLUDED_GlutKeyboardManager
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+// So pissed off with Glut callback stuff
+// that is impossible to call objects unless they are global
+
+// inherit from GlutKeyboardHandler and installl the drawer in the singleton
+// class GlutKeyboardManager.
+
+class GlutKeyboardHandler : public MEM_NonCopyable {
+public :
+
+ virtual
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ )= 0;
+
+ virtual
+ ~GlutKeyboardHandler(
+ ){};
+};
+
+class GlutKeyboardManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutKeyboardManager *
+ Instance(
+ );
+
+ // this is the function you should pass to glut
+
+ static
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ );
+
+ void
+ InstallHandler(
+ GlutKeyboardHandler *
+ );
+
+ void
+ ReleaseHandler(
+ );
+
+ ~GlutKeyboardManager(
+ );
+
+private :
+
+ GlutKeyboardManager (
+ ) :
+ m_handler (0)
+ {
+ };
+
+ GlutKeyboardHandler * m_handler;
+
+ static MEM_SmartPtr<GlutKeyboardManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
new file mode 100644
index 00000000000..57f4a65327e
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
@@ -0,0 +1,104 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "GlutMouseManager.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutMouseManager> GlutMouseManager::m_s_instance = MEM_SmartPtr<GlutMouseManager>();
+
+
+ GlutMouseManager *
+GlutMouseManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutMouseManager();
+ }
+
+ return m_s_instance;
+}
+
+// these are the functions you should pass to GLUT
+
+ void
+GlutMouseManager::
+Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+){
+ GlutMouseManager *manager = GlutMouseManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->Mouse(button,state,x,y);
+ }
+}
+
+ void
+GlutMouseManager::
+Motion(
+ int x,
+ int y
+){
+ GlutMouseManager *manager = GlutMouseManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->Motion(x,y);
+ }
+}
+
+ void
+GlutMouseManager::
+InstallHandler(
+ GlutMouseHandler *handler
+){
+
+ MT_assert(m_handler == NULL);
+ m_handler = handler;
+}
+
+ void
+GlutMouseManager::
+ReleaseHandler(
+){
+ m_handler = NULL;
+}
+
+GlutMouseManager::
+~GlutMouseManager(
+){
+
+ delete(m_handler);
+}
+
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
new file mode 100644
index 00000000000..95700bc14dd
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
@@ -0,0 +1,116 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_GlutMouseManager_h
+
+#define NAN_INCLUDED_GlutMouseManager_h
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+class GlutMouseHandler {
+public :
+
+ virtual
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ ) = 0;
+
+ virtual
+ void
+ Motion(
+ int x,
+ int y
+ ) = 0;
+
+ virtual
+ ~GlutMouseHandler(
+ ){};
+};
+
+class GlutMouseManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutMouseManager *
+ Instance(
+ );
+
+ // these are the functions you should pass to GLUT
+
+ static
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ );
+
+ static
+ void
+ Motion(
+ int x,
+ int y
+ );
+
+ void
+ InstallHandler(
+ GlutMouseHandler *
+ );
+
+ void
+ ReleaseHandler(
+ );
+
+ ~GlutMouseManager(
+ );
+
+private :
+
+ GlutMouseManager (
+ ) :
+ m_handler (0)
+ {
+ };
+
+ GlutMouseHandler * m_handler;
+
+ static MEM_SmartPtr<GlutMouseManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/Makefile b/intern/iksolver/test/ik_glut_test/common/Makefile
new file mode 100644
index 00000000000..07ad1837a7d
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/Makefile
@@ -0,0 +1,44 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver test intern Makefile
+#
+
+LIBNAME = common
+SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
new file mode 100644
index 00000000000..a164e686e37
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
@@ -0,0 +1,387 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_ChainDrawer_h
+
+#define NAN_INCLUDED_ChainDrawer_h
+
+#include "../common/GlutDrawer.h"
+#include "MyGlutMouseHandler.h"
+#include "MyGlutKeyHandler.h"
+#include "MT_Transform.h"
+#ifdef USE_QUATERNIONS
+# include "IK_Qsolver.h"
+# include "../intern/IK_QChain.h"
+# include "../intern/IK_QSolver_Class.h"
+#else
+# include "IK_solver.h"
+# include "../intern/IK_Chain.h"
+# include "../intern/IK_Solver_Class.h"
+#endif
+#include <GL/glut.h>
+
+class ChainDrawer : public GlutDrawer
+{
+public :
+ static
+ ChainDrawer *
+ New(
+ ) {
+ return new ChainDrawer();
+ }
+
+ void
+ SetMouseHandler(
+ MyGlutMouseHandler *mouse_handler
+ ) {
+ m_mouse_handler = mouse_handler;
+ }
+
+ void
+ SetKeyHandler (
+ MyGlutKeyHandler *key_handler
+ ) {
+ m_key_handler = key_handler;
+ }
+
+ void
+ SetChain(
+ IK_Chain_ExternPtr *chains,int chain_num
+ ) {
+ m_chain_num = chain_num;
+ m_chains = chains;
+ }
+
+
+ // inherited from GlutDrawer
+ void
+ Draw(
+ ) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glPopMatrix();
+ glPushMatrix();
+ glRotatef(m_mouse_handler->AngleX(), 0.0, 1.0, 0.0);
+ glRotatef(m_mouse_handler->AngleY(), 1.0, 0.0, 0.0);
+
+ DrawScene();
+ glutSwapBuffers();
+
+ }
+
+ ~ChainDrawer(
+ ){
+ // nothing to do
+ };
+
+private :
+
+ void
+ DrawScene(
+ ){
+
+ // draw a little cross at the position of the key handler
+ // coordinates
+
+ MT_Vector3 line_x(4,0,0);
+ MT_Vector3 line_y(0.0,4,0);
+ MT_Vector3 line_z(0.0,0.0,4);
+
+ MT_Vector3 cross_origin = m_mouse_handler->Position();
+ MT_Vector3 temp;
+
+ glDisable(GL_LIGHTING);
+
+
+ glBegin(GL_LINES);
+
+ glColor3f (1.0f,1.0f,1.0f);
+
+ temp = cross_origin - line_x;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_x;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ temp = cross_origin - line_y;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_y;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ temp = cross_origin - line_z;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_z;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+
+ IK_Chain_ExternPtr chain;
+
+ int chain_num;
+ for (chain_num = 0; chain_num < m_chain_num; chain_num++) {
+ chain = m_chains[chain_num];
+
+
+ IK_Segment_ExternPtr segs = chain->segments;
+ IK_Segment_ExternPtr seg_start = segs;
+ const IK_Segment_ExternPtr seg_end = segs + chain->num_segments;
+ float ogl_matrix[16];
+
+ glColor3f (0.0f,1.0f,0.0f);
+
+ MT_Vector3 previous_origin(0,0,0);
+
+ MT_Transform global_transform;
+ global_transform.setIdentity();
+
+ for (; seg_start != seg_end; ++seg_start) {
+
+ glPushMatrix();
+
+ // fill ogl_matrix with zeros
+
+ std::fill(ogl_matrix,ogl_matrix + 16,float(0));
+
+ // we have to do a bit of work here to compute the chain's
+ // bone values
+
+ // first compute all the matrices we need
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,seg_start->length,0));
+
+ MT_Matrix3x3 seg_rot(
+ seg_start->basis_change[0],seg_start->basis_change[1],seg_start->basis_change[2],
+ seg_start->basis_change[3],seg_start->basis_change[4],seg_start->basis_change[5],
+ seg_start->basis_change[6],seg_start->basis_change[7],seg_start->basis_change[8]
+ );
+
+ seg_rot.transpose();
+
+ MT_Matrix3x3 seg_pre_rot(
+ seg_start->basis[0],seg_start->basis[1],seg_start->basis[2],
+ seg_start->basis[3],seg_start->basis[4],seg_start->basis[5],
+ seg_start->basis[6],seg_start->basis[7],seg_start->basis[8]
+ );
+
+
+ MT_Transform seg_t_pre_rot(
+ MT_Point3(
+ seg_start->seg_start[0],
+ seg_start->seg_start[1],
+ seg_start->seg_start[2]
+ ),
+ seg_pre_rot
+ );
+ // start of the bone is just the current global transform
+ // multiplied by the seg_start vector
+
+
+
+ MT_Transform seg_t_rot(MT_Point3(0,0,0),seg_rot);
+ MT_Transform seg_local = seg_t_pre_rot * seg_t_rot * translation;
+
+ MT_Vector3 bone_start = global_transform *
+ MT_Point3(
+ seg_start->seg_start[0],
+ seg_start->seg_start[1],
+ seg_start->seg_start[2]
+ );
+
+
+ global_transform = global_transform * seg_local;
+
+ global_transform.getValue(ogl_matrix);
+ MT_Vector3 bone_end = global_transform.getOrigin();
+
+ glMultMatrixf(ogl_matrix);
+// glutSolidSphere(0.5,5,5);
+
+ glPopMatrix();
+
+ glDisable(GL_LIGHTING);
+
+ glBegin(GL_LINES);
+
+ // draw lines of the principle axis of the local transform
+
+ MT_Vector3 x_axis(1,0,0);
+ MT_Vector3 y_axis(0,1,0);
+ MT_Vector3 z_axis(0,0,1);
+
+ x_axis = global_transform.getBasis() * x_axis * 5;
+ y_axis = global_transform.getBasis() * y_axis * 5;
+ z_axis = global_transform.getBasis() * z_axis * 5;
+
+
+ x_axis = x_axis + bone_start;
+ y_axis = y_axis + bone_start;
+ z_axis = z_axis + bone_start;
+
+ glColor3f(1,0,0);
+
+ glVertex3f(x_axis.x(),x_axis.y(),x_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,1,0);
+
+ glVertex3f(y_axis.x(),y_axis.y(),y_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,1,1);
+
+ glVertex3f(z_axis.x(),z_axis.y(),z_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,0,1);
+
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+ glVertex3f(bone_end[0],bone_end[1],bone_end[2]);
+
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+#if 0
+ // draw jacobian column vectors
+
+ // hack access to internals
+
+ IK_Solver_Class * internals = static_cast<IK_Solver_Class *>(chain->intern);
+
+ glDisable(GL_LIGHTING);
+
+ glBegin(GL_LINES);
+
+ const TNT::Matrix<MT_Scalar> & jac = internals->Chain().TransposedJacobian();
+
+ int i = 0;
+ for (i=0; i < jac.num_rows(); i++) {
+ glColor3f(1,1,1);
+
+ previous_origin = internals->Chain().Segments()[i/3].GlobalSegmentStart();
+
+ glVertex3f(previous_origin[0],previous_origin[1],previous_origin[2]);
+ glVertex3f(jac[i][0] + previous_origin[0],jac[i][1] + previous_origin[1],jac[i][2] + previous_origin[2]);
+
+
+ }
+ glEnd();
+ glEnable(GL_LIGHTING);
+#endif
+
+ }
+
+ glColor3f(1.0,1.0,1.0);
+
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+
+ MT_Scalar cube_size = 50;
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,cube_size,cube_size);
+
+ glVertex3f(cube_size,-cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,cube_size);
+
+ glVertex3f(cube_size,cube_size,-cube_size);
+ glVertex3f(-cube_size,cube_size,-cube_size);
+
+ glVertex3f(cube_size,-cube_size,-cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+
+
+ glVertex3f(-cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,cube_size);
+
+ glVertex3f(cube_size,cube_size,-cube_size);
+ glVertex3f(cube_size,-cube_size,-cube_size);
+
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(cube_size,-cube_size,cube_size);
+
+ glVertex3f(-cube_size,cube_size,-cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+
+
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(cube_size,cube_size,-cube_size);
+
+ glVertex3f(cube_size,-cube_size,cube_size);
+ glVertex3f(cube_size,-cube_size,-cube_size);
+
+ glVertex3f(-cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,cube_size,-cube_size);
+
+ glVertex3f(-cube_size,-cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+ };
+
+
+
+private :
+
+ MyGlutMouseHandler * m_mouse_handler;
+ MyGlutKeyHandler *m_key_handler;
+ IK_Chain_ExternPtr *m_chains;
+
+ int m_chain_num;
+ ChainDrawer (
+ ) : m_chains (NULL),
+ m_mouse_handler (NULL),
+ m_chain_num (0)
+ {
+ };
+
+};
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/intern/Makefile b/intern/iksolver/test/ik_glut_test/intern/Makefile
new file mode 100644
index 00000000000..fe1f4b54182
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/Makefile
@@ -0,0 +1,51 @@
+#
+# $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.
+#
+# 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 *****
+# iksolver test intern Makefile
+#
+
+LIBNAME = intern
+SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I../../../extern
+CPPFLAGS += -I../common
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
+ifeq ($(OS),windows)
+ CPPFLAGS += -I$(NAN_LIBDIR)/windows/glut-3.7/include
+endif
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
new file mode 100644
index 00000000000..5f88bda378c
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
@@ -0,0 +1,84 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MyGlutKeyHandler_h
+
+#define NAN_INCLUDED_MyGlutKeyHandler_h
+
+#include "../common/GlutKeyboardManager.h"
+
+class MyGlutKeyHandler : public GlutKeyboardHandler
+{
+public :
+ static
+ MyGlutKeyHandler *
+ New(
+ ) {
+ MEM_SmartPtr<MyGlutKeyHandler> output = new MyGlutKeyHandler();
+
+ if (output == NULL
+ ) {
+ return NULL;
+ }
+ return output.Release();
+
+ }
+
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ ){
+
+ switch (key) {
+
+ case 27 :
+
+ exit(0);
+ }
+ }
+
+ ~MyGlutKeyHandler(
+ )
+ {
+ };
+
+private :
+
+ MyGlutKeyHandler(
+ )
+ {
+ }
+
+};
+#endif
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
new file mode 100644
index 00000000000..e7d210beffb
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
@@ -0,0 +1,211 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MyGlutMouseHandler_h
+
+#define NAN_INCLUDED_MyGlutMouseHandler_h
+
+#include "../common/GlutMouseManager.h"
+#include <GL/glut.h>
+#include "IK_solver.h"
+
+class MyGlutMouseHandler : public GlutMouseHandler
+{
+
+public :
+
+ static
+ MyGlutMouseHandler *
+ New(
+ ) {
+ MEM_SmartPtr<MyGlutMouseHandler> output = new MyGlutMouseHandler();
+ if (output == NULL
+ ) {
+ return NULL;
+ }
+ return output.Release();
+
+ }
+
+ void
+ SetChain(
+ IK_Chain_ExternPtr *chains, int num_chains
+ ){
+ m_chains = chains;
+ m_num_chains = num_chains;
+ }
+
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ ){
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+ m_moving = true;
+ m_begin_x = x;
+ m_begin_y = y;
+ }
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ m_moving = false;
+ }
+
+ if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
+ m_tracking = true;
+ }
+ if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
+ m_tracking = false;
+ }
+
+ if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
+ m_cg_on = true;
+ }
+ if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) {
+ m_cg_on = false;
+ }
+
+ }
+
+
+ void
+ Motion(
+ int x,
+ int y
+ ){
+ if (m_moving) {
+ m_angle_x = m_angle_x + (x - m_begin_x);
+ m_begin_x = x;
+
+ m_angle_y = m_angle_y + (y - m_begin_y);
+ m_begin_y = y;
+
+ glutPostRedisplay();
+ }
+ if (m_tracking) {
+
+ int w_h = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+
+ y = w_h - y;
+
+ double mvmatrix[16];
+ double projmatrix[16];
+ GLint viewport[4];
+
+ double px, py, pz,sz;
+
+ /* Get the matrices needed for gluUnProject */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
+
+ // work out the position of the end effector in screen space
+
+ GLdouble ex,ey,ez;
+ ex = m_pos.x();
+ ey = m_pos.y();
+ ez = m_pos.z();
+
+ gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
+ gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+
+ m_pos = MT_Vector3(px,py,pz);
+
+ }
+ if (m_tracking || m_cg_on) {
+ float temp[3];
+ m_pos.getValue(temp);
+
+ IK_SolveChain(m_chains[0],temp,0.01,200,0.1,m_chains[1]->segments);
+ IK_LoadChain(m_chains[0],m_chains[0]->segments,m_chains[0]->num_segments);
+
+ glutPostRedisplay();
+ }
+
+
+ }
+
+ const
+ float
+ AngleX(
+ ) const {
+ return m_angle_x;
+ }
+
+ const
+ float
+ AngleY(
+ ) const {
+ return m_angle_y;
+ }
+
+ const
+ MT_Vector3
+ Position(
+ ) const {
+ return m_pos;
+ }
+
+
+private :
+
+ MyGlutMouseHandler (
+ ) :
+ m_angle_x(0),
+ m_angle_y(0),
+ m_begin_x(0),
+ m_begin_y(0),
+ m_moving (false),
+ m_tracking (false),
+ m_pos(0,0,0),
+ m_cg_on (false),
+ m_chains(NULL),
+ m_num_chains(0)
+ {
+ };
+
+ float m_angle_x;
+ float m_angle_y;
+ float m_begin_x;
+ float m_begin_y;
+
+ bool m_moving;
+ bool m_tracking;
+ bool m_cg_on;
+ MT_Vector3 m_pos;
+
+ IK_Chain_ExternPtr *m_chains;
+ int m_num_chains;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/intern/main.cpp b/intern/iksolver/test/ik_glut_test/intern/main.cpp
new file mode 100644
index 00000000000..137c9bd4470
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/main.cpp
@@ -0,0 +1,361 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#include "MEM_SmartPtr.h"
+
+#ifdef USE_QUATERNIONS
+#include "IK_Qsolver.h"
+#else
+#include "IK_solver.h"
+#endif
+
+#include <GL/glut.h>
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MyGlutMouseHandler.h"
+#include "MyGlutKeyHandler.h"
+#include "ChainDrawer.h"
+
+void
+init(MT_Vector3 min,MT_Vector3 max)
+{
+
+ GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
+ GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
+
+ GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 1.0}; /* Red diffuse light. */
+ GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
+
+ /* Enable a single OpenGL light. */
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHTING);
+
+ /* Use depth buffering for hidden surface elimination. */
+ glEnable(GL_DEPTH_TEST);
+
+ /* Setup the view of the cube. */
+ glMatrixMode(GL_PROJECTION);
+
+ // centre of the box + 3* depth of box
+
+ MT_Vector3 centre = (min + max) * 0.5;
+ MT_Vector3 diag = max - min;
+
+ float depth = diag.length();
+ float distance = 2;
+
+ gluPerspective(
+ /* field of view in degree */ 40.0,
+ /* aspect ratio */ 1.0,
+ /* Z near */ 1.0,
+ /* Z far */ distance * depth * 2
+ );
+ glMatrixMode(GL_MODELVIEW);
+
+
+ gluLookAt(
+ centre.x(), centre.y(), centre.z() + distance*depth, /* eye is at (0,0,5) */
+ centre.x(), centre.y(), centre.z(), /* center is at (0,0,0) */
+ 0.0, 1.0, 0.); /* up is in positive Y direction */
+
+ glPushMatrix();
+
+
+}
+int
+main(int argc, char **argv)
+{
+
+
+ const int seg_num = 5;
+ const MT_Scalar seg_length = 15;
+
+ const float seg_startA[3] = {0,0,0};
+ const float seg_startB[3] = {0,-20,0};
+
+ // create some segments to solve with
+
+ // First chain
+ //////////////
+
+
+ IK_Segment_ExternPtr const segmentsA = new IK_Segment_Extern[seg_num];
+ IK_Segment_ExternPtr const segmentsB = new IK_Segment_Extern[seg_num];
+
+ IK_Segment_ExternPtr seg_it = segmentsA;
+ IK_Segment_ExternPtr seg_itB = segmentsB;
+
+
+ {
+
+// MT_Quaternion qmat(MT_Vector3(0,0,1),-3.141/2);
+ MT_Quaternion qmat(MT_Vector3(0,0,1),0);
+ MT_Matrix3x3 mat(qmat);
+
+ seg_it->seg_start[0] = seg_startA[0];
+ seg_it->seg_start[1] = seg_startA[1];
+ seg_it->seg_start[2] = seg_startA[2];
+
+ float temp[12];
+ mat.getValue(temp);
+
+ seg_it->basis[0] = temp[0];
+ seg_it->basis[1] = temp[1];
+ seg_it->basis[2] = temp[2];
+
+ seg_it->basis[3] = temp[4];
+ seg_it->basis[4] = temp[5];
+ seg_it->basis[5] = temp[6];
+
+ seg_it->basis[6] = temp[8];
+ seg_it->basis[7] = temp[9];
+ seg_it->basis[8] = temp[10];
+
+ seg_it->length = seg_length;
+
+ MT_Quaternion q;
+ q.setEuler(0,0,0);
+
+
+ MT_Matrix3x3 qrot(q);
+
+ seg_it->basis_change[0] = 1;
+ seg_it->basis_change[1] = 0;
+ seg_it->basis_change[2] = 0;
+ seg_it->basis_change[3] = 0;
+ seg_it->basis_change[4] = 1;
+ seg_it->basis_change[5] = 0;
+ seg_it->basis_change[6] = 0;
+ seg_it->basis_change[7] = 0;
+ seg_it->basis_change[8] = 1;
+
+
+ seg_it ++;
+
+ seg_itB->seg_start[0] = seg_startA[0];
+ seg_itB->seg_start[1] = seg_startA[1];
+ seg_itB->seg_start[2] = seg_startA[2];
+
+ seg_itB->basis[0] = temp[0];
+ seg_itB->basis[1] = temp[1];
+ seg_itB->basis[2] = temp[2];
+
+ seg_itB->basis[3] = temp[4];
+ seg_itB->basis[4] = temp[5];
+ seg_itB->basis[5] = temp[6];
+
+ seg_itB->basis[6] = temp[8];
+ seg_itB->basis[7] = temp[9];
+ seg_itB->basis[8] = temp[10];
+
+ seg_itB->length = seg_length;
+
+ seg_itB->basis_change[0] = 1;
+ seg_itB->basis_change[1] = 0;
+ seg_itB->basis_change[2] = 0;
+ seg_itB->basis_change[3] = 0;
+ seg_itB->basis_change[4] = 1;
+ seg_itB->basis_change[5] = 0;
+ seg_itB->basis_change[6] = 0;
+ seg_itB->basis_change[7] = 0;
+ seg_itB->basis_change[8] = 1;
+
+
+ seg_itB ++;
+
+
+ }
+
+
+ int i;
+ for (i=1; i < seg_num; ++i, ++seg_it,++seg_itB) {
+
+ MT_Quaternion qmat(MT_Vector3(0,0,1),0.3);
+ MT_Matrix3x3 mat(qmat);
+
+ seg_it->seg_start[0] = 0;
+ seg_it->seg_start[1] = 0;
+ seg_it->seg_start[2] = 0;
+
+ float temp[12];
+ mat.getValue(temp);
+
+ seg_it->basis[0] = temp[0];
+ seg_it->basis[1] = temp[1];
+ seg_it->basis[2] = temp[2];
+
+ seg_it->basis[3] = temp[4];
+ seg_it->basis[4] = temp[5];
+ seg_it->basis[5] = temp[6];
+
+ seg_it->basis[6] = temp[8];
+ seg_it->basis[7] = temp[9];
+ seg_it->basis[8] = temp[10];
+
+ seg_it->length = seg_length;
+
+ MT_Quaternion q;
+ q.setEuler(0,0,0);
+
+
+ MT_Matrix3x3 qrot(q);
+
+ seg_it->basis_change[0] = 1;
+ seg_it->basis_change[1] = 0;
+ seg_it->basis_change[2] = 0;
+ seg_it->basis_change[3] = 0;
+ seg_it->basis_change[4] = 1;
+ seg_it->basis_change[5] = 0;
+ seg_it->basis_change[6] = 0;
+ seg_it->basis_change[7] = 0;
+ seg_it->basis_change[8] = 1;
+
+
+ ///////////////////////////////
+
+ seg_itB->seg_start[0] = 0;
+ seg_itB->seg_start[1] = 0;
+ seg_itB->seg_start[2] = 0;
+
+ seg_itB->basis[0] = temp[0];
+ seg_itB->basis[1] = temp[1];
+ seg_itB->basis[2] = temp[2];
+
+ seg_itB->basis[3] = temp[4];
+ seg_itB->basis[4] = temp[5];
+ seg_itB->basis[5] = temp[6];
+
+ seg_itB->basis[6] = temp[8];
+ seg_itB->basis[7] = temp[9];
+ seg_itB->basis[8] = temp[10];
+
+ seg_itB->length = seg_length;
+
+ seg_itB->basis_change[0] = 1;
+ seg_itB->basis_change[1] = 0;
+ seg_itB->basis_change[2] = 0;
+ seg_itB->basis_change[3] = 0;
+ seg_itB->basis_change[4] = 1;
+ seg_itB->basis_change[5] = 0;
+ seg_itB->basis_change[6] = 0;
+ seg_itB->basis_change[7] = 0;
+ seg_itB->basis_change[8] = 1;
+
+
+
+ }
+
+ // create the chains
+
+ const int num_chains = 2;
+
+ IK_Chain_ExternPtr chains[num_chains];
+
+ chains[0] = IK_CreateChain();
+ chains[1] = IK_CreateChain();
+
+ // load segments into chain
+
+ IK_LoadChain(chains[0],segmentsA,seg_num);
+ IK_LoadChain(chains[1],segmentsB,seg_num);
+
+ // make and install a mouse handler
+
+ MEM_SmartPtr<MyGlutMouseHandler> mouse_handler (MyGlutMouseHandler::New());
+ GlutMouseManager::Instance()->InstallHandler(mouse_handler);
+
+ mouse_handler->SetChain(chains,num_chains);
+
+ // make and install a keyhandler
+ MEM_SmartPtr<MyGlutKeyHandler> key_handler (MyGlutKeyHandler::New());
+ GlutKeyboardManager::Instance()->InstallHandler(key_handler);
+
+ // instantiate the drawing class
+
+ MEM_SmartPtr<ChainDrawer> drawer (ChainDrawer::New());
+ GlutDrawManager::Instance()->InstallDrawer(drawer);
+
+ drawer->SetMouseHandler(mouse_handler);
+ drawer->SetChain(chains,num_chains);
+ drawer->SetKeyHandler(key_handler);
+
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutCreateWindow("ik");
+ glutDisplayFunc(GlutDrawManager::Draw);
+ glutMouseFunc(GlutMouseManager::Mouse);
+ glutMotionFunc(GlutMouseManager::Motion);
+ glutKeyboardFunc(GlutKeyboardManager::HandleKeyboard);
+
+ init(MT_Vector3(-50,-50,-50),MT_Vector3(50,50,50));
+ glutMainLoop();
+ return 0; /* ANSI C requires main to return int. */
+}
diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp
new file mode 100644
index 00000000000..8688b2fcc2c
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="ik_glut_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ik_glut_test - 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 "ik_glut_test.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 "ik_glut_test.mak" CFG="ik_glut_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ik_glut_test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ik_glut_test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ik_glut_test - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 iksolver_rmtd.lib libmoto.a /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\release" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib"
+
+!ELSEIF "$(CFG)" == "ik_glut_test - 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 "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 iksolver_dmtd.lib libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCMTD.lib" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\debug" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib\debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "ik_glut_test - Win32 Release"
+# Name "ik_glut_test - Win32 Debug"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\common\GlutDrawer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutDrawer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutKeyboardManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutKeyboardManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutMouseManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutMouseManager.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\intern\ChainDrawer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MyGlutKeyHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MyGlutMouseHandler.h
+# End Source File
+# End Target
+# End Project
diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw
new file mode 100644
index 00000000000..09b7094137b
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw
@@ -0,0 +1,49 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ik_glut_test"=.\ik_glut_test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name iksolver
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "iksolver"=..\..\..\..\make\msvc_6_0\iksolver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
+
+
+
+
+
diff --git a/intern/img/doc/Doxyfile.win b/intern/img/doc/Doxyfile.win
new file mode 100644
index 00000000000..242357fe7b5
--- /dev/null
+++ b/intern/img/doc/Doxyfile.win
@@ -0,0 +1,747 @@
+# Doxyfile 1.2.4
+
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+#MAART: changed
+PROJECT_NAME = ImgLib
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+#MAART: changed
+OUTPUT_DIRECTORY = doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
+# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
+# Polish, Portuguese and Slovene.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+# MAART: changed
+EXTRACT_STATIC = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a class diagram (in Html and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off.
+
+CLASS_DIAGRAMS = YES
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+#MAART: changed
+JAVADOC_AUTOBRIEF = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The ENABLE_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .
+#C:\Documents and Settings\maarten\My Documents\develop\blender\source\blender\img
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Netscape 4.0+
+# or Internet explorer 4.0+).
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+#MAART: changed
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+#MAART: changed
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using a WORD or other.
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+#MAART: changed
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Warning: This feature
+# is still experimental and very incomplete.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other
+# documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
+# YES then doxygen will generate a graph for each documented header file showing
+# the documented files that directly or indirectly include this file
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = c:\program files\doxygen\bin
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/intern/img/extern/IMG_Pixmap.h b/intern/img/extern/IMG_Pixmap.h
new file mode 100644
index 00000000000..9d9f247e3b4
--- /dev/null
+++ b/intern/img/extern/IMG_Pixmap.h
@@ -0,0 +1,198 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Abstract base class for pixmaps of different types.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+#ifndef _H_IMG_Pixmap
+#define _H_IMG_Pixmap
+
+#include "GEN_Types.h"
+#include "GEN_Rect.h"
+
+
+class IMG_Pixmap
+{
+public:
+ /** The type of pixels that are stored in this pixmap. */
+ typedef enum {
+ kPixelTypeUnknown = 0, /**< R:8, G:8, B:8, Ignore:8 */
+// kPixelTypeRGB32 = 1, /**< R:8, G:8, B:8, Ignore:8 */
+ kPixelTypeRGBA32 = 2, /**< R:8, G:8, B:8, Alpha:8 */
+// kPixelTypeRGB16 = 3, /**< Ignore:1, R:5, G:5, B:5 */
+// kPixelTypeRGBA16 = 4, /**< Alpha:1, R:5, G:5, B:5 */
+// kPixelTypeRGB16_565 = 5, /**< R:5, G:6, B:5 */
+// kPixelTypeRGB24 = 6 /**< R:8, G:8, B:8 */
+ } TPixelType;
+
+ /**
+ * Default constructor.
+ */
+ IMG_Pixmap();
+
+ /**
+ * Constructs a pixmap with the requested width and height.
+ * @param width The width of the pixmap created.
+ * @param height The height of the pixmap created.
+ */
+ IMG_Pixmap(GEN_TUns32 width, GEN_TUns32 height);
+
+ /**
+ * Destructor.
+ */
+ virtual ~IMG_Pixmap();
+
+ /**
+ * Access to image data
+ * @return pointer to the image data
+ */
+ virtual void* getDataPtr() const = 0;
+
+ /**
+ * Access to image width.
+ * @return width of the image
+ */
+ inline GEN_TUns32 getWidth() const;
+
+ /**
+ * Access to image height.
+ * @return height of the image
+ */
+ inline GEN_TUns32 getHeight() const;
+
+ /**
+ * Returns the bounds of the pixmap in a rectangle.
+ * @param bounds of the image
+ */
+ inline void getBounds(GEN_Rect& r) const;
+
+ /**
+ * Access to pixel type.
+ * @return the pixel type
+ */
+ inline TPixelType getPixelType() const;
+
+ /**
+ * Clamps coordinates inside (0, 0) and (width, height).
+ * @param x requested x-coordinate
+ * @param y requested y-coordinate
+ */
+ inline void clamp(GEN_TInt32& x, GEN_TInt32& y) const;
+
+ /**
+ * Clamps u, v coordinates between 0 and 1.
+ * @param u requested u-coordinate
+ * @param v requested v-coordinate
+ */
+ inline void clamp(float& u, float& v) const;
+
+ /**
+ * Converts (u,v) coordinates to pixel addresses.
+ * Assumes that (u,v) coordinates are in the [0,1] range.
+ * @param u requested u-coordinate in the image
+ * @param v requested v-coordinate in the image
+ * @param x calculated x-coordinate in the image
+ * @param y calculated y-coordinate in the image
+ */
+ inline void getPixelAddress(float u, float v, GEN_TInt32& x, GEN_TInt32& y) const;
+
+ /**
+ * Fills the rectangle given with the color given.
+ * Performs a bounds check.
+ * @param r requested bounds rectangle in the image
+ * @param c color to use
+ */
+ //virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c) = 0;
+
+protected:
+ /** Width of the image in pixels */
+ GEN_TUns32 m_width;
+ /** Height of the image in pixels */
+ GEN_TUns32 m_height;
+ /** Number of bytes for one row in the image. */
+ GEN_TUns32 m_rowBytes;
+ /** Size in bits for one pixel */
+ GEN_TUns32 m_pixelSize;
+ /** Type of pixels in this image. */
+ TPixelType m_pixelType;
+// TEndian m_bitOrder;
+// TEndian m_byteOrder;
+};
+
+inline GEN_TUns32 IMG_Pixmap::getWidth() const
+{
+ return m_width;
+}
+
+inline GEN_TUns32 IMG_Pixmap::getHeight() const
+{
+ return m_height;
+}
+
+inline void IMG_Pixmap::getBounds(GEN_Rect& r) const
+{
+ r.set(0, 0, m_width, m_height);
+}
+
+inline IMG_Pixmap::TPixelType IMG_Pixmap::getPixelType() const
+{
+ return m_pixelType;
+}
+
+inline void IMG_Pixmap::clamp(GEN_TInt32& x, GEN_TInt32& y) const
+{
+ if (x < 0) x = 0;
+ if (x > (GEN_TInt32)m_width) x = (GEN_TInt32)m_width;
+ if (y < 0) y = 0;
+ if (y > (GEN_TInt32)m_height) y = (GEN_TInt32)m_height;
+}
+
+inline void IMG_Pixmap::clamp(float& u, float& v) const
+{
+ if (u < 0.f) u = 0.f;
+ if (u > 1.f) u = 1.f;
+ if (v < 0.f) v = 0.f;
+ if (v > 1.f) v = 1.f;
+}
+
+inline void IMG_Pixmap::getPixelAddress(float u, float v, GEN_TInt32& x, GEN_TInt32& y) const
+{
+ x = (GEN_TInt32)(((float)m_width) * u);
+ y = (GEN_TInt32)(((float)m_height) * v);
+}
+
+#endif // _H_IMG_Pixmap \ No newline at end of file
diff --git a/intern/img/extern/IMG_PixmapRGBA32.h b/intern/img/extern/IMG_PixmapRGBA32.h
new file mode 100644
index 00000000000..541bdcfa9a4
--- /dev/null
+++ b/intern/img/extern/IMG_PixmapRGBA32.h
@@ -0,0 +1,217 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Pixmap of kPixelTypeRGBA32 type.
+ * A pixmap with 24 bits per pixel in ABGR format.
+ * Provides methods to fill rectangular areas in this image with a color.
+ * Provides methods to paste or blend other pixmaps into this pixmap.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+
+#ifndef _H_IMG_PixmapRGBA32
+#define _H_IMG_PixmapRGBA32
+
+#include "IMG_Pixmap.h"
+#include "IMG_MemPtr.h"
+#include "IMG_Color.h"
+
+
+class IMG_PixmapRGBA32 : public IMG_Pixmap {
+public:
+ /** The pixel type in this pixmap. */
+ typedef GEN_TUns32 TPixelRGBA32;
+
+ /** The pixel pointer type of this pixmap. */
+ typedef TPixelRGBA32* TPixelPtr;
+
+ /** Indices of color component byes within a pixel. */
+ typedef enum {
+ bi_r = 0,
+ bi_g = 1,
+ bi_b = 2,
+ bi_a = 3
+ } TPixelIndex;
+
+ /**
+ * Constructor.
+ * Creates a new pixmap of the kPixelTypeRGBA32 type with the requested dimensions.
+ * @throw <IMG_MemPtr::Size> when an invalid width and/or height is passed.
+ * @throw <IMG_MemPtr::Memory> when a there is not enough memory to allocate the image.
+ * @param width the width in pixels of the image.
+ * @param height the height in pixels of the image.
+ */
+ IMG_PixmapRGBA32(GEN_TUns32 width, GEN_TUns32 height);
+
+ /**
+ * Constructor.
+ * Creates a new pixmap of the kPixelTypeRGBA32 from a pointer to image data.
+ * The image data will not be freed upon destruction of this object.
+ * The owner of this object is reponsible for that.
+ * @throw <Size> when an invalid width and/or height is passed.
+ * @param image pointer to the image data.
+ * @param width the width in pixels of the image.
+ * @param height the height in pixels of the image.
+ */
+ IMG_PixmapRGBA32(void* image, GEN_TUns32 width, GEN_TUns32 height, GEN_TUns32 rowBytes);
+
+#if 0
+ /**
+ * Destructor.
+ */
+ virtual ~IMG_PixmapRGBA32();
+#endif
+
+ /**
+ * Fills the rectangle given with the color given.
+ * Retains the alpha values.
+ * Performs a bounds check.
+ * @param r requested bounds rectangle in the image
+ * @param c color to use
+ */
+ virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGB& c);
+
+ /**
+ * Fills the rectangle given with the color given.
+ * Sets the alpha values from the color.
+ * Performs a bounds check.
+ * @param r requested bounds rectangle in the image
+ * @param c color to use
+ */
+ virtual void fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c);
+
+ /**
+ * Pastes an area of a pixmap into this pixmap.
+ * Pastes an area of the given pixmap centered at the given coordinates into this pixmap.
+ * Ignores the alpha information, this is pasted as well.
+ * Performs a bounds check.
+ * @param src the pixmap to paste.
+ * @param srcBnds the bounds of the area of the pixmap to paste.
+ * @param destBnds the destination area for the paste.
+ */
+ virtual void setPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds);
+
+ /**
+ * Blends an area of a pixmap into this pixmap.
+ * Blends an area of the given pixmap centered at the given coordinates into this pixmap.
+ * The alpha information in the given image is used to blend.
+ * Performs a bounds check.
+ * @param src the pixmap to paste.
+ * @param srcBnds the bounds of the area of the pixmap to paste.
+ * @param destBnds the destination area for the paste.
+ */
+ virtual void blendPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds);
+
+protected:
+ /**
+ * Returns pointer to the pixel.
+ * Returns a pointer of TPixelPtr type to the pixel at the requested coordinates.
+ * Does not perform a bounds check!
+ * @param x column address of the pixel.
+ * @param y row address of the pixel.
+ * @return the pointer calculated.
+ */
+ inline TPixelPtr getPixelPtr(GEN_TUns32 x, GEN_TUns32 y) const;
+
+ /**
+ * Returns the pixel value of a color.
+ * @param c the color to convert
+ * @return the pixel value calculated
+ */
+ inline TPixelRGBA32 getPixelValue(const IMG_ColorRGBA& c) const;
+
+ /**
+ * Returns the color of from a pixel value.
+ * @param p the pixel value
+ * @param c the color calculated
+ */
+ inline void getColor(TPixelRGBA32 p, IMG_ColorRGBA& c) const;
+
+protected:
+ /** "Save" memory pointer. */
+ IMG_MemPtr<TPixelRGBA32> m_pixels;
+
+ /** Pointer to the first pixel. */
+ TPixelPtr m_pixelsBase;
+};
+
+
+inline IMG_PixmapRGBA32::TPixelPtr IMG_PixmapRGBA32::getPixelPtr(GEN_TUns32 x, GEN_TUns32 y) const
+{
+ return (TPixelPtr) (((GEN_TUns8*)m_pixelsBase) + (y*m_rowBytes) + (x<<2));
+}
+
+
+inline IMG_PixmapRGBA32::TPixelRGBA32 IMG_PixmapRGBA32::getPixelValue(const IMG_ColorRGBA& c) const
+{
+#if 0
+ // Obtain pixel value through shifting
+ TPixelRGBA32 p = ((TPixelRGBA32) (((float) 0xFF) * c.m_a)) << 24;
+ p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_b)) << 16;
+ p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_g)) << 8;
+ p |= ((TPixelRGBA32) (((float) 0xFF) * c.m_r));
+ return p;
+#else
+ // Obtain pixel value through byte indexing
+ TPixelRGBA32 pixel;
+ GEN_TUns8* bytes = (GEN_TUns8*)&pixel;
+ bytes[bi_r] = (GEN_TUns8)(((float) 0xFF) * c.m_r);
+ bytes[bi_g] = (GEN_TUns8)(((float) 0xFF) * c.m_g);
+ bytes[bi_b] = (GEN_TUns8)(((float) 0xFF) * c.m_b);
+ bytes[bi_a] = (GEN_TUns8)(((float) 0xFF) * c.m_a);
+ return pixel;
+#endif
+}
+
+inline void IMG_PixmapRGBA32::getColor(TPixelRGBA32 p, IMG_ColorRGBA& c) const
+{
+#if 0
+ // Obtain color value through shifting
+ c.m_a = ((float) ((p >> 24) & 0x00FF)) / ((float) 0xFF);
+ c.m_b = ((float) ((p >> 16) & 0x00FF)) / ((float) 0xFF);
+ c.m_g = ((float) ((p >> 8) & 0x00FF)) / ((float) 0xFF);
+ c.m_r = ((float) ( p & 0x00FF)) / ((float) 0xFF);
+#else
+ // Obtain color value through byte indexing
+ GEN_TUns8* bytes = (GEN_TUns8*)&p;
+ c.m_r = ((float)bytes[bi_r]) / ((float) 0xFF);
+ c.m_g = ((float)bytes[bi_g]) / ((float) 0xFF);
+ c.m_b = ((float)bytes[bi_b]) / ((float) 0xFF);
+ c.m_a = ((float)bytes[bi_a]) / ((float) 0xFF);
+#endif
+}
+
+#endif // _H_IMG_PixmapRGBA32 \ No newline at end of file
diff --git a/intern/img/intern/IMG_Color.h b/intern/img/intern/IMG_Color.h
new file mode 100644
index 00000000000..9e6ef5c74fc
--- /dev/null
+++ b/intern/img/intern/IMG_Color.h
@@ -0,0 +1,144 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Declaration of an RGB color with red, green and blue components.
+ * Declaration of an RGBA color with red, green, blue and alpha components.
+ * Components are stored as floats.
+ * @author Maarten Gribnau
+ * @date March 7, 2001
+ */
+
+#ifndef _H_IMG_Color
+#define _H_IMG_Color
+
+class IMG_ColorRGBA;
+
+
+class IMG_ColorRGB {
+public:
+ /**
+ * Constructs a color with the given values.
+ * @param r requested red component of the color
+ * @param g requested green component of the color
+ * @param b requested blue component of the color
+ */
+ IMG_ColorRGB(float r=0, float g=0, float b=0)
+ : m_r(r), m_g(g), m_b(b) {}
+
+ /**
+ * Copy constructor.
+ * @param c the color to copy.
+ */
+ IMG_ColorRGB(const IMG_ColorRGB& c)
+ : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b) {}
+
+ /**
+ * Constructs a color without alpha from one with.
+ * @param c the color to copy.
+ */
+ inline IMG_ColorRGB(const IMG_ColorRGBA& c);
+
+ /** Red component of the color */
+ float m_r;
+ /** Green component of the color */
+ float m_g;
+ /** Blue component of the color */
+ float m_b;
+};
+
+
+class IMG_ColorRGBA {
+public:
+ /**
+ * Constructs a color with the given values.
+ * @param r requested red component of the color
+ * @param g requested green component of the color
+ * @param b requested blue component of the color
+ * @param a requested alpha component of the color
+ */
+ IMG_ColorRGBA(float r=0, float g=0, float b=0, float a=0)
+ : m_r(r), m_g(g), m_b(b), m_a(a) {}
+
+ /**
+ * Copy constructor.
+ * @param c the color to copy.
+ */
+ IMG_ColorRGBA(const IMG_ColorRGBA& c)
+ : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b), m_a(c.m_a) {}
+
+ /**
+ * Constructs a color with alpha from one without.
+ * @param c the color to copy.
+ */
+ IMG_ColorRGBA(const IMG_ColorRGB& c)
+ : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b), m_a(0) {}
+
+ /**
+ * Blends the given color with this color.
+ * Uses the alpha of the given color for blending.
+ * The alpha of this color is left untouched.
+ * @param c the color to blend
+ */
+ inline void blendColor(const IMG_ColorRGBA& c);
+
+ /** Red component of the color */
+ float m_r;
+ /** Green component of the color */
+ float m_g;
+ /** Blue component of the color */
+ float m_b;
+ /** Alpha component of the color */
+ float m_a;
+};
+
+inline IMG_ColorRGB::IMG_ColorRGB(const IMG_ColorRGBA& c)
+ : m_r(c.m_r), m_g(c.m_g), m_b(c.m_b) {}
+
+inline void IMG_ColorRGBA::blendColor(const IMG_ColorRGBA& c)
+{
+ float r1 = 1 - c.m_a; // The reverse of alpha
+#if IMG_REVERSED_ALPHA
+ m_r = c.m_a * m_r + r1 * c.m_r;
+ m_g = c.m_a * m_g + r1 * c.m_g;
+ m_b = c.m_a * m_b + r1 * c.m_b;
+#else
+ m_r = r1 * m_r + c.m_a * c.m_r;
+ m_g = r1 * m_g + c.m_a * c.m_g;
+ m_b = r1 * m_b + c.m_a * c.m_b;
+#endif
+}
+
+
+#endif // _H_IMG_Color \ No newline at end of file
diff --git a/intern/img/intern/IMG_MemPtr.h b/intern/img/intern/IMG_MemPtr.h
new file mode 100644
index 00000000000..e81a5b5c873
--- /dev/null
+++ b/intern/img/intern/IMG_MemPtr.h
@@ -0,0 +1,117 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * @author Maarten Gribnau
+ * @date March 8, 2001
+ */
+
+#ifndef _H_IMG_MemPtr
+#define _H_IMG_MemPtr
+
+#include <stddef.h>
+
+/**
+ * A memory pointer for memory of any type.
+ * It can be used to avoid memory leaks when allocating memory in constructors.
+ * @author Maarten Gribnau
+ * @date March 8, 2001
+ */
+
+template <class T> class IMG_MemPtr {
+public:
+ /** Pointer to the memory */
+ T* m_p;
+ bool m_owned;
+
+ /**
+ * Size exception.
+ * A size exception is thrown when an invalid width and/or height is passed.
+ */
+ class Size {};
+ /**
+ * Memory exception.
+ * A size exception is thrown when a there is not enough memory to allocate the image.
+ */
+ class Memory {};
+
+ /**
+ * Constructs a memory pointer.
+ * @param s requested size of the pointer
+ * @throw <Size> when an invalid width and/or height is passed.
+ * @throw <Memory> when a there is not enough memory to allocate the image.
+ */
+ IMG_MemPtr(size_t s)
+ : m_p(0), m_owned(false)
+ {
+ if (s > 0) {
+ m_p = new T[s];
+ if (!m_p) {
+ throw Memory();
+ }
+ m_owned = true;
+ }
+ else {
+ throw Size();
+ }
+ }
+
+ /**
+ * Constructs a memory pointer from a pointer.
+ * @param p the pointer
+ * @param s requested size of the pointer
+ * @throw <Size> when an invalid width and/or height is passed.
+ */
+ IMG_MemPtr(void* p, size_t s)
+ : m_p(0), m_owned(false)
+ {
+ if (p && (s > 0)) {
+ m_p = (T*)p;
+ }
+ else {
+ throw Size();
+ }
+ }
+
+ /**
+ * Destructor.
+ */
+ ~IMG_MemPtr() { if (m_p && m_owned) { delete [] m_p; m_p = 0; } }
+
+ /**
+ * Access to the memory.
+ * @return pointer to the memory
+ */
+ operator T*() { return m_p; }
+};
+
+#endif // _H_IMG_MemPtr \ No newline at end of file
diff --git a/intern/img/intern/IMG_Pixmap.cpp b/intern/img/intern/IMG_Pixmap.cpp
new file mode 100644
index 00000000000..74888647b75
--- /dev/null
+++ b/intern/img/intern/IMG_Pixmap.cpp
@@ -0,0 +1,85 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Base class for pixmaps.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+
+#include "../extern/IMG_Pixmap.h"
+
+
+IMG_Pixmap::IMG_Pixmap()
+{
+ m_width = 0;
+ m_height = 0;
+ m_rowBytes = 0;
+ m_pixelSize = 0;
+ m_pixelType = kPixelTypeUnknown;
+/*
+#if OS_MACINTOSH
+ bitOrder = kQ3EndianBig;
+ byteOrder = kQ3EndianBig;
+#else
+ bitOrder = kQ3EndianLittle;
+ byteOrder = kQ3EndianLittle;
+#endif
+*/
+}
+
+
+IMG_Pixmap::IMG_Pixmap(GEN_TUns32 width, GEN_TUns32 height)
+{
+ m_width = width;
+ m_height = height;
+ m_rowBytes = 0;
+ m_pixelSize = 0;
+ m_pixelType = kPixelTypeUnknown;
+/*
+#if OS_MACINTOSH
+ bitOrder = kQ3EndianBig;
+ byteOrder = kQ3EndianBig;
+#else
+ bitOrder = kQ3EndianLittle;
+ byteOrder = kQ3EndianLittle;
+#endif
+*/
+}
+
+
+IMG_Pixmap::~IMG_Pixmap()
+{
+} \ No newline at end of file
diff --git a/intern/img/intern/IMG_PixmapRGBA32.cpp b/intern/img/intern/IMG_PixmapRGBA32.cpp
new file mode 100644
index 00000000000..a7b70e03616
--- /dev/null
+++ b/intern/img/intern/IMG_PixmapRGBA32.cpp
@@ -0,0 +1,260 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Base class for pixmaps.
+ * @author Maarten Gribnau
+ * @date March 6, 2001
+ */
+
+
+#include "../extern/IMG_PixmapRGBA32.h"
+
+IMG_PixmapRGBA32::IMG_PixmapRGBA32(GEN_TUns32 width, GEN_TUns32 height)
+ : IMG_Pixmap(), m_pixels(width * height)
+{
+ m_pixelsBase = m_pixels;
+ m_width = width;
+ m_height = height;
+ m_rowBytes = width * sizeof(TPixelRGBA32);
+ m_pixelSize = 32;
+ m_pixelType = kPixelTypeRGBA32;
+}
+
+
+IMG_PixmapRGBA32::IMG_PixmapRGBA32(void* image, GEN_TUns32 width, GEN_TUns32 height, GEN_TUns32 rowBytes)
+ : IMG_Pixmap(), m_pixels(image, width * rowBytes)
+{
+ m_pixelsBase = m_pixels;
+ m_width = width;
+ m_height = height;
+ m_rowBytes = rowBytes;
+ m_pixelSize = 32;
+ m_pixelType = kPixelTypeRGBA32;
+}
+
+
+void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGB& c)
+{
+ GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ GEN_Rect r_bnds (r); // Area to set
+
+ // Determine visibility
+ GEN_TVisibility v = t_bnds.getVisibility(r_bnds);
+ if (v == GEN_kNotVisible) return;
+ if (v == GEN_kPartiallyVisible) {
+ // Clip the destination rectangle to the bounds of this pixmap
+ t_bnds.clip(r_bnds);
+ if (r_bnds.isEmpty()) {
+ return;
+ }
+ }
+
+#if 0
+ // Set new pixels using shifting
+ // Prepare the pixel value to set
+ IMG_ColorRGBA ca (c);
+ TPixelRGBA32 pv = getPixelValue(c);
+ // Mask off the alpha bits
+ pv &= 0x00FFFFFF; //0xFFFFFF00;
+
+ // Set the pixels in the destination rectangle
+ for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
+ // Park pixel pointer at the start pixels
+ TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y);
+ for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
+ // Set the new pixel value (retain current alpha)
+ *(desPtr++) = pv | ((*desPtr) & 0xFF000000); //0x000000FF);
+ }
+ }
+#else
+ // Set new values using byte indexing
+ //IMG_ColorRGBA ca (c);
+ TPixelRGBA32 src = getPixelValue(c);
+ TPixelPtr desPtr;
+ GEN_TUns8* srcBytes = (GEN_TUns8*) &src;
+
+ // Set the pixels in the destination rectangle
+ for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
+ // Park pixel pointer at the start pixels
+ desPtr = getPixelPtr(r_bnds.m_l, y);
+ for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
+ // Set the new pixel value (retain current alpha)
+ ((GEN_TUns8*)desPtr)[bi_r] = srcBytes[bi_r];
+ ((GEN_TUns8*)desPtr)[bi_g] = srcBytes[bi_g];
+ ((GEN_TUns8*)desPtr)[bi_b] = srcBytes[bi_b];
+ desPtr++;
+ }
+ }
+#endif
+}
+
+
+void IMG_PixmapRGBA32::fillRect(const GEN_Rect& r, const IMG_ColorRGBA& c)
+{
+ GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ GEN_Rect r_bnds (r); // Area to set
+
+ // Determine visibility
+ GEN_TVisibility v = t_bnds.getVisibility(r_bnds);
+ if (v == GEN_kNotVisible) return;
+ if (v == GEN_kPartiallyVisible) {
+ // Clip the destination rectangle to the bounds of this pixmap
+ t_bnds.clip(r_bnds);
+ if (r_bnds.isEmpty()) {
+ return;
+ }
+ }
+
+ // Set the pixels in the destination rectangle
+ TPixelRGBA32 pixel = getPixelValue(c);
+ for (GEN_TInt32 y = r.m_t; y < r.m_b; y++) {
+ // Park pixel pointer at the start pixels
+ TPixelPtr desPtr = getPixelPtr(r_bnds.m_l, y);
+ for (GEN_TInt32 x = r.m_l; x < r.m_r; x++) {
+ *(desPtr++) = pixel;
+ }
+ }
+}
+
+
+void IMG_PixmapRGBA32::setPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds)
+{
+ GEN_Rect i_bnds (srcBnds); // Bounds of input pixmap
+ GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ GEN_Rect p_bnds (destBnds); // Bounds of the paste area
+
+ // The next check could be removed if the caller is made responsible for handing us non-empty rectangles
+ if (i_bnds.isEmpty()) {
+ // Nothing to do
+ return;
+ }
+
+ // Determine visibility of the paste area
+ GEN_TVisibility v = t_bnds.getVisibility(p_bnds);
+ if (v == GEN_kNotVisible) return;
+ if (v == GEN_kPartiallyVisible) {
+ // Clipping is needed
+ if (p_bnds.m_l < 0) {
+ i_bnds.m_l += -p_bnds.m_l;
+ p_bnds.m_l = 0;
+ }
+ if (p_bnds.m_t < 0) {
+ i_bnds.m_t += -p_bnds.m_t;
+ p_bnds.m_t = 0;
+ }
+ GEN_TInt32 d = t_bnds.getWidth();
+ if (p_bnds.m_r > d) {
+ i_bnds.m_r -= d - p_bnds.m_r;
+ p_bnds.m_r = d;
+ }
+ d = t_bnds.getHeight();
+ if (p_bnds.m_b > d) {
+ i_bnds.m_b -= d - p_bnds.m_b;
+ p_bnds.m_b = d;
+ }
+ }
+
+ // Iterate through the rows
+ for (GEN_TInt32 r = 0; r < p_bnds.getHeight(); r++) {
+ // Park pixel pointers at the start pixels
+ TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r);
+ TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r);
+ // Iterate through the columns
+ for (int c = 0; c < p_bnds.getWidth(); c++) {
+ *(desPtr++) = *(srcPtr++);
+ }
+ }
+}
+
+
+void IMG_PixmapRGBA32::blendPixmap(const IMG_PixmapRGBA32& src, const GEN_Rect& srcBnds, const GEN_Rect& destBnds)
+{
+ GEN_Rect i_bnds (srcBnds); // Bounds of input pixmap
+ GEN_Rect t_bnds (0, 0, m_width, m_height); // Bounds of this pixmap
+ GEN_Rect p_bnds (destBnds); // Bounds of the paste area
+
+ // The next check could be removed if the caller is made responsible for handing us non-empty rectangles
+ if (i_bnds.isEmpty()) {
+ // Nothing to do
+ return;
+ }
+
+ // Determine visibility of the paste area
+ GEN_TVisibility v = t_bnds.getVisibility(p_bnds);
+ if (v == GEN_kNotVisible) return;
+ if (v == GEN_kPartiallyVisible) {
+ // Clipping is needed
+ if (p_bnds.m_l < 0) {
+ i_bnds.m_l += -p_bnds.m_l;
+ p_bnds.m_l = 0;
+ }
+ if (p_bnds.m_t < 0) {
+ i_bnds.m_t += -p_bnds.m_t;
+ p_bnds.m_t = 0;
+ }
+ GEN_TInt32 d = t_bnds.getWidth();
+ if (p_bnds.m_r > d) {
+ i_bnds.m_r -= p_bnds.m_r - d;
+ p_bnds.m_r = d;
+ }
+ d = t_bnds.getHeight();
+ if (p_bnds.m_b > d) {
+ i_bnds.m_b -= p_bnds.m_b - d;
+ p_bnds.m_b = d;
+ }
+ }
+
+ IMG_ColorRGBA srcColor;
+ IMG_ColorRGBA desColor;
+
+ // Iterate through the rows
+ for (int r = 0; r < p_bnds.getHeight(); r++) {
+ // Park pixel pointers at the start pixels
+ TPixelPtr srcPtr = src.getPixelPtr(i_bnds.m_l, i_bnds.m_t + r);
+ TPixelPtr desPtr = getPixelPtr(p_bnds.m_l, p_bnds.m_t + r);
+ // Iterate through the columns
+ for (int c = 0; c < p_bnds.getWidth(); c++) {
+ // Retrieve colors from source and destination pixmaps
+ getColor(*srcPtr, srcColor);
+ getColor(*desPtr, desColor);
+ // Blend the colors
+ desColor.blendColor(srcColor);
+ // Write color back to destination pixmap
+ *desPtr = getPixelValue(desColor);
+ srcPtr++;
+ desPtr++;
+ }
+ }
+}
diff --git a/intern/img/intern/Makefile b/intern/img/intern/Makefile
new file mode 100644
index 00000000000..824699f49bc
--- /dev/null
+++ b/intern/img/intern/Makefile
@@ -0,0 +1,43 @@
+#
+# $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.
+#
+# 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 *****
+# Makefile for the img library
+
+LIBNAME = img
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I../../generic/extern
+CPPFLAGS += -I../extern
+CPPFLAGS += -I../intern
+
diff --git a/intern/img/make/msvc/img.dsp b/intern/img/make/msvc/img.dsp
new file mode 100644
index 00000000000..5110bdbb200
--- /dev/null
+++ b/intern/img/make/msvc/img.dsp
@@ -0,0 +1,126 @@
+# Microsoft Developer Studio Project File - Name="img" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=img - 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 "img.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 "img.mak" CFG="img - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "img - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "img - 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)" == "img - 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\img\windows\"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\img\windows\"
+# 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 "../../../generic/extern" /I "../extern" /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
+
+!ELSEIF "$(CFG)" == "img - 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\img\windows\debug"
+# PROP Intermediate_Dir "..\..\..\..\..\obj\img\windows\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 "../../../generic/extern" /I "../extern" /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "img - Win32 Release"
+# Name "img - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\IMG_Pixmap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IMG_PixmapRGBA32.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\IMG_Color.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IMG_MemPtr.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\extern\IMG_Pixmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\extern\IMG_PixmapRGBA32.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/intern/img/make/msvc/img.dsw b/intern/img/make/msvc/img.dsw
new file mode 100644
index 00000000000..433f994ce5c
--- /dev/null
+++ b/intern/img/make/msvc/img.dsw
@@ -0,0 +1,41 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "generic"="..\..\..\generic\make\msvc\generic.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "img"=".\img.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/memutil/MEM_NonCopyable.h b/intern/memutil/MEM_NonCopyable.h
new file mode 100644
index 00000000000..88284d53803
--- /dev/null
+++ b/intern/memutil/MEM_NonCopyable.h
@@ -0,0 +1,59 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_NonCopyable_h
+
+#define NAN_INCLUDED_NonCopyable_h
+
+/**
+ * Simple class that makes sure sub classes cannot
+ * generate standard copy constructors.
+ * If you want to make sure that your class does
+ * not have any of these cheesy hidden constructors
+ * inherit from this class.
+ */
+
+class MEM_NonCopyable {
+protected :
+
+ MEM_NonCopyable(
+ ) {
+ };
+
+private :
+
+ MEM_NonCopyable (const MEM_NonCopyable *);
+ MEM_NonCopyable (const MEM_NonCopyable &);
+};
+
+#endif
+
+
diff --git a/intern/memutil/MEM_RefCountPtr.h b/intern/memutil/MEM_RefCountPtr.h
new file mode 100644
index 00000000000..fb563109087
--- /dev/null
+++ b/intern/memutil/MEM_RefCountPtr.h
@@ -0,0 +1,294 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MEM_RefCountPtr_h
+
+#define NAN_INCLUDED_MEM_RefCountPtr_h
+
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include <stdlib.h> // for NULL !
+
+/**
+ * @section MEM_RefCountable
+ * This is a base class for reference countable objects.
+ * If you want an object to be shared using a reference
+ * counted system derrivce from this class. All subclasses
+ * should insist that they are created on the heap, this
+ * can be done by makeing all constructors private and
+ * defining a static New() method that returns a ref counted
+ * ptr to a new()ly allocated instance.
+ *
+ * @section Example subclass
+ *
+ *
+ * class MySharedObject : public MEM_RefCountable {
+ *
+ * private :
+ * MySharedObject() : MEM_RefCountable() { //class specific initialization};
+ * MySharedObject(const MySharedObject &other) // not implemented
+ * public :
+ * static
+ * MEM_RefCountPtr<MySharedObject>
+ * New(
+ * ) {
+ * return MEM_RefCountPtr<MySharedObject>( new MySharedObject());
+ * }
+ *
+ * // other member functions
+ * };
+ *
+ * Alternitively you may first wish to define a fully functional
+ * class and then define a reference counting wrapper for this class.
+ * This is useful when the base type can be used without reference
+ * counting.
+ *
+ * E.g.
+ * class UsefullClass {
+ * private :
+ * ...
+ * public :
+ *
+ * UsefullClass()
+ * UsefullMethod(...)
+ * AnotherUsefullMethod(...)
+ * };
+ *
+ * class RcUsefullClass : public UsefullClass, public MEM_RefCountable
+ * {
+ * private :
+ * // Override base class public constructor --- forces
+ * // use of New(...)
+ * RcUsefullClass(...)
+ * public :
+ *
+ * // Override each public constructor of UsefullClass with
+ * // an equivalent static New method returning a MEM_RefCountPtr
+ *
+ * static
+ * MEM_RefCountPtr<RcUsefullClass>
+ * New(...){
+ * return MEM_RefCountPtr<RcUsefullClass> output(
+ * new UsefullClass(...)
+ * );
+ * }
+ *
+ * // warning never call destructor directly allow ref counting
+ * // mechanism to handle object lifetime.
+ * ~RcUsefullClass();
+ * };
+ *
+ *
+ */
+
+class MEM_RefCountable {
+private :
+
+ /**
+ * The reference count!
+ * We use mutable here because we would like to
+ * share references of const objects!
+ * Maybe should think about having decRef()
+ * another value because we should not be deleting
+ * non-const objects
+ */
+
+ mutable int m_count;
+
+protected :
+
+ /**
+ * Protected constructors
+ * This class is not for direct instanciation. Sub classes
+ * should only be allocated on the heap.
+ */
+
+ MEM_RefCountable (
+ ) :
+ m_count (0)
+ {
+ };
+
+ MEM_RefCountable (
+ const MEM_RefCountable & other
+ ) :
+ m_count (0)
+ {
+ }
+
+public :
+
+ void
+ IncRef(
+ ) const {
+ m_count++;
+ }
+
+ int
+ DecRef(
+ ) {
+ return (--m_count);
+ }
+
+ ~MEM_RefCountable(
+ ) {
+ //nothing to do
+ }
+};
+
+/**
+ * @section MEM_RefCountPtr
+ */
+
+template
+ < class T >
+class MEM_RefCountPtr {
+
+public :
+
+ /**
+ * Construction from reference - share ownership with
+ * the right hand side.
+ */
+
+ MEM_RefCountPtr(
+ const MEM_RefCountPtr &rhs
+ ) : m_val (NULL) {
+ ShareOwnership(rhs.m_val);
+ }
+
+ /**
+ * Construction from ptr - this class shares
+ * ownership of object val.
+ */
+
+ MEM_RefCountPtr(
+ const T* val
+ ) :
+ m_val (NULL)
+ {
+ ShareOwnership(val);
+ }
+
+ /**
+ * Defalut constructor
+ */
+
+ MEM_RefCountPtr(
+ ) :
+ m_val (NULL)
+ {
+ }
+
+ /**
+ * Type conversion from this class to the type
+ * of a pointer to the template parameter.
+ * This means you can pass an instance of this class
+ * to a function expecting a ptr of type T.
+ */
+
+ operator T * () const {
+ return m_val;
+ }
+
+
+ MEM_RefCountPtr & operator=(
+ const MEM_RefCountPtr &rhs
+ ) {
+ if (this->m_val != rhs.m_val) {
+ ReleaseOwnership();
+ ShareOwnership(rhs.m_val);
+ }
+ return *this;
+ }
+
+ /**
+ * Overload the operator -> so that it's possible to access
+ * all the normal methods of the internal ptr.
+ */
+
+ T * operator->() const {
+ return m_val;
+ }
+
+ /**
+ * Returrn a reference to the shared object.
+ */
+
+ T&
+ Ref(
+ ) {
+ return *m_val;
+ }
+
+ /**
+ * Destructor - deletes object if it's ref count is zero.
+ */
+
+ ~MEM_RefCountPtr(
+ ) {
+ ReleaseOwnership();
+ }
+
+private :
+
+ /// The ptr owned by this class.
+ T * m_val;
+
+ void
+ ShareOwnership(
+ const T * val
+ ) {
+ if (val != NULL) {
+ val->IncRef();
+ }
+ m_val = const_cast<T *>(val);
+ }
+
+ void
+ ReleaseOwnership(
+ ) {
+ if (m_val) {
+ if (m_val->DecRef() == 0) {
+ delete(m_val);
+ m_val = NULL;
+ }
+ }
+ }
+
+};
+
+#endif
diff --git a/intern/memutil/MEM_RefCounted.h b/intern/memutil/MEM_RefCounted.h
new file mode 100644
index 00000000000..3531f700ee3
--- /dev/null
+++ b/intern/memutil/MEM_RefCounted.h
@@ -0,0 +1,120 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+#ifndef _H_MEM_REF_COUNTED
+#define _H_MEM_REF_COUNTED
+
+
+/**
+ * An object with reference counting.
+ * Base class for objects with reference counting.
+ * When a shared object is ceated, it has reference count == 1.
+ * If the the reference count of a shared object reaches zero, the object self-destructs.
+ * The default destructor of this object has been made protected on purpose.
+ * This disables the creation of shared objects on the stack.
+ *
+ * @author Maarten Gribnau
+ * @date March 31, 2001
+ */
+
+class MEM_RefCounted {
+public:
+ /**
+ * Constructs a a shared object.
+ */
+ MEM_RefCounted() : m_refCount(1)
+ {
+ }
+
+ /**
+ * Returns the reference count of this object.
+ * @return the reference count.
+ */
+ inline virtual int getRef() const;
+
+ /**
+ * Increases the reference count of this object.
+ * @return the new reference count.
+ */
+ inline virtual int incRef();
+
+ /**
+ * Decreases the reference count of this object.
+ * If the the reference count reaches zero, the object self-destructs.
+ * @return the new reference count.
+ */
+ inline virtual int decRef();
+
+protected:
+ /**
+ * Destructs a shared object.
+ * The destructor is protected to force the use of incRef and decRef.
+ */
+ virtual ~MEM_RefCounted()
+ {
+ }
+
+protected:
+ /// The reference count.
+ int m_refCount;
+};
+
+
+inline int MEM_RefCounted::getRef() const
+{
+ return m_refCount;
+}
+
+inline int MEM_RefCounted::incRef()
+{
+ return ++m_refCount;
+}
+
+inline int MEM_RefCounted::decRef()
+{
+ m_refCount--;
+ if (m_refCount == 0) {
+ delete this;
+ return 0;
+ }
+ return m_refCount;
+}
+
+
+#endif // _H_MEM_REF_COUNTED \ No newline at end of file
diff --git a/intern/memutil/MEM_RefCountedC-Api.h b/intern/memutil/MEM_RefCountedC-Api.h
new file mode 100644
index 00000000000..abaef47604c
--- /dev/null
+++ b/intern/memutil/MEM_RefCountedC-Api.h
@@ -0,0 +1,90 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * Interface for C access to functionality relating to shared objects in the foundation library.
+ * @author Maarten Gribnau
+ * @date June 17, 2001
+ */
+
+#ifndef _H_MEM_REF_COUNTED_C_API
+#define _H_MEM_REF_COUNTED_C_API
+
+/** A pointer to a private object. */
+typedef struct MEM_TOpaqueObject* MEM_TObjectPtr;
+/** A pointer to a shared object. */
+typedef MEM_TObjectPtr MEM_TRefCountedObjectPtr;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * A shared object in an object with reference counting.
+ * When a shared object is ceated, it has reference count == 1.
+ * If the the reference count of a shared object reaches zero, the object self-destructs.
+ * The default constrcutor and destructor of this object have been made protected on purpose.
+ * This disables the creation and disposal of shared objects on the stack.
+ */
+
+/**
+ * Returns the reference count of this object.
+ * @param shared The object to query.
+ * @return The current reference count.
+ */
+extern int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared);
+
+/**
+ * Increases the reference count of this object.
+ * @param shared The object to query.
+ * @return The new reference count.
+ */
+extern int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared);
+
+/**
+ * Decreases the reference count of this object.
+ * If the the reference count reaches zero, the object self-destructs.
+ * @param shared The object to query.
+ * @return The new reference count.
+ */
+extern int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _H_MEM_REF_COUNTED_C_API \ No newline at end of file
diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h
new file mode 100644
index 00000000000..b47b2bdc1a4
--- /dev/null
+++ b/intern/memutil/MEM_SmartPtr.h
@@ -0,0 +1,240 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef NAN_INCLUDED_MEM_SmartPtr_h
+
+#define NAN_INCLUDED_MEM_SmartPtr_h
+
+/**
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include <stdlib.h> // for NULL !
+
+/**
+ * @section MEM_SmartPtr
+ * This class defines a smart pointer similar to that defined in
+ * the Standard Template Library but without the painful get()
+ * semantics to access the internal c style pointer.
+ *
+ * It is often useful to explicitely decalre ownership of memory
+ * allocated on the heap within class or function scope. This
+ * class helps you to encapsulate this ownership within a value
+ * type. When an instance of this class goes out of scope it
+ * makes sure that any memory associated with it's internal pointer
+ * is deleted. It can help to inform users of an aggregate class
+ * that it owns instances of it's members and these instances
+ * should not be shared. This is not reliably enforcable in C++
+ * but this class attempts to make the 1-1 relationship clear.
+ *
+ * @section Example usage
+ *
+ * class foo {
+ * ...constructors accessors etc.
+ * int x[1000];
+ * }
+ *
+ * class bar {
+ * public :
+ * static
+ * bar *
+ * New(
+ * ) {
+ * MEM_SmartPtr<foo> afoo = new foo();
+ * MEM_SmartPtr<bar> that = new bar();
+ *
+ * if (foo == NULL || that == NULL) return NULL;
+ *
+ * that->m_foo = afoo.Release();
+ * return that.Release();
+ * }
+ *
+ * ~bar() {
+ * // smart ptr takes care of deletion
+ * }
+ * private :
+ * MEM_SmartPtr<foo> m_foo;
+ * }
+ *
+ * You my also safely construct vectors of MEM_SmartPtrs and
+ * have the vector own stuff you put into it.
+ *
+ * e.g.
+ * {
+ * std::vector<MEM_SmartPtr<foo> > foo_vector;
+ * foo_vector.push_back( new foo());
+ * foo_vector.push_back( new foo());
+ *
+ * foo_vector[0]->bla();
+ * } // foo_vector out of scope => heap memory freed for both foos
+ *
+ * @warning this class should only be used for objects created
+ * on the heap via the new function. It will not behave correctly
+ * if you pass ptrs to objects created with new[] nor with
+ * objects declared on the stack. Doing this is likely to crash
+ * the program or lead to memory leaks.
+ */
+
+template
+ < class T >
+class MEM_SmartPtr {
+
+public :
+
+ /**
+ * Construction from reference - this class
+ * always assumes ownership from the rhs.
+ */
+
+ MEM_SmartPtr(
+ const MEM_SmartPtr &rhs
+ ){
+ m_val = rhs.Release();
+ }
+
+ /**
+ * Construction from ptr - this class always
+ * assumes that it now owns the memory associated with the
+ * ptr.
+ */
+
+ MEM_SmartPtr(
+ T* val
+ ) :
+ m_val (val)
+ {
+ }
+
+ /**
+ * Defalut constructor
+ */
+
+ MEM_SmartPtr(
+ ) :
+ m_val (NULL)
+ {
+ }
+
+ /**
+ * Type conversion from this class to the type
+ * of a pointer to the template parameter.
+ * This means you can pass an instance of this class
+ * to a function expecting a ptr of type T.
+ */
+
+ operator T * () const {
+ return m_val;
+ }
+
+ /**
+ * Return a reference to the internal ptr class.
+ * Use with care when you now that the internal ptr
+ * is not NULL!
+ */
+
+ T &
+ Ref(
+ ) const {
+ return *m_val;
+ }
+
+ /**
+ * Assignment operator - ownership is transfered from rhs to lhs.
+ * There is an intenional side-effect of function of transferring
+ * ownership from the const parameter rhs. This is to insure
+ * the 1-1 relationship.
+ * The object associated with this instance is deleted if it
+ * is not the same as that contained in the rhs.
+ */
+
+ MEM_SmartPtr & operator=(
+ const MEM_SmartPtr &rhs
+ ) {
+ if (this->m_val != rhs.m_val) {
+ delete this->m_val;
+ }
+
+ this->m_val = rhs.Release();
+ return *this;
+ }
+
+ /**
+ * Overload the operator -> so that it's possible to access
+ * all the normal methods of the internal ptr.
+ */
+
+ T * operator->() const {
+ return m_val;
+ }
+
+ /**
+ * Caller takes ownership of the object - the object will not
+ * be deleted when the ptr goes out of scope.
+ */
+
+ T *
+ Release(
+ ) const {
+ T* temp = m_val;
+ (const_cast<MEM_SmartPtr *>(this))->m_val = NULL;
+ return temp;
+ }
+
+ /**
+ * Force destruction of the internal object.
+ */
+
+ void
+ Delete(
+ ) {
+ delete (m_val);
+ m_val = NULL;
+ }
+
+ /**
+ * Destructor - deletes object if it exists
+ */
+
+ ~MEM_SmartPtr(
+ ) {
+ delete (m_val);
+ }
+
+private :
+
+ /// The ptr owned by this class.
+ T * m_val;
+};
+
+#endif
diff --git a/intern/memutil/Makefile b/intern/memutil/Makefile
new file mode 100644
index 00000000000..e163fa63eff
--- /dev/null
+++ b/intern/memutil/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# memutil main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = memutil
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+#not yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_MEMUTIL) ] || mkdir $(NAN_MEMUTIL)
+ @[ -d $(NAN_MEMUTIL)/include ] || mkdir $(NAN_MEMUTIL)/include
+ @[ -d $(NAN_MEMUTIL)/lib ] || mkdir $(NAN_MEMUTIL)/lib
+ @[ -d $(NAN_MEMUTIL)/lib/debug ] || mkdir $(NAN_MEMUTIL)/lib/debug
+ cp -f $(DIR)/libmemutil.a $(NAN_MEMUTIL)/lib/
+ cp -f $(DIR)/debug/libmemutil.a $(NAN_MEMUTIL)/lib/debug
+ cp -f *.h $(NAN_MEMUTIL)/include/
+
diff --git a/intern/memutil/intern/MEM_RefCountedC-Api.cpp b/intern/memutil/intern/MEM_RefCountedC-Api.cpp
new file mode 100644
index 00000000000..92f02ac78fa
--- /dev/null
+++ b/intern/memutil/intern/MEM_RefCountedC-Api.cpp
@@ -0,0 +1,64 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date Jun 17, 2001
+ */
+
+#include "MEM_RefCountedC-Api.h"
+
+#include "MEM_RefCounted.h"
+
+
+
+int MEM_RefCountedGetRef(MEM_TRefCountedObjectPtr shared)
+{
+ return shared ? ((MEM_RefCounted*)shared)->getRef() : 0;
+}
+
+
+int MEM_RefCountedIncRef(MEM_TRefCountedObjectPtr shared)
+{
+ return shared ? ((MEM_RefCounted*)shared)->incRef() : 0;
+}
+
+
+int MEM_RefCountedDecRef(MEM_TRefCountedObjectPtr shared)
+{
+ return shared ? ((MEM_RefCounted*)shared)->decRef() : 0;
+}
+
+
+
diff --git a/intern/memutil/intern/Makefile b/intern/memutil/intern/Makefile
new file mode 100644
index 00000000000..0d0d3af6327
--- /dev/null
+++ b/intern/memutil/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# memutil intern Makefile
+#
+
+LIBNAME = memutil
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I..
+
diff --git a/intern/memutil/make/msvc_60/memutil.dsp b/intern/memutil/make/msvc_60/memutil.dsp
new file mode 100644
index 00000000000..85e903f8764
--- /dev/null
+++ b/intern/memutil/make/msvc_60/memutil.dsp
@@ -0,0 +1,134 @@
+# Microsoft Developer Studio Project File - Name="memutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=memutil - 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 "memutil.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 "memutil.mak" CFG="memutil - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "memutil - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "memutil - 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)" == "memutil - 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/memutil"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/memutil"
+# 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 /Ob2 /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:"Release\memutil.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\memutil\include" ECHO Copying lib COPY "Release\memutil.lib" "..\..\..\..\lib\windows\memutil\lib\memutil.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "memutil - 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/memutil/debug"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/memutil/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 "../.." /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:"Debug\memutil.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\memutil\include" ECHO Copying lib COPY "Debug\memutil.lib" "..\..\..\..\lib\windows\memutil\lib\debug\memutil.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\memutil\lib\debug\" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "memutil - Win32 Release"
+# Name "memutil - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\..\intern\MEM_RefCountedC-Api.cpp"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\MEM_NonCopyable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\MEM_RefCounted.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\MEM_RefCountedC-Api.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\MEM_RefCountPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\MEM_SmartPtr.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/intern/memutil/make/msvc_60/memutil.dsw b/intern/memutil/make/msvc_60/memutil.dsw
new file mode 100644
index 00000000000..2ac4d9e7a48
--- /dev/null
+++ b/intern/memutil/make/msvc_60/memutil.dsw
@@ -0,0 +1,30 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+
+###############################################################################
+
+Project: "memutil"=".\memutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/intern/moto/Makefile b/intern/moto/Makefile
new file mode 100644
index 00000000000..97b4b321d99
--- /dev/null
+++ b/intern/moto/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# moto main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = moto
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+#not ready yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_MOTO) ] || mkdir $(NAN_MOTO)
+ @[ -d $(NAN_MOTO)/include ] || mkdir $(NAN_MOTO)/include
+ @[ -d $(NAN_MOTO)/lib ] || mkdir $(NAN_MOTO)/lib
+ @[ -d $(NAN_MOTO)/lib/debug ] || mkdir $(NAN_MOTO)/lib/debug
+ cp -f $(DIR)/libmoto.a $(NAN_MOTO)/lib/
+ cp -f $(DIR)/debug/libmoto.a $(NAN_MOTO)/lib/debug/
+ cp -f include/*.h $(NAN_MOTO)/include/
+
diff --git a/intern/moto/include/GEN_List.h b/intern/moto/include/GEN_List.h
new file mode 100644
index 00000000000..c7f974430f3
--- /dev/null
+++ b/intern/moto/include/GEN_List.h
@@ -0,0 +1,120 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#ifndef GEN_LIST_H
+#define GEN_LIST_H
+
+class GEN_Link {
+public:
+ GEN_Link() : m_next(0), m_prev(0) {}
+ GEN_Link(GEN_Link *next, GEN_Link *prev) : m_next(next), m_prev(prev) {}
+
+ GEN_Link *getNext() const { return m_next; }
+ GEN_Link *getPrev() const { return m_prev; }
+
+ bool isHead() const { return m_prev == 0; }
+ bool isTail() const { return m_next == 0; }
+
+ void insertBefore(GEN_Link *link) {
+ m_next = link;
+ m_prev = link->m_prev;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void insertAfter(GEN_Link *link) {
+ m_next = link->m_next;
+ m_prev = link;
+ m_next->m_prev = this;
+ m_prev->m_next = this;
+ }
+
+ void remove() {
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
+
+private:
+ GEN_Link *m_next;
+ GEN_Link *m_prev;
+};
+
+class GEN_List {
+public:
+ GEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+ GEN_Link *getHead() const { return m_head.getNext(); }
+ GEN_Link *getTail() const { return m_tail.getPrev(); }
+
+ void addHead(GEN_Link *link) { link->insertAfter(&m_head); }
+ void addTail(GEN_Link *link) { link->insertBefore(&m_tail); }
+
+private:
+ GEN_Link m_head;
+ GEN_Link m_tail;
+};
+
+#endif
+
+
+
diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h
new file mode 100644
index 00000000000..a1d0dbfe73a
--- /dev/null
+++ b/intern/moto/include/GEN_Map.h
@@ -0,0 +1,152 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef GEN_MAP_H
+
+#define GEN_MAP_H
+
+template <class Key, class Value>
+class GEN_Map {
+private:
+ struct Entry {
+ Entry (Entry *next, Key key, Value value) :
+ m_next(next),
+ m_key(key),
+ m_value(value) {}
+
+ Entry *m_next;
+ Key m_key;
+ Value m_value;
+ };
+
+public:
+ GEN_Map(int num_buckets = 100) : m_num_buckets(num_buckets) {
+ m_buckets = new Entry *[num_buckets];
+ for (int i = 0; i < num_buckets; ++i) {
+ m_buckets[i] = 0;
+ }
+ }
+
+ int size() {
+ int count=0;
+ for (int i=0;i<m_num_buckets;i++)
+ {
+ Entry* bucket = m_buckets[i];
+ while(bucket)
+ {
+ bucket = bucket->m_next;
+ count++;
+ }
+ }
+ return count;
+ }
+
+ Value* at(int index) {
+ int count=0;
+ for (int i=0;i<m_num_buckets;i++)
+ {
+ Entry* bucket = m_buckets[i];
+ while(bucket)
+ {
+ if (count==index)
+ {
+ return &bucket->m_value;
+ }
+ bucket = bucket->m_next;
+ count++;
+ }
+ }
+ return 0;
+ }
+
+ void clear() {
+ for (int i = 0; i < m_num_buckets; ++i) {
+ Entry *entry_ptr = m_buckets[i];
+
+ while (entry_ptr != 0) {
+ Entry *tmp_ptr = entry_ptr->m_next;
+ delete entry_ptr;
+ entry_ptr = tmp_ptr;
+ }
+ m_buckets[i] = 0;
+ }
+ }
+
+ ~GEN_Map() {
+ clear();
+ delete [] m_buckets;
+ }
+
+ void insert(const Key& key, const Value& value) {
+ Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets];
+ while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) {
+ entry_ptr = entry_ptr->m_next;
+ }
+
+ if (entry_ptr != 0) {
+ entry_ptr->m_value = value;
+ }
+ else {
+ Entry **bucket = &m_buckets[key.hash() % m_num_buckets];
+ *bucket = new Entry(*bucket, key, value);
+ }
+ }
+
+ void remove(const Key& key) {
+ Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets];
+ while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) {
+ entry_ptr = &(*entry_ptr)->m_next;
+ }
+
+ if (*entry_ptr != 0) {
+ Entry *tmp_ptr = (*entry_ptr)->m_next;
+ delete *entry_ptr;
+ *entry_ptr = tmp_ptr;
+ }
+ }
+
+ Value *operator[](Key key) {
+ Entry *bucket = m_buckets[key.hash() % m_num_buckets];
+ while ((bucket != 0) && !(key == bucket->m_key)) {
+ bucket = bucket->m_next;
+ }
+ return bucket != 0 ? &bucket->m_value : 0;
+ }
+
+private:
+ int m_num_buckets;
+ Entry **m_buckets;
+};
+
+#endif
+
+
+
diff --git a/intern/moto/include/MT_CmMatrix4x4.h b/intern/moto/include/MT_CmMatrix4x4.h
new file mode 100644
index 00000000000..a6e259fbe17
--- /dev/null
+++ b/intern/moto/include/MT_CmMatrix4x4.h
@@ -0,0 +1,147 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef INCLUDED_MT_CmMatrix4x4
+
+#define INCLUDED_MT_CmMatrix4x4
+
+/**
+ * A 4x4 matrix. This is an OpenGl style matrix (column major) meaning
+ * that the vector {m[0][0],m[0][1],m[0][2],m[0][3]} is the first column of
+ * the matrix , the same as what you get if you transform {1,0,0,0}.
+ * This makes it easy to transform stuff to OpenGl. Please note that the
+ * the other MoTo matrices are row major.
+ *
+ * This class should be deprecated in favour of the more consistent
+ * MT_Matrix4x4. Please do not start using this class.
+ */
+
+#include "MT_Scalar.h"
+
+class MT_Point3;
+class MT_Vector3;
+
+class MT_CmMatrix4x4
+{
+
+public :
+
+ MT_CmMatrix4x4(
+ const float value[4][4]
+ );
+
+ MT_CmMatrix4x4(
+ );
+
+
+ MT_CmMatrix4x4(
+ const double value[16]
+ );
+
+ MT_CmMatrix4x4(
+ const MT_CmMatrix4x4 & other
+ );
+
+ MT_CmMatrix4x4(
+ const MT_Point3& orig,
+ const MT_Vector3& dir,
+ const MT_Vector3 up
+ );
+
+ void
+ Identity(
+ );
+
+ void
+ SetMatrix(
+ const MT_CmMatrix4x4 & other
+ );
+
+ double*
+ getPointer(
+ );
+
+ const
+ double*
+ getPointer(
+ ) const;
+
+ void
+ setElem(
+ int pos,
+ double newvalue
+ );
+
+ MT_Vector3
+ GetRight(
+ ) const;
+
+ MT_Vector3
+ GetUp(
+ ) const;
+
+ MT_Vector3
+ GetDir(
+ ) const;
+
+ MT_Point3
+ GetPos(
+ ) const;
+
+ void
+ SetPos(
+ const MT_Vector3 & v
+ );
+
+ double&
+ operator (
+ ) (int row,int col) { return m_V[col][row]; }
+
+ static
+ MT_CmMatrix4x4
+ Perspective(
+ MT_Scalar inLeft,
+ MT_Scalar inRight,
+ MT_Scalar inBottom,
+ MT_Scalar inTop,
+ MT_Scalar inNear,
+ MT_Scalar inFar
+ );
+
+protected:
+ union
+ {
+ double m_V[4][4];
+ double m_Vflat[16];
+ };
+};
+
+#endif //MT_CmMatrix4x4
diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h
new file mode 100755
index 00000000000..01e5f01b539
--- /dev/null
+++ b/intern/moto/include/MT_Matrix3x3.h
@@ -0,0 +1,214 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_MATRIX3X3_H
+#define MT_MATRIX3X3_H
+
+#include <MT_assert.h>
+
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+
+class MT_Matrix3x3 {
+public:
+ MT_Matrix3x3() {}
+ MT_Matrix3x3(const float *m) { setValue(m); }
+ MT_Matrix3x3(const double *m) { setValue(m); }
+ MT_Matrix3x3(const MT_Quaternion& q) { setRotation(q); }
+
+ MT_Matrix3x3(const MT_Quaternion& q, const MT_Vector3& s) {
+ setRotation(q);
+ scale(s[0], s[1], s[2]);
+ }
+
+ MT_Matrix3x3(const MT_Vector3& euler) { setEuler(euler); }
+ MT_Matrix3x3(const MT_Vector3& euler, const MT_Vector3& s) {
+ setEuler(euler);
+ scale(s[0], s[1], s[2]);
+ }
+
+ MT_Matrix3x3(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz,
+ MT_Scalar yx, MT_Scalar yy, MT_Scalar yz,
+ MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) {
+ setValue(xx, xy, xz,
+ yx, yy, yz,
+ zx, zy, zz);
+ }
+
+ MT_Vector3& operator[](int i) { return m_el[i]; }
+ const MT_Vector3& operator[](int i) const { return m_el[i]; }
+
+ void setValue(const float *m) {
+ m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
+ m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++;
+ m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
+ }
+
+ void setValue(const double *m) {
+ m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
+ m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++;
+ m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
+ }
+
+ void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz,
+ MT_Scalar yx, MT_Scalar yy, MT_Scalar yz,
+ MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) {
+ m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz;
+ m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz;
+ m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz;
+ }
+
+ void setRotation(const MT_Quaternion& q) {
+ MT_Scalar d = q.length2();
+ MT_assert(!MT_fuzzyZero2(d));
+ MT_Scalar s = MT_Scalar(2.0) / d;
+ MT_Scalar xs = q[0] * s, ys = q[1] * s, zs = q[2] * s;
+ MT_Scalar wx = q[3] * xs, wy = q[3] * ys, wz = q[3] * zs;
+ MT_Scalar xx = q[0] * xs, xy = q[0] * ys, xz = q[0] * zs;
+ MT_Scalar yy = q[1] * ys, yz = q[1] * zs, zz = q[2] * zs;
+ setValue(MT_Scalar(1.0) - (yy + zz), xy - wz , xz + wy,
+ xy + wz , MT_Scalar(1.0) - (xx + zz), yz - wx,
+ xz - wy , yz + wx, MT_Scalar(1.0) - (xx + yy));
+ }
+
+ /**
+ * setEuler
+ * @param euler a const reference to a MT_Vector3 of euler angles
+ * These angles are used to produce a rotation matrix. The euler
+ * angles are applied in ZYX order. I.e a vector is first rotated
+ * about X then Y and then Z
+ **/
+
+ void setEuler(const MT_Vector3& euler) {
+ MT_Scalar ci = cos(euler[0]);
+ MT_Scalar cj = cos(euler[1]);
+ MT_Scalar ch = cos(euler[2]);
+ MT_Scalar si = sin(euler[0]);
+ MT_Scalar sj = sin(euler[1]);
+ MT_Scalar sh = sin(euler[2]);
+ MT_Scalar cc = ci * ch;
+ MT_Scalar cs = ci * sh;
+ MT_Scalar sc = si * ch;
+ MT_Scalar ss = si * sh;
+
+ setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+ cj * sh, sj * ss + cc, sj * cs - sc,
+ -sj, cj * si, cj * ci);
+ }
+
+ void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
+ m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z;
+ m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z;
+ m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z;
+ }
+
+ MT_Matrix3x3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const {
+ return MT_Matrix3x3(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z,
+ m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z,
+ m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z);
+ }
+
+ void setIdentity() {
+ setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0),
+ MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0),
+ MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0));
+ }
+
+ void getValue(float *m) const {
+ *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = 0.0;
+ *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = 0.0;
+ *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m = 0.0;
+ }
+
+ void getValue(double *m) const {
+ *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = 0.0;
+ *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = 0.0;
+ *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m = 0.0;
+ }
+
+ MT_Quaternion getRotation() const;
+
+ MT_Matrix3x3& operator*=(const MT_Matrix3x3& m);
+
+ MT_Scalar tdot(int c, const MT_Vector3& v) const {
+ return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2];
+ }
+
+ MT_Scalar cofac(int r1, int c1, int r2, int c2) const {
+ return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+ }
+
+ MT_Scalar determinant() const;
+ MT_Matrix3x3 adjoint() const;
+
+ MT_Matrix3x3 absolute() const;
+
+ MT_Matrix3x3 transposed() const;
+ void transpose();
+
+ MT_Matrix3x3 inverse() const;
+ void invert();
+
+protected:
+
+ MT_Vector3 m_el[3];
+};
+
+MT_Vector3 operator*(const MT_Matrix3x3& m, const MT_Vector3& v);
+MT_Vector3 operator*(const MT_Vector3& v, const MT_Matrix3x3& m);
+MT_Matrix3x3 operator*(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
+
+MT_Matrix3x3 MT_multTransposeLeft(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
+MT_Matrix3x3 MT_multTransposeRight(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
+
+inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix3x3& m) {
+ return os << m[0] << GEN_endl << m[1] << GEN_endl << m[2] << GEN_endl;
+}
+
+#ifdef GEN_INLINED
+#include "MT_Matrix3x3.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Matrix3x3.inl b/intern/moto/include/MT_Matrix3x3.inl
new file mode 100644
index 00000000000..c581640ebfe
--- /dev/null
+++ b/intern/moto/include/MT_Matrix3x3.inl
@@ -0,0 +1,128 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Quaternion MT_Matrix3x3::getRotation() const {
+ static int next[3] = { 1, 2, 0 };
+
+ MT_Quaternion result;
+
+ MT_Scalar trace = m_el[0][0] + m_el[1][1] + m_el[2][2];
+
+ if (trace > 0.0)
+ {
+ MT_Scalar s = sqrt(trace + MT_Scalar(1.0));
+ result[3] = s * MT_Scalar(0.5);
+ s = MT_Scalar(0.5) / s;
+
+ result[0] = (m_el[2][1] - m_el[1][2]) * s;
+ result[1] = (m_el[0][2] - m_el[2][0]) * s;
+ result[2] = (m_el[1][0] - m_el[0][1]) * s;
+ }
+ else
+ {
+ int i = 0;
+ if (m_el[1][1] > m_el[0][0])
+ i = 1;
+ if (m_el[2][2] > m_el[i][i])
+ i = 2;
+
+ int j = next[i];
+ int k = next[j];
+
+ MT_Scalar s = sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + MT_Scalar(1.0));
+
+ result[i] = s * MT_Scalar(0.5);
+
+ s = MT_Scalar(0.5) / s;
+
+ result[3] = (m_el[k][j] - m_el[j][k]) * s;
+ result[j] = (m_el[j][i] + m_el[i][j]) * s;
+ result[k] = (m_el[k][i] + m_el[i][k]) * s;
+ }
+ return result;
+}
+
+GEN_INLINE MT_Matrix3x3& MT_Matrix3x3::operator*=(const MT_Matrix3x3& m) {
+ setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]),
+ m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]),
+ m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]));
+ return *this;
+}
+
+GEN_INLINE MT_Scalar MT_Matrix3x3::determinant() const {
+ return MT_triple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::absolute() const {
+ return
+ MT_Matrix3x3(MT_abs(m_el[0][0]), MT_abs(m_el[0][1]), MT_abs(m_el[0][2]),
+ MT_abs(m_el[1][0]), MT_abs(m_el[1][1]), MT_abs(m_el[1][2]),
+ MT_abs(m_el[2][0]), MT_abs(m_el[2][1]), MT_abs(m_el[2][2]));
+}
+
+GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::transposed() const {
+ return MT_Matrix3x3(m_el[0][0], m_el[1][0], m_el[2][0],
+ m_el[0][1], m_el[1][1], m_el[2][1],
+ m_el[0][2], m_el[1][2], m_el[2][2]);
+}
+
+GEN_INLINE void MT_Matrix3x3::transpose() {
+ *this = transposed();
+}
+
+GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::adjoint() const {
+ return
+ MT_Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+ cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+ cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+GEN_INLINE MT_Matrix3x3 MT_Matrix3x3::inverse() const {
+ MT_Vector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+ MT_Scalar det = MT_dot((*this)[0], co);
+ MT_assert(!MT_fuzzyZero2(det));
+ MT_Scalar s = MT_Scalar(1.0) / det;
+ return
+ MT_Matrix3x3(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+ co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+GEN_INLINE void MT_Matrix3x3::invert() {
+ *this = inverse();
+}
+
+GEN_INLINE MT_Vector3 operator*(const MT_Matrix3x3& m, const MT_Vector3& v) {
+ return MT_Vector3(MT_dot(m[0], v), MT_dot(m[1], v), MT_dot(m[2], v));
+}
+
+GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v, const MT_Matrix3x3& m) {
+ return MT_Vector3(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v));
+}
+
+GEN_INLINE MT_Matrix3x3 operator*(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) {
+ return
+ MT_Matrix3x3(m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]),
+ m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]),
+ m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]));
+}
+
+GEN_INLINE MT_Matrix3x3 MT_multTransposeLeft(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) {
+ return MT_Matrix3x3(
+ m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+ m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+ m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+ m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+ m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+ m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+ m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+ m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+ m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+
+GEN_INLINE MT_Matrix3x3 MT_multTransposeRight(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2) {
+ return
+ MT_Matrix3x3(m1[0].dot(m2[0]), m1[0].dot(m2[1]), m1[0].dot(m2[2]),
+ m1[1].dot(m2[0]), m1[1].dot(m2[1]), m1[1].dot(m2[2]),
+ m1[2].dot(m2[0]), m1[2].dot(m2[1]), m1[2].dot(m2[2]));
+
+}
diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h
new file mode 100755
index 00000000000..0376db9e122
--- /dev/null
+++ b/intern/moto/include/MT_Matrix4x4.h
@@ -0,0 +1,250 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * A 4x4 matrix compatible with other stuff.
+ */
+
+#ifndef MT_MATRIX4X4_H
+#define MT_MATRIX4X4_H
+
+#include <MT_assert.h>
+
+#include "MT_Vector4.h"
+#include "MT_Transform.h"
+
+// Row-major 4x4 matrix
+
+class MT_Matrix4x4 {
+public:
+ /**
+ * Empty contructor.
+ */
+ MT_Matrix4x4() {}
+ /**
+ * Initialize all fields with the values pointed at by m. A
+ * contigous block of 16 values is read. */
+ MT_Matrix4x4(const float *m) { setValue(m); }
+ /**
+ * Initialize all fields with the values pointed at by m. A
+ * contigous block of 16 values is read. */
+ MT_Matrix4x4(const double *m) { setValue(m); }
+
+ /**
+ * Initialise with these 16 explicit values.
+ */
+ MT_Matrix4x4(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw,
+ MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw,
+ MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw,
+ MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) {
+ setValue(xx, xy, xz, xw,
+ yx, yy, yz, yw,
+ zx, zy, zz, zw,
+ wx, wy, wz, ww);
+ }
+
+ /**
+ * Initialize from an MT_Transform.
+ */
+ MT_Matrix4x4(const MT_Transform &t) {
+
+ const MT_Matrix3x3 &basis = t.getBasis();
+ const MT_Vector3 &origin = t.getOrigin();
+
+ setValue(
+ basis[0][0],basis[0][1],basis[0][2],origin[0],
+ basis[1][0],basis[1][1],basis[1][2],origin[1],
+ basis[2][0],basis[2][1],basis[2][2],origin[2],
+ MT_Scalar(0),MT_Scalar(0),MT_Scalar(0),MT_Scalar(1)
+ );
+ }
+
+ /**
+ * Get the i-th row.
+ */
+ MT_Vector4& operator[](int i) { return m_el[i]; }
+ /**
+ * Get the i-th row.
+ */
+ const MT_Vector4& operator[](int i) const { return m_el[i]; }
+
+ /**
+ * Set the matrix to the values pointer at by m. A contiguous
+ * block of 16 values is copied. */
+ void setValue(const float *m) {
+ m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++;
+ m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++;
+ m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++;
+ m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m;
+ }
+
+ /**
+ * Set the matrix to the values pointer at by m. A contiguous
+ * block of 16 values is copied.
+ */
+ void setValue(const double *m) {
+ m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++;
+ m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++;
+ m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++;
+ m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m;
+ }
+
+ /**
+ * Set the matrix to these 16 explicit values.
+ */
+ void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw,
+ MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw,
+ MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw,
+ MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) {
+ m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz; m_el[0][3] = xw;
+ m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz; m_el[1][3] = yw;
+ m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz; m_el[2][3] = zw;
+ m_el[3][0] = wx; m_el[3][1] = wy; m_el[3][2] = wz; m_el[3][3] = ww;
+ }
+
+ /**
+ * Scale the columns of this matrix with x, y, z, w respectively.
+ */
+ void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
+ m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; m_el[0][3] *= w;
+ m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; m_el[1][3] *= w;
+ m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z; m_el[2][3] *= w;
+ m_el[3][0] *= x; m_el[3][1] *= y; m_el[3][2] *= z; m_el[3][3] *= w;
+ }
+
+ /**
+ * Return a column-scaled version of this matrix.
+ */
+ MT_Matrix4x4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const {
+ return MT_Matrix4x4(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z, m_el[0][3] * w,
+ m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z, m_el[1][3] * w,
+ m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z, m_el[2][3] * w,
+ m_el[3][0] * x, m_el[3][1] * y, m_el[3][2] * z, m_el[3][3] * w);
+ }
+
+ /**
+ * Set this matrix to I.
+ */
+ void setIdentity() {
+ setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0),
+ MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0),
+ MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0),
+ MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0));
+ }
+
+ /**
+ * Read the element from row i, column j.
+ */
+ float getElement(int i, int j) {
+ return m_el[i][j];
+ }
+
+ /**
+ * Copy the contents to a contiguous block of 16 floats.
+ */
+ void getValue(float *m) const {
+ *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0];
+ *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1];
+ *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2];
+ *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3];
+ }
+
+ /**
+ * Copy the contents to a contiguous block of 16 doubles.
+ */
+ void getValue(double *m) const {
+ *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0];
+ *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1];
+ *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2];
+ *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3];
+ }
+
+ /**
+ * Left-multiply this matrix with the argument.
+ */
+ MT_Matrix4x4& operator*=(const MT_Matrix4x4& m);
+
+ /**
+ * Left-multiply column c with row vector c.
+ */
+ MT_Scalar tdot(int c, const MT_Vector4& v) const {
+ return m_el[0][c] * v[0]
+ + m_el[1][c] * v[1]
+ + m_el[2][c] * v[2]
+ + m_el[3][c] * v[3];
+ }
+
+ /* I'll postpone this for now... - nzc*/
+/* MT_Scalar determinant() const; */
+/* MT_Matrix4x4 adjoint() const; */
+/* MT_Matrix4x4 inverse() const; */
+
+ MT_Matrix4x4 absolute() const;
+
+ MT_Matrix4x4 transposed() const;
+ void transpose();
+
+ void invert();
+
+protected:
+ /**
+ * Access with [row index][column index]
+ */
+ MT_Vector4 m_el[4];
+};
+
+/* These multiplicators do exactly what you ask from them: they
+ * multiply in the indicated order. */
+MT_Vector4 operator*(const MT_Matrix4x4& m, const MT_Vector4& v);
+MT_Vector4 operator*(const MT_Vector4& v, const MT_Matrix4x4& m);
+MT_Matrix4x4 operator*(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2);
+
+/* MT_Matrix4x4 MT_multTransposeLeft(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */
+/* MT_Matrix4x4 MT_multTransposeRight(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */
+
+inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix4x4& m) {
+ return os << m[0] << GEN_endl
+ << m[1] << GEN_endl
+ << m[2] << GEN_endl
+ << m[3] << GEN_endl;
+
+
+
+}
+
+#ifdef GEN_INLINED
+#include "MT_Matrix4x4.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Matrix4x4.inl b/intern/moto/include/MT_Matrix4x4.inl
new file mode 100644
index 00000000000..a2aa893a6b3
--- /dev/null
+++ b/intern/moto/include/MT_Matrix4x4.inl
@@ -0,0 +1,108 @@
+#include "MT_Optimize.h"
+
+/*
+ * This is a supposedly faster inverter than the cofactor
+ * computation. It uses an LU decomposition sort of thing. */
+GEN_INLINE void MT_Matrix4x4::invert() {
+ /* normalize row 0 */
+
+ int i,j,k;
+
+ for (i=1; i < 4; i++) m_el[0][i] /= m_el[0][0];
+ for (i=1; i < 4; i++) {
+ for (j=i; j < 4; j++) { // do a column of L
+ MT_Scalar sum = 0.0;
+ for (k = 0; k < i; k++)
+ sum += m_el[j][k] * m_el[k][i];
+ m_el[j][i] -= sum;
+ }
+ if (i == 3) continue;
+ for (j=i+1; j < 4; j++) { // do a row of U
+ MT_Scalar sum = 0.0;
+ for (k = 0; k < i; k++)
+ sum += m_el[i][k]*m_el[k][j];
+ m_el[i][j] =
+ (m_el[i][j]-sum) / m_el[i][i];
+ }
+ }
+ for (i = 0; i < 4; i++ ) // invert L
+ for (j = i; j < 4; j++ ) {
+ MT_Scalar x = 1.0;
+ if ( i != j ) {
+ x = 0.0;
+ for (k = i; k < j; k++ )
+ x -= m_el[j][k]*m_el[k][i];
+ }
+ m_el[j][i] = x / m_el[j][j];
+ }
+ for (i = 0; i < 4; i++ ) // invert U
+ for (j = i; j < 4; j++ ) {
+ if ( i == j ) continue;
+ MT_Scalar sum = 0.0;
+ for (k = i; k < j; k++ )
+ sum += m_el[k][j]*( (i==k) ? 1.0 : m_el[i][k] );
+ m_el[i][j] = -sum;
+ }
+ for (i = 0; i < 4; i++ ) // final inversion
+ for (j = 0; j < 4; j++ ) {
+ MT_Scalar sum = 0.0;
+ for (k = ((i>j)?i:j); k < 4; k++ )
+ sum += ((j==k)?1.0:m_el[j][k])*m_el[k][i];
+ m_el[j][i] = sum;
+ }
+}
+
+/* We do things slightly different here, because the invert() modifies
+ * the buffer itself. This makes it impossible to make this op right
+ * away. Like other, still missing facilities, I will repair this
+ * later. */
+/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */
+/* { */
+/* } */
+
+
+GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m)
+{
+ setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]), m.tdot(3, m_el[0]),
+ m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]), m.tdot(3, m_el[1]),
+ m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]), m.tdot(3, m_el[2]),
+ m.tdot(0, m_el[3]), m.tdot(1, m_el[3]), m.tdot(2, m_el[3]), m.tdot(3, m_el[3]));
+ return *this;
+
+}
+
+GEN_INLINE MT_Vector4 operator*(const MT_Matrix4x4& m, const MT_Vector4& v) {
+ return MT_Vector4(MT_dot(m[0], v), MT_dot(m[1], v), MT_dot(m[2], v), MT_dot(m[3], v));
+}
+
+GEN_INLINE MT_Vector4 operator*(const MT_Vector4& v, const MT_Matrix4x4& m) {
+ return MT_Vector4(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v), m.tdot(3, v));
+}
+
+GEN_INLINE MT_Matrix4x4 operator*(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2) {
+ return
+ MT_Matrix4x4(m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]), m2.tdot(3, m1[0]),
+ m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]), m2.tdot(3, m1[1]),
+ m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]), m2.tdot(3, m1[2]),
+ m2.tdot(0, m1[3]), m2.tdot(1, m1[3]), m2.tdot(2, m1[3]), m2.tdot(3, m1[3]));
+}
+
+
+GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::transposed() const {
+ return MT_Matrix4x4(m_el[0][0], m_el[1][0], m_el[2][0], m_el[3][0],
+ m_el[0][1], m_el[1][1], m_el[2][1], m_el[3][1],
+ m_el[0][2], m_el[1][2], m_el[2][2], m_el[3][2],
+ m_el[0][3], m_el[1][3], m_el[2][3], m_el[3][3]);
+}
+
+GEN_INLINE void MT_Matrix4x4::transpose() {
+ *this = transposed();
+}
+
+GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::absolute() const {
+ return
+ MT_Matrix4x4(MT_abs(m_el[0][0]), MT_abs(m_el[0][1]), MT_abs(m_el[0][2]), MT_abs(m_el[0][3]),
+ MT_abs(m_el[1][0]), MT_abs(m_el[1][1]), MT_abs(m_el[1][2]), MT_abs(m_el[1][3]),
+ MT_abs(m_el[2][0]), MT_abs(m_el[2][1]), MT_abs(m_el[2][2]), MT_abs(m_el[2][3]),
+ MT_abs(m_el[3][0]), MT_abs(m_el[3][1]), MT_abs(m_el[3][2]), MT_abs(m_el[3][3]));
+}
diff --git a/intern/moto/include/MT_MinMax.h b/intern/moto/include/MT_MinMax.h
new file mode 100755
index 00000000000..b206aa6efaf
--- /dev/null
+++ b/intern/moto/include/MT_MinMax.h
@@ -0,0 +1,69 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_MINMAX_H
+#define MT_MINMAX_H
+
+template <class T>
+inline const T& MT_min(const T& a, const T& b) {
+ return b < a ? b : a;
+}
+
+template <class T>
+inline const T& MT_max(const T& a, const T& b) {
+ return a < b ? b : a;
+}
+
+template <class T>
+inline void MT_set_min(T& a, const T& b) {
+ if (a > b) a = b;
+}
+
+template <class T>
+inline void MT_set_max(T& a, const T& b) {
+ if (a < b) a = b;
+}
+
+#endif
diff --git a/intern/moto/include/MT_Optimize.h b/intern/moto/include/MT_Optimize.h
new file mode 100644
index 00000000000..0ff3afcbd60
--- /dev/null
+++ b/intern/moto/include/MT_Optimize.h
@@ -0,0 +1,42 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef GEN_OPTIMIZE_H
+
+#define GEN_OPTIMIZE_H
+
+#ifdef GEN_INLINED
+#define GEN_INLINE inline
+#else
+#define GEN_INLINE
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Plane3.h b/intern/moto/include/MT_Plane3.h
new file mode 100644
index 00000000000..bb9dd9e4f79
--- /dev/null
+++ b/intern/moto/include/MT_Plane3.h
@@ -0,0 +1,139 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef MT_PLANE3
+
+#define MT_PLANE3
+
+#include "MT_Tuple4.h"
+#include "MT_Point3.h"
+
+/**
+ * A simple 3d plane class.
+ *
+ * This class represents a plane in 3d. The internal parameterization used
+ * is n.x + d =0 where n is a unit vector and d is a scalar.
+ *
+ * It inherits data from MT_Tuple4 please see this class for low level
+ * access to the internal representation.
+ *
+ */
+
+class MT_Plane3 : public MT_Tuple4
+{
+public :
+ /**
+ * Constructor from 3 points
+ */
+
+ MT_Plane3(
+ const MT_Vector3 &a,
+ const MT_Vector3 &b,
+ const MT_Vector3 &c
+ );
+ /**
+ * Construction from vector and a point.
+ */
+
+ MT_Plane3(
+ const MT_Vector3 &n,
+ const MT_Vector3 &p
+ );
+
+ /**
+ * Default constructor
+ */
+ MT_Plane3(
+ );
+
+ /**
+ * Default constructor
+ */
+
+ MT_Plane3(
+ const MT_Plane3 & p
+ ):
+ MT_Tuple4(p)
+ {
+ }
+
+ /**
+ * Return plane normal
+ */
+
+ MT_Vector3
+ Normal(
+ ) const;
+
+ /**
+ * Return plane scalar i.e the d from n.x + d = 0
+ */
+
+ MT_Scalar
+ Scalar(
+ ) const ;
+
+ /**
+ * Invert the plane - just swaps direction of normal.
+ */
+ void
+ Invert(
+ );
+
+ /**
+ * Assignment operator
+ */
+
+ MT_Plane3 &
+ operator = (
+ const MT_Plane3 & rhs
+ );
+
+ /**
+ * Return the signed perpendicular distance from a point to the plane
+ */
+
+ MT_Scalar
+ signedDistance(
+ const MT_Vector3 &
+ ) const;
+
+
+};
+
+#ifdef GEN_INLINED
+#include "MT_Plane3.inl"
+#endif
+
+
+#endif
+
+
diff --git a/intern/moto/include/MT_Plane3.inl b/intern/moto/include/MT_Plane3.inl
new file mode 100644
index 00000000000..77db9b35e1d
--- /dev/null
+++ b/intern/moto/include/MT_Plane3.inl
@@ -0,0 +1,128 @@
+#include "MT_Optimize.h"
+
+
+GEN_INLINE
+MT_Plane3::
+MT_Plane3(
+ const MT_Vector3 &a,
+ const MT_Vector3 &b,
+ const MT_Vector3 &c
+){
+ MT_Vector3 l1 = b-a;
+ MT_Vector3 l2 = c-b;
+
+ MT_Vector3 n = l1.cross(l2);
+ n = n.safe_normalized();
+ MT_Scalar d = n.dot(a);
+
+ m_co[0] = n.x();
+ m_co[1] = n.y();
+ m_co[2] = n.z();
+ m_co[3] = -d;
+}
+
+/**
+ * Construction from vector and a point.
+ */
+GEN_INLINE
+MT_Plane3::
+MT_Plane3(
+ const MT_Vector3 &n,
+ const MT_Vector3 &p
+){
+
+ MT_Vector3 mn = n.safe_normalized();
+ MT_Scalar md = mn.dot(p);
+
+ m_co[0] = mn.x();
+ m_co[1] = mn.y();
+ m_co[2] = mn.z();
+ m_co[3] = -md;
+}
+
+
+/**
+ * Default constructor
+ */
+GEN_INLINE
+MT_Plane3::
+MT_Plane3(
+):
+ MT_Tuple4()
+{
+ m_co[0] = MT_Scalar(1);
+ m_co[1] = MT_Scalar(0);
+ m_co[2] = MT_Scalar(0);
+ m_co[3] = MT_Scalar(0);
+}
+
+/**
+ * Return plane normal
+ */
+
+GEN_INLINE
+ MT_Vector3
+MT_Plane3::
+Normal(
+) const {
+ return MT_Vector3(m_co[0],m_co[1],m_co[2]);
+}
+
+/**
+ * Return plane scalar i.e the d from n.x + d = 0
+ */
+
+GEN_INLINE
+ MT_Scalar
+MT_Plane3::
+Scalar(
+) const {
+ return m_co[3];
+}
+
+GEN_INLINE
+ void
+MT_Plane3::
+Invert(
+) {
+ m_co[0] = -m_co[0];
+ m_co[1] = -m_co[1];
+ m_co[2] = -m_co[2];
+ m_co[3] = -m_co[3];
+}
+
+
+/**
+ * Assignment operator
+ */
+
+GEN_INLINE
+ MT_Plane3 &
+MT_Plane3::
+operator = (
+ const MT_Plane3 & rhs
+) {
+ m_co[0] = rhs.m_co[0];
+ m_co[1] = rhs.m_co[1];
+ m_co[2] = rhs.m_co[2];
+ m_co[3] = rhs.m_co[3];
+ return *this;
+}
+
+/**
+ * Return the distance from a point to the plane
+ */
+
+GEN_INLINE
+ MT_Scalar
+MT_Plane3::
+signedDistance(
+ const MT_Vector3 &v
+) const {
+ return Normal().dot(v) + m_co[3];
+}
+
+
+
+
+
diff --git a/intern/moto/include/MT_Point2.h b/intern/moto/include/MT_Point2.h
new file mode 100644
index 00000000000..2c3abaaf977
--- /dev/null
+++ b/intern/moto/include/MT_Point2.h
@@ -0,0 +1,81 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_POINT2_H
+#define MT_POINT2_H
+
+#include "MT_Vector2.h"
+
+class MT_Point2 : public MT_Vector2 {
+public:
+ MT_Point2() {}
+ MT_Point2(const float *v) : MT_Vector2(v) {}
+ MT_Point2(const double *v) : MT_Vector2(v) {}
+ MT_Point2(MT_Scalar x, MT_Scalar y) : MT_Vector2(x, y) {}
+
+ MT_Point2& operator+=(const MT_Vector2& v);
+ MT_Point2& operator-=(const MT_Vector2& v);
+ MT_Point2& operator=(const MT_Vector2& v);
+
+ MT_Scalar distance(const MT_Point2& p) const;
+ MT_Scalar distance2(const MT_Point2& p) const;
+
+ MT_Point2 lerp(const MT_Point2& p, MT_Scalar t) const;
+};
+
+MT_Point2 operator+(const MT_Point2& p, const MT_Vector2& v);
+MT_Point2 operator-(const MT_Point2& p, const MT_Vector2& v);
+MT_Vector2 operator-(const MT_Point2& p1, const MT_Point2& p2);
+
+MT_Scalar MT_distance(const MT_Point2& p1, const MT_Point2& p2);
+MT_Scalar MT_distance2(const MT_Point2& p1, const MT_Point2& p2);
+
+MT_Point2 MT_lerp(const MT_Point2& p1, const MT_Point2& p2, MT_Scalar t);
+
+#ifdef GEN_INLINED
+#include "MT_Point2.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Point2.inl b/intern/moto/include/MT_Point2.inl
new file mode 100644
index 00000000000..ec09a3260e2
--- /dev/null
+++ b/intern/moto/include/MT_Point2.inl
@@ -0,0 +1,54 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Point2& MT_Point2::operator+=(const MT_Vector2& v) {
+ m_co[0] += v[0]; m_co[1] += v[1];
+ return *this;
+}
+
+GEN_INLINE MT_Point2& MT_Point2::operator-=(const MT_Vector2& v) {
+ m_co[0] -= v[0]; m_co[1] -= v[1];
+ return *this;
+}
+
+GEN_INLINE MT_Point2& MT_Point2::operator=(const MT_Vector2& v) {
+ m_co[0] = v[0]; m_co[1] = v[1];
+ return *this;
+}
+
+GEN_INLINE MT_Scalar MT_Point2::distance(const MT_Point2& p) const {
+ return (p - *this).length();
+}
+
+GEN_INLINE MT_Scalar MT_Point2::distance2(const MT_Point2& p) const {
+ return (p - *this).length2();
+}
+
+GEN_INLINE MT_Point2 MT_Point2::lerp(const MT_Point2& p, MT_Scalar t) const {
+ return MT_Point2(m_co[0] + (p[0] - m_co[0]) * t,
+ m_co[1] + (p[1] - m_co[1]) * t);
+}
+
+GEN_INLINE MT_Point2 operator+(const MT_Point2& p, const MT_Vector2& v) {
+ return MT_Point2(p[0] + v[0], p[1] + v[1]);
+}
+
+GEN_INLINE MT_Point2 operator-(const MT_Point2& p, const MT_Vector2& v) {
+ return MT_Point2(p[0] - v[0], p[1] - v[1]);
+}
+
+GEN_INLINE MT_Vector2 operator-(const MT_Point2& p1, const MT_Point2& p2) {
+ return MT_Vector2(p1[0] - p2[0], p1[1] - p2[1]);
+}
+
+GEN_INLINE MT_Scalar MT_distance(const MT_Point2& p1, const MT_Point2& p2) {
+ return p1.distance(p2);
+}
+
+GEN_INLINE MT_Scalar MT_distance2(const MT_Point2& p1, const MT_Point2& p2) {
+ return p1.distance2(p2);
+}
+
+GEN_INLINE MT_Point2 MT_lerp(const MT_Point2& p1, const MT_Point2& p2, MT_Scalar t) {
+ return p1.lerp(p2, t);
+}
+
diff --git a/intern/moto/include/MT_Point3.h b/intern/moto/include/MT_Point3.h
new file mode 100644
index 00000000000..aa0b4c5f1bb
--- /dev/null
+++ b/intern/moto/include/MT_Point3.h
@@ -0,0 +1,81 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_POINT_H
+#define MT_POINT_H
+
+#include "MT_Vector3.h"
+
+class MT_Point3 : public MT_Vector3 {
+public:
+ MT_Point3() {}
+ MT_Point3(const float *v) : MT_Vector3(v) {}
+ MT_Point3(const double *v) : MT_Vector3(v) {}
+ MT_Point3(MT_Scalar x, MT_Scalar y, MT_Scalar z) : MT_Vector3(x, y, z) {}
+
+ MT_Point3& operator+=(const MT_Vector3& v);
+ MT_Point3& operator-=(const MT_Vector3& v);
+ MT_Point3& operator=(const MT_Vector3& v);
+
+ MT_Scalar distance(const MT_Point3& p) const;
+ MT_Scalar distance2(const MT_Point3& p) const;
+
+ MT_Point3 lerp(const MT_Point3& p, MT_Scalar t) const;
+};
+
+MT_Point3 operator+(const MT_Point3& p, const MT_Vector3& v);
+MT_Point3 operator-(const MT_Point3& p, const MT_Vector3& v);
+MT_Vector3 operator-(const MT_Point3& p1, const MT_Point3& p2);
+
+MT_Scalar MT_distance(const MT_Point3& p1, const MT_Point3& p2);
+MT_Scalar MT_distance2(const MT_Point3& p1, const MT_Point3& p2);
+
+MT_Point3 MT_lerp(const MT_Point3& p1, const MT_Point3& p2, MT_Scalar t);
+
+#ifdef GEN_INLINED
+#include "MT_Point3.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Point3.inl b/intern/moto/include/MT_Point3.inl
new file mode 100644
index 00000000000..e6ce4f9d9a3
--- /dev/null
+++ b/intern/moto/include/MT_Point3.inl
@@ -0,0 +1,54 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Point3& MT_Point3::operator+=(const MT_Vector3& v) {
+ m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2];
+ return *this;
+}
+
+GEN_INLINE MT_Point3& MT_Point3::operator-=(const MT_Vector3& v) {
+ m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2];
+ return *this;
+}
+
+GEN_INLINE MT_Point3& MT_Point3::operator=(const MT_Vector3& v) {
+ m_co[0] = v[0]; m_co[1] = v[1]; m_co[2] = v[2];
+ return *this;
+}
+
+GEN_INLINE MT_Scalar MT_Point3::distance(const MT_Point3& p) const {
+ return (p - *this).length();
+}
+
+GEN_INLINE MT_Scalar MT_Point3::distance2(const MT_Point3& p) const {
+ return (p - *this).length2();
+}
+
+GEN_INLINE MT_Point3 MT_Point3::lerp(const MT_Point3& p, MT_Scalar t) const {
+ return MT_Point3(m_co[0] + (p[0] - m_co[0]) * t,
+ m_co[1] + (p[1] - m_co[1]) * t,
+ m_co[2] + (p[2] - m_co[2]) * t);
+}
+
+GEN_INLINE MT_Point3 operator+(const MT_Point3& p, const MT_Vector3& v) {
+ return MT_Point3(p[0] + v[0], p[1] + v[1], p[2] + v[2]);
+}
+
+GEN_INLINE MT_Point3 operator-(const MT_Point3& p, const MT_Vector3& v) {
+ return MT_Point3(p[0] - v[0], p[1] - v[1], p[2] - v[2]);
+}
+
+GEN_INLINE MT_Vector3 operator-(const MT_Point3& p1, const MT_Point3& p2) {
+ return MT_Vector3(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]);
+}
+
+GEN_INLINE MT_Scalar MT_distance(const MT_Point3& p1, const MT_Point3& p2) {
+ return p1.distance(p2);
+}
+
+GEN_INLINE MT_Scalar MT_distance2(const MT_Point3& p1, const MT_Point3& p2) {
+ return p1.distance2(p2);
+}
+
+GEN_INLINE MT_Point3 MT_lerp(const MT_Point3& p1, const MT_Point3& p2, MT_Scalar t) {
+ return p1.lerp(p2, t);
+}
diff --git a/intern/moto/include/MT_Quaternion.h b/intern/moto/include/MT_Quaternion.h
new file mode 100644
index 00000000000..577df2e9fa5
--- /dev/null
+++ b/intern/moto/include/MT_Quaternion.h
@@ -0,0 +1,112 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_QUATERNION_H
+#define MT_QUATERNION_H
+
+#include <MT_assert.h>
+
+#include "MT_Vector3.h"
+#include "MT_Vector4.h"
+
+class MT_Quaternion : public MT_Vector4 {
+public:
+ MT_Quaternion() {}
+ MT_Quaternion(const MT_Vector4& v) : MT_Vector4(v) {}
+ MT_Quaternion(const float v[4]) : MT_Vector4(v) {}
+ MT_Quaternion(const double v[4]) : MT_Vector4(v) {}
+ MT_Quaternion(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) :
+ MT_Vector4(x, y, z, w) {}
+ MT_Quaternion(const MT_Vector3& axis, MT_Scalar angle) {
+ setRotation(axis, angle);
+ }
+ MT_Quaternion(MT_Scalar yaw, MT_Scalar pitch, MT_Scalar roll) {
+ setEuler(yaw, pitch, roll);
+ }
+
+ void setRotation(const MT_Vector3& axis, MT_Scalar angle) {
+ MT_Scalar d = axis.length();
+ MT_assert(!MT_fuzzyZero(d));
+ MT_Scalar s = sin(angle * MT_Scalar(0.5)) / d;
+ setValue(axis[0] * s, axis[1] * s, axis[2] * s,
+ cos(angle * MT_Scalar(0.5)));
+ }
+
+ void setEuler(MT_Scalar yaw, MT_Scalar pitch, MT_Scalar roll) {
+ MT_Scalar cosYaw = cos(yaw * MT_Scalar(0.5));
+ MT_Scalar sinYaw = sin(yaw * MT_Scalar(0.5));
+ MT_Scalar cosPitch = cos(pitch * MT_Scalar(0.5));
+ MT_Scalar sinPitch = sin(pitch * MT_Scalar(0.5));
+ MT_Scalar cosRoll = cos(roll * MT_Scalar(0.5));
+ MT_Scalar sinRoll = sin(roll * MT_Scalar(0.5));
+ setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+ cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+ sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+ cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+ }
+
+ MT_Quaternion& operator*=(const MT_Quaternion& q);
+
+ void conjugate();
+ MT_Quaternion conjugate() const;
+
+ void invert();
+ MT_Quaternion inverse() const;
+
+ static MT_Quaternion random();
+};
+
+MT_Quaternion operator*(const MT_Quaternion& q1, const MT_Quaternion& q2);
+MT_Quaternion operator*(const MT_Quaternion& q, const MT_Vector3& w);
+MT_Quaternion operator*(const MT_Vector3& w, const MT_Quaternion& q);
+
+#ifdef GEN_INLINED
+#include "MT_Quaternion.inl"
+#endif
+
+#endif
+
+
+
diff --git a/intern/moto/include/MT_Quaternion.inl b/intern/moto/include/MT_Quaternion.inl
new file mode 100644
index 00000000000..225b95b78ce
--- /dev/null
+++ b/intern/moto/include/MT_Quaternion.inl
@@ -0,0 +1,62 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Quaternion& MT_Quaternion::operator*=(const MT_Quaternion& q) {
+ setValue(m_co[3] * q[0] + m_co[0] * q[3] + m_co[1] * q[2] - m_co[2] * q[1],
+ m_co[3] * q[1] + m_co[1] * q[3] + m_co[2] * q[0] - m_co[0] * q[2],
+ m_co[3] * q[2] + m_co[2] * q[3] + m_co[0] * q[1] - m_co[1] * q[0],
+ m_co[3] * q[3] - m_co[0] * q[0] - m_co[1] * q[1] - m_co[2] * q[2]);
+ return *this;
+}
+
+GEN_INLINE void MT_Quaternion::conjugate() {
+ m_co[0] = -m_co[0]; m_co[1] = -m_co[1]; m_co[2] = -m_co[2];
+}
+
+GEN_INLINE MT_Quaternion MT_Quaternion::conjugate() const {
+ return MT_Quaternion(-m_co[0], -m_co[1], -m_co[2], m_co[3]);
+}
+
+GEN_INLINE void MT_Quaternion::invert() {
+ conjugate();
+ *this /= length2();
+}
+
+GEN_INLINE MT_Quaternion MT_Quaternion::inverse() const {
+ return conjugate() / length2();
+}
+
+// From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III,
+// pg. 124-132
+GEN_INLINE MT_Quaternion MT_Quaternion::random() {
+ MT_Scalar x0 = MT_random();
+ MT_Scalar r1 = sqrt(MT_Scalar(1.0) - x0), r2 = sqrt(x0);
+ MT_Scalar t1 = MT_2_PI * MT_random(), t2 = MT_2_PI * MT_random();
+ MT_Scalar c1 = cos(t1), s1 = sin(t1);
+ MT_Scalar c2 = cos(t2), s2 = sin(t2);
+ return MT_Quaternion(s1 * r1, c1 * r1, s2 * r2, c2 * r2);
+}
+
+GEN_INLINE MT_Quaternion operator*(const MT_Quaternion& q1,
+ const MT_Quaternion& q2) {
+ return MT_Quaternion(q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1],
+ q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2],
+ q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0],
+ q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]);
+}
+
+GEN_INLINE MT_Quaternion operator*(const MT_Quaternion& q, const MT_Vector3& w)
+{
+ return MT_Quaternion( q[3] * w[0] + q[1] * w[2] - q[2] * w[1],
+ q[3] * w[1] + q[2] * w[0] - q[0] * w[2],
+ q[3] * w[2] + q[0] * w[1] - q[1] * w[0],
+ -q[0] * w[0] - q[1] * w[1] - q[2] * w[2]);
+}
+
+GEN_INLINE MT_Quaternion operator*(const MT_Vector3& w, const MT_Quaternion& q)
+{
+ return MT_Quaternion( w[0] * q[3] + w[1] * q[2] - w[2] * q[1],
+ w[1] * q[3] + w[2] * q[0] - w[0] * q[2],
+ w[2] * q[3] + w[0] * q[1] - w[1] * q[0],
+ -w[0] * q[0] - w[1] * q[1] - w[2] * q[2]);
+}
+
diff --git a/intern/moto/include/MT_Scalar.h b/intern/moto/include/MT_Scalar.h
new file mode 100755
index 00000000000..a3257c3c73d
--- /dev/null
+++ b/intern/moto/include/MT_Scalar.h
@@ -0,0 +1,88 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_SCALAR_H
+#define MT_SCALAR_H
+
+#include <math.h>
+#include <float.h>
+
+#include "MT_random.h"
+#include "NM_Scalar.h"
+
+typedef double MT_Scalar;
+
+const MT_Scalar MT_DEGS_PER_RAD(57.29577951308232286465);
+const MT_Scalar MT_RADS_PER_DEG(0.01745329251994329547);
+const MT_Scalar MT_PI(3.14159265358979323846);
+const MT_Scalar MT_2_PI(6.28318530717958623200);
+const MT_Scalar MT_EPSILON(1.0e-10);
+const MT_Scalar MT_EPSILON2(1.0e-20);
+const MT_Scalar MT_INFINITY(1.0e50);
+
+inline int MT_sign(MT_Scalar x) {
+ return x < 0.0 ? -1 : x > 0.0 ? 1 : 0;
+}
+
+inline MT_Scalar MT_abs(MT_Scalar x) { return fabs(x); }
+
+inline bool MT_fuzzyZero(MT_Scalar x) { return MT_abs(x) < MT_EPSILON; }
+inline bool MT_fuzzyZero2(MT_Scalar x) { return MT_abs(x) < MT_EPSILON2; }
+
+inline MT_Scalar MT_radians(MT_Scalar x) {
+ return x * MT_RADS_PER_DEG;
+}
+
+inline MT_Scalar MT_degrees(MT_Scalar x) {
+ return x * MT_DEGS_PER_RAD;
+}
+
+inline MT_Scalar MT_random() {
+ return MT_Scalar(MT_rand()) / MT_Scalar(MT_RAND_MAX);
+}
+
+
+#endif
+
diff --git a/intern/moto/include/MT_Stream.h b/intern/moto/include/MT_Stream.h
new file mode 100755
index 00000000000..6be0437f257
--- /dev/null
+++ b/intern/moto/include/MT_Stream.h
@@ -0,0 +1,58 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef GEN_STREAM_H
+
+#define GEN_STREAM_H
+
+#ifdef __CUSTOM_STREAM
+
+class MT_OStream
+{
+public:
+ inline MT_OStream& operator<<(double);
+ inline MT_OStream& operator<<(int);
+ inline MT_OStream& operator<<(char*);
+};
+
+const char GEN_endl = '\n';
+
+#else
+
+#include <iostream>
+
+typedef std::ostream MT_OStream;
+
+inline MT_OStream& GEN_endl(MT_OStream& os) { return std::endl(os); }
+
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Transform.h b/intern/moto/include/MT_Transform.h
new file mode 100644
index 00000000000..73ad0c77fa5
--- /dev/null
+++ b/intern/moto/include/MT_Transform.h
@@ -0,0 +1,172 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ MoTo - 3D Motion Toolkit
+ Copyright (C) 2000 Gino van den Bergen <gino@acm.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef MT_TRANSFORM_H
+#define MT_TRANSFORM_H
+
+#include "MT_Point3.h"
+#include "MT_Matrix3x3.h"
+
+class MT_Transform {
+public:
+ MT_Transform() {}
+ MT_Transform(const float *m) { setValue(m); }
+ MT_Transform(const double *m) { setValue(m); }
+ MT_Transform(const MT_Point3& p, const MT_Quaternion& q) {
+ setOrigin(p);
+ setRotation(q);
+ }
+
+ MT_Transform(const MT_Point3& p, const MT_Matrix3x3& m) {
+ setOrigin(p);
+ setBasis(m);
+ }
+
+
+
+ MT_Point3 operator()(const MT_Point3& p) const {
+ return MT_Point3(MT_dot(m_basis[0], p) + m_origin[0],
+ MT_dot(m_basis[1], p) + m_origin[1],
+ MT_dot(m_basis[2], p) + m_origin[2]);
+ }
+
+ MT_Point3 operator*(const MT_Point3& p) const {
+ return (*this)(p);
+ }
+
+ MT_Matrix3x3& getBasis() { return m_basis; }
+ const MT_Matrix3x3& getBasis() const { return m_basis; }
+ MT_Point3& getOrigin() { return m_origin; }
+ const MT_Point3& getOrigin() const { return m_origin; }
+ MT_Quaternion getRotation() const { return m_basis.getRotation(); }
+
+ void setValue(const float *m);
+ void setValue(const double *m);
+
+ void setOrigin(const MT_Point3& origin) {
+ m_origin = origin;
+ m_type |= TRANSLATION;
+ }
+
+ void setBasis(const MT_Matrix3x3& basis) {
+ m_basis = basis;
+ m_type |= LINEAR;
+ }
+
+ void setRotation(const MT_Quaternion& q) {
+ m_basis.setRotation(q);
+ m_type &= ~SCALING;
+ m_type |= ROTATION;
+ }
+
+ void getValue(float *m) const;
+ void getValue(double *m) const;
+
+ void setIdentity();
+
+ MT_Transform& operator*=(const MT_Transform& t);
+
+ /**
+ * Translate the origin of the transform according to the vector.
+ * @param v The vector to translate over. The vector is specified
+ * in the coordinate system of the transform itself.
+ */
+ void translate(const MT_Vector3& v);
+ void rotate(const MT_Quaternion& q);
+ void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z);
+
+ void invert(const MT_Transform& t);
+ void mult(const MT_Transform& t1, const MT_Transform& t2);
+ void multInverseLeft(const MT_Transform& t1, const MT_Transform& t2);
+
+private:
+ enum {
+ IDENTITY = 0x00,
+ TRANSLATION = 0x01,
+ ROTATION = 0x02,
+ RIGID = TRANSLATION | ROTATION,
+ SCALING = 0x04,
+ LINEAR = ROTATION | SCALING,
+ AFFINE = TRANSLATION | LINEAR
+ };
+
+ MT_Transform(const MT_Matrix3x3& basis, const MT_Point3& origin,
+ unsigned int type) {
+ setValue(basis, origin, type);
+ }
+
+ void setValue(const MT_Matrix3x3& basis, const MT_Point3& origin,
+ unsigned int type) {
+ m_basis = basis;
+ m_origin = origin;
+ m_type = type;
+ }
+
+ friend MT_Transform operator*(const MT_Transform& t1, const MT_Transform& t2);
+
+ MT_Matrix3x3 m_basis;
+ MT_Point3 m_origin;
+ unsigned int m_type;
+};
+
+inline MT_Transform operator*(const MT_Transform& t1, const MT_Transform& t2) {
+ return MT_Transform(t1.m_basis * t2.m_basis,
+ t1(t2.m_origin),
+ t1.m_type | t2.m_type);
+}
+
+#endif
+
+
+
+
+
diff --git a/intern/moto/include/MT_Tuple2.h b/intern/moto/include/MT_Tuple2.h
new file mode 100755
index 00000000000..edefc2669e5
--- /dev/null
+++ b/intern/moto/include/MT_Tuple2.h
@@ -0,0 +1,109 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_Tuple2_H
+#define MT_Tuple2_H
+
+#include "MT_Stream.h"
+#include "MT_Scalar.h"
+
+class MT_Tuple2 {
+public:
+ MT_Tuple2() {}
+ MT_Tuple2(const float *v) { setValue(v); }
+ MT_Tuple2(const double *v) { setValue(v); }
+ MT_Tuple2(MT_Scalar x, MT_Scalar y) { setValue(x, y); }
+
+ MT_Scalar& operator[](int i) { return m_co[i]; }
+ const MT_Scalar& operator[](int i) const { return m_co[i]; }
+
+ MT_Scalar& x() { return m_co[0]; }
+ const MT_Scalar& x() const { return m_co[0]; }
+
+ MT_Scalar& y() { return m_co[1]; }
+ const MT_Scalar& y() const { return m_co[1]; }
+
+ MT_Scalar& u() { return m_co[0]; }
+ const MT_Scalar& u() const { return m_co[0]; }
+
+ MT_Scalar& v() { return m_co[1]; }
+ const MT_Scalar& v() const { return m_co[1]; }
+
+ MT_Scalar *getValue() { return m_co; }
+ const MT_Scalar *getValue() const { return m_co; }
+
+ void getValue(float *v) const {
+ v[0] = m_co[0]; v[1] = m_co[1];
+ }
+
+ void getValue(double *v) const {
+ v[0] = m_co[0]; v[1] = m_co[1];
+ }
+
+ void setValue(const float *v) {
+ m_co[0] = v[0]; m_co[1] = v[1];
+ }
+
+ void setValue(const double *v) {
+ m_co[0] = v[0]; m_co[1] = v[1];
+ }
+
+ void setValue(MT_Scalar x, MT_Scalar y) {
+ m_co[0] = x; m_co[1] = y;
+ }
+
+protected:
+ MT_Scalar m_co[2];
+};
+
+inline bool operator==(const MT_Tuple2& t1, const MT_Tuple2& t2) {
+ return t1[0] == t2[0] && t1[1] == t2[1];
+}
+
+inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple2& t) {
+ return os << t[0] << ' ' << t[1];
+}
+
+#endif
diff --git a/intern/moto/include/MT_Tuple3.h b/intern/moto/include/MT_Tuple3.h
new file mode 100755
index 00000000000..127b18bd41b
--- /dev/null
+++ b/intern/moto/include/MT_Tuple3.h
@@ -0,0 +1,114 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_TUPLE3_H
+#define MT_TUPLE3_H
+
+#include "MT_Stream.h"
+#include "MT_Scalar.h"
+
+class MT_Tuple3 {
+public:
+ MT_Tuple3() {}
+ MT_Tuple3(const float *v) { setValue(v); }
+ MT_Tuple3(const double *v) { setValue(v); }
+ MT_Tuple3(MT_Scalar x, MT_Scalar y, MT_Scalar z) { setValue(x, y, z); }
+
+ MT_Scalar& operator[](int i) { return m_co[i]; }
+ const MT_Scalar& operator[](int i) const { return m_co[i]; }
+
+ MT_Scalar& x() { return m_co[0]; }
+ const MT_Scalar& x() const { return m_co[0]; }
+
+ MT_Scalar& y() { return m_co[1]; }
+ const MT_Scalar& y() const { return m_co[1]; }
+
+ MT_Scalar& z() { return m_co[2]; }
+ const MT_Scalar& z() const { return m_co[2]; }
+
+ MT_Scalar *getValue() { return m_co; }
+ const MT_Scalar *getValue() const { return m_co; }
+
+ void getValue(float *v) const {
+ v[0] = float(m_co[0]);
+ v[1] = float(m_co[1]);
+ v[2] = float(m_co[2]);
+ }
+
+ void getValue(double *v) const {
+ v[0] = double(m_co[0]);
+ v[1] = double(m_co[1]);
+ v[2] = double(m_co[2]);
+ }
+
+ void setValue(const float *v) {
+ m_co[0] = MT_Scalar(v[0]);
+ m_co[1] = MT_Scalar(v[1]);
+ m_co[2] = MT_Scalar(v[2]);
+ }
+
+ void setValue(const double *v) {
+ m_co[0] = MT_Scalar(v[0]);
+ m_co[1] = MT_Scalar(v[1]);
+ m_co[2] = MT_Scalar(v[2]);
+ }
+
+ void setValue(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
+ m_co[0] = x; m_co[1] = y; m_co[2] = z;
+ }
+
+protected:
+ MT_Scalar m_co[3];
+};
+
+inline bool operator==(const MT_Tuple3& t1, const MT_Tuple3& t2) {
+ return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2];
+}
+
+inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple3& t) {
+ return os << t[0] << ' ' << t[1] << ' ' << t[2];
+}
+
+#endif
diff --git a/intern/moto/include/MT_Tuple4.h b/intern/moto/include/MT_Tuple4.h
new file mode 100755
index 00000000000..96ee2d1d1e1
--- /dev/null
+++ b/intern/moto/include/MT_Tuple4.h
@@ -0,0 +1,124 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_TUPLE4_H
+#define MT_TUPLE4_H
+
+#include "MT_Stream.h"
+#include "MT_Scalar.h"
+
+class MT_Tuple4 {
+public:
+ MT_Tuple4() {}
+ MT_Tuple4(const float *v) { setValue(v); }
+ MT_Tuple4(const double *v) { setValue(v); }
+ MT_Tuple4(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
+ setValue(x, y, z, w);
+ }
+
+ MT_Scalar& operator[](int i) { return m_co[i]; }
+ const MT_Scalar& operator[](int i) const { return m_co[i]; }
+
+ MT_Scalar& x() { return m_co[0]; }
+ const MT_Scalar& x() const { return m_co[0]; }
+
+ MT_Scalar& y() { return m_co[1]; }
+ const MT_Scalar& y() const { return m_co[1]; }
+
+ MT_Scalar& z() { return m_co[2]; }
+ const MT_Scalar& z() const { return m_co[2]; }
+
+ MT_Scalar& w() { return m_co[3]; }
+ const MT_Scalar& w() const { return m_co[3]; }
+
+ MT_Scalar *getValue() { return m_co; }
+ const MT_Scalar *getValue() const { return m_co; }
+
+
+ void getValue(float *v) const {
+ v[0] = float(m_co[0]);
+ v[1] = float(m_co[1]);
+ v[2] = float(m_co[2]);
+ v[3] = float(m_co[3]);
+ }
+
+ void getValue(double *v) const {
+ v[0] = double(m_co[0]);
+ v[1] = double(m_co[1]);
+ v[2] = double(m_co[2]);
+ v[3] = double(m_co[3]);
+ }
+
+ void setValue(const float *v) {
+ m_co[0] = MT_Scalar(v[0]);
+ m_co[1] = MT_Scalar(v[1]);
+ m_co[2] = MT_Scalar(v[2]);
+ m_co[3] = MT_Scalar(v[3]);
+ }
+
+ void setValue(const double *v) {
+ m_co[0] = MT_Scalar(v[0]);
+ m_co[1] = MT_Scalar(v[1]);
+ m_co[2] = MT_Scalar(v[2]);
+ m_co[3] = MT_Scalar(v[3]);
+ }
+
+ void setValue(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
+ m_co[0] = x; m_co[1] = y; m_co[2] = z; m_co[3] = w;
+ }
+
+protected:
+ MT_Scalar m_co[4];
+};
+
+inline bool operator==(const MT_Tuple4& t1, const MT_Tuple4& t2) {
+ return t1[0] == t2[0] && t1[1] == t2[1] && t1[2] == t2[2] && t1[3] == t2[3];
+}
+
+inline MT_OStream& operator<<(MT_OStream& os, const MT_Tuple4& t) {
+ return os << t[0] << ' ' << t[1] << ' ' << t[2] << ' ' << t[3];
+}
+
+#endif
diff --git a/intern/moto/include/MT_Vector2.h b/intern/moto/include/MT_Vector2.h
new file mode 100644
index 00000000000..8cdeaacdbb0
--- /dev/null
+++ b/intern/moto/include/MT_Vector2.h
@@ -0,0 +1,112 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_VECTOR2_H
+#define MT_VECTOR2_H
+
+#include <MT_assert.h>
+#include "MT_Tuple2.h"
+
+class MT_Vector2 : public MT_Tuple2 {
+public:
+ MT_Vector2() {}
+ MT_Vector2(const float *v) : MT_Tuple2(v) {}
+ MT_Vector2(const double *v) : MT_Tuple2(v) {}
+ MT_Vector2(MT_Scalar x, MT_Scalar y) : MT_Tuple2(x, y) {}
+
+ MT_Vector2& operator+=(const MT_Vector2& v);
+ MT_Vector2& operator-=(const MT_Vector2& v);
+ MT_Vector2& operator*=(MT_Scalar s);
+ MT_Vector2& operator/=(MT_Scalar s);
+
+ MT_Scalar dot(const MT_Vector2& v) const;
+
+ MT_Scalar length2() const;
+ MT_Scalar length() const;
+
+ MT_Vector2 absolute() const;
+
+ void normalize();
+ MT_Vector2 normalized() const;
+
+ void scale(MT_Scalar x, MT_Scalar y);
+ MT_Vector2 scaled(MT_Scalar x, MT_Scalar y) const;
+
+ bool fuzzyZero() const;
+
+ MT_Scalar angle(const MT_Vector2& v) const;
+ MT_Vector2 cross(const MT_Vector2& v) const;
+ MT_Scalar triple(const MT_Vector2& v1, const MT_Vector2& v2) const;
+
+ int closestAxis() const;
+
+ static MT_Vector2 random();
+};
+
+MT_Vector2 operator+(const MT_Vector2& v1, const MT_Vector2& v2);
+MT_Vector2 operator-(const MT_Vector2& v1, const MT_Vector2& v2);
+MT_Vector2 operator-(const MT_Vector2& v);
+MT_Vector2 operator*(const MT_Vector2& v, MT_Scalar s);
+MT_Vector2 operator*(MT_Scalar s, const MT_Vector2& v);
+MT_Vector2 operator/(const MT_Vector2& v, MT_Scalar s);
+
+MT_Scalar MT_dot(const MT_Vector2& v1, const MT_Vector2& v2);
+
+MT_Scalar MT_length2(const MT_Vector2& v);
+MT_Scalar MT_length(const MT_Vector2& v);
+
+bool MT_fuzzyZero(const MT_Vector2& v);
+bool MT_fuzzyEqual(const MT_Vector2& v1, const MT_Vector2& v2);
+
+MT_Scalar MT_angle(const MT_Vector2& v1, const MT_Vector2& v2);
+MT_Vector2 MT_cross(const MT_Vector2& v1, const MT_Vector2& v2);
+MT_Scalar MT_triple(const MT_Vector2& v1, const MT_Vector2& v2,
+ const MT_Vector2& v3);
+
+#ifdef GEN_INLINED
+#include "MT_Vector2.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Vector2.inl b/intern/moto/include/MT_Vector2.inl
new file mode 100644
index 00000000000..a4a402f2183
--- /dev/null
+++ b/intern/moto/include/MT_Vector2.inl
@@ -0,0 +1,89 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Vector2& MT_Vector2::operator+=(const MT_Vector2& v) {
+ m_co[0] += v[0]; m_co[1] += v[1];
+ return *this;
+}
+
+GEN_INLINE MT_Vector2& MT_Vector2::operator-=(const MT_Vector2& v) {
+ m_co[0] -= v[0]; m_co[1] -= v[1];
+ return *this;
+}
+
+GEN_INLINE MT_Vector2& MT_Vector2::operator*=(MT_Scalar s) {
+ m_co[0] *= s; m_co[1] *= s;
+ return *this;
+}
+
+GEN_INLINE MT_Vector2& MT_Vector2::operator/=(MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return *this *= 1.0 / s;
+}
+
+GEN_INLINE MT_Vector2 operator+(const MT_Vector2& v1, const MT_Vector2& v2) {
+ return MT_Vector2(v1[0] + v2[0], v1[1] + v2[1]);
+}
+
+GEN_INLINE MT_Vector2 operator-(const MT_Vector2& v1, const MT_Vector2& v2) {
+ return MT_Vector2(v1[0] - v2[0], v1[1] - v2[1]);
+}
+
+GEN_INLINE MT_Vector2 operator-(const MT_Vector2& v) {
+ return MT_Vector2(-v[0], -v[1]);
+}
+
+GEN_INLINE MT_Vector2 operator*(const MT_Vector2& v, MT_Scalar s) {
+ return MT_Vector2(v[0] * s, v[1] * s);
+}
+
+GEN_INLINE MT_Vector2 operator*(MT_Scalar s, const MT_Vector2& v) { return v * s; }
+
+GEN_INLINE MT_Vector2 operator/(const MT_Vector2& v, MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return v * (1.0 / s);
+}
+
+GEN_INLINE MT_Scalar MT_Vector2::dot(const MT_Vector2& v) const {
+ return m_co[0] * v[0] + m_co[1] * v[1];
+}
+
+GEN_INLINE MT_Scalar MT_Vector2::length2() const { return dot(*this); }
+GEN_INLINE MT_Scalar MT_Vector2::length() const { return sqrt(length2()); }
+
+GEN_INLINE MT_Vector2 MT_Vector2::absolute() const {
+ return MT_Vector2(MT_abs(m_co[0]), MT_abs(m_co[1]));
+}
+
+GEN_INLINE bool MT_Vector2::fuzzyZero() const { return MT_fuzzyZero2(length2()); }
+
+GEN_INLINE void MT_Vector2::normalize() { *this /= length(); }
+GEN_INLINE MT_Vector2 MT_Vector2::normalized() const { return *this / length(); }
+
+GEN_INLINE void MT_Vector2::scale(MT_Scalar x, MT_Scalar y) {
+ m_co[0] *= x; m_co[1] *= y;
+}
+
+GEN_INLINE MT_Vector2 MT_Vector2::scaled(MT_Scalar x, MT_Scalar y) const {
+ return MT_Vector2(m_co[0] * x, m_co[1] * y);
+}
+
+GEN_INLINE MT_Scalar MT_Vector2::angle(const MT_Vector2& v) const {
+ MT_Scalar s = sqrt(length2() * v.length2());
+ MT_assert(!MT_fuzzyZero(s));
+ return acos(dot(v) / s);
+}
+
+
+GEN_INLINE MT_Scalar MT_dot(const MT_Vector2& v1, const MT_Vector2& v2) {
+ return v1.dot(v2);
+}
+
+GEN_INLINE MT_Scalar MT_length2(const MT_Vector2& v) { return v.length2(); }
+GEN_INLINE MT_Scalar MT_length(const MT_Vector2& v) { return v.length(); }
+
+GEN_INLINE bool MT_fuzzyZero(const MT_Vector2& v) { return v.fuzzyZero(); }
+GEN_INLINE bool MT_fuzzyEqual(const MT_Vector2& v1, const MT_Vector2& v2) {
+ return MT_fuzzyZero(v1 - v2);
+}
+
+GEN_INLINE MT_Scalar MT_angle(const MT_Vector2& v1, const MT_Vector2& v2) { return v1.angle(v2); }
diff --git a/intern/moto/include/MT_Vector3.h b/intern/moto/include/MT_Vector3.h
new file mode 100644
index 00000000000..b1578f81c51
--- /dev/null
+++ b/intern/moto/include/MT_Vector3.h
@@ -0,0 +1,118 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_VECTOR3_H
+#define MT_VECTOR3_H
+
+#include <MT_assert.h>
+#include "MT_Tuple3.h"
+
+class MT_Vector3 : public MT_Tuple3 {
+public:
+ MT_Vector3() {}
+ MT_Vector3(const float *v) : MT_Tuple3(v) {}
+ MT_Vector3(const double *v) : MT_Tuple3(v) {}
+ MT_Vector3(MT_Scalar x, MT_Scalar y, MT_Scalar z) : MT_Tuple3(x, y, z) {}
+
+ MT_Vector3& operator+=(const MT_Vector3& v);
+ MT_Vector3& operator-=(const MT_Vector3& v);
+ MT_Vector3& operator*=(MT_Scalar s);
+ MT_Vector3& operator/=(MT_Scalar s);
+
+ MT_Scalar dot(const MT_Vector3& v) const;
+
+ MT_Scalar length2() const;
+ MT_Scalar length() const;
+
+ MT_Vector3 absolute() const;
+
+ void noiseGate(MT_Scalar threshold);
+
+ void normalize();
+ MT_Vector3 normalized() const;
+ MT_Vector3 safe_normalized() const;
+
+
+ void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z);
+ MT_Vector3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const;
+
+ bool fuzzyZero() const;
+
+ MT_Scalar angle(const MT_Vector3& v) const;
+ MT_Vector3 cross(const MT_Vector3& v) const;
+ MT_Scalar triple(const MT_Vector3& v1, const MT_Vector3& v2) const;
+
+ int closestAxis() const;
+
+ static MT_Vector3 random();
+};
+
+MT_Vector3 operator+(const MT_Vector3& v1, const MT_Vector3& v2);
+MT_Vector3 operator-(const MT_Vector3& v1, const MT_Vector3& v2);
+MT_Vector3 operator-(const MT_Vector3& v);
+MT_Vector3 operator*(const MT_Vector3& v, MT_Scalar s);
+MT_Vector3 operator*(MT_Scalar s, const MT_Vector3& v);
+MT_Vector3 operator/(const MT_Vector3& v, MT_Scalar s);
+
+MT_Vector3 operator*(const MT_Vector3& v1, const MT_Vector3& v2);
+
+MT_Scalar MT_dot(const MT_Vector3& v1, const MT_Vector3& v2);
+
+MT_Scalar MT_length2(const MT_Vector3& v);
+MT_Scalar MT_length(const MT_Vector3& v);
+
+bool MT_fuzzyZero(const MT_Vector3& v);
+bool MT_fuzzyEqual(const MT_Vector3& v1, const MT_Vector3& v2);
+
+MT_Scalar MT_angle(const MT_Vector3& v1, const MT_Vector3& v2);
+MT_Vector3 MT_cross(const MT_Vector3& v1, const MT_Vector3& v2);
+MT_Scalar MT_triple(const MT_Vector3& v1, const MT_Vector3& v2,
+ const MT_Vector3& v3);
+
+#ifdef GEN_INLINED
+#include "MT_Vector3.inl"
+#endif
+
+#endif
diff --git a/intern/moto/include/MT_Vector3.inl b/intern/moto/include/MT_Vector3.inl
new file mode 100644
index 00000000000..7d65970fe96
--- /dev/null
+++ b/intern/moto/include/MT_Vector3.inl
@@ -0,0 +1,134 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Vector3& MT_Vector3::operator+=(const MT_Vector3& v) {
+ m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2];
+ return *this;
+}
+
+GEN_INLINE MT_Vector3& MT_Vector3::operator-=(const MT_Vector3& v) {
+ m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2];
+ return *this;
+}
+
+GEN_INLINE MT_Vector3& MT_Vector3::operator*=(MT_Scalar s) {
+ m_co[0] *= s; m_co[1] *= s; m_co[2] *= s;
+ return *this;
+}
+
+GEN_INLINE MT_Vector3& MT_Vector3::operator/=(MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return *this *= MT_Scalar(1.0) / s;
+}
+
+GEN_INLINE MT_Vector3 operator+(const MT_Vector3& v1, const MT_Vector3& v2) {
+ return MT_Vector3(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
+}
+
+GEN_INLINE MT_Vector3 operator-(const MT_Vector3& v1, const MT_Vector3& v2) {
+ return MT_Vector3(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
+}
+
+GEN_INLINE MT_Vector3 operator-(const MT_Vector3& v) {
+ return MT_Vector3(-v[0], -v[1], -v[2]);
+}
+
+GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v, MT_Scalar s) {
+ return MT_Vector3(v[0] * s, v[1] * s, v[2] * s);
+}
+
+GEN_INLINE MT_Vector3 operator*(MT_Scalar s, const MT_Vector3& v) { return v * s; }
+
+GEN_INLINE MT_Vector3 operator/(const MT_Vector3& v, MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return v * (MT_Scalar(1.0) / s);
+}
+
+GEN_INLINE MT_Vector3 operator*(const MT_Vector3& v1, const MT_Vector3& v2) {
+ return MT_Vector3(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
+}
+
+GEN_INLINE MT_Scalar MT_Vector3::dot(const MT_Vector3& v) const {
+ return m_co[0] * v[0] + m_co[1] * v[1] + m_co[2] * v[2];
+}
+
+GEN_INLINE MT_Scalar MT_Vector3::length2() const { return dot(*this); }
+GEN_INLINE MT_Scalar MT_Vector3::length() const { return sqrt(length2()); }
+
+GEN_INLINE MT_Vector3 MT_Vector3::absolute() const {
+ return MT_Vector3(MT_abs(m_co[0]), MT_abs(m_co[1]), MT_abs(m_co[2]));
+}
+
+GEN_INLINE bool MT_Vector3::fuzzyZero() const {
+ return MT_fuzzyZero(length2());
+}
+
+GEN_INLINE void MT_Vector3::noiseGate(MT_Scalar threshold) {
+ if (length2() < threshold) {
+ setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+ }
+}
+
+GEN_INLINE void MT_Vector3::normalize() { *this /= length(); }
+GEN_INLINE MT_Vector3 MT_Vector3::normalized() const { return *this / length(); }
+GEN_INLINE MT_Vector3 MT_Vector3::safe_normalized() const {
+ MT_Scalar len = length();
+ return MT_fuzzyZero(len) ?
+ MT_Vector3(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0)) :
+ *this / len;
+}
+
+GEN_INLINE void MT_Vector3::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
+ m_co[0] *= x; m_co[1] *= y; m_co[2] *= z;
+}
+
+GEN_INLINE MT_Vector3 MT_Vector3::scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const {
+ return MT_Vector3(m_co[0] * x, m_co[1] * y, m_co[2] * z);
+}
+
+GEN_INLINE MT_Scalar MT_Vector3::angle(const MT_Vector3& v) const {
+ MT_Scalar s = sqrt(length2() * v.length2());
+ MT_assert(!MT_fuzzyZero(s));
+ return acos(dot(v) / s);
+}
+
+GEN_INLINE MT_Vector3 MT_Vector3::cross(const MT_Vector3& v) const {
+ return MT_Vector3(m_co[1] * v[2] - m_co[2] * v[1],
+ m_co[2] * v[0] - m_co[0] * v[2],
+ m_co[0] * v[1] - m_co[1] * v[0]);
+}
+
+GEN_INLINE MT_Scalar MT_Vector3::triple(const MT_Vector3& v1, const MT_Vector3& v2) const {
+ return m_co[0] * (v1[1] * v2[2] - v1[2] * v2[1]) +
+ m_co[1] * (v1[2] * v2[0] - v1[0] * v2[2]) +
+ m_co[2] * (v1[0] * v2[1] - v1[1] * v2[0]);
+}
+
+GEN_INLINE int MT_Vector3::closestAxis() const {
+ MT_Vector3 a = absolute();
+ return a[0] < a[1] ? (a[1] < a[2] ? 2 : 1) : (a[0] < a[2] ? 2 : 0);
+}
+
+GEN_INLINE MT_Vector3 MT_Vector3::random() {
+ MT_Scalar z = MT_Scalar(2.0) * MT_random() - MT_Scalar(1.0);
+ MT_Scalar r = sqrt(MT_Scalar(1.0) - z * z);
+ MT_Scalar t = MT_2_PI * MT_random();
+ return MT_Vector3(r * cos(t), r * sin(t), z);
+}
+
+GEN_INLINE MT_Scalar MT_dot(const MT_Vector3& v1, const MT_Vector3& v2) {
+ return v1.dot(v2);
+}
+
+GEN_INLINE MT_Scalar MT_length2(const MT_Vector3& v) { return v.length2(); }
+GEN_INLINE MT_Scalar MT_length(const MT_Vector3& v) { return v.length(); }
+
+GEN_INLINE bool MT_fuzzyZero(const MT_Vector3& v) { return v.fuzzyZero(); }
+GEN_INLINE bool MT_fuzzyEqual(const MT_Vector3& v1, const MT_Vector3& v2) {
+ return MT_fuzzyZero(v1 - v2);
+}
+
+GEN_INLINE MT_Scalar MT_angle(const MT_Vector3& v1, const MT_Vector3& v2) { return v1.angle(v2); }
+GEN_INLINE MT_Vector3 MT_cross(const MT_Vector3& v1, const MT_Vector3& v2) { return v1.cross(v2); }
+GEN_INLINE MT_Scalar MT_triple(const MT_Vector3& v1, const MT_Vector3& v2, const MT_Vector3& v3) {
+ return v1.triple(v2, v3);
+}
diff --git a/intern/moto/include/MT_Vector4.h b/intern/moto/include/MT_Vector4.h
new file mode 100644
index 00000000000..32b71f950b8
--- /dev/null
+++ b/intern/moto/include/MT_Vector4.h
@@ -0,0 +1,102 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Gino van den Bergen makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#ifndef MT_VECTOR4_H
+#define MT_VECTOR4_H
+
+#include <MT_assert.h>
+
+#include "MT_Tuple4.h"
+
+class MT_Vector4 : public MT_Tuple4 {
+public:
+ MT_Vector4() {}
+ MT_Vector4(const float *v) : MT_Tuple4(v) {}
+ MT_Vector4(const double *v) : MT_Tuple4(v) {}
+ MT_Vector4(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) :
+ MT_Tuple4(x, y, z, w) {}
+
+ MT_Vector4& operator+=(const MT_Vector4& v);
+ MT_Vector4& operator-=(const MT_Vector4& v);
+ MT_Vector4& operator*=(MT_Scalar s);
+ MT_Vector4& operator/=(MT_Scalar s);
+
+ MT_Scalar dot(const MT_Vector4& v) const;
+
+ MT_Scalar length2() const;
+ MT_Scalar length() const;
+
+ MT_Vector4 absolute() const;
+
+ void normalize();
+ MT_Vector4 normalized() const;
+
+ void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w);
+ MT_Vector4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const;
+
+ bool fuzzyZero() const;
+};
+
+MT_Vector4 operator+(const MT_Vector4& v1, const MT_Vector4& v2);
+MT_Vector4 operator-(const MT_Vector4& v1, const MT_Vector4& v2);
+MT_Vector4 operator-(const MT_Vector4& v);
+MT_Vector4 operator*(const MT_Vector4& v, MT_Scalar s);
+MT_Vector4 operator*(MT_Scalar s, const MT_Vector4& v);
+MT_Vector4 operator/(const MT_Vector4& v, MT_Scalar s);
+
+MT_Scalar MT_dot(const MT_Vector4& v1, const MT_Vector4& v2);
+
+MT_Scalar MT_length2(const MT_Vector4& v);
+MT_Scalar MT_length(const MT_Vector4& v);
+
+bool MT_fuzzyZero(const MT_Vector4& v);
+bool MT_fuzzyEqual(const MT_Vector4& v1, const MT_Vector4& v2);
+
+#ifdef GEN_INLINED
+#include "MT_Vector4.inl"
+#endif
+
+#endif
+
diff --git a/intern/moto/include/MT_Vector4.inl b/intern/moto/include/MT_Vector4.inl
new file mode 100644
index 00000000000..762c1c49c50
--- /dev/null
+++ b/intern/moto/include/MT_Vector4.inl
@@ -0,0 +1,80 @@
+#include "MT_Optimize.h"
+
+GEN_INLINE MT_Vector4& MT_Vector4::operator+=(const MT_Vector4& v) {
+ m_co[0] += v[0]; m_co[1] += v[1]; m_co[2] += v[2]; m_co[3] += v[3];
+ return *this;
+}
+
+GEN_INLINE MT_Vector4& MT_Vector4::operator-=(const MT_Vector4& v) {
+ m_co[0] -= v[0]; m_co[1] -= v[1]; m_co[2] -= v[2]; m_co[3] -= v[3];
+ return *this;
+}
+
+GEN_INLINE MT_Vector4& MT_Vector4::operator*=(MT_Scalar s) {
+ m_co[0] *= s; m_co[1] *= s; m_co[2] *= s; m_co[3] *= s;
+ return *this;
+}
+
+GEN_INLINE MT_Vector4& MT_Vector4::operator/=(MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return *this *= MT_Scalar(1.0) / s;
+}
+
+GEN_INLINE MT_Vector4 operator+(const MT_Vector4& v1, const MT_Vector4& v2) {
+ return MT_Vector4(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2], v1[3] + v2[3]);
+}
+
+GEN_INLINE MT_Vector4 operator-(const MT_Vector4& v1, const MT_Vector4& v2) {
+ return MT_Vector4(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2], v1[3] - v2[3]);
+}
+
+GEN_INLINE MT_Vector4 operator-(const MT_Vector4& v) {
+ return MT_Vector4(-v[0], -v[1], -v[2], -v[3]);
+}
+
+GEN_INLINE MT_Vector4 operator*(const MT_Vector4& v, MT_Scalar s) {
+ return MT_Vector4(v[0] * s, v[1] * s, v[2] * s, v[3] * s);
+}
+
+GEN_INLINE MT_Vector4 operator*(MT_Scalar s, const MT_Vector4& v) { return v * s; }
+
+GEN_INLINE MT_Vector4 operator/(const MT_Vector4& v, MT_Scalar s) {
+ MT_assert(!MT_fuzzyZero(s));
+ return v * (MT_Scalar(1.0) / s);
+}
+
+GEN_INLINE MT_Scalar MT_Vector4::dot(const MT_Vector4& v) const {
+ return m_co[0] * v[0] + m_co[1] * v[1] + m_co[2] * v[2] + m_co[3] * v[3];
+}
+
+GEN_INLINE MT_Scalar MT_Vector4::length2() const { return MT_dot(*this, *this); }
+GEN_INLINE MT_Scalar MT_Vector4::length() const { return sqrt(length2()); }
+
+GEN_INLINE MT_Vector4 MT_Vector4::absolute() const {
+ return MT_Vector4(MT_abs(m_co[0]), MT_abs(m_co[1]), MT_abs(m_co[2]), MT_abs(m_co[3]));
+}
+
+GEN_INLINE void MT_Vector4::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
+ m_co[0] *= x; m_co[1] *= y; m_co[2] *= z; m_co[3] *= w;
+}
+
+GEN_INLINE MT_Vector4 MT_Vector4::scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const {
+ return MT_Vector4(m_co[0] * x, m_co[1] * y, m_co[2] * z, m_co[3] * w);
+}
+
+GEN_INLINE bool MT_Vector4::fuzzyZero() const { return MT_fuzzyZero2(length2()); }
+
+GEN_INLINE void MT_Vector4::normalize() { *this /= length(); }
+GEN_INLINE MT_Vector4 MT_Vector4::normalized() const { return *this / length(); }
+
+GEN_INLINE MT_Scalar MT_dot(const MT_Vector4& v1, const MT_Vector4& v2) {
+ return v1.dot(v2);
+}
+
+GEN_INLINE MT_Scalar MT_length2(const MT_Vector4& v) { return v.length2(); }
+GEN_INLINE MT_Scalar MT_length(const MT_Vector4& v) { return v.length(); }
+
+GEN_INLINE bool MT_fuzzyZero(const MT_Vector4& v) { return v.fuzzyZero(); }
+GEN_INLINE bool MT_fuzzyEqual(const MT_Vector4& v1, const MT_Vector4& v2) {
+ return MT_fuzzyZero(v1 - v2);
+}
diff --git a/intern/moto/include/MT_assert.h b/intern/moto/include/MT_assert.h
new file mode 100644
index 00000000000..392bcac311b
--- /dev/null
+++ b/intern/moto/include/MT_assert.h
@@ -0,0 +1,51 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef MT_ASSERT_H
+
+#define MT_ASSERT_H
+
+#ifdef MT_NDEBUG
+
+#define MT_assert(predicate) ((void)0)
+
+#else
+
+#include <assert.h>
+
+#define MT_assert(predicate) assert(predicate)
+
+#endif /* MT_NDEBUG */
+
+#endif
+
+
+
diff --git a/intern/moto/include/MT_random.h b/intern/moto/include/MT_random.h
new file mode 100755
index 00000000000..adfe31f9c41
--- /dev/null
+++ b/intern/moto/include/MT_random.h
@@ -0,0 +1,44 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#ifndef MT_RANDOM_H
+
+#define MT_RANDOM_H
+
+#include <limits.h>
+
+#define MT_RAND_MAX ULONG_MAX
+
+extern void MT_srand(unsigned long);
+extern unsigned long MT_rand();
+
+#endif
+
diff --git a/intern/moto/include/NM_Scalar.h b/intern/moto/include/NM_Scalar.h
new file mode 100644
index 00000000000..98b14ed7ee0
--- /dev/null
+++ b/intern/moto/include/NM_Scalar.h
@@ -0,0 +1,166 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include <math.h>
+
+#include <iostream>
+
+template <class T>
+class NM_Scalar {
+public:
+ NM_Scalar() {}
+ explicit NM_Scalar(T value, T error = 0.0) :
+ m_value(value), m_error(error) {}
+
+ T getValue() const { return m_value; }
+ T getError() const { return m_error; }
+
+ operator T() const { return m_value; }
+
+ NM_Scalar operator-() const {
+ return NM_Scalar<T>(-m_value, m_error);
+ }
+
+ NM_Scalar& operator=(T value) {
+ m_value = value;
+ m_error = 0.0;
+ return *this;
+ }
+
+ NM_Scalar& operator+=(const NM_Scalar& x) {
+ m_value += x.m_value;
+ m_error = (fabs(m_value) * (m_error + 1.0) +
+ fabs(x.m_value) * (x.m_error + 1.0)) /
+ fabs(m_value + x.m_value);
+ return *this;
+ }
+
+ NM_Scalar& operator-=(const NM_Scalar& x) {
+ m_value -= x.m_value;
+ m_error = (fabs(m_value) * (m_error + 1.0) +
+ fabs(x.m_value) * (x.m_error + 1.0)) /
+ fabs(m_value - x.m_value);
+ return *this;
+ }
+
+ NM_Scalar& operator*=(const NM_Scalar& x) {
+ m_value *= x.m_value;
+ m_error += x.m_error + 1.0;
+ return *this;
+ }
+
+ NM_Scalar& operator/=(const NM_Scalar& x) {
+ m_value /= x.m_value;
+ m_error += x.m_error + 1.0;
+ return *this;
+ }
+
+private:
+ T m_value;
+ T m_error;
+};
+
+template <class T>
+inline NM_Scalar<T> operator+(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
+ return x.getValue() == 0.0 && y.getValue() == 0.0 ?
+ NM_Scalar<T>(0.0, 0.0) :
+ NM_Scalar<T>(x.getValue() + y.getValue(),
+ (fabs(x.getValue()) * (x.getError() + 1.0) +
+ fabs(y.getValue()) * (y.getError() + 1.0)) /
+ fabs(x.getValue() + y.getValue()));
+}
+
+template <class T>
+inline NM_Scalar<T> operator-(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
+ return x.getValue() == 0.0 && y.getValue() == 0.0 ?
+ NM_Scalar<T>(0.0, 0.0) :
+ NM_Scalar<T>(x.getValue() - y.getValue(),
+ (fabs(x.getValue()) * (x.getError() + 1.0) +
+ fabs(y.getValue()) * (y.getError() + 1.0)) /
+ fabs(x.getValue() - y.getValue()));
+}
+
+template <class T>
+inline NM_Scalar<T> operator*(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
+ return NM_Scalar<T>(x.getValue() * y.getValue(),
+ x.getError() + y.getError() + 1.0);
+}
+
+template <class T>
+inline NM_Scalar<T> operator/(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
+ return NM_Scalar<T>(x.getValue() / y.getValue(),
+ x.getError() + y.getError() + 1.0);
+}
+
+template <class T>
+inline std::ostream& operator<<(std::ostream& os, const NM_Scalar<T>& x) {
+ return os << x.getValue() << '[' << x.getError() << ']';
+}
+
+template <class T>
+inline NM_Scalar<T> sqrt(const NM_Scalar<T>& x) {
+ return NM_Scalar<T>(sqrt(x.getValue()),
+ 0.5 * x.getError() + 1.0);
+}
+
+template <class T>
+inline NM_Scalar<T> acos(const NM_Scalar<T>& x) {
+ return NM_Scalar<T>(acos(x.getValue()), x.getError() + 1.0);
+}
+
+template <class T>
+inline NM_Scalar<T> cos(const NM_Scalar<T>& x) {
+ return NM_Scalar<T>(cos(x.getValue()), x.getError() + 1.0);
+}
+
+template <class T>
+inline NM_Scalar<T> sin(const NM_Scalar<T>& x) {
+ return NM_Scalar<T>(sin(x.getValue()), x.getError() + 1.0);
+}
+
+template <class T>
+inline NM_Scalar<T> fabs(const NM_Scalar<T>& x) {
+ return NM_Scalar<T>(fabs(x.getValue()), x.getError());
+}
+
+template <class T>
+inline NM_Scalar<T> pow(const NM_Scalar<T>& x, const NM_Scalar<T>& y) {
+ return NM_Scalar<T>(pow(x.getValue(), y.getValue()),
+ fabs(y.getValue()) * x.getError() + 1.0);
+}
+
+
+
+
+
+
+
+
diff --git a/intern/moto/intern/MT_CmMatrix4x4.cpp b/intern/moto/intern/MT_CmMatrix4x4.cpp
new file mode 100755
index 00000000000..0cc830980a0
--- /dev/null
+++ b/intern/moto/intern/MT_CmMatrix4x4.cpp
@@ -0,0 +1,237 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#include "MT_CmMatrix4x4.h"
+#include "MT_Vector3.h"
+#include "MT_Point3.h"
+
+
+MT_CmMatrix4x4::MT_CmMatrix4x4()
+{
+ Identity();
+}
+
+
+
+MT_CmMatrix4x4::MT_CmMatrix4x4(const float value[4][4])
+{
+ for (int i=0;i<4;i++)
+ {
+ for (int j=0;j<4;j++)
+ m_V[i][j] = value[i][j];
+ }
+}
+
+
+
+MT_CmMatrix4x4::MT_CmMatrix4x4(const double value[16])
+{
+ for (int i=0;i<16;i++)
+ m_Vflat[i] = value[i];
+}
+
+
+
+MT_CmMatrix4x4::MT_CmMatrix4x4(const MT_CmMatrix4x4& other)
+{
+ SetMatrix(other);
+}
+
+
+
+MT_CmMatrix4x4::MT_CmMatrix4x4(const MT_Point3& orig,
+ const MT_Vector3& dir,
+ const MT_Vector3 up)
+{
+ MT_Vector3 z = -(dir.normalized());
+ MT_Vector3 x = (up.cross(z)).normalized();
+ MT_Vector3 y = (z.cross(x));
+
+ m_V[0][0] = x.x();
+ m_V[0][1] = y.x();
+ m_V[0][2] = z.x();
+ m_V[0][3] = 0.0f;
+
+ m_V[1][0] = x.y();
+ m_V[1][1] = y.y();
+ m_V[1][2] = z.y();
+ m_V[1][3] = 0.0f;
+
+ m_V[2][0] = x.z();
+ m_V[2][1] = y.z();
+ m_V[2][2] = z.z();
+ m_V[2][3] = 0.0f;
+
+ m_V[3][0] = orig.x();//0.0f;
+ m_V[3][1] = orig.y();//0.0f;
+ m_V[3][2] = orig.z();//0.0f;
+ m_V[3][3] = 1.0f;
+
+ //Translate(-orig);
+}
+
+
+
+MT_Vector3 MT_CmMatrix4x4::GetRight() const
+{
+ return MT_Vector3(m_V[0][0], m_V[0][1], m_V[0][2]);
+}
+
+
+
+MT_Vector3 MT_CmMatrix4x4::GetUp() const
+{
+ return MT_Vector3(m_V[1][0], m_V[1][1], m_V[1][2]);
+}
+
+
+
+MT_Vector3 MT_CmMatrix4x4::GetDir() const
+{
+ return MT_Vector3(m_V[2][0], m_V[2][1], m_V[2][2]);
+}
+
+
+
+MT_Point3 MT_CmMatrix4x4::GetPos() const
+{
+ return MT_Point3(m_V[3][0], m_V[3][1], m_V[3][2]);
+}
+
+
+
+void MT_CmMatrix4x4::Identity()
+{
+ for (int i=0; i<4; i++)
+ {
+ for (int j=0; j<4; j++)
+ m_V[i][j] = (i==j?1.0f:0.0f);
+ }
+}
+
+
+
+void MT_CmMatrix4x4::SetMatrix(const MT_CmMatrix4x4& other)
+{
+ for (int i=0; i<16; i++)
+ m_Vflat[i] = other.m_Vflat[i];
+}
+
+
+
+double* MT_CmMatrix4x4::getPointer()
+{
+ return &m_V[0][0];
+}
+
+
+
+const double* MT_CmMatrix4x4::getPointer() const
+{
+ return &m_V[0][0];
+}
+
+
+
+void MT_CmMatrix4x4::setElem(int pos,double newvalue)
+{
+ m_Vflat[pos] = newvalue;
+}
+
+MT_CmMatrix4x4 MT_CmMatrix4x4::Perspective(
+ MT_Scalar inLeft,
+ MT_Scalar inRight,
+ MT_Scalar inBottom,
+ MT_Scalar inTop,
+ MT_Scalar inNear,
+ MT_Scalar inFar
+){
+
+ MT_CmMatrix4x4 mat;
+
+ // Column 0
+ mat(0, 0) = -(2.0*inNear) / (inRight-inLeft);
+ mat(1, 0) = 0;
+ mat(2, 0) = 0;
+ mat(3, 0) = 0;
+
+ // Column 1
+ mat(0, 1) = 0;
+ mat(1, 1) = (2.0*inNear) / (inTop-inBottom);
+ mat(2, 1) = 0;
+ mat(3, 1) = 0;
+
+ // Column 2
+ mat(0, 2) = (inRight+inLeft) / (inRight-inLeft);
+ mat(1, 2) = (inTop+inBottom) / (inTop-inBottom);
+ mat(2, 2) = -(inFar+inNear) / (inFar-inNear);
+ mat(3, 2) = -1;
+
+ // Column 3
+ mat(0, 3) = 0;
+ mat(1, 3) = 0;
+ mat(2, 3) = -(2.0*inFar*inNear) / (inFar-inNear);
+ mat(3, 3) = 0;
+
+ return mat;
+}
diff --git a/intern/moto/intern/MT_Matrix3x3.cpp b/intern/moto/intern/MT_Matrix3x3.cpp
new file mode 100644
index 00000000000..ded09a6b851
--- /dev/null
+++ b/intern/moto/intern/MT_Matrix3x3.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Matrix3x3.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Matrix3x3.inl"
+#endif
diff --git a/intern/moto/intern/MT_Matrix4x4.cpp b/intern/moto/intern/MT_Matrix4x4.cpp
new file mode 100644
index 00000000000..ce2c3bcf616
--- /dev/null
+++ b/intern/moto/intern/MT_Matrix4x4.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Matrix4x4.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Matrix4x4.inl"
+#endif
diff --git a/intern/moto/intern/MT_Plane3.cpp b/intern/moto/intern/MT_Plane3.cpp
new file mode 100644
index 00000000000..01d10dac5b9
--- /dev/null
+++ b/intern/moto/intern/MT_Plane3.cpp
@@ -0,0 +1,68 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+
+#ifndef GEN_INLINED
+#include "MT_Plane3.h"
+#include "MT_Plane3.inl"
+#endif
+
diff --git a/intern/moto/intern/MT_Point3.cpp b/intern/moto/intern/MT_Point3.cpp
new file mode 100644
index 00000000000..4d704e4949a
--- /dev/null
+++ b/intern/moto/intern/MT_Point3.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Point3.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Point3.inl"
+#endif
diff --git a/intern/moto/intern/MT_Quaternion.cpp b/intern/moto/intern/MT_Quaternion.cpp
new file mode 100644
index 00000000000..eb55ed45f5d
--- /dev/null
+++ b/intern/moto/intern/MT_Quaternion.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Quaternion.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Quaternion.inl"
+#endif
diff --git a/intern/moto/intern/MT_Transform.cpp b/intern/moto/intern/MT_Transform.cpp
new file mode 100644
index 00000000000..31af8223a4f
--- /dev/null
+++ b/intern/moto/intern/MT_Transform.cpp
@@ -0,0 +1,138 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/*
+
+ MOTTO - 3D Motion Toolkit
+ Copyright (C) 2000 Gino van den Bergen <gino@acm.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "MT_Transform.h"
+
+void MT_Transform::setValue(const float *m) {
+ m_basis.setValue(m);
+ m_origin.setValue(&m[12]);
+ m_type = AFFINE;
+}
+
+void MT_Transform::setValue(const double *m) {
+ m_basis.setValue(m);
+ m_origin.setValue(&m[12]);
+ m_type = AFFINE;
+}
+
+void MT_Transform::getValue(float *m) const {
+ m_basis.getValue(m);
+ m_origin.getValue(&m[12]);
+ m[15] = 1.0;
+}
+
+void MT_Transform::getValue(double *m) const {
+ m_basis.getValue(m);
+ m_origin.getValue(&m[12]);
+ m[15] = 1.0;
+}
+
+MT_Transform& MT_Transform::operator*=(const MT_Transform& t) {
+ m_origin += m_basis * t.m_origin;
+ m_basis *= t.m_basis;
+ m_type |= t.m_type;
+ return *this;
+}
+
+void MT_Transform::translate(const MT_Vector3& v) {
+ m_origin += m_basis * v;
+ m_type |= TRANSLATION;
+}
+
+void MT_Transform::rotate(const MT_Quaternion& q) {
+ m_basis *= MT_Matrix3x3(q);
+ m_type |= ROTATION;
+}
+
+void MT_Transform::scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
+ m_basis.scale(x, y, z);
+ m_type |= SCALING;
+}
+
+void MT_Transform::setIdentity() {
+ m_basis.setIdentity();
+ m_origin.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
+ m_type = IDENTITY;
+}
+
+void MT_Transform::invert(const MT_Transform& t) {
+ m_basis = t.m_type & SCALING ?
+ t.m_basis.inverse() :
+ t.m_basis.transposed();
+ m_origin.setValue(-MT_dot(m_basis[0], t.m_origin),
+ -MT_dot(m_basis[1], t.m_origin),
+ -MT_dot(m_basis[2], t.m_origin));
+ m_type = t.m_type;
+}
+
+void MT_Transform::mult(const MT_Transform& t1, const MT_Transform& t2) {
+ m_basis = t1.m_basis * t2.m_basis;
+ m_origin = t1(t2.m_origin);
+ m_type = t1.m_type | t2.m_type;
+}
+
+void MT_Transform::multInverseLeft(const MT_Transform& t1, const MT_Transform& t2) {
+ MT_Vector3 v = t2.m_origin - t1.m_origin;
+ if (t1.m_type & SCALING) {
+ MT_Matrix3x3 inv = t1.m_basis.inverse();
+ m_basis = inv * t2.m_basis;
+ m_origin = inv * v;
+ }
+ else {
+ m_basis = MT_multTransposeLeft(t1.m_basis, t2.m_basis);
+ m_origin = v * t1.m_basis;
+ }
+ m_type = t1.m_type | t2.m_type;
+}
+
+
+
diff --git a/intern/moto/intern/MT_Vector2.cpp b/intern/moto/intern/MT_Vector2.cpp
new file mode 100644
index 00000000000..93284098195
--- /dev/null
+++ b/intern/moto/intern/MT_Vector2.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Vector2.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Vector2.inl"
+#endif
diff --git a/intern/moto/intern/MT_Vector3.cpp b/intern/moto/intern/MT_Vector3.cpp
new file mode 100644
index 00000000000..fe5861b0a41
--- /dev/null
+++ b/intern/moto/intern/MT_Vector3.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Vector3.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Vector3.inl"
+#endif
diff --git a/intern/moto/intern/MT_Vector4.cpp b/intern/moto/intern/MT_Vector4.cpp
new file mode 100644
index 00000000000..db77b20130c
--- /dev/null
+++ b/intern/moto/intern/MT_Vector4.cpp
@@ -0,0 +1,37 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+#include "MT_Vector4.h"
+
+
+#ifndef GEN_INLINED
+#include "MT_Vector4.inl"
+#endif
diff --git a/intern/moto/intern/MT_random.cpp b/intern/moto/intern/MT_random.cpp
new file mode 100755
index 00000000000..72e7c373201
--- /dev/null
+++ b/intern/moto/intern/MT_random.cpp
@@ -0,0 +1,142 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/* A C-program for MT19937: Real number version */
+
+/* genrand() generates one pseudorandom real number (double) */
+/* which is uniformly distributed on [0,1]-interval, for each */
+/* call. sgenrand(seed) set initial values to the working area */
+/* of 624 words. Before genrand(), sgenrand(seed) must be */
+/* called once. (seed is any 32-bit integer except for 0). */
+/* Integer generator is obtained by modifying two lines. */
+/* Coded by Takuji Nishimura, considering the suggestions by */
+/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
+
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later */
+/* version. */
+/* This library 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 Library General Public License for more details. */
+/* You should have received a copy of the GNU Library General */
+/* Public License along with this library; if not, write to the */
+/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
+/* 02111-1307 USA */
+
+/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
+/* When you use this, send an email to: matumoto@math.keio.ac.jp */
+/* with an appropriate reference to your work. */
+
+#include "MT_random.h"
+
+/* Period parameters */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0df /* constant vector a */
+#define UPPER_MASK 0x80000000 /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffff /* least significant r bits */
+
+/* Tempering parameters */
+#define TEMPERING_MASK_B 0x9d2c5680
+#define TEMPERING_MASK_C 0xefc60000
+#define TEMPERING_SHIFT_U(y) (y >> 11)
+#define TEMPERING_SHIFT_S(y) (y << 7)
+#define TEMPERING_SHIFT_T(y) (y << 15)
+#define TEMPERING_SHIFT_L(y) (y >> 18)
+
+static unsigned long mt[N]; /* the array for the state vector */
+static int mti = N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializing the array with a NONZERO seed */
+void MT_srand(unsigned long seed)
+{
+ /* setting initial seeds to mt[N] using */
+ /* the generator Line 25 of Table 1 in */
+ /* [KNUTH 1981, The Art of Computer Programming */
+ /* Vol. 2 (2nd Ed.), pp102] */
+ mt[0] = seed & 0xffffffff;
+ for (mti = 1; mti < N; mti++)
+ mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
+}
+
+unsigned long MT_rand()
+{
+ static unsigned long mag01[2] = { 0x0, MATRIX_A };
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ unsigned long y;
+
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (mti == N+1) /* if sgenrand() has not been called, */
+ MT_srand(4357); /* a default initial seed is used */
+
+ for (kk = 0; kk < N - M; kk++) {
+ y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
+ }
+ for (; kk < N-1; kk++) {
+ y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
+ }
+ y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
+
+ mti = 0;
+ }
+
+ y = mt[mti++];
+ y ^= TEMPERING_SHIFT_U(y);
+ y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
+ y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
+ y ^= TEMPERING_SHIFT_L(y);
+
+ return y;
+}
+
+#undef N
+#undef M
+#undef MATRIX_A
+#undef UPPER_MASK
+#undef LOWER_MASK
+
+/* Tempering parameters */
+#undef TEMPERING_MASK_B
+#undef TEMPERING_MASK_C
+#undef TEMPERING_SHIFT_U
+#undef TEMPERING_SHIFT_S
+#undef TEMPERING_SHIFT_T
+#undef TEMPERING_SHIFT_L
+
diff --git a/intern/moto/intern/Makefile b/intern/moto/intern/Makefile
new file mode 100644
index 00000000000..eeba381ab2a
--- /dev/null
+++ b/intern/moto/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# moto intern Makefile
+#
+
+LIBNAME = moto
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I../include
+
diff --git a/intern/moto/make/msvc_6_0/MoTo.dsp b/intern/moto/make/msvc_6_0/MoTo.dsp
new file mode 100755
index 00000000000..b2e70ac7255
--- /dev/null
+++ b/intern/moto/make/msvc_6_0/MoTo.dsp
@@ -0,0 +1,379 @@
+# Microsoft Developer Studio Project File - Name="MoTo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=MoTo - 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 "MoTo.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 "MoTo.mak" CFG="MoTo - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "MoTo - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "MoTo - 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)" == "MoTo - 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 "Release"
+# PROP Intermediate_Dir "Release"
+# 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 /W4 /GX /O2 /Ob2 /I "..\..\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\libmoto.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\include\*.h" "..\..\..\..\lib\windows\moto\include" ECHO Copying lib COPY "Release\libmoto.lib" "..\..\..\..\lib\windows\moto\lib\libmoto.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "MoTo - 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 "Debug"
+# PROP Intermediate_Dir "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 "..\..\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\libmoto.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\include\*.h" "..\..\..\..\lib\windows\moto\include" ECHO Copying lib COPY "Debug\libmoto.lib" "..\..\..\..\lib\windows\moto\lib\debug\libmoto.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\moto\lib\debug\" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "MoTo - Win32 Release"
+# Name "MoTo - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\MT_CmMatrix4x4.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Matrix3x3.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Matrix4x4.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Plane3.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Point3.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Quaternion.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_random.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Transform.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Vector2.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Vector3.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_Vector4.cpp
+
+!IF "$(CFG)" == "MoTo - Win32 Release"
+
+# ADD CPP /W3 /I "../../include"
+
+!ELSEIF "$(CFG)" == "MoTo - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "inlines"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\include\MT_Matrix3x3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Matrix4x4.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Plane3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Point2.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Point3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Quaternion.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector2.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector3.inl
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector4.inl
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\include\GEN_List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\GEN_Map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_assert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_CmMatrix4x4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Matrix3x3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Matrix4x4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_MinMax.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Optimize.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Plane3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Point2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Point3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Quaternion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Scalar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Stream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Transform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Tuple2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Tuple3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Tuple4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\MT_Vector4.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\NM_Scalar.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/moto/make/msvc_6_0/MoTo.dsw b/intern/moto/make/msvc_6_0/MoTo.dsw
new file mode 100755
index 00000000000..349342c2ae2
--- /dev/null
+++ b/intern/moto/make/msvc_6_0/MoTo.dsw
@@ -0,0 +1,58 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+
+
+###############################################################################
+
+
+
+Project: "MoTo"=.\MoTo.dsp - Package Owner=<4>
+
+
+
+Package=<5>
+
+{{{
+
+}}}
+
+
+
+Package=<4>
+
+{{{
+
+}}}
+
+
+
+###############################################################################
+
+
+
+Global:
+
+
+
+Package=<5>
+
+{{{
+
+}}}
+
+
+
+Package=<3>
+
+{{{
+
+}}}
+
+
+
+###############################################################################
+
+
+
diff --git a/intern/python/Blender.py b/intern/python/Blender.py
new file mode 100644
index 00000000000..ef9e527386e
--- /dev/null
+++ b/intern/python/Blender.py
@@ -0,0 +1,349 @@
+#! /usr/bin/env python
+
+#######################
+# (c) Jan Walter 2000 #
+#######################
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+"""This is the Python API for Blender"""
+
+def _findNewName(name, names):
+ import string
+ words = string.split(name, ".")
+ basename = words[0]
+ newname = name
+ num = 1
+ while newname in names:
+ newname = basename + ".%03d" % num
+ num = num + 1
+ return newname
+
+###################
+# Blender classes #
+###################
+
+class Camera:
+ def __init__(self, name, Lens = 35.0, ClipSta = 0.1, ClipEnd = 100.0):
+ self.name = name
+ self.ipos = {}
+ self.Lens = Lens
+ self.ClipSta = ClipSta
+ self.ClipEnd = ClipEnd
+
+class Curve:
+ def __init__(self, name):
+ # ...
+ self.name = name
+ self.ipos = {}
+ self.materials = []
+
+class Ika:
+ def __init__(self, name):
+ self.name = name
+
+class Ipo:
+ def __init__(self, name):
+ self.name = name
+
+class Lamp:
+ def __init__(self, name, Energ = 1.0, R = 1.0, G = 1.0, B = 1.0,
+ SpoSi = 45.0,
+ OfsX = 0.0, OfsY = 0.0, OfsZ = 0.0,
+ SizeX = 1.0, SizeY = 1.0, SizeZ = 1.0):
+ self.name = name
+ self.ipos = {}
+ self.Energ = Energ
+ self.R = R
+ self.G = G
+ self.B = B
+ self.SpoSi = SpoSi
+ self.OfsX = OfsX
+ self.OfsY = OfsY
+ self.OfsZ = OfsZ
+ self.SizeX = SizeX
+ self.SizeY = SizeY
+ self.SizeZ = SizeZ
+
+class Material:
+ def __init__(self, name,
+ R = 0.8, G = 0.8, B = 0.8,
+ SpecR = 1.0, SpecG = 1.0, SpecB = 1.0,
+ MirR = 1.0, MirG = 1.0, MirB = 1.0,
+ Ref = 0.8, Alpha = 1.0, Emit = 0.0, Amb = 0.5,
+ Spec = 0.5, Hard = 50):
+ self.name = name
+ self.ipos = {}
+ self.R = R
+ self.G = G
+ self.B = B
+ self.SpecR = SpecR
+ self.SpecG = SpecG
+ self.SpecB = SpecB
+ self.MirR = MirR
+ self.MirG = MirG
+ self.MirB = MirB
+ self.Ref = Ref
+ self.Alpha = Alpha
+ self.Emit = Emit
+ self.Amb = Amb
+ self.Spec = Spec
+ self.Hard = Hard
+
+class Matrix:
+ def __init__(self):
+ self.elements = [[1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, 0],
+ [0, 0, 0, 1]]
+
+ def __repr__(self):
+ str = "%s" % self.elements
+ return str
+
+class Mesh:
+ """Creates an (empty) instance of a Blender mesh.\n\
+ E.g.: "m = Blender.Mesh('Plane')"\n\
+ To create faces first add vertices with \n\
+ "i1 = m.addVertex(x, y, z, nx, ny, nz, r = -1.0, r = 0.0, b = 0.0)"\n\
+ then create faces with "index = m.addFace(i1, i2, i3, i4, isSmooth)"."""
+
+ _meshes = {}
+
+ def __init__(self, name):
+ self.name = name
+ self.ipos = {}
+ self.materials = []
+ self.vertices = []
+ self.normals = []
+ self.colors = []
+ self.faces = []
+ if name in Mesh._meshes.keys():
+ print 'Mesh "%s" already exists ...' % name
+ self.name = _findNewName(name, Mesh._meshes.keys())
+ print '... so it will be called "%s"' % self.name
+ Mesh._meshes[self.name] = self
+
+ def __repr__(self):
+ str = 'Mesh(name = "%s",\n' % self.name
+ str = str + ' vertices = %s,\n' % len(self.vertices)
+ str = str + ' faces = %s)' % len(self.faces)
+ return str
+
+ def addFace(self, i1, i2, i3, i4, isSmooth):
+ """addFace(self, i1, i2, i3, i4)"""
+ self.faces.append([i1, i2, i3, i4, isSmooth])
+ return (len(self.faces) - 1)
+
+ def addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0):
+ """addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0)"""
+ self.vertices.append([x, y, z])
+ self.normals.append([nx, ny, nz])
+ if r != -1.0:
+ self.colors.append([r, g, b])
+ return (len(self.vertices) - 1)
+
+class MetaBall:
+ def __init__(self, name):
+ self.name = name
+
+class Object:
+ """Creates an instance of a Blender object"""
+
+ _objects = {}
+
+ def __init__(self, name):
+ self.name = name
+ self.ipos = {}
+ self.materials = []
+ self.matrix = Matrix()
+ self.data = None
+ self.type = None
+ if name in Object._objects.keys():
+ print 'Object "%s" already exists ...' % name
+ self.name = _findNewName(name, Object._objects.keys())
+ print '... so it will be called "%s"' % self.name
+ Object._objects[self.name] = self
+
+ def __repr__(self):
+ str = 'Object(name = "%s",\n' % self.name
+ str = str + ' matrix = %s,\n' % self.matrix
+ if self.type:
+ str = str + ' data = %s("%s"))' % (self.type, self.data)
+ else:
+ str = str + ' data = None)'
+ return str
+
+class Scene:
+ """Creates an instance of a Blender scene"""
+
+ _scenes = {}
+
+ def __init__(self, name):
+ self.name = name
+ self.objects = []
+## self.camera = None
+## self.world = None
+ Scene._scenes[self.name] = self
+
+ def __repr__(self):
+ str = 'Scene(name = "%s", \n' % self.name
+ str = str + ' objects = %s)' % len(self.objects)
+ return str
+
+ def addObject(self, object):
+ """addObject(self, object)"""
+ self.objects.append(object.name)
+ return (len(self.objects) - 1)
+
+class Surface:
+ def __init__(self, name):
+ self.name = name
+ self.ipos = {}
+ self.materials = []
+ # ...
+
+class Text(Surface):
+ def __init__(self, name):
+ Surface.__init__(name)
+
+##############
+# primitives #
+##############
+
+def addMesh(type, sceneName):
+ """Blender.addMesh(type, sceneName)\n\
+ where type is one of ["Plane"]"""
+
+ if type == "Plane":
+ object = Object(type)
+ mesh = Mesh(type)
+ i1 = mesh.addVertex(+1.0, +1.0, 0.0, 0.0, 0.0, 1.0)
+ i2 = mesh.addVertex(+1.0, -1.0, 0.0, 0.0, 0.0, 1.0)
+ i3 = mesh.addVertex(-1.0, -1.0, 0.0, 0.0, 0.0, 1.0)
+ i4 = mesh.addVertex(-1.0, +1.0, 0.0, 0.0, 0.0, 1.0)
+ mesh.addFace(i1, i4, i3, i2, 0)
+ connect("OB" + object.name, "ME" + mesh.name)
+ connect("SC" + sceneName, "OB" + object.name)
+ return object.name, mesh.name
+ elif type == "Cube":
+ pass
+ elif type == "Circle":
+ pass
+ elif type == "UVsphere":
+ pass
+ elif type == "Icosphere":
+ pass
+ elif type == "Cylinder":
+ pass
+ elif type == "Tube":
+ pass
+ elif type == "Cone":
+ pass
+ elif type == "Grid":
+ pass
+ else:
+ raise TypeError
+
+def addCurve(type):
+ if type == "Bezier Curve":
+ pass
+ elif type == "Bezier Circle":
+ pass
+ elif type == "Nurbs Curve":
+ pass
+ elif type == "Nurbs Circle":
+ pass
+ elif type == "Path":
+ pass
+ else:
+ raise TypeError
+
+def addSurface(type):
+ if type == "Curve":
+ pass
+ elif type == "Circle":
+ pass
+ elif type == "Surface":
+ pass
+ elif type == "Tube":
+ pass
+ elif type == "Sphere":
+ pass
+ elif type == "Donut":
+ pass
+ else:
+ raise TypeError
+
+def connect(objName1, objName2):
+ """connect(objName1, objName2)"""
+
+ if objName1[:2] == "OB" and objName2[:2] == "ME":
+ obj1 = getObject(objName1[2:])
+ obj1.data = objName2[2:]
+ obj1.type = "Mesh"
+ elif objName1[:2] == "SC" and objName2[:2] == "OB":
+ obj1 = getScene(objName1[2:])
+ obj2 = getObject(objName2[2:])
+ obj1.addObject(obj2)
+ else:
+ print "ERROR: connect(%s, %s)" % (objName1, objName2)
+
+def getCurrentScene():
+ """getCurrentScene()"""
+
+ return Scene._scenes[0]
+
+def getMesh(name):
+ """getMesh(name)"""
+
+ if name in Mesh._meshes.keys():
+ return Mesh._meshes[name]
+ else:
+ return None
+
+def getObject(name):
+ """getObject(name)"""
+
+ if name in Object._objects.keys():
+ return Object._objects[name]
+ else:
+ return None
+
+def getScene(name):
+ """getScene(name)"""
+
+ if name in Scene._scenes.keys():
+ return Scene._scenes[name]
+ else:
+ return None
+
+def testBlender():
+ scene = Scene("1")
+ print scene
+ objName, meshName = addMesh("Plane", "1")
+ print scene
+ obj = Object("Plane")
+ connect("OB" + obj.name, "ME" + meshName)
+ connect("SC" + scene.name, "OB" + obj.name)
+ print scene
+ for name in scene.objects:
+ obj = getObject(name)
+ print obj
+ if obj.type == "Mesh":
+ mesh = getMesh(obj.data)
+ print mesh
+ print mesh.vertices
+ print mesh.faces
+ Mesh("Plane")
+ # print global data
+ print Scene._scenes
+ print Object._objects
+ print Mesh._meshes
+
+if __name__ == "__main__":
+ testBlender()
diff --git a/intern/python/README b/intern/python/README
new file mode 100644
index 00000000000..c46e3b10af7
--- /dev/null
+++ b/intern/python/README
@@ -0,0 +1,7 @@
+setenv CFLAGS "-g -Wall -I/usr/local/Python-1.6/Include"
+setenv LDFLAGS "-L/usr/local/Python-1.6"
+aclocal
+autoconf
+automake -a
+./configure
+make
diff --git a/intern/python/blendermodule/main.c b/intern/python/blendermodule/main.c
new file mode 100644
index 00000000000..1811b80cfa3
--- /dev/null
+++ b/intern/python/blendermodule/main.c
@@ -0,0 +1,873 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/***************************************************************************
+
+ main.c - description
+ -------------------
+ begin : Fri Sep 15 19:19:43 CEST 2000
+ copyright : (C) 2000 by Jan Walter
+ email : jan@blender.nl
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+/* CVS */
+/* $Author$ */
+/* $Date$ */
+/* $RCSfile$ */
+/* $Revision$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Python.h"
+
+static PyObject* ErrorObject;
+static PyObject* _scene;
+
+static PyObject* blend_connect(PyObject* self, PyObject* args);
+
+/**************/
+/* structures */
+/**************/
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* vertices;
+ PyObject* normals;
+ PyObject* faces;
+} mshobject;
+
+staticforward PyTypeObject Mshtype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* matrix;
+ PyObject* data;
+ PyObject* type;
+} objobject;
+
+staticforward PyTypeObject Objtype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* objects;
+} sceobject;
+
+staticforward PyTypeObject Scetype;
+
+/********/
+/* mesh */
+/********/
+
+static char msh_addFace__doc__[] =
+"addFace(self, i1, i2, i3, i4, isSmooth)"
+;
+
+static PyObject*
+msh_addFace(mshobject* self, PyObject* args)
+{
+ int index;
+ int i1, i2, i3, i4;
+ int isSmooth;
+ PyObject *item = NULL;
+
+ if (!PyArg_ParseTuple(args, "iiiii", &i1, &i2, &i3, &i4, &isSmooth))
+ {
+ return NULL;
+ }
+ item = PyList_New(5);
+ PyList_SetItem(item, 0, PyInt_FromLong(i1));
+ PyList_SetItem(item, 1, PyInt_FromLong(i2));
+ PyList_SetItem(item, 2, PyInt_FromLong(i3));
+ PyList_SetItem(item, 3, PyInt_FromLong(i4));
+ PyList_SetItem(item, 4, PyInt_FromLong(isSmooth));
+ PyList_Append(self->faces, item);
+ index = PyList_Size(self->faces) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static char msh_addVertex__doc__[] =
+"addVertex(self, x, y, z, nx, ny, nz)"
+;
+
+static PyObject*
+msh_addVertex(mshobject* self, PyObject* args)
+{
+ int index;
+ float x, y, z, nx, ny, nz;
+ PyObject *item1 = NULL;
+ PyObject *item2 = NULL;
+
+ if (!PyArg_ParseTuple(args, "ffffff", &x, &y, &z, &nx, &ny, &nz))
+ {
+ return NULL;
+ }
+ item1 = PyList_New(3);
+ item2 = PyList_New(3);
+ PyList_SetItem(item1, 0, PyFloat_FromDouble(x));
+ PyList_SetItem(item1, 1, PyFloat_FromDouble(y));
+ PyList_SetItem(item1, 2, PyFloat_FromDouble(z));
+ PyList_SetItem(item2, 0, PyFloat_FromDouble(nx));
+ PyList_SetItem(item2, 1, PyFloat_FromDouble(ny));
+ PyList_SetItem(item2, 2, PyFloat_FromDouble(nz));
+ PyList_Append(self->vertices, item1);
+ PyList_Append(self->normals, item2);
+ index = PyList_Size(self->vertices) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static struct PyMethodDef msh_methods[] = {
+ {"addFace", (PyCFunction)msh_addFace,
+ METH_VARARGS, msh_addFace__doc__},
+ {"addVertex", (PyCFunction)msh_addVertex,
+ METH_VARARGS, msh_addVertex__doc__},
+
+ { NULL, NULL }
+};
+
+static mshobject*
+newmshobject(char* name)
+{
+ mshobject* self;
+
+ self = PyObject_NEW(mshobject, &Mshtype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->vertices = PyList_New(0);
+ self->normals = PyList_New(0);
+ self->faces = PyList_New(0);
+
+ return self;
+}
+
+static void
+msh_dealloc(mshobject* self)
+{
+ mshobject* msh = (mshobject*) self;
+
+ Py_DECREF(msh->vertices);
+ Py_DECREF(msh->normals);
+ Py_DECREF(msh->faces);
+
+ PyMem_DEL(self);
+}
+
+static int
+msh_print(mshobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Mesh(name = \"%s\",\n", self->name);
+ fprintf(fp, " vertices = %d,\n", PyList_Size(self->vertices));
+ fprintf(fp, " faces = %d)\n", PyList_Size(self->faces));
+
+ return 0;
+}
+
+static PyObject*
+msh_repr(mshobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Mesh()\n");
+
+ return s;
+}
+
+static PyObject*
+msh_str(mshobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Mesh()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist msh_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"vertices", T_OBJECT, offsetof(mshobject, vertices), RO},
+ {"normals", T_OBJECT, offsetof(mshobject, normals), RO},
+ {"faces", T_OBJECT, offsetof(mshobject, faces), RO},
+ {NULL}
+};
+
+static PyObject*
+msh_getattr(mshobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, msh_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(msh_methods, (PyObject*)self, name);
+}
+
+
+static int
+msh_setattr(mshobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, msh_memberlist, name, v);
+}
+
+static char Mshtype__doc__[] =
+""
+;
+
+static PyTypeObject Mshtype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Mesh", /*tp_name*/
+ sizeof(mshobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) msh_dealloc, /*tp_dealloc*/
+ (printfunc) msh_print, /*tp_print*/
+ (getattrfunc) msh_getattr, /*tp_getattr*/
+ (setattrfunc) msh_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) msh_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) msh_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Mshtype__doc__ /* Documentation string */
+};
+
+/**********/
+/* object */
+/**********/
+
+static struct PyMethodDef obj_methods[] = {
+
+ { NULL, NULL }
+};
+
+static objobject*
+newobjobject(char* name)
+{
+ objobject* self = NULL;
+ PyObject* row1 = NULL;
+ PyObject* row2 = NULL;
+ PyObject* row3 = NULL;
+ PyObject* row4 = NULL;
+
+ self = PyObject_NEW(objobject, &Objtype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->matrix = PyList_New(4);
+ row1 = PyList_New(4);
+ row2 = PyList_New(4);
+ row3 = PyList_New(4);
+ row4 = PyList_New(4);
+ PyList_SetItem(row1, 0, PyInt_FromLong(1));
+ PyList_SetItem(row1, 1, PyInt_FromLong(0));
+ PyList_SetItem(row1, 2, PyInt_FromLong(0));
+ PyList_SetItem(row1, 3, PyInt_FromLong(0));
+ PyList_SetItem(row2, 0, PyInt_FromLong(0));
+ PyList_SetItem(row2, 1, PyInt_FromLong(1));
+ PyList_SetItem(row2, 2, PyInt_FromLong(0));
+ PyList_SetItem(row2, 3, PyInt_FromLong(0));
+ PyList_SetItem(row3, 0, PyInt_FromLong(0));
+ PyList_SetItem(row3, 1, PyInt_FromLong(0));
+ PyList_SetItem(row3, 2, PyInt_FromLong(1));
+ PyList_SetItem(row3, 3, PyInt_FromLong(0));
+ PyList_SetItem(row4, 0, PyInt_FromLong(0));
+ PyList_SetItem(row4, 1, PyInt_FromLong(0));
+ PyList_SetItem(row4, 2, PyInt_FromLong(0));
+ PyList_SetItem(row4, 3, PyInt_FromLong(1));
+ PyList_SetItem(self->matrix, 0, row1);
+ PyList_SetItem(self->matrix, 1, row2);
+ PyList_SetItem(self->matrix, 2, row3);
+ PyList_SetItem(self->matrix, 3, row4);
+ Py_INCREF(Py_None);
+ self->data = Py_None;
+ Py_INCREF(Py_None);
+ self->type = Py_None;
+
+ return self;
+}
+
+static void
+obj_dealloc(objobject* self)
+{
+ objobject* obj = (objobject*) self;
+
+ Py_DECREF(obj->matrix);
+ Py_DECREF(obj->data);
+ Py_DECREF(obj->type);
+
+ PyMem_DEL(self);
+}
+
+static int
+obj_print(objobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Object(name = \"%s\",\n", self->name);
+/* fprintf(fp, " matrix = %s,\n", */
+/* PyString_AsString(mtx_repr((mtxobject*) self->matrix))); */
+ if (self->type == Py_None)
+ {
+ fprintf(fp, " data = None)\n");
+ }
+ else
+ {
+ fprintf(fp, " data = %s(\"%s\"))\n",
+ PyString_AsString(self->type),
+ ((mshobject*) self->data)->name);
+ }
+
+ return 0;
+}
+
+static PyObject*
+obj_repr(objobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Object()\n");
+
+ return s;
+}
+
+static PyObject*
+obj_str(objobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Object()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist obj_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"data", T_OBJECT, offsetof(objobject, data), RO},
+ {"matrix", T_OBJECT, offsetof(objobject, matrix), RO},
+ {"type", T_OBJECT, offsetof(objobject, type), RO},
+ {NULL}
+};
+
+static PyObject*
+obj_getattr(objobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, obj_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(obj_methods, (PyObject*)self, name);
+}
+
+
+static int
+obj_setattr(objobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, obj_memberlist, name, v);
+}
+
+static char Objtype__doc__[] =
+""
+;
+
+static PyTypeObject Objtype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Object", /*tp_name*/
+ sizeof(objobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) obj_dealloc, /*tp_dealloc*/
+ (printfunc) obj_print, /*tp_print*/
+ (getattrfunc) obj_getattr, /*tp_getattr*/
+ (setattrfunc) obj_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) obj_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) obj_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Objtype__doc__ /* Documentation string */
+};
+
+/*********/
+/* scene */
+/*********/
+
+static char sce_addObject__doc__[] =
+"addObject(self, object)"
+;
+
+static PyObject*
+sce_addObject(sceobject* self, PyObject* args)
+{
+ int index;
+ PyObject* object = NULL;
+
+ if (!PyArg_ParseTuple(args, "O", &object))
+ {
+ return NULL;
+ }
+ PyList_Append(self->objects, object);
+ index = PyList_Size(self->objects) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static struct PyMethodDef sce_methods[] = {
+ {"addObject", (PyCFunction)sce_addObject,
+ METH_VARARGS, sce_addObject__doc__},
+
+ { NULL, NULL }
+};
+
+static sceobject*
+newsceobject(char* name)
+{
+ sceobject* self;
+
+ self = PyObject_NEW(sceobject, &Scetype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->objects = PyList_New(0);
+
+ return self;
+}
+
+static void
+sce_dealloc(sceobject* self)
+{
+ sceobject* sce = (sceobject*) self;
+
+ Py_DECREF(sce->objects);
+
+ PyMem_DEL(self);
+}
+
+static int
+sce_print(sceobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Scene(name = \"%s\",\n", self->name);
+ fprintf(fp, " objects = %d)\n", PyList_Size(self->objects));
+
+ return 0;
+}
+
+static PyObject*
+sce_repr(sceobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Scene()\n");
+
+ return s;
+}
+
+static PyObject*
+sce_str(sceobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Scene()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist sce_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"objects", T_OBJECT, offsetof(sceobject, objects), RO},
+ {NULL}
+};
+
+static PyObject*
+sce_getattr(sceobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, sce_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(sce_methods, (PyObject*)self, name);
+}
+
+
+static int
+sce_setattr(sceobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, sce_memberlist, name, v);
+}
+
+static char Scetype__doc__[] =
+""
+;
+
+static PyTypeObject Scetype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Scene", /*tp_name*/
+ sizeof(sceobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) sce_dealloc, /*tp_dealloc*/
+ (printfunc) sce_print, /*tp_print*/
+ (getattrfunc) sce_getattr, /*tp_getattr*/
+ (setattrfunc) sce_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) sce_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) sce_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Scetype__doc__ /* Documentation string */
+};
+
+static char blend_Mesh__doc__[] =
+"Creates an (empty) instance of a Blender mesh.\n\
+ E.g.: \"m = Blender.Mesh('Plane')\"\n\
+ To create faces first add vertices with \n\
+ \"i1 = m.addVertex(x, y, z, nx, ny, nz)\"\n\
+ then create faces with \"index = m.addFace(i1, i2, i3, i4, isSmooth)\".\
+"
+;
+
+static PyObject*
+blend_Mesh(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_Object__doc__[] =
+"Creates an instance of a Blender object"
+;
+
+static PyObject*
+blend_Object(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+
+ return ((PyObject*) newobjobject(name));
+}
+
+static char blend_Scene__doc__[] =
+"Creates an instance of a Blender scene"
+;
+
+static PyObject*
+blend_Scene(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+
+ return ((PyObject*) newsceobject(name));
+}
+
+static char blend_addMesh__doc__[] =
+"Blender.addMesh(type, scene)\n\
+ where type is one of [\"Plane\"]"
+;
+
+static PyObject*
+blend_addMesh(PyObject* self, PyObject* args)
+{
+ char* type = NULL;
+ PyObject* scene = NULL;
+ PyObject* tuple = NULL;
+ PyObject* object = NULL;
+ PyObject* mesh = NULL;
+ PyObject* index = NULL;
+ PyObject* indices = NULL;
+
+ if (!PyArg_ParseTuple(args, "sO", &type, &scene))
+ {
+ return NULL;
+ }
+
+ if (strcmp(type, "Plane") == 0)
+ {
+ object = (PyObject*) newobjobject(type);
+ mesh = (PyObject*) newmshobject(type);
+ indices = PyList_New(5);
+ /* vertices */
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ 1.0, 1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 0, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ 1.0, -1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 1, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ -1.0, -1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 2, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ -1.0, 1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 3, index);
+ PyList_SetItem(indices, 4, PyInt_FromLong(0)); /* smooth flag */
+ /* faces */
+ msh_addFace((mshobject*) mesh,
+ Py_BuildValue("OOOOO",
+ PyList_GetItem(indices, 0),
+ PyList_GetItem(indices, 3),
+ PyList_GetItem(indices, 2),
+ PyList_GetItem(indices, 1),
+ PyList_GetItem(indices, 4)));
+ /* connection */
+ blend_connect(self, Py_BuildValue("OO", object, mesh));
+ blend_connect(self, Py_BuildValue("OO", scene, object));
+ /* return value */
+ tuple = PyTuple_New(2);
+ PyTuple_SetItem(tuple, 0, object);
+ PyTuple_SetItem(tuple, 1, mesh);
+
+ return tuple;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_connect__doc__[] =
+"connect(obj1, obj2)"
+;
+
+static PyObject*
+blend_connect(PyObject* self, PyObject* args)
+{
+ PyObject* obj1 = NULL;
+ PyObject* obj2 = NULL;
+
+ if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2))
+ {
+ return NULL;
+ }
+ if (obj1->ob_type == &Objtype)
+ {
+ if (obj2->ob_type == &Mshtype)
+ {
+ Py_INCREF(obj2);
+ ((objobject*) obj1)->data = obj2;
+ ((objobject*) obj1)->type = PyString_FromString("Mesh");
+ }
+ }
+ else if (obj1->ob_type == &Scetype)
+ {
+ if (obj2->ob_type == &Objtype)
+ {
+ sce_addObject((sceobject*) obj1, Py_BuildValue("(O)", obj2));
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_getCurrentScene__doc__[] =
+"getCurrentScene()"
+;
+
+static PyObject*
+blend_getCurrentScene(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+
+ Py_INCREF(_scene);
+ return _scene;
+}
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef blend_methods[] = {
+ {"Mesh", (PyCFunction) blend_Mesh,
+ METH_VARARGS, blend_Mesh__doc__},
+ {"Object", (PyCFunction) blend_Object,
+ METH_VARARGS, blend_Object__doc__},
+ {"Scene", (PyCFunction) blend_Scene,
+ METH_VARARGS, blend_Scene__doc__},
+ {"addMesh", (PyCFunction) blend_addMesh,
+ METH_VARARGS, blend_addMesh__doc__},
+ {"connect", (PyCFunction) blend_connect,
+ METH_VARARGS, blend_connect__doc__},
+ {"getCurrentScene", (PyCFunction) blend_getCurrentScene,
+ METH_VARARGS, blend_getCurrentScene__doc__},
+ { NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+
+/* Initialization function for the module (*must* be called initBlender) */
+
+static char Blender_module_documentation[] =
+"This is the Python API for Blender"
+;
+
+void
+initBlender()
+{
+ PyObject* m;
+ PyObject* d;
+
+ /* Create the module and add the functions */
+ m = Py_InitModule4("Blender", blend_methods,
+ Blender_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ /* Add some symbolic constants to the module */
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("Blender.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ /* XXXX Add constants here */
+ _scene = (PyObject*) newsceobject("1");
+ PyDict_SetItemString(d, "_scene", _scene);
+
+ /* Check for errors */
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module Blender");
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ char filename[] = "test.py";
+ FILE* fp = NULL;
+
+ Py_SetProgramName("blender");
+ Py_Initialize();
+ initBlender();
+ fp = fopen(filename, "r");
+ PyRun_AnyFile(fp, filename);
+
+ Py_Finalize();
+
+ return EXIT_SUCCESS;
+}
diff --git a/intern/python/blendermodule/test.py b/intern/python/blendermodule/test.py
new file mode 100644
index 00000000000..8c2307a2317
--- /dev/null
+++ b/intern/python/blendermodule/test.py
@@ -0,0 +1,52 @@
+import Blender
+
+def printModuleInfo():
+ # module information
+ names = dir(Blender)
+ print names
+ for name in names:
+ execString = ('print "Blender.' + name + ':",\n' +
+ 'if type(Blender.' + name + ') == type(""):\n' +
+ ' print Blender.' + name + '\n' +
+ 'elif type(Blender.' + name +
+ ') == type(Blender.addMesh) or type(Blender.' + name +
+ ') == type(Blender.Object):\n' +
+ ' print Blender.' + name + '.__doc__\n' +
+ 'else:\n' +
+ ' print type(Blender.' + name + ')\n')
+ exec execString
+ print "#" * 79
+
+def testModule():
+ # get current scene
+ scene = Blender.getCurrentScene()
+ print scene
+ # create object and mesh (primitives)
+ obj, msh = Blender.addMesh("Plane", scene)
+ print "obj ="
+ print obj
+ print "msh ="
+ print msh
+ print "vertices:"
+ for vertex in msh.vertices:
+ print vertex
+ print "faces:"
+ for face in msh.faces:
+ print face
+ # create object only and share mesh
+ obj2 = Blender.Object("Plane2")
+ print obj2
+ Blender.connect(obj2, msh)
+ Blender.connect(scene, obj2)
+ print obj2
+ print obj2.data
+ print "vertices:"
+ for vertex in obj2.data.vertices:
+ print vertex
+ print "faces:"
+ for face in obj2.data.faces:
+ print face
+ print scene
+
+printModuleInfo()
+testModule()
diff --git a/intern/python/freeze/Makefile b/intern/python/freeze/Makefile
new file mode 100644
index 00000000000..3c344029b3e
--- /dev/null
+++ b/intern/python/freeze/Makefile
@@ -0,0 +1,14 @@
+# $Id$
+# This is the makefile for the bytecode freezing of all modules which
+# the main file depends on (last argument in importer rule)
+
+SRCDIR = ../modules
+
+TARGETDIR = ../../../source/blender/bpython/frozen
+
+PYFLAGS = -S -O
+
+default: importer
+
+importer:
+ python $(PYFLAGS) freeze.py -d -x os -x pprint -x Blender -I $(SRCDIR) -o $(TARGETDIR) $(SRCDIR)/VRMLmain.py
diff --git a/intern/python/freeze/README b/intern/python/freeze/README
new file mode 100644
index 00000000000..fcdd67029a5
--- /dev/null
+++ b/intern/python/freeze/README
@@ -0,0 +1,173 @@
+THE FREEZE SCRIPT
+=================
+
+(Directions for Windows are at the end of this file.)
+
+
+What is Freeze?
+---------------
+
+Freeze make it possible to ship arbitrary Python programs to people
+who don't have Python. The shipped file (called a "frozen" version of
+your Python program) is an executable, so this only works if your
+platform is compatible with that on the receiving end (this is usually
+a matter of having the same major operating system revision and CPU
+type).
+
+The shipped file contains a Python interpreter and large portions of
+the Python run-time. Some measures have been taken to avoid linking
+unneeded modules, but the resulting binary is usually not small.
+
+The Python source code of your program (and of the library modules
+written in Python that it uses) is not included in the binary --
+instead, the compiled byte-code (the instruction stream used
+internally by the interpreter) is incorporated. This gives some
+protection of your Python source code, though not much -- a
+disassembler for Python byte-code is available in the standard Python
+library. At least someone running "strings" on your binary won't see
+the source.
+
+
+How does Freeze know which modules to include?
+----------------------------------------------
+
+Previous versions of Freeze used a pretty simple-minded algorithm to
+find the modules that your program uses, essentially searching for
+lines starting with the word "import". It was pretty easy to trick it
+into making mistakes, either missing valid import statements, or
+mistaking string literals (e.g. doc strings) for import statements.
+
+This has been remedied: Freeze now uses the regular Python parser to
+parse the program (and all its modules) and scans the generated byte
+code for IMPORT instructions. It may still be confused -- it will not
+know about calls to the __import__ built-in function, or about import
+statements constructed on the fly and executed using the 'exec'
+statement, and it will consider import statements even when they are
+unreachable (e.g. "if 0: import foobar").
+
+This new version of Freeze also knows about Python's new package
+import mechanism, and uses exactly the same rules to find imported
+modules and packages. One exception: if you write 'from package
+import *', Python will look into the __all__ variable of the package
+to determine which modules are to be imported, while Freeze will do a
+directory listing.
+
+One tricky issue: Freeze assumes that the Python interpreter and
+environment you're using to run Freeze is the same one that would be
+used to run your program, which should also be the same whose sources
+and installed files you will learn about in the next section. In
+particular, your PYTHONPATH setting should be the same as for running
+your program locally. (Tip: if the program doesn't run when you type
+"python hello.py" there's little chance of getting the frozen version
+to run.)
+
+
+How do I use Freeze?
+--------------------
+
+Normally, you should be able to use it as follows:
+
+ python freeze.py hello.py
+
+where hello.py is your program and freeze.py is the main file of
+Freeze (in actuality, you'll probably specify an absolute pathname
+such as /usr/joe/python/Tools/freeze/freeze.py).
+
+
+What do I do next?
+------------------
+
+Freeze creates a number of files: frozen.c, config.c and Makefile,
+plus one file for each Python module that gets included named
+M_<module>.c. To produce the frozen version of your program, you can
+simply type "make". This should produce a binary file. If the
+filename argument to Freeze was "hello.py", the binary will be called
+"hello".
+
+Note: you can use the -o option to freeze to specify an alternative
+directory where these files are created. This makes it easier to
+clean up after you've shipped the frozen binary. You should invoke
+"make" in the given directory.
+
+
+Freezing Tkinter programs
+-------------------------
+
+Unfortunately, it is currently not possible to freeze programs that
+use Tkinter. It *seems* to work, but when you ship the frozen program
+to a site without a Tcl/Tk installation, it will fail with a complaint
+about missing Tcl/Tk initialization files.
+
+A workaround would be possible, in which the Tcl/Tk library files are
+incorporated in a frozen Python module as string literals and written
+to a temporary location when the program runs; this is currently left
+as an exercise for the reader. (If you implement this, please post to
+the Python newsgroup!)
+
+Of course, you can also simply require that Tcl/Tk is required on the
+target installation.
+
+
+A warning against shared library modules
+----------------------------------------
+
+When your Python installation uses shared library modules, these will
+not be incorporated in the frozen program. Again, the frozen program
+will work when you test it, but it won't work when you ship it to a
+site without a Python installation.
+
+Freeze prints a warning when this is the case at the end of the
+freezing process:
+
+ Warning: unknown modules remain: ...
+
+When this occurs, the best thing to do is usually to rebuild Python
+using static linking only.
+
+
+Troubleshooting
+---------------
+
+If you have trouble using Freeze for a large program, it's probably
+best to start playing with a really simple program first (like the file
+hello.py). If you can't get that to work there's something
+fundamentally wrong -- perhaps you haven't installed Python. To do a
+proper install, you should do "make install" in the Python root
+directory.
+
+
+Usage under Windows 95 or NT
+----------------------------
+
+Under Windows 95 or NT, you *must* use the -p option and point it to
+the top of the Python source tree.
+
+WARNING: the resulting executable is not self-contained; it requires
+the Python DLL, currently PYTHON20.DLL (it does not require the
+standard library of .py files though). It may also require one or
+more extension modules loaded from .DLL or .PYD files; the module
+names are printed in the warning message about remaining unknown
+modules.
+
+The driver script generates a Makefile that works with the Microsoft
+command line C compiler (CL). To compile, run "nmake"; this will
+build a target "hello.exe" if the source was "hello.py". Only the
+files frozenmain.c and frozen.c are used; no config.c is generated or
+used, since the standard DLL is used.
+
+In order for this to work, you must have built Python using the VC++
+(Developer Studio) 5.0 compiler. The provided project builds
+python20.lib in the subdirectory pcbuild\Release of thje Python source
+tree, and this is where the generated Makefile expects it to be. If
+this is not the case, you can edit the Makefile or (probably better)
+winmakemakefile.py (e.g., if you are using the 4.2 compiler, the
+python20.lib file is generated in the subdirectory vc40 of the Python
+source tree).
+
+You can freeze programs that use Tkinter, but Tcl/Tk must be installed
+on the target system.
+
+It is possible to create frozen programs that don't have a console
+window, by specifying the option '-s windows'.
+
+--Guido van Rossum (home page: http://www.python.org/~guido/)
diff --git a/intern/python/freeze/README.NaN b/intern/python/freeze/README.NaN
new file mode 100644
index 00000000000..93892543c4f
--- /dev/null
+++ b/intern/python/freeze/README.NaN
@@ -0,0 +1,12 @@
+$Id$
+
+This is a modification of the freeze.py script used to freeze python
+modules as byte code in Blender.
+
+To create this byte code, simply type 'make'. Freeze will then generate
+the C source files in the TARGETDIR (specified in the Makefile), provided
+that you have a valid python installation.
+
+Be warned: testing of the module dependencies is needed, as these are
+resolved AT RUNTIME!
+
diff --git a/intern/python/freeze/bkfile.py b/intern/python/freeze/bkfile.py
new file mode 100644
index 00000000000..d29716a93c9
--- /dev/null
+++ b/intern/python/freeze/bkfile.py
@@ -0,0 +1,47 @@
+_orig_open = open
+
+class _BkFile:
+ def __init__(self, file, mode, bufsize):
+ import os
+ self.__filename = file
+ self.__backup = file + '~'
+ try:
+ os.unlink(self.__backup)
+ except os.error:
+ pass
+ try:
+ os.rename(file, self.__backup)
+ except os.error:
+ self.__backup = None
+ self.__file = _orig_open(file, mode, bufsize)
+ self.closed = self.__file.closed
+ self.fileno = self.__file.fileno
+ self.flush = self.__file.flush
+ self.isatty = self.__file.isatty
+ self.mode = self.__file.mode
+ self.name = self.__file.name
+ self.read = self.__file.read
+ self.readinto = self.__file.readinto
+ self.readline = self.__file.readline
+ self.readlines = self.__file.readlines
+ self.seek = self.__file.seek
+ self.softspace = self.__file.softspace
+ self.tell = self.__file.tell
+ self.truncate = self.__file.truncate
+ self.write = self.__file.write
+ self.writelines = self.__file.writelines
+
+ def close(self):
+ self.__file.close()
+ if self.__backup is None:
+ return
+ import filecmp
+ if filecmp.cmp(self.__backup, self.__filename, shallow = 0):
+ import os
+ os.unlink(self.__filename)
+ os.rename(self.__backup, self.__filename)
+
+def open(file, mode = 'r', bufsize = -1):
+ if 'w' not in mode:
+ return _orig_open(file, mode, bufsize)
+ return _BkFile(file, mode, bufsize)
diff --git a/intern/python/freeze/checkextensions.py b/intern/python/freeze/checkextensions.py
new file mode 100644
index 00000000000..8d597bfae96
--- /dev/null
+++ b/intern/python/freeze/checkextensions.py
@@ -0,0 +1,91 @@
+# Check for a module in a set of extension directories.
+# An extension directory should contain a Setup file
+# and one or more .o files or a lib.a file.
+
+import os
+import string
+import parsesetup
+
+def checkextensions(unknown, extensions):
+ files = []
+ modules = []
+ edict = {}
+ for e in extensions:
+ setup = os.path.join(e, 'Setup')
+ liba = os.path.join(e, 'lib.a')
+ if not os.path.isfile(liba):
+ liba = None
+ edict[e] = parsesetup.getsetupinfo(setup), liba
+ for mod in unknown:
+ for e in extensions:
+ (mods, vars), liba = edict[e]
+ if not mods.has_key(mod):
+ continue
+ modules.append(mod)
+ if liba:
+ # If we find a lib.a, use it, ignore the
+ # .o files, and use *all* libraries for
+ # *all* modules in the Setup file
+ if liba in files:
+ break
+ files.append(liba)
+ for m in mods.keys():
+ files = files + select(e, mods, vars,
+ m, 1)
+ break
+ files = files + select(e, mods, vars, mod, 0)
+ break
+ return files, modules
+
+def select(e, mods, vars, mod, skipofiles):
+ files = []
+ for w in mods[mod]:
+ w = treatword(w)
+ if not w:
+ continue
+ w = expandvars(w, vars)
+ for w in string.split(w):
+ if skipofiles and w[-2:] == '.o':
+ continue
+ # Assume $var expands to absolute pathname
+ if w[0] not in ('-', '$') and w[-2:] in ('.o', '.a'):
+ w = os.path.join(e, w)
+ if w[:2] in ('-L', '-R') and w[2:3] != '$':
+ w = w[:2] + os.path.join(e, w[2:])
+ files.append(w)
+ return files
+
+cc_flags = ['-I', '-D', '-U']
+cc_exts = ['.c', '.C', '.cc', '.c++']
+
+def treatword(w):
+ if w[:2] in cc_flags:
+ return None
+ if w[:1] == '-':
+ return w # Assume loader flag
+ head, tail = os.path.split(w)
+ base, ext = os.path.splitext(tail)
+ if ext in cc_exts:
+ tail = base + '.o'
+ w = os.path.join(head, tail)
+ return w
+
+def expandvars(str, vars):
+ i = 0
+ while i < len(str):
+ i = k = string.find(str, '$', i)
+ if i < 0:
+ break
+ i = i+1
+ var = str[i:i+1]
+ i = i+1
+ if var == '(':
+ j = string.find(str, ')', i)
+ if j < 0:
+ break
+ var = str[i:j]
+ i = j+1
+ if vars.has_key(var):
+ str = str[:k] + vars[var] + str[i:]
+ i = k
+ return str
diff --git a/intern/python/freeze/checkextensions_win32.py b/intern/python/freeze/checkextensions_win32.py
new file mode 100644
index 00000000000..85c3a3c0cdd
--- /dev/null
+++ b/intern/python/freeze/checkextensions_win32.py
@@ -0,0 +1,190 @@
+"""Extension management for Windows.
+
+Under Windows it is unlikely the .obj files are of use, as special compiler options
+are needed (primarily to toggle the behavior of "public" symbols.
+
+I dont consider it worth parsing the MSVC makefiles for compiler options. Even if
+we get it just right, a specific freeze application may have specific compiler
+options anyway (eg, to enable or disable specific functionality)
+
+So my basic stragtegy is:
+
+* Have some Windows INI files which "describe" one or more extension modules.
+ (Freeze comes with a default one for all known modules - but you can specify
+ your own).
+* This description can include:
+ - The MSVC .dsp file for the extension. The .c source file names
+ are extraced from there.
+ - Specific compiler/linker options
+ - Flag to indicate if Unicode compilation is expected.
+
+At the moment the name and location of this INI file is hardcoded,
+but an obvious enhancement would be to provide command line options.
+"""
+
+import os, string, sys
+try:
+ import win32api
+except ImportError:
+ win32api = None # User has already been warned
+
+class CExtension:
+ """An abstraction of an extension implemented in C/C++
+ """
+ def __init__(self, name, sourceFiles):
+ self.name = name
+ # A list of strings defining additional compiler options.
+ self.sourceFiles = sourceFiles
+ # A list of special compiler options to be applied to
+ # all source modules in this extension.
+ self.compilerOptions = []
+ # A list of .lib files the final .EXE will need.
+ self.linkerLibs = []
+
+ def GetSourceFiles(self):
+ return self.sourceFiles
+
+ def AddCompilerOption(self, option):
+ self.compilerOptions.append(option)
+ def GetCompilerOptions(self):
+ return self.compilerOptions
+
+ def AddLinkerLib(self, lib):
+ self.linkerLibs.append(lib)
+ def GetLinkerLibs(self):
+ return self.linkerLibs
+
+def checkextensions(unknown, extra_inis, prefix):
+ # Create a table of frozen extensions
+
+ defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")
+ if not os.path.isfile(defaultMapName):
+ sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found" % mapFileName)
+ else:
+ # must go on end, so other inis can override.
+ extra_inis.append(defaultMapName)
+
+ ret = []
+ for mod in unknown:
+ for ini in extra_inis:
+# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",
+ defn = get_extension_defn( mod, ini, prefix )
+ if defn is not None:
+# print "Yay - found it!"
+ ret.append( defn )
+ break
+# print "Nope!"
+ else: # For not broken!
+ sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))
+
+ return ret
+
+def get_extension_defn(moduleName, mapFileName, prefix):
+ if win32api is None: return None
+ os.environ['PYTHONPREFIX'] = prefix
+ dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)
+ if dsp=="":
+ return None
+
+ # We allow environment variables in the file name
+ dsp = win32api.ExpandEnvironmentStrings(dsp)
+ # If the path to the .DSP file is not absolute, assume it is relative
+ # to the description file.
+ if not os.path.isabs(dsp):
+ dsp = os.path.join( os.path.split(mapFileName)[0], dsp)
+ # Parse it to extract the source files.
+ sourceFiles = parse_dsp(dsp)
+ if sourceFiles is None:
+ return None
+
+ module = CExtension(moduleName, sourceFiles)
+ # Put the path to the DSP into the environment so entries can reference it.
+ os.environ['dsp_path'] = os.path.split(dsp)[0]
+ os.environ['ini_path'] = os.path.split(mapFileName)[0]
+
+ cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)
+ if cl_options:
+ module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))
+
+ exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
+ exclude = string.split(exclude)
+
+ if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
+ module.AddCompilerOption('/D UNICODE /D _UNICODE')
+
+ libs = string.split(win32api.GetProfileVal(moduleName, "libs", "", mapFileName))
+ for lib in libs:
+ module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
+
+ for exc in exclude:
+ if exc in module.sourceFiles:
+ modules.sourceFiles.remove(exc)
+
+ return module
+
+# Given an MSVC DSP file, locate C source files it uses
+# returns a list of source files.
+def parse_dsp(dsp):
+# print "Processing", dsp
+ # For now, only support
+ ret = []
+ dsp_path, dsp_name = os.path.split(dsp)
+ try:
+ lines = open(dsp, "r").readlines()
+ except IOError, msg:
+ sys.stderr.write("%s: %s\n" % (dsp, msg))
+ return None
+ for line in lines:
+ fields = string.split(string.strip(line), "=", 2)
+ if fields[0]=="SOURCE":
+ if string.lower(os.path.splitext(fields[1])[1]) in ['.cpp', '.c']:
+ ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
+ return ret
+
+def write_extension_table(fname, modules):
+ fp = open(fname, "w")
+ try:
+ fp.write (ext_src_header)
+ # Write fn protos
+ for module in modules:
+ # bit of a hack for .pyd's as part of packages.
+ name = string.split(module.name,'.')[-1]
+ fp.write('extern void init%s(void);\n' % (name) )
+ # Write the table
+ fp.write (ext_tab_header)
+ for module in modules:
+ name = string.split(module.name,'.')[-1]
+ fp.write('\t{"%s", init%s},\n' % (name, name) )
+
+ fp.write (ext_tab_footer)
+ fp.write(ext_src_footer)
+ finally:
+ fp.close()
+
+
+ext_src_header = """\
+#include "Python.h"
+"""
+
+ext_tab_header = """\
+
+static struct _inittab extensions[] = {
+"""
+
+ext_tab_footer = """\
+ /* Sentinel */
+ {0, 0}
+};
+"""
+
+ext_src_footer = """\
+extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
+
+int PyInitFrozenExtensions()
+{
+ return PyImport_ExtendInittab(extensions);
+}
+
+"""
+
+
diff --git a/intern/python/freeze/freeze.py b/intern/python/freeze/freeze.py
new file mode 100755
index 00000000000..e6f4ead15d5
--- /dev/null
+++ b/intern/python/freeze/freeze.py
@@ -0,0 +1,461 @@
+#! /usr/bin/env python
+
+# changes made by strubi@blender.nl
+
+"""Freeze a Python script into a binary.
+
+usage: freeze [options...] script [module]...
+
+Options:
+-p prefix: This is the prefix used when you ran ``make install''
+ in the Python build directory.
+ (If you never ran this, freeze won't work.)
+ The default is whatever sys.prefix evaluates to.
+ It can also be the top directory of the Python source
+ tree; then -P must point to the build tree.
+
+-P exec_prefix: Like -p but this is the 'exec_prefix', used to
+ install objects etc. The default is whatever sys.exec_prefix
+ evaluates to, or the -p argument if given.
+ If -p points to the Python source tree, -P must point
+ to the build tree, if different.
+
+-e extension: A directory containing additional .o files that
+ may be used to resolve modules. This directory
+ should also have a Setup file describing the .o files.
+ On Windows, the name of a .INI file describing one
+ or more extensions is passed.
+ More than one -e option may be given.
+
+-o dir: Directory where the output files are created; default '.'.
+
+-m: Additional arguments are module names instead of filenames.
+
+-a package=dir: Additional directories to be added to the package's
+ __path__. Used to simulate directories added by the
+ package at runtime (eg, by OpenGL and win32com).
+ More than one -a option may be given for each package.
+
+-l file: Pass the file to the linker (windows only)
+
+-d: Debugging mode for the module finder.
+
+-q: Make the module finder totally quiet.
+
+-h: Print this help message.
+
+-x module Exclude the specified module.
+
+-i filename: Include a file with additional command line options. Used
+ to prevent command lines growing beyond the capabilities of
+ the shell/OS. All arguments specified in filename
+ are read and the -i option replaced with the parsed
+ params (note - quoting args in this file is NOT supported)
+
+-s subsystem: Specify the subsystem (For Windows only.);
+ 'console' (default), 'windows', 'service' or 'com_dll'
+
+-w: Toggle Windows (NT or 95) behavior.
+ (For debugging only -- on a win32 platform, win32 behavior
+ is automatic.)
+
+Arguments:
+
+script: The Python script to be executed by the resulting binary.
+
+module ...: Additional Python modules (referenced by pathname)
+ that will be included in the resulting binary. These
+ may be .py or .pyc files. If -m is specified, these are
+ module names that are search in the path instead.
+
+NOTES:
+
+In order to use freeze successfully, you must have built Python and
+installed it ("make install").
+
+The script should not use modules provided only as shared libraries;
+if it does, the resulting binary is not self-contained.
+"""
+
+
+# Import standard modules
+
+import getopt
+import os
+import string
+import sys
+
+
+# Import the freeze-private modules
+
+import checkextensions
+import modulefinder
+import makeconfig
+import makefreeze
+import makemakefile
+import parsesetup
+import bkfile
+
+
+# Main program
+
+def main():
+ # overridable context
+ prefix = None # settable with -p option
+ exec_prefix = None # settable with -P option
+ extensions = []
+ exclude = [] # settable with -x option
+ addn_link = [] # settable with -l, but only honored under Windows.
+ path = sys.path[:]
+ modargs = 0
+ debug = 1
+ odir = ''
+ win = sys.platform[:3] == 'win'
+
+ # default the exclude list for each platform
+ if win: exclude = exclude + [
+ 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', 'os2', 'ce']
+
+ # modules that are imported by the Python runtime
+ #implicits = ["site", "exceptions"]
+ implicits = ["exceptions"]
+
+ # output files
+ frozen_c = 'frozen.c'
+ config_c = 'config.c'
+ target = 'a.out' # normally derived from script name
+ makefile = 'Makefile.freeze'
+ subsystem = 'console'
+
+ # parse command line by first replacing any "-i" options with the file contents.
+ pos = 1
+ while pos < len(sys.argv)-1: # last option can not be "-i", so this ensures "pos+1" is in range!
+ if sys.argv[pos] == '-i':
+ try:
+ options = string.split(open(sys.argv[pos+1]).read())
+ except IOError, why:
+ usage("File name '%s' specified with the -i option can not be read - %s" % (sys.argv[pos+1], why) )
+ # Replace the '-i' and the filename with the read params.
+ sys.argv[pos:pos+2] = options
+ pos = pos + len(options) - 1 # Skip the name and the included args.
+ pos = pos + 1
+
+ # Now parse the command line with the extras inserted.
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], 'a:de:hmo:p:P:I:qs:wx:l:')
+ except getopt.error, msg:
+ usage('getopt error: ' + str(msg))
+
+ # proces option arguments
+ for o, a in opts:
+ if o == '-h':
+ print __doc__
+ return
+ if o == '-d':
+ debug = debug + 1
+ if o == '-e':
+ extensions.append(a)
+ if o == '-I': # include path
+ path.append(a)
+ if o == '-m':
+ modargs = 1
+ if o == '-o':
+ odir = a
+ if o == '-p':
+ prefix = a
+ if o == '-P':
+ exec_prefix = a
+ if o == '-q':
+ debug = 0
+ if o == '-w':
+ win = not win
+ if o == '-s':
+ if not win:
+ usage("-s subsystem option only on Windows")
+ subsystem = a
+ if o == '-x':
+ exclude.append(a)
+ if o == '-l':
+ addn_link.append(a)
+ if o == '-a':
+ apply(modulefinder.AddPackagePath, tuple(string.split(a,"=", 2)))
+
+ # default prefix and exec_prefix
+ if not exec_prefix:
+ if prefix:
+ exec_prefix = prefix
+ else:
+ exec_prefix = sys.exec_prefix
+ if not prefix:
+ prefix = sys.prefix
+
+ # determine whether -p points to the Python source tree
+ ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c'))
+
+ # locations derived from options
+ version = sys.version[:3]
+ if win:
+ extensions_c = 'frozen_extensions.c'
+ if ishome:
+ print "(Using Python source directory)"
+ binlib = exec_prefix
+ incldir = os.path.join(prefix, 'Include')
+ config_h_dir = exec_prefix
+ config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
+ frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c')
+ makefile_in = os.path.join(exec_prefix, 'Modules', 'Makefile')
+ if win:
+ frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
+ else:
+ binlib = os.path.join(exec_prefix,
+ 'lib', 'python%s' % version, 'config')
+ incldir = os.path.join(prefix, 'include', 'python%s' % version)
+ config_h_dir = os.path.join(exec_prefix, 'include',
+ 'python%s' % version)
+ config_c_in = os.path.join(binlib, 'config.c.in')
+ frozenmain_c = os.path.join(binlib, 'frozenmain.c')
+ makefile_in = os.path.join(binlib, 'Makefile')
+ frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c')
+ supp_sources = []
+ defines = []
+ includes = ['-I' + incldir, '-I' + config_h_dir]
+
+ # sanity check of directories and files
+ check_dirs = [prefix, exec_prefix, binlib, incldir]
+ if not win: check_dirs = check_dirs + extensions # These are not directories on Windows.
+ for dir in check_dirs:
+ if not os.path.exists(dir):
+ usage('needed directory %s not found' % dir)
+ if not os.path.isdir(dir):
+ usage('%s: not a directory' % dir)
+ if win:
+ files = supp_sources + extensions # extensions are files on Windows.
+ else:
+ files = [config_c_in, makefile_in] + supp_sources
+ for file in supp_sources:
+ if not os.path.exists(file):
+ usage('needed file %s not found' % file)
+ if not os.path.isfile(file):
+ usage('%s: not a plain file' % file)
+ if not win:
+ for dir in extensions:
+ setup = os.path.join(dir, 'Setup')
+ if not os.path.exists(setup):
+ usage('needed file %s not found' % setup)
+ if not os.path.isfile(setup):
+ usage('%s: not a plain file' % setup)
+
+ # check that enough arguments are passed
+ if not args:
+ usage('at least one filename argument required')
+
+ # check that file arguments exist
+ for arg in args:
+ if arg == '-m':
+ break
+ # if user specified -m on the command line before _any_
+ # file names, then nothing should be checked (as the
+ # very first file should be a module name)
+ if modargs:
+ break
+ if not os.path.exists(arg):
+ usage('argument %s not found' % arg)
+ if not os.path.isfile(arg):
+ usage('%s: not a plain file' % arg)
+
+ # process non-option arguments
+ scriptfile = args[0]
+ modules = args[1:]
+
+ # derive target name from script name
+ base = os.path.basename(scriptfile)
+ base, ext = os.path.splitext(base)
+ if base:
+ if base != scriptfile:
+ target = base
+ else:
+ target = base + '.bin'
+
+ # handle -o option
+ base_frozen_c = frozen_c
+ base_config_c = config_c
+ base_target = target
+ if odir and not os.path.isdir(odir):
+ try:
+ os.mkdir(odir)
+ print "Created output directory", odir
+ except os.error, msg:
+ usage('%s: mkdir failed (%s)' % (odir, str(msg)))
+ base = ''
+ if odir:
+ base = os.path.join(odir, '')
+ frozen_c = os.path.join(odir, frozen_c)
+ config_c = os.path.join(odir, config_c)
+ target = os.path.join(odir, target)
+ makefile = os.path.join(odir, makefile)
+ if win: extensions_c = os.path.join(odir, extensions_c)
+
+ # Handle special entry point requirements
+ # (on Windows, some frozen programs do not use __main__, but
+ # import the module directly. Eg, DLLs, Services, etc
+ custom_entry_point = None # Currently only used on Windows
+ python_entry_is_main = 1 # Is the entry point called __main__?
+ # handle -s option on Windows
+ if win:
+ import winmakemakefile
+ try:
+ custom_entry_point, python_entry_is_main = \
+ winmakemakefile.get_custom_entry_point(subsystem)
+ except ValueError, why:
+ usage(why)
+
+
+ # Actual work starts here...
+
+ # collect all modules of the program
+ dir = os.path.dirname(scriptfile)
+ path[0] = dir
+ mf = modulefinder.ModuleFinder(path, debug, exclude)
+
+ if win and subsystem=='service':
+ # If a Windows service, then add the "built-in" module.
+ mod = mf.add_module("servicemanager")
+ mod.__file__="dummy.pyd" # really built-in to the resulting EXE
+
+ for mod in implicits:
+ mf.import_hook(mod)
+ for mod in modules:
+ if mod == '-m':
+ modargs = 1
+ continue
+ if modargs:
+ if mod[-2:] == '.*':
+ mf.import_hook(mod[:-2], None, ["*"])
+ else:
+ mf.import_hook(mod)
+ else:
+ mf.load_file(mod)
+
+ # Add the main script as either __main__, or the actual module name.
+ if python_entry_is_main:
+ mf.run_script(scriptfile)
+ else:
+ mf.load_file(scriptfile)
+
+ if debug > 0:
+ mf.report()
+ print
+ dict = mf.modules
+
+ # generate output for frozen modules
+ files = makefreeze.makefreeze(base, dict, debug, custom_entry_point, 1)
+ # look for unfrozen modules (builtin and of unknown origin)
+ builtins = []
+ unknown = []
+ mods = dict.keys()
+ mods.sort()
+ for mod in mods:
+ if dict[mod].__code__:
+ continue
+ if not dict[mod].__file__:
+ builtins.append(mod)
+ else:
+ unknown.append(mod)
+
+ # search for unknown modules in extensions directories (not on Windows)
+ addfiles = []
+ frozen_extensions = [] # Windows list of modules.
+ if unknown or (not win and builtins):
+ if not win:
+ addfiles, addmods = \
+ checkextensions.checkextensions(unknown+builtins,
+ extensions)
+ for mod in addmods:
+ if mod in unknown:
+ unknown.remove(mod)
+ builtins.append(mod)
+ else:
+ # Do the windows thang...
+ import checkextensions_win32
+ # Get a list of CExtension instances, each describing a module
+ # (including its source files)
+ frozen_extensions = checkextensions_win32.checkextensions(
+ unknown, extensions, prefix)
+ for mod in frozen_extensions:
+ unknown.remove(mod.name)
+
+ # report unknown modules
+ if unknown:
+ sys.stderr.write('Warning: unknown modules remain: %s\n' %
+ string.join(unknown))
+
+ # windows gets different treatment
+ if win:
+ # Taking a shortcut here...
+ import winmakemakefile, checkextensions_win32
+ checkextensions_win32.write_extension_table(extensions_c,
+ frozen_extensions)
+ # Create a module definition for the bootstrap C code.
+ xtras = [frozenmain_c, os.path.basename(frozen_c),
+ frozendllmain_c, os.path.basename(extensions_c)] + files
+ maindefn = checkextensions_win32.CExtension( '__main__', xtras )
+ frozen_extensions.append( maindefn )
+ outfp = open(makefile, 'w')
+ try:
+ winmakemakefile.makemakefile(outfp,
+ locals(),
+ frozen_extensions,
+ os.path.basename(target))
+ finally:
+ outfp.close()
+ return
+
+ # generate config.c and Makefile
+ builtins.sort()
+ infp = open(config_c_in)
+ outfp = bkfile.open(config_c, 'w')
+ try:
+ makeconfig.makeconfig(infp, outfp, builtins)
+ finally:
+ outfp.close()
+ infp.close()
+
+ cflags = defines + includes + ['$(OPT)']
+ libs = [os.path.join(binlib, 'libpython$(VERSION).a')]
+
+ somevars = {}
+ if os.path.exists(makefile_in):
+ makevars = parsesetup.getmakevars(makefile_in)
+ for key in makevars.keys():
+ somevars[key] = makevars[key]
+
+ somevars['CFLAGS'] = string.join(cflags) # override
+ files = ['$(OPT)', '$(LDFLAGS)', base_config_c, base_frozen_c] + \
+ files + supp_sources + addfiles + libs + \
+ ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
+
+ outfp = bkfile.open(makefile, 'w')
+ try:
+ makemakefile.makemakefile(outfp, somevars, files, base_target)
+ finally:
+ outfp.close()
+
+ # Done!
+
+ if odir:
+ print 'Now run "make" in', odir,
+ print 'to build the target:', base_target
+ else:
+ print 'Now run "make" to build the target:', base_target
+
+
+# Print usage message and exit
+
+def usage(msg):
+ sys.stdout = sys.stderr
+ print "Error:", msg
+ print "Use ``%s -h'' for help" % sys.argv[0]
+ sys.exit(2)
+
+
+main()
diff --git a/intern/python/freeze/hello.py b/intern/python/freeze/hello.py
new file mode 100644
index 00000000000..f978acc883c
--- /dev/null
+++ b/intern/python/freeze/hello.py
@@ -0,0 +1 @@
+print 'Hello world...'
diff --git a/intern/python/freeze/makeconfig.py b/intern/python/freeze/makeconfig.py
new file mode 100644
index 00000000000..5d1ba2c333c
--- /dev/null
+++ b/intern/python/freeze/makeconfig.py
@@ -0,0 +1,61 @@
+import regex
+
+
+# Write the config.c file
+
+never = ['marshal', '__main__', '__builtin__', 'sys', 'exceptions']
+
+def makeconfig(infp, outfp, modules, with_ifdef=0):
+ m1 = regex.compile('-- ADDMODULE MARKER 1 --')
+ m2 = regex.compile('-- ADDMODULE MARKER 2 --')
+ while 1:
+ line = infp.readline()
+ if not line: break
+ outfp.write(line)
+ if m1 and m1.search(line) >= 0:
+ m1 = None
+ for mod in modules:
+ if mod in never:
+ continue
+ if with_ifdef:
+ outfp.write("#ifndef init%s\n"%mod)
+ outfp.write('extern void init%s();\n' % mod)
+ if with_ifdef:
+ outfp.write("#endif\n")
+ elif m2 and m2.search(line) >= 0:
+ m2 = None
+ for mod in modules:
+ if mod in never:
+ continue
+ outfp.write('\t{"%s", init%s},\n' %
+ (mod, mod))
+ if m1:
+ sys.stderr.write('MARKER 1 never found\n')
+ elif m2:
+ sys.stderr.write('MARKER 2 never found\n')
+
+
+# Test program.
+
+def test():
+ import sys
+ if not sys.argv[3:]:
+ print 'usage: python makeconfig.py config.c.in outputfile',
+ print 'modulename ...'
+ sys.exit(2)
+ if sys.argv[1] == '-':
+ infp = sys.stdin
+ else:
+ infp = open(sys.argv[1])
+ if sys.argv[2] == '-':
+ outfp = sys.stdout
+ else:
+ outfp = open(sys.argv[2], 'w')
+ makeconfig(infp, outfp, sys.argv[3:])
+ if outfp != sys.stdout:
+ outfp.close()
+ if infp != sys.stdin:
+ infp.close()
+
+if __name__ == '__main__':
+ test()
diff --git a/intern/python/freeze/makefreeze.py b/intern/python/freeze/makefreeze.py
new file mode 100644
index 00000000000..8bd9ce1a2e2
--- /dev/null
+++ b/intern/python/freeze/makefreeze.py
@@ -0,0 +1,115 @@
+##
+##
+## Customized makefreeze for NaN
+##
+##
+## 1.11.2001, strubi@blender.nl
+##
+##
+import marshal
+import string
+import bkfile
+
+
+# Write a file containing frozen code for the modules in the dictionary.
+
+header = """
+#include "Python.h"
+
+static struct _frozen _PyImport_FrozenModules[] = {
+"""
+trailer = """\
+ {0, 0, 0} /* sentinel */
+};
+"""
+
+# if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app.
+main_entry_point = """
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int Py_FrozenMain(int, char **);
+ init_frozen_modules();
+ return Py_FrozenMain(argc, argv);
+}
+
+"""
+
+default_entry_point = """
+void
+init_frozenmodules(void)
+{
+""" + ((not __debug__ and """
+ Py_OptimizeFlag++;
+""") or "") + """
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+}
+"""
+
+HEADER = """
+/* This is a generated file, containing frozen bytecode.
+ * Check $(HOME)/develop/intern/python/freeze/README for more information.
+ */
+
+"""
+
+def makefreeze(base, dict, debug=0, entry_point = None, exclude_main = 0):
+ if entry_point is None: entry_point = default_entry_point
+ done = []
+ files = []
+ mods = dict.keys()
+ if exclude_main:
+ mods.remove("__main__")
+ mods.sort()
+ for mod in mods:
+ m = dict[mod]
+ mangled = string.join(string.split(mod, "."), "__")
+ if m.__code__:
+ file = 'M_' + mangled + '.c'
+ outfp = bkfile.open(base + file, 'w')
+ outfp.write(HEADER)
+ files.append(file)
+ if debug:
+ print "freezing", mod, "..."
+ str = marshal.dumps(m.__code__)
+ size = len(str)
+ if m.__path__:
+ # Indicate package by negative size
+ size = -size
+ done.append((mod, mangled, size))
+ writecode(outfp, mangled, str)
+ outfp.close()
+ if debug:
+ print "generating table of frozen modules"
+ outfp = bkfile.open(base + 'frozen.c', 'w')
+ for mod, mangled, size in done:
+ outfp.write('extern unsigned char M_%s[];\n' % mangled)
+ outfp.write(header)
+ for mod, mangled, size in done:
+ outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
+ outfp.write(trailer)
+ outfp.write(entry_point)
+ outfp.close()
+ #outfp = bkfile.open(base + 'main.c', 'w')
+ #outfp.write(main_entry_point)
+ #outfp.close()
+ return files
+
+
+
+# Write a C initializer for a module containing the frozen python code.
+# The array is called M_<mod>.
+
+def writecode(outfp, mod, str):
+ outfp.write('unsigned char M_%s[] = {' % mod)
+ for i in range(0, len(str), 16):
+ outfp.write('\n\t')
+ for c in str[i:i+16]:
+ outfp.write('%d,' % ord(c))
+ outfp.write('\n};\n')
+
+## def writecode(outfp, mod, str):
+## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
+## string.join(map(lambda s: `s`[1:-1], string.split(str, '"')), '\\"')))
diff --git a/intern/python/freeze/makemakefile.py b/intern/python/freeze/makemakefile.py
new file mode 100644
index 00000000000..bb2ed43430d
--- /dev/null
+++ b/intern/python/freeze/makemakefile.py
@@ -0,0 +1,57 @@
+# Write the actual Makefile.
+##
+##
+## Customized makemakefile for NaN
+##
+##
+## 1.11.2001, strubi@blender.nl
+##
+##
+
+
+import os
+import string
+
+def makemakefile(outfp, makevars, files, target):
+ outfp.write("# Makefile generated by freeze.py script\n\n")
+
+ target = "frozen"
+ libtarget = "lib" + target
+ targetlib = libtarget + ".a"
+ #targetlib = "libpyfrozen.a"
+
+ keys = makevars.keys()
+ keys.sort()
+ for key in keys:
+ outfp.write("%s=%s\n" % (key, makevars[key]))
+ outfp.write("\nall: %s\n\n" % libtarget)
+
+ deps = []
+ for i in range(len(files)):
+ file = files[i]
+ if file[-2:] == '.c':
+ base = os.path.basename(file)
+ dest = base[:-2] + '.o'
+ # outfp.write("%s: %s\n" % (dest, file))
+ # outfp.write("\t$(CC) $(CFLAGS) -c %s\n" % file)
+ files[i] = dest
+ deps.append(dest)
+
+ mainfile = 'M___main__.o'
+
+ try:
+ deps.remove(mainfile)
+ except:
+ pass
+ outfp.write("OBJS = %s\n" % string.join(deps))
+
+# libfiles.remove('M___main__.o') # don't link with __main__
+
+ outfp.write("\n%s: $(OBJS)\n" % (libtarget))
+ outfp.write("\t$(AR) ruv %s $(OBJS)\n" % (targetlib))
+
+ outfp.write("\n%s: %s $(OBJS)\n" % (target, mainfile))
+ outfp.write("\t$(CC) %s %s -o %s $(LDLAST)\n" %
+ (mainfile, " ".join(deps), target))
+
+ outfp.write("\nclean:\n\t-rm -f *.o *.a %s\n" % target)
diff --git a/intern/python/freeze/modulefinder.py b/intern/python/freeze/modulefinder.py
new file mode 100644
index 00000000000..e84a54128f6
--- /dev/null
+++ b/intern/python/freeze/modulefinder.py
@@ -0,0 +1,444 @@
+"""Find modules used by a script, using introspection."""
+
+import dis
+import imp
+import marshal
+import os
+import re
+import string
+import sys
+
+if sys.platform=="win32":
+ # On Windows, we can locate modules in the registry with
+ # the help of the win32api package.
+ try:
+ import win32api
+ except ImportError:
+ print "The win32api module is not available - modules listed"
+ print "in the registry will not be found."
+ win32api = None
+
+
+IMPORT_NAME = dis.opname.index('IMPORT_NAME')
+IMPORT_FROM = dis.opname.index('IMPORT_FROM')
+STORE_NAME = dis.opname.index('STORE_NAME')
+STORE_FAST = dis.opname.index('STORE_FAST')
+STORE_GLOBAL = dis.opname.index('STORE_GLOBAL')
+STORE_OPS = [STORE_NAME, STORE_FAST, STORE_GLOBAL]
+
+# Modulefinder does a good job at simulating Python's, but it can not
+# handle __path__ modifications packages make at runtime. Therefore there
+# is a mechanism whereby you can register extra paths in this map for a
+# package, and it will be honored.
+
+# Note this is a mapping is lists of paths.
+packagePathMap = {}
+
+# A Public interface
+def AddPackagePath(packagename, path):
+ paths = packagePathMap.get(packagename, [])
+ paths.append(path)
+ packagePathMap[packagename] = paths
+
+class Module:
+
+ def __init__(self, name, file=None, path=None):
+ self.__name__ = name
+ self.__file__ = file
+ self.__path__ = path
+ self.__code__ = None
+
+ def __repr__(self):
+ s = "Module(%s" % `self.__name__`
+ if self.__file__ is not None:
+ s = s + ", %s" % `self.__file__`
+ if self.__path__ is not None:
+ s = s + ", %s" % `self.__path__`
+ s = s + ")"
+ return s
+
+
+class ModuleFinder:
+
+ def __init__(self, path=None, debug=0, excludes = []):
+ if path is None:
+ path = sys.path
+ self.path = path
+ self.modules = {}
+ self.badmodules = {}
+ self.debug = debug
+ self.indent = 0
+ self.excludes = excludes
+
+ def msg(self, level, str, *args):
+ if level <= self.debug:
+ for i in range(self.indent):
+ print " ",
+ print str,
+ for arg in args:
+ print repr(arg),
+ print
+
+ def msgin(self, *args):
+ level = args[0]
+ if level <= self.debug:
+ self.indent = self.indent + 1
+ apply(self.msg, args)
+
+ def msgout(self, *args):
+ level = args[0]
+ if level <= self.debug:
+ self.indent = self.indent - 1
+ apply(self.msg, args)
+
+ def run_script(self, pathname):
+ self.msg(2, "run_script", pathname)
+ fp = open(pathname)
+ stuff = ("", "r", imp.PY_SOURCE)
+ self.load_module('__main__', fp, pathname, stuff)
+
+ def load_file(self, pathname):
+ dir, name = os.path.split(pathname)
+ name, ext = os.path.splitext(name)
+ fp = open(pathname)
+ stuff = (ext, "r", imp.PY_SOURCE)
+ self.load_module(name, fp, pathname, stuff)
+
+ def import_hook(self, name, caller=None, fromlist=None):
+ self.msg(3, "import_hook", name, caller, fromlist)
+ parent = self.determine_parent(caller)
+ q, tail = self.find_head_package(parent, name)
+ m = self.load_tail(q, tail)
+ if not fromlist:
+ return q
+ if m.__path__:
+ self.ensure_fromlist(m, fromlist)
+
+ def determine_parent(self, caller):
+ self.msgin(4, "determine_parent", caller)
+ if not caller:
+ self.msgout(4, "determine_parent -> None")
+ return None
+ pname = caller.__name__
+ if caller.__path__:
+ parent = self.modules[pname]
+ assert caller is parent
+ self.msgout(4, "determine_parent ->", parent)
+ return parent
+ if '.' in pname:
+ i = string.rfind(pname, '.')
+ pname = pname[:i]
+ parent = self.modules[pname]
+ assert parent.__name__ == pname
+ self.msgout(4, "determine_parent ->", parent)
+ return parent
+ self.msgout(4, "determine_parent -> None")
+ return None
+
+ def find_head_package(self, parent, name):
+ self.msgin(4, "find_head_package", parent, name)
+ if '.' in name:
+ i = string.find(name, '.')
+ head = name[:i]
+ tail = name[i+1:]
+ else:
+ head = name
+ tail = ""
+ if parent:
+ qname = "%s.%s" % (parent.__name__, head)
+ else:
+ qname = head
+ q = self.import_module(head, qname, parent)
+ if q:
+ self.msgout(4, "find_head_package ->", (q, tail))
+ return q, tail
+ if parent:
+ qname = head
+ parent = None
+ q = self.import_module(head, qname, parent)
+ if q:
+ self.msgout(4, "find_head_package ->", (q, tail))
+ return q, tail
+ self.msgout(4, "raise ImportError: No module named", qname)
+ raise ImportError, "No module named " + qname
+
+ def load_tail(self, q, tail):
+ self.msgin(4, "load_tail", q, tail)
+ m = q
+ while tail:
+ i = string.find(tail, '.')
+ if i < 0: i = len(tail)
+ head, tail = tail[:i], tail[i+1:]
+ mname = "%s.%s" % (m.__name__, head)
+ m = self.import_module(head, mname, m)
+ if not m:
+ self.msgout(4, "raise ImportError: No module named", mname)
+ raise ImportError, "No module named " + mname
+ self.msgout(4, "load_tail ->", m)
+ return m
+
+ def ensure_fromlist(self, m, fromlist, recursive=0):
+ self.msg(4, "ensure_fromlist", m, fromlist, recursive)
+ for sub in fromlist:
+ if sub == "*":
+ if not recursive:
+ all = self.find_all_submodules(m)
+ if all:
+ self.ensure_fromlist(m, all, 1)
+ elif not hasattr(m, sub):
+ subname = "%s.%s" % (m.__name__, sub)
+ submod = self.import_module(sub, subname, m)
+ if not submod:
+ raise ImportError, "No module named " + subname
+
+ def find_all_submodules(self, m):
+ if not m.__path__:
+ return
+ modules = {}
+ suffixes = [".py", ".pyc", ".pyo"]
+ for dir in m.__path__:
+ try:
+ names = os.listdir(dir)
+ except os.error:
+ self.msg(2, "can't list directory", dir)
+ continue
+ for name in names:
+ mod = None
+ for suff in suffixes:
+ n = len(suff)
+ if name[-n:] == suff:
+ mod = name[:-n]
+ break
+ if mod and mod != "__init__":
+ modules[mod] = mod
+ return modules.keys()
+
+ def import_module(self, partname, fqname, parent):
+ self.msgin(3, "import_module", partname, fqname, parent)
+ try:
+ m = self.modules[fqname]
+ except KeyError:
+ pass
+ else:
+ self.msgout(3, "import_module ->", m)
+ return m
+ if self.badmodules.has_key(fqname):
+ self.msgout(3, "import_module -> None")
+ if parent:
+ self.badmodules[fqname][parent.__name__] = None
+ return None
+ try:
+ fp, pathname, stuff = self.find_module(partname,
+ parent and parent.__path__)
+ except ImportError:
+ self.msgout(3, "import_module ->", None)
+ return None
+ try:
+ m = self.load_module(fqname, fp, pathname, stuff)
+ finally:
+ if fp: fp.close()
+ if parent:
+ setattr(parent, partname, m)
+ self.msgout(3, "import_module ->", m)
+ return m
+
+ def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
+ self.msgin(2, "load_module", fqname, fp and "fp", pathname)
+ if type == imp.PKG_DIRECTORY:
+ m = self.load_package(fqname, pathname)
+ self.msgout(2, "load_module ->", m)
+ return m
+ if type == imp.PY_SOURCE:
+ co = compile(fp.read()+'\n', pathname, 'exec')
+ elif type == imp.PY_COMPILED:
+ if fp.read(4) != imp.get_magic():
+ self.msgout(2, "raise ImportError: Bad magic number", pathname)
+ raise ImportError, "Bad magic number in %s" % pathname
+ fp.read(4)
+ co = marshal.load(fp)
+ else:
+ co = None
+ m = self.add_module(fqname)
+ m.__file__ = pathname
+ if co:
+ m.__code__ = co
+ self.scan_code(co, m)
+ self.msgout(2, "load_module ->", m)
+ return m
+
+ def scan_code(self, co, m):
+ code = co.co_code
+ n = len(code)
+ i = 0
+ lastname = None
+ while i < n:
+ c = code[i]
+ i = i+1
+ op = ord(c)
+ if op >= dis.HAVE_ARGUMENT:
+ oparg = ord(code[i]) + ord(code[i+1])*256
+ i = i+2
+ if op == IMPORT_NAME:
+ name = lastname = co.co_names[oparg]
+ if not self.badmodules.has_key(lastname):
+ try:
+ self.import_hook(name, m)
+ except ImportError, msg:
+ self.msg(2, "ImportError:", str(msg))
+ if not self.badmodules.has_key(name):
+ self.badmodules[name] = {}
+ self.badmodules[name][m.__name__] = None
+ elif op == IMPORT_FROM:
+ name = co.co_names[oparg]
+ assert lastname is not None
+ if not self.badmodules.has_key(lastname):
+ try:
+ self.import_hook(lastname, m, [name])
+ except ImportError, msg:
+ self.msg(2, "ImportError:", str(msg))
+ fullname = lastname + "." + name
+ if not self.badmodules.has_key(fullname):
+ self.badmodules[fullname] = {}
+ self.badmodules[fullname][m.__name__] = None
+ elif op in STORE_OPS:
+ # Skip; each IMPORT_FROM is followed by a STORE_* opcode
+ pass
+ else:
+ lastname = None
+ for c in co.co_consts:
+ if isinstance(c, type(co)):
+ self.scan_code(c, m)
+
+ def load_package(self, fqname, pathname):
+ self.msgin(2, "load_package", fqname, pathname)
+ m = self.add_module(fqname)
+ m.__file__ = pathname
+ m.__path__ = [pathname]
+
+ # As per comment at top of file, simulate runtime __path__ additions.
+ m.__path__ = m.__path__ + packagePathMap.get(fqname, [])
+
+ fp, buf, stuff = self.find_module("__init__", m.__path__)
+ self.load_module(fqname, fp, buf, stuff)
+ self.msgout(2, "load_package ->", m)
+ return m
+
+ def add_module(self, fqname):
+ if self.modules.has_key(fqname):
+ return self.modules[fqname]
+ self.modules[fqname] = m = Module(fqname)
+ return m
+
+ def find_module(self, name, path):
+ if name in self.excludes:
+ self.msgout(3, "find_module -> Excluded")
+ raise ImportError, name
+
+ if path is None:
+ if name in sys.builtin_module_names:
+ return (None, None, ("", "", imp.C_BUILTIN))
+
+ # Emulate the Registered Module support on Windows.
+ if sys.platform=="win32" and win32api is not None:
+ HKEY_LOCAL_MACHINE = 0x80000002
+ try:
+ pathname = win32api.RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore\\%s\\Modules\\%s" % (sys.winver, name))
+ fp = open(pathname, "rb")
+ # XXX - To do - remove the hard code of C_EXTENSION.
+ stuff = "", "rb", imp.C_EXTENSION
+ return fp, pathname, stuff
+ except win32api.error:
+ pass
+
+ path = self.path
+ return imp.find_module(name, path)
+
+ def report(self):
+ print
+ print " %-25s %s" % ("Name", "File")
+ print " %-25s %s" % ("----", "----")
+ # Print modules found
+ keys = self.modules.keys()
+ keys.sort()
+ for key in keys:
+ m = self.modules[key]
+ if m.__path__:
+ print "P",
+ else:
+ print "m",
+ print "%-25s" % key, m.__file__ or ""
+
+ # Print missing modules
+ keys = self.badmodules.keys()
+ keys.sort()
+ for key in keys:
+ # ... but not if they were explicitly excluded.
+ if key not in self.excludes:
+ mods = self.badmodules[key].keys()
+ mods.sort()
+ print "?", key, "from", string.join(mods, ', ')
+
+
+def test():
+ # Parse command line
+ import getopt
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")
+ except getopt.error, msg:
+ print msg
+ return
+
+ # Process options
+ debug = 1
+ domods = 0
+ addpath = []
+ exclude = []
+ for o, a in opts:
+ if o == '-d':
+ debug = debug + 1
+ if o == '-m':
+ domods = 1
+ if o == '-p':
+ addpath = addpath + string.split(a, os.pathsep)
+ if o == '-q':
+ debug = 0
+ if o == '-x':
+ exclude.append(a)
+
+ # Provide default arguments
+ if not args:
+ script = "hello.py"
+ else:
+ script = args[0]
+
+ # Set the path based on sys.path and the script directory
+ path = sys.path[:]
+ path[0] = os.path.dirname(script)
+ path = addpath + path
+ if debug > 1:
+ print "path:"
+ for item in path:
+ print " ", `item`
+
+ # Create the module finder and turn its crank
+ mf = ModuleFinder(path, debug, exclude)
+ for arg in args[1:]:
+ if arg == '-m':
+ domods = 1
+ continue
+ if domods:
+ if arg[-2:] == '.*':
+ mf.import_hook(arg[:-2], None, ["*"])
+ else:
+ mf.import_hook(arg)
+ else:
+ mf.load_file(arg)
+ mf.run_script(script)
+ mf.report()
+
+
+if __name__ == '__main__':
+ try:
+ test()
+ except KeyboardInterrupt:
+ print "\n[interrupt]"
diff --git a/intern/python/freeze/parsesetup.py b/intern/python/freeze/parsesetup.py
new file mode 100644
index 00000000000..1795671e946
--- /dev/null
+++ b/intern/python/freeze/parsesetup.py
@@ -0,0 +1,98 @@
+# Parse Makefiles and Python Setup(.in) files.
+
+import regex
+import string
+
+
+# Extract variable definitions from a Makefile.
+# Return a dictionary mapping names to values.
+# May raise IOError.
+
+makevardef = regex.compile('^\([a-zA-Z0-9_]+\)[ \t]*=\(.*\)')
+
+def getmakevars(filename):
+ variables = {}
+ fp = open(filename)
+ try:
+ while 1:
+ line = fp.readline()
+ if not line:
+ break
+ if makevardef.match(line) < 0:
+ continue
+ name, value = makevardef.group(1, 2)
+ # Strip trailing comment
+ i = string.find(value, '#')
+ if i >= 0:
+ value = value[:i]
+ value = string.strip(value)
+ variables[name] = value
+ finally:
+ fp.close()
+ return variables
+
+
+# Parse a Python Setup(.in) file.
+# Return two dictionaries, the first mapping modules to their
+# definitions, the second mapping variable names to their values.
+# May raise IOError.
+
+setupvardef = regex.compile('^\([a-zA-Z0-9_]+\)=\(.*\)')
+
+def getsetupinfo(filename):
+ modules = {}
+ variables = {}
+ fp = open(filename)
+ try:
+ while 1:
+ line = fp.readline()
+ if not line:
+ break
+ # Strip comments
+ i = string.find(line, '#')
+ if i >= 0:
+ line = line[:i]
+ if setupvardef.match(line) >= 0:
+ name, value = setupvardef.group(1, 2)
+ variables[name] = string.strip(value)
+ else:
+ words = string.split(line)
+ if words:
+ modules[words[0]] = words[1:]
+ finally:
+ fp.close()
+ return modules, variables
+
+
+# Test the above functions.
+
+def test():
+ import sys
+ import os
+ if not sys.argv[1:]:
+ print 'usage: python parsesetup.py Makefile*|Setup* ...'
+ sys.exit(2)
+ for arg in sys.argv[1:]:
+ base = os.path.basename(arg)
+ if base[:8] == 'Makefile':
+ print 'Make style parsing:', arg
+ v = getmakevars(arg)
+ prdict(v)
+ elif base[:5] == 'Setup':
+ print 'Setup style parsing:', arg
+ m, v = getsetupinfo(arg)
+ prdict(m)
+ prdict(v)
+ else:
+ print arg, 'is neither a Makefile nor a Setup file'
+ print '(name must begin with "Makefile" or "Setup")'
+
+def prdict(d):
+ keys = d.keys()
+ keys.sort()
+ for key in keys:
+ value = d[key]
+ print "%-15s" % key, str(value)
+
+if __name__ == '__main__':
+ test()
diff --git a/intern/python/freeze/winmakemakefile.py b/intern/python/freeze/winmakemakefile.py
new file mode 100644
index 00000000000..d668a6e8273
--- /dev/null
+++ b/intern/python/freeze/winmakemakefile.py
@@ -0,0 +1,146 @@
+import sys, os, string
+
+# Template used then the program is a GUI program
+WINMAINTEMPLATE = """
+#include <windows.h>
+
+int WINAPI WinMain(
+ HINSTANCE hInstance, // handle to current instance
+ HINSTANCE hPrevInstance, // handle to previous instance
+ LPSTR lpCmdLine, // pointer to command line
+ int nCmdShow // show state of window
+ )
+{
+ extern int Py_FrozenMain(int, char **);
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+ return Py_FrozenMain(__argc, __argv);
+}
+"""
+
+SERVICETEMPLATE = """
+extern int PythonService_main(int, char **);
+
+int main( int argc, char **argv)
+{
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+ return PythonService_main(argc, argv);
+}
+"""
+
+subsystem_details = {
+ # -s flag : (C entry point template), (is it __main__?), (is it a DLL?)
+ 'console' : (None, 1, 0),
+ 'windows' : (WINMAINTEMPLATE, 1, 0),
+ 'service' : (SERVICETEMPLATE, 0, 0),
+ 'com_dll' : ("", 0, 1),
+}
+
+def get_custom_entry_point(subsystem):
+ try:
+ return subsystem_details[subsystem][:2]
+ except KeyError:
+ raise ValueError, "The subsystem %s is not known" % subsystem
+
+
+def makemakefile(outfp, vars, files, target):
+ save = sys.stdout
+ try:
+ sys.stdout = outfp
+ realwork(vars, files, target)
+ finally:
+ sys.stdout = save
+
+def realwork(vars, moddefns, target):
+ version_suffix = `sys.version_info[0]`+`sys.version_info[1]`
+ print "# Makefile for Microsoft Visual C++ generated by freeze.py script"
+ print
+ print 'target = %s' % target
+ print 'pythonhome = %s' % vars['prefix']
+ print
+ print 'DEBUG=0 # Set to 1 to use the _d versions of Python.'
+ print '!IF $(DEBUG)'
+ print 'debug_suffix=_d'
+ print 'c_debug=/Zi /Od /DDEBUG /D_DEBUG'
+ print 'l_debug=/DEBUG'
+ print 'temp_dir=Build\\Debug'
+ print '!ELSE'
+ print 'debug_suffix='
+ print 'c_debug=/Ox'
+ print 'l_debug='
+ print 'temp_dir=Build\\Release'
+ print '!ENDIF'
+ print
+
+ print '# The following line assumes you have built Python using the standard instructions'
+ print '# Otherwise fix the following line to point to the library.'
+ print 'pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix
+ print
+
+ # We only ever write one "entry point" symbol - either
+ # "main" or "WinMain". Therefore, there is no need to
+ # pass a subsystem switch to the linker as it works it
+ # out all by itself. However, the subsystem _does_ determine
+ # the file extension and additional linker flags.
+ target_link_flags = ""
+ target_ext = ".exe"
+ if subsystem_details[vars['subsystem']][2]:
+ target_link_flags = "-dll"
+ target_ext = ".dll"
+
+
+ print "# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix
+ print "cdl = /MD"
+ print
+ print "all: $(target)$(debug_suffix)%s" % (target_ext)
+ print
+
+ print '$(temp_dir):'
+ print ' if not exist $(temp_dir)\. mkdir $(temp_dir)'
+ print
+
+ objects = []
+ libs = ["shell32.lib", "comdlg32.lib", "wsock32.lib", "user32.lib", "oleaut32.lib"]
+ for moddefn in moddefns:
+ print "# Module", moddefn.name
+ for file in moddefn.sourceFiles:
+ base = os.path.basename(file)
+ base, ext = os.path.splitext(base)
+ objects.append(base + ".obj")
+ print '$(temp_dir)\%s.obj: "%s"' % (base, file)
+ print "\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE",
+ print '"-I$(pythonhome)/Include" "-I$(pythonhome)/PC" \\'
+ print "\t\t$(cflags) $(cdebug) $(cinclude) \\"
+ extra = moddefn.GetCompilerOptions()
+ if extra:
+ print "\t\t%s \\" % (string.join(extra),)
+ print '\t\t"%s"' % file
+ print
+
+ # Add .lib files this module needs
+ for modlib in moddefn.GetLinkerLibs():
+ if modlib not in libs:
+ libs.append(modlib)
+
+ print "ADDN_LINK_FILES=",
+ for addn in vars['addn_link']: print '"%s"' % (addn),
+ print ; print
+
+ print "OBJS=",
+ for obj in objects: print '"$(temp_dir)\%s"' % (obj),
+ print ; print
+
+ print "LIBS=",
+ for lib in libs: print '"%s"' % (lib),
+ print ; print
+
+ print "$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext)
+ print "\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags),
+ print "\t$(OBJS) \\"
+ print "\t$(LIBS) \\"
+ print "\t$(ADDN_LINK_FILES) \\"
+ print "\t$(pythonlib) $(lcustom) $(l_debug)\\"
+ print "\t$(resources)"
+ print
+ print "clean:"
+ print "\t-rm -f *.obj"
+ print "\t-rm -f $(target).exe"
diff --git a/intern/python/ivexport.py b/intern/python/ivexport.py
new file mode 100644
index 00000000000..85987aad66b
--- /dev/null
+++ b/intern/python/ivexport.py
@@ -0,0 +1,225 @@
+#######################
+# (c) Jan Walter 2000 #
+#######################
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+import Blender
+
+class InventorExport:
+ def __init__(self, filename):
+ self.file = open(filename, "w")
+
+ def beginObject(self, object):
+ self.file.write(" Separator {\n")
+
+ def endObject(self, object):
+ self.file.write(" }\n")
+
+ def export(self, scene):
+ print "exporting ..."
+ self.writeHeader()
+ for name in scene.objects:
+ object = Blender.getObject(name)
+ self.beginObject(object)
+ self.writeObject(object)
+ self.endObject(object)
+ self.writeEnd()
+
+ def writeEnd(self):
+ self.file.write("}\n")
+ self.file.close()
+ print "... finished"
+
+ def writeFaces(self, faces, smooth, colors, materials, texture):
+ self.file.write(" IndexedFaceSet {\n")
+ # colors
+ if colors:
+ self.file.write(" vertexProperty VertexProperty {\n")
+ self.file.write(" orderedRGBA [\n")
+ for color in colors[:-1]:
+ r = hex(int(color[0] * 255))
+ if len(r) == 3:
+ r = r + "0"
+ g = hex(int(color[1] * 255))
+ if len(g) == 3:
+ g = g + "0"
+ b = hex(int(color[2] * 255))
+ if len(b) == 3:
+ b = b + "0"
+ colstr = r + g[2:] + b[2:]
+ self.file.write(" %sff,\n" % colstr)
+ color = colors[-1]
+ r = hex(int(color[0] * 255))
+ if len(r) == 3:
+ r = r + "0"
+ g = hex(int(color[1] * 255))
+ if len(g) == 3:
+ g = g + "0"
+ b = hex(int(color[2] * 255))
+ if len(b) == 3:
+ b = b + "0"
+ colstr = r + g[2:] + b[2:]
+ self.file.write(" %sff\n" % colstr)
+ self.file.write(" ]\n")
+ self.file.write(" materialBinding PER_VERTEX_INDEXED\n")
+ self.file.write(" }\n")
+ # coordinates
+ self.file.write(" coordIndex [\n")
+ for face in faces[:-1]:
+ if face[4] != smooth:
+ pass
+ elif face[2] == 0 and face[3] == 0:
+ print "can't export lines at the moment ..."
+ elif face[3] == 0:
+ self.file.write(" %s, %s, %s, -1,\n" %
+ (face[0], face[1], face[2]))
+ else:
+ self.file.write(" %s, %s, %s, %s, -1,\n"%
+ (face[0], face[1], face[2], face[3]))
+ face = faces[-1]
+ if face[4] != smooth:
+ pass
+ elif face[2] == 0 and face[3] == 0:
+ print "can't export lines at the moment ..."
+ elif face[3] == 0:
+ self.file.write(" %s, %s, %s, -1,\n" %
+ (face[0], face[1], face[2]))
+ else:
+ self.file.write(" %s, %s, %s, %s, -1,\n"%
+ (face[0], face[1], face[2], face[3]))
+ self.file.write(" ]\n")
+ # materials
+ if not colors and materials:
+ self.file.write(" materialIndex [\n")
+ for face in faces[:-1]:
+ if face[4] != smooth:
+ pass
+ else:
+ self.file.write(" %s,\n" % face[5])
+ face = faces[-1]
+ if face[4] != smooth:
+ pass
+ else:
+ self.file.write(" %s\n" % face[5])
+ self.file.write(" ]\n")
+ # texture coordinates
+ if texture:
+ self.file.write(" textureCoordIndex [\n")
+ index = 0
+ for face in faces:
+ if face[3] == 0:
+ self.file.write(" " +
+ "%s, %s, %s, -1,\n" %
+ (index, index+1, index+2))
+ else:
+ self.file.write(" " +
+ "%s, %s, %s, %s, -1,\n" %
+ (index, index+1, index+2, index+3))
+ index = index + 4
+ self.file.write(" ]\n")
+ self.file.write(" }\n")
+
+ def writeHeader(self):
+ self.file.write("#Inventor V2.1 ascii\n\n")
+ self.file.write("Separator {\n")
+ self.file.write(" ShapeHints {\n")
+ self.file.write(" vertexOrdering COUNTERCLOCKWISE\n")
+ self.file.write(" }\n")
+
+ def writeMaterials(self, materials):
+ if materials:
+ self.file.write(" Material {\n")
+ self.file.write(" diffuseColor [\n")
+ for name in materials[:-1]:
+ material = Blender.getMaterial(name)
+ self.file.write(" %s %s %s,\n" %
+ (material.R, material.G, material.B))
+ name = materials[-1]
+ material = Blender.getMaterial(name)
+ self.file.write(" %s %s %s\n" %
+ (material.R, material.G, material.B))
+ self.file.write(" ]\n")
+ self.file.write(" }\n")
+ self.file.write(" MaterialBinding {\n")
+ self.file.write(" value PER_FACE_INDEXED\n")
+ self.file.write(" }\n")
+
+ def writeMatrix(self, matrix):
+ self.file.write(" MatrixTransform {\n")
+ self.file.write(" matrix %s %s %s %s\n" %
+ (matrix[0][0], matrix[0][1],
+ matrix[0][2], matrix[0][3]))
+ self.file.write(" %s %s %s %s\n" %
+ (matrix[1][0], matrix[1][1],
+ matrix[1][2], matrix[1][3]))
+ self.file.write(" %s %s %s %s\n" %
+ (matrix[2][0], matrix[2][1],
+ matrix[2][2], matrix[2][3]))
+ self.file.write(" %s %s %s %s\n" %
+ (matrix[3][0], matrix[3][1],
+ matrix[3][2], matrix[3][3]))
+ self.file.write(" }\n")
+
+ def writeNormals(self, normals):
+ self.file.write(" Normal {\n")
+ self.file.write(" vector [\n")
+ for normal in normals[:-1]:
+ self.file.write(" %s %s %s,\n" %
+ (normal[0], normal[1], normal[2]))
+ normal = normals[-1]
+ self.file.write(" %s %s %s\n" %
+ (normal[0], normal[1], normal[2]))
+ self.file.write(" ]\n")
+ self.file.write(" }\n")
+
+ def writeObject(self, object):
+ if object.type == "Mesh":
+ mesh = Blender.getMesh(object.data)
+ self.writeMatrix(object.matrix)
+ self.writeMaterials(object.materials)
+ self.writeTexture(mesh.texture, mesh.texcoords)
+ self.writeVertices(mesh.vertices)
+ self.writeFaces(mesh.faces, 0, mesh.colors, object.materials,
+ mesh.texture)
+ self.writeNormals(mesh.normals)
+ self.writeFaces(mesh.faces, 1, mesh.colors, object.materials,
+ mesh.texture)
+ else:
+ print "can't export %s at the moment ..." % object.type
+
+ def writeTexture(self, texture, texcoords):
+ if texture:
+ self.file.write(" Texture2 {\n")
+ self.file.write(' filename "%s"\n' % texture)
+ self.file.write(" }\n")
+ self.file.write(" TextureCoordinate2 {\n")
+ self.file.write(" point [\n")
+ for texcoord in texcoords:
+ self.file.write(" %s %s,\n" %
+ (texcoord[0], texcoord[1]))
+ self.file.write(" ]\n")
+ self.file.write(" }\n")
+ self.file.write(" TextureCoordinateBinding {\n")
+ self.file.write(" value PER_VERTEX_INDEXED\n")
+ self.file.write(" }\n")
+
+ def writeVertices(self, vertices):
+ self.file.write(" Coordinate3 {\n")
+ self.file.write(" point [\n")
+ for vertex in vertices[:-1]:
+ self.file.write(" %s %s %s,\n" %
+ (vertex[0], vertex[1], vertex[2]))
+ vertex = vertices[-1]
+ self.file.write(" %s %s %s\n" %
+ (vertex[0], vertex[1], vertex[2]))
+ self.file.write(" ]\n")
+ self.file.write(" }\n")
+
+ivexport = InventorExport("test.iv")
+scene = Blender.getCurrentScene()
+ivexport.export(scene)
diff --git a/intern/python/modules/Blender/BGL.py b/intern/python/modules/Blender/BGL.py
new file mode 100644
index 00000000000..033b3560e4f
--- /dev/null
+++ b/intern/python/modules/Blender/BGL.py
@@ -0,0 +1 @@
+from _Blender.BGL import *
diff --git a/intern/python/modules/Blender/Camera.py b/intern/python/modules/Blender/Camera.py
new file mode 100644
index 00000000000..33f615fc0da
--- /dev/null
+++ b/intern/python/modules/Blender/Camera.py
@@ -0,0 +1,106 @@
+"""The Blender Camera module
+
+This module provides access to **Camera** objects in Blender
+
+Example::
+
+ from Blender import Camera, Object, Scene
+ c = Camera.New('ortho') # create new ortho camera data
+ c.lens = 35.0 # set lens value
+ cur = Scene.getCurrent() # get current Scene
+ ob = Object.New('Camera') # make camera object
+ ob.link(c) # link camera data with this object
+ cur.link(ob) # link object into scene
+ cur.setCurrentCamera(ob) # make this camera the active
+"""
+
+import shadow
+import _Blender.Camera as _Camera
+
+
+class Camera(shadow.hasIPO):
+ """Wrapper for Camera DataBlock
+
+ Attributes
+
+ lens -- The lens value
+
+ clipStart -- The clipping start of the view frustum
+
+ clipEnd -- The end clipping plane of the view frustum
+
+ type -- The camera type:
+ 0: perspective camera,
+ 1: orthogonal camera - (see Types)
+
+ mode -- Drawing mode; see Modes
+"""
+
+ _emulation = {'Lens' : "lens",
+ 'ClSta' : "clipStart",
+ 'ClEnd' : "clipEnd",
+ }
+
+ Types = {'persp' : 0,
+ 'ortho' : 1,
+ }
+
+ Modes = {'showLimits' : 1,
+ 'showMist' : 2,
+ }
+
+ def __init__(self, object):
+ self._object = object
+
+ def getType(self):
+ """Returns camera type: "ortho" or "persp" """
+ if self.type == self.Types['ortho']:
+ return 'ortho'
+ else:
+ return 'persp'
+
+ def setType(self, type):
+ """Sets Camera type to 'type' which must be one of ["persp", "ortho"]"""
+ self._object.type = self.Types[type]
+
+ def setMode(self, *modes):
+ """Sets Camera modes *the nice way*, instead of direct access
+of the 'mode' member.
+This function takes a variable number of string arguments of the types
+listed in self.Modes.
+
+
+Example::
+
+ c = Camera.New()
+ c.setMode('showMist', 'showLimits')
+"""
+ flags = 0
+ try:
+ for a in modes:
+ flags |= self.Modes[a]
+ except:
+ raise TypeError, "mode must be one of %s" % self.Modes.keys()
+ self.mode = flags
+
+ def __repr__(self):
+ return "[Camera \"%s\"]" % self.name
+
+def New(type = 'persp'):
+ """Creates new camera Object and returns it. 'type', if specified,
+must be one of Types"""
+ cam = Camera(_Camera.New())
+ cam.setType(type)
+ return cam
+
+def get(name = None):
+ """Returns the Camera with name 'name', if given. Otherwise, a list
+of all Cameras is returned"""
+ if name:
+ return Camera(_Camera.get(name))
+ else:
+ return shadow._List(_Camera.get(), Camera)
+
+Get = get # emulation
+
+
diff --git a/intern/python/modules/Blender/Draw.py b/intern/python/modules/Blender/Draw.py
new file mode 100644
index 00000000000..6c2cb8be09f
--- /dev/null
+++ b/intern/python/modules/Blender/Draw.py
@@ -0,0 +1 @@
+from _Blender.Draw import *
diff --git a/intern/python/modules/Blender/Image.py b/intern/python/modules/Blender/Image.py
new file mode 100644
index 00000000000..c1737e1bb0d
--- /dev/null
+++ b/intern/python/modules/Blender/Image.py
@@ -0,0 +1,52 @@
+"""The Blender Image module
+
+ This module provides (yet) basic support for Blender *Image* data blocks
+
+ Example::
+
+ from Blender import Image
+ im = Image.Load('dead-parrot.jpg')
+"""
+
+import _Blender.Image as _Image
+import shadow
+
+class Image(shadow.shadow):
+ """Image DataBlock object
+
+ See above example on how to create instances of Image objects.
+
+ Attributes
+
+ xrep -- Texture image tiling factor (subdivision) in X
+
+ yrep -- Texture image tiling factor (subdivision) in Y
+
+ LATER:
+
+ * Image buffer access
+
+ * better loading / saving of images
+"""
+ pass
+
+def get(name):
+ """If 'name' given, the Image 'name' is returned if existing, 'None' otherwise.
+If no name is given, a list of all Images is returned"""
+ pass
+
+def Load(filename):
+ """Returns image from file 'filename' as Image object if found, 'None' else."""
+ pass
+
+def New(name):
+ """This function is currently not implemented"""
+ pass
+
+# override all functions again, the above classes are just made
+# for documentation
+
+get = _Image.get
+Get = get
+Load = _Image.Load
+
diff --git a/intern/python/modules/Blender/Ipo.py b/intern/python/modules/Blender/Ipo.py
new file mode 100644
index 00000000000..110f95a5d07
--- /dev/null
+++ b/intern/python/modules/Blender/Ipo.py
@@ -0,0 +1,279 @@
+"""The Blender Ipo module
+
+This module provides access to **Ipo** objects in Blender.
+
+An Ipo object is a datablock of IpoCurves which control properties of
+an object in time.
+
+Note that IpoCurves assigned to rotation values (which must be specified
+in radians) appear scaled in the IpoWindow (which is in fact true, due
+to the fact that conversion to an internal unit of 10.0 angles happens).
+
+Example::
+
+ from Blender import Ipo, Object
+
+ ipo = Ipo.New('Object', 'ObIpo') # Create object ipo with name 'ObIpo'
+ curve = ipo.addCurve('LocY') # add IpoCurve for LocY
+ curve.setInterpolation('Bezier') # set interpolation type
+ curve.setExtrapolation('CyclicLinear') # set extrapolation type
+
+ curve.addBezier((0.0, 0.0)) # add automatic handle bezier point
+ curve.addBezier((20.0, 5.0), 'Free', (10.0, 4.0)) # specify left handle, right auto handle
+ curve.addBezier((30.0, 1.0), 'Vect') # automatic split handle
+ curve.addBezier((100.0, 1.0)) # auto handle
+
+ curve.update() # recalculate curve handles
+
+ curve.eval(35.0) # evaluate curve at 35.0
+
+ ob = Object.get('Plane')
+ ob.setIpo(ipo) # assign ipo to object
+"""
+
+import _Blender.Ipo as _Ipo
+
+import shadow
+
+_RotIpoCurves = ["RotX", "RotY", "RotZ", "dRotX", "dRotY", "dRotZ"]
+
+_radian_factor = 5.72957814 # 18.0 / 3.14159255
+
+def _convertBPoint(b):
+ f = _radian_factor
+ newb = BezierPoint()
+ p = b.pt
+ q = newb.pt
+ q[0], q[1] = (p[0], f * p[1])
+ p = b.h1
+ q = newb.h1
+ q[0], q[1] = (p[0], f * p[1])
+ p = b.h2
+ q = newb.h2
+ q[0], q[1] = (p[0], f * p[1])
+ return newb
+
+
+class IpoBlock(shadow.shadowEx):
+ """Wrapper for Blender Ipo DataBlock
+
+ Attributes
+
+ curves -- list of owned IpoCurves
+"""
+ def get(self, channel = None):
+ """Returns curve with channel identifier 'channel', which is one of the properties
+listed in the Ipo Window, 'None' if not found.
+If 'channel' is not specified, all curves are returned in a list"""
+ if channel:
+ for c in self._object.curves:
+ if c.name == channel:
+ return IpoCurve(c)
+ return None
+ else:
+ return map(lambda x: IpoCurve(x), self._object.curves)
+
+ def __getitem__(self, k):
+ """Emulates dictionary syntax, e.g. ipocurve = ipo['LocX']"""
+ curve = self.get(k)
+ if not curve:
+ raise KeyError, "Ipo does not have a curve for channel %s" % k
+ return curve
+
+ def __setitem__(self, k, val):
+ """Emulates dictionary syntax, e.g. ipo['LocX'] = ipocurve"""
+ c = self.addCurve(k, val)
+
+ has_key = get # dict emulation
+
+ items = get # dict emulation
+
+ def keys(self):
+ return map(lambda x: x.name, self.get())
+
+ def addCurve(self, channel, curve = None):
+ """Adds a curve of channel type 'channel' to the Ipo Block. 'channel' must be one of
+the object properties listed in the Ipo Window. If 'curve' is not specified,
+an empty curve is created, otherwise, the existing IpoCurve 'curve' is copied and
+added to the IpoBlock 'self'.
+In any case, the added curve is returned.
+"""
+ if curve:
+ if curve.__class__.__name__ != "IpoCurve":
+ raise TypeError, "IpoCurve expected"
+ c = self._object.addCurve(channel, curve._object)
+
+ ### RotIpo conversion hack
+ if channel in _RotIpoCurves:
+ print "addCurve, converting", curve.name
+ c.points = map(_convertBPoint, curve.bezierPoints)
+ else:
+ c.points = curve.bezierPoints
+ else:
+ c = self._object.addCurve(channel)
+ return IpoCurve(c)
+
+ _getters = { 'curves' : get }
+
+class BezierPoint:
+ """BezierPoint object
+
+ Attributes
+
+ pt -- Coordinates of the Bezier point
+
+ h1 -- Left handle coordinates
+
+ h2 -- Right handle coordinates
+
+ h1t -- Left handle type (see IpoCurve.addBezier(...) )
+
+ h2t -- Right handle type
+"""
+
+BezierPoint = _Ipo.BezTriple # override
+
+class IpoCurve(shadow.shadowEx):
+ """Wrapper for Blender IpoCurve
+
+ Attributes
+
+ bezierPoints -- A list of BezierPoints (see class BezierPoint),
+ defining the curve shape
+"""
+
+ InterpolationTypes = _Ipo.InterpolationTypes
+ ExtrapolationTypes = _Ipo.ExtrapolationTypes
+
+ def __init__(self, object):
+ self._object = object
+ self.__dict__['bezierPoints'] = self._object.points
+
+ def __getitem__(self, k):
+ """Emulate a sequence of BezierPoints"""
+ print k, type(k)
+ return self.bezierPoints[k]
+
+ def __repr__(self):
+ return "[IpoCurve %s]" % self.name
+
+ def __len__(self):
+ return len(self.bezierPoints)
+
+ def eval(self, time):
+ """Returns float value of curve 'self' evaluated at time 'time' which
+must be a float."""
+ return self._object.eval(time)
+
+ def addBezier(self, p, leftType = 'Auto', left = None, rightType = None, right = None):
+ """Adds a Bezier triple to the IpoCurve.
+
+The following values are float tuples (x,y), denoting position of a control vertex:
+
+p -- The position of the Bezier point
+
+left -- The position of the leftmost handle
+
+right -- The position of the rightmost handle
+
+'leftType', 'rightType' must be one of:
+
+"Auto" -- automatic handle calculation. In this case, 'left' and 'right' don't need to be specified
+
+"Vect" -- automatic split handle calculation. 'left' and 'right' are disregarded.
+
+"Align" -- Handles are aligned automatically. In this case, 'right' does not need to be specified.
+
+"Free" -- Handles can be set freely - this requires both arguments 'left' and 'right'.
+
+"""
+
+ b = _Ipo.BezTriple()
+ b.pt[0], b.pt[1] = (p[0], p[1])
+ b.h1t = leftType
+
+ if rightType:
+ b.h2t = rightType
+ else:
+ b.h2t = leftType
+
+ if left:
+ b.h1[0], b.h1[1] = (left[0], left[1])
+
+ if right:
+ b.h2[0], b.h2[1] = (right[0], right[1])
+
+ self.__dict__['bezierPoints'].append(b)
+ return b
+
+ def update(self, noconvert = 0):
+ # This is an ugly fix for the 'broken' storage of Rotation
+ # ipo values. The angles are stored in units of 10.0 degrees,
+ # which is totally inconsistent with anything I know :-)
+ # We can't (at the moment) change the internals, so we
+ # apply a conversion kludge..
+ if self._object.name in _RotIpoCurves and not noconvert:
+ points = map(_convertBPoint, self.bezierPoints)
+ else:
+ points = self.bezierPoints
+ self._object.points = points
+ self._object.update()
+
+ def getInterpolationType(self, ipotype):
+ "Returns the Interpolation type - see also IpoCurve.InterpolationTypes"
+ return self._object.getInterpolationType()
+
+ def setInterpolationType(self, ipotype):
+ """Sets the interpolation type which must be one of IpoCurve.InterpolationTypes"""
+ try:
+ self._object.setInterpolationType(ipotype)
+ except:
+ raise TypeError, "must be one of %s" % self.InterpolationTypes.keys()
+
+ def getExtrapolationType(self, ipotype):
+ "Returns the Extrapolation type - see also IpoCurve.ExtrapolationTypes"
+ return self._object.getExtrapolationType()
+
+ def setExtrapolationType(self, ipotype):
+ """Sets the interpolation type which must be one of IpoCurve.ExtrapolationTypes"""
+ try:
+ self._object.setInterpolationType(ipotype)
+ except:
+ raise TypeError, "must be one of %s" % self.ExtrapolationTypes.keys()
+
+
+def New(blocktype, name = None):
+ """Returns a new IPO block of type 'blocktype' which must be one of:
+["Object", "Camera", "World", "Material"]
+"""
+ if name:
+ i = _Ipo.New(blocktype, name)
+ else:
+ i = _Ipo.New(blocktype)
+ return IpoBlock(i)
+
+def Eval(ipocurve, time): # emulation code
+ """This function is just there for compatibility.
+Use IpoCurve.eval(time) instead"""
+ return ipocurve.eval(time)
+
+def Recalc(ipocurve): # emulation code
+ """This function is just there for compatibility. Note that Ipos
+assigned to rotation values will *not* get converted to the proper
+unit of radians.
+In the new style API, use IpoCurve.update() instead"""
+ return ipocurve.update(1)
+
+def get(name = None):
+ """If 'name' given, the Ipo 'name' is returned if existing, 'None' otherwise.
+If no name is given, a list of all Ipos is returned"""
+ if name:
+ ipo = _Ipo.get(name)
+ if ipo:
+ return IpoBlock(ipo)
+ else:
+ return None
+ else:
+ return shadow._List(_Ipo.get(), IpoBlock)
+
+Get = get # emulation
diff --git a/intern/python/modules/Blender/Lamp.py b/intern/python/modules/Blender/Lamp.py
new file mode 100644
index 00000000000..ab7ed63592a
--- /dev/null
+++ b/intern/python/modules/Blender/Lamp.py
@@ -0,0 +1,168 @@
+"""The Blender Lamp module
+
+This module provides control over **Lamp** objects in Blender.
+
+Example::
+
+ from Blender import Lamp
+ l = Lamp.New('Spot')
+ l.setMode('square', 'shadow')
+ ob = Object.New('Lamp')
+ ob.link(l)
+"""
+
+import _Blender.Lamp as _Lamp
+import shadow
+
+_validBufferSizes = [512, 768, 1024, 1536, 2560]
+
+def _setBufferSize(self, bufsize):
+ """Set the lamp's buffersize. This function makes sure that a valid
+bufferSize value is set (unlike setting lamp.bufferSize directly)"""
+ if bufsize not in _validBufferSizes:
+ print """Buffer size should be one of:
+%s
+Setting to default 512""" % _validBufferSizes
+ bufsize = 512
+ self._object.bufferSize = bufsize
+
+class Lamp(shadow.hasIPO, shadow.hasModes):
+ """Wrapper for Blender Lamp DataBlock
+
+ Attributes
+
+ mode -- Lamp mode value - see EditButtons. Do not access directly
+ See setMode()
+
+ type -- Lamp type value - see EditButtons. No direct access, please.
+ See setType()
+
+ col -- RGB vector (R, G, B) of lamp colour
+
+ energy -- Intensity (float)
+
+ dist -- clipping distance of a spot lamp or decay range
+
+ spotSize -- float angle (in degrees) of spot cone
+ (between 0.0 and 180.0)
+
+ spotBlend -- value defining the blurriness of the spot edge
+
+ haloInt -- Halo intensity
+
+ clipStart -- shadow buffer clipping start
+
+ clipStart -- shadow buffer clipping end
+
+ bias -- The bias value for the shadowbuffer routine
+
+ softness -- The filter value for the shadow blurring
+
+ samples -- Number of samples in shadow calculation - the
+ larger, the better
+
+ bufferSize -- Size of the shadow buffer which should be one of:
+ [512, 768, 1024, 1536, 2560]
+
+ haloStep -- Number of steps in halo calculation - the smaller, the
+ the better (and slower). A value of 0 disables shadow
+ halo calculation
+ """
+
+ _emulation = {'Energ' : "energy",
+ 'SpoSi' : "spotSize",
+ 'SpoBl' : "SpotBlend",
+ 'HaInt' : "haloInt",
+ 'Dist' : "dist",
+ 'Quad1' : "quad1",
+ 'Quad2' : "quad2",
+ }
+
+ _setters = {'bufferSize' : _setBufferSize}
+
+ t = _Lamp.Types
+
+ Types = {'Lamp' : t.LOCAL,
+ 'Spot' : t.SPOT,
+ 'Sun' : t.SUN,
+ 'Hemi' : t.HEMI,
+ }
+
+ t = _Lamp.Modes
+
+ Modes = {'quad' : t.QUAD,
+ 'sphere' : t.SPHERE,
+ 'shadow' : t.SHAD,
+ 'halo' : t.HALO,
+ 'layer' : t.LAYER,
+ 'negative' : t.NEG,
+ 'onlyShadow' : t.ONLYSHADOW,
+ 'square' : t.SQUARE,
+ }
+
+ del t
+
+ def __repr__(self):
+ return "[Lamp \"%s\"]" % self.name
+
+ def setType(self, name):
+ """Set the Lamp type of Lamp 'self'. 'name' must be a string of:
+
+* 'Lamp': A standard point light source
+
+* 'Spot': A spot light
+
+* 'Sun' : A unidirectional light source, very far away (like a Sun!)
+
+* 'Hemi': A diffuse hemispherical light source (daylight without sun)"""
+
+ try:
+ self._object.type = self.Types[name]
+ except:
+ raise TypeError, "type must be one of %s" % self.Types.keys()
+
+ def getType(self):
+ """Returns the lamp's type as string. See setType()"""
+ for k in self.Types.keys():
+ if self.Types[k] == self.type:
+ return k
+
+ def getMode(self):
+ """Returns the Lamp modes as a list of strings"""
+ return shadow._getModeBits(self.Modes, self._object.mode)
+
+ def setMode(self, *args):
+ """Set the Lamp mode of Lamp 'self'. This function takes a variable number
+of string arguments of the types listed in self.Modes.
+
+ Example::
+
+ l = Lamp.New()
+ l.setMode('quad', 'shadow')
+"""
+ print args
+ self._object.mode = shadow._setModeBits(self.Modes, args)
+
+ def getBufferSize(self):
+ return self.bufferSize
+
+def New(type = "Lamp", name = "Lamp"):
+ """Returns a new Lamp datablock of type 'type' and optional name 'name'
+"""
+ t = Lamp.Types[type]
+ rawlamp = _Lamp.New()
+ rawlamp.type = t
+ rawlamp.name = name
+ return Lamp(rawlamp)
+
+
+def get(name = None):
+ """If 'name' given, the Lamp 'name' is returned if existing, 'None' otherwise.
+If no name is given, a list of all Lamps is returned"""
+
+ if name:
+ return Lamp(_Lamp.get(name))
+ else:
+ return shadow._List(_Lamp.get(), Lamp)
+
+Types = _Lamp.Types
diff --git a/intern/python/modules/Blender/Material.py b/intern/python/modules/Blender/Material.py
new file mode 100644
index 00000000000..f24541f0f03
--- /dev/null
+++ b/intern/python/modules/Blender/Material.py
@@ -0,0 +1,251 @@
+"""The Blender Material module
+
+ This module provides access to *Material* datablocks
+
+ Example::
+
+ from Blender import Material, NMesh, Object, Scene
+ m = Material.New() # create free Material datablock
+ m.rgbCol = (1.0, 0.0, 0.3) # assign RGB values
+ mesh = NMesh.GetRaw() # get new mesh
+ mesh.addMaterial(m) # add material to mesh
+ object = Object.New('Mesh') # create new object
+ object.link(mesh) # link mesh data to object
+ Scene.getCurrent().link(ob) # link object to current scene
+"""
+
+import _Blender.Material as _Material
+import shadow
+#import Blender.Curve as Curve
+
+# These are getters and setters needed for emulation
+
+def _getRGB(obj):
+ return (obj.R, obj.G, obj.B)
+
+def _getSpec(obj):
+ return (obj.specR, obj.specG, obj.specB)
+
+def _getMir(obj):
+ return (obj.mirR, obj.mirG, obj.mirB)
+
+def _setRGB(obj, rgb):
+ obj.R, obj.G, obj.B = rgb
+
+def _setSpec(obj, rgb):
+ obj.specR, obj.specG, obj.specB = rgb
+
+def _setMir(obj, rgb):
+ obj.mirR, obj.mirG, obj.mirB = rgb
+
+
+
+class Material(shadow.hasIPO, shadow.hasModes):
+ """Material DataBlock object
+
+ See example in the Material module documentation on how to create
+ an instance of a Material object.
+
+ Attributes
+
+ The following attributes are colour vectors (r, g, b)
+
+ rgbCol -- The color vector (R, G, B).
+ The RGB values can be accessed individually as .R, .G and .B
+
+ specCol -- Specularity color vector (specR, specG, specG)
+
+ mirCol -- Mirror color vector (mirR, mirG, mirB)
+
+ The following are float values:
+
+ alpha -- The transparency
+
+ ref -- Reflectivity float value
+
+ emit -- Emit intensity value
+
+ amb -- Ambient intensity value
+
+ spec -- specularity value
+
+ specTransp -- Specular transpareny
+
+ haloSize -- Halo size
+
+ mode -- The material mode bit vector - see Material.ModeFlags
+
+ hard -- The hardness value
+
+"""
+
+ _emulation = {'Mode' : "mode",
+ 'Ref' : "ref",
+ 'HaSize' : "haloSize",
+ 'SpTra' : "specTransp",
+ 'Alpha' : "alpha",
+ 'Spec' : "spec",
+ 'Emit' : "emit",
+ 'Hard' : "hard",
+ 'Amb' : "amb",
+ }
+
+ _getters = {'rgbCol' : _getRGB,
+ 'specCol' : _getSpec,
+ 'mirCol' : _getMir,
+ }
+
+ _setters = {'rgbCol' : _setRGB,
+ 'specCol' : _setSpec,
+ 'mirCol' : _setMir,
+ }
+
+ t = _Material.Modes
+
+ Modes = {'traceable' : t.TRACEABLE,
+ 'shadow' : t.SHADOW,
+ 'shadeless' : t.SHADELESS,
+ 'wire' : t.WIRE,
+ 'vcolLight' : t.VCOL_LIGHT,
+ 'vcolPaint' : t.VCOL_PAINT,
+ 'zTransp' : t.ZTRANSP,
+ 'zInvert' : t.ZINVERT,
+ 'onlyShadow': t.ONLYSHADOW,
+ 'star' : t.STAR,
+ 'texFace' : t.TEXFACE,
+ 'noMist' : t.NOMIST,
+ }
+
+ t = _Material.HaloModes
+
+ HaloModes = { "rings" : t.RINGS,
+ "lines" : t.LINES,
+ "tex" : t.TEX,
+ "haloPuno": t.PUNO,
+ "shade" : t.SHADE,
+ "flare" : t.FLARE,
+ }
+
+
+ del t
+
+ def setMode(self, *args):
+ """Set the mode of 'self'. This function takes a variable number
+of string arguments of the types listed in self.Modes.
+
+ Example::
+
+ m = Material.New()
+ m.setMode('shadow', 'wire')
+"""
+ flags = 0
+ try:
+ for a in args:
+ flags |= self.Modes[a]
+ except:
+ raise TypeError, "mode must be one of" % self.Modes.keys()
+ self._object.mode = flags
+
+ def setHaloMode(self, *args):
+ """Sets the material to Halo mode.
+This function takes a variable number of string arguments of the types
+listed in self.HaloModes"""
+ flags = _Material.Modes.HALO
+
+ try:
+ for a in args:
+ flags |= self.HaloModes[a]
+ except:
+ raise TypeError, "mode must be one of" % self.HaloModes.keys()
+ self._object.mode = flags
+
+
+class ModeFlags:
+ """Readonly dictionary
+
+...containing Material mode bitvectors:
+
+|------------------------------------------|
+| Name | Description |
+|==========================================|
+| TRACEABLE | visible for shadow lamps |
+|------------------------------------------|
+| SHADOW | cast shadow |
+|------------------------------------------|
+| SHADELESS | do not shade |
+|------------------------------------------|
+| WIRE | draw in wireframe |
+|------------------------------------------|
+| VCOL_LIGHT | use vertex colors |
+| | with lighting |
+|------------------------------------------|
+| VCOL_PAINT | vertex colours |
+|------------------------------------------|
+| HALO | Halo material |
+|------------------------------------------|
+| ZTRANSP | Z transparency |
+|------------------------------------------|
+| ZINVERT | invert Z |
+|------------------------------------------|
+| ONLYSHADOW | only shadow, but |
+| | don't render |
+|------------------------------------------|
+| STAR | ? |
+|------------------------------------------|
+| TEXFACE | textured faces |
+|------------------------------------------|
+| NOMIST | disable mist |
+|------------------------------------------|
+
+These mode flags directly represent the buttons in the Material parameters
+window (EditButtons)
+
+Example::
+
+ # be 'm' a material
+ from Blender.Material.Modes import *
+ m.mode |= (TRACEABLE + WIRE) # Set 'wire' and 'traceable' flagsd
+ m.mode &= ~SHADELESS # clear 'shadeless' flag
+"""
+
+ t = _Material.Modes
+ TRACEABLE = t.TRACEABLE
+ SHADOW = t.SHADOW
+ SHADELESS = t.SHADELESS
+ WIRE = t.WIRE
+ VCOL_LIGHT = t.VCOL_LIGHT
+ VCOL_PAINT = t.VCOL_PAINT
+ HALO = t.HALO
+ ZTRANSP = t.ZTRANSP
+ ZINVERT = t.ZINVERT
+ ONLYSHADOW = t.ONLYSHADOW
+ STAR = t.STAR
+ TEXFACE = t.TEXFACE
+ NOMIST = t.NOMIST
+ del t
+
+# override:
+ModeFlags = _Material.Modes
+
+def get(name = None):
+ """If 'name' given, the Material 'name' is returned if existing, 'None' otherwise.
+If no name is given, a list of all Materials is returned"""
+ if name:
+ return Material(_Material.get(name))
+ else:
+ return shadow._List(_Material.get(), Material)
+
+Get = get # emulation
+
+def New(name = None):
+ """Creates a new, empty Material and returns it.
+
+Example::
+
+ from Blender import Material
+ mat = Material.New()
+"""
+ mat = Material(_Material.New())
+ if name:
+ mat.name = name
+ return mat
diff --git a/intern/python/modules/Blender/Mesh.py b/intern/python/modules/Blender/Mesh.py
new file mode 100644
index 00000000000..dd8103919f8
--- /dev/null
+++ b/intern/python/modules/Blender/Mesh.py
@@ -0,0 +1,250 @@
+"""The Blender Mesh module
+
+ This module provides routines for more extensive mesh manipulation.
+ Later, this Mesh type will also allow interactive access (like in
+ EditMode).
+ In the Publisher, Ngons will also be supported (and converted to
+ triangles on mesh.update(). The following code demonstrates
+ creation of an Ngon.
+
+ Example::
+
+ from Blender import Mesh, Object, Scene
+
+ m = Mesh.New() # new empty mesh
+ vlist = []
+ vlist.append(m.addVert((-0.0, -1.0, 0.0)))
+ vlist.append(m.addVert((1.0, 0.0, 0.0)))
+ vlist.append(m.addVert((1.0, 1.0, 0.0)))
+ vlist.append(m.addVert((0.0, 3.0, 0.0)))
+ vlist.append(m.addVert((-1.0, 2.0, 0.0)))
+ vlist.append(m.addVert((-3.0, 1.0, 0.0)))
+ vlist.append(m.addVert((-3.0, 3.0, 0.0)))
+ vlist.append(m.addVert((-4.0, 3.0, 0.0)))
+ vlist.append(m.addVert((-4.0, 0.0, 0.0)))
+
+ f = m.addFace(vlist)
+
+ # do some calculations: top project vertex coordinates to
+ # UV coordinates and normalize them to the square [0.0, 1.0]*[0.0, 1.0]
+
+ uvlist = map(lambda x: (x.co[0], x.co[1]), vlist)
+ maxx = max(map(lambda x: x[0], uvlist))
+ maxy = max(map(lambda x: x[1], uvlist))
+ minx = min(map(lambda x: x[0], uvlist))
+ miny = min(map(lambda x: x[1], uvlist))
+
+ len = max((maxx - minx), (maxy - miny))
+ offx = -minx / len
+ offy = -miny / len
+
+ f.uv = map(lambda x: (x[0]/len + offx, x[1]/len + offy), uvlist) # assign UV coordinates by 'top' projection
+
+ m.update() # update and triangulate mesh
+
+ ob = Object.New('Mesh') # create new Object
+ ob.link(m) # link mesh data
+ sc = Scene.getCurrent() # get current Scene
+ sc.link(ob) # link Object to scene
+"""
+
+from Blender.Types import NMFaceType
+import Blender.Material as Material
+
+from _Blender import NMesh as _NMesh
+
+FACEFLAGS = _NMesh.Const
+DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC
+
+import shadow
+
+def makeFace(f):
+ face = _NMesh.Face()
+ for v in f:
+ face.v.append(v)
+ face.uv.append((v.uvco[0], v.uvco[1]))
+ return face
+
+def toTriangles(ngon):
+ from utils import tesselation
+ # This should be a Publisher only feature...once the tesselation
+ # is improved. The GLU tesselator of Mesa < 4.0 is crappy...
+ if len(ngon.uv) == len(ngon.v):
+ i = 0
+ for v in ngon.v:
+ v.uvco = ngon.uv[i]
+ i += 1
+
+ return tesselation.NgonAsTriangles(ngon, makeFace) # return triangles
+
+def Color(r, g, b, a = 1.0):
+ return _NMesh.Col(255 * r, 255 * g, 255 * b, 255 * a)
+
+class Vert: #shadow NMVert class for the tesselator
+ """Vertex wrapper class
+This class emulates a float coordinate vector triple
+"""
+ def __init__(self):
+ self.vert = None
+ self.uv = []
+ def __len__(self):
+ return 3
+ def __setitem__(self, i, val):
+ self.vert[i] = val
+ def __getitem__(self, i):
+ return self.vert.co[i]
+
+class Face:
+ """Face wrapper class
+This class emulates a list of vertex references
+"""
+ def __init__(self, vlist):
+ self.v= vlist
+ self.uv = []
+
+ def __len__(self):
+ return len(self.v)
+
+ def __setitem__(self, i, val):
+ self.v[i] = val
+
+ def __getitem__(self, i):
+ return self.v[i]
+
+# override:
+
+Vert = _NMesh.Vert
+Face = _NMesh.Face
+
+class rawMesh:
+ """Wrapper for raw Mesh data"""
+ def __init__(self, object = None):
+ if object:
+ self._object = object
+ else:
+ self._object = _NMesh.GetRaw()
+
+ self.flags = DEFAULTFLAGS
+ self.smooth = 0
+ self.recalc_normals = 1
+ self.faces = self._object.faces[:]
+
+ def __getattr__(self, name):
+ if name == 'vertices':
+ return self._object.verts
+ elif name == 'has_col':
+ return self._object.hasVertexColours()
+ elif name == 'has_uv':
+ return self._object.hasFaceUV()
+ else:
+ return getattr(self._object, name)
+
+ def __repr__(self):
+ return "Mesh: %d faces, %d vertices" % (len(self.faces), len(self.verts))
+
+ def hasFaceUV(self, true = None):
+ """Sets the per-face UV texture flag, if 'true' specified (either
+ 0 or 1). Returns the texture flag in any case."""
+ if true == None:
+ return self._object.hasFaceUV()
+ return self._object.hasFaceUV(true)
+
+ def hasVertexUV(self, true = None):
+ """Sets the per-vertex UV texture flag, if 'true' specified (either
+ 0 or 1). Returns the texture flag in any case."""
+ if true == None:
+ return self._object.hasVertexUV()
+ return self._object.hasVertexUV(true)
+
+ def hasVertexColours(self, true = None):
+ """Sets the per-face UV texture flag, if 'true' specified (either
+ 0 or 1). Returns the texture flag in any case."""
+ if true == None:
+ return self._object.hasVertexColours()
+ return self._object.hasVertexColours(true)
+
+ def addVert(self, v):
+ """Adds a vertex to the mesh and returns a reference to it. 'v' can
+be a float triple or any data type emulating a sequence, containing the
+coordinates of the vertex. Note that the returned value references an
+*owned* vertex"""
+ vert = _NMesh.Vert(v[0], v[1], v[2])
+ self._object.verts.append(vert)
+ return vert
+
+ def addFace(self, vlist, flags = None, makedefaultUV = 0):
+ """Adds a face to the mesh and returns a reference to it. 'vlist'
+must be a list of vertex references returned by addVert().
+Note that the returned value references an *owned* face"""
+ if type(vlist) == NMFaceType:
+ face = vlist
+ else:
+ n = len(vlist)
+ face = _NMesh.Face(vlist)
+ if makedefaultUV:
+ face.uv = defaultUV[:n]
+
+ self.faces.append(face)
+ # turn on default flags:
+ if not flags:
+ face.mode = self.flags
+ else:
+ face.mode = flags
+ return face
+
+ def update(self):
+ """Updates the mesh datablock in Blender"""
+ o = self._object
+ o = self._object
+ o.faces = []
+ smooth = self.smooth
+ for f in self.faces:
+ if len(f) > 4: #it's a NGON
+ faces = toTriangles(f)
+ for nf in faces:
+ nf.smooth = smooth
+ o.faces.append(nf)
+ else:
+ o.faces.append(f)
+ o.update()
+
+ def link(self, material):
+ """Link material 'material' with the mesh. Note that a mesh can
+currently have up to 16 materials, which are referenced by
+Face().materialIndex"""
+ mats = self._object.materials
+ if material in mats:
+ print "material already assigned to mesh"
+ return
+ mats.append(material._object)
+
+ def unlink(self, material):
+ """Unlink (remove) material 'material' from the mesh. Note
+that the material indices per face need to be updated."""
+ self._object.materials.remove(material._object)
+
+ def setMaterials(self, materials = []):
+ """Sets materials. 'materials' must be a list of valid material objects
+Note that a mesh can currently have up to 16 materials, which are referenced
+by Face().materialIndex"""
+
+ self._object.materials = (map(lambda x: x._object, materials))
+
+ def getMaterials(self, materials = []):
+ """Returns materials assigned to the mesh"""
+ return shadow._List(self._object.materials, Material.Material)
+
+def New():
+ return rawMesh()
+
+def get(name = None):
+ """If 'name' given, the Mesh 'name' is returned if existing, 'None' otherwise."""
+ if name:
+ ob = _NMesh.GetRaw(name)
+ if ob:
+ return rawMesh(ob)
+ else:
+ return None
+ else:
+ raise SystemError, "get() for Meshes is not yet supported"
+
diff --git a/intern/python/modules/Blender/NMesh.py b/intern/python/modules/Blender/NMesh.py
new file mode 100644
index 00000000000..3e6c60bab21
--- /dev/null
+++ b/intern/python/modules/Blender/NMesh.py
@@ -0,0 +1,192 @@
+"""The Blender NMesh module
+
+ This module provides access to the raw **Mesh** data block.
+
+ Examples will not be given, as the life time of this module will be
+ most probably limited. Use the 'Mesh' module instead.
+"""
+
+import _Blender.NMesh as _NMesh
+import shadow
+
+class Mesh(shadow.shadow):
+ """The NMesh object
+
+ This contains a copy of the raw mesh object data.
+
+ Attributes
+
+ verts -- A list of vertices of type 'Vert'
+
+ faces -- List of faces of type 'Face'
+"""
+ def update(self):
+ """updates the mesh object in Blender with the modified mesh data"""
+ self._object.update()
+
+class Vert:
+ """Vertex object
+
+ Attributes
+
+ co -- The vertex coordinates (x, y, z)
+
+ no -- Vertex normal vector (nx, ny, nz)
+
+ uvco -- Vertex texture ("sticky") coordinates
+
+ index -- The vertex index, if owned by a mesh
+"""
+
+class Face:
+ """Face object
+
+ Attributes
+
+ mode -- Display mode, see NMesh.FaceModes
+
+ flag -- flag bit vector, specifying selection flags.
+ see NMesh.FaceFlags
+
+ transp -- transparency mode bit vector; see NMesh.FaceTranspModes
+
+ v -- List of Face vertices
+
+ col -- List of Vertex colours
+
+ materialIndex -- Material index (referring to one of the Materials in
+ the Meshes material list, see Mesh documentation
+
+ smooth -- Flag whether smooth normals should be calculated (1 = yes)
+
+ image -- Reference to texture image object
+
+ uv -- A list of per-face UV coordinates:
+ [(u0, v0), (u1, v1), (u2, v2), .. ]
+"""
+
+class Col:
+ """Colour object
+
+ See NMesh module documentation for an example.
+
+ Attributes
+
+ r, g, b, a -- The RGBA components of the colour
+ A component must lie in the range of [0, 255]
+"""
+
+
+class FaceModes:
+ """Face mode bit flags
+
+ BILLBOARD -- always orient after camera
+
+ DYNAMIC -- respond to collisions
+
+ INVISIBLE -- invisible face
+
+ HALO -- halo face, always point to camera
+
+ LIGHT -- dynamic lighting
+
+ OBCOL -- use object colour instead of vertex colours
+
+ SHADOW -- shadow type
+
+ SHAREDCOL -- shared vertex colors (per vertex)
+
+ TEX -- has texture image
+
+ TILES -- uses tiled image
+
+ TWOSIDE -- twosided face
+"""
+ t = _NMesh.Const
+ BILLBOARD = t.BILLBOARD
+ DYNAMIC = t.DYNAMIC
+ INVISIBLE = t.INVISIBLE
+ HALO = t.HALO
+ LIGHT = t.LIGHT
+ OBCOL = t.OBCOL
+ SHADOW = t.SHADOW
+ SHAREDCOL = t.SHAREDCOL
+ TEX = t.TEX
+ TILES = t.TILES
+ TWOSIDE = t.TWOSIDE
+ del t
+
+
+class FaceTranspModes:
+ """Readonly dictionary
+
+...containing Face transparency draw modes. They are of type 'enum', i.e.
+can not be combined like a bit vector.
+
+ SOLID -- draw solid
+
+ ADD -- add to background(halo)
+
+ ALPHA -- draw with transparency
+
+ SUB -- subtract from background
+"""
+ t = _NMesh.Const
+ SOLID = t.SOLID
+ ADD = t.ADD
+ ALPHA = t.ALPHA
+ SUB = t.SUB
+ del t
+
+class FaceFlags:
+ """Readonly dictionary
+
+...containing Face flags bitvectors:
+
+ SELECT -- selected
+
+ HIDE -- hidden
+
+ ACTIVE -- the active face
+"""
+ t = _NMesh.Const
+ SELECT = t.SELECT
+ HIDE = t.HIDE
+ ACTIVE = t.ACTIVE
+ del t
+
+
+def New(name = None):
+ """Creates a new NMesh mesh object and returns it"""
+ pass
+
+def GetRaw(name = None):
+ """If 'name' specified, the Mesh object with 'name' is returned, 'None'
+if not existant. Otherwise, a new empty Mesh is initialized and returned."""
+ pass
+
+def PutRaw(mesh, name = "Mesh"):
+ """Creates a Mesh Object instance in Blender, i.e. a Mesh Object in the
+current Scene and returns a reference to it. If 'name' specified, the Mesh
+'name' is overwritten. In this case, no Object reference is returned."""
+ pass
+
+def GetRawFromObject(name):
+ """This returns the mesh as used by the object, which
+means it contains all deformations and modifications."""
+ pass
+
+# override all these functions again, because we only used them for
+# documentation -- NMesh will be no longer supported in future
+
+New = _NMesh.New
+GetRaw = _NMesh.GetRaw
+PutRaw = _NMesh.PutRaw
+GetRawFromObject = _NMesh.GetRawFromObject
+Const = _NMesh.Const
+Vert = _NMesh.Vert
+Face = _NMesh.Face
+Col = _NMesh.Col
+
+def NMesh(data):
+ return data
diff --git a/intern/python/modules/Blender/Object.py b/intern/python/modules/Blender/Object.py
new file mode 100644
index 00000000000..7fefedf4725
--- /dev/null
+++ b/intern/python/modules/Blender/Object.py
@@ -0,0 +1,391 @@
+##
+## Blender API mid level layer 01/2002 // strubi@blender.nl
+##
+## $Id$
+##
+
+"""The Blender Object module
+
+ This module provides **Object** manipulation routines.
+
+ Example::
+
+ from Blender import Object
+ ob = Object.get('Plane')
+ actobj = Object.getSelected()[0] # get active Object
+ print actobj.loc # print position
+ ob.makeParent([actobj]) # make ob the parent of actobj
+"""
+
+import _Blender.Object as _Object
+
+import shadow
+reload(shadow) # XXX
+
+class _C:
+ pass
+
+InstanceType = type(_C())
+del _C # don't export this
+
+
+def _Empty_nodata(obj):
+ return None
+
+class Object(shadow.hasIPO):
+ """Blender Object
+
+ A Blender Object (note the capital O) is the instance of a 3D structure,
+ or rather, the Object that is (normally) visible in your Blender Scene.
+
+ An instance of a Blender Object object is created by::
+
+ from Blender import Object
+ ob = Object.New(type) # type must be a valid type string,
+ # see Object.Types
+
+ ...
+
+ Attributes
+
+ Note that it is in general not recommended to access the Object's
+ attributes directly. Please rather use the get-/set- functions instead.
+
+ loc -- position vector (LocX, LocY, LocZ)
+
+ dloc -- delta position vector (dLocX, dLocY, dLocZ)
+
+ rot -- euler rotation vector (RotX, RotY, RotZ).
+ Warning: this may change in future.
+
+ drot -- delta rotation euler vector (dRotX, dRotY, dRotZ)
+ Warning: this may change in future.
+
+ size -- scale vector (SizeX, SizeY, SizeZ)
+
+ dsize -- delta scale vector (dSizeX, dSizeY, dSizeZ)
+
+ layer -- layer bitvector (20 bit), defining what layers the object is
+ visible in
+
+
+ The following items are listed here only for compatibility to older
+ scripts and are READ-ONLY! **USE the get- functions instead!**
+
+ data -- reference to the data object (e.g. Mesh, Camera, Lamp, etc.)
+
+ parent -- reference to the parent object, if existing, 'None' otherwise.
+
+ track -- reference to the tracked object, if existing, 'None' otherwise.
+
+ This bit mask can be read and written:
+
+ colbits -- the Material usage mask. A set bit #n means:
+ The Material #n in the *Object's* material list is used.
+ Otherwise, the Material #n of the Objects *Data* material list
+ is displayed.
+"""
+
+ def __init__(self, object = None):
+ """Returns an empty shadow Object"""
+ self._object = object
+
+ def __repr__(self):
+ return "[Object \"%s\"]" % self.name
+
+ def link(self, data):
+ """Links Object 'self' with data 'data'. The data type must match
+the Object's type, so you cannot link a Lamp to a mesh type Object.
+'data' can also be an Ipo object (IpoBlock)
+"""
+ from _Blender import Types
+ # special case for NMesh:
+ if type(data) == Types.NMeshType:
+ return self._object.link(data)
+ elif type(data) == InstanceType:
+ if data.__class__.__name__ == "rawMesh":
+ data.update() # update mesh
+ elif data.__class__.__name__ == "IpoBlock":
+ self.setIpo(data)
+
+ return shadow._link(self, data)
+
+ def copy(self):
+ """Returns a copy of 'self'.
+This is a true, linked copy, i.e. the copy shares the same data as the
+original. The returned object is *free*, meaning, not linked to any scene."""
+ return Object(self._object.copy())
+
+ #def clone(self):
+ #"""Makes a clone of the specified object in the current scene and
+##returns its reference"""
+ #return Object(self._object.clone())
+
+ def shareFrom(self, object):
+ """Link data of 'self' with data of 'object'. This works only if
+'object' has the same type as 'self'."""
+ return Object(self._object.shareFrom(object._object))
+
+ def getMatrix(self):
+ """Returns the object matrix"""
+ return self._object.getMatrix()
+
+ def getInverseMatrix(self):
+ """Returns the object's inverse matrix"""
+ return self._object.getInverseMatrix()
+
+ def getData(self):
+ "Returns the Datablock object containing the object's data, e.g. Mesh"
+ t = self._object.getType()
+ data = self._object.data
+ try:
+ return self._dataWrappers[t][1](data)
+ except:
+ raise TypeError, "getData() not yet supported for this object type"
+
+ def getDeformData(self):
+ """Returns the Datablock object containing the object's deformed data.
+Currently, this is only supported for a Mesh"""
+ import _Blender.NMesh as _NMesh
+ t = self._object.getType()
+ if t == self.Types['Mesh']:
+ data = _NMesh.GetRawFromObject(self.name)
+ return self._dataWrappers[t][1](data)
+ else:
+ raise TypeError, "getDeformData() not yet supported for this object type"
+
+ def getType(self):
+ "Returns type string of Object, which is one of Object.Types.keys()"
+ t = self._object.getType()
+ try:
+ return self._dataWrappers[t][0]
+ except:
+ return "<unsupported>"
+
+ def getParent(self):
+ "Returns object's parent object"
+ if self._object.parent:
+ return Object(self._object.parent)
+ return None
+
+ def getTracked(self):
+ "Returns object's tracked object"
+ if self._object.track:
+ return Object(self._object.track)
+ return None
+
+# FUTURE FEATURE :-) :
+# def getLocation():
+# """Returns the object's location (x, y, z).
+#By default, the location vector is always relative to the object's parent.
+#If the location of another coordinate system is wanted, specify 'origin' by
+#the object whose coordinate system the location should be calculated in.
+
+#If world coordinates are wanted, set 'relative' = "World"."""
+
+ def getLocation(self, relative = None):
+ """Returns the object's location (x, y, z). For the moment,
+'relative' has no effect."""
+ l = self._object.loc
+ return (l[0], l[1], l[2])
+
+ def setLocation(self, location, relative = None):
+ """Sets the object's location. 'location' must be a vector triple.
+See 'getLocation()' about relative coordinate systems."""
+ l = self._object.loc # make sure this is copied
+ l[0], l[1], l[2] = location
+
+ def getDeltaLocation(self):
+ """Returns the object's delta location (x, y, z)"""
+ l = self._object.dloc
+ return (l[0], l[1], l[2])
+
+ def setDeltaLocation(self, delta_location):
+ """Sets the object's delta location which must be a vector triple"""
+ l = self._object.dloc # make sure this is copied
+ l[0], l[1], l[2] = delta_location
+
+ def getEuler(self):
+ """Returns the object's rotation as Euler rotation vector
+(rotX, rotY, rotZ)"""
+ e = self._object.rot
+ return (e[0], e[1], e[2])
+
+ def setEuler(self, euler = (0.0, 0.0, 0.0)):
+ """Sets the object's rotation according to the specified Euler angles.
+'euler' must be a vector triple"""
+ e = self._object.rot
+ e[0], e[1], e[2] = euler
+
+ def makeParent(self, objlist, mode = 0, fast = 0):
+ """Makes 'self' the parent of the objects in 'objlist' which must be
+a list of valid Objects.
+If specified:
+
+ mode -- 0: make parent with inverse
+
+ 1: without inverse
+
+ fast -- 0: update scene hierarchy automatically
+
+ 1: don't update scene hierarchy (faster). In this case, you
+ must explicitely update the Scene hierarchy, see:
+ 'Blender.Scene.getCurrent().update()'"""
+ list = map(lambda x: x._object, objlist)
+ return Object(self._object.makeParent(list, mode, fast))
+
+ def clrParent(self, mode = 0, fast = 0):
+ """Clears parent object.
+If specified:
+
+ mode -- 2: keep object transform
+
+ fast > 0 -- don't update scene hierarchy (faster)"""
+ return Object(self._object.clrParent(mode, fast))
+
+ def getMaterials(self):
+ """Returns list of materials assigned to the object"""
+ from Blender import Material
+ return shadow._List(self._object.getMaterials(), Material.Material)
+
+ def setMaterials(self, materials = []):
+ """Sets materials. 'materials' must be a list of valid material objects"""
+ o = self._object
+ old_mask = o.colbits
+ o.colbits = -1 # set material->object linking
+ o.setMaterials(map(lambda x: x._object, materials))
+ o.colbits = old_mask
+
+ def materialUsage(self, flag):
+ """Determines the way the material is used and returns status.
+
+'flag' = 'Data' : Materials assigned to the object's data are shown. (default)
+
+'flag' = 'Object' : Materials assigned to the object are shown.
+
+The second case is desired when the object's data wants to be shared among
+objects, but not the Materials assigned to their data. See also 'colbits'
+attribute for more (and no future compatible) control."""
+ if flag == "Object":
+ self._object.colbits = -1
+ elif flag == "Data":
+ self._object.colbits = 0
+ return self._object.colbits
+ else:
+ raise TypeError, "unknown mode %s" % flag
+
+ _getters = {}
+
+ from Blender import Mesh, Camera, Lamp
+
+ t = _Object.Types
+ Types = {"Camera" : t.CAMERA,
+ "Empty" : t.EMPTY,
+ "Lamp" : t.LAMP,
+ "Mesh" : t.MESH,
+ }
+
+ # create lookup table for data wrappers
+ _dataWrappers = range(max(Types.values()) + 1)
+ _dataWrappers[t.MESH] = ("Mesh", Mesh.rawMesh)
+ _dataWrappers[t.CAMERA] = ("Camera", Camera.Camera)
+ _dataWrappers[t.LAMP] = ("Lamp", Lamp.Lamp)
+ _dataWrappers[t.EMPTY] = ("Empty", _Empty_nodata)
+
+ t = _Object.DrawTypes
+ DrawTypes = {"Bounds" : t.BOUNDBOX,
+ "Wire" : t.WIRE,
+ "Solid" : t.SOLID,
+ "Shaded" : t.SHADED,
+ }
+
+ t = _Object.DrawModes
+ DrawModes = {"axis" : t.AXIS,
+ "boundbox" : t.BOUNDBOX,
+ "texspace" : t.TEXSPACE,
+ "name" : t.NAME,
+ }
+
+
+ del t
+ del Mesh, Camera, Lamp
+
+ def getDrawMode(self):
+ """Returns the Object draw modes as a list of strings"""
+ return shadow._getModeBits(self.DrawModes, self._object.drawMode)
+
+ def setDrawMode(self, *args):
+ """Sets the Object's drawing modes as a list of strings"""
+ self._object.drawMode = shadow._setModeBits(self.DrawModes, args)
+
+ def getDrawType(self):
+ """Returns the Object draw type"""
+ for k in self.DrawTypes.keys():
+ if self.DrawTypes[k] == self.drawType:
+ return k
+
+ def setDrawType(self, name):
+ """Sets the Object draw type. 'name' must be one of:
+
+* 'Bounds' : Draw bounding box only
+
+* 'Wire' : Draw in wireframe mode
+
+* 'Solid' : Draw solid
+
+* 'Shaded' : Draw solid, shaded and textures
+"""
+ try:
+ self._object.drawType = self.DrawTypes[name]
+ except:
+ raise TypeError, "type must be one of %s" % self.DrawTypes.keys()
+
+
+##################
+# MODULE FUNCTIONS
+
+def New(objtype, name = None):
+ """Creates a new, empty object and returns it.
+'objtype' is a string and must be one of::
+
+ Camera
+ Empty
+ Mesh
+ Lamp
+
+More object types will be supported in future.
+
+Example::
+
+ ob = Object.New('Camera')
+"""
+
+ if type(objtype) == type(0):
+ obj = Object(_Object.New(objtype)) # emulate old syntax
+ else:
+ t = Object.Types[objtype]
+ obj = Object(_Object.New(t))
+ return obj
+
+def get(name = None):
+ """If 'name' given, the Object 'name' is returned if existing, 'None' otherwise.
+If no name is given, a list of all Objects is returned"""
+ if name:
+ ob = _Object.get(name)
+ if ob:
+ return Object(ob)
+ else:
+ return None
+ else:
+ return shadow._List(_Object.get(), Object)
+
+Get = get # emulation
+
+def getSelected():
+ """Returns a list of selected Objects in the active layer(s).
+The active object is the first in the list, if visible"""
+ return shadow._List(_Object.getSelected(), Object)
+
+GetSelected = getSelected # emulation
+
+Types = _Object.Types # for compatibility
diff --git a/intern/python/modules/Blender/Scene.py b/intern/python/modules/Blender/Scene.py
new file mode 100644
index 00000000000..a6deaeb5a46
--- /dev/null
+++ b/intern/python/modules/Blender/Scene.py
@@ -0,0 +1,143 @@
+"""The Blender Scene module
+
+ This module provides *Scene* manipulation routines.
+
+ Example::
+
+ from Blender import Scene
+
+ curscene = Scene.getCurrent()
+ ob = curscene.getChildren()[0] # first object
+ newscene = Scene.New('testscene')
+ cam = curscene.getCurrentCamera() # get current camera object
+ newscene.link(ob) # link 'ob' to Scene
+ newscene.link(cam)
+ newscene.makeCurrent() # make current Scene
+"""
+import _Blender.Scene as _Scene
+
+from Object import Object
+import shadow
+
+class Scene(shadow.shadowEx):
+ """Wrapper for Scene DataBlock
+"""
+ def link(self, object):
+ """Links Object 'object' into Scene 'self'."""
+ # This is a strange workaround; Python does not release
+ # 'self' (and thus self._object) when an exception in the C API occurs.
+ # Therefore, we catch that exception and do it ourselves..
+ # Maybe Python 2.2 is able to resolve this reference dependency ?
+ try:
+ return self._object.link(object._object)
+ except:
+ del self._object
+ raise
+
+ def unlink(self, object):
+ """Unlinks (deletes) Object 'object' from Scene."""
+ ret = self._object.unlink(object._object)
+ return ret
+
+ def copy(self, duplicate_objects = 1):
+ """Returns a copy of itself.
+
+The optional argument defines, how the Scene's children objects are
+duplicated::
+
+ 0: Link Objects
+ 1: Link Object data
+ 2: Full Copy"""
+ return Scene(self._object.copy(duplicate_objects))
+
+ def update(self):
+ """Updates scene 'self'.
+ This function explicitely resorts the base list of a newly created object
+ hierarchy."""
+ return self._object.update()
+
+ def makeCurrent(self):
+ """Makes 'self' the current Scene"""
+ return self._object.makeCurrent()
+
+ def frameSettings(self, start = None, end = None, current = None):
+ """Sets or retrieves the Scene's frame settings.
+If the frame arguments are specified, they are set.
+A tuple (start, end, current) is returned in any case."""
+ if start and end and current:
+ return self._object.frameSettings(start, end, current)
+ else:
+ return self._object.frameSettings()
+
+ def currentFrame(self, frame = None):
+ """If 'frame' is given, the current frame is set and returned in any case"""
+ if frame:
+ return self._object.frameSettings(-1, -1, frame)
+ return self._object.frameSettings()[2]
+
+ def startFrame(self, frame = None):
+ """If 'frame' is given, the start frame is set and returned in any case"""
+ if frame:
+ return self._object.frameSettings(frame, -1, -1)
+ return self._object.frameSettings()[0]
+
+ def endFrame(self, frame = None):
+ """If 'frame' is given, the end frame is set and returned in any case"""
+ if frame:
+ return self._object.frameSettings(-1, frame, -1)
+ return self._object.frameSettings()[1]
+
+ def getChildren(self):
+ """Returns a list of the Scene's children Objects"""
+ return shadow._List(self._object.getChildren(), Object)
+
+ def getCurrentCamera(self):
+ """Returns current active camera Object"""
+ cam = self._object.getCurrentCamera()
+ if cam:
+ return Object(cam)
+
+ def setCurrentCamera(self, object):
+ """Sets the current active camera Object 'object'"""
+ return self._object.setCurrentCamera(object._object)
+
+ def getRenderdir(self):
+ """Returns directory where rendered images are saved to"""
+ return self._object.getRenderdir(self._object)
+
+ def getBackbufdir(self):
+ """Returns the Backbuffer images location"""
+ return self._object.getBackbufdir(self._object)
+
+# Module methods
+
+def New(name = 'Scene'):
+ """Creates and returns new Scene with (optionally given) name"""
+ return Scene(_Scene.New(name))
+
+def get(name = None):
+ """Returns a Scene object with name 'name' if given, None if not existing,
+or a list of all Scenes otherwise."""
+ if name:
+ ob = _Scene.get(name)
+ if ob:
+ return Scene(ob)
+ else:
+ return None
+ else:
+ return shadow._List(_Scene.get(), Scene)
+
+Get = get # emulation
+
+def getCurrent():
+ """Returns the currently active Scene"""
+ sc = Scene(_Scene.getCurrent())
+ return sc
+
+def unlink(scene):
+ """Removes the Scene 'scene' from Blender"""
+ if scene._object.name == _Scene.getCurrent().name:
+ raise SystemError, "current Scene can not be removed!"
+ for ob in scene.getChildren():
+ scene.unlink(ob)
+ return _Scene.unlink(scene._object)
diff --git a/intern/python/modules/Blender/Text.py b/intern/python/modules/Blender/Text.py
new file mode 100644
index 00000000000..0d5f615f190
--- /dev/null
+++ b/intern/python/modules/Blender/Text.py
@@ -0,0 +1,57 @@
+"""The Blender Text module
+
+ This module lets you manipulate the Text buffers inside Blender.
+ Text objects are currently owned by the Text editor in Blender.
+
+ Example::
+
+ from Blender import Text
+ text = Text.New('Text') # create new text buffer
+ text.write('hello') # write string
+ Text.unlink(text) # delete
+"""
+
+import _Blender.Text as _Text
+
+class Text:
+ """Wrapper for Text DataBlock"""
+
+ def clear(self):
+ """Clears the Text objects text buffer"""
+ pass
+
+ def write(self, string):
+ """Appends 'string' to the text buffer"""
+ pass
+
+ def asLines(self):
+ """Returns the text buffer as a list of lines (strings)"""
+ pass
+
+ def set(self, attr, val):
+ """Set the Text attribute of name 'name' to value 'val'.
+
+Currently supported::
+
+ follow_cursor : 1: Text output follows the cursor"""
+
+# Module methods
+
+def New(name = None):
+ """Creates new empty Text with (optionally given) name and returns it"""
+ pass
+
+def get(name = None):
+ """Returns a Text object with name 'name' if given, 'None' if not existing,
+or a list of all Text objects in Blender otherwise."""
+ pass
+
+def unlink(text):
+ """Removes the Text 'text' from the Blender text window"""
+ pass
+
+
+# override:
+New = _Text.New
+get = _Text.get
+unlink = _Text.unlink
diff --git a/intern/python/modules/Blender/Types.py b/intern/python/modules/Blender/Types.py
new file mode 100644
index 00000000000..d49d9c35407
--- /dev/null
+++ b/intern/python/modules/Blender/Types.py
@@ -0,0 +1 @@
+from _Blender.Types import *
diff --git a/intern/python/modules/Blender/Window.py b/intern/python/modules/Blender/Window.py
new file mode 100644
index 00000000000..e51ab894dfa
--- /dev/null
+++ b/intern/python/modules/Blender/Window.py
@@ -0,0 +1,65 @@
+"""The Blender Window module
+
+This module currently only supports redrawing commands of windows.
+Later on, it will allow screen manipulations and access to Window
+properties"""
+
+import _Blender.Window as _Window
+
+t = _Window.Types
+Const = t # emulation
+
+Types = { 'View' : t.VIEW3D,
+ 'Ipo' : t.IPO,
+ 'Oops' : t.OOPS,
+ 'Button' : t.BUTS,
+ 'File' : t.FILE,
+ 'Image' : t.IMAGE,
+ 'Text' : t.TEXT,
+ 'Action' : t.ACTION,
+ }
+
+del t
+
+def Redraw(t= 'View'):
+ """Redraws all windows of the type 't' which must be one of:
+
+* "View" - The 3D view
+
+* "Ipo" - The Ipo Window
+
+* "Oops" - The OOPS (scenegraph) window
+
+* "Button" - The Button Window
+
+* "File" - The File Window
+
+* "Image" - The Image Window (UV editor)
+
+* "Text" - The Text editor
+
+* "Action" - The Action Window"""
+
+ if type(t) == type(1):
+ return _Window.Redraw(t)
+ try:
+ _Window.Redraw(Types[t])
+ except:
+ raise TypeError, "type must be one of %s" % Types.keys()
+
+def RedrawAll():
+ """Redraws the whole screen"""
+ _Window.RedrawAll()
+
+def drawProgressBar(val, text):
+ """Draws a progress bar behind the Blender version information.
+'val' is a float value <= 1.0, 'text' contains info about what is currently
+being done.
+This function must be called with 'val' = 0.0 at start and end of the executed
+(and probably time consuming) action.
+The user may cancel the progress with the 'Esc' key, in this case, 0 is returned,
+1 else."""
+ return _Window.draw_progressbar(val, text)
+
+draw_progressbar = _Window.draw_progressbar # emulation
+QRedrawAll = _Window.QRedrawAll
diff --git a/intern/python/modules/Blender/World.py b/intern/python/modules/Blender/World.py
new file mode 100644
index 00000000000..e0c42d33f16
--- /dev/null
+++ b/intern/python/modules/Blender/World.py
@@ -0,0 +1,157 @@
+import _Blender.World as _World
+
+import shadow
+
+def _getAmbCol(obj):
+ return obj.ambR, obj.ambG, obj.ambB
+
+def _setAmbCol(obj, rgb):
+ obj.ambR, obj.ambG, obj.ambB = rgb
+
+def _getZenCol(obj):
+ return obj.zenR, obj.zenG, obj.zenB
+
+def _setZenCol(obj, rgb):
+ obj.zenR, obj.zenG, obj.zenB = rgb
+
+def _getHorCol(obj):
+ return obj.horR, obj.horG, obj.horB
+
+def _setHorCol(obj, rgb):
+ obj.horR, obj.horG, obj.horB = rgb
+
+def _setMist(obj, mist):
+ obj.mistStart = mist.start
+ obj.mistDepth = mist.depth
+ obj.mistHeight = mist.height
+ obj.mistType = mist.type
+
+def _getMist(obj):
+ mist = Mist()
+ mist.start = obj.mistStart
+ mist.depth = obj.mistDepth
+ mist.height = obj.mistHeight
+ mist.type = obj.mistType
+ return mist
+
+class World(shadow.hasIPO, shadow.hasModes):
+ """Wrapper for Blender World DataBlock
+
+ Attributes
+
+ horCol -- horizon colour triple '(r, g, b)' where r, g, b must lie
+ in the range of [0.0, 1.0]
+
+ zenCol -- zenith colour triple
+
+ ambCol -- ambient colour triple
+
+ exposure -- exposure value
+
+ mist -- mist structure, see class Mist
+
+ starDensity -- star density (the higher, the more stars)
+
+ starMinDist -- the minimum distance to the camera
+
+ starSize -- size of the stars
+
+ starColNoise -- star colour noise
+
+ gravity -- The gravity constant (9.81 for earth gravity)
+"""
+
+ SkyTypes = {'blend' : 1,
+ 'real' : 2,
+ 'paper' : 4,
+ }
+
+ Modes = {'mist' : 1,
+ 'stars' : 2,
+ }
+
+ _emulation = {'Expos' : "exposure",
+ 'HorR' : "horR",
+ 'HorG' : "horG",
+ 'HorB' : "horB",
+ 'ZenR' : "zenR",
+ 'ZenG' : "zenG",
+ 'ZenB' : "zenB",
+ 'StarDi' : "starDensity",
+ 'StarSi' : "starSize",
+ 'MisSta' : "mistStart",
+ 'MisDi' : "mistDepth",
+ 'MisHi' : "mistHeight",
+ }
+
+ _setters = {'horCol' : _getHorCol,
+ 'zenCol' : _getZenCol,
+ 'ambCol' : _getAmbCol,
+ 'mist' : _getMist,
+ }
+
+ _setters = {'horCol' : _setHorCol,
+ 'zenCol' : _setZenCol,
+ 'ambCol' : _setAmbCol,
+ 'mist' : _setMist,
+ }
+
+ def getSkyType(self):
+ """Returns a list of the set Sky properties, see setSkyType()"""
+ list = []
+ for k in self.SkyTypes.keys():
+ i = self.SkyTypes[k]
+ if self._object.skyType & i:
+ list.append(k)
+ return list
+
+ def setSkyType(self, *args):
+ """Set the sky type. This function takes a variable number
+of string arguments of ['blend', 'real', 'paper']"""
+ flags = 0
+ try:
+ for a in args:
+ flags |= self.SkyTypes[a]
+ except:
+ raise TypeError, "mode must be one of" % self.SkyTypes.keys()
+ self._object.skyType = flags
+
+
+class Mist:
+ """Mist structure
+
+ Attributes
+
+ start -- start of the mist
+
+ depth -- depth of the "mist wall"
+
+ height -- height of the mist layer
+"""
+
+ Types = { 'quadratic' : 0,
+ 'linear' : 1,
+ 'sqrt' : 2,
+ }
+
+ def __init__(self):
+ self.start = 0.0
+ self.depth = 0.0
+ self.height = 0.0
+ self.type = 0
+
+ def setType(self, name):
+ """Set the Mist type (one of ['quadratic', 'linear', 'sqrt'])"""
+ try:
+ t = self.Types[name]
+ else:
+ raise TypeError, "type must be one of %s" % self.Types.keys()
+ self.type = t
+
+ def getType(self):
+ """Returns the Mist type as string. See setType()"""
+ for k in self.Types.keys():
+ if self.Types[k] == self.type:
+ return k
+
+
diff --git a/intern/python/modules/Blender/__init__.py b/intern/python/modules/Blender/__init__.py
new file mode 100644
index 00000000000..7356d9ddf9f
--- /dev/null
+++ b/intern/python/modules/Blender/__init__.py
@@ -0,0 +1,23 @@
+#
+# The Blender main module wrapper
+# (c) 06/2001, NaN // strubi@blender.nl
+
+__all__ = ["Object", "Image", "NMesh", "Window", "Mesh", "Tools", "sys",
+ "Lamp", "Scene", "Draw", "Camera", "Material", "Types", "Ipo",
+ "BGL"]
+
+import _Blender
+
+Get = _Blender.Get
+Redraw = _Blender.Redraw
+link = _Blender.link
+bylink = _Blender.bylink
+
+import Object, Image, Mesh, Window, Tools, sys, Lamp, Scene, Draw, Camera
+import Material, NMesh, BGL, Types, Ipo, Text
+
+deg = lambda x: 0.0174532925199 * x # conversion from degrees to radians
+
+import __builtin__
+__builtin__.deg = deg
+
diff --git a/intern/python/modules/Blender/shadow.py b/intern/python/modules/Blender/shadow.py
new file mode 100644
index 00000000000..15c5de88f66
--- /dev/null
+++ b/intern/python/modules/Blender/shadow.py
@@ -0,0 +1,195 @@
+#
+# Blender mid level modules
+# author: strubi@blender.nl
+#
+#
+
+"""Shadow class module
+
+ These classes shadow the internal Blender objects
+
+ There is no need for you to use the shadow module really - it is
+ just there for documentation. Blender object classes with a common
+ subset of function members derive from these sub classes.
+"""
+
+
+def _List(list, Wrapper):
+ """This function returns list of wrappers, taking a list of raw objects
+and the wrapper method"""
+ return map(Wrapper, list)
+
+def _getModeBits(dict, attr):
+ list = []
+ for k in dict.keys():
+ i = dict[k]
+ if attr & i:
+ list.append(k)
+ return list
+
+def _setModeBits(dict, args):
+ flags = 0
+ try:
+ for a in args:
+ flags |= dict[a]
+ except:
+ raise TypeError, "mode must be one of %s" % dict.keys()
+ return flags
+
+
+def _link(self, data):
+ """Links Object 'self' with data 'data'. The data type must match
+the Object's type, so you cannot link a Lamp to a mesh type Object"""
+ try:
+ self._object.link(data._object)
+ except:
+ print "Users:", self._object.users
+
+class shadow:
+ """This is the shadow base class"""
+ _getters = {}
+ _setters = {}
+ _emulation = {}
+
+ def __init__(self, object):
+ self._object = object
+
+ def __getattr__(self, a):
+ try:
+ return getattr(self._object, a)
+ except:
+ if self._emulation.has_key(a):
+ return getattr(self._object, self._emulation[a])
+ elif self._getters.has_key(a):
+ return self._getters[a](self)
+ else:
+ raise AttributeError, a
+
+ def __setattr__(self, a, val):
+ if a == "_object":
+ self.__dict__['_object'] = val
+ return
+
+ try:
+ setattr(self.__dict__['_object'], a, val)
+ except:
+ if self._emulation.has_key(a):
+ setattr(self.__dict__['_object'], self._emulation[a], val)
+ elif self._setters.has_key(a):
+ self._setters[a](self, val)
+ else:
+ raise AttributeError, a
+ link = _link
+
+ def rename(self, name):
+ """Tries to set the name of the object to 'name'. If the name already
+exists, a unique name is created by appending a version number (e.g. '.001')
+to 'name'. The effective name is returned."""
+ self._object.name = name
+ return self._object.name
+
+def _getattrEx(self, a):
+ if self._emulation.has_key(a):
+ return getattr(self._object, self._emulation[a])
+ elif self._getters.has_key(a):
+ return self._getters[a](self)
+ else:
+ return getattr(self._object, a)
+
+class shadowEx:
+ """This is the shadow base class with a minor change; check for
+emulation attributes happens before access to the raw object's attributes"""
+ _getters = {}
+ _setters = {}
+ _emulation = {}
+
+ def __del__(self):
+ self.__dict__.clear()
+
+ def __init__(self, object):
+ self._object = object
+
+ def __getattr__(self, a):
+ return _getattrEx(self, a)
+
+ def __setattr__(self, a, val):
+ if a == "_object":
+ self.__dict__['_object'] = val
+ return
+
+ if self._emulation.has_key(a):
+ setattr(self.__dict__['_object'], self._emulation[a], val)
+ elif self._setters.has_key(a):
+ self._setters[a](self, val)
+ else:
+ setattr(self.__dict__['_object'], a, val)
+
+ def __repr__(self):
+ return repr(self._object)
+
+ def rename(self, name):
+ """Tries to set the name of the object to 'name'. If the name already
+exists, a unique name is created by appending a version number (e.g. '.001')
+to 'name'. The effective name is returned."""
+ self._object.name = name
+ return self._object.name
+
+ link = _link
+
+class hasIPO(shadowEx):
+ """Object class which has Ipo curves assigned"""
+
+ def getIpo(self):
+ "Returns the Ipo assigned to 'self'"
+ import Ipo
+ return Ipo.IpoBlock(self._object.ipo)
+
+ def setIpo(self, ipo):
+ "Assigns the IpoBlock 'ipo' to 'self'"
+ return self._object.assignIpo(ipo._object)
+
+ def __getattr__(self, a):
+ if a == "ipo":
+ print "ipo member access deprecated, use self.getIpo() instead!"
+ return self.getIpo()
+ else:
+ return _getattrEx(self, a)
+
+class hasModes(shadowEx):
+ """Object class which has different Modes"""
+ def getMode(self):
+ """Returns a list of the modes which are set for 'self'"""
+ list = []
+ for k in self.Modes.keys():
+ i = self.Modes[k]
+ if self._object.mode & i:
+ list.append(k)
+ return list
+
+ def setMode(self, *args):
+ """Set the mode of 'self'. This function takes a variable number
+of string arguments of the types listed in self.Modes"""
+ flags = 0
+ try:
+ for a in args:
+ flags |= self.Modes[a]
+ except:
+ raise TypeError, "mode must be one of" % self.Modes.keys()
+ self._object.mode = flags
+
+class dict:
+ """readonly dictionary shadow"""
+ _emulation = {}
+
+ def __init__(self, dict):
+ self._dict = dict
+
+ def __getitem__(self, key):
+ try:
+ return self._dict[key]
+ except:
+ key = _emulation[key]
+ return self._dict[key]
+
+ def __repr__(self):
+ return repr(self._dict)
diff --git a/intern/python/modules/Blender/sys.py b/intern/python/modules/Blender/sys.py
new file mode 100644
index 00000000000..f76c0074c1f
--- /dev/null
+++ b/intern/python/modules/Blender/sys.py
@@ -0,0 +1,20 @@
+from _Blender.sys import *
+
+sep = dirsep # path separator ('/' or '\')
+
+class Path:
+ def dirname(self, name):
+ return dirname(name)
+ def join(self, a, *p):
+ path = a
+ for b in p:
+ if b[:1] == dirsep:
+ path = b
+ elif path == '' or path[-1:] == dirsep:
+ path = path + b
+ else:
+ path = path + dirsep + b
+ return path
+
+path = Path()
+
diff --git a/intern/python/modules/Converter/__init__.py b/intern/python/modules/Converter/__init__.py
new file mode 100644
index 00000000000..81db84a66f6
--- /dev/null
+++ b/intern/python/modules/Converter/__init__.py
@@ -0,0 +1,4 @@
+__all__ = ["importer", "importloader"]
+
+import importloader
+
diff --git a/intern/python/modules/Converter/bimporter.py b/intern/python/modules/Converter/bimporter.py
new file mode 100644
index 00000000000..d788d4bccce
--- /dev/null
+++ b/intern/python/modules/Converter/bimporter.py
@@ -0,0 +1,34 @@
+class importer:
+ def __init__(self,writer=None):
+ self.writer = writer
+ self.filename = None
+ self.file = None
+ self.ext = ""
+ def readfile(self, name):
+ file = open(name, "r")
+ if not file:
+ return 0
+ self.file = file
+ self.filename = name
+ self.lines = file.readlines()
+ def close(self):
+ if self.filename:
+ self.file.close()
+ def checkmagic(self, name):
+ # return 1 if magic true (format verified), 0 else
+ return 0
+ def parse(self, data):
+ # parse and convert the data shere
+ pass
+
+class writer:
+ def __init__(self, args = None):
+ pass
+ def mesh(self, me, name):
+ pass
+
+_inst = importer()
+readfile = _inst.readfile
+close = _inst.close
+checkmagic = _inst.checkmagic
+parse = _inst.parse
diff --git a/intern/python/modules/Converter/importer/VRMLimporter.py b/intern/python/modules/Converter/importer/VRMLimporter.py
new file mode 100644
index 00000000000..e2bcea6a51e
--- /dev/null
+++ b/intern/python/modules/Converter/importer/VRMLimporter.py
@@ -0,0 +1,988 @@
+# VRML import prototype
+#
+# strubi@blender.nl
+#
+
+"""VRML import module
+
+ This is a prototype for VRML97 file import
+
+ Supported:
+
+ - Object hierarchies, transform collapsing (optional)
+
+ - Meshes (IndexedFaceSet, no Basic primitives yet)
+
+ - Materials
+
+ - Textures (jpg, tga), conversion option from alien formats
+
+"""
+
+import Blender.sys as os # Blender os emulation
+from beta import Scenegraph
+
+Transform = Scenegraph.Transform
+
+import beta.Objects
+
+_b = beta.Objects
+
+#from Blender import Mesh
+Color = _b.Color
+DEFAULTFLAGS = _b.DEFAULTFLAGS
+FACEFLAGS = _b.FACEFLAGS
+shadowNMesh = _b.shadowNMesh
+
+quat = Scenegraph.quat # quaternion math
+vect = quat.vect # vector math module
+from vrml import loader
+
+#### GLOBALS
+
+OB = Scenegraph.Object.Types # CONST values
+LA = Scenegraph.Lamp.Types
+
+g_level = 1
+g_supported_fileformats = ["jpg", "jpeg", "tga"]
+
+#### OPTIONS
+
+OPTIONS = {'cylres' : 16, # resolution of cylinder
+ 'flipnormals' : 0, # flip normals (force)
+ 'mat_as_vcol' : 0, # material as vertex color - warning, this increases mem usage drastically on big files
+ 'notextures' : 0, # no textures - saves some memory
+ 'collapseDEFs' : 0, # collapse DEF nodes
+ 'collapseTF' : 0, # collapse Transforms (as far as possible,
+ # i.e. currently to Object transform level)
+ }
+
+#### CONSTANTS
+
+LAYER_EMPTY = (1 << 2)
+LAYER_LAMP = (1 << 4)
+LAYER_CAMERA = 1 + (1 << 4)
+
+CREASE_ANGLE_THRESHOLD = 0.45 # radians
+
+PARSE_TIME = (loader.parser.IMPORT_PARSE_TIME )
+PROCESS_TIME = (1.0 - PARSE_TIME )
+PROGRESS_DEPTH = loader.parser.PROGRESS_DEPTH
+VERBOSE_DEPTH = PROGRESS_DEPTH
+
+#### DEBUG
+
+def warn(text):
+ print "###", text
+
+def debug2(text):
+ print (g_level - 1) * 4 * " " + text
+
+def verbose(text):
+ print text
+
+def quiet(text):
+ pass
+
+debug = quiet
+
+#### ERROR message filtering:
+
+g_error = {} # dictionary for non-fatal errors to mark whether an error
+ # was already reported
+
+def clrError():
+ global g_error
+ g_error['toomanyfaces'] = 0
+
+def isError(name):
+ return g_error[name]
+
+def setError(name):
+ global g_error
+ g_error[name] = 1
+
+#### ERROR handling
+
+class baseError:
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return `self.value`
+
+class MeshError(baseError):
+ pass
+
+UnfinishedError = loader.parser.UnfinishedError
+
+##########################################################
+# HELPER ROUTINES
+
+def assignImage(f, img):
+ f.image = img
+
+def assignUV(f, uv):
+ if len(uv) != len(f.v):
+ uv = uv[:len(f.v)]
+ #raise MeshError, "Number of UV coordinates does not match number of vertices in face"
+ f.uv = []
+ for u in uv:
+ f.uv.append((u[0], u[1])) # make sure it's a tuple
+
+
+#### VRML STUFF
+
+# this is used for transform collapsing
+class TransformStack:
+ def __init__(self):
+ self.stack = [Transform()]
+ def push(self, t):
+ self.stack.append(t)
+ def pop(self):
+ return self.stack.pop()
+ def last(self):
+ return self.stack[-1]
+
+def fromVRMLTransform(tfnode):
+ t = Transform()
+ s = tfnode.scale
+ t.scale = (s[0], s[1], s[2])
+ r = tfnode.rotation
+ if r[0] == 0.0 and r[1] == 0.0 and r[2] == 0.0:
+ rotaxis = (0.0, 0.0, 1.0)
+ ang = 0.0
+ else:
+ rotaxis = vect.norm3(r[:3])
+ ang = r[3]
+
+ #t.rotation = (rotaxis, ang)
+ t.calcRotfromAxis((rotaxis, ang))
+ tr = tfnode.translation
+ t.translation = (tr[0], tr[1], tr[2])
+ # XXX more to come..
+ return t
+
+
+### TODO: enable material later on
+#class dummyMaterial:
+ #def setMode(self, *args):
+ #pass
+
+def fromVRMLMaterial(mat):
+ name = mat.DEF
+ from Blender import Material
+ m = Material.New(name)
+
+ m.rgbCol = mat.diffuseColor
+ m.alpha = 1.0 - mat.transparency
+ m.emit = vect.len3(mat.emissiveColor)
+ if m.Emit > 0.01:
+ if vect.cross(mat.diffuseColor, mat.emissiveColor) > 0.01 * m.Emit:
+ m.rgbCol = mat.emissiveColor
+
+ m.ref = 1.0
+ m.spec = mat.shininess
+ m.specCol = mat.specularColor
+ m.amb = mat.ambientIntensity
+ return m
+
+# override:
+#def fromVRMLMaterial(mat):
+# return dummyMaterial()
+
+def buildVRMLTextureMatrix(tr):
+ from math import sin, cos
+ newMat = vect.Matrix
+ newVec = vect.Vector
+ # rotmatrix
+ s = tr.scale
+ t = tr.translation
+ c = tr.center
+
+ phi = tr.rotation
+
+ SR = newMat()
+ C = newMat()
+ C[2] = newVec(c[0], c[1], 1.0)
+
+ if abs(phi) > 0.00001:
+ SR[0] = newVec(s[0] * cos(phi), s[1] * sin(phi), 0.0)
+ SR[1] = newVec(-s[0] * sin(phi), s[1] * cos(phi), 0.0)
+ else:
+ SR[0] = newVec(s[0], 0.0, 0.0)
+ SR[1] = newVec(0.0, s[1], 0.0)
+
+ SR = C * SR * C.inverse() # rotate & scale about rotation center
+
+ T = newMat()
+ T[2] = newVec(t[0], t[1], 1.0)
+ return SR * T # texture transform matrix
+
+def imageConvert(fromfile, tofile):
+ """This should convert from a image file to another file, type is determined
+automatically (on extension). It's currently just a stub - users can override
+this function to implement their own converters"""
+ return 0 # we just fail in general
+
+def addImage(path, filename):
+ "returns a possibly existing image which is imported by Blender"
+ from Blender import Image
+ img = None
+ try:
+ r = filename.rindex('.')
+ except:
+ return None
+
+ naked = filename[:r]
+ ext = filename[r+1:].lower()
+
+ if path:
+ name = os.sep.join([path, filename])
+ file = os.sep.join([path, naked])
+ else:
+ name = filename
+ file = naked
+
+ if not ext in g_supported_fileformats:
+ tgafile = file + '.tga'
+ jpgfile = file + '.jpg'
+ for f in tgafile, jpgfile: # look for jpg, tga
+ try:
+ img = Image.Load(f)
+ if img:
+ verbose("couldn't load %s (unsupported).\nFound %s instead" % (name, f))
+ return img
+ except IOError, msg:
+ pass
+ try:
+ imgfile = open(name, "rb")
+ imgfile.close()
+ except IOError, msg:
+ warn("Image %s not found" % name)
+ return None
+
+ verbose("Format unsupported, trying to convert to %s" % tgafile)
+ if not imageConvert(name, tgafile):
+ warn("image conversion failed")
+ return None
+ else:
+ return Image.Load(tgafile)
+ return None # failed
+ try:
+ img = Image.Load(name)
+ except IOError, msg:
+ warn("Image %s not found" % name)
+ return img
+ # ok, is supported
+
+def callMethod(_class, method, vnode, newnode, warn = 1):
+ meth = None
+ try:
+ meth = getattr(_class, method)
+ except AttributeError:
+ if warn:
+ unknownType(method)
+ return None, None
+ if meth:
+ return meth(vnode, parent = newnode)
+
+def unknownType(type):
+ warn("unsupported:" + repr(type))
+
+def getChildren(vnode):
+ try:
+ children = vnode.children
+ except:
+ children = None
+ return children
+
+def getNodeType(vnode):
+ return vnode.__gi__
+
+GroupingNodeTypes = ["Group", "Collision", "Anchor", "Billboard", "Inline",
+ "LOD", "Switch", "Transform"]
+
+################################################################################
+#
+#### PROCESSING CLASSES
+
+
+class NullProcessor:
+ def __init__(self, tstack = TransformStack()):
+ self.stack = tstack
+ self.walker = None
+ self.mesh = None
+ self.ObjectNode = Scenegraph.NodefromData # may be altered...
+ self.MaterialCache = {}
+ self.ImageCache = {}
+
+# This is currently not used XXX
+class DEFcollapser(NullProcessor):
+ """This is for collapsing DEF Transform nodes into a single object"""
+ def __init__(self):
+ self.collapsedNodes = []
+
+ def Transform(self, curnode, parent, **kw):
+ name = curnode.DEF
+ if not name: # node is a DEF node
+ return None, None
+
+ return children, None
+
+
+class Processor(NullProcessor):
+ """The processor class defines the handler for a VRML Scenegraph node.
+Definition of a handler method simply happens by use of the VRML Scenegraph
+entity name.
+
+A handler usually creates a new Scenegraph node in the target scenegraph,
+converting the data from the given VRML node.
+
+A handler takes the arguments:
+
+ curnode: the currently visited VRML node
+ parent: the previously generated target scenegraph parent node
+ **kw: additional keywords
+
+It MUST return: (children, newBnode) where:
+ children: the children of the current VRML node. These will be further
+ processed by the processor. If this is not wanted (because they
+ might have been processed by the handler), None must be returned.
+ newBnode: the newly created target node or None.
+ """
+
+ def _handleProto(self, curnode, parent, **kw):
+ p = curnode.PROTO
+ if not p.sceneGraph:
+ print curnode.__gi__, "unsupported"
+ return None, None
+
+ def _dummy(self, curnode, parent, **kw):
+ print curnode.sceneGraph
+ return None, None
+
+ #def __getattr__(self, name):
+ #"""If method is not statically defined, look up prototypes"""
+ #return self._handleProto
+
+ def _currentTransform(self):
+ return self.stack.last()
+
+ def _parent(self, curnode, parent, trans):
+ name = curnode.DEF
+ children = getChildren(curnode)
+ debug("children: %s" % children)
+ objects = []
+ transforms = []
+ groups = []
+ isempty = 0
+ for c in children:
+ type = getNodeType(c)
+ if type == 'Transform':
+ transforms.append(c)
+ elif type in GroupingNodeTypes:
+ groups.append(c)
+ #else:
+ elif hasattr(self, type):
+ objects.append(c)
+ if transforms or groups or len(objects) != 1:
+ # it's an empty
+ if not name:
+ name = 'EMPTY'
+ Bnode = self.ObjectNode(None, OB.EMPTY, name) # empty Blender Object node
+ if options['layers']:
+ Bnode.object.Layer = LAYER_EMPTY
+ Bnode.transform = trans
+ Bnode.update()
+ isempty = 1
+ parent.insert(Bnode)
+ else: # don't insert extra empty if only one object has children
+ Bnode = parent
+
+ for node in objects:
+ c, new = self.walker.walk(node, Bnode)
+ if not isempty: # only apply transform if no extra transform empty in hierarchy
+ new.transform = trans
+ Bnode.insert(new)
+ for node in transforms:
+ self.walker.walk(node, Bnode)
+ for node in groups:
+ self.walker.walk(node, Bnode)
+
+ return None, None
+
+ def sceneGraph(self, curnode, parent, **kw):
+ parent.type = 'ROOT'
+ return curnode.children, None
+
+ def Transform(self, curnode, parent, **kw):
+ # we support 'center' and 'scaleOrientation' by inserting
+ # another Empty in between the Transforms
+
+ t = fromVRMLTransform(curnode)
+ cur = self._currentTransform()
+
+ chainable = 0
+
+ if OPTIONS['collapseTF']:
+ try:
+ cur = cur * t # chain transforms
+ except:
+ cur = self._currentTransform()
+ chainable = 1
+
+ self.stack.push(cur)
+
+ # here comes the tricky hacky transformation conversion
+
+ # TODO: SR not supported yet
+
+ if chainable == 1: # collapse, but not chainable
+ # insert extra transform:
+ Bnode = self.ObjectNode(None, OB.EMPTY, 'Transform') # Empty
+ Bnode.transform = cur
+ parent.insert(Bnode)
+ parent = Bnode
+
+ c = curnode.center
+ if c != [0.0, 0.0, 0.0]:
+ chainable = 1
+ trans = Transform()
+ trans.translation = (-c[0], -c[1], -c[2])
+ tr = t.translation
+ t.translation = (tr[0] + c[0], tr[1] + c[1], tr[2] + c[2])
+
+ Bnode = self.ObjectNode(None, OB.EMPTY, 'C') # Empty
+ Bnode.transform = t
+ parent.insert(Bnode)
+ parent = Bnode
+ else:
+ trans = t
+
+ if chainable == 2: # collapse and is chainable
+ # don't parent, insert into root node:
+ for c in getChildren(curnode):
+ dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent
+ if node: # a valid Blender node
+ node.transform = cur
+ else:
+ self._parent(curnode, parent, trans)
+
+
+ self.stack.pop()
+ return None, None
+
+ def Switch(self, curnode, parent, **kw):
+ return None, None
+
+ def Group(self, curnode, parent, **kw):
+ if OPTIONS['collapseTF']:
+ cur = self._currentTransform()
+ # don't parent, insert into root node:
+ children = getChildren(curnode)
+ for c in children:
+ dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent
+ if node: # a valid Blender node
+ node.transform = cur
+ else:
+ t = Transform()
+ self._parent(curnode, parent, t)
+ return None, None
+
+ def Collision(self, curnode, parent, **kw):
+ return self.Group(curnode, parent)
+
+# def LOD(self, curnode, parent, **kw):
+# c, node = self.walker.walk(curnode.level[0], parent)
+# parent.insert(node)
+# return None, None
+
+ def Appearance(self, curnode, parent, **kw):
+ # material colors:
+ mat = curnode.material
+ self.curColor = mat.diffuseColor
+
+ name = mat.DEF
+ if name:
+ if self.MaterialCache.has_key(name):
+ self.curmaterial = self.MaterialCache[name]
+ else:
+ m = fromVRMLMaterial(mat)
+ self.MaterialCache[name] = m
+ self.curmaterial = m
+ else:
+ if curnode.DEF:
+ name = curnode.DEF
+ if self.MaterialCache.has_key(name):
+ self.curmaterial = self.MaterialCache[name]
+ else:
+ m = fromVRMLMaterial(mat)
+ self.MaterialCache[name] = m
+ self.curmaterial = m
+ else:
+ self.curmaterial = fromVRMLMaterial(mat)
+
+ try:
+ name = curnode.texture.url[0]
+ except:
+ name = None
+ if name:
+ if self.ImageCache.has_key(name):
+ self.curImage = self.ImageCache[name]
+ else:
+ self.ImageCache[name] = self.curImage = addImage(self.curpath, name)
+ else:
+ self.curImage = None
+
+ tr = curnode.textureTransform
+ if tr:
+ self.curtexmatrix = buildVRMLTextureMatrix(tr)
+ else:
+ self.curtexmatrix = None
+ return None, None
+
+ def Shape(self, curnode, parent, **kw):
+ name = curnode.DEF
+ debug(name)
+ #self.mesh = Mesh.rawMesh()
+ self.mesh = shadowNMesh()
+ self.mesh.name = name
+
+ # don't mess with the order of these..
+ if curnode.appearance:
+ self.walker.preprocess(curnode.appearance, self.walker.preprocessor)
+ else:
+ # no appearance, get colors from shape (vertex colors)
+ self.curColor = None
+ self.curImage = None
+ self.walker.preprocess(curnode.geometry, self.walker.preprocessor)
+
+ if hasattr(self, 'curmaterial'):
+ self.mesh.assignMaterial(self.curmaterial)
+
+ meshobj = self.mesh.write() # write mesh
+ del self.mesh
+ bnode = Scenegraph.ObjectNode(meshobj, OB.MESH, name)
+ if name:
+ curnode.setTargetnode(bnode) # mark as already processed
+ return None, bnode
+
+ def Box(self, curnode, parent, **kw):
+ col = apply(Color, self.curColor)
+
+ faces = []
+ x, y, z = curnode.size
+ x *= 0.5; y *= 0.5; z *= 0.5
+ name = curnode.DEF
+ m = self.mesh
+ v0 = m.addVert((-x, -y, -z))
+ v1 = m.addVert(( x, -y, -z))
+ v2 = m.addVert(( x, y, -z))
+ v3 = m.addVert((-x, y, -z))
+ v4 = m.addVert((-x, -y, z))
+ v5 = m.addVert(( x, -y, z))
+ v6 = m.addVert(( x, y, z))
+ v7 = m.addVert((-x, y, z))
+
+ flags = DEFAULTFLAGS
+ if not self.curImage:
+ uvflag = 1
+ else:
+ uvflag = 0
+
+ m.addFace([v3, v2, v1, v0], flags, uvflag)
+ m.addFace([v0, v1, v5, v4], flags, uvflag)
+ m.addFace([v1, v2, v6, v5], flags, uvflag)
+ m.addFace([v2, v3, v7, v6], flags, uvflag)
+ m.addFace([v3, v0, v4, v7], flags, uvflag)
+ m.addFace([v4, v5, v6, v7], flags, uvflag)
+
+ for f in m.faces:
+ f.col = [col, col, col, col]
+ return None, None
+
+ def Viewpoint(self, curnode, parent, **kw):
+ t = Transform()
+ r = curnode.orientation
+ name = 'View_' + curnode.description
+ t.calcRotfromAxis((r[:3], r[3]))
+ t.translation = curnode.position
+ Bnode = self.ObjectNode(None, OB.CAMERA, name) # Empty
+ Bnode.object.Layer = LAYER_CAMERA
+ Bnode.transform = t
+ return None, Bnode
+
+ def DirectionalLight(self, curnode, parent, **kw):
+ loc = (0.0, 10.0, 0.0)
+ l = self._lamp(curnode, loc)
+ l.object.data.type = LA.SUN
+ return None, l
+
+ def PointLight(self, curnode, parent, **kw):
+ l = self._lamp(curnode, curnode.location)
+ l.object.data.type = LA.LOCAL
+ return None, l
+
+ def _lamp(self, curnode, location):
+ t = Transform()
+ name = curnode.DEF
+ energy = curnode.intensity
+ t.translation = location
+ Bnode = self.ObjectNode(None, OB.LAMP, "Lamp")
+ Bnode.object.data.energy = energy * 5.0
+ if options['layers']:
+ Bnode.object.Layer = LAYER_LAMP
+ Bnode.transform = t
+ return Bnode
+
+ def IndexedFaceSet(self, curnode, **kw):
+ matxvec = vect.matxvec
+ mesh = self.mesh
+ debug("IFS, read mesh")
+
+ texcoo = curnode.texCoord
+ uvflag = 0
+
+ if curnode.color:
+ colors = curnode.color.color
+ if curnode.colorIndex: # we have color indices
+ colindex = curnode.colorIndex
+ else:
+ colindex = curnode.coordIndex
+ if not texcoo:
+ uvflag = 1
+ else:
+ colors = None
+
+ faceflags = DEFAULTFLAGS
+
+ if not texcoo and OPTIONS['mat_as_vcol'] and self.curColor:
+ uvflag = 1
+ col = apply(Color, self.curColor)
+ elif self.curImage:
+ faceflags += FACEFLAGS.TEX
+
+# MAKE VERTICES
+
+ coo = curnode.coord
+ ncoo = len(coo.point)
+
+ if curnode.normal: # normals defined
+ normals = curnode.normal.vector
+ if curnode.normalPerVertex and len(coo.point) == len(normals):
+ self.mesh.recalc_normals = 0
+ normindex = curnode.normalIndex
+ i = 0
+ for v in coo.point:
+ newv = mesh.addVert(v)
+ n = newv.no
+ n[0], n[1], n[2] = normals[normindex[i]]
+ i += 1
+ else:
+ for v in coo.point:
+ mesh.addVert(v)
+ else:
+ for v in coo.point:
+ mesh.addVert(v)
+ if curnode.creaseAngle < CREASE_ANGLE_THRESHOLD:
+ self.mesh.smooth = 1
+
+ nvertices = len(mesh.vertices)
+ if nvertices != ncoo:
+ print "todo: %d, done: %d" % (ncoo, nvertices)
+ raise RuntimeError, "FATAL: could not create all vertices"
+
+# MAKE FACES
+
+ index = curnode.coordIndex
+ vlist = []
+
+ flip = OPTIONS['flipnormals']
+ facecount = 0
+ vertcount = 0
+
+ cols = []
+ if curnode.colorPerVertex: # per vertex colors
+ for i in index:
+ if i == -1:
+ if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def
+ vlist.reverse()
+ f = mesh.addFace(vlist, faceflags, uvflag)
+ if uvflag or colors:
+ f.col = cols
+ cols = []
+ vlist = []
+ else:
+ if colors:
+ col = apply(Color, colors[colindex[vertcount]])
+ cols.append(col)
+ vertcount += 1
+ v = mesh.vertices[i]
+ vlist.append(v)
+ else: # per face colors
+ for i in index:
+ if i == -1:
+ if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def
+ vlist.reverse()
+ f = mesh.addFace(vlist, faceflags, uvflag)
+ facecount += 1
+
+ if colors:
+ col = apply(Color, colors[colindex[facecount]])
+ cols = len(f.v) * [col]
+
+ if uvflag or colors:
+ f.col = cols
+ vlist = []
+ else:
+ v = mesh.vertices[i]
+ vlist.append(v)
+
+# TEXTURE COORDINATES
+
+ if not texcoo:
+ return None, None
+
+ self.curmaterial.setMode("traceable", "shadow", "texFace")
+ m = self.curtexmatrix
+ if m: # texture transform exists:
+ for uv in texcoo.point:
+ v = (uv[0], uv[1], 1.0)
+ v1 = matxvec(m, v)
+ uv[0], uv[1] = v1[0], v1[1]
+
+ UVindex = curnode.texCoordIndex
+ if not UVindex:
+ UVindex = curnode.coordIndex
+ # go assign UVs
+ self.mesh.hasFaceUV(1)
+ j = 0
+ uv = []
+ for i in UVindex:
+ if i == -1: # flush
+ if not curnode.ccw:
+ uv.reverse()
+ assignUV(f, uv)
+ assignImage(f, self.curImage)
+ uv = []
+ j +=1
+ else:
+ f = mesh.faces[j]
+ uv.append(texcoo.point[i])
+ return None, None
+
+class PostProcessor(NullProcessor):
+ def Shape(self, curnode, **kw):
+ pass
+ return None, None
+ def Transform(self, curnode, **kw):
+ return None, None
+
+class Walker:
+ """The node visitor (walker) class for VRML nodes"""
+ def __init__(self, pre, post = NullProcessor(), progress = None):
+ self.scene = Scenegraph.BScene()
+ self.preprocessor = pre
+ self.postprocessor = post
+ pre.walker = self # processor knows about walker
+ post.walker = self
+ self.nodes = 1
+ self.depth = 0
+ self.progress = progress
+ self.processednodes = 0
+
+ def walk(self, vnode, parent):
+ """Essential walker routine. It walks along the scenegraph nodes and
+processes them according to its pre/post processor methods.
+
+The preprocessor methods return the children of the node remaining
+to be processed or None. Also, a new created target node is returned.
+If the target node is == None, the current node will be skipped in the
+target scenegraph generation. If it is a valid node, the walker routine
+inserts it into the 'parent' node of the target scenegraph, which
+must be a valid root node on first call, leading us to the example usage:
+
+ p = Processor()
+ w = Walker(p, PostProcessor())
+ root = Scenegraph.RootNode()
+ w.walk(SG, root) # SG is a VRML scenegraph
+ """
+ global g_level #XXX
+ self.depth += 1
+ g_level = self.depth
+ if self.depth < PROGRESS_DEPTH:
+ self.processednodes += 1
+ if self.progress:
+ ret = self.progress(PARSE_TIME + PROCESS_TIME * float(self.processednodes) / self.nodes)
+ if not ret:
+ progress(1.0)
+ raise UnfinishedError, "User cancelled conversion"
+
+ # if vnode has already been processed, call Linker method, Processor method otherwise
+ id = vnode.DEF # get name
+ if not id:
+ id = 'Object'
+
+ processed = vnode.getTargetnode()
+ if processed: # has been processed ?
+ debug("linked obj: %s" % id)
+ children, bnode = self.link(processed, parent)
+ else:
+ children, bnode = self.preprocess(vnode, parent)
+
+ if not bnode:
+ bnode = parent # pass on
+ else:
+ parent.insert(bnode) # insert into SG
+
+ if children:
+ for c in children:
+ self.walk(c, bnode)
+ if not processed:
+ self.postprocess(vnode, bnode)
+
+ self.depth -= 1
+
+ return children, bnode
+
+ def link(self, bnode, parent):
+ """Link already processed data"""
+ # link data:
+ new = bnode.clone()
+ if not new:
+ raise RuntimeError, "couldn't clone object"
+ return None, new
+
+ def preprocess(self, vnode, newnode = None):
+ """Processes a VRML node 'vnode' and returns a custom node. The processor must
+be specified in 'p'.
+Optionally, a custom parent node (previously created) is passed as 'newnode'."""
+
+ pre = "pre"
+
+ nodetype = vnode.__gi__
+
+ debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF)
+ return callMethod(self.preprocessor, nodetype, vnode, newnode)
+
+ def postprocess(self, vnode, newnode = None):
+ """Postprocessing of a VRML node, see Walker.preprocess()"""
+
+ nodetype = vnode.__gi__
+ pre = "post"
+
+ debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF)
+ return callMethod(self.postprocessor, nodetype, vnode, newnode, 0)
+
+testfile2 = '/home/strubi/exotic/wrl/BrownTrout1.wrl'
+testfile = '/home/strubi/exotic/wrl/examples/VRML_Model_HSL.wrl'
+
+def fix_VRMLaxes(root, scale):
+ from Blender import Object, Scene
+ q = quat.fromRotAxis((1.0, 0.0, 0.0), 1.57079)
+ empty = Object.New(OB.EMPTY)
+ empty.layer = LAYER_EMPTY
+ Scene.getCurrent().link(empty)
+ node = Scenegraph.ObjectNode(empty, None, "VRMLscene")
+ node.transform.rotation = q
+ if scale:
+ node.transform.scale = (0.01, 0.01, 0.01)
+ for c in root.children:
+ node.insert(c)
+ node.update()
+ root.children = [node]
+
+#################################################################
+# these are the routines that must be provided for the importer
+# interface in blender
+
+def checkmagic(name):
+ "check for file magic"
+ f = open(name, "r")
+ magic = loader.getFileType(f)
+ f.close()
+ if magic == 'vrml':
+ return 1
+ elif magic == 'gzip':
+ verbose("gzipped file detected")
+ try:
+ import gzip
+ except ImportError, value:
+ warn("Importing gzip module: %s" % value)
+ return 0
+
+ f = gzip.open(name, 'rb')
+ header = f.readline()
+ f.close()
+ if header[:10] == "#VRML V2.0":
+ return 1
+ else:
+ return 0
+ print "unknown file"
+ return 0
+
+g_infotxt = ""
+
+def progress(done):
+ from Blender import Window
+ ret = Window.draw_progressbar(done, g_infotxt)
+ return ret
+
+class Counter:
+ def __init__(self):
+ self._count = 0
+ self.depth = 0
+ def count(self, node):
+ if self.depth >= PROGRESS_DEPTH:
+ return 0
+
+ self.depth += 1
+ self._count += 1
+ if not getChildren(node):
+ self.depth -= 1
+ return 0
+ else:
+ for c in node.children:
+ self.count(c)
+ self.depth -= 1
+ return self._count
+
+################################################################################
+# MAIN ROUTINE
+
+def importfile(name):
+
+ global g_infotxt
+ global options
+ global DEFAULTFLAGS
+
+ from Blender import Get # XXX
+ options = Get('vrmloptions')
+ DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC
+ if options['twoside']:
+ print "TWOSIDE"
+ DEFAULTFLAGS |= FACEFLAGS.TWOSIDE
+ clrError()
+ g_infotxt = "load & parse file..."
+ progress(0.0)
+ root = Scenegraph.RootNode()
+ try:
+ l = loader.Loader(name, progress)
+ SG = l.load()
+ p = Processor()
+ w = Walker(p, PostProcessor(), progress)
+ g_infotxt = "convert data..."
+ p.curpath = os.path.dirname(name)
+ print "counting nodes...",
+ c = Counter()
+ nodes = c.count(SG)
+ print "done."
+ w.nodes = nodes # let walker know about number of nodes parsed # XXX
+ w.walk(SG, root)
+ except UnfinishedError, msg:
+ print msg
+
+ progress(1.0)
+ fix_VRMLaxes(root, options['autoscale']) # rotate coordinate system: in VRML, y is up!
+ root.update() # update baselist for proper display
+ return root
diff --git a/intern/python/modules/Converter/importer/__init__.py b/intern/python/modules/Converter/importer/__init__.py
new file mode 100644
index 00000000000..003e2733b17
--- /dev/null
+++ b/intern/python/modules/Converter/importer/__init__.py
@@ -0,0 +1,17 @@
+"""This module contains a list of valid importers in 'importers'. At runtime,
+importer modules can be registered by the 'register' function."""
+
+__all__ = ["VRMLimporter"]
+
+importers = __all__
+
+import VRMLimporter
+
+def register(importer):
+ """Register an file importer"""
+ methods = ["checkmagic", "importfile"]
+ for m in methods:
+ if not hasattr(importer, m):
+ raise TypeError, "This is not an importer"
+ importers.append(importer)
+
diff --git a/intern/python/modules/Converter/importloader.py b/intern/python/modules/Converter/importloader.py
new file mode 100644
index 00000000000..245ab108d1f
--- /dev/null
+++ b/intern/python/modules/Converter/importloader.py
@@ -0,0 +1,23 @@
+# this is the importloader which blender calls on unknown
+# file types
+
+import importer
+
+supported= {'wrl': importer.VRMLimporter}
+
+def process(name):
+ # run through importerlist and check for magic
+ m = None
+ for modname in importer.importers:
+ mod = getattr(importer, modname)
+ if mod.checkmagic(name):
+ m = mod
+ break
+ if not m:
+ return 0
+ m.importfile(name)
+ #except:
+ #import sys
+ #print "Import failed"sys.exc_value
+ return 1
+
diff --git a/intern/python/modules/TextTools/Constants/Sets.py b/intern/python/modules/TextTools/Constants/Sets.py
new file mode 100644
index 00000000000..bf260aa3e0c
--- /dev/null
+++ b/intern/python/modules/TextTools/Constants/Sets.py
@@ -0,0 +1,39 @@
+""" Constants for sets (of characters)
+
+ (c) Copyright Marc-Andre Lemburg; All Rights Reserved.
+ See the documentation for further information on copyrights,
+ or contact the author (mal@lemburg.com).
+"""
+import string
+
+# Simple character strings
+
+a2z = 'abcdefghijklmnopqrstuvwxyz'
+A2Z = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+umlaute = 'äöüß'
+Umlaute = 'ÄÖÜ'
+alpha = A2Z + a2z
+german_alpha = A2Z + a2z + umlaute + Umlaute
+number = '0123456789'
+alphanumeric = alpha + number
+white = ' \t\v'
+newline = '\r\n'
+formfeed = '\f'
+whitespace = white + newline + formfeed
+any = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377'
+
+# Precompiled as sets, e.g. a2z_set = set(a2z)
+a2z_set = '\000\000\000\000\000\000\000\000\000\000\000\000\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+A2Z_set = '\000\000\000\000\000\000\000\000\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+alpha_set = '\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+german_alpha_set = '\000\000\000\000\000\000\000\000\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\020\000@\220\020\000@\020'
+number_set = '\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+alphanumeric_set = '\000\000\000\000\000\000\377\003\376\377\377\007\376\377\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+white_set = '\000\002\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+newline_set = '\000$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+whitespace_set = '\000&\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000'
+nonwhitespace_set = '\377\301\377\377\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377'
+any_set = '\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377'
+
+# Clean up
+del string
diff --git a/intern/python/modules/TextTools/Constants/TagTables.py b/intern/python/modules/TextTools/Constants/TagTables.py
new file mode 100644
index 00000000000..315d825b94e
--- /dev/null
+++ b/intern/python/modules/TextTools/Constants/TagTables.py
@@ -0,0 +1,348 @@
+""" Constants for writing tag tables
+
+ The documentation in this file is obsoleted by the HTML docs in
+ the Doc/ subdirectory of the package. Constants defined here must
+ match those in mxTextTools/mxte.h.
+
+ (c) Copyright Marc-Andre Lemburg; All Rights Reserved.
+ See the documentation for further information on copyrights,
+ or contact the author (mal@lemburg.com).
+"""
+#########################################################################
+# This file contains the definitions and constants used by the tagging
+# engine:
+#
+# 1. Matching Tables
+# 2. Commands & Constants
+# 3. Matching Functions
+# 4. Callable tagobjects
+# 5. Calling the engine & Taglists
+#
+
+#########################################################################
+# 1. Matching Tables:
+#
+# these are tuples of tuples, each entry having the following meaning:
+#
+# syntax: (tag, cmd, chars|table|fct [,jne] [,je=1])
+# tag = object used to mark this section, if it matches
+# cmd = command (see below)
+# chars = match one or more of these characters
+# table = table to use for matching characters
+# fct = function to call (see below)
+# jne = if the current character doesn't match, jump this
+# many table entries relative to the current entry
+# je = if we have a match make a relative jump of this length
+#
+# * a table matches a string iff the end of the table is reached
+# (that is: an index is requested that is beyond the end-of-table)
+# * a table is not matched if a tag is not matched and no jne is given;
+# if it is matched then processing simply moves on to the next entry
+# * marking is done by adding the matching slice in the string
+# together with the marking object to the tag list; if the object is
+# None, then it will not be appended to the taglist list
+# * if the flag CallTag is set in cmd, then instead of appending
+# matches to the taglist, the tagobj will be called (see below)
+#
+# TIP: if you are getting an error 'call of a non-function' while
+# writing a table definition, you probably have a missing ','
+# somewhere in the tuple !
+#
+# For examples see the tag*.py - files that came with this engine.
+#
+
+#########################################################################
+# 2. Commands & Constants
+#
+#
+
+#
+# some useful constants for writing matching tables
+#
+
+To = None # good for cmd=Jump
+Here = None # good for cmd=Fail and EOF
+MatchOk = 20000 # somewhere beyond the end of the tag table...
+MatchFail = -20000 # somewhere beyond the start of the tag table...
+ToEOF = -1 # good for cmd=Move
+
+ThisTable = 999 # to recursively match using the current table;
+ # can be passed as argument to Table and SubTable
+ # instead of a tuple
+
+#
+# commands and flags passed in cmd (see below)
+#
+# note: I might add some further commands to this list, if needed
+# (the numbers will then probably change, but not the
+# names)
+#
+# convention: a command "matches", if and only if it moves the
+# current position at least one character; a command "reads"
+# characters the characters, if they match ok
+#
+# notations:
+#
+# x refers to the current position in the string
+# len refers to the string length or what the function tag() is told to
+# believe it to be (i.e. the engine only looks at the slice text[x:len])
+# text refers to the text string
+# jne is the optional relative jump distance in case the command
+# did not match, i.e. x before and after applying the command
+# are the same (if not given the current table is considered
+# not to match)
+# je is the optional relative jump distance in case the command
+# did match (it defaults to +1)
+#
+
+# commands
+Fail = 0 # this will always fail (position remains unchanged)
+Jump = 0 # jump to jne (position remains unchanged)
+
+# match & read chars
+AllIn = 11 # all chars in match (at least one)
+AllNotIn = 12 # all chars not in match (at least one)
+Is = 13 # current char must be == match (matches one char)
+IsIn = 14 # current char must be in match (matches one char)
+IsNot = 15 # current char must be be != match (matches one char)
+IsNotIn = 15 # current char must be not be in match (matches one char)
+
+AllInSet = 31
+IsInSet = 32
+
+# match & read for whole words
+Word = 21 # the next chars must be those in match
+WordStart = 22 # all chars up to the first occ. of match (at least one)
+WordEnd = 23 # same as WordStart, accept that the text pointer
+ # is moved behind the match
+NoWord = WordStart # all chars up to the first occ. of match (at least one)
+
+
+# match using search objects BMS or FS
+sWordStart = 111 # all chars up to the first occ. of match (may be 0 chars)
+sWordEnd = 112 # same as WordStart, accept that the text pointer
+ # is moved behind the match
+sFindWord = 113 # find match and process the found slice only (ignoring
+ # the chars that lead up to the match); positions
+ # the text pointer right after the match like WordEnd
+
+# functions & tables
+Call = 201 # call match(text,x,len) as function (see above)
+CallArg = 202 # match has to be a 2-tuple (fct,arg), then
+ # fct(text,x,len,arg) is called; the return value is taken
+ # as new x; it is considered matching if the new x is
+ # different than the x before the call -- like always
+ # (note: arg has to be *one* object, e.g. a tuple)
+Table = 203 # match using table (given in match)
+SubTable = 207 # match using sub table (given in match); the sub table
+ # uses the same taglist as the calling table
+TableInList = 204 # same as Table, but match is a tuple (list,index)
+ # and the table list[index] is used as matching
+ # table
+SubTableInList = 208
+ # same as TableInList, but the sub table
+ # uses the same taglist as the calling table
+
+# specials
+EOF = 1 # current position must be EOF, e.g. >= len(string)
+Skip = 2 # skip match (must be an integer) chars; note: this cmd
+ # always matches ok, so jne doesn't have any meaning in
+ # this context
+Move = 3 # move the current text position to match (if negative,
+ # the text length + 1 (!) is added, thus -1 moves to the
+ # EOF, -2 to the last char and so on); note: this cmd
+ # always matches ok, so jne doesn't have any meaning in
+ # this context
+
+# loops
+Loop = 205 # loop-construct
+ #
+ # (tagobj,Loop,Count,jne,je) - sets/decrements the
+ # loop variable for current table according to the
+ # following rules:
+ # 1. the first time the engine passes this entry
+ # sets the loop variable to Count and continues
+ # without reading any character, but saving the
+ # current position in text
+ # 2. the next time, it decrements the loop variable
+ # and checks if it is < 0:
+ # (a) if it is, then the tagobj is added to the
+ # taglist with the slice (saved position, current
+ # position) and processing continues at entry
+ # current + jne
+ # (b) else, processing continues at entry current + je
+ # Note: if you jump out of the loop while the loop
+ # variable is still > 0, then you *must*
+ # reset the loop mechanism with
+ # (None,LoopControl,Reset)
+ # Note: you can skip the remaining loops by calling
+ # (None,LoopControl,Break) and jumping back
+ # to the Loop-entry; this sets the loop
+ # variable to 0
+ # Note: tables cannot have nested loops within their
+ # context; you can have nested loops in nested
+ # tables though (there is one loop var per
+ # tag()-call which takes place every time
+ # a table match is done)
+ #
+LoopControl = 206 # controls the loop variable (always succeeds, i.e.
+ # jne has no meaning);
+ # match may be one of:
+Break = 0 # * sets the loop variable to 0, thereby allowing
+ # to skip the remaining loops
+Reset = -1 # * resets the loop mechanism (see note above)
+ #
+ # See tagLoop.py for some examples.
+
+##########################################################################
+#
+# Flags (to be '+'ed with the above command code)
+#
+CallTag = 256 # call tagobj(taglist,text,l,r,subtags)
+ # upon successfully matching the slice [l:r] in text
+ # * taglist is the current list tags found (may be None)
+ # * subtags is a sub-list, passed when a subtable was used
+ # to do the matching -- it is None otherwise !)
+#
+# example entry with CallTag-flag set:
+#
+# (found_a_tag,CallTag+Table,tagtable)
+# -- if tagtable matches the current text position,
+# found_a_tag(taglist,text,l,r,newtaglist) is called and
+# the match is *not* appended to the taglist by the tagging
+# engine (the function would have to do this, in case it is needed)
+
+AppendToTagobj = 512 # this appends the slice found to the tagobj, assuming
+ # that it is a Python list:
+ # does a tagobj.append((None,l,r,subtags)) call
+# Alias for b/w comp.
+AppendToTag = AppendToTagobj
+
+AppendTagobj = 1024 # don't append (tagobj,l,r,subtags) to the taglist,
+ # but only tagobj itself; the information in l,r,subtags
+ # is lost, yet this can be used to write tag tables
+ # whose output can be used directly by tag.join()
+
+AppendMatch = 2048 # append the match to the taglist instead of
+ # the tag object; this produces non-standard
+ # taglists !
+
+#########################################################################
+# 3. Matching Functions
+#
+# syntax:
+#
+# fct(s,x,len_s)
+# where s = string we are working on
+# x = current index in s where we wnat to match something
+# len_s = 'length' of s, this is how far the search may be
+# conducted in s, not necessarily the true length of s
+#
+# * the function has to return the index of the char right after
+# matched string, e.g.
+#
+# 'xyzabc' ---> 'xyz' matches ---> return x+3
+#
+# * if the string doesn't match simply return x; in other words:
+# the function has to return the matching slice's right index
+# * you can use this to match e.g. 10 characters of a certain kind,
+# or any word out of a given list, etc.
+# * note: you cannot give the function additional parameters from within
+# the matching table, so it has to know everything it needs to
+# know a priori; use dynamic programming !
+#
+# some examples (not needed, since all are implemented by commands)
+#
+#
+#def matchword(x):
+# s = """
+#def a(s,x,len_text):
+# y = x+%i
+# if s[x:y] == %s: return y
+# return x
+#"""
+# exec s % (len(x),repr(x))
+# return a
+#
+#def rejectword(x):
+# s = """
+#def a(s,x,len_text):
+# while x < len(s) and s[x:x+%i] != %s:
+# x = x + 1
+# return x
+#"""
+# exec s % (len(x),repr(x))
+# return a
+#
+#def HTML_Comment(s,x,len_text):
+# while x < len_text and s[x:x+3] != '-->':
+# x = x + 1
+# return x
+#
+#
+
+#########################################################################
+# 4. Callable tagobjects
+#
+# a sample callable tagobj:
+#
+#
+#def test(taglist,text,l,r,newtaglist):
+#
+# print 'found',repr(text[l:r])[:40],(l,r)
+#
+#
+
+#########################################################################
+# 5. Calling the engine & Taglists
+#
+# The function
+# tag(text,table,start=0,len_text=len(text),taglistinit=[])
+# found in mxTextTools:
+#
+# This function does all the matching according to the above rules.
+# You give it a text string and a tag table and it will
+# start processing the string starting from 'start' (which defaults to 0)
+# and continue working until it reaches the 'EOF', i.e. len_text (which
+# defaults to the text length). It thus tags the slice text[start:len_text].
+#
+# The function will create a list of found tags in the following
+# format (which I call taglist):
+#
+# (tagobj,l,r,subtaglist)
+#
+# where: tagobj = specified tag object taken from the table
+# [l:r] = slice that matched the tag in text
+# subtaglist = if matching was done using a subtable
+# this is the taglist it produced; in all other
+# cases this will be None
+#
+# * if you pass None as taglistinit, then no taglist will be created,
+# i.e. only CallTag commands will have any effect. (This saves
+# temporary memory for big files)
+# * the function returns a tuple:
+# (success, taglist, nextindex)
+# where: success = 0/1
+# taglist = the produced list or None
+# nextindex = the index+1 of the last char that matched
+# (in case of failure, this points to the beginning
+# of the substring that caused the problem)
+#
+
+### Module init.
+
+def _module_init():
+
+ global id2cmd
+
+ import types
+ id2cmd = {}
+ IntType = types.IntType
+ for cmd,value in globals().items():
+ if type(value) == IntType:
+ if value == 0:
+ id2cmd[0] = 'Fail/Jump'
+ else:
+ id2cmd[value] = cmd
+
+_module_init()
diff --git a/intern/python/modules/TextTools/Constants/__init__.py b/intern/python/modules/TextTools/Constants/__init__.py
new file mode 100644
index 00000000000..0519ecba6ea
--- /dev/null
+++ b/intern/python/modules/TextTools/Constants/__init__.py
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/intern/python/modules/TextTools/TextTools.py b/intern/python/modules/TextTools/TextTools.py
new file mode 100644
index 00000000000..7eae2bcfc39
--- /dev/null
+++ b/intern/python/modules/TextTools/TextTools.py
@@ -0,0 +1,766 @@
+""" mxTextTools - A tools package for fast text processing.
+
+ (c) Copyright Marc-Andre Lemburg; All Rights Reserved.
+ See the documentation for further information on copyrights,
+ or contact the author (mal@lemburg.com).
+"""
+import string,types
+
+#
+# import the C module and the version number
+#
+from mxTextTools import *
+from mxTextTools import __version__
+
+#
+# import the symbols needed to write tag tables
+#
+from Constants.TagTables import *
+
+#
+# import the some handy character sets
+#
+from Constants.Sets import *
+
+#
+# format and print tables, taglists and joinlists:
+#
+def format_entry(table,i,
+
+ TupleType=types.TupleType):
+
+ """ Returns a pp-formatted tag table entry as string
+ """
+ e = table[i]
+ jne = 0
+ je = 1
+ t,c,m = e[:3]
+ if len(e)>3: jne = e[3]
+ if len(e)>4: je = e[4]
+ flags,cmd = divmod(c,256)
+ c = id2cmd[cmd]
+ if type(m) == TupleType and c in ('Table','SubTable'):
+ m = '<table>'
+ elif m == None:
+ m = 'Here/To'
+ else:
+ m = repr(m)
+ if len(m) > 17:
+ m = m[:17]+'...'
+ return '%-15.15s : %-30s : jne=%+i : je=%+i' % \
+ (repr(t),'%-.15s : %s'%(c,m),jne,je)
+
+def format_table(table,i=-1):
+
+ """ Returns a pp-formatted version of the tag table as string """
+
+ l = []
+ for j in range(len(table)):
+ if i == j:
+ l.append('--> '+format_entry(table,j))
+ else:
+ l.append(' '+format_entry(table,j))
+ return string.join(l,'\n')+'\n'
+
+def print_tagtable(table):
+
+ """ Print the tag table
+ """
+ print format_table(table)
+
+def print_tags(text,tags,indent=0):
+
+ """ Print the taglist tags for text using the given indent level
+ """
+ for tag,l,r,subtags in tags:
+ tagname = repr(tag)
+ if len(tagname) > 20:
+ tagname = tagname[:20] + '...'
+ target = repr(text[l:r])
+ if len(target) > 60:
+ target = target[:60] + '...'
+ if subtags == None:
+ print ' '+indent*' |',tagname,': ',target,(l,r)
+ else:
+ print ' '+indent*' |',tagname,': ',target,(l,r)
+ print_tags(text,subtags,indent+1)
+
+def print_joinlist(joins,indent=0,
+
+ StringType=types.StringType):
+
+ """ Print the joinlist joins using the given indent level
+ """
+ for j in joins:
+ if type(j) == StringType:
+ text = repr(j)
+ if len(text) > 40:
+ text = text[:40] + '...'
+ print ' '+indent*' |',text,' (len = %i)' % len(j)
+ else:
+ text = j[0]
+ l,r = j[1:3]
+ text = repr(text[l:r])
+ if len(text) > 40:
+ text = text[:40] + '...'
+ print ' '+indent*' |',text,' (len = %i)' % (r-l),(l,r)
+
+def normlist(jlist,
+
+ StringType=types.StringType):
+
+ """ Return a normalized joinlist.
+
+ All tuples in the joinlist are turned into real strings. The
+ resulting list is a equivalent copy of the joinlist only
+ consisting of strings.
+
+ """
+ l = [''] * len(jlist)
+ for i in range(len(jlist)):
+ entry = jlist[i]
+ if type(entry) == StringType:
+ l[i] = entry
+ else:
+ l[i] = entry[0][entry[1]:entry[2]]
+ return l
+
+#
+# aid for matching from a list of words
+#
+def _lookup_dict(l,index=0):
+
+ d = {}
+ for w in l:
+ c = w[index]
+ if d.has_key(c):
+ d[c].append(w)
+ else:
+ d[c] = [w]
+ return d
+
+def word_in_list(l):
+
+ """ Creates a lookup table that matches the words in l
+ """
+ t = []
+ d = _lookup_dict(l)
+ keys = d.keys()
+ if len(keys) < 18: # somewhat arbitrary bound
+ # fast hint for small sets
+ t.append((None,IsIn,string.join(d.keys(),'')))
+ t.append((None,Skip,-1))
+ # test groups
+ for c, group in d.items():
+ t.append(None) # hint will be filled in later
+ i = len(t)-1
+ for w in group:
+ t.append((None,Word,w[1:],+1,MatchOk))
+ t.append((None,Fail,Here))
+ # add hint
+ t[i] = (None,Is,c,len(t)-i)
+ t.append((None,Fail,Here))
+ return tuple(t)
+
+#
+# Extra stuff useful in combination with the C functions
+#
+
+def replace(text,what,with,start=0,stop=None,
+
+ SearchObject=BMS,join=join,joinlist=joinlist,tag=tag,
+ string_replace=string.replace,type=type,
+ StringType=types.StringType):
+
+ """A fast replacement for string.replace.
+
+ what can be given as string or search object.
+
+ This function is a good example for the AppendTagobj-flag usage
+ (the taglist can be used directly as joinlist).
+
+ """
+ if type(what) == StringType:
+ so = SearchObject(what)
+ else:
+ so = what
+ what = so.match
+ if stop is None:
+ if start == 0 and len(what) < 2:
+ return string_replace(text,what,with)
+ stop = len(text)
+ t = ((text,sWordStart,so,+2),
+ # Found something, replace and continue searching
+ (with,Skip+AppendTagobj,len(what),-1,-1),
+ # Rest of text
+ (text,Move,ToEOF)
+ )
+ found,taglist,last = tag(text,t,start,stop)
+ if not found:
+ return text
+ return join(taglist)
+
+# Alternative (usually slower) versions using different techniques:
+
+def _replace2(text,what,with,start=0,stop=None,
+
+ join=join,joinlist=joinlist,tag=tag,
+ StringType=types.StringType,BMS=BMS):
+
+ """Analogon to string.replace; returns a string with all occurences
+ of what in text[start:stop] replaced by with
+ - uses a one entry tag-table and a Boyer-Moore-Search-object
+ - what can be a string or a BMS/FS search object
+ - it's faster than string.replace in those cases, where
+ the what-string gets long and/or many replacements are found;
+ faster meaning from a few percent up to many times as fast
+ - start and stop define the slice of text to work in
+ - stop defaults to len(text)
+ """
+ if stop is None:
+ stop = len(text)
+ if type(what) == StringType:
+ what=BMS(what)
+ t = ((with,sFindWord,what,+1,+0),)
+ found,taglist,last = tag(text,t,start,stop)
+ if not found:
+ return text
+ return join(joinlist(text,taglist))
+
+def _replace3(text,what,with,
+
+ join=string.join,FS=FS,
+ StringType=types.StringType):
+
+ if type(what) == StringType:
+ what=FS(what)
+ slices = what.findall(text)
+ if not slices:
+ return text
+ l = []
+ x = 0
+ for left,right in slices:
+ l.append(text[x:left] + with)
+ x = right
+ l.append(text[x:])
+ return join(l,'')
+
+def _replace4(text,what,with,
+
+ join=join,joinlist=joinlist,tag=tag,FS=FS,
+ StringType=types.StringType):
+
+ if type(what) == StringType:
+ what=FS(what)
+ slices = what.findall(text)
+ if not slices:
+ return text
+ repl = [None]*len(slices)
+ for i in range(len(slices)):
+ repl[i] = (with,)+slices[i]
+ return join(joinlist(text,repl))
+
+
+def find(text,what,start=0,stop=None,
+
+ SearchObject=FS):
+
+ """ A faster replacement for string.find().
+
+ Uses a search object for the task. Returns the position of the
+ first occurance of what in text[start:stop]. stop defaults to
+ len(text). Returns -1 in case no occurance was found.
+
+ """
+ if stop:
+ return SearchObject(what).find(text,start,stop)
+ else:
+ return SearchObject(what).find(text,start)
+
+def findall(text,what,start=0,stop=None,
+
+ SearchObject=FS):
+
+ """ Find all occurances of what in text.
+
+ Uses a search object for the task. Returns a list of slice
+ tuples (l,r) marking the all occurances in
+ text[start:stop]. stop defaults to len(text). Returns an
+ empty list in case no occurance was found.
+
+ """
+ if stop:
+ return SearchObject(what).findall(text,start,stop)
+ else:
+ return SearchObject(what).findall(text,start)
+
+def split(text,sep,start=0,stop=None,translate=None,
+
+ SearchObject=FS):
+
+ """ A faster replacement for string.split().
+
+ Uses a search object for the task. Returns the result of
+ cutting the text[start:stop] string into snippets at every sep
+ occurance in form of a list of substrings. translate is passed
+ to the search object as translation string.
+
+ XXX convert to a C function... or even better, add as method
+ to search objects.
+
+ """
+ if translate:
+ so = SearchObject(sep,translate)
+ else:
+ so = SearchObject(sep)
+ if stop:
+ cuts = so.findall(text,start,stop)
+ else:
+ cuts = so.findall(text,start)
+ l = 0
+ list = []
+ append = list.append
+ for left,right in cuts:
+ append(text[l:left])
+ l = right
+ append(text[l:])
+ return list
+
+# helper for tagdict
+def _tagdict(text,dict,prefix,taglist):
+
+ for o,l,r,s in taglist:
+ pfx = prefix + str(o)
+ dict[pfx] = text[l:r]
+ if s:
+ _tagdict(text,dict,pfx+'.',s)
+
+def tagdict(text,*args):
+
+ """ Tag a text just like the function tag() and then convert
+ its output into a dictionary where the tagobjects reference
+ their respective strings
+ - this function emulates the interface of tag()
+ - in contrast to tag() this funtion *does* make copies
+ of the found stings
+ - returns a tuple (rc,tagdict,next) with the same meaning
+ of rc and next as tag(); tagdict is the new dictionary -
+ None in case rc is 0
+ """
+ rc,taglist,next = apply(tag,(text,)+args)
+ if not rc:
+ return (rc,None,next)
+ d = {}
+ tagdict = _tagdict
+ for o,l,r,s in taglist:
+ pfx = str(o)
+ d[pfx] = text[l:r]
+ if s:
+ tagdict(text,dict,pfx+'.',s)
+ return (rc,d,next)
+
+def invset(chars):
+
+ """ Return a set with all characters *except* the ones in chars.
+ """
+ return set(chars,0)
+
+def is_whitespace(text,start=0,stop=None,
+
+ nonwhitespace=nonwhitespace_set,setfind=setfind):
+
+ """ Return 1 iff text[start:stop] only contains whitespace
+ characters (as defined in Constants/Sets.py), 0 otherwise.
+ """
+ if stop is None:
+ stop = len(text)
+ i = setfind(text,nonwhitespace,start,stop)
+ return (i < 0)
+
+def collapse(text,seperator=' ',
+
+ join=join,setsplit=setsplit,collapse_set=set(newline+whitespace)):
+
+ """ Eliminates newline characters and compresses whitespace
+ characters into one space.
+
+ The result is a one line text string. Tim Peters will like
+ this function called with '-' seperator ;-)
+
+ """
+ return join(setsplit(text,collapse_set),seperator)
+
+_linesplit_table = (
+ (None,Is,'\r',+1),
+ (None,Is,'\n',+1),
+ ('line',AllInSet+AppendMatch,set('\r\n',0),+1,-2),
+ (None,EOF,Here,+1,MatchOk),
+ ('empty line',Skip+AppendMatch,0,0,-4),
+ )
+
+def splitlines(text,
+
+ tag=tag,linesplit_table=_linesplit_table):
+
+ """ Split text into a list of single lines.
+
+ The following combinations are considered to be line-ends:
+ '\r', '\r\n', '\n'; they may be used in any combination. The
+ line-end indicators are removed from the strings prior to
+ adding them to the list.
+
+ This function allows dealing with text files from Macs, PCs
+ and Unix origins in a portable way.
+
+ """
+ return tag(text,linesplit_table)[1]
+
+_linecount_table = (
+ (None,Is,'\r',+1),
+ (None,Is,'\n',+1),
+ ('line',AllInSet+AppendTagobj,set('\r\n',0),+1,-2),
+ (None,EOF,Here,+1,MatchOk),
+ ('empty line',Skip+AppendTagobj,0,0,-4),
+ )
+
+def countlines(text,
+
+ linecount_table=_linecount_table):
+
+ """ Returns the number of lines in text.
+
+ Line ends are treated just like for splitlines() in a
+ portable way.
+ """
+ return len(tag(text,linecount_table)[1])
+
+_wordsplit_table = (
+ (None,AllInSet,whitespace_set,+1),
+ ('word',AllInSet+AppendMatch,nonwhitespace_set,+1,-1),
+ (None,EOF,Here,+1,MatchOk),
+ )
+
+def splitwords(text,
+
+ setsplit=setsplit,whitespace_set=whitespace_set):
+
+ """ Split text into a list of single words.
+
+ Words are separated by whitespace. The whitespace is stripped
+ before adding the words to the list.
+
+ """
+ return setsplit(text,whitespace_set)
+
+#
+# Testing and benchmarking
+#
+
+# Taken from my hack.py module:
+import time
+class _timer:
+
+ """ timer class with a quite obvious interface
+ - .start() starts a fairly accurate CPU-time timer plus an
+ absolute timer
+ - .stop() stops the timer and returns a tuple: the CPU-time in seconds
+ and the absolute time elapsed since .start() was called
+ """
+
+ utime = 0
+ atime = 0
+
+ def start(self,
+ clock=time.clock,time=time.time):
+ self.atime = time()
+ self.utime = clock()
+
+ def stop(self,
+ clock=time.clock,time=time.time):
+ self.utime = clock() - self.utime
+ self.atime = time() - self.atime
+ return self.utime,self.atime
+
+ def usertime(self,
+ clock=time.clock,time=time.time):
+ self.utime = clock() - self.utime
+ self.atime = time() - self.atime
+ return self.utime
+
+ def abstime(self,
+ clock=time.clock,time=time.time):
+ self.utime = clock() - self.utime
+ self.atime = time() - self.atime
+ return self.utime
+
+ def __str__(self):
+
+ return '%0.2fu %0.2fa sec.' % (self.utime,self.atime)
+
+def _bench(file='mxTextTools/mxTextTools.c'):
+
+ def mismatch(orig,new):
+ print
+ for i in range(len(orig)):
+ if orig[i] != new[i]:
+ break
+ else:
+ print 'Length mismatch: orig=%i new=%i' % (len(orig),len(new))
+ if len(orig) > len(new):
+ print 'Missing chars:'+repr(orig[len(new):])
+ else:
+ print 'Excess chars:'+repr(new[len(orig):])
+ print
+ return
+ print 'Mismatch at offset %i:' % i
+ print (orig[i-100:i]
+ + '<- %s != %s ->' % (repr(orig[i]),repr(new[i]))
+ + orig[i+1:i+100])
+ print
+
+ text = open(file).read()
+ import string
+
+ t = _timer()
+ print 'Working on a %i byte string' % len(text)
+
+ if 0:
+ print
+ print 'Replacing strings'
+ print '-'*72
+ print
+ for what,with in (('m','M'),('mx','MX'),('mxText','MXTEXT'),
+ ('hmm','HMM'),('hmmm','HMM'),('hmhmm','HMM')):
+ print 'Replace "%s" with "%s"' % (what,with)
+ t.start()
+ for i in range(100):
+ rtext = string.replace(text,what,with)
+ print 'with string.replace:',t.stop(),'sec.'
+ t.start()
+ for i in range(100):
+ ttext = replace(text,what,with)
+ print 'with tag.replace:',t.stop(),'sec.'
+ if ttext != rtext:
+ print 'results are NOT ok !'
+ print '-'*72
+ mismatch(rtext,ttext)
+ t.start()
+ for i in range(100):
+ ttext = _replace2(text,what,with)
+ print 'with tag._replace2:',t.stop(),'sec.'
+ if ttext != rtext:
+ print 'results are NOT ok !'
+ print '-'*72
+ print rtext
+ t.start()
+ for i in range(100):
+ ttext = _replace3(text,what,with)
+ print 'with tag._replace3:',t.stop(),'sec.'
+ if ttext != rtext:
+ print 'results are NOT ok !'
+ print '-'*72
+ print rtext
+ t.start()
+ for i in range(100):
+ ttext = _replace4(text,what,with)
+ print 'with tag._replace4:',t.stop(),'sec.'
+ if ttext != rtext:
+ print 'results are NOT ok !'
+ print '-'*72
+ print rtext
+ print
+
+ if 0:
+ print
+ print 'String lower/upper'
+ print '-'*72
+ print
+
+ op = string.lower
+ t.start()
+ for i in range(1000):
+ op(text)
+ t.stop()
+ print ' string.lower:',t
+
+ op = string.upper
+ t.start()
+ for i in range(1000):
+ op(text)
+ t.stop()
+ print ' string.upper:',t
+
+ op = upper
+ t.start()
+ for i in range(1000):
+ op(text)
+ t.stop()
+ print ' TextTools.upper:',t
+
+ op = lower
+ t.start()
+ for i in range(1000):
+ op(text)
+ t.stop()
+ print ' TextTools.lower:',t
+
+ print 'Testing...',
+ ltext = string.lower(text)
+ assert ltext == lower(text)
+ utext = string.upper(text)
+ assert utext == upper(text)
+ print 'ok.'
+
+ if 0:
+ print
+ print 'Joining lists'
+ print '-'*72
+ print
+
+ l = setsplit(text,whitespace_set)
+
+ op = string.join
+ t.start()
+ for i in range(1000):
+ op(l)
+ t.stop()
+ print ' string.join:',t
+
+ op = join
+ t.start()
+ for i in range(1000):
+ op(l)
+ t.stop()
+ print ' TextTools.join:',t
+
+ op = string.join
+ t.start()
+ for i in range(1000):
+ op(l,' ')
+ t.stop()
+ print ' string.join with seperator:',t
+
+ op = join
+ t.start()
+ for i in range(1000):
+ op(l,' ')
+ t.stop()
+ print ' TextTools.join with seperator:',t
+
+ if 0:
+ print
+ print 'Creating join lists'
+ print '-'*72
+ print
+
+ repl = []
+ for i in range(0,len(text),10):
+ repl.append(str(i),i,i+1)
+
+ op = joinlist
+ t.start()
+ for i in range(1000):
+ op(text,repl)
+ t.stop()
+ print ' TextTools.joinlist:',t
+
+ if 0:
+ print
+ print 'Splitting text'
+ print '-'*72
+ print
+
+ op = string.split
+ t.start()
+ for i in range(100):
+ op(text)
+ t.stop()
+ print ' string.split whitespace:',t,'(',len(op(text)),'snippets )'
+
+ op = setsplit
+ ws = whitespace_set
+ t.start()
+ for i in range(100):
+ op(text,ws)
+ t.stop()
+ print ' TextTools.setsplit whitespace:',t,'(',len(op(text,ws)),'snippets )'
+
+ assert string.split(text) == setsplit(text,ws)
+
+ op = string.split
+ sep = 'a'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' string.split at "a":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = split
+ sep = 'a'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.split at "a":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = charsplit
+ sep = 'a'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.charsplit at "a":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = setsplit
+ sep = set('a')
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.setsplit at "a":',t,'(',len(op(text,sep)),'snippets )'
+
+ # Note: string.split and setsplit don't work identically !
+
+ op = string.split
+ sep = 'int'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' string.split at "int":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = split
+ sep = 'int'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.split at "int":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = setsplit
+ sep = set('int')
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.setsplit at "i", "n", "t":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = string.split
+ sep = 'register'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' string.split at "register":',t,'(',len(op(text,sep)),'snippets )'
+
+ op = split
+ sep = 'register'
+ t.start()
+ for i in range(100):
+ op(text,sep)
+ t.stop()
+ print ' TextTools.split at "register":',t,'(',len(op(text,sep)),'snippets )'
+
+if __name__=='__main__':
+ _bench()
+
diff --git a/intern/python/modules/TextTools/__init__.py b/intern/python/modules/TextTools/__init__.py
new file mode 100644
index 00000000000..f9255aca276
--- /dev/null
+++ b/intern/python/modules/TextTools/__init__.py
@@ -0,0 +1,48 @@
+""" mxTextTools - A tools package for fast text processing.
+
+ (c) Copyright Marc-Andre Lemburg; All Rights Reserved.
+ See the documentation for further information on copyrights,
+ or contact the author (mal@lemburg.com).
+"""
+__package_info__ = """
+BEGIN PYTHON-PACKAGE-INFO 1.0
+Title: mxTextTools - Tools for fast text processing
+Current-Version: 1.1.1
+Home-Page: http://starship.skyport.net/~lemburg/mxTextTools.html
+Primary-Site: http://starship.skyport.net/~lemburg/mxTextTools-1.1.1.zip
+
+This package provides several different functions and mechanisms
+to do fast text text processing. Amongst these are character set
+operations, parsing & tagging tools (using a finite state machine
+executing byte code) and common things such as Boyer-Moore search
+objects. For full documentation see the home page.
+END PYTHON-PACKAGE-INFO
+"""
+from TextTools import *
+from TextTools import __version__
+
+### Make the types pickleable:
+
+# Shortcuts for pickle (reduces the pickle's length)
+def _BMS(match,translate):
+ return BMS(match,translate)
+def _FS(match,translate):
+ return FS(match,translate)
+
+# Module init
+class modinit:
+
+ ### Register the two types
+ import copy_reg
+ def pickle_BMS(so):
+ return _BMS,(so.match,so.translate)
+ def pickle_FS(so):
+ return _FS,(so.match,so.translate)
+ copy_reg.pickle(BMSType,
+ pickle_BMS,
+ _BMS)
+ copy_reg.pickle(FSType,
+ pickle_FS,
+ _FS)
+
+del modinit
diff --git a/intern/python/modules/TextTools/mxTextTools/__init__.py b/intern/python/modules/TextTools/mxTextTools/__init__.py
new file mode 100644
index 00000000000..009b7cbd4c7
--- /dev/null
+++ b/intern/python/modules/TextTools/mxTextTools/__init__.py
@@ -0,0 +1,17 @@
+""" mxTextTools - A tools package for fast text processing.
+
+ (c) Copyright Marc-Andre Lemburg; All Rights Reserved.
+ See the documentation for further information on copyrights,
+ or contact the author (mal@lemburg.com).
+"""
+from mxTextTools import *
+from mxTextTools import __version__
+
+#
+# Make BMS take the role of FS in case the Fast Search object was not built
+#
+try:
+ FS
+except NameError:
+ FS = BMS
+ FSType = BMSType
diff --git a/intern/python/modules/VRMLmain.py b/intern/python/modules/VRMLmain.py
new file mode 100644
index 00000000000..836c803269e
--- /dev/null
+++ b/intern/python/modules/VRMLmain.py
@@ -0,0 +1,3 @@
+# this file is the entry point for freeze.py
+
+from Converter import importloader
diff --git a/intern/python/modules/beta/Objects.py b/intern/python/modules/beta/Objects.py
new file mode 100644
index 00000000000..0ae56870fd6
--- /dev/null
+++ b/intern/python/modules/beta/Objects.py
@@ -0,0 +1,167 @@
+from Blender import Scene
+import Blender.NMesh as _NMesh
+import Blender.Material as Material
+
+
+defaultUV = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)]
+
+FACEFLAGS = _NMesh.Const
+DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC
+
+curface = None
+tessfaces = None
+
+def error():
+ pass
+def beginPolygon():
+ global curface
+ global tessfaces
+ curface = _NMesh.Face()
+def endPolygon():
+ global curface
+ global tessfaces
+ tessfaces.append(curface)
+def addVertex(v):
+ global curface
+ curface.v.append(v)
+ curface.uv.append((v.uvco[0], v.uvco[1]))
+
+class Face:
+ def __init__(self, vlist):
+ self.v= vlist
+ self.uv = []
+ self.mode = 0
+
+class shadow:
+ def __setattr__(self, name, val):
+ setattr(self.data, name, val)
+ def __getattr__(self, name):
+ return getattr(self.data, name)
+ def __repr__(self):
+ return repr(self.data)
+
+##########################################
+# replacement xMesh (NMesh shadow class)
+
+class shadowNVert: #shadow NMVert class for the tesselator
+ def __init__(self):
+ self.vert = None
+ self.uv = []
+ def __len__(self):
+ return 3
+ def __getitem__(self, i):
+ return self.vert.co[i]
+
+def Color(r, g, b, a = 1.0):
+ return _NMesh.Col(255 * r, 255 * g, 255 * b, 255 * a)
+
+class shadowNMesh:
+ def __init__(self, name = None, default_flags = None):
+ self.scene = Scene.getCurrent()
+ self.data = _NMesh.GetRaw()
+ self.name = name
+ if default_flags:
+ flags = default_flags
+ else:
+ flags = DEFAULTFLAGS
+ self.flags = flags
+ self.smooth = 0
+ self.faces = []
+ try:
+ import tess
+ self.tess = tess.Tess(256, beginPolygon, endPolygon, error, addVertex)
+ except:
+ #print "couldn't import tesselator"
+ self.tess = None
+ self.curface = None
+ self.tessfaces = []
+ self.recalc_normals = 1
+
+ def __del__(self):
+ del self.data
+
+ def __getattr__(self, name):
+ if name == 'vertices':
+ return self.data.verts
+ else:
+ return getattr(self.data, name)
+
+ def __repr__(self):
+ return "Mesh: %d faces, %d vertices" % (len(self.faces), len(self.verts))
+ def toNMFaces(self, ngon):
+ # This should be a Publisher only feature...once the tesselation
+ # is improved. The GLU tesselator of Mesa < 4.0 is crappy...
+ if not self.tess:
+ return [] # no faces converted
+ import tess
+ i = 0
+ global tessfaces
+ tessfaces = []
+ tess.beginPolygon(self.tess)
+ for v in ngon.v:
+ if len(ngon.uv) == len(ngon.v):
+ v.uvco = ngon.uv[i]
+ tess.vertex(self.tess, (v.co[0], v.co[1], v.co[2]), v)
+ i += 1
+ tess.endPolygon(self.tess)
+ return tessfaces
+
+ def hasFaceUV(self, true):
+ self.data.hasFaceUV(true)
+
+ def addVert(self, v):
+ vert = _NMesh.Vert(v[0], v[1], v[2])
+ self.data.verts.append(vert)
+ return vert
+
+ def addFace(self, vlist, flags = None, makedefaultUV = 0):
+ n = len(vlist)
+ if n > 4:
+ face = Face(vlist)
+ else:
+ face = _NMesh.Face()
+ for v in vlist:
+ face.v.append(v)
+ if makedefaultUV:
+ face.uv = defaultUV[:n]
+ self.faces.append(face)
+ # turn on default flags:
+ if not flags:
+ face.mode = self.flags
+ else:
+ face.mode = flags
+ return face
+
+ def write(self):
+ from Blender import Object
+ # new API style:
+ self.update()
+ ob = Object.New(Object.Types.MESH) # create object
+ ob.link(self.data) # link mesh data to it
+ self.scene.link(ob)
+ return ob
+
+ def update(self):
+ from Blender.Types import NMFaceType
+ smooth = self.smooth
+ for f in self.faces:
+ if type(f) == NMFaceType:
+ f.smooth = smooth
+ self.data.faces.append(f)
+ f.materialIndex = 0
+ else: #it's a NGON (shadow face)
+ faces = self.toNMFaces(f)
+ for nf in faces:
+ nf.smooth = smooth
+ nf.materialIndex = 0
+ self.data.faces.append(nf)
+
+ if not self.name:
+ self.name = "Mesh"
+
+ def assignMaterial(self, material):
+ self.data.materials = [material._object]
+
+Mesh = shadowNMesh
+Vert = shadowNVert
+
diff --git a/intern/python/modules/beta/Scenegraph.py b/intern/python/modules/beta/Scenegraph.py
new file mode 100644
index 00000000000..388beeb7b11
--- /dev/null
+++ b/intern/python/modules/beta/Scenegraph.py
@@ -0,0 +1,182 @@
+
+"""This is a basic scenegraph module for Blender
+It contains low level API calls..."""
+
+# (c) 2001, Martin Strubel // onk@section5.de
+
+from utils import quat #quaternions
+
+from Blender import Object, Lamp, Scene
+
+
+TOLERANCE = 0.01
+
+def uniform_scale(vec):
+ v0 = vec[0]
+ d = abs(vec[1] - v0)
+ if d > TOLERANCE:
+ return 0
+ d = abs(vec[2] - v0)
+ if d > TOLERANCE:
+ return 0
+ return v0
+
+class Transform:
+ """An abstract transform, containing translation, rotation and scale information"""
+ def __init__(self):
+ self.scale = (1.0, 1.0, 1.0)
+ self.translation = (0.0, 0.0, 0.0)
+ self.rotation = quat.Quat()
+ self.scaleOrientation = quat.Quat() # axis, angle
+ self.parent = None
+ def __mul__(self, other):
+ s = uniform_scale(self.scale)
+ if not s:
+ raise RuntimeError, "non uniform scale, can't multiply"
+ t = Transform()
+ sc = other.scale
+ t.scale = (s * sc[0], s * sc[1], s * sc[2])
+ t.rotation = self.rotation * other.rotation
+ tr = s * apply(quat.Vector, other.translation)
+ t.translation = self.rotation.asMatrix() * tr + self.translation
+ return t
+ def getLoc(self):
+ t = self.translation
+ return (t[0], t[1], t[2]) # make sure it's a tuple..silly blender
+ def calcRotfromAxis(self, axisrotation):
+ self.rotation = apply(quat.fromRotAxis,axisrotation)
+ def getRot(self):
+ return self.rotation.asEuler()
+ def getSize(self):
+ s = self.scale
+ return (s[0], s[1], s[2])
+ def __repr__(self):
+ return "Transform: rot: %s loc:%s" % (self.getRot(), self.getLoc())
+ def copy(self):
+ "returns copy of self"
+ t = Transform()
+ t.scale = self.scale
+ t.translation = self.translation
+ t.rotation = self.rotation
+ t.scaleOrientation = self.scaleOrientation
+ return t
+
+class BID:
+ "Blender named Object ID"
+ def __init__(self, name):
+ self.name = name
+ self.data = None
+
+class BScene:
+ def __init__(self, name = None):
+ from Blender import Scene
+ self.dict = {'Image': {}, 'Object':{}, 'Mesh' : {}}
+ self.name = name
+ def __getitem__(self, name):
+ return self.dict[name]
+ def __setitem__(self, name, val):
+ self.dict[name] = val
+ def has_key(self, name):
+ if self.dict.has_key(name):
+ return 1
+ else:
+ return 0
+ def getnewID(self, templ):
+ n = 0
+ name = templ
+ while self.dict.has_key(name):
+ n += 1
+ name = "%s.%03d" % (templ, n)
+ return name
+
+class BSGNode:
+ "Blender Scenegraph node"
+ isRoot = 0
+ def __init__(self, object = None, type = "", name = ""):
+ self.type = type
+ self.name = name
+ self.children = []
+ self.level = 0
+ self.object = object
+ def addChildren(self, children):
+ self.children += children
+ def traverse(self, visitor):
+ ret = visitor()
+ for c in self.children:
+ c.traverse(visitor)
+ return ret
+ def setDepth(self, level):
+ self.level = level
+ for c in self.children:
+ c.setDepth(level + 1)
+ def update(self):
+ ob.name = self.name
+ def __repr__(self):
+ l = self.level
+ children = ""
+ pre = l * ' '
+ return "\n%s%s [%s] ->%s" % (pre, self.name, self.type, self.children)
+
+class ObjectNode(BSGNode):
+ def __init__(self, object = None, type = "", name = ""):
+ self.transform = Transform()
+ self.scene = Scene.getCurrent()
+ BSGNode.__init__(self, object, type, name)
+ def makeParent(self, child):
+ self.child = parent
+ child.parent = self
+ def clone(self):
+ ob = self.object
+ newob = ob.copy()
+ self.scene.link(newob)
+ new = ObjectNode(newob)
+ new.transform = self.transform.copy()
+ return new
+ def insert(self, child):
+ self.children.append(child)
+ child.level = self.level + 1
+ ob = child.object
+ self.object.makeParent([ob], 1, 1)
+ # first parent, THEN set local transform
+ child.update()
+ def applyTransform(self, tf):
+ self.transform = tf * self.transform
+ def update(self):
+ ob = self.object
+ t = self.transform
+ ob.loc = t.getLoc()
+ ob.size = t.getSize()
+ ob.rot = t.getRot()
+ ob.name = self.name
+
+def NodefromData(ob, type, name):
+ new = ObjectNode(None, type, name)
+ if ob:
+ obj = ob
+ else:
+ obj = Object.New(type)
+ Scene.getCurrent().link(obj)
+ if not obj:
+ raise RuntimeError, "FATAL: could not create object"
+ new.object= obj
+ new.object.name = name
+ #new.fromData(ob)
+ return new
+
+class RootNode(ObjectNode):
+ """stupid simple scenegraph prototype"""
+ level = 0
+ isRoot = 1
+ type = 'Root'
+ name = 'ROOT'
+
+ def __init__(self, object = None, type = "", name = ""):
+ from Blender import Scene
+ self.transform = Transform()
+ BSGNode.__init__(self, object, type, name)
+ self.scene = Scene.getCurrent()
+ def insert(self, child):
+ child.update()
+ self.children.append(child)
+ def update(self):
+ self.scene.update()
diff --git a/intern/python/modules/beta/__init__.py b/intern/python/modules/beta/__init__.py
new file mode 100644
index 00000000000..4ceb9fd97a1
--- /dev/null
+++ b/intern/python/modules/beta/__init__.py
@@ -0,0 +1 @@
+__all__ = ["Scenegraph", "Objects"]
diff --git a/intern/python/modules/blenderos.py b/intern/python/modules/blenderos.py
new file mode 100644
index 00000000000..d093388d88f
--- /dev/null
+++ b/intern/python/modules/blenderos.py
@@ -0,0 +1,24 @@
+# This is the built in Blender emulation module for os.py
+# not all features are implemented yet...
+
+import Blender.sys as bsys
+
+sep = bsys.dirsep # path separator ('/' or '\')
+
+class Path:
+ def dirname(self, name):
+ return bsys.dirname(name)
+ def join(self, a, *p):
+ dirsep = bsys.dirsep
+ path = a
+ for b in p:
+ if b[:1] == dirsep:
+ path = b
+ elif path == '' or path[-1:] == dirsep:
+ path = path + b
+ else:
+ path = path + dirsep + b
+ return path
+
+path = Path()
+
diff --git a/intern/python/modules/mcf/__init__.py b/intern/python/modules/mcf/__init__.py
new file mode 100644
index 00000000000..a553f20ba1c
--- /dev/null
+++ b/intern/python/modules/mcf/__init__.py
@@ -0,0 +1,6 @@
+#mcf 'vendor' packages
+
+#These packages are free software, provided without warranty or
+#guarantee, if you use them, you must agree to use them at your
+#own risk. Please see the file license.txt for full license
+#details.
diff --git a/intern/python/modules/mcf/utils/__init__.py b/intern/python/modules/mcf/utils/__init__.py
new file mode 100644
index 00000000000..156e4dbe16b
--- /dev/null
+++ b/intern/python/modules/mcf/utils/__init__.py
@@ -0,0 +1,6 @@
+'''
+mcf.utils package
+
+
+'''
+
diff --git a/intern/python/modules/mcf/utils/collapse.py b/intern/python/modules/mcf/utils/collapse.py
new file mode 100644
index 00000000000..25da50c2adb
--- /dev/null
+++ b/intern/python/modules/mcf/utils/collapse.py
@@ -0,0 +1,169 @@
+'''
+Destructive Functions for "collapsing" Sequences into single levels
+
+>>> from mcf.utils import collapse
+
+>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]])
+
+[1, 2, 3, 4, 5, 6] # note that is the same root list
+
+>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]])
+
+[1, 2, 3, 4, 5, 6] # note is the same root list
+'''
+import copy, types, sys
+from types import ListType, TupleType # this now only supports the obsolete stuff...
+
+def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint):
+ '''
+ Destructively flatten a mixed hierarchy to a single level.
+ Non-recursive, many speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ expandable = 1
+ while expandable:
+ expandable = 0
+ if allowedmap.has_key( type(inlist[ind]) ):
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = list( inlist[ind])
+ expandable = 1
+
+ # alternately you could iterate through checking for isinstance on all possible
+ # classes, but that would be very slow
+ elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ):
+ # here figure out some way to generically expand that doesn't risk
+ # infinite loops...
+ templist = []
+ for x in inlist[ind]:
+ templist.append( x)
+ inlist[ind:ind+1] = templist
+ expandable = 1
+ except IndexError:
+ pass
+ return inlist
+
+
+def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ Further speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ while type(inlist[ind]) is ltype:
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = inlist[ind]
+ #ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse_safe(inlist):
+ '''
+ As collapse, but works on a copy of the inlist
+ '''
+ return collapse( inlist[:] )
+
+def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Will expand tuple children as well, but will fail if the
+ top level element is not a list.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ '''
+ ind = 0
+ try:
+ while 1:
+ while type(inlist[ind]) in ltype:
+ try:
+ inlist[ind:ind+1] = inlist[ind]
+ except TypeError:
+ inlist[ind:ind+1] = list(inlist[ind])
+ ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse2_safe(inlist):
+ '''
+ As collapse2, but works on a copy of the inlist
+ '''
+ return collapse( list(inlist) )
+
+def old_buggy_collapse(inlist):
+ '''Always return a one-level list of all the non-list elements in listin,
+ rewritten to be non-recursive 96-12-28 Note that the new versions work
+ on the original list, not a copy of the original.'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) == ListType:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) == ListType:
+ x = x - 1 # need to collapse that list...
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened
+ else:
+ inlist[x:x+1]=y
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def old_buggy_collapse2(inlist):
+ '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) in [ListType, TupleType]:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) in [ListType,TupleType]:
+ x = x-1 #(to deal with that element)
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened, will raise exception with tuples...
+ else:
+ inlist[x:x+1]=list(y)
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def oldest_buggy_collapse(listin):
+ 'Always return a one-level list of all the non-list elements in listin'
+ if type(listin) == ListType:
+ return reduce(lambda x,y: x+y, map(collapse, listin), [])
+ else: return [listin]
+
+def oldest_buggy_collapse2(seqin):
+
+ if type(seqin) in [ListType, TupleType]:
+ return reduce(lambda x,y: x+y, map(collapse2, seqin), [])
+ else:
+ return [seqin]
+
diff --git a/intern/python/modules/mcf/utils/copy_extend.py b/intern/python/modules/mcf/utils/copy_extend.py
new file mode 100644
index 00000000000..687564cf12c
--- /dev/null
+++ b/intern/python/modules/mcf/utils/copy_extend.py
@@ -0,0 +1,83 @@
+'''
+Module to allow for "copying" Numeric arrays,
+(and thereby also matrices and userarrays)
+standard arrays, classes and modules
+(last two are not actually copied, but hey :) ).
+
+Could do approximately the same thing with
+copy_reg, but would be inefficient because
+of passing the data into and out of strings.
+
+To use, just import this module.
+'''
+# altered 98.11.05, moved copy out of NUMPY test
+import copy
+try: # in case numpy not installed
+ import Numeric
+ def _numpyarray_copy(somearray, memo=None):
+ '''
+ Simple function for getting a copy of a NUMPY array
+ '''
+ if memo == None:
+ memo = {} # yeah, I know, not _really_ necessary
+ # see if already done this item, return the copy if we have...
+ d = id(somearray)
+ try:
+ return memo[d]
+ except KeyError:
+ pass
+ temp = Numeric.array(somearray, copy=1)
+ memo[d] = temp
+ return temp
+ # now make it available to the copying functions
+ copy._copy_dispatch[Numeric.ArrayType] = _numpyarray_copy
+ copy._deepcopy_dispatch[Numeric.ArrayType] = _numpyarray_copy
+except ImportError: # Numeric not installed...
+ pass
+
+try: # in case array not installed
+ import array
+ def _array_copy(somearray, memo = None):
+ '''
+ Simple function for getting a copy of a standard array.
+ '''
+ if memo == None:
+ memo = {} # yeah, I know, not _really_ necessary
+ # see if already done this item, return the copy if we have...
+ d = id(somearray)
+ try:
+ return memo[d]
+ except KeyError:
+ pass
+ newarray = somearay[:]
+ memo[d] = newarray
+ return newarray
+
+ # now make it available to the copying functions
+ copy._copy_dispatch[ array.ArrayType ] = _array_copy
+ copy._deepcopy_dispatch[ array.ArrayType ] = _array_copy
+except ImportError:
+ pass
+
+import types
+
+def _module_copy(somemodule, memo = None):
+ '''
+ Modules we will always treat as themselves during copying???
+ '''
+ return somemodule
+
+# now make it available to the copying functions
+copy._copy_dispatch[ types.ModuleType ] = _module_copy
+copy._deepcopy_dispatch[ types.ModuleType ] = _module_copy
+
+def _class_copy(someclass, memo=None):
+ '''
+ Again, classes are considered immutable, they are
+ just returned as themselves, not as new objects.
+ '''
+ return someclass
+
+# now make it available to the copying functions
+#copy._copy_dispatch[ types.ClassType ] = _class_copy
+copy._deepcopy_dispatch[ types.ClassType ] = _class_copy
diff --git a/intern/python/modules/mcf/utils/cpickle_extend.py b/intern/python/modules/mcf/utils/cpickle_extend.py
new file mode 100644
index 00000000000..aaca41d51fb
--- /dev/null
+++ b/intern/python/modules/mcf/utils/cpickle_extend.py
@@ -0,0 +1,190 @@
+'''
+Extend cpickle storage to include modules, and builtin functions/methods
+
+To use, just import this module.
+'''
+import copy_reg
+
+### OBJECTS WHICH ARE RESTORED THROUGH IMPORTS
+# MODULES
+def pickle_module(module):
+ '''
+ Store a module to a pickling stream, must be available for
+ reimport during unpickling
+ '''
+ return unpickle_imported_code, ('import %s'%module.__name__, module.__name__)
+
+# FUNCTIONS, METHODS (BUILTIN)
+def pickle_imported_code(funcmeth):
+ '''
+ Store a reference to an imported element (such as a function/builtin function,
+ Must be available for reimport during unpickling.
+ '''
+ module = _whichmodule(funcmeth)
+ return unpickle_imported_code, ('from %s import %s'%(module.__name__,funcmeth.__name__),funcmeth.__name__)
+
+import types, regex
+import_filter = regex.compile('''\(from [A-Za-z0-9_\.]+ \)?import [A-Za-z0-9_\.]+''') # note the limitations on whitespace
+getattr_filter = regex.compile('''[A-Za-z0-9_\.]+''') # note we allow you to use x.y.z here
+
+# MODULES, AND FUNCTIONS
+def unpickle_imported_code(impstr,impname):
+ '''
+ Attempt to load a reference to a module or other imported code (such as functions/builtin functions)
+ '''
+ if import_filter.match(impstr) != len(impstr) or getattr_filter.match(impname)!= len(impname):
+ import sys
+ sys.stderr.write('''Possible attempt to smuggle arbitrary code into pickle file (see module cpickle_extend).\nPassed code was %s\n%s\n'''%(impstr,impname))
+ del(sys)
+ else:
+ ns = {}
+ try:
+ exec (impstr) in ns # could raise all sorts of errors, of course, and is still dangerous when you have no control over the modules on your system! Do not allow for untrusted code!!!
+ return eval(impname, ns)
+ except:
+ import sys
+ sys.stderr.write('''Error unpickling module %s\n None returned, will likely raise errors.'''%impstr)
+ return None
+
+# Modules
+copy_reg.pickle(type(regex),pickle_module,unpickle_imported_code)
+# builtin functions/methods
+copy_reg.pickle(type(regex.compile),pickle_imported_code, unpickle_imported_code)
+
+del(regex) # to keep the namespace neat as possible
+
+### INSTANCE METHODS
+'''
+The problem with instance methods is that they are almost always
+stored inside a class somewhere. We really need a new type: reference
+that lets us just say "y.this"
+
+We also need something that can reliably find burried functions :( not
+likely to be easy or clean...
+
+then filter for x is part of the set
+'''
+import new
+
+def pickle_instance_method(imeth):
+ '''
+ Use the (rather surprisingly clean) internals of
+ the method to store a reference to a method. Might
+ be better to use a more general "get the attribute
+ 'x' of this object" system, but I haven't written that yet :)
+ '''
+ klass = imeth.im_class
+ funcimp = _imp_meth(imeth)
+ self = imeth.im_self # will be None for UnboundMethodType
+ return unpickle_instance_method, (funcimp,self,klass)
+def unpickle_instance_method(funcimp,self,klass):
+ '''
+ Attempt to restore a reference to an instance method,
+ the instance has already been recreated by the system
+ as self, so we just call new.instancemethod
+ '''
+ funcimp = apply(unpickle_imported_code, funcimp)
+ return new.instancemethod(func,self,klass)
+
+copy_reg.pickle(types.MethodType, pickle_instance_method, unpickle_instance_method)
+copy_reg.pickle(types.UnboundMethodType, pickle_instance_method, unpickle_instance_method)
+
+### Arrays
+try:
+ import array
+ LittleEndian = array.array('i',[1]).tostring()[0] == '\001'
+ def pickle_array(somearray):
+ '''
+ Store a standard array object, inefficient because of copying to string
+ '''
+ return unpickle_array, (somearray.typecode, somearray.tostring(), LittleEndian)
+ def unpickle_array(typecode, stringrep, origendian):
+ '''
+ Restore a standard array object
+ '''
+ newarray = array.array(typecode)
+ newarray.fromstring(stringrep)
+ # floats are always big-endian, single byte elements don't need swapping
+ if origendian != LittleEndian and typecode in ('I','i','h','H'):
+ newarray.byteswap()
+ return newarray
+ copy_reg.pickle(array.ArrayType, pickle_array, unpickle_array)
+except ImportError: # no arrays
+ pass
+
+### NUMPY Arrays
+try:
+ import Numeric
+ LittleEndian = Numeric.array([1],'i').tostring()[0] == '\001'
+ def pickle_numpyarray(somearray):
+ '''
+ Store a numpy array, inefficent, but should work with cPickle
+ '''
+ return unpickle_numpyarray, (somearray.typecode(), somearray.shape, somearray.tostring(), LittleEndian)
+ def unpickle_numpyarray(typecode, shape, stringval, origendian):
+ '''
+ Restore a numpy array
+ '''
+ newarray = Numeric.fromstring(stringval, typecode)
+ Numeric.reshape(newarray, shape)
+ if origendian != LittleEndian and typecode in ('I','i','h','H'):
+ # this doesn't seem to work correctly, what's byteswapped doing???
+ return newarray.byteswapped()
+ else:
+ return newarray
+ copy_reg.pickle(Numeric.ArrayType, pickle_numpyarray, unpickle_numpyarray)
+except ImportError:
+ pass
+
+### UTILITY FUNCTIONS
+classmap = {}
+def _whichmodule(cls):
+ """Figure out the module in which an imported_code object occurs.
+ Search sys.modules for the module.
+ Cache in classmap.
+ Return a module name.
+ If the class cannot be found, return __main__.
+ Copied here from the standard pickle distribution
+ to prevent another import
+ """
+ if classmap.has_key(cls):
+ return classmap[cls]
+ clsname = cls.__name__
+ for name, module in sys.modules.items():
+ if name != '__main__' and \
+ hasattr(module, clsname) and \
+ getattr(module, clsname) is cls:
+ break
+ else:
+ name = '__main__'
+ classmap[cls] = name
+ return name
+
+import os, string, sys
+
+def _imp_meth(im):
+ '''
+ One-level deep recursion on finding methods, i.e. we can
+ find them only if the class is at the top level.
+ '''
+ fname = im.im_func.func_code.co_filename
+ tail = os.path.splitext(os.path.split(fname)[1])[0]
+ ourkeys = sys.modules.keys()
+ possibles = filter(lambda x,tail=tail: x[-1] == tail, map(string.split, ourkeys, ['.']*len(ourkeys)))
+
+ # now, iterate through possibles to find the correct class/function
+ possibles = map(string.join, possibles, ['.']*len(possibles))
+ imp_string = _search_modules(possibles, im.im_func)
+ return imp_string
+
+def _search_modules(possibles, im_func):
+ for our_mod_name in possibles:
+ our_mod = sys.modules[our_mod_name]
+ if hasattr(our_mod, im_func.__name__) and getattr(our_mod, im_func.__name__).im_func is im_func:
+ return 'from %s import %s'%(our_mod.__name__, im_func.__name__), im_func.__name__
+ for key,val in our_mod.__dict__.items():
+ if hasattr(val, im_func.__name__) and getattr(val, im_func.__name__).im_func is im_func:
+ return 'from %s import %s'%(our_mod.__name__,key), '%s.%s'%(key,im_func.__name__)
+ raise '''No import string calculable for %s'''%im_func
+
+
diff --git a/intern/python/modules/mcf/utils/dictbool.py b/intern/python/modules/mcf/utils/dictbool.py
new file mode 100644
index 00000000000..cd549b7a681
--- /dev/null
+++ b/intern/python/modules/mcf/utils/dictbool.py
@@ -0,0 +1,80 @@
+'''
+DictBool:
+Simplistic (and slow) implementation of Boolean operations for
+dictionaries... really these should be implemented in C, but I
+can't do that till I have MSVC++, which I don't really want to
+buy... this will have to do in the meantime.
+
+>>> from mcf.utils import dictbool
+
+>>> a = {1:2}; b = {2:3}; c={4:5,6:7,8:9,1:5}
+
+>>> dictbool.union(a,b,c) # overwrite a with b and the result with c
+
+{1: 5, 2: 3, 4: 5, 8: 9, 6: 7}
+
+>>> dictbool.collectunion(a,b,c) # collect all possible for each key
+
+{1: [2, 5], 2: [3], 4: [5], 8: [9], 6: [7]}
+
+>>> dictbool.intersect(a,b,c) # no common elements in all three
+
+{}
+
+>>> dictbool.intersect(a,c) # one element is common to both
+
+{1: [2, 5]}
+'''
+
+def union(*args):
+ '''
+ Build a new dictionary with the key,val from all args,
+ first overwritten by second, overwritten by third etc.
+ Rewritten for Python 1.5 on 98.03.31
+ '''
+ temp = {}
+ for adict in args:
+ # following is the 1.5 version
+ temp.update(adict)
+# for key,val in adict.items():
+# temp[key] = val
+ return temp
+
+def collectunion(*args):
+ '''
+ As union, save instead of overwriting, all vals are
+ returned in lists, and duplicates are appended to those
+ lists.
+ '''
+ temp = {}
+ for adict in args:
+ for key,val in adict.items():
+ try:
+ temp[key].append(val)
+ except KeyError:
+ temp[key] = [val]
+ return temp
+
+def intersect(*args):
+ '''
+ Build a new dictionary with those keys common to all args,
+ the vals of the new dict are lists of length len(args), where
+ list[ind] is the value of args[ind] for that key.
+ '''
+ args = map(lambda x: (len(x),x), args)
+ args.sort()
+ temp = {}
+ master = args[0][1]
+ rest = map(lambda x: x[1], args[1:])
+ for var,val in master.items():
+ tempval = [val]
+ for slave in rest:
+ try:
+ tempval.append(slave[var])
+ except KeyError:
+ tempval = None
+ break
+ if tempval:
+ temp[var] = tempval
+ return temp
+
diff --git a/intern/python/modules/mcf/utils/dsort.py b/intern/python/modules/mcf/utils/dsort.py
new file mode 100644
index 00000000000..cd6ad6b6c32
--- /dev/null
+++ b/intern/python/modules/mcf/utils/dsort.py
@@ -0,0 +1,91 @@
+nullval = (1,)
+
+class DSort:
+ '''
+ A "dependency" sorting class, used to order elements
+ according to declared "dependencies" (many-to-one relationships)
+ Is not a beautiful algo, but it works (or seems to)
+ Requires hashable values for all elements.
+
+ This is a quick hack, use at your own risk!
+
+ Basic usage:
+ Create a DSort mysorter
+ for each element q which is part of the set to sort, call:
+ mysorter.rule( dsort.nullval, q)
+ # this is not strictly necessary for elements which are
+ # dependent on other objects, but it is necessary for
+ # those which are not. Generally it's easiest to call
+ # the null rule for each element.
+ for each rule x depends on y, call:
+ mysorter.rule( x, y)
+ when _all_ rules are entered, call
+ try:
+ sortedlist = mysorter.sort()
+ except ValueError:
+ handle recursive dependencies here...
+
+
+ For an example of real-life use, see the VRML lineariser.
+
+ '''
+ def __init__(self, recurseError=None ):
+ self.dependon = {nullval:[0]}
+ self.recurseError = recurseError
+ def rule( self, depon, deps):
+ '''
+ Register a "rule". Both elements must be hashable values.
+ See the class' documentation for usage.
+ '''
+# print '''registering rule:''', depon, deps
+ if self.dependon.has_key( deps ) and depon is not nullval:
+ self.dependon[ deps ].append( depon )
+ elif depon is not nullval:
+ self.dependon[ deps ] = [-1, depon]
+ elif not self.dependon.has_key( deps ):
+ self.dependon[ deps ] = [-1 ]
+ def sort( self ):
+ '''
+ Get the sorted results as a list
+ '''
+ for key, value in self.dependon.items():
+ self._dsort( key, value)
+ temp = []
+ for key, value in self.dependon.items():
+ temp.append( (value[0], key) )
+ temp.sort()
+ temp.reverse()
+ temp2 = []
+ for x,y in temp:
+ temp2.append( y )
+ # following adds the elements with no dependencies
+ temp2[len(temp2):] = self.dependon[ nullval ][1:]
+ return temp2
+ def _dsort( self, key, value ):
+ if value[0] == -2:
+ if self.recurseError:
+ raise ValueError, '''Dependencies were recursive!'''
+ else:
+ if __debug__:
+ print '''Recursive dependency discovered and ignored in dsort.Dsort._dsort on %s:%s'''%(key, value)
+ return 1 # we know it has at least one reference...
+ elif value[0] == -1: # haven't yet calculated this rdepth
+ value[0] = -2
+ tempval = [0]
+ for x in value[1:]:
+ try:
+ tempval.append( 1 + self._dsort( x, self.dependon[x]) )
+ except KeyError:
+ self.dependon[ nullval ].append( x ) # is an unreferenced element
+ tempval.append( 1 )
+ value[0] = max( tempval )
+ return value[0]
+ else:
+ return value[0]
+'''
+from mcf.utils import dsort
+>>> x = dsort.DSort()
+>>> map( x.rule, [1,2,2,4,5,4], [2,3,4,5,6,3] )
+[None, None, None, None, None, None]
+>>> x.sort()
+''' \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/dummy.py b/intern/python/modules/mcf/utils/dummy.py
new file mode 100644
index 00000000000..fb68c4049bf
--- /dev/null
+++ b/intern/python/modules/mcf/utils/dummy.py
@@ -0,0 +1,91 @@
+'''
+Dummy Class, intended as an abstract class for the creation
+of base/builtin classes with slightly altered functionality
+uses _base as the name of an instance of the base datatype,
+mapping all special functions to that name.
+
+>>> from mcf.utils import dummy
+
+>>> j = dummy.Dummy({})
+
+>>> j['this'] = 23
+
+>>> j
+
+{'this': 23}
+
+>>> class example(dummy.Dummy):
+
+... def __repr__(self):
+
+... return '<example: %s>'%`self._base`
+
+>>> k = example([])
+
+>>> k # uses the __repr__ function
+
+<example: []>
+
+>>> k.append # finds the attribute of the _base
+
+<built-in method append of list object at 501830>
+
+'''
+import types, copy
+
+class Dummy:
+ 'Abstract class for slightly altering functionality of objects (including builtins)'
+ def __init__(self, val=None):
+ 'Initialisation, should be overridden'
+ if val and type(val)== types.InstanceType and hasattr(val, '_base'):
+ # Dict is used because subclasses often want to override
+ # the setattr function
+ self.__dict__['_base']=copy.copy(val.__dict__['_base'])
+ else:
+ self.__dict__['_base'] = val
+ def __repr__(self):
+ 'Return a string representation'
+ return repr(self._base)
+ def __str__(self):
+ 'Convert to a string'
+ return str(self._base)
+ def __cmp__(self,other):
+ 'Compare to other value'
+ # altered 98.03.17 from if...elif...else statement
+ return cmp(self._base, other)
+ def __getitem__(self, key):
+ 'Get an item by index'
+ return self._base[key]
+ def __setitem__(self, key, val):
+ 'Set an item by index'
+ self._base[key]=val
+ def __len__(self):
+ 'return the length of the self'
+ return len(self._base)
+ def __delitem__(self, key):
+ 'remove an item by index'
+ del(self._base[key])
+ def __getslice__(self, i, j):
+ 'retrieve a slice by indexes'
+ return self._base[i:j]
+ def __setslice__(self, i, j, val):
+ 'set a slice by indexes to values'
+ self._base[i:j]=val
+ def __delslice__(self, i, j):
+ 'remove a slice by indexes'
+ del(self._base[i:j])
+ def __nonzero__(self):
+ if self._base:
+ return 1
+ else:
+ return 0
+ def __getattr__(self, attr):
+ 'find an attribute when normal lookup fails, will raise a KeyError if missing _base attribute'
+ try:
+ return getattr( self.__dict__['_base'], attr)
+ except (AttributeError, KeyError):
+ try:
+ return self.__dict__['_base'][attr]
+ except (KeyError,TypeError):
+ pass
+ raise AttributeError, attr
diff --git a/intern/python/modules/mcf/utils/err.py b/intern/python/modules/mcf/utils/err.py
new file mode 100644
index 00000000000..3c6591a6873
--- /dev/null
+++ b/intern/python/modules/mcf/utils/err.py
@@ -0,0 +1,37 @@
+'''
+err.py Encapsulated writing to sys.stderr
+
+The idea of this module is that, for a GUI system (or a more advanced UI),
+you can just import a different err module (or object) and keep
+your code the same. (For instance, you often want a status window
+which flashes warnings and info, and have error messages pop up an
+alert to get immediate attention.
+'''
+
+import sys
+
+def err(message, Code=0):
+ '''
+ report an error, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Error #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Error: %s\n'%message)
+def warn(message, Code=0):
+ '''
+ report a warning, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Warning #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Warning: %s\n'%message)
+def info(message, Code=0):
+ '''
+ report information/status, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Info #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Info: %s\n'%message)
+
diff --git a/intern/python/modules/mcf/utils/extpkl.py b/intern/python/modules/mcf/utils/extpkl.py
new file mode 100644
index 00000000000..8ae52969281
--- /dev/null
+++ b/intern/python/modules/mcf/utils/extpkl.py
@@ -0,0 +1,19 @@
+'''
+Make either cPickle or pickle available as the virtual
+module mcf.utils.pickle. This allows you to use a single
+import statement:
+
+ from mcf.utils import extpkl, pickle
+
+and then use that pickle, knowing that you have the best
+available pickling engine.
+'''
+defaultset = ('import cPickle', 'cPickle')
+import sys, mcf.utils
+from mcf.utils import cpickle_extend
+try:
+ import cPickle
+ pickle = cPickle
+except:
+ import pickle
+sys.modules['mcf.utils.pickle'] = mcf.utils.pickle = pickle
diff --git a/intern/python/modules/mcf/utils/fileassociation.py b/intern/python/modules/mcf/utils/fileassociation.py
new file mode 100644
index 00000000000..55fd9735bfb
--- /dev/null
+++ b/intern/python/modules/mcf/utils/fileassociation.py
@@ -0,0 +1,65 @@
+### WARNING:
+# I don't have a clue what I'm doing here!
+
+import win32api
+### Following is the "normal" approach,
+### but it requires loading the entire win32con file (which is big)
+### for two values...
+##import win32con
+##HKEY_CLASSES_ROOT = win32con.HKEY_CLASSES_ROOT
+##REG_SZ = win32con.REG_SZ
+
+### These are the hard-coded values, should work everywhere as far as I know...
+HKEY_CLASSES_ROOT = 0x80000000
+REG_SZ= 1
+
+def associate( extension, filetype, description="", commands=(), iconfile="" ):
+ '''Warning: I don't have a clue what I'm doing here!
+ extension -- extension including "." character, e.g. .proc
+ filetype -- formal name, no spaces allowed, e.g. SkeletonBuilder.RulesFile
+ description -- human-readable description of the file type
+ commands -- sequence of (command, commandline), e.g. (("Open", "someexe.exe %1"),)
+ iconfile -- optional default icon file for the filetype
+ '''
+ win32api.RegSetValue(
+ HKEY_CLASSES_ROOT,
+ extension,
+ REG_SZ,
+ filetype
+ )
+ if description:
+ win32api.RegSetValue(
+ HKEY_CLASSES_ROOT ,
+ filetype,
+ REG_SZ,
+ description
+ )
+ if iconfile:
+ win32api.RegSetValue(
+ HKEY_CLASSES_ROOT ,
+ "%(filetype)s\\DefaultIcon" % locals(),
+ REG_SZ,
+ iconfile
+ )
+ for (command, commandline) in commands:
+ win32api.RegSetValue(
+ HKEY_CLASSES_ROOT ,
+ "%(filetype)s\\Shell\\%(command)s" % locals(),
+ REG_SZ,
+ command,
+ )
+ win32api.RegSetValue(
+ HKEY_CLASSES_ROOT ,
+ "%(filetype)s\\Shell\\%(command)s\\Command" % locals(),
+ REG_SZ,
+ commandline
+ )
+
+if __name__ == "__main__":
+ associate(
+ ".proc",
+ "SkeletonBuilder.Processing",
+ "SkeletonBuilder Processing File",
+ (("Open", '''z:\\skeletonbuilder\\skeletonbuilder.exe "%1" %*'''),),
+ '''z:\\skeletonbuilder\\bitmaps\\skeletonbuildericon.ico''',
+ ) \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/findourfile.py b/intern/python/modules/mcf/utils/findourfile.py
new file mode 100644
index 00000000000..1c70ff0dd70
--- /dev/null
+++ b/intern/python/modules/mcf/utils/findourfile.py
@@ -0,0 +1,30 @@
+'''
+This utility allows a python system to find a file in it's
+directory. To do this, you need to pass it a function object from
+a module in the correct directory. I know there must be a better
+way to do this, but I haven't seen it yet. Incidentally, the
+current directory should be _different_ from the module in which
+the function is contained, otherwise this function will go off into
+the root directory.
+
+Currently this has to be called with the current directory a directory
+other than the directory we're trying to find... need a better solution
+for this kind of thing... a python registry would be great :)
+
+NOTE: as of Python 1.5, this module should be obsolete! As soon as I
+have verified that all of my code is fixed, it will be moved to the unused
+directories.
+'''
+import os,sys
+
+def findourfile(function, filename):
+ '''
+ Given the function, return a path to the a file in the
+ same directory with 'filename'. We also let the caller
+ know if the file already exists.
+ '''
+ ourfilename = os.path.split(function.func_code.co_filename)[0]+os.sep+filename
+ exists = os.path.exists(ourfilename)
+ return (exists,ourfilename)
+
+
diff --git a/intern/python/modules/mcf/utils/hier_rx.py b/intern/python/modules/mcf/utils/hier_rx.py
new file mode 100644
index 00000000000..3770f0bab22
--- /dev/null
+++ b/intern/python/modules/mcf/utils/hier_rx.py
@@ -0,0 +1,201 @@
+'''
+Simple Hierarchic Walking functions for use with hierobj-type objects.
+
+Provide for recurse-safe processing. Currently only provide depth-first
+processing, and don't provide means for ignoring branches of the tree
+during processing. For an example of breadth-first processing, see
+mcf.pars.int.index.indutils. For more complex hierarchic processing,
+see the mcf.walker package.
+
+Originally these functions were only methods of the hierobj class (they
+still are methods of it). I've split them out to allow them to be
+imported selectively by other classes (some classes will only want
+the simple walking functions, and not want to be bothered with the
+methods which hierobj uses to keep track of its particular internal
+structures.
+'''
+
+def hier_rapply(self, function,arglist=None,argdict={},moreattr = '__childlist__'):
+ '''
+ Safely apply a function to self and all children for
+ the function's side effects. Discard the return values
+ that function returns.
+
+ function
+ function to apply
+ arglist
+ (self,)+arglist is the set of arguments passed to function
+ argdict
+ passed as namedargs to the function
+ moreattr
+ the attribute representing the children of a node
+ '''
+ alreadydone = {}
+ tobedone = [self]
+ if arglist or argdict:
+ if not arglist: arglist=[self]
+ else:
+ arglist.insert(0,self) # we could insert anything... self is convenient
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ arglist[0]=object
+ apply(function,tuple(arglist),argdict)
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+ else: # no arglist or argdict
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ function(object)
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+def hier_rreturn(self, function,arglist=None,argdict={},moreattr = '__childlist__'):
+ '''
+ Safely apply a function to self and all children,
+ collect the results in a list and return.
+
+ function
+ function to apply
+ arglist
+ (self,)+arglist is the set of arguments passed to function
+ argdict
+ passed as namedargs to the function
+ moreattr
+ the attribute representing the children of a node
+ '''
+ alreadydone = {}
+ tobedone = [self]
+ results = []
+ if arglist or argdict:
+ if not arglist: arglist=[self]
+ else:
+ arglist.insert(0,self) # or anything you feel like
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ arglist[0]=object
+ results.append(apply(function,tuple(arglist),argdict))
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+ else:
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ results.append(function(object))
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+ return results
+def hier_rgetattr(self, attrname, multiple=1, moreattr = '__childlist__'):
+ '''
+ Recursively collect the values for attrname and
+ return as a list.
+
+ attrname
+ attribute to collect
+ arglist
+ (self,)+arglist is the set of arguments passed to function
+ argdict
+ passed as namedargs to the function
+ moreattr
+ the attribute representing the children of a node
+ '''
+ alreadydone = {}
+ tobedone = [self]
+ results = []
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ try:
+ if multiple:
+ results.append(getattr(object, attrname))
+ else:
+ return getattr(object, attrname)
+ except AttributeError:
+ pass
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+ return results
+def hier_rmethod(self, methodname,arglist=(),argdict={},moreattr = '__childlist__'):
+ '''
+ return the result of calling every object's method methodname,
+ as for hier_rreturn otherwise.
+
+ methodname
+ method to call
+ arglist
+ (self,)+arglist is the set of arguments passed to function
+ argdict
+ passed as namedargs to the function
+ moreattr
+ the attribute representing the children of a node
+ '''
+
+ alreadydone = {}
+ tobedone = [self]
+ results = []
+ while tobedone:
+ object = tobedone[0]
+ try:
+ alreadydone[id(object)]
+ # We've already processed this object
+ except KeyError:
+ # We haven't processed this object
+ alreadydone[id(object)]=1
+ try:
+ results.append(apply(getattr(object,methodname),arglist,argdict))
+ except:
+ pass
+ try:
+ tobedone[1:1]=getattr(object,moreattr)
+ except AttributeError:
+ # if the object isn't a hierobj, we don't need to recurse into it.
+ pass
+ del(tobedone[0])
+ return results
+
diff --git a/intern/python/modules/mcf/utils/hierdummy.py b/intern/python/modules/mcf/utils/hierdummy.py
new file mode 100644
index 00000000000..0cf86e9e0c0
--- /dev/null
+++ b/intern/python/modules/mcf/utils/hierdummy.py
@@ -0,0 +1,16 @@
+'''
+Hierarchic 'Dummy' objects
+'''
+
+import hierobj, dummy
+
+class HierobjDummy(hierobj.Hierobj,dummy.Dummy):
+ '''
+ An Hierarchic Dummy object, which provides direct access to its
+ children through object[x] interfaces, allows "index" "count"
+ etceteras by returning the corresponding attributes of the _base.
+ '''
+ def __init__(self, parent=None, childlist=None):
+ hierobj.Hierobj.__init__(self, parent, childlist)
+ self._base = self.__childlist__ #set by init function above
+
diff --git a/intern/python/modules/mcf/utils/hierobj.py b/intern/python/modules/mcf/utils/hierobj.py
new file mode 100644
index 00000000000..7730b4d3ba4
--- /dev/null
+++ b/intern/python/modules/mcf/utils/hierobj.py
@@ -0,0 +1,133 @@
+'''
+Generic Hierarchic Objects Module
+Hierobj's store their children (which can be anything) in their
+__childlist__ attribute, and provide methods for walking the
+hierarchy, either collecting results or not.
+
+The index function returns an index of the objects (effectively a
+flattened copy of the hierarchy)
+
+97-03-17 Added ability to pass arguments to hier_rapply and hier_rreturn.
+97-10-31 Removed dependencies on mcf.store
+'''
+import copy,types
+import singletonlist, hier_rx
+
+class Hierobj:
+ '''
+ An abstract class which handles hierarchic functions and information
+ # remade as a DAG 97-04-02, also reduced memory overhead for
+ hier-r* functions by using while-del-IndexError construct versus
+ for loop (probably makes it slower though)
+ If you require a true hierarchy, use the TrueHierobj class below...
+ '''
+ def __init__(self, parent=None, childlist=None):
+ if parent is None: # passed no parents
+ self.__dict__['__parent__'] = []
+ elif type(parent) == types.ListType: # passed a list of parents
+ self.__dict__['__parent__'] = parent
+ else: # passed a single parent
+ self.__dict__['__parent__'] = [parent]
+ self.__dict__['__childlist__'] = childlist or []
+ for child in self.__childlist__:
+ try:
+ child.__parent__.append(self)
+ except:
+ pass
+ # import simple hierarchic processing methods
+ hier_rapply = hier_rx.hier_rapply
+ hier_rreturn = hier_rx.hier_rreturn
+ hier_rgetattr = hier_rx.hier_rgetattr
+ hier_rmethod = hier_rx.hier_rmethod
+
+
+ def hier_addchild(self, child):
+ '''
+ Add a single child to the childlist
+ '''
+ self.__childlist__.append(child)
+ try:
+ # Hierobj-aware child
+ child.__parent__.append(self) # raises error if not hier_obj aware
+ except (TypeError, AttributeError):
+ # Non Hierobj-aware child
+ pass
+ append = hier_addchild
+ def hier_remchild(self, child):
+ '''
+ Breaks the child relationship with child, including the
+ reciprocal parent relationship
+ '''
+ try:
+ self.__childlist__.remove(child)
+ try:
+ child.hier_remparent(self) # if this fails, no problem
+ except AttributeError: pass
+ except (AttributeError,ValueError):
+ return 0 # didn't manage to remove the child
+ return 1 # succeeded
+ def hier_remparent(self, parent):
+ '''
+ Normally only called by hier_remchild of the parent,
+ just removes the parent from the child's parent list,
+ but leaves child in parent's childlist
+ '''
+ try:
+ self.__parent__.remove(parent)
+ except (AttributeError,ValueError):
+ return 0
+ return 1
+ def hier_replacewith(self,newel):
+ '''
+ As far as the hierarchy is concerned, the new element
+ is exactly the same as the old element, it has all
+ the same children, all the same parents. The old
+ element becomes completely disconnected from the hierarchy,
+ but it still retains all of its references
+
+ For every parent, replace this as a child
+ For every child, replace this as the parent
+ '''
+ for parent in self.__parent__:
+ try:
+ parent.hier_replacechild(self, newel)
+ except AttributeError:
+ pass
+ for child in self.__childlist__:
+ try:
+ child.hier_replaceparent(self,parent)
+ except AttributeError:
+ pass
+ def hier_replaceparent(self, oldparent, newparent):
+ ind = self.__parent__.index(oldparent)
+ self.__parent__[ind] = newparent
+ def hier_replacechild(self, oldchild, newchild):
+ ind = self.__childlist__.index(oldchild)
+ self.__childlist__[ind] = newchild
+
+class TrueHierobj(Hierobj):
+ '''
+ An inefficient implementation of an Hierobj which limits the
+ __parent__ attribute to a single element. This will likely be
+ _slower_ than an equivalent Hierobj. That will have to be fixed
+ eventually.
+ '''
+ def __init__(self, parent=None, childlist=[]):
+ if parent is None: # passed no parents
+ self.__dict__['__parent__'] = singletonlist.SingletonList()
+ else: # passed a single parent
+ self.__dict__['__parent__'] = singletonlist.SingletonList(parent)
+ self.__dict__['__childlist__'] = copy.copy(childlist)
+ for child in self.__childlist__:
+ try:
+ child.__parent__.append(self)
+ except:
+ pass
+
+def index(grove):
+ '''
+ Returns a flattened version of the grove
+ '''
+ return grove.hier_rreturn(lambda x: x)
+
+
diff --git a/intern/python/modules/mcf/utils/in_place_ops.py b/intern/python/modules/mcf/utils/in_place_ops.py
new file mode 100644
index 00000000000..7d64f196597
--- /dev/null
+++ b/intern/python/modules/mcf/utils/in_place_ops.py
@@ -0,0 +1,38 @@
+class inplace:
+ def __add__( self, num ):
+ self.base = self.base + num
+ return self.base
+ def __sub__( self, num ):
+ self.base = self.base - num
+ return self.base
+ def __init__(self, base ):
+ self.base = base
+ def __repr__(self ):
+ return repr( self.base)
+ def __str__(self ):
+ return str( self.base)
+ __radd__ = __add__
+ def __mul__(self, num ):
+ return self.base * num
+ def __div__(self, num ):
+ return self.base / num
+ def __mod__(self, num ):
+ return self.base % num
+ def __neg__(self ):
+ return - abs( self.base)
+ def __pos__(self ):
+ return abs( self.base)
+ def __abs__(self ):
+ return abs( self.base )
+ def __inv__(self ):
+ return -self.base
+ def __lshift__(self, num ):
+ return self.base << num
+ def __rshift__(self, num ):
+ return self.base >> num
+ def __and__(self, num ):
+ return self.base and num
+ def __or__(self, num ):
+ return self.base or num
+ def value( self ):
+ return self.base \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/namespace.py b/intern/python/modules/mcf/utils/namespace.py
new file mode 100644
index 00000000000..819531e10db
--- /dev/null
+++ b/intern/python/modules/mcf/utils/namespace.py
@@ -0,0 +1,224 @@
+'''
+NameSpace v0.04:
+
+A "NameSpace" is an object wrapper around a _base dictionary
+which allows chaining searches for an 'attribute' within that
+dictionary, or any other namespace which is defined as part
+of the search path (depending on the downcascade variable, is
+either the hier-parents or the hier-children).
+
+You can assign attributes to the namespace normally, and read
+them normally. (setattr, getattr, a.this = that, a.this)
+
+I use namespaces for writing parsing systems, where I want to
+differentiate between sources (have multiple sources that I can
+swap into or out of the namespace), but want to be able to get
+at them through a single interface. There is a test function
+which gives you an idea how to use the system.
+
+In general, call NameSpace(someobj), where someobj is a dictionary,
+a module, or another NameSpace, and it will return a NameSpace which
+wraps up the keys of someobj. To add a namespace to the NameSpace,
+just call the append (or hier_addchild) method of the parent namespace
+with the child as argument.
+
+### NOTE: if you pass a module (or anything else with a dict attribute),
+names which start with '__' will be removed. You can avoid this by
+pre-copying the dict of the object and passing it as the arg to the
+__init__ method.
+
+### NOTE: to properly pickle and/or copy module-based namespaces you
+will likely want to do: from mcf.utils import extpkl, copy_extend
+
+### Changes:
+ 97.05.04 -- Altered to use standard hierobj interface, cleaned up
+ interface by removing the "addparent" function, which is reachable
+ by simply appending to the __parent__ attribute, though normally
+ you would want to use the hier_addchild or append functions, since
+ they let both objects know about the addition (and therefor the
+ relationship will be restored if the objects are stored and unstored)
+
+ 97.06.26 -- Altered the getattr function to reduce the number of
+ situations in which infinite lookup loops could be created
+ (unfortunately, the cost is rather high). Made the downcascade
+ variable harden (resolve) at init, instead of checking for every
+ lookup. (see next note)
+
+ 97.08.29 -- Discovered some _very_ weird behaviour when storing
+ namespaces in mcf.store dbases. Resolved it by storing the
+ __namespace_cascade__ attribute as a normal attribute instead of
+ using the __unstore__ mechanism... There was really no need to
+ use the __unstore__, but figuring out how a functions saying
+ self.__dict__['__namespace_cascade__'] = something
+ print `self.__dict__['__namespace_cascade__']` can print nothing
+ is a bit beyond me. (without causing an exception, mind you)
+
+ 97.11.15 Found yet more errors, decided to make two different
+ classes of namespace. Those based on modules now act similar
+ to dummy objects, that is, they let you modify the original
+ instead of keeping a copy of the original and modifying that.
+
+ 98.03.15 -- Eliminated custom pickling methods as they are no longer
+ needed for use with Python 1.5final
+
+ 98.03.15 -- Fixed bug in items, values, etceteras with module-type
+ base objects.
+'''
+import copy, types, string
+import hierobj
+
+class NameSpace(hierobj.Hierobj):
+ '''
+ An hierarchic NameSpace, allows specification of upward or downward
+ chaining search for resolving names
+ '''
+ def __init__(self, val = None, parents=None, downcascade=1,children=[]):
+ '''
+ A NameSpace can be initialised with a dictionary, a dummied
+ dictionary, another namespace, or something which has a __dict__
+ attribute.
+ Note that downcascade is hardened (resolved) at init, not at
+ lookup time.
+ '''
+ hierobj.Hierobj.__init__(self, parents, children)
+ self.__dict__['__downcascade__'] = downcascade # boolean
+ if val is None:
+ self.__dict__['_base'] = {}
+ else:
+ if type( val ) == types.StringType:
+ # this is a reference to a module which has been pickled
+ val = __import__( val, {},{}, string.split( val, '.') )
+ try:
+ # See if val's a dummy-style object which has a _base
+ self.__dict__['_base']=copy.copy(val._base)
+ except (AttributeError,KeyError):
+ # not a dummy-style object... see if it has a dict attribute...
+ try:
+ if type(val) != types.ModuleType:
+ val = copy.copy(val.__dict__)
+ except (AttributeError, KeyError):
+ pass
+ # whatever val is now, it's going to become our _base...
+ self.__dict__['_base']=val
+ # harden (resolve) the reference to downcascade to speed attribute lookups
+ if downcascade: self.__dict__['__namespace_cascade__'] = self.__childlist__
+ else: self.__dict__['__namespace_cascade__'] = self.__parent__
+ def __setattr__(self, var, val):
+ '''
+ An attempt to set an attribute should place the attribute in the _base
+ dictionary through a setitem call.
+ '''
+ # Note that we use standard attribute access to allow ObStore loading if the
+ # ._base isn't yet available.
+ try:
+ self._base[var] = val
+ except TypeError:
+ setattr(self._base, var, val)
+ def __getattr__(self,var):
+## print '__getattr__', var
+ return self.__safe_getattr__(var, {}) # the {} is a stopdict
+
+ def __safe_getattr__(self, var,stopdict):
+ '''
+ We have a lot to do in this function, if the attribute is an unloaded
+ but stored attribute, we need to load it. If it's not in the stored
+ attributes, then we need to load the _base, then see if it's in the
+ _base.
+ If it's not found by then, then we need to check our resource namespaces
+ and see if it's in them.
+ '''
+ # we don't have a __storedattr__ or it doesn't have this key...
+ if var != '_base':
+ try:
+ return self._base[var]
+ except (KeyError,TypeError), x:
+ try:
+ return getattr(self._base, var)
+ except AttributeError:
+ pass
+ try: # with pickle, it tries to get the __setstate__ before restoration is complete
+ for cas in self.__dict__['__namespace_cascade__']:
+ try:
+ stopdict[id(cas)] # if succeeds, we've already tried this child
+ # no need to do anything, if none of the children succeeds we will
+ # raise an AttributeError
+ except KeyError:
+ stopdict[id(cas)] = None
+ return cas.__safe_getattr__(var,stopdict)
+ except (KeyError,AttributeError):
+ pass
+ raise AttributeError, var
+ def items(self):
+ try:
+ return self._base.items()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.items()
+ except AttributeError:
+ pass
+ def keys(self):
+ try:
+ return self._base.keys()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.keys()
+ except AttributeError:
+ pass
+ def has_key( self, key ):
+ try:
+ return self._base.has_key( key)
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.has_key( key)
+ except AttributeError:
+ pass
+ def values(self):
+ try:
+ return self._base.values()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.values()
+ except AttributeError:
+ pass
+
+ def __getinitargs__(self):
+ if type( self._base ) is types.ModuleType:
+ base = self._base.__name__
+ else:
+ base = self._base
+ return (base, self.__parent__, self.__downcascade__, self.__childlist__)
+ def __getstate__(self):
+ return None
+ def __setstate__(self,*args):
+ pass
+ def __deepcopy__(self, memo=None):
+ d = id(self)
+ if memo is None:
+ memo = {}
+ elif memo.has_key(d):
+ return memo[d]
+ if type(self._base) == types.ModuleType:
+ rest = tuple(map( copy.deepcopy, (self.__parent__, self.__downcascade__, self.__childlist__) ))
+ new = apply(self.__class__, (self._base,)+rest )
+ else:
+ new = tuple(map( copy.deepcopy, (self._base, self.__parent__, self.__downcascade__, self.__childlist__) ))
+ return new
+## def __del__( self, id=id ):
+## print 'del namespace', id( self )
+
+
+def test():
+ import string
+ a = NameSpace(string)
+ del(string)
+ a.append(NameSpace({'a':23,'b':42}))
+ import math
+ a.append(NameSpace(math))
+ print 'The returned object should allow access to the attributes of the string,\nand math modules, and two simple variables "a" and "b" (== 23 and42 respectively)'
+ return a
+
+
diff --git a/intern/python/modules/mcf/utils/quote.py b/intern/python/modules/mcf/utils/quote.py
new file mode 100644
index 00000000000..5f6dccdd511
--- /dev/null
+++ b/intern/python/modules/mcf/utils/quote.py
@@ -0,0 +1,78 @@
+'''
+Generic quoting functions (very fast),
+generalised to allow use in any number of
+situations, but normally you'll want to create
+a new function based on these patterns which
+has the default args you need. This will
+prevent an extra function call.
+'''
+import string, regex
+# create a translator which is fully worked out...
+
+def _quote(somestring,trans,start='"',stop='"'):
+ '''
+ Return a quoted version of somestring.
+ '''
+ # would be _so_ much better if we could use the
+ # getitem, consider...
+ # return '%s%s%s'%(start,string.join(map(trans.__getitem__, somestring), ''),stop)
+ temp = list(somestring)
+ for charno in xrange(len(temp)):
+ temp[charno]= trans[temp[charno]]
+ return '%s%s%s'%(start,string.join(temp, ''),stop)
+
+def compilerex(trans):
+ '''
+ Compiles a suitable regex from a dictionary
+ translation table. Should be used at design
+ time in most cases to improve speed. Note:
+ is not a very intelligent algo. You could
+ do better by creating a character-class []
+ for the single-character keys and then the
+ groups for the or-ing after it, but I've not
+ got the time at the moment.
+ '''
+ keyset = trans.keys()
+ multitrans = []
+ for x in range(len(keyset)):
+ if len(keyset[x]) != len(trans[keyset[x]]):
+ multitrans.append((keyset[x],trans[keyset[x]]))
+ if len(keyset[x])!= 1:
+ keyset[x] = '\(%s\)'%keyset[x]
+ if multitrans:
+ return 1,regex.compile(string.join(keyset,'\|'))
+
+
+def quote2(somestring,trans,rex,start='',stop=''):
+ '''
+ Should be a faster version of _quote once
+ the regex is built. Rex should be a simple
+ or'ing of all characters requiring substitution,
+ use character ranges whereever possible (should
+ be in most cases)
+ '''
+ temp = list(somestring)
+ curpos = 0
+ try:
+ while rex.search(somestring,curpos) != -1:
+ pos = rex.regs[0]
+ print pos
+ replacement = list(trans[rex.group(0)])
+ temp[pos[0]:pos[1]] = replacement
+ curpos = pos[0]+len(replacement)
+ except (IndexError,regex.error):
+ pass
+ return '%s%s%s'%(start,string.join(temp, ''),stop)
+# compatability
+_quote2 = quote2
+
+def reprq(obj, qtype):
+ '''
+ Return representation of a string obj as a string with qtype
+ quotes surrounding it. Usable when linearising Python objects
+ to languages which have only a particular type of string. (Such
+ as VRML). This is not a generalised nor a particularly reliable
+ solution. You should use the _quote2 function instead.
+ '''
+ return '%s%s%s'%(qtype,string.join(string.split(string.join(string.split(obj, '\\'), '\\\\'), qtype), '\\%s'%qtype),qtype)
+
diff --git a/intern/python/modules/mcf/utils/rangeval.py b/intern/python/modules/mcf/utils/rangeval.py
new file mode 100644
index 00000000000..dd166dbebfb
--- /dev/null
+++ b/intern/python/modules/mcf/utils/rangeval.py
@@ -0,0 +1,64 @@
+''' Classes which match ranges, sets, or anything at all. '''
+import dummy # provides storage functions as well as a few others
+
+class BetwVal(dummy.Dummy):
+ '''
+ Matches any object greater than smaller and less than larger
+ '''
+ def __init__(self, first, second):
+ if first <= second:
+ dummy.Dummy.__init__(self, [first, second])
+ else:
+ dummy.Dummy.__init__(self, [second, first])
+ def __getinitargs__(self):
+ return (self._base[0], self._base[1])
+ def __cmp__(self, object):
+ '''The Guts of the Class, allows standard comparison operators'''
+ if self._base[0]<=object:
+ if self._base[1] >=object:
+ return 0
+ else: return 1
+ else: return -1
+ def __repr__(self):
+ return '%s(%s,%s)'% (self.__class__.__name__,`self._base[0]`,`self._base[1]`)
+
+class WInVal(dummy.Dummy):
+ '''
+ Matches any value in the sequential object used as initialiser
+ Doesn't gracefully handle situations where not found, as it just
+ returns a -1
+ '''
+ def __init__(self,seq):
+ self._base = seq
+ def __cmp__(self, object):
+ ''' Standard comparison operators '''
+ for x in self._base:
+ if x == object:
+ return 0
+ return -1
+ def __repr__(self):
+ return '%s(%s)'% (self.__class__.__name__,`self._base`)
+
+class ExceptVal(WInVal):
+ '''
+ A negative Version of WInVal
+ '''
+ def __cmp__(self, object):
+ for x in self._base:
+ if x == object:
+ return -1
+ return 0
+
+class AnyVal:
+ '''
+ Matches anything at all
+ '''
+ def __init__(self):
+ pass
+ def __getinitargs__(self):
+ return ()
+ def __cmp__(self, object):
+ return 0
+ def __repr__(self):
+ return 'AnyVal()'
+
diff --git a/intern/python/modules/mcf/utils/regutils_ex.py b/intern/python/modules/mcf/utils/regutils_ex.py
new file mode 100644
index 00000000000..5ef48454e78
--- /dev/null
+++ b/intern/python/modules/mcf/utils/regutils_ex.py
@@ -0,0 +1,158 @@
+import win32api, win32con, string, types
+
+def _getDataType( data, coerce = 1 ):
+ '''
+ Return a tuple of dataType, data for a given object
+ automatically converts non-string-or-tuple-data into
+ strings by calling pickle.dumps
+ '''
+ if type( data ) is types.StringType:
+ return win32con.REG_SZ, data
+ elif type( data ) is types.IntType:
+ return win32con.REG_DWORD, data
+ # what about attempting to convert Longs, floats, etceteras to ints???
+ elif coerce:
+ import pickle
+ return win32con.REG_SZ, pickle.dumps( data )
+ else:
+ raise TypeError, '''Unsupported datatype for registry, use getDataType( data, coerce=1) to store types other than string/int.'''
+
+def _getBaseKey( fullPathSpec ):
+ '''
+ Split a "full path specification" registry key
+ into its root and subpath components
+ '''
+ key = ''
+ subkey = fullPathSpec
+ # while loop will strip off preceding \\ characters
+ while subkey and not key:
+ key, subkey = string.split( fullPathSpec, '\\', 1 )
+ try:
+ return getattr( win32con, key ), subkey
+ except AttributeError:
+ raise '''Unknown root key %s in registry path %s'''% (key, fullPathSpec)
+
+def RegSetValue( key, valuename='', data='', allowPickling=1 ):
+ '''
+ Set a registry value by providing a fully-specified
+ registry key (and an optional sub-key/value name),
+ and a data element. If allowPickling is true, the
+ data element can be any picklable element, otherwise
+ data element must be a string or integer.
+ '''
+ root, subkey = _getBaseKey( key )
+ dataType, data = _getDataType( data, allowPickling )
+ try:
+ hKey = win32api.RegOpenKeyEx( root , subkey, 0, win32con.KEY_ALL_ACCESS) # could we use a lesser access model?
+ except:
+ hKey = win32api.RegCreateKey( root, subkey )
+ try:
+ if not valuename: # the default value
+ win32api.RegSetValue( hKey, valuename, dataType, data )
+ else: # named sub-value
+ win32api.RegSetValueEx( hKey, valuename, 0, dataType, data )
+ finally:
+ win32api.RegCloseKey( hKey)
+
+def RegQueryValue( key, valuename='', pickling=0 ):
+ '''
+ Get a registry value by providing a fully-specified
+ registry key (and an optional sub-key/value name)
+ If pickling is true, the data element will be
+ unpickled before being returned.
+ '''
+ #print 'key', key
+ root, subkey = _getBaseKey( key )
+ if not valuename: # the default value
+ data, type = win32api.RegQueryValue( root , subkey)
+ else:
+ try:
+ #print root, subkey
+ hKey = win32api.RegOpenKeyEx( root, subkey, 0, win32con.KEY_READ)
+ #print hKey, valuename
+ try:
+ data, type = win32api.RegQueryValueEx( hKey, valuename )
+ except: #
+ data, type = None, 0 # value is not available...
+ pickling = None
+ finally:
+ win32api.RegCloseKey( hKey)
+ if pickling:
+ import pickle
+ data = pickle.loads( data )
+ return data
+
+# following constants seem to reflect where path data is stored on NT machines
+# no idea if it'll work on a 95 machine
+
+def AddPathEntry( newEntry, user = 1, prepend=0 ):
+ '''
+ Add or remove path entry on NT, use prepend == -1 for removal,
+ use prepend == 0 for append, prepend= 1 for prepending to the
+ current path.
+ '''
+ if user:
+ user = 'USER'
+ else:
+ user = 'MACHINE'
+ key, valuename = COMMON_KEYS[ (user, 'PATH') ]
+ _PathManager( key, valuename, newEntry, prepend )
+
+def PyExecutables( user = 1, prepend=0 ):
+ '''
+ Register/Deregister Python files as executables
+ '''
+ if user:
+ user = 'USER'
+ else:
+ user = 'MACHINE'
+ key, valuename = COMMON_KEYS[ (user, 'PYEXECUTABLES') ]
+ # the default executables + Python scripts...
+ if prepend < 0: # are to eliminate only .py
+ newEntry = '.PY'
+ else:
+ newEntry = '.PY;.COM;.EXE;.BAT;.CMD'
+ _PathManager( key, valuename, newEntry, prepend )
+
+def _PathManager( key, valuename, newEntry, prepend=0, eliminate_duplicates=1 ):
+ '''
+ Create a new Path entry on NT machines (or kill an old one)
+ user determines whether to alter the USER or the Machine's path
+ prepend
+ 1 -> add newEntry to start
+ 0 -> add newEntry to end
+ -1 -> don't add newEntry
+ eliminate_duplicates determines whether to kill equal paths
+
+ All values are converted to lower case
+ '''
+ # get current value...
+ curval = RegQueryValue( key, valuename ) or ''
+ # split into elements
+ curval = string.split( string.lower(curval), ';' )
+ if type( newEntry ) not in (types.ListType, types.TupleType):
+ newEntry = string.split( string.lower(newEntry), ';' )
+ # eliminate duplicates of the newEntry
+ curval = filter( None, curval) # strip out null entries
+ if eliminate_duplicates:
+ newval = []
+ for p in curval:
+ if p not in newEntry:
+ newval.append( p )
+ curval = newval
+ if prepend == 1:
+ curval = list(newEntry) + curval
+ elif prepend == 0:
+ curval = curval + list( newEntry )
+ elif prepend == -1: # this call is just killing the path entry
+ pass
+ #now do the recombination
+ curval = string.join( curval, ';' )
+ RegSetValue( key, valuename, curval )
+
+COMMON_KEYS = {
+('USER','PATH') : ('''HKEY_CURRENT_USER\\Environment''', 'path'),
+('MACHINE','PATH') : ('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment''', 'path'),
+('USER','PYEXECUTABLES') : ('''HKEY_CURRENT_USER\\Environment''', 'pathext'),
+('MACHINE','PYEXECUTABLES') : ('''HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment''', 'pathext')
+}
diff --git a/intern/python/modules/mcf/utils/reloader.py b/intern/python/modules/mcf/utils/reloader.py
new file mode 100644
index 00000000000..2d7e2591ed2
--- /dev/null
+++ b/intern/python/modules/mcf/utils/reloader.py
@@ -0,0 +1,33 @@
+import sys, string
+
+class Reloader:
+ '''
+ Class allows for reloading all modules imported
+ after the instance is created. Normally you will
+ use this by doing:
+ import <anything you don't want reloaded>
+ from mcf.utils import reloader
+ <do testing and rewriting>
+ reloader.go()
+ '''
+ def __init__(self):
+ self.keys = sys.modules.keys()
+ def __call__(self, *args, **namedargs):
+ done = []
+ for key, val in sys.modules.items():
+ if key not in self.keys:
+ try:
+ reload( val )
+ done.append( key )
+ except (ImportError):
+ print '''Couldn't reload module:''', key
+ except (TypeError): # for None's
+ # is a flag to prevent reloading
+ pass
+ if done:
+ print '''Reloaded:''', string.join( done, ', ')
+ else:
+ print '''No modules reloaded'''
+
+# the default reloader...
+go = Reloader() \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/singletonlist.py b/intern/python/modules/mcf/utils/singletonlist.py
new file mode 100644
index 00000000000..5ca2f5000c2
--- /dev/null
+++ b/intern/python/modules/mcf/utils/singletonlist.py
@@ -0,0 +1,104 @@
+class SingletonList:
+ '''
+ A SingletonList always has a length of one or 0,
+ appends overwrite the single element, iteration will
+ return precisely one element. Attempts to get any item
+ other than 0 will raise an IndexError or return the single
+ item depending on whether the 'raiseIndexError' flag is
+ true or false (generally it should be true except if the
+ for x in SingletonList: construct is known never to be
+ used, since this construct will create an infinite loop
+ if we never raise an IndexError).
+ '''
+ def __init__(self,base=None,raiseIndexError=1):
+ self._base = base
+ self.raiseIndexError = raiseIndexError
+ def __len__(self):
+ '''
+ The length is 0 if no _base, 1 if a base
+ '''
+ if hasattr(self, '_base'):
+ return 1
+ else:
+ return 0
+ def __getitem__(self,ind):
+ '''
+ Get the item if ind == 0, else raise an IndexError or return
+ the item, depending on the raiseIndexError flag
+ '''
+ if ind == 0:
+ try:
+ return self._base
+ except AttributeError:
+ raise IndexError, ind
+ elif self.raiseIndexError:
+ raise IndexError, ind
+ else:
+ return self._base
+ def __setitem__(self,ind, item):
+ '''
+ The item is to become the base
+ '''
+ self._base = item
+ def __delitem__(self,ind):
+ '''
+ Delete the base, regardless of the index used
+ '''
+ try:
+ del(self._base)
+ except AttributeError:
+ raise IndexError, ind
+ def append(self,item):
+ '''
+ Replace the base with the item
+ '''
+ self._base = item
+ def index(self,item):
+ '''
+ if the item is the base, return the only valid index (0)
+ '''
+ try:
+ if item == self._base:
+ return 0
+ except:
+ pass
+ raise ValueError, item
+ def count(self, item):
+ '''
+ If the item is the base, we have one, else 0
+ '''
+ try:
+ if item == self._base:
+ return 1
+ except:
+ pass
+ return 0
+ insert = __setitem__
+ def remove(self, item):
+ '''
+ if the item is the base, delete the base, else ValueError
+ '''
+ try:
+ if item == self._base:
+ del(self._base)
+ return
+ except:
+ pass
+ raise ValueError, item
+ def reverse(self):
+ pass
+ def sort(self):
+ pass
+ def __repr__(self):
+ try:
+ return '[%s]'%`self._base`
+ except AttributeError:
+ return '[]'
+ # store and copy functions
+# def __getinitargs__(self):
+# return (self._base,self.raiseIndexError)
+# def __getstate__(self,*args,**namedargs):
+# pass
+# def __setstate__(self,*args,**namedargs):
+# pass
+
diff --git a/intern/python/modules/mcf/utils/tempclassmodule.py b/intern/python/modules/mcf/utils/tempclassmodule.py
new file mode 100644
index 00000000000..9fe6eed3918
--- /dev/null
+++ b/intern/python/modules/mcf/utils/tempclassmodule.py
@@ -0,0 +1,251 @@
+'''
+Generate module for holding temporary classes which
+will be reconstructed into the same module to allow
+cPickle and the like to properly import them.
+
+Note: You _must_ pickle a reference to the tempclassmodule
+_before_ you pickle any instances which use the classes stored
+in the module! Also, the classes cannot reference anything
+in their dictionary or bases tuples which are not normally
+pickleable (in particular, you can't subclass a class in the
+same tempclassmodule or a tempclassmodule which you cannot
+guarantee will be loaded before the dependent classes. (i.e.
+by guaranteeing they will be pickled first)
+'''
+import new, time, string, sys, types
+
+def buildModule(packagename, basename, rebuild=None, initialcontents=None):
+ '''
+ Dynamically build a module or rebuild one, generates
+ a persistent ID/name if not rebuilding. The persistent
+ ID is the value of basename+`time.time()` with the decimal
+ point removed (i.e. a long string of digits). Packagename
+ must be an importable package! Will raise an ImportError
+ otherwise. Also, for easy reconstitution, basename must not
+ include any decimal points.
+
+ initialcontents is a dictionary (or list) of elements which will be
+ added to the new module.
+ '''
+ if rebuild == None:
+ timestamp = `time.time()`
+ decpos = string.find(timestamp,'.')
+ basename = basename+timestamp[:decpos]+timestamp[decpos+1:]
+ name = string.join((packagename, basename), '.')
+ a = {}
+ b = {}
+ try: # see if we've already loaded this module...
+ mod = __import__( name, {},{}, string.split( name, '.'))
+ if initialcontents:
+ _updateFrom(mod, initialcontents)
+ return mod.__name__, mod
+ except ImportError:
+ pass
+ mod = new.module(name)
+ sys.modules[name] = mod
+ # following is just to make sure the package is loaded before attempting to alter it...
+ __import__( packagename, {}, {}, string.split(packagename) )
+## exec 'import %s'%(packagename) in a, b ### Security Risk!
+ setattr(sys.modules[ packagename ], basename, mod)
+ # now do the update if there were initial contents...
+ if initialcontents:
+ _updateFrom(mod, initialcontents)
+ return name, mod
+
+def buildClassIn(module, *classargs, **namedclassargs):
+ '''
+ Build a new class and register it in the module
+ as if it were really defined there.
+ '''
+ print module, classargs, namedclassargs
+ namedclassargs["__temporary_class__"] = 1
+ newclass = new.classobj(classargs[0], classargs[1], namedclassargs)
+ newclass.__module__ = module.__name__
+ setattr(module, newclass.__name__, newclass)
+ return newclass
+
+def addClass(module, classobj):
+ '''
+ Insert a classobj into the tempclassmodule, setting the
+ class' __module__ attribute to point to this tempclassmodule
+ '''
+ classobj.__module__ = module.__name__
+ setattr(module, classobj.__name__, classobj)
+ setattr( classobj, "__temporary_class__", 1)
+
+def delClass(module, classobj):
+ '''
+ Remove this class from the module, Note: after running this
+ the classobj is no longer able to be pickled/unpickled unless
+ it is subsequently added to another module. This is because
+ it's __module__ attribute is now pointing to a module which
+ is no longer going to save its definition!
+ '''
+ try:
+ delattr(module, classobj.__name__)
+ except AttributeError:
+ pass
+
+def _packageName(modulename):
+ decpos = string.rfind(modulename, '.')
+ return modulename[:decpos], modulename[decpos+1:]
+
+def _updateFrom(module, contentsource):
+ '''
+ For dealing with unknown datatypes (those passed in by the user),
+ we want to check and make sure we're building the classes correctly.
+ '''
+ # often will pass in a protoNamespace from which to update (during cloning)
+ if type(contentsource) in ( types.DictType, types.InstanceType):
+ contentsource = contentsource.values()
+ # contentsource should now be a list of classes or class-building tuples
+ for val in contentsource:
+ if type(val) is types.ClassType:
+ try:
+ addClass(module, val)
+ except:
+ pass
+ elif type(val) is types.TupleType:
+ try:
+ apply(buildClassIn, (module,)+val)
+ except:
+ pass
+
+def deconstruct(templatemodule):
+ '''
+ Return a tuple which can be passed to reconstruct
+ in order to get a rebuilt version of the module
+ after pickling. i.e. apply(reconstruct, deconstruct(tempmodule))
+ is the equivalent of doing a deepcopy on the tempmodule.
+ '''
+## import pdb
+## pdb.set_trace()
+ classbuilder = []
+ for name, classobj in templatemodule.__dict__.items():
+ if type(classobj) is types.ClassType: # only copy class objects, could do others, but these are special-purpose modules, not general-purpose ones.
+ classbuilder.append( deconstruct_class( classobj) )
+## import pdb
+## pdb.set_trace()
+ return (templatemodule.__name__, classbuilder)
+## except AttributeError:
+## print templatemodule
+## print classbuilder
+
+def deconstruct_class( classobj ):
+ '''
+ Pull apart a class into a tuple of values which can be used
+ to reconstruct it through a call to buildClassIn
+ '''
+ if not hasattr( classobj, "__temporary_class__"):
+ # this is a regular class, re-import on load...
+ return (classobj.__module__, classobj.__name__)
+ else:
+ # this is a temporary class which can be deconstructed
+ bases = []
+ for classobject in classobj.__bases__:
+ bases.append( deconstruct_class (classobject) )
+ return (classobj.__name__, tuple (bases), classobj.__dict__)
+
+
+def reconstruct(modulename, classbuilder):
+ '''
+ Rebuild a temporary module and all of its classes
+ from the structure created by deconstruct.
+ i.e. apply(reconstruct, deconstruct(tempmodule))
+ is the equivalent of doing a deepcopy on the tempmodule.
+ '''
+## import pdb
+## pdb.set_trace()
+ mname, newmod = apply(buildModule, _packageName(modulename)+(1,) ) # 1 signals reconstruct
+ reconstruct_classes( newmod, classbuilder )
+ return newmod
+
+def reconstruct_classes( module, constructors ):
+ '''
+ Put a class back together from the tuple of values
+ created by deconstruct_class.
+ '''
+ classes = []
+ import pprint
+ pprint.pprint( constructors)
+ for constructor in constructors:
+ if len (constructor) == 2:
+ module, name = constructor
+ # this is a standard class, re-import
+ temporarymodule = __import__(
+ module,
+ {},{},
+ string.split(module)+[name]
+ )
+ classobject =getattr (temporarymodule, name)
+ else:
+ # this is a class which needs to be re-constructed
+ (name, bases,namedarguments) = constructor
+ bases = tuple( reconstruct_classes( module, bases ))
+ classobject = apply (
+ buildClassIn,
+ (module, name, bases), # name and bases are the args to the class constructor along with the dict contents in namedarguments
+ namedarguments,
+ )
+ classes.append (classobject)
+ return classes
+
+
+def destroy(tempmodule):
+ '''
+ Destroy the module to allow the system to do garbage collection
+ on it. I'm not sure that the system really does do gc on modules,
+ but one would hope :)
+ '''
+ name = tempmodule.__name__
+ tempmodule.__dict__.clear() # clears references to the classes
+ try:
+ del(sys.modules[name])
+ except KeyError:
+ pass
+ packagename, modname = _packageName(name)
+ try:
+ delattr(sys.modules[ packagename ], modname)
+ except AttributeError:
+ pass
+ del( tempmodule ) # no, I don't see any reason to do it...
+ return None
+
+
+def deepcopy(templatemodule, packagename=None, basename=None):
+ '''
+ Rebuild the whole Module and it's included classes
+ (just the classes). Note: This will _not_ make instances
+ based on the old classes point to the new classes!
+ The value of this function is likely to be minimal given
+ this restriction. For pickling use deconstruct/reconstruct
+ for simple copying just return the module.
+ '''
+ name, classbuilder = deconstruct( templatemodule )
+ if packagename is None:
+ tp, tb = _packageName( name )
+ if packagename is None:
+ packagename = tp
+ if basename is None:
+ basename = tb
+ newmod = buildModule(packagename, basename, initialcontents=classbuilder )
+ return newmod
+
+if __name__ == "__main__":
+ def testPickle ():
+ import mcf.vrml.prototype
+ name, module = buildModule( 'mcf.vrml.temp', 'scenegraph' )
+ buildClassIn( module, 'this', () )
+ buildClassIn( module, 'that', (mcf.vrml.prototype.ProtoTypeNode,) )
+## import pdb
+## pdb.set_trace()
+ import pprint
+ pprint.pprint( deconstruct( module ))
+ name,builder = deconstruct( module )
+ destroy( module)
+ return reconstruct(name, builder)
+ t = testPickle()
+ print t
+
+
+ \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/typeclasses.py b/intern/python/modules/mcf/utils/typeclasses.py
new file mode 100644
index 00000000000..ed798dfe3da
--- /dev/null
+++ b/intern/python/modules/mcf/utils/typeclasses.py
@@ -0,0 +1,50 @@
+'''
+Classes of Types
+
+Often you want to be able to say:
+ if type(obj) in MutableTypes:
+ yada
+
+This module is intended to make that easier.
+Just import and use :)
+'''
+import types
+
+MutableTypes = [ types.ListType, types.DictType, types.InstanceType ]
+MutableSequenceTypes = [ types.ListType ]
+SequenceTypes = [ types.ListType, types.StringType, types.TupleType ]
+NumericTypes = [ types.IntType, types.FloatType, types.LongType, types.ComplexType ]
+MappingTypes = [ types.DictType ]
+
+def regarray():
+ if globals().has_key('array'):
+ return 1
+ try:
+ import array
+ SequenceTypes.append( array.ArrayType )
+ MutableTypes.append( array.ArrayType )
+ MutableSequenceTypes.append( array.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+def regnumpy():
+ '''
+ Call if you want to register numpy arrays
+ according to their types.
+ '''
+ if globals().has_key('Numeric'):
+ return 1
+ try:
+ import Numeric
+ SequenceTypes.append( Numeric.ArrayType )
+ MutableTypes.append( Numeric.ArrayType )
+ MutableSequenceTypes.append( Numeric.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+# for now, I'm going to always register these, if the module becomes part of the base distribution
+# it might be better to leave it out so numpy isn't always getting loaded...
+regarray()
+regnumpy() \ No newline at end of file
diff --git a/intern/python/modules/mcf/utils/userquery.py b/intern/python/modules/mcf/utils/userquery.py
new file mode 100644
index 00000000000..e1dc1bfeda5
--- /dev/null
+++ b/intern/python/modules/mcf/utils/userquery.py
@@ -0,0 +1,17 @@
+import string
+
+def userquery( prompt, choices, contextdata = '', defaultind=0 ):
+ if contextdata:
+ print 'Contextual Information:', contextdata
+ for x in range( len( choices ) ):
+ print '(%s)'%x, `choices[x]`
+ choice = raw_input( prompt+( '(%s):'%defaultind ) )
+ if not choice:
+ return choices[ defaultind ]
+ try:
+ choice = string.atoi( choice )
+ return choices[ choice]
+ except IndexError :
+ return choices[ defaultind ]
+ except ValueError:
+ return choice
diff --git a/intern/python/modules/mcf/utils/ver.py b/intern/python/modules/mcf/utils/ver.py
new file mode 100644
index 00000000000..1d36fcd122a
--- /dev/null
+++ b/intern/python/modules/mcf/utils/ver.py
@@ -0,0 +1,17 @@
+'''
+Module giving a float representation
+of the interpreter major version (1.4, 1.5 etceteras)
+
+ver -- Float representation of the current interpreter version
+
+Note: Since I no longer have any Python 1.4 modules, this module is
+no longer in use by me. I intend to leave it here for the next version
+jump :) .
+'''
+import regex, sys, string
+ver = string.atof(sys.version[:regex.match('[0-9.]*', sys.version)])
+
+### Clean up namespace
+del(regex)
+del(sys)
+del(string)
diff --git a/intern/python/modules/mcf/utils/walkerable.py b/intern/python/modules/mcf/utils/walkerable.py
new file mode 100644
index 00000000000..e4c18302097
--- /dev/null
+++ b/intern/python/modules/mcf/utils/walkerable.py
@@ -0,0 +1,46 @@
+'''
+Really simplistic walker-processable hierobjects, doesn't
+have parent attributes, every element has an __attrDict__
+item and a childlist. This is different from the mechanisms
+we'll want to use for multi-tree systems, but it's fairly
+close. Should be fairly simply worked with.
+'''
+class WalkerAble:
+ '''
+ Simple hierarchic objects with the following elements
+
+ __attrDict__ -- app-specific attributes
+ __childlist__ -- childen of this node
+ __gi__ -- "type" or Generic Indicator of this node
+ __childlist__append__ -- as you'd expect, method on childlist to add an element
+ '''
+ def __init__(self, childlist=None, attrDict=None, gi=None):
+ self.__dict__['__attrDict__'] = attrDict or {}
+ self.__dict__['__childlist__'] = childlist or []
+ self.__dict__['__gi__'] = gi or ''
+ self.__dict__['__childlist__append__'] = self.__childlist__.append
+
+ def __getattr__(self, attrName):
+ '''
+ Note: you can store attributes with the same names as
+ the reserved names, but to get them back, you'll need
+ to read it directly out of the attrDict
+ '''
+ if attrName != '__attrDict__':
+ try:
+ return self.__attrDict__[attrName]
+ except KeyError:
+ pass
+ raise AttributeError, attrName
+
+ def __setattr__(self, attrName, attrVal):
+ self.__attrDict__[attrName] = attrVal
+ def __setGI__(self, gi):
+ self.__dict__['__gi__'] = gi
+ def __repr__(self):
+ return '''<WalkerAble %(__gi__)s %(__attrDict__)s %(__childlist__)s>'''%self.__dict__
+
+ # copy functions
+# def __getinitargs__(self):
+# return (self.__childlist__, self.__attrDict__, self.__gi__)
+
diff --git a/intern/python/modules/simpleparse/__init__.py b/intern/python/modules/simpleparse/__init__.py
new file mode 100644
index 00000000000..961871c36a5
--- /dev/null
+++ b/intern/python/modules/simpleparse/__init__.py
@@ -0,0 +1,5 @@
+'''
+Simple parsing using mxTextTools
+
+tar -cvf simpleparse.tar --exclude-from=exclude.txt
+''' \ No newline at end of file
diff --git a/intern/python/modules/simpleparse/bootstrap.py b/intern/python/modules/simpleparse/bootstrap.py
new file mode 100644
index 00000000000..65274bb03ee
--- /dev/null
+++ b/intern/python/modules/simpleparse/bootstrap.py
@@ -0,0 +1,279 @@
+
+from TextTools.TextTools import *
+
+#####################################################
+# FOLLOWING IS THE BOOTSTRAP PARSER, HAND-CODED!
+
+parsernamelist = [
+'declarationset', # 0
+'declaration', # 1
+'implicit_group', # 2 --> no longer used
+'added_token', # 3
+'seq_added_token', #4
+'fo_added_token', #5
+'or_added_token', #6
+'and_added_token', #7
+'element_token', #8
+'group', #9
+'negpos_indicator', #10
+'occurence_indicator', #11
+'unreportedname', #12
+'name', #13
+'<ts>', # 14
+'literal', #15
+'range', # 16
+'CHARBRACE', #17
+'CHARDASH', # 18
+'CHARRANGE', # 19
+'CHARNOBRACE', # 20
+'ESCAPEDCHAR', # 21
+'SPECIALESCAPEDCHAR', # 22
+'OCTALESCAPEDCHAR' # 23
+]
+
+parsertuplelist = range( 24 )
+
+
+
+parsertuplelist[0] = ( # declarationset
+ ('declaration', TableInList,(parsertuplelist, 1)), # must be at least one declaration
+ ('declaration', TableInList,(parsertuplelist, 1),1,0)
+)
+parsertuplelist[1] = ( # declaration
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, SubTable, (
+ ('unreportedname', TableInList,(parsertuplelist, 12),1,2),
+ ('name', TableInList,(parsertuplelist, 13)), # name
+ )
+ ),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, Word, ':='),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ ('element_token', TableInList,(parsertuplelist, 8)),
+ (None, SubTable, ( # added_token
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ),
+ (None, Fail, Here),
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ),
+ ),1,1),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+)
+parsertuplelist[3] = ( # added_token
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ),
+ (None, Fail, Here),
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ),
+)
+parsertuplelist[4] = ( # seq_added_token
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, Is, ','),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ ('element_token', TableInList,(parsertuplelist, 8)),
+ (None, TableInList,(parsertuplelist, 14),4,1), # ts
+ (None, Is, ',',3,1),
+ (None, TableInList,(parsertuplelist, 14),2,1), # ts
+ ('element_token', TableInList,(parsertuplelist, 8),1,-3),
+)
+parsertuplelist[5] = ( # fo_added_token
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, Is, '/'),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ ('element_token', TableInList,(parsertuplelist, 8)),
+ (None, TableInList,(parsertuplelist, 14),4,1), # ts
+ (None, Is, '/',3,1),
+ (None, TableInList,(parsertuplelist, 14),2,1), # ts
+ ('element_token', TableInList,(parsertuplelist, 8),1,-3),
+)
+parsertuplelist[6] = ( # or_added_token
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, Is, '|'),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ ('element_token', TableInList,(parsertuplelist, 8)),
+ (None, TableInList,(parsertuplelist, 14),4,1), # ts
+ (None, Is, '|',3,1),
+ (None, TableInList,(parsertuplelist, 14),2,1), # ts
+ ('element_token', TableInList,(parsertuplelist, 8),1,-3),
+)
+parsertuplelist[7] = ( # and_added_token
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ (None, Is, '&'),
+ (None, TableInList,(parsertuplelist, 14)), # ts
+ ('element_token', TableInList,(parsertuplelist, 8)),
+ (None, TableInList,(parsertuplelist, 14),4,1), # ts
+ (None, Is, '&',3,1),
+ (None, TableInList,(parsertuplelist, 14),2,1), # ts
+ ('element_token', TableInList,(parsertuplelist, 8),1,-3),
+)
+parsertuplelist[8] = ( # element_token
+ ('negpos_indicator', TableInList,(parsertuplelist, 10),1,1),
+ (None, TableInList,(parsertuplelist, 14),1,1), # ts, very inefficient :(
+ ('literal', TableInList, (parsertuplelist,15),1, 4 ),
+ ('range', TableInList, (parsertuplelist,16),1, 3 ),
+ ('group', TableInList, (parsertuplelist,9),1, 2 ),
+ ('name', TableInList, (parsertuplelist,13) ),
+ (None, TableInList,(parsertuplelist, 14),1,1), # ts, very inefficient :(
+ ('occurence_indicator', TableInList,(parsertuplelist, 11), 1,1),
+)
+parsertuplelist[9] = ( # group
+ (None, Is, '('),
+ (None, TableInList,(parsertuplelist, 14),1,1), # ts
+ ('element_token', TableInList, (parsertuplelist,8) ),
+ (None, SubTable, ( # added_token
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 5 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, 4 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, 3 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, 2 ),
+ (None, Fail, Here),
+ ('seq_added_token', TableInList, (parsertuplelist,4), 1, 0 ),
+ ('fo_added_token', TableInList, (parsertuplelist,5), 1, -1 ),
+ ('or_added_token', TableInList, (parsertuplelist,6), 1, -2 ),
+ ('and_added_token', TableInList, (parsertuplelist,7), 1, -3 ),
+ ),1,1),
+ (None, TableInList,(parsertuplelist, 14),1,1), # ts
+ (None, Is, ')'),
+)
+parsertuplelist[10] = ( # negpos_indicator
+ (None, Is, "+",1,2),
+ (None, Is, "-"),
+)
+parsertuplelist[11] = ( #occurence_indicator
+ (None, Is, "+",1,3),
+ (None, Is, "*",1,2),
+ (None, Is, '?'),
+)
+parsertuplelist[12] = ( #unreportedname
+ (None, Is, '<'),
+ ('name', TableInList, (parsertuplelist, 13)), # inefficiency in final system :(
+ (None, Is, '>'),
+)
+parsertuplelist[13] = ( # name
+ (None, IsIn, alpha+'_'),
+ (None, AllIn, alphanumeric+'_',1,1)
+)
+
+parsertuplelist[14] = ( # ts (whitespace)
+ (None, AllIn, ' \011\012\013\014\015',1,1),
+ (None, SubTable, (
+ (None, Is, '#' ),
+ (None, AllNotIn, '\n',1,1 ) # problem if there's a comment at the end of the file :(
+ )
+ ,1,-1 ),
+ )
+# this isn't actually used in the bootstrap parser...
+_specialescapedchar = parsertuplelist[22] = ( # SPECIALESCAPEDCHAR
+ ('SPECIALESCAPEDCHAR', IsIn, '\\abfnrtv'),
+)
+_octalescapechar = parsertuplelist[23] = ( # OCTALESCAPEDCHAR
+ (None, IsIn, '01234567'),
+ (None, IsIn, '01234567',2),
+ (None, IsIn, '01234567',1),
+)
+_escapedchar = parsertuplelist[21] = ( # escapedcharacter
+ (None, Is, '\\' ),
+ ('SPECIALESCAPEDCHAR', IsIn, '\\abfnrtv',1,4),
+ ('OCTALESCAPEDCHAR', SubTable, _octalescapechar)
+)
+
+_charnobrace = parsertuplelist[20] = ( # charnobrace
+ ('ESCAPEDCHAR', Table, _escapedchar, 1,2),
+ ('CHAR', IsNot, ']'),
+)
+_rangedef = parsertuplelist[19] = ( # charrange
+ ('CHARNOBRACE', Table, _charnobrace ),
+ (None, Is, '-'),
+ ('CHARNOBRACE', Table, _charnobrace ),
+)
+
+
+parsertuplelist[16] = ( #range
+ (None, Is, '['),
+ ('CHARBRACE', Is, ']',1,1),
+ ('CHARDASH', Is, '-',1,1),
+ ('CHARRANGE', Table, _rangedef, 1,0),
+ (None, SubTable, _charnobrace, 1,-1),
+ (None, Is, ']')
+)
+
+_sqstr = (
+ (None, Is, "'" ),
+# (None, Is, "'",1, 5 ), # immediate close
+ (None, AllNotIn, "\\'",1,1 ), # all not an escape or end
+ (None, Is, "\\", 2, 1), # is an escaped char
+ (None, Skip, 1, 1, -2), # consume the escaped char and loop back
+ (None, Is, "'" ) # in case there was no matching ', which would also cause a fail for allnotin
+ )
+_dblstr = (
+ (None, Is, '"' ),
+# (None, Is, '"',1, 5 ), # immediate close
+ (None, AllNotIn, '\\"' ,1,1), # not an escaped or end
+ (None, Is, "\\", 2, 1), # is an escaped char
+ (None, Skip, 1, 1, -2), # consume the escaped char and loop back
+ (None, Is, '"' ) # in case there was no matching ", which would also cause a fail for allnotin
+ )
+
+
+
+# literal := ("'",(CHARNOSNGLQUOTE/ESCAPEDCHAR)*,"'") / ('"',(CHARNODBLQUOTE/ESCAPEDCHAR)*,'"')
+
+parsertuplelist[15] = ( # literal
+ (None, Is, "'", 4, 1 ),
+ ('CHARNOSNGLQUOTE', AllNotIn, "\\'",1,1 ), # all not an escape or end
+ ('ESCAPEDCHAR', Table, _escapedchar, 1, -1),
+ (None, Is, "'", 1,5 ),
+ (None, Is, '"' ),
+ ('CHARNODBLQUOTE', AllNotIn, '\\"',1,1 ), # all not an escape or end
+ ('ESCAPEDCHAR', Table, _escapedchar, 1, -1),
+ (None, Is, '"'),
+)
+
+declaration = r'''declarationset := declaration+
+declaration := ts , (unreportedname/name) ,ts,':=',ts, element_token, ( seq_added_token / fo_added_token / or_added_token / and_added_token )*, ts
+seq_added_token := (ts,',',ts, element_token)+
+fo_added_token := (ts,'/',ts, element_token)+
+or_added_token := (ts,'|',ts, element_token)+ # not currently supported
+and_added_token := (ts,'&',ts, element_token)+ # not currently supported
+element_token := negpos_indicator?, ts, (literal/range/group/name),ts, occurence_indicator?
+group := '(',ts, element_token, ( seq_added_token / fo_added_token / or_added_token / and_added_token )*, ts, ')'
+
+negpos_indicator := '+'/'-'
+occurence_indicator := '+'/'*'/'?'
+unreportedname := '<', name, '>'
+name := [a-zA-Z_],[a-zA-Z0-9_]*
+<ts> := ( [ \011-\015]+ / ('#',-'\n'+,'\n')+ )*
+literal := ("'",(CHARNOSNGLQUOTE/ESCAPEDCHAR)*,"'") / ('"',(CHARNODBLQUOTE/ESCAPEDCHAR)*,'"')
+
+
+range := '[',CHARBRACE?,CHARDASH?, (CHARRANGE/CHARNOBRACE)*, CHARDASH?,']'
+CHARBRACE := ']'
+CHARDASH := '-'
+CHARRANGE := CHARNOBRACE, '-', CHARNOBRACE
+CHARNOBRACE := ESCAPEDCHAR/CHAR
+CHAR := -[]]
+ESCAPEDCHAR := '\\',( SPECIALESCAPEDCHAR / OCTALESCAPEDCHAR )
+SPECIALESCAPEDCHAR := [\\abfnrtv]
+OCTALESCAPEDCHAR := [0-7],[0-7]?,[0-7]?
+CHARNODBLQUOTE := -[\\"]+
+CHARNOSNGLQUOTE := -[\\']+
+'''
+
+def parse( instr = declaration, parserelement = 'declarationset' ):
+ tbl = (
+ (parserelement, Table, parsertuplelist[parsernamelist.index( parserelement )] ),
+ )
+ return tag( instr, tbl)
+
+if __name__ == '__main__':
+ import sys, pprint
+ pprint.pprint( apply( parse, tuple( sys.argv[1:] ) ) )
+
+
diff --git a/intern/python/modules/simpleparse/generator.py b/intern/python/modules/simpleparse/generator.py
new file mode 100644
index 00000000000..67f83106dfe
--- /dev/null
+++ b/intern/python/modules/simpleparse/generator.py
@@ -0,0 +1,432 @@
+from TextTools.TextTools import *
+import bootstrap # the hand-coded parser
+import operator, strop as string
+
+def err( value ):
+ print value
+
+class _BaseGenerator:
+ '''
+ Class providing the functions required to turn a
+ parse tree as generated by the bootstrap parser into
+ a new set of parser tuples. I.e a parser generator :)
+ Effectively this is the bootstrap generator.
+ '''
+ def __init__( self, syntaxstring = bootstrap.declaration, parserelement = 'declarationset' ):
+ '''
+ Turn syntaxstring into a parsetree using
+ the bootstrap module's parse command
+ '''
+ # should do some error checking in here :)
+ self.syntaxstring = syntaxstring
+ self.parsetree = bootstrap.parse( syntaxstring, parserelement )[1][0] # the child list
+ self.nameset = []
+ self.tupleset = []
+ def stringval( self, tuple ):
+ '''
+ Return the string value for a parse-result tuple
+ '''
+ return self.syntaxstring[ tuple[1]:tuple[2] ]
+ def build( self, prebuiltnodes=() ):
+ '''
+ Build a new parsing table from the syntax string.
+ New parsers may be accessed using the parserbyname method.
+
+ The pre-built nodes are parsing tables for inclusion in the grammar
+ Added version 1.0.1 to provide greater extensibility.
+ '''
+ # first register all declared names to reserve their indicies
+ #if self.__class__.__name__ == 'Generator':
+ # import pdb
+ # pdb.set_trace()
+ for key, value in prebuiltnodes:
+ self.nameset.append( key )
+ self.tupleset.append( value )
+ for decl in self.parsetree[3]:
+ #print decl
+ name = self.stringval( decl[3][0] )
+ self.nameset.append( name )
+ self.tupleset.append( None)
+ #print 'Declared names:',self.nameset
+ for i in range( len( self.nameset)):
+ #print '''Processing declaration %s '''% self.nameset[i]
+ dataset = self.group( ('group',1,2, self.parsetree[3][i][3][1:]), self )
+ if dataset:
+ self.tupleset[i] = tuple( dataset)
+ def parserbyname( self, name ):
+ '''
+ Retrieve a single parsing tuple by its production name
+ '''
+ try:
+ return self.tupleset[ self.nameset.index( name ) ]
+ except ValueError:
+ print '''Could not find parser tuple of name''', name
+ return ()
+ def allparsers (self):
+ '''
+ Return a list of (productionname, parsingtuple) values
+ suitable for passing to another generator as its pre-calculated
+ set of parsing tuples. (See method build)
+ '''
+ returnvalue = []
+ for i in range(len( self.nameset)):
+ returnvalue.append ( (self.nameset[i],self.tupleset[i]) )
+ return returnvalue
+ ### Actual processing functions...
+ def element_token( self, eltup, genobj, reportname=None ):
+ # Determine the type of element
+ # Descry the various options for the element
+ negative = optional = repeating = element = None
+ for data in eltup[3]:
+ if data[0] == 'negpos_indicator':
+ if genobj.stringval ( data ) == '-':
+ negative = 1
+ elif data[0] == 'occurence_indicator':
+ data = genobj.stringval ( data )
+ if data == '*':
+ optional = 1
+ repeating = 1
+ elif data == '+':
+ repeating = 1
+ elif data == '?':
+ optional = 1
+ else:
+ err( 'Unknown occurence indicator '+ data )
+ else:
+ element = data
+ # call the appropriate handler
+ try:
+ return getattr( self, element [0])( element, genobj, negative, repeating, optional)
+ except AttributeError,x:
+ err( '''Didn't find handler for element type %s, parser build aborted'''%element [0])
+ raise x
+
+ def group( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None):
+ '''
+ Determine what type of group we're dealing with and determine what
+ function to call, then call it.
+ '''
+ groupset = els[3]
+ # groupset is an element_token followed by a possible added_token
+ if groupset:
+ els = []
+ els.append( groupset[0] )
+ if len(groupset) > 1:
+ els[len(els):] = groupset[1][3]
+ gtype = groupset[1][0]
+ if gtype == 'seq_added_token':
+ return self.seq( els, genobj, negative, repeating, optional, reportname )
+ elif gtype == 'fo_added_token':
+ return self.fo( els, genobj, negative, repeating, optional, reportname )
+ else:
+ err( '''An as-yet undefined group type was used! %s'''%gtype )
+ else: # default "sequence" of one... could do more work and make it process the results specifically, but that's optimisation ;)
+ return self.seq( els, genobj, negative, repeating, optional, None )
+ else:
+ return []
+
+
+ def seq( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None ):
+ elset = map( self.element_token, els, [genobj]*len( els) )
+ elset = reduce( operator.add, elset )
+ if negative:
+ if repeating:
+ if optional:
+ return [(None, SubTable, (( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) ), 2,1 ), ( None, EOF, Here, -1,1 ), ), ), ]
+ else: # not optional
+ return [(None, SubTable, (( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) )), ( None, SubTable,( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here),(None,Skip,1) ), 2,1 ), ( None, EOF, Here, -1,1 ), ), ), ]
+ else: # single
+ if optional:
+ return [ (None, SubTable, ( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here), (None, Skip, 1) ),1,1) ]
+ else: # not optional
+ return [ (None, SubTable, ( (None, SubTable, tuple( elset), 2,1), (None, Fail, Here), (None, Skip, 1) )) ]
+ else: # positive
+ if repeating:
+ if optional:
+ return [ (None, SubTable, tuple( elset), 1,0) ]
+ else: # not optional
+
+ return [ (None, SubTable, tuple( elset)), (None, SubTable, tuple( elset), 1,0) ]
+ else: # single
+ if optional:
+ return [ (None, SubTable, tuple( elset), 1,1) ]
+ else: # not optional
+ return [ (None, SubTable, tuple( elset)) ]
+
+ def fo( self, els, genobj, negative= None, repeating=None, optional = None, reportname=None ):
+ elset = map( self.element_token, els, [genobj]*len( els) )
+ elset = reduce( operator.add, elset )
+ elset = []
+ for el in els:
+ dataset = self.element_token( el, genobj )
+ if len( dataset) == 1 and len(dataset[0]) == 3: # we can alter the jump states with impunity
+ elset.append( dataset[0] )
+ else: # for now I'm eating the inefficiency and doing an extra SubTable for all elements to allow for easy calculation of jumps within the FO group
+ elset.append( (None, SubTable, tuple( dataset )) )
+ if negative:
+ # all negative FO's have the meaning "a positive, single, non-optional FO not matching"
+ # the flags modify how failure and continuation are handled in that case, so they can use
+ # the same procset.
+ # Note: Negative FO groups are _very_ heavy, they have normally about 4 subtable calls
+ # guess we'll find out how well mxTextTools handles recursive tables :)
+ procset = []
+ for i in range( len( elset) -1): # note that we have to treat last el specially
+ ival = elset[i] + (1,len(elset)-i)
+ procset.append( ival ) # if success, jump past end
+ procset.append( elset[-1] + (2,1) ) # will cause a failure if last element doesn't match
+ procset.append( (None, Fail, Here ) )
+ procset.append( (None, Skip, 1) )
+ # if the following looks familiar you probably looked at seq above
+ if repeating:
+ if optional:
+ return [ (None, SubTable, ( (None, SubTable, tuple( procset), 2,1), (None, EOF, Here,-1,1) ) ) ]
+ else: # not optional
+ return [ (None, SubTable, ( (None, SubTable, tuple( procset)),(None, SubTable, tuple( procset), 2,1), (None, EOF, Here,-1,1) ) ) ]
+ else: # single
+ if optional:
+ return [ (None, SubTable, tuple( procset), 1,1) ]
+ else: # not optional
+ return [ (None, SubTable, tuple( procset) ) ]
+ else: # positive
+ if repeating:
+ if optional:
+ procset = []
+ for i in range( len( elset)):
+ procset.append( elset[i] + (1,-i) ) # if success, go back to start which is -i elements back
+ return procset
+ else: # not optional
+ procset = []
+ for i in range( len( elset)-1):
+ procset.append( elset[i] + (1, len(elset)-i+1) ) # if success, jump to later section
+ procset.append( elset[-1] + ( 1, 2) ) # will cause a failure if last element doesn't match using an explicit fail command
+ procset.append( (None, Fail, Here) ) # will cause a failure if last element doesn't match using an explicit fail command
+ for i in range( len( elset)-1):
+ procset.append( elset[i] + (1, -i) ) # if success, go back to start which is -i elements back
+ procset.append( elset[-1] + ( 1, 1-(len(elset)) ) ) # will cause a failure if last element doesn't match using an explicit fail command
+ return procset
+ else: # single
+ if optional:
+ procset = []
+ for i in range( len( elset)):
+ procset.append( elset[i] + (1,len(elset)-i) ) # if success, jump past end
+ return procset
+ else: # not optional
+ procset = []
+ for i in range( len( elset) -1): # note that we have to treat last el specially
+ procset.append( elset[i] + (1,len(elset)-i) ) # if success, jump past end
+ procset.append( elset[-1] ) # will cause a failure if last element doesn't match
+ return procset
+
+ def name( self, value, genobj, negative = None, repeating = None, optional = None, reportname=None ):
+ svalue = genobj.stringval( value )
+ try:
+ sindex = genobj.nameset.index( svalue )
+ except ValueError: # eeps, a value not declared
+ try:
+ sindex = genobj.nameset.index( '<'+svalue+'>' )
+ svalue = None
+ except ValueError:
+ err( '''The name %s could not be found in the declarationset. The parser will not compile.'''%svalue)
+ genobj.nameset.append( svalue )
+ genobj.tupleset.append( None )
+ sindex = len( genobj.nameset) - 1
+ if negative:
+ if repeating:
+ if optional:
+ return [ (svalue, SubTable, ( (None, TableInList, (genobj.tupleset, sindex), 1,3), (None, EOF, Here,1,2), (None,Skip,1,-2,-2) ) ) ]
+ else: # not optional
+ return [ (svalue, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(None, Skip, 1), (None, TableInList, (genobj.tupleset, sindex), 1,3), (None, EOF, Here,1,2), (None,Skip,1,-2,-2) ) ) ]
+ else: # single
+ if optional:
+ return [ (None, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(svalue, Skip, 1) ),1,1) ]
+ else: # not optional
+ return [ (None, SubTable, ( (None, TableInList, (genobj.tupleset, sindex),2,1),(None, Fail, Here),(svalue, Skip, 1) )) ]
+ else: # positive
+ if repeating:
+ if optional:
+ return [ (svalue, TableInList, (genobj.tupleset, sindex), 1,0) ]
+ else: # not optional
+ return [ (svalue, TableInList, (genobj.tupleset, sindex)), (svalue, TableInList, (genobj.tupleset, sindex),1,0) ]
+ else: # single
+ if optional:
+ return [ (svalue, TableInList, (genobj.tupleset, sindex), 1,1) ]
+ else: # not optional
+ return [ (svalue, TableInList, (genobj.tupleset, sindex)) ]
+ specialescapedmap = {
+ 'a':'\a',
+ 'b':'\b',
+ 'f':'\f',
+ 'n':'\n',
+ 'r':'\r',
+ 't':'\t',
+ 'v':'\v',
+ '\\':'\\',
+ '"':'"',
+ "'":"'",
+ }
+
+ def escapedchar( self, el, genobj ):
+ svalue = ''
+ if el[3][0][0] == 'SPECIALESCAPEDCHAR':
+ svalue = svalue + self.specialescapedmap[ genobj.stringval( el[3][0] ) ]
+ elif el[3][0][0] == 'OCTALESCAPEDCHAR':
+ #print 'OCTALESCAPEDCHAR', genobj.stringval( el)
+ ovnum = 0
+ ovpow = 0
+ ov = genobj.stringval( el[3][0] )
+ while ov:
+ ovnum = ovnum + int( ov[-1] ) * (8**ovpow)
+ ovpow = ovpow + 1
+ ov = ov[:-1]
+ svalue = svalue + chr( ovnum )
+ #print 'svalue ', `svalue`
+ return svalue
+
+
+ def literal( self, value, genobj, negative = None, repeating=None, optional=None, reportname=None ):
+ '''
+ Calculate the tag-table for a literal element token
+ '''
+ svalue = ''
+ for el in value[3]:
+ if el[0] in ('CHARNOSNGLQUOTE', 'CHARNODBLQUOTE'):
+ svalue = svalue+genobj.stringval( el )
+ elif el[0] == 'ESCAPEDCHAR':
+ svalue = svalue + self.escapedchar( el, genobj )
+ #print 'literal value', `genobj.stringval( value )`
+ #print ' svalue', `svalue`
+ # svalue = svalue[1:-1]
+ if negative:
+ if repeating: # a repeating negative value, a "search" in effect
+ if optional: # if fails, then go to end of file
+ return [ (None, sWordStart, BMS( svalue ),1,2), (None, Move, ToEOF ) ]
+ else: # must first check to make sure the current position is not the word, then the same
+ return [ (None, Word, svalue, 2,1),(None, Fail, Here),(None, sWordStart, BMS( svalue ),1,2), (None, Move, ToEOF ) ]
+ #return [ (None, Word, svalue, 2,1),(None, Fail, Here),(None, WordStart, svalue,1,2), (None, Move, ToEOF ) ]
+ else: # a single-character test saying "not a this"
+ if optional: # test for a success, move back if success, move one forward if failure
+ if len(svalue) > 1:
+ return [ (None, Word, svalue, 2,1),
+ (None, Skip, -len(svalue), 2,2), # backup if this was the word to start of word, succeed
+ (None, Skip, 1 ) ] # else just move one character and succeed
+ else: # Uses Is test instead of Word test, should be faster I'd imagine
+ return [ (None, Is, svalue, 2,1),
+ (None, Skip, -1, 2,2), # backtrack
+ (None, Skip, 1 ) ] # else just move one character and succeed
+ else: # must find at least one character not part of the word, so
+ if len(svalue) > 1:
+ return [ (None, Word, svalue, 2,1),
+ (None, Fail, Here),
+ (None, Skip, 1 ) ] # else just move one character and succeed
+ else: #must fail if it finds or move one forward
+ return [ (None, Is, svalue, 2,1),
+ (None, Fail, Here),
+ (None, Skip, 1 ) ] # else just move one character and succeed
+ else: # positive
+ if repeating:
+ if optional:
+ if len(svalue) > 1:
+ return [ (None, Word, svalue, 1,0) ]
+ else:
+ return [ (None, Is, svalue, 1,0) ]
+ else: # not optional
+ if len(svalue) > 1:
+ return [ (None, Word, svalue),(None, Word, svalue,1,0) ]
+ else:
+ return [ (None, Is, svalue),(None, Is, svalue,1,0) ]
+ else: # not repeating
+ if optional:
+ if len(svalue) > 1:
+ return [ (None, Word, svalue, 1,1) ]
+ else:
+ return [ (None, Is, svalue, 1,1) ]
+ else: # not optional
+ if len(svalue) > 1:
+ return [ (None, Word, svalue) ]
+ else:
+ return [ (None, Word, svalue) ]
+
+ def charnobrace( self, cval, genobj ):
+ #print 'cval', cval
+ if cval[3][0][0] == 'ESCAPEDCHAR':
+ return self.escapedchar( cval[3][0], genobj )
+ #print '''Straight non-brace character''', `genobj.stringval( cval[3][0] )`
+ return genobj.stringval( cval )
+ def range( self, value, genobj, negative = None, repeating=None, optional=None, reportname=None ):
+ dataset = []
+ for cval in value[3]:
+ if cval[0] == 'CHARBRACE':
+ dataset.append( ']')
+ elif cval[0] == 'CHARDASH':
+ dataset.append( '-')
+ elif cval[0] == 'CHARNOBRACE':
+ dataset.append( self.charnobrace( cval, genobj ) )
+ elif cval[0] == 'CHARRANGE':
+ start = ord( self.charnobrace( cval[3][0], genobj ) )
+ end = ord( self.charnobrace( cval[3][1], genobj ) )
+ if start < end:
+ dataset.append( string.join( map( chr, range( start, end +1 ) ), '' ) )
+ else:
+ dataset.append( string.join( map( chr, range( end, start +1 ) ), '' ) )
+ else:
+ dataset.append( genobj.stringval( cval ) )
+ if negative:
+ #svalue = set( string.join( dataset, '' ), 0 )
+ svalue = string.join( dataset, '' )
+ else:
+ #svalue = set( string.join( dataset, '' ), 1)
+ svalue = string.join( dataset, '' )
+ if negative:
+ if repeating:
+ if optional:
+ #return [ (None, AllInSet, svalue, 1 ) ]
+ return [ (None, AllNotIn, svalue, 1 ) ]
+ else: # not optional
+ #return [ (None, AllInSet, svalue ) ]
+ return [ (None, AllNotIn, svalue ) ]
+ else: # not repeating
+ if optional:
+ #return [ (None, IsInSet, svalue, 1 ) ]
+ return [ (None, IsNotIn, svalue, 1 ) ]
+ else: # not optional
+ #return [ (None, IsInSet, svalue ) ]
+ return [ (None, IsNotIn, svalue ) ]
+ else:
+ if repeating:
+ if optional:
+ #return [ (None, AllInSet, svalue, 1 ) ]
+ return [ (None, AllIn, svalue, 1 ) ]
+ else: # not optional
+ #return [ (None, AllInSet, svalue ) ]
+ return [ (None, AllIn, svalue ) ]
+ else: # not repeating
+ if optional:
+ #return [ (None, IsInSet, svalue, 1 ) ]
+ return [ (None, IsIn, svalue, 1 ) ]
+ else: # not optional
+ #return [ (None, IsInSet, svalue ) ]
+ return [ (None, IsIn, svalue ) ]
+
+class Generator( _BaseGenerator ):
+ def __init__( self, syntaxstring , parser ):
+ self.syntaxstring = syntaxstring
+ self.parsetree = [0,1,2, tag( syntaxstring, parser )[1] ]
+ self.nameset = []
+ self.tupleset = []
+
+def buildParser( declaration, prebuiltnodes=() ):
+ '''
+ End-developer function to create an application-specific parser
+ the parsing tuple is available on the returned object as
+ object.parserbyname( 'declaredname' ), where declaredname is the
+ name you defined in your language defintion file.
+
+ The declaration argument is the text of a language defintion file.
+ '''
+ proc = _BaseGenerator( )
+ proc.build()
+ newgen = Generator( declaration, proc.parserbyname( 'declarationset' ) )
+ newgen.build( prebuiltnodes=prebuiltnodes )
+ return newgen
+
+
diff --git a/intern/python/modules/util/README.txt b/intern/python/modules/util/README.txt
new file mode 100644
index 00000000000..60321531bd7
--- /dev/null
+++ b/intern/python/modules/util/README.txt
@@ -0,0 +1,13 @@
+3D utilities
+
+ (c) onk, 1998-2001
+
+ A few low level & math utilities for 2D/3D computations as:
+
+ - area.py: solving close packing problems in 2D
+
+ - vect.py: low level / OO like matrix and vector calculation module
+
+ - vectools.py: more vector tools for intersection calculation, etc.
+
+ - tree.py: binary trees (used by the BSPtree module)
diff --git a/intern/python/modules/util/__init__.py b/intern/python/modules/util/__init__.py
new file mode 100644
index 00000000000..ee6b0cef939
--- /dev/null
+++ b/intern/python/modules/util/__init__.py
@@ -0,0 +1,2 @@
+__all__ = ["vect", "vectools", "area", "quat", "blvect", "tree"]
+
diff --git a/intern/python/modules/util/quat.py b/intern/python/modules/util/quat.py
new file mode 100644
index 00000000000..d23b1c3f6d9
--- /dev/null
+++ b/intern/python/modules/util/quat.py
@@ -0,0 +1,109 @@
+"""Quaternion module
+
+ This module provides conversion routines between Matrices, Quaternions (rotations around
+ an axis) and Eulers.
+
+ (c) 2000, onk@section5.de """
+
+# NON PUBLIC XXX
+
+from math import sin, cos, acos
+from util import vect
+reload(vect)
+
+Vector = vect.Vector
+
+Matrix = vect.Matrix
+
+class Quat:
+ """Simple Quaternion class
+
+Usually, you create a quaternion from a rotation axis (x, y, z) and a given
+angle 'theta', defining the right hand rotation:
+
+ q = fromRotAxis((x, y, z), theta)
+
+This class supports multiplication, providing an efficient way to
+chain rotations"""
+
+ def __init__(self, w = 1.0, x = 0.0, y = 0.0, z = 0.0):
+ self.v = (w, x, y, z)
+
+ def asRotAxis(self):
+ """returns rotation axis (x, y, z) and angle phi (right hand rotation)"""
+ phi2 = acos(self.v[0])
+ if phi2 == 0.0:
+ return Vector(0.0, 0.0, 1.0), 0.0
+ else:
+ s = 1 / (sin(phi2))
+
+ v = Vector(s * self.v[1], s * self.v[2], s * self.v[3])
+ return v, 2.0 * phi2
+
+ def __mul__(self, other):
+ w1, x1, y1, z1 = self.v
+ w2, x2, y2, z2 = other.v
+
+ w = w1*w2 - x1*x2 - y1*y2 - z1*z2
+ x = w1*x2 + x1*w2 + y1*z2 - z1*y2
+ y = w1*y2 - x1*z2 + y1*w2 + z1*x2
+ z = w1*z2 + x1*y2 - y1*x2 + z1*w2
+ return Quat(w, x, y, z)
+
+ def asMatrix(self):
+ w, x, y, z = self.v
+
+ v1 = Vector(1.0 - 2.0 * (y*y + z*z), 2.0 * (x*y + w*z), 2.0 * (x*z - w*y))
+ v2 = Vector(2.0 * (x*y - w*z), 1.0 - 2.0 * (x*x + z*z), 2.0 * (y*z + w*x))
+ v3 = Vector(2.0 * (x*z + w*y), 2.0 * (y*z - w*x), 1.0 - 2.0 * (x*x + y*y))
+
+ return Matrix(v1, v2, v3)
+
+# def asEuler1(self, transp = 0):
+# m = self.asMatrix()
+# if transp:
+# m = m.transposed()
+# return m.asEuler()
+
+ def asEuler(self, transp = 0):
+ from math import atan, asin, atan2
+ w, x, y, z = self.v
+ x2 = x*x
+ z2 = z*z
+ tmp = x2 - z2
+ r = (w*w + tmp - y*y )
+ phi_z = atan2(2.0 * (x * y + w * z) , r)
+ phi_y = asin(2.0 * (w * y - x * z))
+ phi_x = atan2(2.0 * (w * x + y * z) , (r - 2.0*tmp))
+
+ return phi_x, phi_y, phi_z
+
+def fromRotAxis(axis, phi):
+ """computes quaternion from (axis, phi)"""
+ phi2 = 0.5 * phi
+ s = sin(phi2)
+ return Quat(cos(phi2), axis[0] * s, axis[1] * s, axis[2] * s)
+
+#def fromEuler1(eul):
+ #qx = fromRotAxis((1.0, 0.0, 0.0), eul[0])
+ #qy = fromRotAxis((0.0, 1.0, 0.0), eul[1])
+ #qz = fromRotAxis((0.0, 0.0, 1.0), eul[2])
+ #return qz * qy * qx
+
+def fromEuler(eul):
+ from math import sin, cos
+ e = eul[0] / 2.0
+ cx = cos(e)
+ sx = sin(e)
+ e = eul[1] / 2.0
+ cy = cos(e)
+ sy = sin(e)
+ e = eul[2] / 2.0
+ cz = cos(e)
+ sz = sin(e)
+
+ w = cx * cy * cz - sx * sy * sz
+ x = sx * cy * cz - cx * sy * sz
+ y = cx * sy * cz + sx * cy * sz
+ z = cx * cy * sz + sx * sy * cz
+ return Quat(w, x, y, z)
diff --git a/intern/python/modules/util/tree.py b/intern/python/modules/util/tree.py
new file mode 100644
index 00000000000..313159239c6
--- /dev/null
+++ b/intern/python/modules/util/tree.py
@@ -0,0 +1,215 @@
+# Basisklasse fuer Baumstruktur
+# Object-orientiertes Programmieren Wi/97
+#
+# (c) Martin Strubel, Fakultaet fuer Physik, Universitaet Konstanz
+# (strubi@gandalf.physik.uni-konstanz.de)
+
+# updated 08.2001
+
+"""Simple binary tree module
+
+ This module demonstrates a binary tree class.
+
+ Example::
+
+ a = [5, 8, 8, 3, 7, 9]
+ t1 = Tree()
+ t1.fromList(a)
+
+ Operations on tree nodes are done by writing a simple operator class::
+
+ class myOp:
+ def __init__(self):
+ ...
+ def operate(self, node):
+ do_something(node)
+
+ and calling the recursive application::
+
+ op = MyOp()
+ t1.recurse(op)
+
+ Objects inserted into the tree can be of any kind, as long as they define a
+ comparison operation.
+"""
+
+def recurse(node, do):
+ if node == None:
+ return
+ recurse(node.left, do)
+ do(node)
+ recurse(node.right, do)
+
+class Nullnode:
+ def __init__(self):
+ self.left = None
+ self.right = None
+ self.depth = 0
+
+ def recurse(self, do):
+ if self == Nil:
+ return
+ self.left.recurse(do)
+ do(self)
+ self.right.recurse(do)
+
+Nil = Nullnode()
+
+def nothing(x):
+ return x
+
+class Node(Nullnode):
+ def __init__(self, data = None):
+ self.left = Nil
+ self.right = Nil
+ self.data = data
+ self.depth = 0
+
+ def __repr__(self):
+ return "Node: %s" % self.data
+
+ def insert(self, node):
+ if node.data < self.data:
+ if self.left != Nil:
+ return self.left.insert(node)
+ else:
+ node.depth = self.depth + 1
+ self.left = node
+ # print "inserted left"
+ return self
+
+ elif node.data > self.data:
+ if self.right != Nil:
+ return self.right.insert(node)
+ else:
+ node.depth = self.depth + 1
+ self.right = node
+ # print "inserted right"
+ return self
+ else:
+ return self.insert_equal(node)
+
+ def find(self, node, do = nothing):
+ if node.data < self.data:
+ if self.left != Nil:
+ return self.left.find(node, do)
+ else:
+ return self
+ elif node.data > self.data:
+ if self.right != Nil:
+ return self.right.find(node, do)
+ else:
+ return self
+ else:
+ return do(self)
+
+ def remove(self, node):
+ newpar
+ return self
+ def insert_equal(self, node):
+ #print "insert:",
+ self.equal(node)
+ return self
+ def found_equal(self, node):
+ self.equal(node)
+ def equal(self, node):
+ # handle special
+ print "node (%s) is equal self (%s)" % (node, self)
+ def copy(self):
+ n = Node(self.data)
+ return n
+
+ def recursecopy(self):
+ n = Node()
+ n.data = self.data
+ n.flag = self.flag
+ if self.left != Nil:
+ n.left = self.left.recursecopy()
+ if self.right != Nil:
+ n.right = self.right.recursecopy()
+
+ return n
+
+class NodeOp:
+ def __init__(self):
+ self.list = []
+ def copy(self, node):
+ self.list.append(node.data)
+
+class Tree:
+ def __init__(self, root = None):
+ self.root = root
+ self.n = 0
+ def __radd__(self, other):
+ print other
+ t = self.copy()
+ t.merge(other)
+ return t
+ def __repr__(self):
+ return "Tree with %d elements" % self.n
+ def insert(self, node):
+ if self.root == None:
+ self.root = node
+ else:
+ self.root.insert(node)
+ self.n += 1
+ def recurse(self, do):
+ if self.root == None:
+ return
+ self.root.recurse(do)
+ def find(self, node):
+ return self.root.find(node)
+ def remove(self, node):
+ self.root.remove(node)
+ def copy(self):
+ "make true copy of self"
+ t = newTree()
+ c = NodeOp()
+ self.recurse(c.copy)
+ t.fromList(c.list)
+ return t
+ def asList(self):
+ c = NodeOp()
+ self.recurse(c.copy)
+ return c.list
+ def fromList(self, list):
+ for item in list:
+ n = Node(item)
+ self.insert(n)
+ def insertcopy(self, node):
+ n = node.copy()
+ self.insert(n)
+ def merge(self, other):
+ other.recurse(self.insertcopy)
+# EXAMPLE:
+
+newTree = Tree
+
+def printnode(x):
+ print "Element: %s, depth: %s" % (x, x.depth)
+
+def test():
+ a = [5, 8, 8, 3, 7, 9]
+ t1 = Tree()
+ t1.fromList(a)
+
+ b = [12, 4, 56, 7, 34]
+ t2 = Tree()
+ t2.fromList(b)
+
+ print "tree1:"
+ print t1.asList()
+ print "tree2:"
+ print t2.asList()
+ print '-----'
+ print "Trees can be added:"
+
+
+ t3 = t1 + t2
+ print t3.asList()
+ print "..or alternatively merged:"
+ t1.merge(t2)
+ print t1.asList()
+
+if __name__ == '__main__':
+ test()
diff --git a/intern/python/modules/util/vect.py b/intern/python/modules/util/vect.py
new file mode 100644
index 00000000000..3724079519b
--- /dev/null
+++ b/intern/python/modules/util/vect.py
@@ -0,0 +1,480 @@
+#------------------------------------------------------------------------------
+# simple 3D vector / matrix class
+#
+# (c) 9.1999, Martin Strubel // onk@section5.de
+# updated 4.2001
+#
+# This module consists of a rather low level command oriented
+# and a more OO oriented part for 3D vector/matrix manipulation
+#
+# For documentation, please look at the EXAMPLE code below - execute by:
+#
+# > python vect.py
+#
+#
+# permission to use in scientific and free programs granted
+# In doubt, please contact author.
+#
+# history:
+#
+# 1.5: Euler/Rotation matrix support moved here
+# 1.4: high level Vector/Matrix classes extended/improved
+#
+
+"""Vector and matrix math module
+
+ Version 1.5
+ by onk@section5.de
+
+ This is a lightweight 3D matrix and vector module, providing basic vector
+ and matrix math plus a more object oriented layer.
+
+ For examples, look at vect.test()
+"""
+
+VERSION = 1.5
+
+TOLERANCE = 0.0000001
+
+VectorType = 'Vector3'
+MatrixType = 'Matrix3'
+FloatType = type(1.0)
+
+def dot(x, y):
+ "(x,y) - Returns the dot product of vector 'x' and 'y'"
+ return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2])
+
+def cross(x, y):
+ "(x,y) - Returns the cross product of vector 'x' and 'y'"
+ return (x[1] * y[2] - x[2] * y[1],
+ x[2] * y[0] - x[0] * y[2],
+ x[0] * y[1] - x[1] * y[0])
+
+def matrix():
+ "Returns Unity matrix"
+ return ((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))
+
+def matxvec(m, x):
+ "y = matxvec(m,x) - Returns product of Matrix 'm' and vector 'x'"
+ vx = m[0][0] * x[0] + m[1][0] * x[1] + m[2][0] * x[2]
+ vy = m[0][1] * x[0] + m[1][1] * x[1] + m[2][1] * x[2]
+ vz = m[0][2] * x[0] + m[1][2] * x[1] + m[2][2] * x[2]
+ return (vx, vy, vz)
+
+def matfromnormal(z, y = (0.0, 1.0, 0.0)):
+ """(z, y) - returns transformation matrix for local coordinate system
+ where 'z' = local z, with optional *up* axis 'y'"""
+ y = norm3(y)
+ x = cross(y, z)
+ y = cross(z, x)
+ return (x, y, z)
+
+def matxmat(m, n):
+ "(m,n) - Returns matrix product of 'm' and 'n'"
+ return (matxvec(m, n[0]), matxvec(m, n[1]), matxvec(m, n[2]))
+
+def len(x):
+ "(x) - Returns the length of vector 'x'"
+ import math
+ return math.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2])
+
+len3 = len # compatiblity reasons
+
+def norm3(x):
+ "(x) - Returns the vector 'x' normed to 1.0"
+ import math
+ r = math.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2])
+ return (x[0]/r, x[1]/r, x[2]/r)
+
+def add3(x, y):
+ "(x,y) - Returns vector ('x' + 'y')"
+ return (x[0]+y[0], x[1]+y[1], x[2]+y[2])
+
+def sub3(x, y):
+ "(x,y) - Returns vector ('x' - 'y')"
+ return ((x[0] - y[0]), (x[1] - y[1]), (x[2] - y[2]))
+
+def dist3(x, y):
+ "(x,y) - Returns euclidian distance from Point 'x' to 'y'"
+ return len3(sub3(x, y))
+
+def scale3(s, x):
+ "(s,x) - Returns the vector 'x' scaled by 's'"
+ return (s*x[0], s*x[1], s*x[2])
+
+def scalemat(s,m):
+ "(s,m) - Returns the Matrix 'm' scaled by 's'"
+ return (scale3(s, m[0]), scale3(s, m[1]), scale3(s,m[2]))
+
+def invmatdet(m):
+ """n, det = invmat(m) - Inverts matrix without determinant correction.
+ Inverse matrix 'n' and Determinant 'det' are returned"""
+
+ # Matrix: (row vectors)
+ # 00 10 20
+ # 01 11 21
+ # 02 12 22
+
+ wk = [0.0, 0.0, 0.0]
+
+ t = m[1][1] * m[2][2] - m[1][2] * m[2][1]
+ wk[0] = t
+ det = t * m[0][0]
+
+ t = m[2][1] * m[0][2] - m[0][1] * m[2][2]
+ wk[1] = t
+ det = det + t * m[1][0]
+
+ t = m[0][1] * m[1][2] - m[1][1] * m[0][2]
+ wk[2] = t
+ det = det + t * m[2][0]
+
+ v0 = (wk[0], wk[1], wk[2])
+
+ t = m[2][0] * m[1][2] - m[1][0] * m[2][2]
+ wk[0] = t
+ det = det + t * m[0][1]
+
+ t = m[0][0] * m[2][2] - m[0][2] * m[2][0]
+ wk[1] = t
+ det = det + t * m[1][1]
+
+ t = m[1][0] * m[0][2] - m[0][0] * m[1][2]
+ wk[2] = t
+ det = det + t * m[2][1]
+
+ v1 = (wk[0], wk[1], wk[2])
+
+ t = m[1][0] * m[2][1] - m[1][1] * m[2][0]
+ wk[0] = t
+ det = det + t * m[0][2]
+
+ t = m[2][0] * m[0][1] - m[0][0] * m[2][1]
+ wk[1] = t
+ det = det + t * m[1][2]
+
+ t = m[0][0] * m[1][1] - m[1][0] * m[0][1]
+ wk[2] = t
+ det = det + t * m[2][2]
+
+ v2 = (wk[0], wk[1], wk[2])
+ # det = 3 * determinant
+ return ((v0,v1,v2), det/3.0)
+
+def invmat(m):
+ "(m) - Inverts the 3x3 matrix 'm', result in 'n'"
+ n, det = invmatdet(m)
+ if det < 0.000001:
+ raise ZeroDivisionError, "minor rank matrix"
+ d = 1.0/det
+ return (scale3(d, n[0]),
+ scale3(d, n[1]),
+ scale3(d, n[2]))
+
+def transmat(m):
+ # can be used to invert orthogonal rotation matrices
+ "(m) - Returns transposed matrix of 'm'"
+ return ((m[0][0], m[1][0], m[2][0]),
+ (m[0][1], m[1][1], m[2][1]),
+ (m[0][2], m[1][2], m[2][2]))
+
+def coplanar(verts):
+ "checks whether list of 4 vertices is coplanar"
+ v1 = verts[0]
+ v2 = verts[1]
+ a = sub3(v2, v1)
+ v1 = verts[1]
+ v2 = verts[2]
+ b = sub3(v2, v1)
+ if dot(cross(a,b), sub3(verts[3] - verts[2])) < 0.0001:
+ return 1
+ return 0
+
+################################################################################
+# Matrix / Vector highlevel
+# (and slower)
+# TODO: include better type checks !
+
+class Vector:
+ """Vector class
+
+ This vector class provides vector operations as addition, multiplication, etc.
+
+ Usage::
+
+ v = Vector(x, y, z)
+
+ where 'x', 'y', 'z' are float values, representing coordinates.
+ Note: This datatype emulates a float triple."""
+
+ def __init__(self, x = 0.0, y = 0.0, z = 0.0):
+ # don't change these to lists, very ugly referencing details...
+ self.v = (x, y, z)
+ # ... can lead to same data being shared by several matrices..
+ # (unless you want this to happen)
+ self.type = VectorType
+
+ def __neg__(self):
+ return self.new(-self.v[0], -self.v[1], -self.v[2])
+
+ def __getitem__(self, i):
+ "Tuple emulation"
+ return self.v[i]
+
+# def __setitem__(self, i, arg):
+# self.v[i] = arg
+
+ def new(self, *args):
+ return Vector(args[0], args[1], args[2])
+
+ def __cmp__(self, v):
+ "Comparison only supports '=='"
+ if self[0] == v[0] and self[1] == v[1] and self[1] == v[1]:
+ return 0
+ return 1
+
+ def __add__(self, v):
+ "Addition of 'Vector' objects"
+ return self.new(self[0] + v[0],
+ self[1] + v[1],
+ self[2] + v[2])
+
+ def __sub__(self, v):
+ "Subtraction of 'Vector' objects"
+ return self.new(self[0] - v[0],
+ self[1] - v[1],
+ self[2] - v[2])
+
+ def __rmul__(self, s): # scaling by s
+ return self.new(s * self[0], s * self[1], s * self[2])
+
+ def __mul__(self, t): # dot product
+ """Left multiplikation supports:
+
+ - scaling with a float value
+
+ - Multiplikation with *Matrix* object"""
+
+ if type(t) == FloatType:
+ return self.__rmul__(t)
+ elif t.type == MatrixType:
+ return Matrix(self[0] * t[0], self[1] * t[1], self[2] * t[2])
+ else:
+ return dot(self, t)
+
+ def cross(self, v):
+ "(Vector v) - returns the cross product of 'self' with 'v'"
+ return self.new(self[1] * v[2] - self[2] * v[1],
+ self[2] * v[0] - self[0] * v[2],
+ self[0] * v[1] - self[1] * v[0])
+
+ def __repr__(self):
+ return "(%.3f, %.3f, %.3f)" % (self.v[0], self.v[1], self.v[2])
+
+class Matrix(Vector):
+ """Matrix class
+
+ This class is representing a vector of Vectors.
+
+ Usage::
+
+ M = Matrix(v1, v2, v3)
+
+ where 'v'n are Vector class instances.
+ Note: This datatype emulates a 3x3 float array."""
+
+ def __init__(self, v1 = Vector(1.0, 0.0, 0.0),
+ v2 = Vector(0.0, 1.0, 0.0),
+ v3 = Vector(0.0, 0.0, 1.0)):
+ self.v = [v1, v2, v3]
+ self.type = MatrixType
+
+ def __setitem__(self, i, arg):
+ self.v[i] = arg
+
+ def new(self, *args):
+ return Matrix(args[0], args[1], args[2])
+
+ def __repr__(self):
+ return "Matrix:\n %s\n %s\n %s\n" % (self.v[0], self.v[1], self.v[2])
+
+ def __mul__(self, m):
+ """Left multiplication supported with:
+
+ - Scalar (float)
+
+ - Matrix
+
+ - Vector: row_vector * matrix; same as self.transposed() * vector
+"""
+ try:
+ if type(m) == FloatType:
+ return self.__rmul__(m)
+ if m.type == MatrixType:
+ M = matxmat(self, m)
+ return self.new(Vector(M[0][0], M[0][1], M[0][2]),
+ Vector(M[1][0], M[1][1], M[1][2]),
+ Vector(M[2][0], M[2][1], M[2][2]))
+ if m.type == VectorType:
+ v = matxvec(self, m)
+ return Vector(v[0], v[1], v[2])
+ except:
+ raise TypeError, "bad multiplicator type"
+
+ def inverse(self):
+ """returns the matrix inverse"""
+ M = invmat(self)
+ return self.new(Vector(M[0][0], M[0][1], M[0][2]),
+ Vector(M[1][0], M[1][1], M[1][2]),
+ Vector(M[2][0], M[2][1], M[2][2]))
+
+ def transposed(self):
+ "returns the transposed matrix"
+ M = self
+ return self.new(Vector(M[0][0], M[1][0], M[2][0]),
+ Vector(M[1][0], M[1][1], M[2][1]),
+ Vector(M[2][0], M[1][2], M[2][2]))
+
+ def det(self):
+ """returns the determinant"""
+ M, det = invmatdet(self)
+ return det
+
+ def tr(self):
+ """returns trace (sum of diagonal elements) of matrix"""
+ return self.v[0][0] + self.v[1][1] + self.v[2][2]
+
+ def __rmul__(self, m):
+ "Right multiplication supported with scalar"
+ if type(m) == FloatType:
+ return self.new(m * self[0],
+ m * self[1],
+ m * self[2])
+ else:
+ raise TypeError, "bad multiplicator type"
+
+ def __div__(self, m):
+ """Division supported with:
+
+ - Scalar
+
+ - Matrix: a / b equivalent b.inverse * a
+"""
+ if type(m) == FloatType:
+ m = 1.0 /m
+ return m * self
+ elif m.type == MatrixType:
+ return self.inverse() * m
+ else:
+ raise TypeError, "bad multiplicator type"
+
+ def __rdiv__(self, m):
+ "Right division of matrix equivalent to multiplication with matrix.inverse()"
+ return m * self.inverse()
+
+ def asEuler(self):
+ """returns Matrix 'self' as Eulers. Note that this not the only result, due to
+the nature of sin() and cos(). The Matrix MUST be a rotation matrix, i.e. orthogonal and
+normalized."""
+ from math import cos, sin, acos, asin, atan2, atan
+ mat = self.v
+ sy = mat[0][2]
+ # for numerical stability:
+ if sy > 1.0:
+ if sy > 1.0 + TOLERANCE:
+ raise RuntimeError, "FATAL: bad matrix given"
+ else:
+ sy = 1.0
+ phi_y = -asin(sy)
+
+ if abs(sy) > (1.0 - TOLERANCE):
+ # phi_x can be arbitrarely chosen, we set it = 0.0
+ phi_x = 0.0
+ sz = mat[1][0]
+ cz = mat[2][0]
+ phi_z = atan(sz/cz)
+ else:
+ cy = cos(phi_y)
+ cz = mat[0][0] / cy
+ sz = mat[0][1] / cy
+ phi_z = atan2(sz, cz)
+
+ sx = mat[1][2] / cy
+ cx = mat[2][2] / cy
+ phi_x = atan2(sx, cx)
+ return phi_x, phi_y, phi_z
+
+Ex = Vector(1.0, 0.0, 0.0)
+Ey = Vector(0.0, 1.0, 0.0)
+Ez = Vector(0.0, 0.0, 1.0)
+
+One = Matrix(Ex, Ey, Ez)
+orig = (0.0, 0.0, 0.0)
+
+def rotmatrix(phi_x, phi_y, phi_z, reverse = 0):
+ """Creates rotation matrix from euler angles. Rotations are applied in order
+X, then Y, then Z. If the reverse is desired, you have to transpose the matrix after."""
+ from math import sin, cos
+ s = sin(phi_z)
+ c = cos(phi_z)
+ matz = Matrix(Vector(c, s, 0.0), Vector(-s, c, 0.0), Ez)
+
+ s = sin(phi_y)
+ c = cos(phi_y)
+ maty = Matrix(Vector(c, 0.0, -s), Ey, Vector(s, 0.0, c))
+
+ s = sin(phi_x)
+ c = cos(phi_x)
+ matx = Matrix(Ex, Vector(0.0, c, s), Vector(0.0, -s, c))
+
+ return matz * maty * matx
+
+
+def test():
+ "The module test"
+ print "********************"
+ print "VECTOR TEST"
+ print "********************"
+
+ a = Vector(1.1, 0.0, 0.0)
+ b = Vector(0.0, 2.0, 0.0)
+
+ print "vectors: a = %s, b = %s" % (a, b)
+ print "dot:", a * a
+ print "scalar:", 4.0 * a
+ print "scalar:", a * 4.0
+ print "cross:", a.cross(b)
+ print "add:", a + b
+ print "sub:", a - b
+ print "sub:", b - a
+ print
+ print "********************"
+ print "MATRIX TEST"
+ print "********************"
+ c = a.cross(b)
+ m = Matrix(a, b, c)
+ v = Vector(1.0, 2.0, 3.0)
+ E = One
+ print "Original", m
+ print "det", m.det()
+ print "add", m + m
+ print "scalar", 0.5 * m
+ print "sub", m - 0.5 * m
+ print "vec mul", v * m
+ print "mul vec", m * v
+ n = m * m
+ print "mul:", n
+ print "matrix div (mul inverse):", n / m
+ print "scal div (inverse):", 1.0 / m
+ print "mat * inverse", m * m.inverse()
+ print "mat * inverse (/-notation):", m * (1.0 / m)
+ print "div scal", m / 2.0
+
+# matrices with rang < dimension have det = 0.0
+ m = Matrix(a, 2.0 * a, c)
+ print "minor rang", m
+ print "det:", m.det()
+
+if __name__ == '__main__':
+ test()
+
diff --git a/intern/python/modules/util/vectools.py b/intern/python/modules/util/vectools.py
new file mode 100644
index 00000000000..860cd568875
--- /dev/null
+++ b/intern/python/modules/util/vectools.py
@@ -0,0 +1,142 @@
+"""Vector tools
+
+ Various vector tools, basing on vect.py"""
+
+from vect import *
+
+EPSILON = 0.0001
+
+def vecarea(v, w):
+ "Computes area of the span of vector 'v' and 'w' in 2D (not regarding z coordinate)"
+ return v[0]*w[1] - v[1]*w[0]
+
+def intersect(a1, b1, a2, b2):
+ """Computes 2D intersection of edges ('a1' -> 'b1') and ('a2' -> 'b2'),
+returning normalized intersection parameter 's' of edge (a1 -> b1).
+If 0.0 < 's' <= 1.0,
+the two edges intersect at the point::
+
+ v = a1 + s * (b1 - a1)
+"""
+ v = (b1[0] - a1[0], b1[1] - a1[1])
+ w = (b2[0] - a2[0], b2[1] - a2[1])
+ d0 = (a2[0] - a1[0])
+ d1 = (a2[1] - a1[1])
+
+ det = w[0]*v[1] - w[1]*v[0]
+ if det == 0: return 0.0
+ t = v[0]*d1 - v[1]*d0
+ s = w[0]*d1 - w[1]*d0
+ s /= det
+ t /= det
+ if s > 1.0 or s < 0.0: return 0.0
+ if t > 1.0 or t < 0.0: return 0.0
+ return s
+
+def insidetri(a, b, c, x):
+ "Returns 1 if 'x' is inside the 2D triangle ('a' -> 'b' -> 'c'), 0 otherwise"
+ v1 = norm3(sub3(b, a))
+ v2 = norm3(sub3(c, a))
+ v3 = norm3(sub3(x, a))
+
+ a1 = (vecarea(v1, v2))
+ a2 = (vecarea(v1, v3))
+ lo = min(0.0, a1)
+ hi = max(0.0, a1)
+
+ if a2 < lo or a2 > hi: return 0
+
+ v2 = norm3(sub3(b, c))
+ v3 = norm3(sub3(b, x))
+
+ a1 = (vecarea(v1, v2))
+ a2 = (vecarea(v1, v3))
+
+ lo = min(0.0, a1)
+ hi = max(0.0, a1)
+
+ if a2 < lo or a2 > hi: return 0
+
+ return 1
+
+def plane_fromface(v1, v2, v3):
+ "Returns plane (normal, point) from 3 vertices 'v1', 'v2', 'v3'"
+ v = sub3(v2, v1)
+ w = sub3(v3, v1)
+ n = norm3(cross(v, w))
+ return n, v1
+
+def inside_halfspace(vec, plane):
+ "Returns 1 if point 'vec' inside halfspace defined by 'plane'"
+ n, t = plane
+ n = norm3(n)
+ v = sub3(vec, t)
+ if dot(n, v) < 0.0:
+ return 1
+ else:
+ return 0
+
+def half_space(vec, plane, tol = EPSILON):
+ """Determine whether point 'vec' is inside (return value -1), outside (+1)
+, or lying in the plane 'plane' (return 0) of a numerical thickness
+'tol' = 'EPSILON' (default)."""
+ n, t = plane
+ v = sub3(vec, t)
+ fac = len3(n)
+
+ d = dot(n, v)
+ if d < -fac * tol:
+ return -1
+ elif d > fac * tol:
+ return 1
+ else:
+ return 0
+
+
+def plane_edge_intersect(plane, edge):
+ """Returns normalized factor 's' of the intersection of 'edge' with 'plane'.
+The point of intersection on the plane is::
+
+ p = edge[0] + s * (edge[1] - edge[0])
+
+"""
+ n, t = plane # normal, translation
+ mat = matfromnormal(n)
+ mat = transmat(mat) # inverse
+ v = matxvec(mat, sub3(edge[0], t)) #transformed edge points
+ w = matxvec(mat, sub3(edge[1], t))
+ w = sub3(w, v)
+ if w[2] != 0.0:
+ s = -v[2] / w[2]
+ return s
+ else:
+ return None
+
+def insidecube(v):
+ "Returns 1 if point 'v' inside normalized cube, 0 otherwise"
+ if v[0] > 1.0 or v[0] < 0.0:
+ return 0
+ if v[1] > 1.0 or v[1] < 0.0:
+ return 0
+ if v[2] > 1.0 or v[2] < 0.0:
+ return 0
+ return 1
+
+
+def flatproject(verts, up):
+ """Projects a 3D set (list of vertices) 'verts' into a 2D set according to
+an 'up'-vector"""
+ z, t = plane_fromface(verts[0], verts[1], verts[2])
+ y = norm3(up)
+ x = cross(y, z)
+ uvs = []
+ for v in verts:
+ w = (v[0] - t[0], v[1] - t[1], v[2] - t[2])
+ # this is the transposed 2x2 matrix * the vertex vector
+ uv = (dot(x, w), dot(y,w)) # do projection
+ uvs.append(uv)
+ return uvs
+
+
+
+
diff --git a/intern/python/modules/vrml/__init__.py b/intern/python/modules/vrml/__init__.py
new file mode 100644
index 00000000000..9e2ebe0fb86
--- /dev/null
+++ b/intern/python/modules/vrml/__init__.py
@@ -0,0 +1 @@
+"""The VRML import module"""
diff --git a/intern/python/modules/vrml/basenodes.py b/intern/python/modules/vrml/basenodes.py
new file mode 100644
index 00000000000..484f000738a
--- /dev/null
+++ b/intern/python/modules/vrml/basenodes.py
@@ -0,0 +1,974 @@
+from scenegraph import Prototype, NULL, sceneGraph, IS, Script, ExternalPrototype, ROUTE
+PROTO = Prototype
+EXTERNPROTO = ExternalPrototype
+
+Anchor = Prototype( "Anchor",
+ {
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'children':('children', 'MFNode', 1),
+ 'parameter':('parameter', 'MFString', 1),
+ 'url':('url', 'MFString', 1),
+ 'description':('description', 'SFString', 1),
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ },
+ {
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'children':[],
+ 'parameter':[],
+ 'url':[],
+ 'description':'',
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ },
+ {
+ 'addChildren':('addChildren', 'MFNode', 0),
+ 'removeChildren':('removeChildren', 'MFNode', 0),
+ },
+)
+Appearance = Prototype( "Appearance",
+ {
+ 'material':('material', 'SFNode', 1),
+ 'texture':('texture', 'SFNode', 1),
+ 'textureTransform':('textureTransform', 'SFNode', 1),
+ },
+ {
+ 'material':NULL,
+ 'texture':NULL,
+ 'textureTransform':NULL,
+ },
+ {
+ },
+)
+AudioClip = Prototype( "AudioClip",
+ {
+ 'pitch':('pitch', 'SFFloat', 1),
+ 'loop':('loop', 'SFBool', 1),
+ 'description':('description', 'SFString', 1),
+ 'stopTime':('stopTime', 'SFTime', 1),
+ 'startTime':('startTime', 'SFTime', 1),
+ 'url':('url', 'MFString', 1),
+ },
+ {
+ 'pitch':1.0,
+ 'loop':0,
+ 'description':'',
+ 'stopTime':0.0,
+ 'startTime':0.0,
+ 'url':[],
+ },
+ {
+ 'isActive':('isActive', 'SFBool', 1),
+ 'duration_changed':('duration_changed', 'SFTime', 1),
+ },
+)
+Background = Prototype( "Background",
+ {
+ 'groundAngle':('groundAngle', 'MFFloat', 1),
+ 'skyAngle':('skyAngle', 'MFFloat', 1),
+ 'frontUrl':('frontUrl', 'MFString', 1),
+ 'bottomUrl':('bottomUrl', 'MFString', 1),
+ 'groundColor':('groundColor', 'MFColor', 1),
+ 'backUrl':('backUrl', 'MFString', 1),
+ 'skyColor':('skyColor', 'MFColor', 1),
+ 'topUrl':('topUrl', 'MFString', 1),
+ 'rightUrl':('rightUrl', 'MFString', 1),
+ 'leftUrl':('leftUrl', 'MFString', 1),
+ },
+ {
+ 'groundAngle':[],
+ 'skyAngle':[],
+ 'frontUrl':[],
+ 'bottomUrl':[],
+ 'groundColor':[],
+ 'backUrl':[],
+ 'skyColor':[[0.0, 0.0, 0.0]],
+ 'topUrl':[],
+ 'rightUrl':[],
+ 'leftUrl':[],
+ },
+ {
+ 'isBound':('isBound', 'SFBool', 1),
+ 'set_bind':('set_bind', 'SFBool', 0),
+ },
+)
+Billboard = Prototype( "Billboard",
+ {
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'children':('children', 'MFNode', 1),
+ 'axisOfRotation':('axisOfRotation', 'SFVec3f', 1),
+ },
+ {
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'children':[],
+ 'axisOfRotation':[0.0, 1.0, 0.0],
+ },
+ {
+ 'addChildren':('addChildren', 'MFNode', 0),
+ 'removeChildren':('removeChildren', 'MFNode', 0),
+ },
+)
+Box = Prototype( "Box",
+ {
+ 'size':('size', 'SFVec3f', 0),
+ },
+ {
+ 'size':[2.0, 2.0, 2.0],
+ },
+ {
+ },
+)
+
+
+Collision = Prototype( "Collision",
+ {
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'children':('children', 'MFNode', 1),
+ 'collide':('collide', 'SFBool', 1),
+ 'proxy':('proxy', 'SFNode', 0),
+ },
+ {
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'children':[],
+ 'collide':1,
+ 'proxy':NULL,
+ },
+ {
+ 'addChildren':('addChildren', 'MFNode', 0),
+ 'removeChildren':('removeChildren', 'MFNode', 0),
+ 'collideTime':('collideTime', 'SFTime', 1),
+ },
+)
+Color = Prototype( "Color",
+ {
+ 'color':('color', 'MFColor', 1),
+ },
+ {
+ 'color':[],
+ },
+ {
+ },
+)
+ColorInterpolator = Prototype( "ColorInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFColor', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'SFColor', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+Cone = Prototype( "Cone",
+ {
+ 'bottomRadius':('bottomRadius', 'SFFloat', 0),
+ 'side':('side', 'SFBool', 0),
+ 'bottom':('bottom', 'SFBool', 0),
+ 'height':('height', 'SFFloat', 0),
+ },
+ {
+ 'bottomRadius':1.0,
+ 'side':1,
+ 'bottom':1,
+ 'height':2.0,
+ },
+ {
+ },
+)
+Coordinate = Prototype( "Coordinate",
+ {
+ 'point':('point', 'MFVec3f', 1),
+ },
+ {
+ 'point':[],
+ },
+ {
+ },
+)
+CoordinateInterpolator = Prototype( "CoordinateInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFVec3f', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'MFVec3f', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+Cylinder = Prototype( "Cylinder",
+ {
+ 'bottom':('bottom', 'SFBool', 0),
+ 'side':('side', 'SFBool', 0),
+ 'radius':('radius', 'SFFloat', 0),
+ 'top':('top', 'SFBool', 0),
+ 'height':('height', 'SFFloat', 0),
+ },
+ {
+ 'bottom':1,
+ 'side':1,
+ 'radius':1.0,
+ 'top':1,
+ 'height':2.0,
+ },
+ {
+ },
+)
+CylinderSensor = Prototype( "CylinderSensor",
+ {
+ 'maxAngle':('maxAngle', 'SFFloat', 1),
+ 'autoOffset':('autoOffset', 'SFBool', 1),
+ 'minAngle':('minAngle', 'SFFloat', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ 'offset':('offset', 'SFFloat', 1),
+ 'diskAngle':('diskAngle', 'SFFloat', 1),
+ },
+ {
+ 'maxAngle':-1.0,
+ 'autoOffset':1,
+ 'minAngle':0.0,
+ 'enabled':1,
+ 'offset':0.0,
+ 'diskAngle':0.262,
+ },
+ {
+ 'rotation_changed':('rotation_changed', 'SFRotation', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1),
+ },
+)
+DirectionalLight = Prototype( "DirectionalLight",
+ {
+ 'color':('color', 'SFColor', 1),
+ 'ambientIntensity':('ambientIntensity', 'SFFloat', 1),
+ 'intensity':('intensity', 'SFFloat', 1),
+ 'on':('on', 'SFBool', 1),
+ 'direction':('direction', 'SFVec3f', 1),
+ },
+ {
+ 'color':[1.0, 1.0, 1.0],
+ 'ambientIntensity':0.0,
+ 'intensity':1.0,
+ 'on':1,
+ 'direction':[0.0, 0.0, -1.0],
+ },
+ {
+ },
+)
+ElevationGrid = Prototype( "ElevationGrid",
+ {
+ 'xSpacing':('xSpacing', 'SFFloat', 0),
+ 'zSpacing':('zSpacing', 'SFFloat', 0),
+ 'xDimension':('xDimension', 'SFInt32', 0),
+ 'colorPerVertex':('colorPerVertex', 'SFBool', 0),
+ 'height':('height', 'MFFloat', 0),
+ 'texCoord':('texCoord', 'SFNode', 1),
+ 'normalPerVertex':('normalPerVertex', 'SFBool', 0),
+ 'ccw':('ccw', 'SFBool', 0),
+ 'color':('color', 'SFNode', 1),
+ 'normal':('normal', 'SFNode', 1),
+ 'creaseAngle':('creaseAngle', 'SFFloat', 0),
+ 'solid':('solid', 'SFBool', 0),
+ 'zDimension':('zDimension', 'SFInt32', 0),
+ },
+ {
+ 'xSpacing':0.0,
+ 'zSpacing':0.0,
+ 'xDimension':0,
+ 'colorPerVertex':1,
+ 'height':[],
+ 'texCoord':NULL,
+ 'normalPerVertex':1,
+ 'ccw':1,
+ 'color':NULL,
+ 'normal':NULL,
+ 'creaseAngle':0.0,
+ 'solid':1,
+ 'zDimension':0,
+ },
+ {
+ 'set_height':('set_height', 'MFFloat', 0),
+ },
+)
+Extrusion = Prototype( "Extrusion",
+ {
+ 'endCap':('endCap', 'SFBool', 0),
+ 'scale':('scale', 'MFVec2f', 0),
+ 'ccw':('ccw', 'SFBool', 0),
+ 'crossSection':('crossSection', 'MFVec2f', 0),
+ 'solid':('solid', 'SFBool', 0),
+ 'convex':('convex', 'SFBool', 0),
+ 'creaseAngle':('creaseAngle', 'SFFloat', 0),
+ 'spine':('spine', 'MFVec3f', 0),
+ 'beginCap':('beginCap', 'SFBool', 0),
+ 'orientation':('orientation', 'MFRotation', 0),
+ },
+ {
+ 'endCap':1,
+ 'scale':[[1.0, 1.0]],
+ 'ccw':1,
+ 'crossSection':[[1.0, 1.0], [1.0, -1.0], [-1.0, -1.0], [-1.0, 1.0], [1.0, 1.0]],
+ 'solid':1,
+ 'convex':1,
+ 'creaseAngle':0.0,
+ 'spine':[[0.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
+ 'beginCap':1,
+ 'orientation':[[0.0, 0.0, 1.0, 0.0]],
+ },
+ {
+ 'set_scale':('set_scale', 'MFVec2f', 0),
+ 'set_spine':('set_spine', 'MFVec3f', 0),
+ 'set_orientation':('set_orientation', 'MFRotation', 0),
+ 'set_crossSection':('set_crossSection', 'MFVec2f', 0),
+ },
+)
+Fog = Prototype( "Fog",
+ {
+ 'fogType':('fogType', 'SFString', 1),
+ 'color':('color', 'SFColor', 1),
+ 'visibilityRange':('visibilityRange', 'SFFloat', 1),
+ },
+ {
+ 'fogType':'LINEAR',
+ 'color':[1.0, 1.0, 1.0],
+ 'visibilityRange':0.0,
+ },
+ {
+ 'isBound':('isBound', 'SFBool', 1),
+ 'set_bind':('set_bind', 'SFBool', 0),
+ },
+)
+FontStyle = Prototype( "FontStyle",
+ {
+ 'justify':('justify', 'MFString', 0),
+ 'leftToRight':('leftToRight', 'SFBool', 0),
+ 'spacing':('spacing', 'SFFloat', 0),
+ 'horizontal':('horizontal', 'SFBool', 0),
+ 'language':('language', 'SFString', 0),
+ 'topToBottom':('topToBottom', 'SFBool', 0),
+ 'size':('size', 'SFFloat', 0),
+ 'style':('style', 'SFString', 0),
+ 'family':('family', 'SFString', 0),
+ },
+ {
+ 'justify':['BEGIN'],
+ 'leftToRight':1,
+ 'spacing':1.0,
+ 'horizontal':1,
+ 'language':'',
+ 'topToBottom':1,
+ 'size':1.0,
+ 'style':'PLAIN',
+ 'family':'SERIF',
+ },
+ {
+ },
+)
+Group = Prototype( "Group",
+ {
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'children':('children', 'MFNode', 1),
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ },
+ {
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'children':[],
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ },
+ {
+ 'addChildren':('addChildren', 'MFNode', 0),
+ 'removeChildren':('removeChildren', 'MFNode', 0),
+ },
+)
+ImageTexture = Prototype( "ImageTexture",
+ {
+ 'repeatS':('repeatS', 'SFBool', 0),
+ 'url':('url', 'MFString', 1),
+ 'repeatT':('repeatT', 'SFBool', 0),
+ },
+ {
+ 'repeatS':1,
+ 'url':[],
+ 'repeatT':1,
+ },
+ {
+ },
+)
+IndexedFaceSet = Prototype( "IndexedFaceSet",
+ {
+ 'texCoordIndex':('texCoordIndex', 'MFInt32', 0),
+ 'normalIndex':('normalIndex', 'MFInt32', 0),
+ 'coordIndex':('coordIndex', 'MFInt32', 0),
+ 'convex':('convex', 'SFBool', 0),
+ 'texCoord':('texCoord', 'SFNode', 1),
+ 'normalPerVertex':('normalPerVertex', 'SFBool', 0),
+ 'coord':('coord', 'SFNode', 1),
+ 'ccw':('ccw', 'SFBool', 0),
+ 'color':('color', 'SFNode', 1),
+ 'normal':('normal', 'SFNode', 1),
+ 'creaseAngle':('creaseAngle', 'SFFloat', 0),
+ 'solid':('solid', 'SFBool', 0),
+ 'colorPerVertex':('colorPerVertex', 'SFBool', 0),
+ 'colorIndex':('colorIndex', 'MFInt32', 0),
+ },
+ {
+ 'texCoordIndex':[],
+ 'normalIndex':[],
+ 'coordIndex':[],
+ 'convex':1,
+ 'texCoord':NULL,
+ 'normalPerVertex':1,
+ 'coord':NULL,
+ 'ccw':1,
+ 'color':NULL,
+ 'normal':NULL,
+ 'creaseAngle':0.0,
+ 'solid':1,
+ 'colorPerVertex':1,
+ 'colorIndex':[],
+ },
+ {
+ 'set_normalIndex':('set_normalIndex', 'MFInt32', 0),
+ 'set_colorIndex':('set_colorIndex', 'MFInt32', 0),
+ 'set_texCoordIndex':('set_texCoordIndex', 'MFInt32', 0),
+ 'set_coordIndex':('set_coordIndex', 'MFInt32', 0),
+ },
+)
+IndexedLineSet = Prototype( "IndexedLineSet",
+ {
+ 'coordIndex':('coordIndex', 'MFInt32', 0),
+ 'coord':('coord', 'SFNode', 1),
+ 'colorIndex':('colorIndex', 'MFInt32', 0),
+ 'colorPerVertex':('colorPerVertex', 'SFBool', 0),
+ 'color':('color', 'SFNode', 1),
+ },
+ {
+ 'coordIndex':[],
+ 'coord':NULL,
+ 'colorIndex':[],
+ 'colorPerVertex':1,
+ 'color':NULL,
+ },
+ {
+ 'set_colorIndex':('set_colorIndex', 'MFInt32', 0),
+ 'set_coordIndex':('set_coordIndex', 'MFInt32', 0),
+ },
+)
+Inline = Prototype( "Inline",
+ {
+ 'url':('url', 'MFString', 1),
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ },
+ {
+ 'url':[],
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ },
+ {
+ },
+)
+LOD = Prototype( "LOD",
+ {
+ 'level':('level', 'MFNode', 1),
+ 'range':('range', 'MFFloat', 0),
+ 'center':('center', 'SFVec3f', 0),
+ },
+ {
+ 'level':[],
+ 'range':[],
+ 'center':[0.0, 0.0, 0.0],
+ },
+ {
+ },
+)
+Material = Prototype( "Material",
+ {
+ 'emissiveColor':('emissiveColor', 'SFColor', 1),
+ 'transparency':('transparency', 'SFFloat', 1),
+ 'shininess':('shininess', 'SFFloat', 1),
+ 'diffuseColor':('diffuseColor', 'SFColor', 1),
+ 'ambientIntensity':('ambientIntensity', 'SFFloat', 1),
+ 'specularColor':('specularColor', 'SFColor', 1),
+ },
+ {
+ 'emissiveColor':[0.0, 0.0, 0.0],
+ 'transparency':0.0,
+ 'shininess':0.2,
+ 'diffuseColor':[0.8, 0.8, 0.8],
+ 'ambientIntensity':0.2,
+ 'specularColor':[0.0, 0.0, 0.0],
+ },
+ {
+ },
+)
+MovieTexture = Prototype( "MovieTexture",
+ {
+ 'loop':('loop', 'SFBool', 1),
+ 'speed':('speed', 'SFFloat', 1),
+ 'repeatT':('repeatT', 'SFBool', 0),
+ 'repeatS':('repeatS', 'SFBool', 0),
+ 'url':('url', 'MFString', 1),
+ 'startTime':('startTime', 'SFTime', 1),
+ 'stopTime':('stopTime', 'SFTime', 1),
+ },
+ {
+ 'loop':0,
+ 'speed':1.0,
+ 'repeatT':1,
+ 'repeatS':1,
+ 'url':[],
+ 'startTime':0.0,
+ 'stopTime':0.0,
+ },
+ {
+ 'isActive':('isActive', 'SFBool', 1),
+ 'duration_changed':('duration_changed', 'SFFloat', 1),
+ },
+)
+NavigationInfo = Prototype( "NavigationInfo",
+ {
+ 'avatarSize':('avatarSize', 'MFFloat', 1),
+ 'speed':('speed', 'SFFloat', 1),
+ 'headlight':('headlight', 'SFBool', 1),
+ 'visibilityLimit':('visibilityLimit', 'SFFloat', 1),
+ 'type':('type', 'MFString', 1),
+ },
+ {
+ 'avatarSize':[0.25, 1.6, 0.75],
+ 'speed':1.0,
+ 'headlight':1,
+ 'visibilityLimit':0.0,
+ 'type':['WALK'],
+ },
+ {
+ 'isBound':('isBound', 'SFBool', 1),
+ 'set_bind':('set_bind', 'SFBool', 0),
+ },
+)
+Normal = Prototype( "Normal",
+ {
+ 'vector':('vector', 'MFVec3f', 1),
+ },
+ {
+ 'vector':[],
+ },
+ {
+ },
+)
+NormalInterpolator = Prototype( "NormalInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFVec3f', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'MFVec3f', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+OrientationInterpolator = Prototype( "OrientationInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFRotation', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'SFRotation', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+PixelTexture = Prototype( "PixelTexture",
+ {
+ 'repeatS':('repeatS', 'SFBool', 0),
+ 'image':('image', 'SFImage', 1),
+ 'repeatT':('repeatT', 'SFBool', 0),
+ },
+ {
+ 'repeatS':1,
+ 'image':[0, 0, 0],
+ 'repeatT':1,
+ },
+ {
+ },
+)
+PlaneSensor = Prototype( "PlaneSensor",
+ {
+ 'offset':('offset', 'SFVec3f', 1),
+ 'autoOffset':('autoOffset', 'SFBool', 1),
+ 'minPosition':('minPosition', 'SFVec2f', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ 'maxPosition':('maxPosition', 'SFVec2f', 1),
+ },
+ {
+ 'offset':[0.0, 0.0, 0.0],
+ 'autoOffset':1,
+ 'minPosition':[0.0, 0.0],
+ 'enabled':1,
+ 'maxPosition':[-1.0, -1.0],
+ },
+ {
+ 'translation_changed':('translation_changed', 'SFVec3f', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1),
+ },
+)
+PointLight = Prototype( "PointLight",
+ {
+ 'ambientIntensity':('ambientIntensity', 'SFFloat', 1),
+ 'color':('color', 'SFColor', 1),
+ 'location':('location', 'SFVec3f', 1),
+ 'radius':('radius', 'SFFloat', 1),
+ 'attenuation':('attenuation', 'SFVec3f', 1),
+ 'intensity':('intensity', 'SFFloat', 1),
+ 'on':('on', 'SFBool', 1),
+ },
+ {
+ 'ambientIntensity':0.0,
+ 'color':[1.0, 1.0, 1.0],
+ 'location':[0.0, 0.0, 0.0],
+ 'radius':100.0,
+ 'attenuation':[1.0, 0.0, 0.0],
+ 'intensity':1.0,
+ 'on':1,
+ },
+ {
+ },
+)
+PointSet = Prototype( "PointSet",
+ {
+ 'coord':('coord', 'SFNode', 1),
+ 'color':('color', 'SFNode', 1),
+ },
+ {
+ 'coord':NULL,
+ 'color':NULL,
+ },
+ {
+ },
+)
+PositionInterpolator = Prototype( "PositionInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFVec3f', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'SFVec3f', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+ProximitySensor = Prototype( "ProximitySensor",
+ {
+ 'size':('size', 'SFVec3f', 1),
+ 'center':('center', 'SFVec3f', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ },
+ {
+ 'size':[0.0, 0.0, 0.0],
+ 'center':[0.0, 0.0, 0.0],
+ 'enabled':1,
+ },
+ {
+ 'enterTime':('enterTime', 'SFTime', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'orientation_changed':('orientation_changed', 'SFRotation', 1),
+ 'exitTime':('exitTime', 'SFTime', 1),
+ 'position_changed':('position_changed', 'SFVec3f', 1),
+ },
+)
+ScalarInterpolator = Prototype( "ScalarInterpolator",
+ {
+ 'key':('key', 'MFFloat', 1),
+ 'keyValue':('keyValue', 'MFFloat', 1),
+ },
+ {
+ 'key':[],
+ 'keyValue':[],
+ },
+ {
+ 'value_changed':('value_changed', 'SFFloat', 1),
+ 'set_fraction':('set_fraction', 'SFFloat', 0),
+ },
+)
+Shape = Prototype( "Shape",
+ {
+ 'appearance':('appearance', 'SFNode', 1),
+ 'geometry':('geometry', 'SFNode', 1),
+ },
+ {
+ 'appearance':NULL,
+ 'geometry':NULL,
+ },
+ {
+ },
+)
+Sound = Prototype( "Sound",
+ {
+ 'spatialize':('spatialize', 'SFBool', 0),
+ 'maxFront':('maxFront', 'SFFloat', 1),
+ 'minBack':('minBack', 'SFFloat', 1),
+ 'maxBack':('maxBack', 'SFFloat', 1),
+ 'minFront':('minFront', 'SFFloat', 1),
+ 'location':('location', 'SFVec3f', 1),
+ 'intensity':('intensity', 'SFFloat', 1),
+ 'direction':('direction', 'SFVec3f', 1),
+ 'source':('source', 'SFNode', 1),
+ 'priority':('priority', 'SFFloat', 1),
+ },
+ {
+ 'spatialize':1,
+ 'maxFront':10.0,
+ 'minBack':1.0,
+ 'maxBack':10.0,
+ 'minFront':1.0,
+ 'location':[0.0, 0.0, 0.0],
+ 'intensity':1.0,
+ 'direction':[0.0, 0.0, 1.0],
+ 'source':NULL,
+ 'priority':0.0,
+ },
+ {
+ },
+)
+Sphere = Prototype( "Sphere",
+ {
+ 'radius':('radius', 'SFFloat', 0),
+ },
+ {
+ 'radius':1.0,
+ },
+ {
+ },
+)
+SphereSensor = Prototype( "SphereSensor",
+ {
+ 'offset':('offset', 'SFRotation', 1),
+ 'autoOffset':('autoOffset', 'SFBool', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ },
+ {
+ 'offset':[0.0, 1.0, 0.0, 0.0],
+ 'autoOffset':1,
+ 'enabled':1,
+ },
+ {
+ 'rotation_changed':('rotation_changed', 'SFRotation', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'trackPoint_changed':('trackPoint_changed', 'SFVec3f', 1),
+ },
+)
+SpotLight = Prototype( "SpotLight",
+ {
+ 'attenuation':('attenuation', 'SFVec3f', 1),
+ 'ambientIntensity':('ambientIntensity', 'SFFloat', 1),
+ 'cutOffAngle':('cutOffAngle', 'SFFloat', 1),
+ 'direction':('direction', 'SFVec3f', 1),
+ 'color':('color', 'SFColor', 1),
+ 'location':('location', 'SFVec3f', 1),
+ 'radius':('radius', 'SFFloat', 1),
+ 'intensity':('intensity', 'SFFloat', 1),
+ 'beamWidth':('beamWidth', 'SFFloat', 1),
+ 'on':('on', 'SFBool', 1),
+ },
+ {
+ 'attenuation':[1.0, 0.0, 0.0],
+ 'ambientIntensity':0.0,
+ 'cutOffAngle':0.785398,
+ 'direction':[0.0, 0.0, -1.0],
+ 'color':[1.0, 1.0, 1.0],
+ 'location':[0.0, 0.0, 0.0],
+ 'radius':100.0,
+ 'intensity':1.0,
+ 'beamWidth':1.570796,
+ 'on':1,
+ },
+ {
+ },
+)
+Switch = Prototype( "Switch",
+ {
+ 'choice':('choice', 'MFNode', 1),
+ 'whichChoice':('whichChoice', 'SFInt32', 1),
+ },
+ {
+ 'choice':[],
+ 'whichChoice':-1,
+ },
+ {
+ },
+)
+Text = Prototype( "Text",
+ {
+ 'maxExtent':('maxExtent', 'SFFloat', 1),
+ 'string':('string', 'MFString', 1),
+ 'fontStyle':('fontStyle', 'SFNode', 1),
+ 'length':('length', 'MFFloat', 1),
+ },
+ {
+ 'maxExtent':0.0,
+ 'string':[],
+ 'fontStyle':NULL,
+ 'length':[],
+ },
+ {
+ },
+)
+TextureCoordinate = Prototype( "TextureCoordinate",
+ {
+ 'point':('point', 'MFVec2f', 1),
+ },
+ {
+ 'point':[],
+ },
+ {
+ },
+)
+TextureTransform = Prototype( "TextureTransform",
+ {
+ 'center':('center', 'SFVec2f', 1),
+ 'scale':('scale', 'SFVec2f', 1),
+ 'rotation':('rotation', 'SFFloat', 1),
+ 'translation':('translation', 'SFVec2f', 1),
+ },
+ {
+ 'center':[0.0, 0.0],
+ 'scale':[1.0, 1.0],
+ 'rotation':0.0,
+ 'translation':[0.0, 0.0],
+ },
+ {
+ },
+)
+TimeSensor = Prototype( "TimeSensor",
+ {
+ 'loop':('loop', 'SFBool', 1),
+ 'cycleInterval':('cycleInterval', 'SFTime', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ 'stopTime':('stopTime', 'SFTime', 1),
+ 'startTime':('startTime', 'SFTime', 1),
+ },
+ {
+ 'loop':0,
+ 'cycleInterval':1.0,
+ 'enabled':1,
+ 'stopTime':0.0,
+ 'startTime':0.0,
+ },
+ {
+ 'fraction_changed':('fraction_changed', 'SFFloat', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'time':('time', 'SFTime', 1),
+ 'cycleTime':('cycleTime', 'SFTime', 1),
+ },
+)
+TouchSensor = Prototype( "TouchSensor",
+ {
+ 'enabled':('enabled', 'SFBool', 1),
+ },
+ {
+ 'enabled':1,
+ },
+ {
+ 'hitNormal_changed':('hitNormal_changed', 'SFVec3f', 1),
+ 'hitPoint_changed':('hitPoint_changed', 'SFVec3f', 1),
+ 'touchTime':('touchTime', 'SFTime', 1),
+ 'hitTexCoord_changed':('hitTexCoord_changed', 'SFVec2f', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'isOver':('isOver', 'SFBool', 1),
+ },
+)
+Transform = Prototype( "Transform",
+ {
+ 'bboxSize':('bboxSize', 'SFVec3f', 0),
+ 'children':('children', 'MFNode', 1),
+ 'scaleOrientation':('scaleOrientation', 'SFRotation', 1),
+ 'rotation':('rotation', 'SFRotation', 1),
+ 'translation':('translation', 'SFVec3f', 1),
+ 'bboxCenter':('bboxCenter', 'SFVec3f', 0),
+ 'center':('center', 'SFVec3f', 1),
+ 'scale':('scale', 'SFVec3f', 1),
+ },
+ {
+ 'bboxSize':[-1.0, -1.0, -1.0],
+ 'children':[],
+ 'scaleOrientation':[0.0, 0.0, 1.0, 0.0],
+ 'rotation':[0.0, 0.0, 1.0, 0.0],
+ 'translation':[0.0, 0.0, 0.0],
+ 'bboxCenter':[0.0, 0.0, 0.0],
+ 'center':[0.0, 0.0, 0.0],
+ 'scale':[1.0, 1.0, 1.0],
+ },
+ {
+ 'addChildren':('addChildren', 'MFNode', 0),
+ 'removeChildren':('removeChildren', 'MFNode', 0),
+ },
+)
+Viewpoint = Prototype( "Viewpoint",
+ {
+ 'jump':('jump', 'SFBool', 1),
+ 'orientation':('orientation', 'SFRotation', 1),
+ 'fieldOfView':('fieldOfView', 'SFFloat', 1),
+ 'position':('position', 'SFVec3f', 1),
+ 'description':('description', 'SFString', 0),
+ },
+ {
+ 'jump':1,
+ 'orientation':[0.0, 0.0, 1.0, 0.0],
+ 'fieldOfView':0.785398,
+ 'position':[0.0, 0.0, 10.0],
+ 'description':'',
+ },
+ {
+ 'isBound':('isBound', 'SFBool', 1),
+ 'set_bind':('set_bind', 'SFBool', 0),
+ 'bindTime':('bindTime', 'SFTime', 1),
+ },
+)
+VisibilitySensor = Prototype( "VisibilitySensor",
+ {
+ 'size':('size', 'SFVec3f', 1),
+ 'center':('center', 'SFVec3f', 1),
+ 'enabled':('enabled', 'SFBool', 1),
+ },
+ {
+ 'size':[0.0, 0.0, 0.0],
+ 'center':[0.0, 0.0, 0.0],
+ 'enabled':1,
+ },
+ {
+ 'exitTime':('exitTime', 'SFTime', 1),
+ 'isActive':('isActive', 'SFBool', 1),
+ 'enterTime':('enterTime', 'SFTime', 1),
+ },
+)
+WorldInfo = Prototype( "WorldInfo",
+ {
+ 'title':('title', 'SFString', 0),
+ 'info':('info', 'MFString', 0),
+ },
+ {
+ 'title':'',
+ 'info':[],
+ },
+ {
+ },
+)
diff --git a/intern/python/modules/vrml/fieldcoercian.py b/intern/python/modules/vrml/fieldcoercian.py
new file mode 100644
index 00000000000..a90f1101b5a
--- /dev/null
+++ b/intern/python/modules/vrml/fieldcoercian.py
@@ -0,0 +1,310 @@
+'''
+Field coercian routines.
+
+To replace the field coercian routines, you must edit
+basenodes.py and node.py to import some other coercian
+routines. Basenodes.py is for use by the parser, node
+is used by each node as it checks the validity of its
+attributes.
+'''
+
+import types, sys, string
+from utils import typeclasses, collapse
+
+class FieldCoercian:
+ '''
+ A Field Coercian class allows for creating new behaviours
+ when dealing with the conversion of fields to-and-from
+ particular field types. This allows the programmer to
+ use alternate representations of fields (such as matrix arrays)
+ '''
+ def SFString( self, someobj, targetType=types.StringType, targetName='SFString', convertfunc=str ):
+ '''
+ Allowable types:
+ simple string -> unchanged
+ instance ( an IS ) -> unchanged
+ sequence of length == 1 where first element is a string -> returns first element
+ sequence of length > 1 where all elements are strings -> returns string.join( someobj, '')
+ '''
+ t = type(someobj)
+ if t is targetType:
+ return someobj
+ if t in typeclasses.SequenceTypes:
+ if len( someobj) == 1 and type( someobj[0] ) is targetType:
+ return someobj[0] #
+ elif len(someobj) > 1:
+ try:
+ return string.join( someobj, '')
+ except:
+ pass # is not a sequence of strings...
+ ### if we get here, then an incorrect value was passed
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+
+ def MFString( self, someobj, targetType=types.StringType, targetName='SFString', convertfunc=str ):
+ '''
+ Allowable Types:
+ simple string -> wrapped in a list
+ instance (an IS ) -> unchanged
+ sequence of strings (of any length) -> equivalent list returned
+ '''
+ t = type(someobj)
+ if t is targetType: # a bare string...
+ return [someobj]
+ elif t in typeclasses.SequenceTypes: # is a sequence
+ if not filter( lambda x, t=targetType: x is not t, map( type, someobj) ): # are all strings...
+ if t is not types.ListType:
+ return list( someobj )
+ else:
+ return someobj
+ ### if we get here, then an incorrect value was passed
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+
+ def SFBool( self, someobj, targetType=types.IntType, targetName='SFBool', convertfunc=int):
+ '''
+ Allowable Types:
+ instance (an IS) -> unchanged
+ Any object which is testable for truth/falsehood -> 1 or 0 respectively
+ SFBool should always succeed
+ '''
+ if (type(someobj) in typeclasses.SequenceTypes):
+ try:
+ if hasattr( someobj[0], '__gi__'):
+ return someobj[0]
+ else:
+ someobj = someobj[0]
+ except IndexError: # is a null MFNode
+ pass
+ if someobj:
+ return 1
+ else:
+ return 0
+
+ def SFNode( self, someobj, targetType=types.InstanceType, targetName='SFNode', convertfunc=None):
+ '''
+ Allowable Types:
+ instance of a Node -> unchanged
+ instance (an IS or USE) -> unchanged
+ sequence of length == 1 where first element is as above -> return first element
+ '''
+ if hasattr( someobj, '__gi__'): # about the only test I have without requiring that elements inherit from Node
+ return someobj
+ elif (type(someobj) in typeclasses.SequenceTypes):
+ try:
+ if hasattr( someobj[0], '__gi__'):
+ return someobj[0]
+ except IndexError: # is a null MFNode
+ pass
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+
+ def MFNode( self, someobj, targetType=types.InstanceType, targetName='MFNode', convertfunc=None):
+ '''
+ Allowable Types:
+ instance (an IS) -> unchanged
+ instance of a Node -> wrapped with a list
+ sequence where all elements are nodes -> returned as list of same
+ '''
+ if hasattr( someobj, '__gi__') and someobj.__gi__ != "IS":
+ # is this a bare SFNode? wrap with a list and return
+ return [someobj]
+ elif hasattr( someobj, "__gi__"): # is this an IS node
+ return someobj
+ elif type(someobj) in typeclasses.SequenceTypes:
+ try:
+ map( getattr, someobj, ['__gi__']*len(someobj) )
+ # is this an IS node wrapped in a list?
+ if len(someobj) == 1 and someobj[0].__gi__ == "IS":
+ return someobj[0]
+ # okay, assume is really nodes...
+ if type(someobj) is types.ListType:
+ return someobj
+ else:
+ return list(someobj)
+ except AttributeError: # something isn't a node
+ pass
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+
+ def SFNumber( self, someobj, targetType, targetName, convertfunc=int ):
+ '''
+ Allowable Types:
+ bare number -> numerically coerced to correct type
+ instance ( an IS ) -> unchanged
+ sequence of length == 1 where first element is a string -> returns first element
+ '''
+ t = type(someobj)
+ if t is targetType or t is types.InstanceType:
+ return someobj
+ elif t in typeclasses.NumericTypes:
+ return convertfunc( someobj)
+ elif t in typeclasses.SequenceTypes:
+ if len( someobj) == 1 and type( someobj[0] ):
+ return convertfunc( someobj[0] ) #
+ ### if we get here, then an incorrect value was passed
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+ def MFInt32 ( self, someobject ):
+ ''' Convert value into a MFInt32 field value (preferably an array, otherwise a list of integers) '''
+ t = type(someobject)
+ value = None
+ if t in typeclasses.SequenceTypes: # is a sequence
+ try:
+ value = map( int, someobject)
+ except:
+ try:
+ value = map( int, collapse.collapse2_safe( someobject) )
+ except:
+ pass
+ elif t in typeclasses.NumericTypes or t is types.StringType:
+ value = [int(someobject)]
+ if value is None:
+ ### if we get here, then an incorrect value was passed
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+ return value
+ SFImage = MFInt32
+ def MFFloat( self, someobject ):
+ ''' Convert value into a MFFloat field value (preferably an array, otherwise a list of integers) '''
+ t = type(someobject)
+ value = None
+ if t in typeclasses.SequenceTypes: # is a sequence
+ try:
+ value = map( float, someobject)
+ except:
+ try:
+ value = map( float, collapse.collapse2_safe( someobject))
+ except:
+ pass
+ elif t in typeclasses.NumericTypes or t is types.StringType:
+ value = [float(someobj)]
+ if value is None:
+ ### if we get here, then an incorrect value was passed
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+ return value
+ def SFVec3f (self, value):
+ ''' Create a new SFVec3f value from value '''
+ t = type(value)
+ try:
+ value = x,y,z = map (float, value)
+ except ValueError:
+ try:
+ value = (x,y,z) = map( float, value[0] )
+ except (IndexError, ValueError):
+ raise ValueError (''' Invalid value for field type SFVec3f: %s'''%(value))
+ return value
+ def SFRotation(self, value):
+ ''' Create a new SFRotation value from value '''
+ t = type(value)
+ try:
+ value = x,y,z, a = map (float, value)
+ except ValueError:
+ try:
+ value = (x,y,z, a) = map( float, value[0] )
+ except (IndexError, ValueError):
+ raise ValueError (''' Invalid value for field type SFRotation: %s'''%(value))
+ # get the normalized vector for x,y,z
+## length = (x*x+y*y+z*z)**.5 or 0.0000
+## value = (x/length,y/length,z/length, a)
+ return value
+ def SFVec2f (self, value):
+ ''' Create a new SFVec3f value from value '''
+ t = type(value)
+ try:
+ value = x,y = map (float, value)
+ except ValueError:
+ try:
+ value = (x,y) = map( float, value[0] )
+ except (IndexError, ValueError):
+ raise ValueError (''' Invalid value for field type SFVec3f: %s'''%(value))
+ return value
+ def SFColor(self, value):
+ ''' Create a new SFVec3f value from value '''
+ t = type(value)
+ try:
+ r,g,b = map (float, value)
+ except ValueError:
+ try:
+ r,g,b = map( float, value[0] )
+ except (IndexError, ValueError):
+ raise ValueError (''' Invalid value for field type SFColor: %s'''%(value))
+ r = max( (0.0, min((r,1.0))) )
+ g = max( (0.0, min((g,1.0))) )
+ b = max( (0.0, min((b,1.0))) )
+ return value
+
+ def MFCompoundNumber( self, someobj, targetName='SFVec3f', convertfunc=float, type=type):
+ '''
+ Allowable Types:
+ instance ( an IS ) -> unchanged
+ # instance ( a matrix ) -> reshaped (eventually)
+ list of lists, sub-sequences of proper length -> unchanged
+ sequence of numeric types of proper length -> converted to list, diced
+ '''
+## if targetName == 'SFColor':
+## import pdb
+## pdb.set_trace()
+ converter = getattr( self, targetName )
+ t = type( someobj)
+ reporterror = 0
+ if t is types.InstanceType:
+ return someobj
+ elif t in typeclasses.SequenceTypes:
+ if not someobj:
+ return []
+ if type( someobj[0] ) is not types.StringType and type( someobj[0] ) in typeclasses.SequenceTypes:
+ try:
+ return map( converter, someobj )
+ except ValueError:
+ pass
+ elif type( someobj[0] ) in typeclasses.NumericTypes or type( someobj[0] ) is types.StringType:
+ # a single-level list?
+ base = map( convertfunc, someobj )
+ # if we get here, someobj is a list
+ if targetName[-2:] == '2f': # vec2f
+ tlen = 2
+ elif targetName[-2:] == 'on': # rotation
+ tlen = 4
+ else:
+ tlen = 3
+ value = []
+ while base:
+ value.append( converter( base[:tlen]) )
+ del base[:tlen]
+ return value
+ raise ValueError, """Attempted to set value for an %s field which is not compatible: %s"""%( targetName, `someobj` )
+ def __call__( self, someobj, targetName):
+ func, args = self.algomap[targetName]
+## try:
+## if targetName == 'SFInt32':
+## import pdb
+## pdb.set_trace()
+ if hasattr( someobj, "__gi__") and someobj.__gi__ == "IS":
+ return someobj
+ else:
+ return apply( func, (self, someobj)+args )
+## except TypeError:
+## print someobj, targetName
+## print func, args
+## raise
+
+ algomap = { \
+ 'SFString': (SFString, (types.StringType, 'SFString', str)), \
+ 'MFString': (MFString, (types.StringType, 'MFString', str)), \
+ 'SFInt32': (SFNumber, (types.IntType, 'SFInt32', int)), \
+ 'SFFloat': (SFNumber, (types.FloatType, 'SFFloat', float)), \
+ 'SFTime': (SFNumber, (types.FloatType, 'SFFloat', float)), \
+ 'SFColor': (SFColor, ()), \
+ 'SFVec2f': (SFVec2f, ()), \
+ 'SFVec3f': (SFVec3f, ()), \
+ 'SFNode': (SFNode, (types.InstanceType, 'SFNode', None)), \
+ 'SFBool': (SFBool, (types.IntType, 'SFBool', int)), \
+ 'SFNode': (SFNode, (types.InstanceType, 'SFNode', None)), \
+ 'MFInt32': (MFInt32, ()), \
+ 'SFImage': (MFInt32, ()), \
+ 'MFTime': (MFFloat, ()), \
+ 'MFFloat': (MFFloat, ()), \
+ 'MFColor': (MFCompoundNumber, ('SFColor', float)), \
+ 'MFVec2f': (MFCompoundNumber, ('SFVec2f', float)), \
+ 'MFVec3f': (MFCompoundNumber, ('SFVec3f', float)), \
+ 'SFRotation': (SFRotation, ()), \
+ 'MFRotation': (MFCompoundNumber, ('SFRotation', float)), \
+ 'MFNode': (MFNode, (types.InstanceType, 'MFNode', None)) \
+ }
+
+FIELDCOERCE = FieldCoercian ()
diff --git a/intern/python/modules/vrml/loader.py b/intern/python/modules/vrml/loader.py
new file mode 100644
index 00000000000..dd53fe49fd3
--- /dev/null
+++ b/intern/python/modules/vrml/loader.py
@@ -0,0 +1,97 @@
+# The VRML loader
+# supports gzipped files
+#
+# TODO: better progress monitoring
+
+import parser
+
+def quiet(txt):
+ pass
+
+debug = quiet
+
+def debug1(txt):
+ print "Loader:", txt
+
+g_last = 0
+
+def getFileType(file):
+ "returns the file type string from 'file'"
+ file.seek(0)
+ magic = file.readline()
+ if magic[:3] == '\037\213\010':
+ file.seek(0)
+ return "gzip"
+ elif magic[:10] == '#VRML V2.0':
+ file.seek(0)
+ return "vrml"
+ else:
+ file.seek(0)
+ return ""
+
+class Loader:
+ def __init__(self, url, progress = None):
+ self.url = url
+ self.debug = debug
+ self.fail = debug
+ self.monitor = debug
+ self.progress = progress
+ self.nodes = 0 # number of nodes parsed
+
+ def getGzipFile(self, file):
+ '''Return gzip file (only called when gzip type is recognised)'''
+ # we now have the local filename and the headers
+ # read the first few bytes, check for gzip magic number
+ self.monitor( "gzip-encoded file... loading gzip library")
+ try:
+ import gzip
+ file = gzip.open(file,"rb")
+ return file
+ except ImportError, value:
+ self.fail("Gzip library unavailable, compressed file cannot be read")
+ except:
+ self.fail("Failed to open Gzip file")
+
+ return None
+
+ def load(self):
+ self.debug("try: load file from %s" % self.url)
+ url = self.url
+
+ # XXX
+ try:
+ file = open(url, 'rb')
+ except IOError, val:
+ self.debug("couldn't open file %s" % url)
+ return None
+
+ if getFileType(file) == 'gzip':
+ file.close()
+ file = self.getGzipFile(url)
+ try:
+ data = file.read()
+ except MemoryError, value:
+ self.fail("Insufficient memory to load file as string", value)
+ return None
+ except IOError, value:
+ self.fail("I/O Error while reading data from file %s "% url)
+ p = parser.Parser(data)
+ if self.progress:
+ scenegraph = p.parse(self.progress)
+ print "progress"
+ else:
+ scenegraph = p.parse()
+
+ self.nodes = p.progresscount # progress
+ del p
+ return scenegraph
+
+
+def load(url, progress = None):
+ l = Loader(url, progress)
+ return l.load()
+
+def test(name = None):
+ if not name:
+ name = '/tmp/gna.wrl'
+ return load(name)
diff --git a/intern/python/modules/vrml/parser.py b/intern/python/modules/vrml/parser.py
new file mode 100644
index 00000000000..1f238126550
--- /dev/null
+++ b/intern/python/modules/vrml/parser.py
@@ -0,0 +1,426 @@
+from TextTools import TextTools
+
+from simpleparse import generator
+
+import scenegraph as proto
+import strop as string
+
+IMPORT_PARSE_TIME = 0.4
+PROGRESS_DEPTH = 5
+
+class UnfinishedError(Exception):
+ pass
+
+class Parser:
+ def __init__( self, data ):
+ self.data = data
+ self.position = 0
+ self.result = proto.sceneGraph()
+ self.finalised = None
+ self.sceneGraphStack = [self.result]
+ self.prototypeStack = []
+ self.nodeStack = []
+ self.fieldTypeStack = []
+ self.readHeader()
+ self.depth = 0
+ self.progresscount = 0
+ def _lines( self, index=None ):
+ if index is None:
+ index = self.position
+ return TextTools.countlines (self.data[:index])
+ def parse( self, progressCallback=None ):
+ datalength = float( len( self.data ))
+ while self.readNext():
+ if progressCallback:
+ if not progressCallback(IMPORT_PARSE_TIME * self.position/datalength ):
+ raise UnfinishedError(
+ "Did not complete parsing, cancelled by user. Stopped at line %s" %(self._lines())
+ )
+ if self.position < len( self.data ):
+ raise UnfinishedError(
+ '''Unable to complete parsing of file, stopped at line %s:\n%s...'''%(self._lines(), self.data[self.position:self.position+120])
+ )
+ return self.result
+ def readHeader( self ):
+ '''Read the file header'''
+ success, tags, next = TextTools.tag( self.data, HEADERPARSER, self.position )
+ if success:
+ self.datalength = len( self.data )
+ #print "header ok"
+ return success
+ else:
+ try:
+ self.decompress()
+ success, tags, next = TextTools.tag( self.data, HEADERPARSER, self.position )
+ self.datalength = len( self.data )
+ return success
+ except:
+ raise ValueError( "Could not find VRML97 header in file!" )
+ def readNext( self):
+ '''Read the next root-level construct'''
+ success, tags, next = TextTools.tag( self.data, ROOTITEMPARSER, self.position )
+## print 'readnext', success
+ if self.position >= self.datalength:
+ print 'reached file end'
+ return None
+ if success:
+# print ' successful parse'
+ self.position = next
+ map (self.rootItem_Item, tags )
+ return success
+ else:
+ return None
+ def rootItem (self, (type, start, stop, (item,))):
+ ''' Process a single root item '''
+ self.rootItem_Item( item )
+ def rootItem_Item( self, item ):
+ result = self._dispatch(item)
+ if result is not None:
+## print "non-null result"
+## print id( self.sceneGraphStack[-1] ), id(self.result )
+ self.sceneGraphStack[-1].children.append( result )
+ def _getString (self, (tag, start, stop, sublist)):
+ ''' Return the raw string for a given interval in the data '''
+ return self.data [start: stop]
+
+ def _dispatch (self, (tag, left, right, sublist)):
+ ''' Dispatch to the appropriate processing function based on tag value '''
+## print "dispatch", tag
+ self.depth += 1
+ if self.depth < PROGRESS_DEPTH:
+ self.progresscount += 1
+ try:
+ meth = getattr (self, tag)
+ except AttributeError:
+ raise AttributeError("Unknown parse tag '%s' found! Check the parser definition!" % (tag))
+ ret = meth( (tag, left, right, sublist) )
+ self.depth -= 1
+ return ret
+
+ def Proto(self, (tag, start, stop, sublist)):
+ ''' Create a new prototype in the current sceneGraph '''
+ # first entry is always ID
+ ID = self._getString ( sublist [0])
+ print "PROTO",ID
+ newNode = proto.Prototype (ID)
+## print "\t",newNode
+ setattr ( self.sceneGraphStack [-1].protoTypes, ID, newNode)
+ self.prototypeStack.append( newNode )
+ # process the rest of the entries with the given stack
+ map ( self._dispatch, sublist [1:] )
+ self.prototypeStack.pop( )
+ def fieldDecl(self,(tag, left, right, (exposure, datatype, name, field))):
+ ''' Create a new field declaration for the current prototype'''
+ # get the definition in recognizable format
+ exposure = self._getString (exposure) == "exposedField"
+ datatype = self._getString (datatype)
+ name = self._getString (name)
+ # get the vrml value for the field
+ self.fieldTypeStack.append( datatype )
+ field = self._dispatch (field)
+ self.fieldTypeStack.pop( )
+ self.prototypeStack[-1].addField ((name, datatype, exposure), field)
+ def eventDecl(self,(tag, left, right, (direction, datatype, name))):
+ # get the definition in recognizable format
+ direction = self._getString (direction) == "eventOut"
+ datatype = self._getString (datatype)
+ name = self._getString (name)
+ # get the vrml value for the field
+ self.prototypeStack[-1].addEvent((name, datatype, direction))
+ def decompress( self ):
+ pass
+ def ExternProto( self, (tag, start, stop, sublist)):
+ ''' Create a new external prototype from a tag list'''
+ # first entry is always ID
+ ID = self._getString ( sublist [0])
+ newNode = proto.Prototype (ID)
+ setattr ( self.sceneGraphStack [-1].protoTypes, ID, newNode)
+ self.prototypeStack.append( newNode )
+ # process the rest of the entries with the given stack
+ map ( self._dispatch, sublist [1:] )
+ self.prototypeStack.pop( )
+ def ExtProtoURL( self, (tag, start, stop, sublist)):
+ ''' add the url to the external prototype '''
+## print sublist
+ values = self.MFString( sublist )
+ self.prototypeStack[-1].url = values
+ return values
+ def extFieldDecl(self, (tag, start, stop, (exposure, datatype, name))):
+ ''' An external field declaration, no default value '''
+ # get the definition in recognizable format
+ exposure = self._getString (exposure) == "exposedField"
+ datatype = self._getString (datatype)
+ name = self._getString (name)
+ # get the vrml value for the field
+ self.prototypeStack[-1].addField ((name, datatype, exposure))
+ def ROUTE(self, (tag, start, stop, names )):
+ ''' Create a new route object, add the current sceneGraph '''
+ names = map(self._getString, names)
+ self.sceneGraphStack [-1].addRoute( names )
+ def Node (self, (tag, start, stop, sublist)):
+ ''' Create new node, returning the value to the caller'''
+## print 'node'
+
+ if sublist[0][0] == 'name':
+ name = self._getString ( sublist [0])
+ ID = self._getString ( sublist [1])
+ rest = sublist [2:]
+ else:
+ name = ""
+ ID = self._getString ( sublist [0])
+ rest = sublist [1:]
+ try:
+ prototype = getattr ( self.sceneGraphStack [-1].protoTypes, ID)
+ except AttributeError:
+ #raise NameError ('''Prototype %s used without declaration! %s:%s'''%(ID, start, stop) )
+ print ('''### Prototype %s used without declaration! %s:%s'''%(ID, start, stop) )
+
+ return None
+ newNode = prototype(name)
+ if name:
+ self.sceneGraphStack [-1].regDefName( name, newNode )
+ self.nodeStack.append (newNode)
+ map (self._dispatch, rest)
+ self.nodeStack.pop ()
+## print 'node finished'
+ return newNode
+ def Attr(self, (tag, start, stop, (name, value))):
+ ''' An attribute of a node or script '''
+ name = self._getString ( name )
+ self.fieldTypeStack.append( self.nodeStack[-1].PROTO.getField( name ).type )
+ value = self._dispatch( value )
+ self.fieldTypeStack.pop()
+ if hasattr( self.nodeStack[-1], "__setattr__" ):
+ self.nodeStack[-1].__setattr__( name, value, raw=1 )
+ else:
+ # use slower coercing versions...
+ setattr( self.nodeStack[-1], name, value )
+ def Script( self, (tag, start, stop, sublist)):
+ ''' A script node (can be a root node)'''
+ # what's the DEF name...
+ if sublist and sublist[0][0] == 'name':
+ name = self._getString ( sublist [0])
+ rest = sublist [1:]
+ else:
+ name = ""
+ rest = sublist
+ # build the script node...
+ newNode = proto.Script( name )
+ # register with sceneGraph
+ if name:
+ self.sceneGraphStack [-1].regDefName( name, newNode )
+ self.nodeStack.append (newNode)
+ map( self._dispatch, rest )
+ self.nodeStack.pop ()
+ return newNode
+ def ScriptEventDecl( self,(tag, left, right, sublist)):
+ # get the definition in recognizable format
+ direction, datatype, name = sublist[:3] # must have at least these...
+ direction = self._getString (direction) == "eventOut"
+ datatype = self._getString (datatype)
+ name = self._getString (name)
+ # get the vrml value for the field
+ self.nodeStack[-1].PROTO.addEvent((name, datatype, direction))
+ if sublist[3:]:
+ # will this work???
+ setattr( self.nodeStack[-1], name, self._dispatch( sublist[3] ) )
+ def ScriptFieldDecl(self,(tag, left, right, (exposure, datatype, name, field))):
+ ''' Create a new field declaration for the current prototype'''
+ # get the definition in recognizable format
+ exposure = self._getString (exposure) == "exposedField"
+ datatype = self._getString (datatype)
+ name = self._getString (name)
+ # get the vrml value for the field
+ self.fieldTypeStack.append( datatype )
+ field = self._dispatch (field)
+ self.fieldTypeStack.pop( )
+ self.nodeStack[-1].PROTO.addField ((name, datatype, exposure))
+ setattr( self.nodeStack[-1], name, field )
+ def SFNull(self, tup):
+ ''' Create a reference to the SFNull node '''
+## print 'hi'
+ return proto.NULL
+ def USE( self, (tag, start, stop, (nametuple,) )):
+ ''' Create a reference to an already defined node'''
+ name = self._getString (nametuple)
+ if self.depth < PROGRESS_DEPTH:
+ self.progresscount += 1
+ try:
+ node = self.sceneGraphStack [-1].defNames [name]
+ return node
+ except KeyError:
+ raise NameError ('''USE without DEF for node %s %s:%s'''%(name, start, stop))
+ def IS(self, (tag, start, stop, (nametuple,))):
+ ''' Create a field reference '''
+ name = self._getString (nametuple)
+ if not self.prototypeStack [-1].getField (name):
+ raise Exception (''' Attempt to create IS mapping of non-existent field %s %s:%s'''%(name, start, stop))
+ return proto.IS(name)
+ def Field( self, (tag, start, stop, sublist)):
+ ''' A field value (of any type) '''
+
+ if sublist and sublist[0][0] in ('USE','Script','Node','SFNull'):
+ if self.fieldTypeStack[-1] == 'SFNode':
+ return self._dispatch( sublist[0] )
+ else:
+ return map( self._dispatch, sublist )
+ elif self.fieldTypeStack[-1] == 'MFNode':
+ return []
+ else:
+ # is a simple data type...
+ function = getattr( self, self.fieldTypeStack[-1] )
+ try:
+ return function( sublist )
+ except ValueError:
+ traceback.print_exc()
+ print sublist
+ raise
+
+ def SFBool( self, (tup,) ):
+ '''Boolean, in Python tradition is either 0 or 1'''
+ return self._getString(tup) == 'TRUE'
+ def SFFloat( self, (x,) ):
+ return string.atof( self._getString(x) )
+ SFTime = SFFloat
+ def SFInt32( self, (x,) ):
+ return string.atoi( self._getString(x), 0 ) # allow for non-decimal numbers
+ def SFVec3f( self, (x,y,z) ):
+ return map( string.atof, map(self._getString, (x,y,z)) )
+ def SFVec2f( self, (x,y) ):
+ return map( string.atof, map(self._getString, (x,y)) )
+ def SFColor( self, (r,g,b) ):
+ return map( string.atof, map(self._getString, (r,g,b)) )
+ def SFRotation( self, (x,y,z,a) ):
+ return map( string.atof, map(self._getString, (x,y,z,a)) )
+
+ def MFInt32( self, tuples ):
+ result = []
+ # localisation
+ atoi = string.atoi
+ append = result.append
+ data = self.data
+ for tag, start, stop, children in tuples:
+ append( atoi( data[start:stop], 0) )
+ return result
+ SFImage = MFInt32
+ def MFFloat( self, tuples ):
+ result = []
+ # localisation
+ atof = string.atof
+ append = result.append
+ data = self.data
+ for tag, start, stop, children in tuples:
+ append( atof( data[start:stop]) )
+ return result
+ MFTime = MFFloat
+ def MFVec3f( self, tuples, length=3, typename='MFVec3f'):
+ result = []
+ # localisation
+ atof = string.atof
+ data = self.data
+ while tuples:
+ newobj = []
+ for tag, start, stop, children in tuples[:length]:
+ newobj.append( atof(data[start:stop] ))
+ if len(newobj) != length:
+ raise ValueError(
+ '''Incorrect number of elements in %s field at line %s'''%(typename, self._lines(stop))
+ )
+ result.append( newobj )
+ del tuples[:length]
+ return result
+ def MFVec2f( self, tuples):
+ return self.MFVec3f( tuples, length=2, typename='MFVec2f')
+ def MFRotation( self, tuples ):
+ return self.MFVec3f( tuples, length=4, typename='MFRotation')
+ def MFColor( self, tuples ):
+ return self.MFVec3f( tuples, length=3, typename='MFColor')
+
+ def MFString( self, tuples ):
+ bigresult = []
+ for (tag, start, stop, sublist) in tuples:
+ result = []
+ for element in sublist:
+ if element[0] == 'CHARNODBLQUOTE':
+ result.append( self.data[element[1]:element[2]] )
+ elif element[0] == 'ESCAPEDCHAR':
+ result.append( self.data[element[1]+1:element[2]] )
+ elif element[0] == 'SIMPLEBACKSLASH':
+ result.append( '\\' )
+ bigresult.append( string.join( result, "") )
+ return bigresult
+## result = []
+## for tuple in tuples:
+## result.append( self.SFString( tuple) )
+## return result
+ def SFString( self, tuples ):
+ '''Return the (escaped) string as a simple Python string'''
+ if tuples:
+ (tag, start, stop, sublist) = tuples[0]
+ if len( tuples ) > 1:
+ print '''Warning: SFString field has more than one string value''', self.data[tuples[0][1]:tuples[-1][2]]
+ result = []
+ for element in sublist:
+ if element[0] == 'CHARNODBLQUOTE':
+ result.append( self.data[element[1]:element[2]] )
+ elif element[0] == 'ESCAPEDCHAR':
+ result.append( self.data[element[1]+1:element[2]] )
+ elif element[0] == 'SIMPLEBACKSLASH':
+ result.append( '\\' )
+ return string.join( result, "")
+ else:
+ raise ValueError( "NULL SFString parsed???!!!" )
+ def vrmlScene( self, (tag, start, stop, sublist)):
+ '''A (prototype's) vrml sceneGraph'''
+ newNode = proto.sceneGraph (root=self.sceneGraphStack [-1])
+ self.sceneGraphStack.append (newNode)
+ #print 'setting proto sceneGraph', `newNode`
+ self.prototypeStack[-1].sceneGraph = newNode
+ results = filter (None, map (self._dispatch, sublist))
+ if results:
+ # items which are not auto-magically inserted into their parent
+ for result in results:
+ newNode.children.append( result)
+ self.sceneGraphStack.pop()
+
+PARSERDECLARATION = r'''header := -[\n]*
+rootItem := ts,(Proto/ExternProto/ROUTE/('USE',ts,USE,ts)/Script/Node),ts
+vrmlScene := rootItem*
+Proto := 'PROTO',ts,nodegi,ts,'[',ts,(fieldDecl/eventDecl)*,']', ts, '{', ts, vrmlScene,ts, '}', ts
+fieldDecl := fieldExposure,ts,dataType,ts,name,ts,Field,ts
+fieldExposure := 'field'/'exposedField'
+dataType := 'SFBool'/'SFString'/'SFFloat'/'SFTime'/'SFVec3f'/'SFVec2f'/'SFRotation'/'SFInt32'/'SFImage'/'SFColor'/'SFNode'/'MFBool'/'MFString'/'MFFloat'/'MFTime'/'MFVec3f'/'MFVec2f'/'MFRotation'/'MFInt32'/'MFColor'/'MFNode'
+eventDecl := eventDirection, ts, dataType, ts, name, ts
+eventDirection := 'eventIn'/'eventOut'
+ExternProto := 'EXTERNPROTO',ts,nodegi,ts,'[',ts,(extFieldDecl/eventDecl)*,']', ts, ExtProtoURL
+extFieldDecl := fieldExposure,ts,dataType,ts,name,ts
+ExtProtoURL := '['?,(ts,SFString)*, ts, ']'?, ts # just an MFString by another name :)
+ROUTE := 'ROUTE',ts, name,'.',name, ts, 'TO', ts, name,'.',name, ts
+Node := ('DEF',ts,name,ts)?,nodegi,ts,'{',ts,(Proto/ExternProto/ROUTE/Attr)*,ts,'}', ts
+Script := ('DEF',ts,name,ts)?,'Script',ts,'{',ts,(ScriptFieldDecl/ScriptEventDecl/Proto/ExternProto/ROUTE/Attr)*,ts,'}', ts
+ScriptEventDecl := eventDirection, ts, dataType, ts, name, ts, ('IS', ts, IS,ts)?
+ScriptFieldDecl := fieldExposure,ts,dataType,ts,name,ts,(('IS', ts,IS,ts)/Field),ts
+SFNull := 'NULL', ts
+
+# should really have an optimised way of declaring a different reporting name for the same production...
+USE := name
+IS := name
+nodegi := name
+Attr := name, ts, (('IS', ts,IS,ts)/Field), ts
+Field := ( '[',ts,((SFNumber/SFBool/SFString/('USE',ts,USE,ts)/Script/Node),ts)*, ']', ts )/((SFNumber/SFBool/SFNull/SFString/('USE',ts,USE,ts)/Script/Node),ts)+
+
+name := -[][0-9{}\000-\020"'#,.\\ ], -[][{}\000-\020"'#,.\\ ]*
+SFNumber := [-+]*, ( ('0',[xX],[0-9]+) / ([0-9.]+,([eE],[-+0-9.]+)?))
+SFBool := 'TRUE'/'FALSE'
+SFString := '"',(CHARNODBLQUOTE/ESCAPEDCHAR/SIMPLEBACKSLASH)*,'"'
+CHARNODBLQUOTE := -[\134"]+
+SIMPLEBACKSLASH := '\134'
+ESCAPEDCHAR := '\\"'/'\134\134'
+<ts> := ( [ \011-\015,]+ / ('#',-'\012'*,'\n')+ )*
+'''
+
+
+PARSERTABLE = generator.buildParser( PARSERDECLARATION )
+HEADERPARSER = PARSERTABLE.parserbyname( "header" )
+ROOTITEMPARSER = PARSERTABLE.parserbyname( "rootItem" )
+
diff --git a/intern/python/modules/vrml/scenegraph.py b/intern/python/modules/vrml/scenegraph.py
new file mode 100644
index 00000000000..2f137b1e259
--- /dev/null
+++ b/intern/python/modules/vrml/scenegraph.py
@@ -0,0 +1,833 @@
+# VRML node prototype class (SGbuilder)
+# Wed Oct 31 16:18:35 CET 2001
+
+'''Prototype2 -- VRML 97 sceneGraph/Node/Script/ROUTE/IS implementations'''
+import copy, types # extern
+import strop as string # builtin
+from utils import typeclasses, err, namespace # XXX
+## TODO: namespace must go
+
+
+class baseProto:
+ def __vrmlStr__( self, **namedargs ):
+ '''Generate a VRML 97-syntax string representing this Prototype
+ **namedargs -- key:value
+ passed arguments for the linearisation object
+ see lineariser4.Lineariser
+ '''
+ import lineariser4
+ lineariser = apply( lineariser4.Lineariser, (), namedargs )
+ return apply( lineariser.linear, ( self, ), namedargs )
+
+ toString = __vrmlStr__
+ # added stuff for linking support for target scenegraph
+ def setTargetnode(self, node):
+ self.__dict__['_targetnode'] = node
+ def getTargetnode(self):
+ try:
+ return self.__dict__['_targetnode']
+ except:
+ return None
+
+class Prototype(baseProto):
+ ''' A VRML 97 Prototype object
+
+ A Prototype is a callable object which produces Node instances
+ the Node uses a pointer to its Prototype to provide much of the
+ Node's standard functionality.
+
+ Prototype's are often stored in a sceneGraph's protoTypes namespace,
+ where you can access them as sceneGraph.protoTypes.nodeGI . They are
+ also commonly found in Nodes' PROTO attributes.
+
+ Attributes:
+ __gi__ -- constant string "PROTO"
+ nodeGI -- string gi
+ The "generic identifier" of the node type, i.e. the name of the node
+ fieldDictionary -- string name: (string name, string dataType, boolean exposed)
+ defaultDictionary -- string name: object defaultValue
+ Will be blank for EXTERNPROTO's and Script prototypes
+ eventDictionary -- string name: (string name, string dataType, boolean eventOut)
+ sceneGraph -- object sceneGraph
+ MFNodeNames -- list of field name strings
+ Allows for easy calculation of "children" nodes
+ SFNodeNames -- list of field name strings
+ Allows for easy calculation of "children" nodes
+ '''
+ __gi__ = "PROTO"
+ def __init__(self, gi, fieldDict=None, defaultDict=None, eventDict=None, sGraph=None):
+ '''
+ gi -- string gi
+ see attribute nodeGI
+ fieldDict -- string name: (string name, string dataType, boolean exposed)
+ see attribute fieldDictionary
+ defaultDict -- string name: object defaultValue
+ see attribute defaultDictionary
+ eventDict -- string name: (string name, string dataType, boolean eventOut)
+ see attribute eventDictionary
+ sceneGraph -- object sceneGraph
+ see attribute sceneGraph
+ '''
+ self.nodeGI = checkName( gi )
+ self.fieldDictionary = {}
+ self.defaultDictionary = {}
+ self.eventDictionary = {}
+ self.SFNodeNames = []
+ self.MFNodeNames = []
+ self.sceneGraph = sGraph
+
+ # setup the fields/events
+ for definition in (fieldDict or {}).values():
+ self.addField( definition, (defaultDict or {}).get( definition[0]))
+ for definition in (eventDict or {}).values():
+ self.addEvent( definition )
+
+ def getSceneGraph( self ):
+ ''' Retrieve the sceneGraph object (may be None object)
+ see attribute sceneGraph'''
+ return self.sceneGraph
+ def setSceneGraph( self, sceneGraph ):
+ ''' Set the sceneGraph object (may be None object)
+ see attribute sceneGraph'''
+ self.sceneGraph = sceneGraph
+ def getChildren(self, includeSceneGraph=None, includeDefaults=1, *args, **namedargs):
+ ''' Calculate the current children of the PROTO and return as a list of nodes
+ if includeDefaults:
+ include those default values which are node values
+ if includeSceneGraph:
+ include the sceneGraph object if it is not None
+
+ see attribute MFNodeNames
+ see attribute SFNodeNames
+ see attribute sceneGraph
+ '''
+ temp = []
+ if includeDefaults:
+ for attrname in self.SFNodeNames:
+ try:
+ temp.append( self.defaultDictionary[attrname] )
+ except KeyError: # sceneGraph object is not copied...
+ pass
+ for attrname in self.MFNodeNames:
+ try:
+ temp[len(temp):] = self.defaultDictionary[attrname]
+ except KeyError:
+ pass
+ if includeSceneGraph and self.sceneGraph:
+ temp.append( self.getSceneGraph() )
+ return temp
+ def addField (self, definition, default = None):
+ ''' Add a single field definition to the Prototype
+ definition -- (string name, string dataType, boolean exposed)
+ default -- object defaultValue
+
+ see attribute fieldDictionary
+ see attribute defaultDictionary
+ '''
+ if type (definition) == types.InstanceType:
+ definition = definition.getDefinition()
+ default = definition.getDefault ()
+ self.removeField( definition[0] )
+ self.fieldDictionary[definition [0]] = definition
+ if default is not None:
+ default = fieldcoercian.FieldCoercian()( default, definition[1] )
+ self.defaultDictionary [definition [0]] = default
+ if definition[1] == 'SFNode':
+ self.SFNodeNames.append(definition[0])
+ elif definition[1] == 'MFNode':
+ self.MFNodeNames.append(definition[0])
+ def removeField (self, key):
+ ''' Remove a single field from the Prototype
+ key -- string fieldName
+ The name of the field to remove
+ '''
+ if self.fieldDictionary.has_key (key):
+ del self.fieldDictionary [key]
+ if self.defaultDictionary.has_key (key):
+ del self.defaultDictionary [key]
+ for attribute in (self.SFNodeNames, self.MFNodeNames):
+ while key in attribute:
+ attribute.remove(key)
+ def addEvent(self, definition):
+ ''' Add a single event definition to the Prototype
+ definition -- (string name, string dataType, boolean eventOut)
+
+ see attribute eventDictionary
+ '''
+ if type (definition) == types.InstanceType:
+ definition = definition.getDefinition()
+ self.eventDictionary[definition [0]] = definition
+ def removeEvent(self, key):
+ ''' Remove a single event from the Prototype
+ key -- string eventName
+ The name of the event to remove
+ '''
+ if self.eventDictionary.has_key (key):
+ del self.eventDictionary [key]
+ def getField( self, key ):
+ '''Return a Field or Event object representing a given name
+ key -- string name
+ The name of the field or event to retrieve
+ will attempt to match key, key[4:], and key [:-8]
+ corresponding to key, set_key and key_changed
+
+ see class Field
+ see class Event
+ '''
+# print self.fieldDictionary, self.eventDictionary
+ for tempkey in (key, key[4:], key[:-8]):
+ if self.fieldDictionary.has_key( tempkey ):
+ return Field( self.fieldDictionary[tempkey], self.defaultDictionary.get(tempkey) )
+ elif self.eventDictionary.has_key( tempkey ):
+ return Event( self.eventDictionary[tempkey] )
+ raise AttributeError, key
+ def getDefault( self, key ):
+ '''Return the default value for the given field
+ key -- string name
+ The name of the field
+ Will attempt to match key, key[4:], and key [:-8]
+ corresponding to key, set_key and key_changed
+
+ see attribute defaultDictionary
+ '''
+ for key in (key, key[4:], key[:-8]):
+ if self.defaultDictionary.has_key( key ):
+ val = self.defaultDictionary[key]
+ if type(val) in typeclasses.MutableTypes:
+ val = copy.deepcopy( val )
+ return val
+ elif self.fieldDictionary.has_key( key ):
+ '''We have the field, but we don't have a default, we are likely an EXTERNPROTO'''
+ return None
+ raise AttributeError, key
+ def setDefault (self, key, value):
+ '''Set the default value for the given field
+ key -- string name
+ The name of the field to set
+ value -- object defaultValue
+ The default value, will be checked for type and coerced if necessary
+ '''
+ field = self.getField (key)
+ self.defaultDictionary [field.name]= field.coerce (value)
+ def clone( self, children = 1, sceneGraph = 1 ):
+ '''Return a copy of this Prototype
+ children -- boolean
+ if true, copy the children of the Prototype, otherwise include them
+ sceneGraph -- boolean
+ if true, copy the sceneGraph of the Prototype
+ '''
+ if sceneGraph:
+ sceneGraph = self.sceneGraph
+ else:
+ sceneGraph = None
+ # defaults should always be copied before modification, but this is still dangerous...
+ defaultDictionary = self.defaultDictionary.copy()
+ if not children:
+ for attrname in self.SFNodeNames+self.MFNodeNames:
+ try:
+ del defaultDictionary[attrname]
+ except KeyError: # sceneGraph object is not copied...
+ pass
+ # now make a copy
+ if self.__gi__ == "PROTO":
+ newNode = self.__class__(
+ self.nodeGI,
+ self.fieldDictionary,
+ defaultDictionary,
+ self.eventDictionary,
+ sceneGraph,
+ )
+ else:
+ newNode = self.__class__(
+ self.nodeGI,
+ self.url,
+ self.fieldDictionary,
+ self.eventDictionary,
+ )
+ return newNode
+ def __call__(self, *args, **namedargs):
+ '''Create a new Node instance associated with this Prototype
+ *args, **namedargs -- passed to the Node.__init__
+ see class Node
+ '''
+ node = apply( Node, (self, )+args, namedargs )
+ return node
+ def __repr__ ( self ):
+ '''Create a simple Python representation'''
+ return '''%s( %s )'''%( self.__class__.__name__, self.nodeGI )
+
+class ExternalPrototype( Prototype ):
+ '''Sub-class of Prototype
+
+ The ExternalPrototype is a minor sub-classing of the Prototype
+ it does not have any defaults, nor a sceneGraph
+
+ Attributes:
+ __gi__ -- constant string "EXTERNPROTO"
+ url -- string list urls
+ implementation source for the ExternalPrototype
+ '''
+ __gi__ = "EXTERNPROTO"
+ def __init__(self, gi, url=None, fieldDict=None, eventDict=None):
+ '''
+ gi -- string gi
+ see attribute nodeGI
+ url -- string list url
+ MFString-compatible list of url's for EXTERNPROTO
+ fieldDict -- string name: (string name, string dataType, boolean exposed)
+ see attribute fieldDictionary
+ eventDict -- string name: (string name, string dataType, boolean eventOut)
+ see attribute eventDictionary
+ '''
+ if url is None:
+ url = []
+ self.url = url
+ Prototype.__init__( self, gi, fieldDict=fieldDict, eventDict=eventDict)
+
+
+from vrml import fieldcoercian # XXX
+class Field:
+ ''' Representation of a Prototype Field
+ The Field object is a simple wrapper to provide convenient
+ access to field coercian and meta- information
+ '''
+ def __init__( self, specification, default=None ):
+ self.name, self.type, self.exposure = specification
+ self.default = default
+ def getDefinition (self):
+ return self.name, self.type, self.exposure
+ def getDefault (self):
+ return self.default
+ def coerce( self, value ):
+ ''' Coerce value to the appropriate dataType for this Field '''
+ return fieldcoercian.FieldCoercian()( value,self.type, )
+ def __repr__( self ):
+ if hasattr (self, "default"):
+ return '%s( (%s,%s,%s), %s)'%( self.__class__.__name__, self.name, self.type, self.exposure, self.default)
+ else:
+ return '%s( (%s,%s,%s),)'%( self.__class__.__name__, self.name, self.type, self.exposure)
+ def __str__( self ):
+ if self.exposure:
+ exposed = "exposedField"
+ else:
+ exposed = field
+ if hasattr (self, "default"):
+ default = ' ' + str( self.default)
+ else:
+ default = ""
+ return '%s %s %s%s'%(exposed, self.type, self.name, default)
+
+class Event (Field):
+ def __str__( self ):
+ if self.exposure:
+ exposed = "eventOut"
+ else:
+ exposed = "eventIn"
+ return '%s %s %s'%(exposed, self.type, self.name)
+
+
+### Translation strings for VRML node names...
+translationstring = '''][0123456789{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023'''
+NAMEFIRSTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) )
+translationstring = '''][{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023'''
+NAMERESTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) )
+del translationstring
+def checkName( name ):
+ '''Convert arbitrary string to a valid VRML id'''
+ if type(name) is types.StringType:
+ if not name:
+ return name
+ return string.translate( name[:1], NAMEFIRSTCHARTRANSLATOR) + string.translate( name[1:], NAMERESTCHARTRANSLATOR)
+ else:
+ raise TypeError, "VRML Node Name must be a string, was a %s: %s"%(type(name), name)
+
+class Node(baseProto):
+ ''' A VRML 97 Node object
+
+ A Node object represents a VRML 97 node. Attributes of the Node
+ can be set/retrieved with standard python setattr/getattr syntax.
+ VRML 97 attributes may be passed to the constructor as named
+ arguments.
+
+ Attributes:
+ __gi__ -- string PROTOname
+ DEF -- string DEFName
+ The DEF name of the node, will be coerced to be a valid
+ identifier (with "" being considered valid)
+ PROTO -- Prototype PROTO
+ The node's Prototype object
+ attributeDictionary -- string name: object value
+ Dictionary in which VRML 97 attributes are stored
+ '''
+ DEF = '' # the default name for all nodes (arbitrary)
+ def __init__(self, PROTO, name='', attrDict=None, *args, **namedargs):
+ '''Normally this method is only called indirectly via the Prototype() interface
+ PROTO -- Prototype PROTO
+ see attribute PROTO
+ name -- string DEFName
+ see attribute DEF
+ attrDict -- string name: object value
+ see attribute attributeDictionary
+ **namedargs -- string name: object value
+ added to attrDict to create attributeDictionary
+ '''
+ self.__dict__["PROTO"] = PROTO
+ self.DEF = name
+ self.__dict__["attributeDictionary"] = {}
+## print attrDict, namedargs
+ for dict in (attrDict or {}), namedargs:
+ if dict:
+ for key, value in dict.items ():
+ self.__setattr__( key, value, check=1 )
+
+ def __setattr__( self, key, value, check=1, raw=0 ):
+ '''Set attribute on Node
+ key -- string attributeName
+ value -- object attributeValue
+ check -- boolean check
+ if false, put values for unrecognized keys into __dict__
+ otherwise, raise an AttributeError
+ '''
+ if key == "DEF":
+ self.__dict__["DEF"] = checkName( value )
+ return None
+ elif key == "PROTO":
+ self.__dict__["PROTO"] = value
+ try:
+ field = self.PROTO.getField( key )
+ if (hasattr( value, "__gi__") and value.__gi__ == "IS") or raw:
+ self.attributeDictionary[ field.name] = value
+ else:
+ self.attributeDictionary[ field.name] = field.coerce( value )
+ except ValueError, x:
+ raise ValueError( "Could not coerce value %s into value of VRML type %s for %s node %s's field %s"%( value, field.type, self.__gi__, self.DEF, key), x.args)
+ except (AttributeError), x:
+ if check:
+ raise AttributeError("%s is not a known field for node %s"%(key, repr(self)))
+ else:
+ self.__dict__[key] = value
+ def __getattr__( self, key, default = 1 ):
+ ''' Retrieve an attribute when standard lookup fails
+ key -- string attributeName
+ default -- boolean default
+ if true, return the default value if the node does not have local value
+ otherwise, raise AttributeError
+ '''
+ if key != "attributeDictionary":
+ if self.__dict__.has_key( key):
+ return self.__dict__[ key ]
+ elif self.attributeDictionary.has_key( key):
+ return self.attributeDictionary[key]
+ if key != "PROTO":
+ if key == "__gi__":
+ return self.PROTO.nodeGI
+ elif default:
+ try:
+ default = self.PROTO.getDefault( key )
+ if type( default ) in typeclasses.MutableTypes:
+ # we need a copy, not the original
+ default = copy.deepcopy( default )
+ self.__setattr__( key, default, check=0, raw=1 )
+ return default
+ except AttributeError:
+ pass
+ raise AttributeError, key
+ def __delattr__( self, key ):
+ ''' Delete an attribute from the Node
+ key -- string attributeName
+ '''
+ if key != "attributeDictionary":
+ if self.attributeDictionary.has_key( key):
+ del self.attributeDictionary[key]
+ elif self.__dict__.has_key( key):
+ del self.__dict__[ key ]
+ raise AttributeError, key
+
+ def __repr__(self):
+ ''' Create simple python representation '''
+ return '<%s(%s): %s>'%(self.__gi__, `self.DEF`, self.attributeDictionary.keys() )
+ def getChildrenNames( self, current = 1, *args, **namedargs ):
+ ''' Get the (current) children of Node
+ returns two lists: MFNode children, SFNode children
+ current -- boolean currentOnly
+ if true, only return current children
+ otherwise, include all potential children
+ '''
+ MFNODES, SFNODES = self.PROTO.MFNodeNames, self.PROTO.SFNodeNames
+ mns, sns = [],[]
+ for key in MFNODES:
+ if current and self.attributeDictionary.has_key(key):
+ mns.append(key)
+ elif not current:
+ mns.append(key)
+ for key in SFNODES:
+ if self.attributeDictionary.has_key(key):
+ sns.append(key)
+ elif not current:
+ sns.append(key)
+ return mns,sns
+ def calculateChildren(self, *args, **namedargs):
+ '''Calculate the current children of the Node as list of Nodes
+ '''
+ MFNODES, SFNODES = self.getChildrenNames( )
+ temp = []
+ for key in MFNODES:
+ try:
+ temp.extend( self.__getattr__( key, default=0 ) )
+ except AttributeError:
+ pass
+ for key in SFNODES:
+ try:
+ temp.append( self.__getattr__(key, default = 0 ) )
+ except AttributeError:
+ pass
+ return temp
+ def clone(self, newclass=None, name=None, children=None, attrDeepCopy=1, *args, **namedargs):
+ '''Return a copy of this Node
+ newclass -- object newClass or None
+ optionally use a different Prototype as base
+ name -- string DEFName or None or 1
+ if 1, copy from current
+ elif None, set to ""
+ else, set to passed value
+ children -- boolean copyChildren
+ if true, copy the children of this node
+ otherwise, skip children
+ attrDeepCopy -- boolean deepCopy
+ if true, use deepcopy
+ otherwise, use copy
+ '''
+ if attrDeepCopy:
+ cpy = copy.deepcopy
+ else:
+ cpy = copy.copy
+ newattrs = self.attributeDictionary.copy()
+ if not children:
+ mnames,snames = self.getChildrenNames( )
+ for key in mnames+snames:
+ try:
+ del(newattrs[key])
+ except KeyError:
+ pass
+ for key, val in newattrs.items():
+ if type(val) in typeclasses.MutableTypes:
+ newattrs[key] = cpy(val)
+ # following is Node specific, won't work for sceneGraphs, scripts, etceteras
+ if name == 1: # asked to copy the name
+ name = self.DEF
+ elif name is None: # asked to clear the name
+ name = ''
+ if not newclass:
+ newclass = self.PROTO
+ return newclass( name, newattrs )
+ def __cmp__( self, other, stop=None ):
+ ''' Compare this node to another object/node
+ other -- object otherNode
+ stop -- boolean stopIfFailure
+ if true, failure to find comparison causes match failure (i.e. considered unequal)
+ '''
+
+ if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
+ try:
+ return cmp( self.DEF, other.DEF) or cmp( self.attributeDictionary, other.attributeDictionary )
+ except:
+ if not stop:
+ try:
+ return other.__cmp__( self , 1) # 1 being stop...
+ except:
+ pass
+ return -1 # could be one, doesn't really matter
+
+def Script( name="", attrDict=None, fieldDict=None, defaultDict=None, eventDict=None, **namedarguments):
+ ''' Create a script node (and associated prototype)
+ name -- string DEFName
+ attrDict -- string name: object value
+ see class Node.attributeDictionary
+ fieldDict -- string name: (string name, string dataType, boolean exposure)
+ see class Prototype.fieldDictionary
+ defaultDict -- string name: object value
+ see class Prototype.defaultDictionary
+ eventDict -- string name: (string name, string dataType, boolean eventOut)
+ '''
+ fieldDictionary = {
+ 'directOutput':('directOutput', 'SFBool',0),
+ 'url':('url',"MFString",0),
+ 'mustEvaluate':('mustEvaluate', 'SFBool',0),
+ }
+ fieldDictionary.update( fieldDict or {})
+ defaultDictionary = {
+ "directOutput":0,
+ "url":[],
+ "mustEvaluate":0,
+ }
+ defaultDictionary.update( defaultDict or {})
+ PROTO = Prototype(
+ "Script",
+ fieldDictionary,
+ defaultDictionary ,
+ eventDict = eventDict,
+ )
+ if attrDict is not None:
+ attrDict.update( namedarguments )
+ else:
+ attrDict = namedarguments
+ return PROTO( name, attrDict )
+
+
+class NullNode:
+ '''NULL SFNode value
+ There should only be a single NULL instance for
+ any particular system. It should, for all intents and
+ purposes just sit there inertly
+ '''
+ __gi__ = 'NULL'
+ DEF = ''
+ __walker_is_temporary_item__ = 1 # hacky signal to walking engine not to reject this node as already processed
+ def __repr__(self):
+ return '<NULL vrml SFNode>'
+ def __vrmlStr__(self,*args,**namedargs):
+ return ' NULL '
+ toString = __vrmlStr__
+ def __nonzero__(self ):
+ return 0
+ def __call__(self, *args, **namedargs):
+ return self
+ def __cmp__( self, other ):
+ if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
+ return 0
+ return -1 # could be one, doesn't really matter
+ def clone( self ):
+ return self
+NULL = NullNode()
+
+class fieldRef:
+ '''IS Prototype field reference
+ '''
+ __gi__ = 'IS'
+ DEF = ''
+ def __init__(self, declaredName):
+ self.declaredName = declaredName
+ def __repr__(self):
+ return 'IS %s'%self.declaredName
+ def __vrmlStr__(self,*args,**namedargs):
+ return 'IS %s'%self.declaredName
+ toString = __vrmlStr__
+ def __cmp__( self, other ):
+ if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
+ return cmp( self.declaredName, other.declaredName )
+ return -1 # could be one, doesn't really matter
+ def clone( self ):
+ return self.__class__( self.declaredName )
+
+IS = fieldRef
+
+class ROUTE:
+ ''' VRML 97 ROUTE object
+ The ROUTE object keeps track of its source and destination nodes and attributes
+ It generally lives in a sceneGraph's "routes" collection
+ '''
+ __gi__ = 'ROUTE'
+ def __init__( self, fromNode, fromField, toNode, toField ):
+ if type(fromNode) is types.StringType:
+ raise TypeError( "String value for ROUTE fromNode",fromNode)
+ if type(toNode) is types.StringType:
+ raise TypeError( "String value for ROUTE toNode",toNode)
+ self.fromNode = fromNode
+ self.fromField = fromField
+ self.toNode = toNode
+ self.toField = toField
+ def __getitem__( self, index ):
+ return (self.fromNode, self.fromField, self.toNode, self.toField)[index]
+ def __setitem__( self, index, value ):
+ attribute = ("fromNode","fromField","toNode", "toField")[index]
+ setattr( self, attribute, value )
+ def __repr__( self ):
+ return 'ROUTE %s.%s TO %s.%s'%( self.fromNode.DEF, self.fromField, self.toNode.DEF, self.toField )
+ def clone( self ):
+ return self.__class__(
+ self.fromNode,
+ self.fromField,
+ self.toNode,
+ self.toField,
+ )
+
+
+class sceneGraph(baseProto):
+ ''' A VRML 97 sceneGraph
+ Attributes:
+ __gi__ -- constant string "sceneGraph"
+ DEF -- constant string ""
+ children -- Node list
+ List of the root children of the sceneGraph, nodes/scripts only
+ routes -- ROUTE list
+ List of the routes within the sceneGraph
+ defNames -- string DEFName: Node node
+ Mapping of DEF names to their respective nodes
+ protoTypes -- Namespace prototypes
+ Namespace (with chaining lookup) collection of prototypes
+ getattr( sceneGraph.protoTypes, 'nodeGI' ) retrieves a prototype
+ '''
+ __gi__ = 'sceneGraph'
+ DEF = ''
+ def __init__(self, root=None, protoTypes=None, routes=None, defNames=None, children=None, *args, **namedargs):
+ '''
+ root -- sceneGraph root or Dictionary root or Module root or None
+ Base object for root of protoType namespace hierarchy
+ protoTypes -- string nodeGI: Prototype PROTO
+ Dictionary of prototype definitions
+ routes -- ROUTE list or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut) list
+ List of route objects or tuples to be added to the sceneGraph
+ see attribute routes
+ defNames -- string DEFName: Node node
+ see attribute defNames
+ children -- Node list
+ see attribute children
+ '''
+ if children is None:
+ self.children = []
+ else:
+ self.children = children
+ if routes is None:
+ self.routes = [] # how will we efficiently handle routes?
+ else:
+ self.routes = routes
+ if defNames == None:
+ self.defNames = {} # maps 'defName':Node
+ else:
+ self.defNames = defNames
+ if protoTypes is None:
+ protoTypes = {}
+ if root is None:
+ from vrml import basenodes # XXX
+ self.protoTypes = namespace.NameSpace(
+ protoTypes,
+ children = [namespace.NameSpace(basenodes)]
+ )
+ else: # there is a root file, so need to use it as the children instead of basenodes...
+ if hasattr( root, "protoTypes"):
+ self.protoTypes = namespace.NameSpace(
+ protoTypes,
+ children = [root.protoTypes]
+ )
+ else:
+ self.protoTypes = namespace.NameSpace(
+ protoTypes,
+ children = [ namespace.NameSpace(root) ]
+ )
+ def __getinitargs__( self ):
+ # we only copy our explicit protos, our routes, our defNames, and our children
+ # inherited protos will be pulled along by their nodes...
+ return None, self.protoTypes._base, self.routes, self.defNames, self.children
+ def __getstate__( self ):
+ return {}
+ def __setstate__( self, dict ):
+ pass
+ def __del__( self, id=id ):
+ '''
+ Need to clean up the namespace's mutual references,
+ this can be done without affecting the cascade by just
+ eliminating the key/value pairs. The namespaces will
+ no longer contain the prototypes, but they will still
+ chain up to the higher-level namespaces, and the nodes
+ will have those prototypes still in use.
+ '''
+## print 'del sceneGraph', id(self )
+ try:
+## import pdb
+## pdb.set_trace()
+## self.protoTypes.__dict__.clear()
+ self.protoTypes._base.clear()
+ del self.protoTypes.__namespace_cascade__[:]
+ except:
+ print 'unable to free references'
+
+ def addRoute(self, routeTuple, getNewNodes=0):
+ ''' Add a single route to the sceneGraph
+ routeTuple -- ROUTE route or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut)
+ getNewNodes -- boolean getNewNodes
+ if true, look up sourcenode and destinationnode within the current defNames to determine source/destination nodes
+ otherwise, just use current if available
+ '''
+ # create and wire together the Routes here,
+ # should just be a matter of pulling the events and passing the nodes...
+## import pdb
+## pdb.set_trace()
+ if type( routeTuple) in ( types.TupleType, types.ListType):
+ (fromNode, fromField, toNode, toField ) = routeTuple
+ if type(fromNode) is types.StringType:
+ # get the node instead of the string...
+ if self.defNames.has_key( fromNode ):
+ fromNode = self.defNames[fromNode]
+ else:
+ err.err( "ROUTE from an unknown node %s "%(routeTuple) )
+ return 0
+ if type(toNode) is types.StringType:
+ # get the node instead of the string...
+ if self.defNames.has_key( toNode ):
+ toNode = self.defNames[toNode]
+ else:
+ err.err( "ROUTE to an unknown node %s "%(routeTuple) )
+ return 0
+ routeTuple = ROUTE( fromNode, fromField, toNode, toField)
+ elif getNewNodes:
+ # get the nodes with the same names...
+ if self.defNames.has_key( routeTuple[0].DEF ):
+ routeTuple[0] = self.defNames[routeTuple[0].DEF]
+ else:
+ err.err( "ROUTE from an unknown node %s "%(routeTuple) )
+ return 0
+ if self.defNames.has_key( routeTuple[2].DEF ):
+ routeTuple[2] = self.defNames[routeTuple[2].DEF]
+ else:
+ err.err( "ROUTE to an unknown node %s "%(routeTuple) )
+ return 0
+ # should be a Route node now, append to our ROUTE list...
+ self.routes.append(routeTuple)
+ return 1
+ def regDefName(self, defName, object):
+ ''' Register a DEF name for a particular object
+ defName -- string DEFName
+ object -- Node node
+ '''
+ object.DEF = defName
+ self.defNames[defName] = object
+ def addProto(self, proto):
+ '''Register a Prototype for this sceneGraph
+ proto -- Prototype PROTO
+ '''
+ setattr( self.protoTypes, proto.__gi__, proto )
+ #toString = __vrmlStr__
+ #__vrmlStr__ = toString
+## def __setattr__( self, key, value ):
+## if key == 'protoTypes' and type( value) is types.ListType:
+## import pdb
+## pdb.set_trace()
+## raise TypeError( "Invalid type for protoTypes attribute of sceneGraph %s"%(`value`) )
+## else:
+## self.__dict__[key] = value
+
+DEFAULTFIELDVALUES ={
+ "SFBool": 0,
+ "SFString": "",
+ "SFFloat": 0,
+ "SFTime": 0,
+ "SFVec3f": (0, 0,0),
+ "SFVec2f": (0,0),
+ "SFRotation": (0, 1,0, 0),
+ "SFInt32": 0,
+ "SFImage": (0,0,0),
+ "SFColor": (0,0, 0),
+ "SFNode": NULL,
+ "MFString": [],
+ "MFFloat": [],
+ "MFTime": [],
+ "MFVec3f": [],
+ "MFVec2f": [],
+ "MFRotation": [],
+ "MFInt32": [],
+ "MFColor": [],
+ "MFNode": [],
+}
+
+
+
diff --git a/intern/python/modules/vrml/utils/__init__.py b/intern/python/modules/vrml/utils/__init__.py
new file mode 100644
index 00000000000..9d708a9084c
--- /dev/null
+++ b/intern/python/modules/vrml/utils/__init__.py
@@ -0,0 +1 @@
+"""utilities"""
diff --git a/intern/python/modules/vrml/utils/collapse.py b/intern/python/modules/vrml/utils/collapse.py
new file mode 100644
index 00000000000..25da50c2adb
--- /dev/null
+++ b/intern/python/modules/vrml/utils/collapse.py
@@ -0,0 +1,169 @@
+'''
+Destructive Functions for "collapsing" Sequences into single levels
+
+>>> from mcf.utils import collapse
+
+>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]])
+
+[1, 2, 3, 4, 5, 6] # note that is the same root list
+
+>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]])
+
+[1, 2, 3, 4, 5, 6] # note is the same root list
+'''
+import copy, types, sys
+from types import ListType, TupleType # this now only supports the obsolete stuff...
+
+def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint):
+ '''
+ Destructively flatten a mixed hierarchy to a single level.
+ Non-recursive, many speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ expandable = 1
+ while expandable:
+ expandable = 0
+ if allowedmap.has_key( type(inlist[ind]) ):
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = list( inlist[ind])
+ expandable = 1
+
+ # alternately you could iterate through checking for isinstance on all possible
+ # classes, but that would be very slow
+ elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ):
+ # here figure out some way to generically expand that doesn't risk
+ # infinite loops...
+ templist = []
+ for x in inlist[ind]:
+ templist.append( x)
+ inlist[ind:ind+1] = templist
+ expandable = 1
+ except IndexError:
+ pass
+ return inlist
+
+
+def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ Further speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ while type(inlist[ind]) is ltype:
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = inlist[ind]
+ #ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse_safe(inlist):
+ '''
+ As collapse, but works on a copy of the inlist
+ '''
+ return collapse( inlist[:] )
+
+def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Will expand tuple children as well, but will fail if the
+ top level element is not a list.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ '''
+ ind = 0
+ try:
+ while 1:
+ while type(inlist[ind]) in ltype:
+ try:
+ inlist[ind:ind+1] = inlist[ind]
+ except TypeError:
+ inlist[ind:ind+1] = list(inlist[ind])
+ ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse2_safe(inlist):
+ '''
+ As collapse2, but works on a copy of the inlist
+ '''
+ return collapse( list(inlist) )
+
+def old_buggy_collapse(inlist):
+ '''Always return a one-level list of all the non-list elements in listin,
+ rewritten to be non-recursive 96-12-28 Note that the new versions work
+ on the original list, not a copy of the original.'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) == ListType:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) == ListType:
+ x = x - 1 # need to collapse that list...
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened
+ else:
+ inlist[x:x+1]=y
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def old_buggy_collapse2(inlist):
+ '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) in [ListType, TupleType]:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) in [ListType,TupleType]:
+ x = x-1 #(to deal with that element)
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened, will raise exception with tuples...
+ else:
+ inlist[x:x+1]=list(y)
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def oldest_buggy_collapse(listin):
+ 'Always return a one-level list of all the non-list elements in listin'
+ if type(listin) == ListType:
+ return reduce(lambda x,y: x+y, map(collapse, listin), [])
+ else: return [listin]
+
+def oldest_buggy_collapse2(seqin):
+
+ if type(seqin) in [ListType, TupleType]:
+ return reduce(lambda x,y: x+y, map(collapse2, seqin), [])
+ else:
+ return [seqin]
+
diff --git a/intern/python/modules/vrml/utils/err.py b/intern/python/modules/vrml/utils/err.py
new file mode 100644
index 00000000000..3c6591a6873
--- /dev/null
+++ b/intern/python/modules/vrml/utils/err.py
@@ -0,0 +1,37 @@
+'''
+err.py Encapsulated writing to sys.stderr
+
+The idea of this module is that, for a GUI system (or a more advanced UI),
+you can just import a different err module (or object) and keep
+your code the same. (For instance, you often want a status window
+which flashes warnings and info, and have error messages pop up an
+alert to get immediate attention.
+'''
+
+import sys
+
+def err(message, Code=0):
+ '''
+ report an error, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Error #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Error: %s\n'%message)
+def warn(message, Code=0):
+ '''
+ report a warning, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Warning #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Warning: %s\n'%message)
+def info(message, Code=0):
+ '''
+ report information/status, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Info #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Info: %s\n'%message)
+
diff --git a/intern/python/modules/vrml/utils/namespace.py b/intern/python/modules/vrml/utils/namespace.py
new file mode 100644
index 00000000000..dd9f0b7dea6
--- /dev/null
+++ b/intern/python/modules/vrml/utils/namespace.py
@@ -0,0 +1,225 @@
+'''
+NameSpace v0.04:
+
+A "NameSpace" is an object wrapper around a _base dictionary
+which allows chaining searches for an 'attribute' within that
+dictionary, or any other namespace which is defined as part
+of the search path (depending on the downcascade variable, is
+either the hier-parents or the hier-children).
+
+You can assign attributes to the namespace normally, and read
+them normally. (setattr, getattr, a.this = that, a.this)
+
+I use namespaces for writing parsing systems, where I want to
+differentiate between sources (have multiple sources that I can
+swap into or out of the namespace), but want to be able to get
+at them through a single interface. There is a test function
+which gives you an idea how to use the system.
+
+In general, call NameSpace(someobj), where someobj is a dictionary,
+a module, or another NameSpace, and it will return a NameSpace which
+wraps up the keys of someobj. To add a namespace to the NameSpace,
+just call the append (or hier_addchild) method of the parent namespace
+with the child as argument.
+
+### NOTE: if you pass a module (or anything else with a dict attribute),
+names which start with '__' will be removed. You can avoid this by
+pre-copying the dict of the object and passing it as the arg to the
+__init__ method.
+
+### NOTE: to properly pickle and/or copy module-based namespaces you
+will likely want to do: from mcf.utils import extpkl, copy_extend
+
+### Changes:
+ 97.05.04 -- Altered to use standard hierobj interface, cleaned up
+ interface by removing the "addparent" function, which is reachable
+ by simply appending to the __parent__ attribute, though normally
+ you would want to use the hier_addchild or append functions, since
+ they let both objects know about the addition (and therefor the
+ relationship will be restored if the objects are stored and unstored)
+
+ 97.06.26 -- Altered the getattr function to reduce the number of
+ situations in which infinite lookup loops could be created
+ (unfortunately, the cost is rather high). Made the downcascade
+ variable harden (resolve) at init, instead of checking for every
+ lookup. (see next note)
+
+ 97.08.29 -- Discovered some _very_ weird behaviour when storing
+ namespaces in mcf.store dbases. Resolved it by storing the
+ __namespace_cascade__ attribute as a normal attribute instead of
+ using the __unstore__ mechanism... There was really no need to
+ use the __unstore__, but figuring out how a functions saying
+ self.__dict__['__namespace_cascade__'] = something
+ print `self.__dict__['__namespace_cascade__']` can print nothing
+ is a bit beyond me. (without causing an exception, mind you)
+
+ 97.11.15 Found yet more errors, decided to make two different
+ classes of namespace. Those based on modules now act similar
+ to dummy objects, that is, they let you modify the original
+ instead of keeping a copy of the original and modifying that.
+
+ 98.03.15 -- Eliminated custom pickling methods as they are no longer
+ needed for use with Python 1.5final
+
+ 98.03.15 -- Fixed bug in items, values, etceteras with module-type
+ base objects.
+'''
+import copy, types, string
+
+from mcf.utils import hierobj
+
+class NameSpace(hierobj.Hierobj):
+ '''
+ An hierarchic NameSpace, allows specification of upward or downward
+ chaining search for resolving names
+ '''
+ def __init__(self, val = None, parents=None, downcascade=1,children=[]):
+ '''
+ A NameSpace can be initialised with a dictionary, a dummied
+ dictionary, another namespace, or something which has a __dict__
+ attribute.
+ Note that downcascade is hardened (resolved) at init, not at
+ lookup time.
+ '''
+ hierobj.Hierobj.__init__(self, parents, children)
+ self.__dict__['__downcascade__'] = downcascade # boolean
+ if val is None:
+ self.__dict__['_base'] = {}
+ else:
+ if type( val ) == types.StringType:
+ # this is a reference to a module which has been pickled
+ val = __import__( val, {},{}, string.split( val, '.') )
+ try:
+ # See if val's a dummy-style object which has a _base
+ self.__dict__['_base']=copy.copy(val._base)
+ except (AttributeError,KeyError):
+ # not a dummy-style object... see if it has a dict attribute...
+ try:
+ if type(val) != types.ModuleType:
+ val = copy.copy(val.__dict__)
+ except (AttributeError, KeyError):
+ pass
+ # whatever val is now, it's going to become our _base...
+ self.__dict__['_base']=val
+ # harden (resolve) the reference to downcascade to speed attribute lookups
+ if downcascade: self.__dict__['__namespace_cascade__'] = self.__childlist__
+ else: self.__dict__['__namespace_cascade__'] = self.__parent__
+ def __setattr__(self, var, val):
+ '''
+ An attempt to set an attribute should place the attribute in the _base
+ dictionary through a setitem call.
+ '''
+ # Note that we use standard attribute access to allow ObStore loading if the
+ # ._base isn't yet available.
+ try:
+ self._base[var] = val
+ except TypeError:
+ setattr(self._base, var, val)
+ def __getattr__(self,var):
+## print '__getattr__', var
+ return self.__safe_getattr__(var, {}) # the {} is a stopdict
+
+ def __safe_getattr__(self, var,stopdict):
+ '''
+ We have a lot to do in this function, if the attribute is an unloaded
+ but stored attribute, we need to load it. If it's not in the stored
+ attributes, then we need to load the _base, then see if it's in the
+ _base.
+ If it's not found by then, then we need to check our resource namespaces
+ and see if it's in them.
+ '''
+ # we don't have a __storedattr__ or it doesn't have this key...
+ if var != '_base':
+ try:
+ return self._base[var]
+ except (KeyError,TypeError), x:
+ try:
+ return getattr(self._base, var)
+ except AttributeError:
+ pass
+ try: # with pickle, it tries to get the __setstate__ before restoration is complete
+ for cas in self.__dict__['__namespace_cascade__']:
+ try:
+ stopdict[id(cas)] # if succeeds, we've already tried this child
+ # no need to do anything, if none of the children succeeds we will
+ # raise an AttributeError
+ except KeyError:
+ stopdict[id(cas)] = None
+ return cas.__safe_getattr__(var,stopdict)
+ except (KeyError,AttributeError):
+ pass
+ raise AttributeError, var
+ def items(self):
+ try:
+ return self._base.items()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.items()
+ except AttributeError:
+ pass
+ def keys(self):
+ try:
+ return self._base.keys()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.keys()
+ except AttributeError:
+ pass
+ def has_key( self, key ):
+ try:
+ return self._base.has_key( key)
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.has_key( key)
+ except AttributeError:
+ pass
+ def values(self):
+ try:
+ return self._base.values()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.values()
+ except AttributeError:
+ pass
+
+ def __getinitargs__(self):
+ if type( self._base ) is types.ModuleType:
+ base = self._base.__name__
+ else:
+ base = self._base
+ return (base, self.__parent__, self.__downcascade__, self.__childlist__)
+ def __getstate__(self):
+ return None
+ def __setstate__(self,*args):
+ pass
+ def __deepcopy__(self, memo=None):
+ d = id(self)
+ if memo is None:
+ memo = {}
+ elif memo.has_key(d):
+ return memo[d]
+ if type(self._base) == types.ModuleType:
+ rest = tuple(map( copy.deepcopy, (self.__parent__, self.__downcascade__, self.__childlist__) ))
+ new = apply(self.__class__, (self._base,)+rest )
+ else:
+ new = tuple(map( copy.deepcopy, (self._base, self.__parent__, self.__downcascade__, self.__childlist__) ))
+ return new
+## def __del__( self, id=id ):
+## print 'del namespace', id( self )
+
+
+def test():
+ import string
+ a = NameSpace(string)
+ del(string)
+ a.append(NameSpace({'a':23,'b':42}))
+ import math
+ a.append(NameSpace(math))
+ print 'The returned object should allow access to the attributes of the string,\nand math modules, and two simple variables "a" and "b" (== 23 and42 respectively)'
+ return a
+
+
diff --git a/intern/python/modules/vrml/utils/typeclasses.py b/intern/python/modules/vrml/utils/typeclasses.py
new file mode 100644
index 00000000000..ed798dfe3da
--- /dev/null
+++ b/intern/python/modules/vrml/utils/typeclasses.py
@@ -0,0 +1,50 @@
+'''
+Classes of Types
+
+Often you want to be able to say:
+ if type(obj) in MutableTypes:
+ yada
+
+This module is intended to make that easier.
+Just import and use :)
+'''
+import types
+
+MutableTypes = [ types.ListType, types.DictType, types.InstanceType ]
+MutableSequenceTypes = [ types.ListType ]
+SequenceTypes = [ types.ListType, types.StringType, types.TupleType ]
+NumericTypes = [ types.IntType, types.FloatType, types.LongType, types.ComplexType ]
+MappingTypes = [ types.DictType ]
+
+def regarray():
+ if globals().has_key('array'):
+ return 1
+ try:
+ import array
+ SequenceTypes.append( array.ArrayType )
+ MutableTypes.append( array.ArrayType )
+ MutableSequenceTypes.append( array.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+def regnumpy():
+ '''
+ Call if you want to register numpy arrays
+ according to their types.
+ '''
+ if globals().has_key('Numeric'):
+ return 1
+ try:
+ import Numeric
+ SequenceTypes.append( Numeric.ArrayType )
+ MutableTypes.append( Numeric.ArrayType )
+ MutableSequenceTypes.append( Numeric.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+# for now, I'm going to always register these, if the module becomes part of the base distribution
+# it might be better to leave it out so numpy isn't always getting loaded...
+regarray()
+regnumpy() \ No newline at end of file
diff --git a/intern/python/objexport/BlendImport.py b/intern/python/objexport/BlendImport.py
new file mode 100644
index 00000000000..d72370f783f
--- /dev/null
+++ b/intern/python/objexport/BlendImport.py
@@ -0,0 +1,157 @@
+#! /usr/bin/env python
+
+#######################
+# (c) Jan Walter 2000 #
+#######################
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+TAB = " "
+
+vertices = []
+vertexNormals = []
+faces = []
+materials = []
+switchMaterial = []
+currentMaterial = []
+materialIndex = 0
+
+def addVertex(x, y, z):
+ global vertices
+ vertices.append([x, y, z])
+ return len(vertices)
+
+def addVertexNormal(i, j, k):
+ global vertexNormals
+ vertexNormals.append([i, j, k])
+ return len(vertexNormals)
+
+def addFace(vi, ti, ni):
+ global faces
+ faces.append([vi, ti, ni])
+ return len(faces)
+
+def addMaterial(name, Kd, Ks, Ka):
+ global materials
+ materials.append([name, Kd, Ks, Ka])
+ return len(materials)
+
+def findMaterial(name):
+ global materials
+ for material in materials:
+ if material[0] == name:
+ return material
+
+def setCurrentMaterial(name):
+ global switchMaterial, faces, currentMaterial
+ switchMaterial.append(len(faces))
+ currentMaterial.append(name)
+
+class OpenInventor:
+ def export(self, filename, useNormals = 1, useMaterials = 1):
+ global vertices, vertexNormals, faces, materials, switchMaterial
+ global currentMaterial, materialIndex
+ file = open(filename, "w")
+ file.write("#Inventor V2.1 ascii\n\n")
+ file.write("Separator {\n")
+ ############
+ # vertices #
+ ############
+ file.write("%sCoordinate3 {\n" % (TAB, ))
+ file.write("%spoint [ \n" % (TAB*2, ))
+ for i in xrange(len(vertices)-1):
+ x, y, z = vertices[i]
+ file.write("%s %s %s %s,\n" % (TAB*2, x, y, z))
+ x, y, z = vertices[i+1]
+ file.write("%s %s %s %s\n" % (TAB*2, x, y, z))
+ file.write("%s ] \n" % (TAB*2, ))
+ file.write("%s}\n" % (TAB, ))
+ ###########
+ # normals #
+ ###########
+ if useNormals:
+ file.write("%sNormal {\n" % (TAB, ))
+ file.write("%svector [ \n" % (TAB*2, ))
+ for i in xrange(len(vertexNormals)-1):
+ x, y, z = vertexNormals[i]
+ file.write("%s %s %s %s,\n" % (TAB*2, x, y, z))
+ x, y, z = vertexNormals[i-1]
+ file.write("%s %s %s %s\n" % (TAB*2, x, y, z))
+ file.write("%s ] \n" % (TAB*2, ))
+ file.write("%s}\n" % (TAB, ))
+ #########
+ # faces #
+ #########
+ switchMaterial.append(len(faces))
+ for si in xrange(len(switchMaterial) - 1):
+ i1, i2 = switchMaterial[si], switchMaterial[si+1]
+ # --------------
+ # write material
+ # --------------
+ if materials:
+ name = currentMaterial[materialIndex]
+ material = findMaterial(name)
+ if useMaterials:
+ file.write("%sMaterial {\n" % (TAB, ))
+ file.write("%sambientColor %s %s %s\n" %
+ (TAB*2,
+ material[3][0],
+ material[3][1],
+ material[3][2]))
+ file.write("%sdiffuseColor %s %s %s\n" %
+ (TAB*2,
+ material[1][0],
+ material[1][1],
+ material[1][2]))
+ file.write("%sspecularColor %s %s %s\n" %
+ (TAB*2,
+ material[2][0],
+ material[2][1],
+ material[2][2]))
+ file.write("%s}\n" % (TAB, ))
+ # -----------
+ # write faces
+ # -----------
+ file.write("%sIndexedFaceSet {\n" % (TAB, ))
+ # indices for vertices
+ file.write("%scoordIndex [ \n" % (TAB*2, ))
+ for i in xrange(i1, i2-1):
+ indices = faces[i][0]
+ istring = ""
+ for index in indices:
+ # indices begin with 0 in OpenInventor
+ istring = istring + "%s, " % (index - 1, )
+ file.write("%s %s-1, \n" % (TAB*2, istring))
+ indices = faces[i+1][0]
+ istring = ""
+ for index in indices:
+ # indices begin with 0 in OpenInventor
+ istring = istring + "%s, " % (index - 1, )
+ file.write("%s %s-1\n" % (TAB*2, istring))
+ file.write("%s ] \n" % (TAB*2, ))
+ # update materialIndex
+ materialIndex = materialIndex + 1
+ if useNormals:
+ # indices for normals
+ file.write("%snormalIndex [ \n" % (TAB*2, ))
+ for i in xrange(i1, i2-1):
+ indices = faces[i][2]
+ istring = ""
+ for index in indices:
+ # indices begin with 0 in OpenInventor
+ istring = istring + "%s, " % (index - 1, )
+ file.write("%s %s-1, \n" % (TAB*2, istring))
+ indices = faces[i+1][2]
+ istring = ""
+ for index in indices:
+ # indices begin with 0 in OpenInventor
+ istring = istring + "%s, " % (index - 1, )
+ file.write("%s %s-1\n" % (TAB*2, istring))
+ file.write("%s ] \n" % (TAB*2, ))
+ file.write("%s}\n" % (TAB, ))
+ file.write("}\n")
+ file.close()
diff --git a/intern/python/objexport/objimport.py b/intern/python/objexport/objimport.py
new file mode 100644
index 00000000000..0150a2571ad
--- /dev/null
+++ b/intern/python/objexport/objimport.py
@@ -0,0 +1,119 @@
+#! /usr/bin/env python
+
+#######################
+# (c) Jan Walter 2000 #
+#######################
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+import BlendImport
+import os
+import sys
+import string
+
+def usage():
+ print "usage: python objimport.py objfile"
+
+def testObjImport(filename):
+ print filename
+ vcount = 0
+ vncount = 0
+ fcount = 0
+ file = open(filename, "r")
+ lines = file.readlines()
+ linenumber = 1
+ for line in lines:
+ words = string.split(line)
+ if words and words[0] == "#":
+ pass # ignore comments
+ elif words and words[0] == "v":
+ vcount = vcount + 1
+ x = string.atof(words[1])
+ y = string.atof(words[2])
+ z = string.atof(words[3])
+ ##print "Vertex %s: (%s, %s, %s)" % (vcount, x, y, z)
+ index = BlendImport.addVertex(x, y, z)
+ ##print "addVertex(%s)" % index
+ elif words and words[0] == "vn":
+ vncount = vncount + 1
+ i = string.atof(words[1])
+ j = string.atof(words[2])
+ k = string.atof(words[3])
+ ##print "VertexNormal %s: (%s, %s, %s)" % (vncount, i, j, k)
+ index = BlendImport.addVertexNormal(i, j, k)
+ ##print "addVertexNormal(%s)" % index
+ elif words and words[0] == "f":
+ fcount = fcount + 1
+ vi = [] # vertex indices
+ ti = [] # texture indices
+ ni = [] # normal indices
+ words = words[1:]
+ lcount = len(words)
+ for index in (xrange(lcount)):
+ vtn = string.split(words[index], "/")
+ vi.append(string.atoi(vtn[0]))
+ if len(vtn) > 1 and vtn[1]:
+ ti.append(string.atoi(vtn[1]))
+ if len(vtn) > 2 and vtn[2]:
+ ni.append(string.atoi(vtn[2]))
+ ##print "Face %s: (%s, %s, %s)" % (fcount, vi, ti, ni)
+ index = BlendImport.addFace(vi, ti, ni)
+ ##print "addFace(%s)" % index
+ elif words and words[0] == "mtllib":
+ # try to export materials
+ directory, dummy = os.path.split(filename)
+ filename = os.path.join(directory, words[1])
+ try:
+ file = open(filename, "r")
+ except:
+ print "no material file %s" % filename
+ else:
+ file = open(filename, "r")
+ line = file.readline()
+ while line:
+ words = string.split(line)
+ if words and words[0] == "newmtl":
+ name = words[1]
+ file.readline() # Ns .
+ file.readline() # d .
+ file.readline() # illum .
+ line = file.readline()
+ words = string.split(line)
+ Kd = [string.atof(words[1]),
+ string.atof(words[2]),
+ string.atof(words[3])]
+ line = file.readline()
+ words = string.split(line)
+ Ks = [string.atof(words[1]),
+ string.atof(words[2]),
+ string.atof(words[3])]
+ line = file.readline()
+ words = string.split(line)
+ Ka = [string.atof(words[1]),
+ string.atof(words[2]),
+ string.atof(words[3])]
+ index = BlendImport.addMaterial(name, Kd, Ks, Ka)
+ line = file.readline()
+ file.close()
+ elif words and words[0] == "usemtl":
+ name = words[1]
+ BlendImport.setCurrentMaterial(name)
+ elif words:
+ pass
+ ##print "%s: %s" % (linenumber, words)
+ linenumber = linenumber + 1
+ file.close()
+ # export to OpenInventor
+ BlendImport.OpenInventor().export("test.iv",
+ useNormals = 1, useMaterials = 1)
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ usage()
+ else:
+ filename = sys.argv[1]
+ testObjImport(filename)
diff --git a/intern/python/py_main.c b/intern/python/py_main.c
new file mode 100644
index 00000000000..308ab0266ff
--- /dev/null
+++ b/intern/python/py_main.c
@@ -0,0 +1,2292 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/* CVS */
+
+/* $Author$ */
+/* $Date$ */
+/* $RCSfile$ */
+/* $Revision$ */
+
+/* Jan Walter's stuff */
+#include "Python.h"
+#include "blender.h"
+
+static PyObject* ErrorObject;
+
+uint* mcol_to_vcol(Mesh *me);
+void mcol_to_rgb(uint col, float *r, float *g, float *b);
+void initBlender();
+static PyObject* blend_connect(PyObject* self, PyObject* args);
+static PyObject* blend_getObject(PyObject* self, PyObject* args);
+/* Jan Walter's stuff */
+
+/* Daniel Dunbar's stuff */
+void start_python (void);
+void end_python(void);
+void txt_do_python (Text* text);
+void do_all_scripts(short event);
+void do_all_scriptlist(ListBase* list, short event);
+void do_pyscript(ID *id, short event);
+void clear_bad_scriptlink(ID* id, Text* byebye);
+void clear_bad_scriptlinks(Text *byebye);
+void free_scriptlink(ScriptLink *slink);
+void copy_scriptlink(ScriptLink *scriptlink);
+
+void start_python (void)
+{
+ Py_SetProgramName("blender");
+ Py_Initialize();
+ initBlender();
+}
+
+void end_python(void)
+{
+ Py_Finalize();
+}
+
+void txt_do_python (Text* text)
+{
+ char filename[] = "test.py";
+ FILE* fp = NULL;
+
+ if (text->name)
+ {
+ fp = fopen(text->name, "r");
+ }
+ else
+ {
+ fp = fopen(filename, "r");
+ }
+ if (fp)
+ {
+ if (text->name)
+ {
+ PyRun_AnyFile(fp, text->name);
+ }
+ else
+ {
+ PyRun_AnyFile(fp, filename);
+ }
+ }
+ else
+ {
+ if (text->name)
+ {
+ printf("Couldn't run %s ...\n", text->name);
+ }
+ else
+ {
+ printf("Couldn't run test.py ...\n");
+ }
+ }
+}
+
+void do_all_scripts(short event)
+{
+}
+
+void do_all_scriptlist(ListBase* list, short event)
+{
+}
+
+void do_pyscript(ID *id, short event)
+{
+}
+
+void clear_bad_scriptlink(ID* id, Text* byebye)
+{
+}
+
+void clear_bad_scriptlinks(Text *byebye)
+{
+}
+
+void free_scriptlink(ScriptLink *slink)
+{
+}
+
+void copy_scriptlink(ScriptLink *scriptlink)
+{
+}
+/* Daniel Dunbar's stuff */
+
+ID* find_name_in_list(ID* list, const char* name)
+{
+ while (list)
+ {
+ if (STREQ(name, list->name+2))
+ {
+ break;
+ }
+ else
+ {
+ list = list->next;
+ }
+ }
+
+ return list;
+}
+
+/* Jan Walter's stuff */
+/**************/
+/* structures */
+/**************/
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* Lens;
+ PyObject* ClSta;
+ PyObject* ClEnd;
+} camobject;
+
+staticforward PyTypeObject Camtype;
+
+typedef struct {
+ PyObject_HEAD
+ PyObject* startFrame;
+ PyObject* endFrame;
+ PyObject* currentFrame;
+ PyObject* xResolution;
+ PyObject* yResolution;
+ PyObject* pixelAspectRatio;
+} dspobject;
+
+staticforward PyTypeObject Dsptype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* R;
+ PyObject* G;
+ PyObject* B;
+} lmpobject;
+
+staticforward PyTypeObject Lmptype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* R;
+ PyObject* G;
+ PyObject* B;
+} matobject;
+
+staticforward PyTypeObject Mattype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* vertices;
+ PyObject* normals;
+ PyObject* colors;
+ PyObject* faces;
+ PyObject* texture;
+ PyObject* texcoords;
+} mshobject;
+
+staticforward PyTypeObject Mshtype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* matrix;
+ PyObject* inverseMatrix;
+ PyObject* materials;
+ PyObject* data;
+ PyObject* type;
+} objobject;
+
+staticforward PyTypeObject Objtype;
+
+typedef struct {
+ PyObject_HEAD
+ char name[24];
+ PyObject* objects;
+} sceobject;
+
+staticforward PyTypeObject Scetype;
+
+/**********/
+/* camera */
+/**********/
+
+static struct PyMethodDef cam_methods[] = {
+ { NULL, NULL }
+};
+
+static camobject*
+newcamobject(char* name)
+{
+ camobject* self;
+ ID* list = NULL;
+
+ self = PyObject_NEW(camobject, &Camtype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->Lens = PyFloat_FromDouble(35.0);
+ self->ClSta = PyFloat_FromDouble(0.1);
+ self->ClEnd = PyFloat_FromDouble(100.0);
+
+ return self;
+}
+
+static void
+cam_dealloc(camobject* self)
+{
+ camobject* cam = (camobject*) self;
+
+ Py_DECREF(cam->Lens);
+ Py_DECREF(cam->ClSta);
+ Py_DECREF(cam->ClEnd);
+
+ PyMem_DEL(self);
+}
+
+static int
+cam_print(camobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Camera(name = \"%s\")\n", self->name);
+
+ return 0;
+}
+
+static PyObject*
+cam_repr(camobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Camera()\n");
+
+ return s;
+}
+
+static PyObject*
+cam_str(camobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Camera()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist cam_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"Lens", T_OBJECT, offsetof(camobject, Lens), RO},
+ {"ClSta", T_OBJECT, offsetof(camobject, ClSta), RO},
+ {"ClEnd", T_OBJECT, offsetof(camobject, ClEnd), RO},
+ {NULL}
+};
+
+static PyObject*
+cam_getattr(camobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, cam_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(cam_methods, (PyObject*)self, name);
+}
+
+
+static int
+cam_setattr(camobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, cam_memberlist, name, v);
+}
+
+static char Camtype__doc__[] =
+""
+;
+
+static PyTypeObject Camtype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Camera", /*tp_name*/
+ sizeof(camobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) cam_dealloc, /*tp_dealloc*/
+ (printfunc) cam_print, /*tp_print*/
+ (getattrfunc) cam_getattr, /*tp_getattr*/
+ (setattrfunc) cam_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) cam_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) cam_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Camtype__doc__ /* Documentation string */
+};
+
+/********************/
+/* display settings */
+/********************/
+
+static struct PyMethodDef dsp_methods[] = {
+ { NULL, NULL }
+};
+
+static dspobject*
+newdspobject(void)
+{
+ dspobject* self;
+ ID* list = NULL;
+
+ self = PyObject_NEW(dspobject, &Dsptype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ self->startFrame = PyInt_FromLong(1);
+ self->endFrame = PyInt_FromLong(250);
+ self->currentFrame = PyInt_FromLong(1);
+ self->xResolution = PyInt_FromLong(320);
+ self->yResolution = PyInt_FromLong(256);
+ self->pixelAspectRatio = PyFloat_FromDouble(1.0);
+
+ return self;
+}
+
+static void
+dsp_dealloc(dspobject* self)
+{
+ dspobject* dsp = (dspobject*) self;
+
+ Py_DECREF(dsp->startFrame);
+ Py_DECREF(dsp->endFrame);
+ Py_DECREF(dsp->currentFrame);
+ Py_DECREF(dsp->xResolution);
+ Py_DECREF(dsp->yResolution);
+ Py_DECREF(dsp->pixelAspectRatio);
+
+ PyMem_DEL(self);
+}
+
+static int
+dsp_print(dspobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "DisplaySettings()\n");
+
+ return 0;
+}
+
+static PyObject*
+dsp_repr(dspobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("DisplaySettings()()\n");
+
+ return s;
+}
+
+static PyObject*
+dsp_str(dspobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("DisplaySettings()()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist dsp_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"startFrame", T_OBJECT, offsetof(dspobject, startFrame), RO},
+ {"endFrame", T_OBJECT, offsetof(dspobject, endFrame), RO},
+ {"currentFrame", T_OBJECT, offsetof(dspobject, currentFrame), RO},
+ {"xResolution", T_OBJECT, offsetof(dspobject, xResolution), RO},
+ {"yResolution", T_OBJECT, offsetof(dspobject, yResolution), RO},
+ {"pixelAspectRatio", T_OBJECT, offsetof(dspobject, pixelAspectRatio), RO},
+ {NULL}
+};
+
+static PyObject*
+dsp_getattr(dspobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, dsp_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(dsp_methods, (PyObject*)self, name);
+}
+
+
+static int
+dsp_setattr(dspobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, dsp_memberlist, name, v);
+}
+
+static char Dsptype__doc__[] =
+""
+;
+
+static PyTypeObject Dsptype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "DisplaySettings", /*tp_name*/
+ sizeof(dspobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) dsp_dealloc, /*tp_dealloc*/
+ (printfunc) dsp_print, /*tp_print*/
+ (getattrfunc) dsp_getattr, /*tp_getattr*/
+ (setattrfunc) dsp_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) dsp_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) dsp_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Dsptype__doc__ /* Documentation string */
+};
+
+/********/
+/* Lamp */
+/********/
+
+static struct PyMethodDef lmp_methods[] = {
+ { NULL, NULL }
+};
+
+static lmpobject*
+newlmpobject(char* name)
+{
+ lmpobject* self;
+ ID* list = NULL;
+
+ self = PyObject_NEW(lmpobject, &Lmptype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->R = PyFloat_FromDouble(0.8);
+ self->G = PyFloat_FromDouble(0.8);
+ self->B = PyFloat_FromDouble(0.8);
+
+ return self;
+}
+
+static void
+lmp_dealloc(lmpobject* self)
+{
+ lmpobject* lmp = (lmpobject*) self;
+
+ Py_DECREF(lmp->R);
+ Py_DECREF(lmp->G);
+ Py_DECREF(lmp->B);
+
+ PyMem_DEL(self);
+}
+
+static int
+lmp_print(lmpobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Lamp(name = \"%s\")\n", self->name);
+
+ return 0;
+}
+
+static PyObject*
+lmp_repr(lmpobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Lamp()\n");
+
+ return s;
+}
+
+static PyObject*
+lmp_str(lmpobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Lamp()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist lmp_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"R", T_OBJECT, offsetof(lmpobject, R), RO},
+ {"G", T_OBJECT, offsetof(lmpobject, G), RO},
+ {"B", T_OBJECT, offsetof(lmpobject, B), RO},
+ {NULL}
+};
+
+static PyObject*
+lmp_getattr(lmpobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, lmp_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(lmp_methods, (PyObject*)self, name);
+}
+
+
+static int
+lmp_setattr(lmpobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, lmp_memberlist, name, v);
+}
+
+static char Lmptype__doc__[] =
+""
+;
+
+static PyTypeObject Lmptype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Lamp", /*tp_name*/
+ sizeof(lmpobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) lmp_dealloc, /*tp_dealloc*/
+ (printfunc) lmp_print, /*tp_print*/
+ (getattrfunc) lmp_getattr, /*tp_getattr*/
+ (setattrfunc) lmp_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) lmp_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) lmp_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Lmptype__doc__ /* Documentation string */
+};
+
+/************/
+/* material */
+/************/
+
+static struct PyMethodDef mat_methods[] = {
+ { NULL, NULL }
+};
+
+static matobject*
+newmatobject(char* name)
+{
+ matobject* self;
+ ID* list = NULL;
+
+ self = PyObject_NEW(matobject, &Mattype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->R = PyFloat_FromDouble(0.8);
+ self->G = PyFloat_FromDouble(0.8);
+ self->B = PyFloat_FromDouble(0.8);
+
+ return self;
+}
+
+static void
+mat_dealloc(matobject* self)
+{
+ matobject* mat = (matobject*) self;
+
+ Py_DECREF(mat->R);
+ Py_DECREF(mat->G);
+ Py_DECREF(mat->B);
+
+ PyMem_DEL(self);
+}
+
+static int
+mat_print(matobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Material(name = \"%s\")\n", self->name);
+
+ return 0;
+}
+
+static PyObject*
+mat_repr(matobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Material()\n");
+
+ return s;
+}
+
+static PyObject*
+mat_str(matobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Material()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist mat_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"R", T_OBJECT, offsetof(matobject, R), RO},
+ {"G", T_OBJECT, offsetof(matobject, G), RO},
+ {"B", T_OBJECT, offsetof(matobject, B), RO},
+ {NULL}
+};
+
+static PyObject*
+mat_getattr(matobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, mat_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(mat_methods, (PyObject*)self, name);
+}
+
+
+static int
+mat_setattr(matobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, mat_memberlist, name, v);
+}
+
+static char Mattype__doc__[] =
+""
+;
+
+static PyTypeObject Mattype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Material", /*tp_name*/
+ sizeof(matobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) mat_dealloc, /*tp_dealloc*/
+ (printfunc) mat_print, /*tp_print*/
+ (getattrfunc) mat_getattr, /*tp_getattr*/
+ (setattrfunc) mat_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) mat_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) mat_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Mattype__doc__ /* Documentation string */
+};
+
+/********/
+/* mesh */
+/********/
+
+static char msh_addFace__doc__[] =
+"addFace(self, i1, i2, i3, i4, isSmooth, matIndex)"
+;
+
+static PyObject*
+msh_addFace(mshobject* self, PyObject* args)
+{
+ int index;
+ int i1, i2, i3, i4;
+ int isSmooth, matIndex;
+ PyObject* item = NULL;
+
+ if (!PyArg_ParseTuple(args, "iiiiii", &i1, &i2, &i3, &i4,
+ &isSmooth, &matIndex))
+ {
+ return NULL;
+ }
+ item = PyList_New(6);
+ PyList_SetItem(item, 0, PyInt_FromLong(i1));
+ PyList_SetItem(item, 1, PyInt_FromLong(i2));
+ PyList_SetItem(item, 2, PyInt_FromLong(i3));
+ PyList_SetItem(item, 3, PyInt_FromLong(i4));
+ PyList_SetItem(item, 4, PyInt_FromLong(isSmooth));
+ PyList_SetItem(item, 5, PyInt_FromLong(matIndex));
+ PyList_Append(self->faces, item);
+ index = PyList_Size(self->faces) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static char msh_addTexCoords__doc__[] =
+"addTexCoords(self, coords)"
+;
+
+static PyObject*
+msh_addTexCoords(mshobject* self, PyObject* args)
+{
+ float u, v;
+ PyObject* item = NULL;
+
+ if (!PyArg_ParseTuple(args, "ff",
+ &u, &v))
+ {
+ return NULL;
+ }
+ if (u < 0.0)
+ {
+ u = 0.0;
+ }
+ if (u > 1.0)
+ {
+ u = 1.0;
+ }
+ if (v < 0.0)
+ {
+ v = 0.0;
+ }
+ if (v > 1.0)
+ {
+ v = 1.0;
+ }
+ item = PyList_New(2);
+ PyList_SetItem(item, 0, PyFloat_FromDouble(u));
+ PyList_SetItem(item, 1, PyFloat_FromDouble(v));
+ PyList_Append(self->texcoords, item);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char msh_addTexture__doc__[] =
+"addTexture(self, filename)"
+;
+
+static PyObject*
+msh_addTexture(mshobject* self, PyObject* args)
+{
+ char* filename = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ {
+ return NULL;
+ }
+ self->texture = PyString_FromString(filename);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char msh_addVertex__doc__[] =
+"addVertex(self, x, y, z, nx, ny, nz, r = -1.0, g = 0.0, b = 0.0)"
+;
+
+static PyObject*
+msh_addVertex(mshobject* self, PyObject* args)
+{
+ int index;
+ float x, y, z, nx, ny, nz;
+ float r = -1.0, g = 0.0, b = 0.0;
+ PyObject* item1 = NULL;
+ PyObject* item2 = NULL;
+ PyObject* item3 = NULL;
+
+ if (!PyArg_ParseTuple(args, "ffffff|fff", &x, &y, &z, &nx, &ny, &nz,
+ &r, &g, &b))
+ {
+ return NULL;
+ }
+ item1 = PyList_New(3);
+ item2 = PyList_New(3);
+ if (r != -1.0)
+ {
+ item3 = PyList_New(3);
+ }
+ PyList_SetItem(item1, 0, PyFloat_FromDouble(x));
+ PyList_SetItem(item1, 1, PyFloat_FromDouble(y));
+ PyList_SetItem(item1, 2, PyFloat_FromDouble(z));
+ PyList_SetItem(item2, 0, PyFloat_FromDouble(nx));
+ PyList_SetItem(item2, 1, PyFloat_FromDouble(ny));
+ PyList_SetItem(item2, 2, PyFloat_FromDouble(nz));
+ if (r != -1.0)
+ {
+ PyList_SetItem(item3, 0, PyFloat_FromDouble(r));
+ PyList_SetItem(item3, 1, PyFloat_FromDouble(g));
+ PyList_SetItem(item3, 2, PyFloat_FromDouble(b));
+ }
+ PyList_Append(self->vertices, item1);
+ PyList_Append(self->normals, item2);
+ if (r != -1.0)
+ {
+ PyList_Append(self->colors, item3);
+ }
+ index = PyList_Size(self->vertices) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static struct PyMethodDef msh_methods[] = {
+ {"addFace", (PyCFunction)msh_addFace,
+ METH_VARARGS, msh_addFace__doc__},
+ {"addTexCoords", (PyCFunction)msh_addTexCoords,
+ METH_VARARGS, msh_addTexCoords__doc__},
+ {"addTexture", (PyCFunction)msh_addTexture,
+ METH_VARARGS, msh_addTexture__doc__},
+ {"addVertex", (PyCFunction)msh_addVertex,
+ METH_VARARGS, msh_addVertex__doc__},
+
+ { NULL, NULL }
+};
+
+static mshobject*
+newmshobject(char* name)
+{
+ mshobject* self;
+ ID* list = NULL;
+
+ self = PyObject_NEW(mshobject, &Mshtype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->vertices = PyList_New(0);
+ self->normals = PyList_New(0);
+ self->colors = PyList_New(0);
+ self->faces = PyList_New(0);
+ self->texcoords = PyList_New(0);
+ Py_INCREF(Py_None);
+ self->texture = Py_None;
+
+ return self;
+}
+
+static void
+msh_dealloc(mshobject* self)
+{
+ mshobject* msh = (mshobject*) self;
+
+ Py_DECREF(msh->vertices);
+ Py_DECREF(msh->normals);
+ Py_DECREF(msh->colors);
+ Py_DECREF(msh->faces);
+ Py_DECREF(msh->texture);
+ Py_DECREF(msh->texcoords);
+
+ PyMem_DEL(self);
+}
+
+static int
+msh_print(mshobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Mesh(name = \"%s\",\n", self->name);
+ fprintf(fp, " vertices = %d,\n", PyList_Size(self->vertices));
+ fprintf(fp, " faces = %d)\n", PyList_Size(self->faces));
+
+ return 0;
+}
+
+static PyObject*
+msh_repr(mshobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Mesh()\n");
+
+ return s;
+}
+
+static PyObject*
+msh_str(mshobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Mesh()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist msh_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"vertices", T_OBJECT, offsetof(mshobject, vertices), RO},
+ {"normals", T_OBJECT, offsetof(mshobject, normals), RO},
+ {"colors", T_OBJECT, offsetof(mshobject, colors), RO},
+ {"faces", T_OBJECT, offsetof(mshobject, faces), RO},
+ {"texture", T_OBJECT, offsetof(mshobject, texture), RO},
+ {"texcoords", T_OBJECT, offsetof(mshobject, texcoords), RO},
+ {NULL}
+};
+
+static PyObject*
+msh_getattr(mshobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, msh_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(msh_methods, (PyObject*)self, name);
+}
+
+
+static int
+msh_setattr(mshobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, msh_memberlist, name, v);
+}
+
+static char Mshtype__doc__[] =
+""
+;
+
+static PyTypeObject Mshtype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Mesh", /*tp_name*/
+ sizeof(mshobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) msh_dealloc, /*tp_dealloc*/
+ (printfunc) msh_print, /*tp_print*/
+ (getattrfunc) msh_getattr, /*tp_getattr*/
+ (setattrfunc) msh_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) msh_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) msh_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Mshtype__doc__ /* Documentation string */
+};
+
+/**********/
+/* object */
+/**********/
+
+static struct PyMethodDef obj_methods[] = {
+
+ { NULL, NULL }
+};
+
+static objobject*
+newobjobject(char* name)
+{
+ objobject* self = NULL;
+ PyObject* row1 = NULL;
+ PyObject* row2 = NULL;
+ PyObject* row3 = NULL;
+ PyObject* row4 = NULL;
+
+ self = PyObject_NEW(objobject, &Objtype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->matrix = PyList_New(4);
+ row1 = PyList_New(4);
+ row2 = PyList_New(4);
+ row3 = PyList_New(4);
+ row4 = PyList_New(4);
+ PyList_SetItem(row1, 0, PyInt_FromLong(1));
+ PyList_SetItem(row1, 1, PyInt_FromLong(0));
+ PyList_SetItem(row1, 2, PyInt_FromLong(0));
+ PyList_SetItem(row1, 3, PyInt_FromLong(0));
+ PyList_SetItem(row2, 0, PyInt_FromLong(0));
+ PyList_SetItem(row2, 1, PyInt_FromLong(1));
+ PyList_SetItem(row2, 2, PyInt_FromLong(0));
+ PyList_SetItem(row2, 3, PyInt_FromLong(0));
+ PyList_SetItem(row3, 0, PyInt_FromLong(0));
+ PyList_SetItem(row3, 1, PyInt_FromLong(0));
+ PyList_SetItem(row3, 2, PyInt_FromLong(1));
+ PyList_SetItem(row3, 3, PyInt_FromLong(0));
+ PyList_SetItem(row4, 0, PyInt_FromLong(0));
+ PyList_SetItem(row4, 1, PyInt_FromLong(0));
+ PyList_SetItem(row4, 2, PyInt_FromLong(0));
+ PyList_SetItem(row4, 3, PyInt_FromLong(1));
+ PyList_SetItem(self->matrix, 0, row1);
+ PyList_SetItem(self->matrix, 1, row2);
+ PyList_SetItem(self->matrix, 2, row3);
+ PyList_SetItem(self->matrix, 3, row4);
+ self->inverseMatrix = PyList_New(4);
+ row1 = PyList_New(4);
+ row2 = PyList_New(4);
+ row3 = PyList_New(4);
+ row4 = PyList_New(4);
+ PyList_SetItem(row1, 0, PyInt_FromLong(1));
+ PyList_SetItem(row1, 1, PyInt_FromLong(0));
+ PyList_SetItem(row1, 2, PyInt_FromLong(0));
+ PyList_SetItem(row1, 3, PyInt_FromLong(0));
+ PyList_SetItem(row2, 0, PyInt_FromLong(0));
+ PyList_SetItem(row2, 1, PyInt_FromLong(1));
+ PyList_SetItem(row2, 2, PyInt_FromLong(0));
+ PyList_SetItem(row2, 3, PyInt_FromLong(0));
+ PyList_SetItem(row3, 0, PyInt_FromLong(0));
+ PyList_SetItem(row3, 1, PyInt_FromLong(0));
+ PyList_SetItem(row3, 2, PyInt_FromLong(1));
+ PyList_SetItem(row3, 3, PyInt_FromLong(0));
+ PyList_SetItem(row4, 0, PyInt_FromLong(0));
+ PyList_SetItem(row4, 1, PyInt_FromLong(0));
+ PyList_SetItem(row4, 2, PyInt_FromLong(0));
+ PyList_SetItem(row4, 3, PyInt_FromLong(1));
+ PyList_SetItem(self->inverseMatrix, 0, row1);
+ PyList_SetItem(self->inverseMatrix, 1, row2);
+ PyList_SetItem(self->inverseMatrix, 2, row3);
+ PyList_SetItem(self->inverseMatrix, 3, row4);
+ self->materials = PyList_New(0);
+ Py_INCREF(Py_None);
+ self->data = Py_None;
+ Py_INCREF(Py_None);
+ self->type = Py_None;
+
+ return self;
+}
+
+static void
+obj_dealloc(objobject* self)
+{
+ objobject* obj = (objobject*) self;
+
+ Py_DECREF(obj->matrix);
+ Py_DECREF(obj->inverseMatrix);
+ Py_DECREF(obj->materials);
+ Py_DECREF(obj->data);
+ Py_DECREF(obj->type);
+
+ PyMem_DEL(self);
+}
+
+static int
+obj_print(objobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Object(name = \"%s\",\n", self->name);
+/* fprintf(fp, " matrix = %s,\n", */
+/* PyString_AsString(mtx_repr((mtxobject*) self->matrix))); */
+ if (self->type == Py_None)
+ {
+ fprintf(fp, " data = None)\n");
+ }
+ else
+ {
+ fprintf(fp, " data = %s(\"%s\"))\n",
+ PyString_AsString(self->type),
+ PyString_AsString(self->data));
+ }
+
+ return 0;
+}
+
+static PyObject*
+obj_repr(objobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Object()\n");
+
+ return s;
+}
+
+static PyObject*
+obj_str(objobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Object()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist obj_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"data", T_OBJECT, offsetof(objobject, data), RO},
+ {"matrix", T_OBJECT, offsetof(objobject, matrix), RO},
+ {"inverseMatrix", T_OBJECT, offsetof(objobject, inverseMatrix), RO},
+ {"materials", T_OBJECT, offsetof(objobject, materials), RO},
+ {"type", T_OBJECT, offsetof(objobject, type), RO},
+ {NULL}
+};
+
+static PyObject*
+obj_getattr(objobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, obj_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(obj_methods, (PyObject*)self, name);
+}
+
+
+static int
+obj_setattr(objobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, obj_memberlist, name, v);
+}
+
+static char Objtype__doc__[] =
+""
+;
+
+static PyTypeObject Objtype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Object", /*tp_name*/
+ sizeof(objobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) obj_dealloc, /*tp_dealloc*/
+ (printfunc) obj_print, /*tp_print*/
+ (getattrfunc) obj_getattr, /*tp_getattr*/
+ (setattrfunc) obj_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) obj_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) obj_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Objtype__doc__ /* Documentation string */
+};
+
+/*********/
+/* scene */
+/*********/
+
+static char sce_addObject__doc__[] =
+"addObject(self, object)"
+;
+
+static PyObject*
+sce_addObject(sceobject* self, PyObject* args)
+{
+ int index;
+ PyObject* object = NULL;
+
+ if (!PyArg_ParseTuple(args, "O", &object))
+ {
+ return NULL;
+ }
+ PyList_Append(self->objects, object);
+ index = PyList_Size(self->objects) - 1;
+
+ return PyInt_FromLong(index);
+}
+
+static char sce_getCurrentCamera__doc__[] =
+"getCurrentCamera(self)"
+;
+
+static PyObject*
+sce_getCurrentCamera(sceobject* self, PyObject* args)
+{
+ char* name = NULL;
+ PyObject* camera = NULL;
+
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+ if (G.scene->camera)
+ {
+ name = G.scene->camera->id.name+2;
+ camera = blend_getObject(NULL,
+ Py_BuildValue("(O)",
+ PyString_FromString(name)));
+
+ return camera;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static struct PyMethodDef sce_methods[] = {
+ {"addObject", (PyCFunction)sce_addObject,
+ METH_VARARGS, sce_addObject__doc__},
+ {"getCurrentCamera", (PyCFunction)sce_getCurrentCamera,
+ METH_VARARGS, sce_getCurrentCamera__doc__},
+
+ { NULL, NULL }
+};
+
+static sceobject*
+newsceobject(char* name)
+{
+ sceobject* self;
+
+ self = PyObject_NEW(sceobject, &Scetype);
+ if (self == NULL)
+ {
+ return NULL;
+ }
+ strcpy(self->name, name);
+ self->objects = PyList_New(0);
+
+ return self;
+}
+
+static void
+sce_dealloc(sceobject* self)
+{
+ sceobject* sce = (sceobject*) self;
+
+ Py_DECREF(sce->objects);
+
+ PyMem_DEL(self);
+}
+
+static int
+sce_print(sceobject* self, FILE* fp, int flags)
+{
+ fprintf(fp, "Scene(name = \"%s\",\n", self->name);
+ fprintf(fp, " objects = %d)\n", PyList_Size(self->objects));
+
+ return 0;
+}
+
+static PyObject*
+sce_repr(sceobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Scene()\n");
+
+ return s;
+}
+
+static PyObject*
+sce_str(sceobject* self)
+{
+ PyObject* s;
+
+ s = PyString_FromString("Scene()\n");
+
+ return s;
+}
+
+#include "structmember.h"
+
+static struct memberlist sce_memberlist[] = {
+ /* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
+ {"objects", T_OBJECT, offsetof(sceobject, objects), RO},
+ {NULL}
+};
+
+static PyObject*
+sce_getattr(sceobject* self, char* name)
+{
+ PyObject* rv;
+
+ /* XXXX Add your own getattr code here */
+ rv = PyMember_Get((char*) self, sce_memberlist, name);
+ if (rv)
+ {
+ return rv;
+ }
+ PyErr_Clear();
+
+ return Py_FindMethod(sce_methods, (PyObject*)self, name);
+}
+
+
+static int
+sce_setattr(sceobject* self, char* name, PyObject* v)
+{
+ /* XXXX Add your own setattr code here */
+ if ( v == NULL )
+ {
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+ return -1;
+ }
+
+ return PyMember_Set((char*)/*XXXX*/0, sce_memberlist, name, v);
+}
+
+static char Scetype__doc__[] =
+""
+;
+
+static PyTypeObject Scetype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "Scene", /*tp_name*/
+ sizeof(sceobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor) sce_dealloc, /*tp_dealloc*/
+ (printfunc) sce_print, /*tp_print*/
+ (getattrfunc) sce_getattr, /*tp_getattr*/
+ (setattrfunc) sce_setattr, /*tp_setattr*/
+ (cmpfunc) 0, /*tp_compare*/
+ (reprfunc) sce_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc) 0, /*tp_hash*/
+ (ternaryfunc) 0, /*tp_call*/
+ (reprfunc) sce_str, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Scetype__doc__ /* Documentation string */
+};
+
+static char blend_Mesh__doc__[] =
+"Creates an (empty) instance of a Blender mesh.\n\
+ E.g.: \"m = Blender.Mesh('Plane')\"\n\
+ To create faces first add vertices with \n\
+ \"i1 = m.addVertex(x, y, z, nx, ny, nz, r = -1.0, r = 0.0, b = 0.0)\"\n\
+ then create faces with \n\
+ \"index = m.addFace(i1, i2, i3, i4, isSmooth, matIndex)\".\
+"
+;
+
+static PyObject*
+blend_Mesh(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_Object__doc__[] =
+"Creates an instance of a Blender object"
+;
+
+static PyObject*
+blend_Object(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+
+ return ((PyObject*) newobjobject(name));
+}
+
+static char blend_Scene__doc__[] =
+"Creates an instance of a Blender scene"
+;
+
+static PyObject*
+blend_Scene(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+
+ return ((PyObject*) newsceobject(name));
+}
+
+static char blend_addMesh__doc__[] =
+"Blender.addMesh(type, sceneName)\n\
+ where type is one of [\"Plane\"]"
+;
+
+static PyObject*
+blend_addMesh(PyObject* self, PyObject* args)
+{
+ char* type = NULL;
+ char* sceneName = NULL;
+ PyObject* tuple = NULL;
+ PyObject* object = NULL;
+ PyObject* mesh = NULL;
+ PyObject* index = NULL;
+ PyObject* indices = NULL;
+ objobject* obj = NULL;
+ mshobject* msh = NULL;
+
+ if (!PyArg_ParseTuple(args, "ss", &type, &sceneName))
+ {
+ return NULL;
+ }
+
+ if (strcmp(type, "Plane") == 0)
+ {
+ obj = newobjobject(type);
+ msh = newmshobject(type);
+ object = (PyObject*) obj;
+ mesh = (PyObject*) msh;
+ indices = PyList_New(6);
+ /* vertices */
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ 1.0, 1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 0, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ 1.0, -1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 1, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ -1.0, -1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 2, index);
+ index = msh_addVertex((mshobject*) mesh,
+ Py_BuildValue("ffffff",
+ -1.0, 1.0, 0.0, 0.0, 0.0, 1.0));
+ PyList_SetItem(indices, 3, index);
+ PyList_SetItem(indices, 4, PyInt_FromLong(0)); /* smooth flag */
+ PyList_SetItem(indices, 5, PyInt_FromLong(0)); /* material index */
+ /* faces */
+ msh_addFace((mshobject*) mesh,
+ Py_BuildValue("OOOOOO",
+ PyList_GetItem(indices, 0),
+ PyList_GetItem(indices, 3),
+ PyList_GetItem(indices, 2),
+ PyList_GetItem(indices, 1),
+ PyList_GetItem(indices, 4),
+ PyList_GetItem(indices, 5)));
+ /* connection */
+ blend_connect(self, Py_BuildValue("OO",
+ PyString_FromString(obj->name),
+ PyString_FromString(msh->name)));
+ blend_connect(self, Py_BuildValue("OO",
+ PyString_FromString(sceneName),
+ PyString_FromString(obj->name)));
+ /* return value */
+ tuple = PyTuple_New(2);
+ PyTuple_SetItem(tuple, 0, object);
+ PyTuple_SetItem(tuple, 1, mesh);
+
+ return tuple;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_connect__doc__[] =
+"connect(obj1, obj2)"
+;
+
+static PyObject*
+blend_connect(PyObject* self, PyObject* args)
+{
+ PyObject* obj1 = NULL;
+ PyObject* obj2 = NULL;
+
+ if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2))
+ {
+ return NULL;
+ }
+ if (obj1->ob_type == &Objtype)
+ {
+ if (obj2->ob_type == &Mshtype)
+ {
+ Py_INCREF(obj2);
+ ((objobject*) obj1)->data = obj2;
+ ((objobject*) obj1)->type = PyString_FromString("Mesh");
+ }
+ }
+ else if (obj1->ob_type == &Scetype)
+ {
+ if (obj2->ob_type == &Objtype)
+ {
+ sce_addObject((sceobject*) obj1, Py_BuildValue("(O)", obj2));
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char blend_getCamera__doc__[] =
+"getCamera()"
+;
+
+static PyObject*
+blend_getCamera(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Camera* cam = NULL;
+ camobject* camera = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->camera.first, name);
+ if (list)
+ {
+ cam = (Camera*) list;
+ camera = newcamobject(cam->id.name+2);
+ camera->Lens = PyFloat_FromDouble(cam->lens);
+ camera->ClSta = PyFloat_FromDouble(cam->clipsta);
+ camera->ClEnd = PyFloat_FromDouble(cam->clipend);
+
+ return (PyObject*) camera;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static char blend_getCurrentScene__doc__[] =
+"getCurrentScene()"
+;
+
+static PyObject*
+blend_getCurrentScene(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ sceobject* scene = NULL;
+ Base* base = NULL;
+ Object* obj = NULL;
+
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+
+ /* create scene in Python */
+ name = G.scene->id.name+2;
+ scene = newsceobject(name);
+
+ /* add existing objects */
+ base = G.scene->base.first;
+ while (base)
+ {
+ obj = base->object;
+ PyList_Append(scene->objects, PyString_FromString(obj->id.name+2));
+ base = base->next;
+ }
+
+ return (PyObject*) scene;
+}
+
+static char blend_getDisplaySettings__doc__[] =
+"getDisplaySettings()"
+;
+
+static PyObject*
+blend_getDisplaySettings(PyObject* self, PyObject* args)
+{
+ RenderData* rd = NULL;
+ dspobject* displayObject = NULL;
+
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+ rd = &(G.scene->r);
+ displayObject = newdspobject();
+ displayObject->startFrame = PyInt_FromLong(rd->sfra);
+ displayObject->endFrame = PyInt_FromLong(rd->efra);
+ displayObject->currentFrame = PyInt_FromLong(rd->cfra);
+ displayObject->xResolution = PyInt_FromLong(rd->xsch);
+ displayObject->yResolution = PyInt_FromLong(rd->ysch);
+ displayObject->pixelAspectRatio = PyInt_FromLong(rd->yasp /
+ (1.0 * rd->xasp));
+
+ return (PyObject*) displayObject;
+}
+
+static char blend_getLamp__doc__[] =
+"getLamp(name)"
+;
+
+static PyObject*
+blend_getLamp(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Lamp* lmp = NULL;
+ lmpobject* lamp = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->lamp.first, name);
+ if (list)
+ {
+ lmp = (Lamp*) list;
+ lamp = newlmpobject(lmp->id.name+2);
+ lamp->R = PyFloat_FromDouble(lmp->r);
+ lamp->G = PyFloat_FromDouble(lmp->g);
+ lamp->B = PyFloat_FromDouble(lmp->b);
+/* lamp->Dist = PyFloat_FromDouble(lmp->dist); */
+/* lamp->SpoSi = PyFloat_FromDouble(lmp->spotsize); */
+/* lamp->SpoBl = PyFloat_FromDouble(lmp->spotblend); */
+/* lamp->Quad1 = PyFloat_FromDouble(lmp->att1); */
+/* lamp->Quad2 = PyFloat_FromDouble(lmp->att2); */
+/* lamp->HaInt = PyFloat_FromDouble(lmp->haint); */
+
+/* lamp->OfsX = PyFloat_FromDouble(lmp->); */
+/* lamp->OfsY = PyFloat_FromDouble(lmp->); */
+/* lamp->OfsZ = PyFloat_FromDouble(lmp->); */
+/* lamp->SizeX = PyFloat_FromDouble(lmp->); */
+/* lamp->SizeY = PyFloat_FromDouble(lmp->); */
+/* lamp->SizeZ = PyFloat_FromDouble(lmp->); */
+/* lamp->texR = PyFloat_FromDouble(lmp->); */
+/* lamp->texG = PyFloat_FromDouble(lmp->); */
+/* lamp->texB = PyFloat_FromDouble(lmp->); */
+/* lamp->DefVar = PyFloat_FromDouble(lmp->); */
+/* lamp->Col = PyFloat_FromDouble(lmp->); */
+/* lamp->Nor = PyFloat_FromDouble(lmp->); */
+/* lamp->Var = PyFloat_FromDouble(lmp->); */
+
+ return (PyObject*) lamp;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static char blend_getMaterial__doc__[] =
+"getMaterial(name)"
+;
+
+static PyObject*
+blend_getMaterial(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Material* mat = NULL;
+ matobject* material = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->mat.first, name);
+ if (list)
+ {
+ mat = (Material*) list;
+ material = newmatobject(mat->id.name+2);
+ material->R = PyFloat_FromDouble(mat->r);
+ material->G = PyFloat_FromDouble(mat->g);
+ material->B = PyFloat_FromDouble(mat->b);
+
+ return (PyObject*) material;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static char blend_getMesh__doc__[] =
+"getMesh(name)"
+;
+
+static PyObject*
+blend_getMesh(PyObject* self, PyObject* args)
+{
+ int i;
+ float r, g, b;
+ char dummy[] = "";
+ char* name = NULL;
+ char* filename = NULL;
+ uint* mcol = NULL;
+ ID* list = NULL;
+ Mesh* msh = NULL;
+ mshobject* mesh = NULL;
+ MFace* mface = NULL;
+ TFace* tface = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->mesh.first, name);
+ if (list)
+ {
+ msh = (Mesh*) list;
+ mesh = newmshobject(msh->id.name+2);
+ /* is there color information? */
+ if (msh->mcol)
+ {
+ mcol = mcol_to_vcol(msh);
+ }
+ /* add vertices */
+ for (i = 0; i < msh->totvert; i++)
+ {
+ if (msh->mcol && mcol)
+ {
+ mcol_to_rgb(*mcol, &r, &g, &b);
+ msh_addVertex(mesh,
+ Py_BuildValue("fffffffff",
+ msh->mvert[i].co[0],
+ msh->mvert[i].co[1],
+ msh->mvert[i].co[2],
+ msh->mvert[i].no[0] / 32767.0,
+ msh->mvert[i].no[1] / 32767.0,
+ msh->mvert[i].no[2] / 32767.0,
+ r, g, b));
+ mcol++;
+ }
+ else
+ {
+ msh_addVertex(mesh,
+ Py_BuildValue("ffffff",
+ msh->mvert[i].co[0],
+ msh->mvert[i].co[1],
+ msh->mvert[i].co[2],
+ msh->mvert[i].no[0] / 32767.0,
+ msh->mvert[i].no[1] / 32767.0,
+ msh->mvert[i].no[2] / 32767.0));
+ }
+ }
+ /* add faces */
+ for (i = 0; i < msh->totface; i++)
+ {
+ mface = ((MFace*) msh->mface)+i;
+ msh_addFace(mesh,
+ Py_BuildValue("iiiiii",
+ mface->v1, mface->v2,
+ mface->v3, mface->v4,
+ mface->flag, mface->mat_nr));
+ }
+ /* add texture coordinates */
+ if (msh->tface)
+ {
+ tface = (TFace*) msh->tface;
+ if (tface->tpage)
+ {
+ filename = ((Image*) tface->tpage)->name;
+ }
+ else
+ {
+ filename = dummy;
+ }
+ msh_addTexture(mesh,
+ Py_BuildValue("(O)", PyString_FromString(filename)));
+ for (i = 0; i < msh->totface; i++)
+ {
+ tface = (TFace*) msh->tface+i;
+ msh_addTexCoords(mesh,
+ Py_BuildValue("ff",
+ tface->uv[0][0],
+ tface->uv[0][1]));
+ msh_addTexCoords(mesh,
+ Py_BuildValue("ff",
+ tface->uv[1][0],
+ tface->uv[1][1]));
+ msh_addTexCoords(mesh,
+ Py_BuildValue("ff",
+ tface->uv[2][0],
+ tface->uv[2][1]));
+ msh_addTexCoords(mesh,
+ Py_BuildValue("ff",
+ tface->uv[3][0],
+ tface->uv[3][1]));
+ }
+ }
+
+ return (PyObject*) mesh;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static char blend_getObject__doc__[] =
+"getObject(name)"
+;
+
+static PyObject*
+blend_getObject(PyObject* self, PyObject* args)
+{
+ int i;
+ float inverse[4][4];
+ char* name = NULL;
+ ID* list = NULL;
+ Object* obj = NULL;
+ Mesh* msh = NULL;
+ objobject* object = NULL;
+ PyObject* row1 = NULL;
+ PyObject* row2 = NULL;
+ PyObject* row3 = NULL;
+ PyObject* row4 = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->object.first, name);
+ if (list)
+ {
+ obj = (Object*) list;
+ object = newobjobject(obj->id.name+2);
+ Py_DECREF(object->matrix);
+ object->matrix = PyList_New(4);
+ row1 = PyList_New(4);
+ row2 = PyList_New(4);
+ row3 = PyList_New(4);
+ row4 = PyList_New(4);
+ PyList_SetItem(row1, 0, PyFloat_FromDouble(obj->obmat[0][0]));
+ PyList_SetItem(row1, 1, PyFloat_FromDouble(obj->obmat[0][1]));
+ PyList_SetItem(row1, 2, PyFloat_FromDouble(obj->obmat[0][2]));
+ PyList_SetItem(row1, 3, PyFloat_FromDouble(obj->obmat[0][3]));
+ PyList_SetItem(row2, 0, PyFloat_FromDouble(obj->obmat[1][0]));
+ PyList_SetItem(row2, 1, PyFloat_FromDouble(obj->obmat[1][1]));
+ PyList_SetItem(row2, 2, PyFloat_FromDouble(obj->obmat[1][2]));
+ PyList_SetItem(row2, 3, PyFloat_FromDouble(obj->obmat[1][3]));
+ PyList_SetItem(row3, 0, PyFloat_FromDouble(obj->obmat[2][0]));
+ PyList_SetItem(row3, 1, PyFloat_FromDouble(obj->obmat[2][1]));
+ PyList_SetItem(row3, 2, PyFloat_FromDouble(obj->obmat[2][2]));
+ PyList_SetItem(row3, 3, PyFloat_FromDouble(obj->obmat[2][3]));
+ PyList_SetItem(row4, 0, PyFloat_FromDouble(obj->obmat[3][0]));
+ PyList_SetItem(row4, 1, PyFloat_FromDouble(obj->obmat[3][1]));
+ PyList_SetItem(row4, 2, PyFloat_FromDouble(obj->obmat[3][2]));
+ PyList_SetItem(row4, 3, PyFloat_FromDouble(obj->obmat[3][3]));
+ PyList_SetItem(object->matrix, 0, row1);
+ PyList_SetItem(object->matrix, 1, row2);
+ PyList_SetItem(object->matrix, 2, row3);
+ PyList_SetItem(object->matrix, 3, row4);
+ /* inverse matrix */
+ Mat4Invert(inverse, obj->obmat);
+ Py_DECREF(object->inverseMatrix);
+ object->inverseMatrix = PyList_New(4);
+ row1 = PyList_New(4);
+ row2 = PyList_New(4);
+ row3 = PyList_New(4);
+ row4 = PyList_New(4);
+ PyList_SetItem(row1, 0, PyFloat_FromDouble(inverse[0][0]));
+ PyList_SetItem(row1, 1, PyFloat_FromDouble(inverse[0][1]));
+ PyList_SetItem(row1, 2, PyFloat_FromDouble(inverse[0][2]));
+ PyList_SetItem(row1, 3, PyFloat_FromDouble(inverse[0][3]));
+ PyList_SetItem(row2, 0, PyFloat_FromDouble(inverse[1][0]));
+ PyList_SetItem(row2, 1, PyFloat_FromDouble(inverse[1][1]));
+ PyList_SetItem(row2, 2, PyFloat_FromDouble(inverse[1][2]));
+ PyList_SetItem(row2, 3, PyFloat_FromDouble(inverse[1][3]));
+ PyList_SetItem(row3, 0, PyFloat_FromDouble(inverse[2][0]));
+ PyList_SetItem(row3, 1, PyFloat_FromDouble(inverse[2][1]));
+ PyList_SetItem(row3, 2, PyFloat_FromDouble(inverse[2][2]));
+ PyList_SetItem(row3, 3, PyFloat_FromDouble(inverse[2][3]));
+ PyList_SetItem(row4, 0, PyFloat_FromDouble(inverse[3][0]));
+ PyList_SetItem(row4, 1, PyFloat_FromDouble(inverse[3][1]));
+ PyList_SetItem(row4, 2, PyFloat_FromDouble(inverse[3][2]));
+ PyList_SetItem(row4, 3, PyFloat_FromDouble(inverse[3][3]));
+ PyList_SetItem(object->inverseMatrix, 0, row1);
+ PyList_SetItem(object->inverseMatrix, 1, row2);
+ PyList_SetItem(object->inverseMatrix, 2, row3);
+ PyList_SetItem(object->inverseMatrix, 3, row4);
+ Py_DECREF(object->materials);
+ object->materials = PyList_New(obj->totcol);
+ for (i = 0; i < obj->totcol; i++)
+ {
+ if (obj->mat[i])
+ {
+ PyList_SetItem(object->materials, i,
+ PyString_FromString(obj->mat[i]->id.name+2));
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ PyList_SetItem(object->materials, i, Py_None);
+ }
+ } /* check type */
+ switch (obj->type)
+ {
+ case OB_EMPTY:
+ printf("Empty\n");
+ break;
+ case OB_MESH:
+ object->data = PyString_FromString(((Mesh*) obj->data)->id.name+2);
+ object->type = PyString_FromString("Mesh");
+ msh = (Mesh*) obj->data;
+ for (i = 0; i < msh->totcol; i++)
+ {
+ if (msh->mat[i])
+ {
+ PyList_SetItem(object->materials, i,
+ PyString_FromString(msh->mat[i]->id.name+2));
+ }
+ }
+ break;
+ case OB_CURVE:
+ printf("Curve\n");
+ break;
+ case OB_SURF:
+ printf("Surface\n");
+ break;
+ case OB_FONT:
+ printf("Font\n");
+ break;
+ case OB_MBALL:
+ printf("Metaball\n");
+ break;
+ case OB_LAMP:
+ object->data = PyString_FromString(((Lamp*) obj->data)->id.name+2);
+ object->type = PyString_FromString("Lamp");
+ break;
+ case OB_CAMERA:
+ object->data = PyString_FromString(((Camera*) obj->data)->id.name+2);
+ object->type = PyString_FromString("Camera");
+ break;
+ case OB_IKA:
+ printf("Ika\n");
+ break;
+ case OB_WAVE:
+ printf("Wave\n");
+ break;
+ case OB_LATTICE:
+ printf("Lattice\n");
+ break;
+ default:
+ printf("ERROR: py_main.c:blend_getObject(...)\n");
+ printf(" unknown type ...\n");
+ break;
+ }
+
+ return (PyObject*) object;
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static char blend_isCamera__doc__[] =
+"isCamera(name)"
+;
+
+static PyObject*
+blend_isCamera(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Object* obj = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->object.first, name);
+ if (list)
+ {
+ obj = (Object*) list;
+ if (obj->type == OB_CAMERA)
+ {
+ return PyInt_FromLong(1);
+ }
+ else
+ {
+ return PyInt_FromLong(0);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static char blend_isLamp__doc__[] =
+"isLamp(name)"
+;
+
+static PyObject*
+blend_isLamp(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Object* obj = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->object.first, name);
+ if (list)
+ {
+ obj = (Object*) list;
+ if (obj->type == OB_LAMP)
+ {
+ return PyInt_FromLong(1);
+ }
+ else
+ {
+ return PyInt_FromLong(0);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static char blend_isMesh__doc__[] =
+"isMesh(name)"
+;
+
+static PyObject*
+blend_isMesh(PyObject* self, PyObject* args)
+{
+ char* name = NULL;
+ ID* list = NULL;
+ Object* obj = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ {
+ return NULL;
+ }
+ list = find_name_in_list((ID*) G.main->object.first, name);
+ if (list)
+ {
+ obj = (Object*) list;
+ if (obj->type == OB_MESH)
+ {
+ return PyInt_FromLong(1);
+ }
+ else
+ {
+ return PyInt_FromLong(0);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static char blend_setCurrentFrame__doc__[] =
+"setCurrentFrame(frame)"
+;
+
+static PyObject*
+blend_setCurrentFrame(PyObject* self, PyObject* args)
+{
+ int frame = -1;
+
+ if (!PyArg_ParseTuple(args, "i", &frame))
+ {
+ return NULL;
+ }
+ CFRA = frame;
+ drawview3d();
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef blend_methods[] = {
+ {"Mesh", (PyCFunction) blend_Mesh,
+ METH_VARARGS, blend_Mesh__doc__},
+ {"Object", (PyCFunction) blend_Object,
+ METH_VARARGS, blend_Object__doc__},
+ {"Scene", (PyCFunction) blend_Scene,
+ METH_VARARGS, blend_Scene__doc__},
+ {"addMesh", (PyCFunction) blend_addMesh,
+ METH_VARARGS, blend_addMesh__doc__},
+ {"connect", (PyCFunction) blend_connect,
+ METH_VARARGS, blend_connect__doc__},
+ {"getCamera", (PyCFunction) blend_getCamera,
+ METH_VARARGS, blend_getCamera__doc__},
+ {"getCurrentScene", (PyCFunction) blend_getCurrentScene,
+ METH_VARARGS, blend_getCurrentScene__doc__},
+ {"getDisplaySettings", (PyCFunction) blend_getDisplaySettings,
+ METH_VARARGS, blend_getDisplaySettings__doc__},
+ {"getLamp", (PyCFunction) blend_getLamp,
+ METH_VARARGS, blend_getLamp__doc__},
+ {"getMaterial", (PyCFunction) blend_getMaterial,
+ METH_VARARGS, blend_getMaterial__doc__},
+ {"getMesh", (PyCFunction) blend_getMesh,
+ METH_VARARGS, blend_getMesh__doc__},
+ {"getObject", (PyCFunction) blend_getObject,
+ METH_VARARGS, blend_getObject__doc__},
+ {"isCamera", (PyCFunction) blend_isCamera,
+ METH_VARARGS, blend_isCamera__doc__},
+ {"isLamp", (PyCFunction) blend_isLamp,
+ METH_VARARGS, blend_isLamp__doc__},
+ {"isMesh", (PyCFunction) blend_isMesh,
+ METH_VARARGS, blend_isMesh__doc__},
+ {"setCurrentFrame", (PyCFunction) blend_setCurrentFrame,
+ METH_VARARGS, blend_setCurrentFrame__doc__},
+ { NULL, (PyCFunction) NULL, 0, NULL }
+};
+
+static char Blender_module_documentation[] =
+"This is the Python API for Blender"
+;
+
+void
+initBlender()
+{
+ PyObject* m;
+ PyObject* d;
+
+ /* Create the module and add the functions */
+ m = Py_InitModule4("Blender", blend_methods,
+ Blender_module_documentation,
+ (PyObject*)NULL,PYTHON_API_VERSION);
+
+ /* Add some symbolic constants to the module */
+ d = PyModule_GetDict(m);
+ ErrorObject = PyString_FromString("Blender.error");
+ PyDict_SetItemString(d, "error", ErrorObject);
+
+ /* XXXX Add constants here */
+
+ /* Check for errors */
+ if (PyErr_Occurred())
+ {
+ Py_FatalError("can't initialize module Blender");
+ }
+}
+/* Jan Walter's stuff */
diff --git a/intern/python/ribexport.py b/intern/python/ribexport.py
new file mode 100644
index 00000000000..f8dd10afb7d
--- /dev/null
+++ b/intern/python/ribexport.py
@@ -0,0 +1,332 @@
+#######################
+# (c) Jan Walter 2000 #
+#######################
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+import Blender
+import math
+
+exportAnimations = 0
+
+class RenderManExport:
+ def __init__(self, filename):
+ self.file = open(filename, "w")
+ self.scene = None
+ self.display = None
+
+ def export(self, scene):
+ global exportAnimations
+
+ print "exporting ..."
+ self.scene = scene
+ self.writeHeader()
+ self.display = Blender.getDisplaySettings()
+ if exportAnimations:
+ for frame in xrange(self.display.startFrame,
+ self.display.endFrame + 1):
+ self.writeFrame(frame)
+ else:
+ self.writeFrame(self.display.currentFrame)
+ self.writeEnd()
+
+ def writeCamera(self):
+ camobj = self.scene.getCurrentCamera()
+ camera = Blender.getCamera(camobj.data)
+ factor = self.display.yResolution / float(self.display.xResolution)
+ self.file.write('Projection "perspective" "fov" [%s]\n' %
+ (360.0 * math.atan(factor * 16.0 / camera.Lens) /
+ math.pi))
+ self.file.write("Clipping %s %s\n" % (camera.ClSta, camera.ClEnd))
+ self.file.write("Transform [" +
+ "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n" %
+ (camobj.inverseMatrix[0][0],
+ camobj.inverseMatrix[0][1],
+ -camobj.inverseMatrix[0][2],
+ camobj.inverseMatrix[0][3],
+ camobj.inverseMatrix[1][0],
+ camobj.inverseMatrix[1][1],
+ -camobj.inverseMatrix[1][2],
+ camobj.inverseMatrix[1][3],
+ camobj.inverseMatrix[2][0],
+ camobj.inverseMatrix[2][1],
+ -camobj.inverseMatrix[2][2],
+ camobj.inverseMatrix[2][3],
+ camobj.inverseMatrix[3][0],
+ camobj.inverseMatrix[3][1],
+ -camobj.inverseMatrix[3][2],
+ camobj.inverseMatrix[3][3]))
+
+ def writeDisplaySettings(self, frame):
+ self.file.write("Format %s %s %s\n" % (self.display.xResolution,
+ self.display.yResolution,
+ self.display.pixelAspectRatio))
+ self.file.write('Display "%s" "file" "rgba"\n' %
+ ("frame" + "%04d" % frame + ".tif"))
+
+ def writeEnd(self):
+ self.file.close()
+ print "... finished"
+
+ def writeFrame(self, frame):
+ print "frame:", frame
+ Blender.setCurrentFrame(frame)
+ self.file.write("FrameBegin %s\n" % (frame - self.display.startFrame))
+ self.writeDisplaySettings(frame)
+ self.writeCamera()
+ self.writeWorld()
+ self.file.write("FrameEnd\n")
+
+ def writeHeader(self):
+ self.file.write("##RenderMan RIB-Structure 1.0\n")
+ self.file.write("version 3.03\n")
+
+ def writeIdentifier(self, name):
+ self.file.write("%s\n" % ("#" * (len(name) + 4)))
+ self.file.write("# %s #\n" % name)
+ self.file.write("%s\n" % ("#" * (len(name) + 4)))
+
+ def writeLamp(self, name, num):
+ self.writeIdentifier(name)
+ lampobj = Blender.getObject(name)
+ lamp = Blender.getLamp(lampobj.data)
+ x = lampobj.matrix[3][0] / lampobj.matrix[3][3]
+ y = lampobj.matrix[3][1] / lampobj.matrix[3][3]
+ z = lampobj.matrix[3][2] / lampobj.matrix[3][3]
+ self.file.write('LightSource "pointlight" %s ' % num +
+ '"from" [%s %s %s] ' % (x, y, z) +
+ '"lightcolor" [%s %s %s] ' % (lamp.R, lamp.G, lamp.B) +
+ '"intensity" 50\n')
+
+ def writeMatrix(self, matrix):
+ self.file.write("Transform [" +
+ "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n" %
+ (matrix[0][0], matrix[0][1],
+ matrix[0][2], matrix[0][3],
+ matrix[1][0], matrix[1][1],
+ matrix[1][2], matrix[1][3],
+ matrix[2][0], matrix[2][1],
+ matrix[2][2], matrix[2][3],
+ matrix[3][0], matrix[3][1],
+ matrix[3][2], matrix[3][3]))
+
+ def writeObject(self, name):
+ if Blender.isMesh(name):
+ self.writeIdentifier(name)
+ meshobj = Blender.getObject(name)
+ mesh = Blender.getMesh(meshobj.data)
+ if mesh.texcoords:
+ self.file.write('Surface "paintedplastic" "texturename" ' +
+ '["%s.tif"]\n' % "st")
+ else:
+ self.file.write('Surface "plastic"\n')
+ self.file.write("Color [%s %s %s]\n" % (0.8, 0.8, 0.8))
+ self.file.write("AttributeBegin\n")
+ self.writeMatrix(meshobj.matrix)
+ index = 0
+ for face in mesh.faces:
+ if meshobj.materials and meshobj.materials[face[5]]:
+ material = Blender.getMaterial(meshobj.materials[face[5]])
+ self.file.write("Color [%s %s %s]\n" %
+ (material.R, material.G, material.B))
+ if face[3]:
+ # quad
+ if face[4]: # smooth
+ # first triangle
+ self.file.write('Polygon "P" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ self.file.write('] "N" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.normals[face[i]][0],
+ mesh.normals[face[i]][1],
+ mesh.normals[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ # second triangle
+ self.file.write('Polygon "P" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ self.file.write('] "N" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s %s " %
+ (mesh.normals[face[i]][0],
+ mesh.normals[face[i]][1],
+ mesh.normals[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ else: # not smooth
+ # first triangle
+ self.file.write('Polygon "P" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ # second triangle
+ self.file.write('Polygon "P" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in [0, 2, 3]:
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ else:
+ # triangle
+ if face[4]: # smooth
+ self.file.write('Polygon "P" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ self.file.write('] "N" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.normals[face[i]][0],
+ mesh.normals[face[i]][1],
+ mesh.normals[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ else: # not smooth
+ self.file.write('Polygon "P" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.vertices[face[i]][0],
+ mesh.vertices[face[i]][1],
+ mesh.vertices[face[i]][2]))
+ if mesh.colors:
+ self.file.write('] "Cs" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s %s " %
+ (mesh.colors[face[i]][0],
+ mesh.colors[face[i]][1],
+ mesh.colors[face[i]][2]))
+ self.file.write(']\n')
+ if mesh.texcoords:
+ self.file.write('] "st" [ ')
+ for i in xrange(3):
+ self.file.write("%s %s " %
+ (mesh.texcoords[index+i][0],
+ 1.0 -
+ mesh.texcoords[index+i][1]))
+ self.file.write(']\n')
+ else:
+ self.file.write(']\n')
+ index = index + 4
+ self.file.write("AttributeEnd\n")
+ else:
+ print "Sorry can export meshes only ..."
+
+ def writeWorld(self):
+ self.file.write("WorldBegin\n")
+ self.file.write('Attribute "light" "shadows" "on"\n')
+ # first all lights
+ lamps = 0
+ for name in self.scene.objects:
+ if Blender.isLamp(name):
+ lamps = lamps + 1
+ self.writeLamp(name, lamps)
+ # now all objects which are not a camera or a light
+ for name in self.scene.objects:
+ if not Blender.isCamera(name) and not Blender.isLamp(name):
+ self.writeObject(name)
+ self.file.write("WorldEnd\n")
+
+ribexport = RenderManExport("test.rib")
+scene = Blender.getCurrentScene()
+ribexport.export(scene)
diff --git a/intern/python/testmodule/Makefile.pre.in b/intern/python/testmodule/Makefile.pre.in
new file mode 100644
index 00000000000..6d9190d76f4
--- /dev/null
+++ b/intern/python/testmodule/Makefile.pre.in
@@ -0,0 +1,305 @@
+# Universal Unix Makefile for Python extensions
+# =============================================
+
+# Short Instructions
+# ------------------
+
+# 1. Build and install Python (1.5 or newer).
+# 2. "make -f Makefile.pre.in boot"
+# 3. "make"
+# You should now have a shared library.
+
+# Long Instructions
+# -----------------
+
+# Build *and install* the basic Python 1.5 distribution. See the
+# Python README for instructions. (This version of Makefile.pre.in
+# only withs with Python 1.5, alpha 3 or newer.)
+
+# Create a file Setup.in for your extension. This file follows the
+# format of the Modules/Setup.in file; see the instructions there.
+# For a simple module called "spam" on file "spammodule.c", it can
+# contain a single line:
+# spam spammodule.c
+# You can build as many modules as you want in the same directory --
+# just have a separate line for each of them in the Setup.in file.
+
+# If you want to build your extension as a shared library, insert a
+# line containing just the string
+# *shared*
+# at the top of your Setup.in file.
+
+# Note that the build process copies Setup.in to Setup, and then works
+# with Setup. It doesn't overwrite Setup when Setup.in is changed, so
+# while you're in the process of debugging your Setup.in file, you may
+# want to edit Setup instead, and copy it back to Setup.in later.
+# (All this is done so you can distribute your extension easily and
+# someone else can select the modules they actually want to build by
+# commenting out lines in the Setup file, without editing the
+# original. Editing Setup is also used to specify nonstandard
+# locations for include or library files.)
+
+# Copy this file (Misc/Makefile.pre.in) to the directory containing
+# your extension.
+
+# Run "make -f Makefile.pre.in boot". This creates Makefile
+# (producing Makefile.pre and sedscript as intermediate files) and
+# config.c, incorporating the values for sys.prefix, sys.exec_prefix
+# and sys.version from the installed Python binary. For this to work,
+# the python binary must be on your path. If this fails, try
+# make -f Makefile.pre.in Makefile VERSION=1.5 installdir=<prefix>
+# where <prefix> is the prefix used to install Python for installdir
+# (and possibly similar for exec_installdir=<exec_prefix>).
+
+# Note: "make boot" implies "make clobber" -- it assumes that when you
+# bootstrap you may have changed platforms so it removes all previous
+# output files.
+
+# If you are building your extension as a shared library (your
+# Setup.in file starts with *shared*), run "make" or "make sharedmods"
+# to build the shared library files. If you are building a statically
+# linked Python binary (the only solution of your platform doesn't
+# support shared libraries, and sometimes handy if you want to
+# distribute or install the resulting Python binary), run "make
+# python".
+
+# Note: Each time you edit Makefile.pre.in or Setup, you must run
+# "make Makefile" before running "make".
+
+# Hint: if you want to use VPATH, you can start in an empty
+# subdirectory and say (e.g.):
+# make -f ../Makefile.pre.in boot srcdir=.. VPATH=..
+
+
+# === Bootstrap variables (edited through "make boot") ===
+
+# The prefix used by "make inclinstall libainstall" of core python
+installdir= /usr/local
+
+# The exec_prefix used by the same
+exec_installdir=$(installdir)
+
+# Source directory and VPATH in case you want to use VPATH.
+# (You will have to edit these two lines yourself -- there is no
+# automatic support as the Makefile is not generated by
+# config.status.)
+srcdir= .
+VPATH= .
+
+# === Variables that you may want to customize (rarely) ===
+
+# (Static) build target
+TARGET= python
+
+# Installed python binary (used only by boot target)
+PYTHON= python
+
+# Add more -I and -D options here
+CFLAGS= $(OPT) -I$(INCLUDEPY) -I$(EXECINCLUDEPY) $(DEFS)
+
+# These two variables can be set in Setup to merge extensions.
+# See example[23].
+BASELIB=
+BASESETUP=
+
+# === Variables set by makesetup ===
+
+MODOBJS= _MODOBJS_
+MODLIBS= _MODLIBS_
+
+# === Definitions added by makesetup ===
+
+# === Variables from configure (through sedscript) ===
+
+VERSION= @VERSION@
+CC= @CC@
+LINKCC= @LINKCC@
+SGI_ABI= @SGI_ABI@
+OPT= @OPT@
+LDFLAGS= @LDFLAGS@
+LDLAST= @LDLAST@
+DEFS= @DEFS@
+LIBS= @LIBS@
+LIBM= @LIBM@
+LIBC= @LIBC@
+RANLIB= @RANLIB@
+MACHDEP= @MACHDEP@
+SO= @SO@
+LDSHARED= @LDSHARED@
+CCSHARED= @CCSHARED@
+LINKFORSHARED= @LINKFORSHARED@
+#@SET_CCC@
+
+# Install prefix for architecture-independent files
+prefix= /usr/local
+
+# Install prefix for architecture-dependent files
+exec_prefix= $(prefix)
+
+# Uncomment the following two lines for AIX
+#LINKCC= $(LIBPL)/makexp_aix $(LIBPL)/python.exp "" $(LIBRARY); $(PURIFY) $(CC)
+#LDSHARED= $(LIBPL)/ld_so_aix $(CC) -bI:$(LIBPL)/python.exp
+
+# === Fixed definitions ===
+
+# Shell used by make (some versions default to the login shell, which is bad)
+SHELL= /bin/sh
+
+# Expanded directories
+BINDIR= $(exec_installdir)/bin
+LIBDIR= $(exec_prefix)/lib
+MANDIR= $(installdir)/man
+INCLUDEDIR= $(installdir)/include
+SCRIPTDIR= $(prefix)/lib
+
+# Detailed destination directories
+BINLIBDEST= $(LIBDIR)/python$(VERSION)
+LIBDEST= $(SCRIPTDIR)/python$(VERSION)
+INCLUDEPY= $(INCLUDEDIR)/python$(VERSION)
+EXECINCLUDEPY= $(exec_installdir)/include/python$(VERSION)
+LIBP= $(exec_installdir)/lib/python$(VERSION)
+DESTSHARED= $(BINLIBDEST)/site-packages
+
+LIBPL= $(LIBP)/config
+
+PYTHONLIBS= $(LIBPL)/libpython$(VERSION).a
+
+MAKESETUP= $(LIBPL)/makesetup
+MAKEFILE= $(LIBPL)/Makefile
+CONFIGC= $(LIBPL)/config.c
+CONFIGCIN= $(LIBPL)/config.c.in
+SETUP= $(LIBPL)/Setup.thread $(LIBPL)/Setup.local $(LIBPL)/Setup
+
+SYSLIBS= $(LIBM) $(LIBC)
+
+ADDOBJS= $(LIBPL)/python.o config.o
+
+# Portable install script (configure doesn't always guess right)
+INSTALL= $(LIBPL)/install-sh -c
+# Shared libraries must be installed with executable mode on some systems;
+# rather than figuring out exactly which, we always give them executable mode.
+# Also, making them read-only seems to be a good idea...
+INSTALL_SHARED= ${INSTALL} -m 555
+
+# === Fixed rules ===
+
+# Default target. This builds shared libraries only
+default: sharedmods
+
+# Build everything
+all: static sharedmods
+
+# Build shared libraries from our extension modules
+sharedmods: $(SHAREDMODS)
+
+# Build a static Python binary containing our extension modules
+static: $(TARGET)
+$(TARGET): $(ADDOBJS) lib.a $(PYTHONLIBS) Makefile $(BASELIB)
+ $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) \
+ $(ADDOBJS) lib.a $(PYTHONLIBS) \
+ $(LINKPATH) $(BASELIB) $(MODLIBS) $(LIBS) $(SYSLIBS) \
+ -o $(TARGET) $(LDLAST)
+
+install: sharedmods
+ if test ! -d $(DESTSHARED) ; then \
+ mkdir $(DESTSHARED) ; else true ; fi
+ -for i in X $(SHAREDMODS); do \
+ if test $$i != X; \
+ then $(INSTALL_SHARED) $$i $(DESTSHARED)/$$i; \
+ fi; \
+ done
+
+# Build the library containing our extension modules
+lib.a: $(MODOBJS)
+ -rm -f lib.a
+ ar cr lib.a $(MODOBJS)
+ -$(RANLIB) lib.a
+
+# This runs makesetup *twice* to use the BASESETUP definition from Setup
+config.c Makefile: Makefile.pre Setup $(BASESETUP) $(MAKESETUP)
+ $(MAKESETUP) \
+ -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP)
+ $(MAKE) -f Makefile do-it-again
+
+# Internal target to run makesetup for the second time
+do-it-again:
+ $(MAKESETUP) \
+ -m Makefile.pre -c $(CONFIGCIN) Setup -n $(BASESETUP) $(SETUP)
+
+# Make config.o from the config.c created by makesetup
+config.o: config.c
+ $(CC) $(CFLAGS) -c config.c
+
+# Setup is copied from Setup.in *only* if it doesn't yet exist
+Setup:
+ cp $(srcdir)/Setup.in Setup
+
+# Make the intermediate Makefile.pre from Makefile.pre.in
+Makefile.pre: Makefile.pre.in sedscript
+ sed -f sedscript $(srcdir)/Makefile.pre.in >Makefile.pre
+
+# Shortcuts to make the sed arguments on one line
+P=prefix
+E=exec_prefix
+H=Generated automatically from Makefile.pre.in by sedscript.
+L=LINKFORSHARED
+
+# Make the sed script used to create Makefile.pre from Makefile.pre.in
+sedscript: $(MAKEFILE)
+ sed -n \
+ -e '1s/.*/1i\\/p' \
+ -e '2s%.*%# $H%p' \
+ -e '/^VERSION=/s/^VERSION=[ ]*\(.*\)/s%@VERSION[@]%\1%/p' \
+ -e '/^CC=/s/^CC=[ ]*\(.*\)/s%@CC[@]%\1%/p' \
+ -e '/^CCC=/s/^CCC=[ ]*\(.*\)/s%#@SET_CCC[@]%CCC=\1%/p' \
+ -e '/^LINKCC=/s/^LINKCC=[ ]*\(.*\)/s%@LINKCC[@]%\1%/p' \
+ -e '/^OPT=/s/^OPT=[ ]*\(.*\)/s%@OPT[@]%\1%/p' \
+ -e '/^LDFLAGS=/s/^LDFLAGS=[ ]*\(.*\)/s%@LDFLAGS[@]%\1%/p' \
+ -e '/^LDLAST=/s/^LDLAST=[ ]*\(.*\)/s%@LDLAST[@]%\1%/p' \
+ -e '/^DEFS=/s/^DEFS=[ ]*\(.*\)/s%@DEFS[@]%\1%/p' \
+ -e '/^LIBS=/s/^LIBS=[ ]*\(.*\)/s%@LIBS[@]%\1%/p' \
+ -e '/^LIBM=/s/^LIBM=[ ]*\(.*\)/s%@LIBM[@]%\1%/p' \
+ -e '/^LIBC=/s/^LIBC=[ ]*\(.*\)/s%@LIBC[@]%\1%/p' \
+ -e '/^RANLIB=/s/^RANLIB=[ ]*\(.*\)/s%@RANLIB[@]%\1%/p' \
+ -e '/^MACHDEP=/s/^MACHDEP=[ ]*\(.*\)/s%@MACHDEP[@]%\1%/p' \
+ -e '/^SO=/s/^SO=[ ]*\(.*\)/s%@SO[@]%\1%/p' \
+ -e '/^LDSHARED=/s/^LDSHARED=[ ]*\(.*\)/s%@LDSHARED[@]%\1%/p' \
+ -e '/^CCSHARED=/s/^CCSHARED=[ ]*\(.*\)/s%@CCSHARED[@]%\1%/p' \
+ -e '/^SGI_ABI=/s/^SGI_ABI=[ ]*\(.*\)/s%@SGI_ABI[@]%\1%/p' \
+ -e '/^$L=/s/^$L=[ ]*\(.*\)/s%@$L[@]%\1%/p' \
+ -e '/^$P=/s/^$P=\(.*\)/s%^$P=.*%$P=\1%/p' \
+ -e '/^$E=/s/^$E=\(.*\)/s%^$E=.*%$E=\1%/p' \
+ $(MAKEFILE) >sedscript
+ echo "/^#@SET_CCC@/d" >>sedscript
+ echo "/^installdir=/s%=.*%= $(installdir)%" >>sedscript
+ echo "/^exec_installdir=/s%=.*%=$(exec_installdir)%" >>sedscript
+ echo "/^srcdir=/s%=.*%= $(srcdir)%" >>sedscript
+ echo "/^VPATH=/s%=.*%= $(VPATH)%" >>sedscript
+ echo "/^LINKPATH=/s%=.*%= $(LINKPATH)%" >>sedscript
+ echo "/^BASELIB=/s%=.*%= $(BASELIB)%" >>sedscript
+ echo "/^BASESETUP=/s%=.*%= $(BASESETUP)%" >>sedscript
+
+# Bootstrap target
+boot: clobber
+ VERSION=`$(PYTHON) -c "import sys; print sys.version[:3]"`; \
+ installdir=`$(PYTHON) -c "import sys; print sys.prefix"`; \
+ exec_installdir=`$(PYTHON) -c "import sys; print sys.exec_prefix"`; \
+ $(MAKE) -f $(srcdir)/Makefile.pre.in VPATH=$(VPATH) srcdir=$(srcdir) \
+ VERSION=$$VERSION \
+ installdir=$$installdir \
+ exec_installdir=$$exec_installdir \
+ Makefile
+
+# Handy target to remove intermediate files and backups
+clean:
+ -rm -f *.o *~
+
+# Handy target to remove everything that is easily regenerated
+clobber: clean
+ -rm -f *.a tags TAGS config.c Makefile.pre $(TARGET) sedscript
+ -rm -f *.so *.sl so_locations
+
+
+# Handy target to remove everything you don't want to distribute
+distclean: clobber
+ -rm -f Makefile Setup
diff --git a/intern/python/testmodule/Setup.in b/intern/python/testmodule/Setup.in
new file mode 100644
index 00000000000..40291806dd0
--- /dev/null
+++ b/intern/python/testmodule/Setup.in
@@ -0,0 +1,2 @@
+*shared*
+testmodule testmodule.c
diff --git a/intern/python/testmodule/test.py b/intern/python/testmodule/test.py
new file mode 100755
index 00000000000..521348acb59
--- /dev/null
+++ b/intern/python/testmodule/test.py
@@ -0,0 +1,16 @@
+#! /usr/bin/env python
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+import testmodule
+
+tc = testmodule.TestClass()
+
+print tc.memberVariable
+tc.memberVariable = 1
+print tc.memberVariable
+tc.memberFunction()
diff --git a/intern/python/testmodule/testmodule.c b/intern/python/testmodule/testmodule.c
new file mode 100644
index 00000000000..8ad894d8aad
--- /dev/null
+++ b/intern/python/testmodule/testmodule.c
@@ -0,0 +1,182 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/***********************/
+
+/* (c) Jan Walter 2000 */
+/***********************/
+
+/* CVS */
+/* $Author$ */
+/* $Date$ */
+/* $RCSfile$ */
+/* $Revision$ */
+
+#include "Python.h"
+
+/************************************/
+/* struct for the class "TestClass" */
+/************************************/
+
+typedef struct {
+ PyObject_HEAD
+ PyObject* memberVariable;
+} testclass;
+
+staticforward PyTypeObject TestclassType;
+
+/************************************/
+/* make instance of class TestClass */
+/************************************/
+
+static testclass*
+newtestclass()
+{
+ testclass* tc;
+ tc = PyObject_NEW(testclass, &TestclassType);
+ if (tc == NULL)
+ {
+ return NULL;
+ }
+ tc->memberVariable = PyString_FromString("initValue");
+
+ return tc;
+}
+
+/*********************************/
+/* instance methods of TestClass */
+/*********************************/
+
+static PyObject*
+testclass_memberFunction(PyObject* tc, PyObject* args)
+{
+ PyRun_SimpleString("print \"inside memberFunction() ...\"\n");
+
+ Py_INCREF(Py_None);
+
+ return Py_None;
+}
+
+static struct PyMethodDef testclass_methods[] = {
+ { "memberFunction", testclass_memberFunction, METH_VARARGS },
+ { NULL, NULL }
+};
+
+/*********************************/
+/* basic operations on TestClass */
+/*********************************/
+
+static PyObject*
+testclass_dealloc(testclass* tc)
+{
+ PyMem_DEL(tc);
+}
+
+static PyObject*
+testclass_getattr(testclass* tc, char* name)
+{
+ if (strcmp(name, "memberVariable") == 0)
+ {
+ return Py_BuildValue("O", tc->memberVariable);
+ }
+ else
+ {
+ return Py_FindMethod(testclass_methods, (PyObject*) tc, name);
+ }
+}
+
+static int
+testclass_setattr(testclass* tc, char* name, PyObject* attr)
+{
+ if (strcmp(name, "memberVariable") == 0)
+ {
+ Py_XDECREF(tc->memberVariable);
+ tc->memberVariable = attr;
+ Py_INCREF(attr);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, name);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/************************************/
+/* table of functions for TestClass */
+/************************************/
+
+static PyTypeObject TestclassType = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+ "testclass", /* tp_name */
+ sizeof(testclass), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) testclass_dealloc, /* tp_dealloc */
+ (printfunc) 0, /* tp_print */
+ (getattrfunc) testclass_getattr, /* tp_getattr */
+ (setattrfunc) testclass_setattr, /* tp_setattr */
+ (cmpfunc) 0, /* tp_compare */
+ (reprfunc) 0, /* tp_repr */
+ /* there is more ... */
+}; /* see Include/object.h */
+
+/***********************************/
+/* constructor for class TestClass */
+/***********************************/
+
+static PyObject*
+testclass_new(PyObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ {
+ return NULL;
+ }
+
+ return (PyObject*) newtestclass();
+}
+
+/*********************/
+/* module testmodule */
+/*********************/
+
+static struct PyMethodDef testmodule_methods[] = {
+ { "TestClass", testclass_new, METH_VARARGS },
+ { NULL, NULL }
+};
+
+void
+inittestmodule()
+{
+ (void) Py_InitModule("testmodule", testmodule_methods);
+}
diff --git a/intern/python/testmodule/testmodule.py b/intern/python/testmodule/testmodule.py
new file mode 100644
index 00000000000..3afb7556361
--- /dev/null
+++ b/intern/python/testmodule/testmodule.py
@@ -0,0 +1,14 @@
+#! /usr/bin/env python
+
+# CVS
+# $Author$
+# $Date$
+# $RCSfile$
+# $Revision$
+
+class TestClass:
+ def __init__(self):
+ self.memberVariable = "initValue"
+
+ def memberFunction(self):
+ print "inside memberFunction() ..."
diff --git a/intern/string/Makefile b/intern/string/Makefile
new file mode 100644
index 00000000000..b2ae80e2179
--- /dev/null
+++ b/intern/string/Makefile
@@ -0,0 +1,52 @@
+#
+# $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.
+#
+# 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 *****
+# string main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = string
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+# not yet TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_STRING) ] || mkdir $(NAN_STRING)
+ @[ -d $(NAN_STRING)/include ] || mkdir $(NAN_STRING)/include
+ @[ -d $(NAN_STRING)/lib ] || mkdir $(NAN_STRING)/lib
+ @[ -d $(NAN_STRING)/lib/debug ] || mkdir $(NAN_STRING)/lib/debug
+ cp -f $(DIR)/libstring.a $(NAN_STRING)/lib/
+ cp -f $(DIR)/debug/libstring.a $(NAN_STRING)/lib/debug/
+ cp -f *.h $(NAN_STRING)/include/
+
diff --git a/intern/string/STR_HashedString.h b/intern/string/STR_HashedString.h
new file mode 100644
index 00000000000..bf18a4e4da6
--- /dev/null
+++ b/intern/string/STR_HashedString.h
@@ -0,0 +1,154 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * This file was formerly known as: GEN_StdString.cpp.
+ * @date November, 14, 2001
+ */
+
+#ifndef __STR_HASHSTRING
+#define __STR_HASHSTRING
+
+#include "STR_String.h"
+
+
+// Hash Mix utility function, by Bob Jenkins - Mix 3 32-bit values reversibly
+//
+// - If gHashMix() is run forward or backward, at least 32 bits in a,b,c have at
+// least 1/4 probability of changing.
+//
+// - If gHashMix() is run forward, every bit of c will change between 1/3 and
+// 2/3 of the time.
+//
+static inline void STR_gHashMix(dword& a, dword& b, dword& c)
+{
+ a -= b; a -= c; a ^= (c>>13);
+ b -= c; b -= a; b ^= (a<<8);
+ c -= a; c -= b; c ^= (b>>13);
+ a -= b; a -= c; a ^= (c>>12);
+ b -= c; b -= a; b ^= (a<<16);
+ c -= a; c -= b; c ^= (b>>5);
+ a -= b; a -= c; a ^= (c>>3);
+ b -= c; b -= a; b ^= (a<<10);
+ c -= a; c -= b; c ^= (b>>15);
+}
+
+//
+// Fast Hashable<int32> functionality
+// http://www.concentric.net/~Ttwang/tech/inthash.htm
+//
+static inline dword STR_gHash(dword inDWord)
+{
+ dword key = inDWord;
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+ return key;
+}
+
+enum { GOLDEN_RATIO = 0x9e3779b9 }; // arbitrary value to initialize hash funtion, well not so arbitrary
+ // as this value is taken from the pigs library (Orange Games/Lost Boys)
+
+
+
+static dword STR_gHash(const void* in, int len, dword init_val)
+{
+ unsigned int length = len;
+ dword a = (dword)GOLDEN_RATIO;
+ dword b = (dword)GOLDEN_RATIO;
+ dword c = init_val; // the previous hash value
+ byte *p_in = (byte *)in;
+
+ // Do the largest part of the key
+ while (length >= 12)
+ {
+ a += (p_in[0] + ((dword)p_in[1]<<8) + ((dword)p_in[2] <<16) + ((dword)p_in[3] <<24));
+ b += (p_in[4] + ((dword)p_in[5]<<8) + ((dword)p_in[6] <<16) + ((dword)p_in[7] <<24));
+ c += (p_in[8] + ((dword)p_in[9]<<8) + ((dword)p_in[10]<<16) + ((dword)p_in[11]<<24));
+ STR_gHashMix(a, b, c);
+ p_in += 12; length -= 12;
+ }
+
+ // Handle the last 11 bytes
+ c += len;
+ switch(length) {
+ case 11: c+=((dword)p_in[10]<<24);
+ case 10: c+=((dword)p_in[9]<<16);
+ case 9 : c+=((dword)p_in[8]<<8); // the first byte of c is reserved for the length
+ case 8 : b+=((dword)p_in[7]<<24);
+ case 7 : b+=((dword)p_in[6]<<16);
+ case 6 : b+=((dword)p_in[5]<<8);
+ case 5 : b+=p_in[4];
+ case 4 : a+=((dword)p_in[3]<<24);
+ case 3 : a+=((dword)p_in[2]<<16);
+ case 2 : a+=((dword)p_in[1]<<8);
+ case 1 : a+=p_in[0];
+ }
+ STR_gHashMix(a, b, c);
+
+ return c;
+}
+
+
+
+
+class STR_HashedString : public STR_String
+{
+public:
+ STR_HashedString() : STR_String(),m_Hashed(false) {}
+ STR_HashedString(const char* str) : STR_String(str),m_Hashed(false) {}
+ STR_HashedString(const STR_String& str) : STR_String(str),m_Hashed(false) {}
+
+ inline dword hash(dword init=0) const
+ {
+ if (!m_Hashed)
+ {
+ const char* str = *this;
+ int length = this->Length();
+ m_CachedHash = STR_gHash(str,length,init);
+ m_Hashed=true;
+ }
+ return m_CachedHash;
+ }
+
+private:
+ mutable bool m_Hashed;
+ mutable dword m_CachedHash;
+};
+
+#endif //__STR_HASHSTRING
+
diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h
new file mode 100644
index 00000000000..78bef5f6728
--- /dev/null
+++ b/intern/string/STR_String.h
@@ -0,0 +1,202 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * This file was formerly known as: GEN_StdString.h.
+ * @date April, 25, 2001
+ */
+
+#ifndef _STR_String_H_
+#define _STR_String_H_
+
+#ifndef STR_NO_ASSERTD
+#undef assertd
+#define assertd(exp) ((void)NULL)
+#endif
+
+#include <vector>
+#include <limits.h>
+using namespace std;
+
+
+class STR_String;
+
+typedef unsigned long dword;
+typedef const STR_String& rcSTR_String;
+typedef unsigned char byte;
+
+/**
+ * Smart String Value class. Is used by parser when an expression tree is build containing string.
+*/
+
+class STR_String
+{
+public:
+ // Initialization
+ STR_String();
+ STR_String(char c);
+ STR_String(char c, int len);
+ STR_String(const char *str);
+ STR_String(const char *str, int len);
+ STR_String(const STR_String &str);
+ STR_String(const STR_String & str, int len);
+ STR_String(const char *src1, int src1_len, const char *src2, int src2_len);
+ explicit STR_String(int val);
+ explicit STR_String(dword val);
+ explicit STR_String(float val);
+ explicit STR_String(double val);
+ inline ~STR_String() { delete[] pData; }
+
+ // Operations
+ STR_String& Format(const char *fmt, ...); // Set formatted text to string
+ STR_String& FormatAdd(const char *fmt, ...); // Add formatted text to string
+ inline void Clear() { Len = pData[0] = 0; }
+ inline const STR_String & Reverse()
+ {
+ for (int i1=0, i2=Len-1; i1<i2; i1++, i2--)
+ swap(pData[i1], pData[i2]); return *this;
+ }
+
+ // Properties
+ bool IsUpper() const;
+ bool IsLower() const;
+ inline bool IsEmpty() const { return Len==0; }
+ inline int Length() const { return Len; }
+
+ // Data access
+ inline STR_String& SetLength(int len) { AllocBuffer(len, true); Len=len; pData[len]=0; return *this; }
+ inline char GetAt(int pos) const { assertd(pos<Len); return pData[pos]; }
+ inline void SetAt(int pos, char c) { assertd(pos<Len); pData[pos]=c; }
+ inline void SetAt(int pos, rcSTR_String str);
+ inline void SetAt(int pos, int num, rcSTR_String str);
+ void Replace(int pos, rcSTR_String str);
+ void Replace(int pos, int num, rcSTR_String str);
+
+ // Substrings
+ inline STR_String Left(int num) const { num = (num < Len ? num:Len ); return STR_String(pData, num); }
+ inline STR_String Right(int num) const { num = (num < Len ? num:Len ); return STR_String(pData+Len-num, num); }
+ inline STR_String Mid(int pos, int num = INT_MAX) const { pos = (pos < Len ? pos:Len ); num = (num < (Len - pos) ? num : (Len - pos)); return STR_String(pData+pos, num); }
+
+ // Comparison
+ int Compare(rcSTR_String rhs) const;
+ int CompareNoCase(rcSTR_String rhs) const;
+ inline bool IsEqual(rcSTR_String rhs) const { return (Compare(rhs)==0); }
+ inline bool IsEqualNoCase(rcSTR_String rhs) const { return (CompareNoCase(rhs)==0); }
+
+ // Search/replace
+ int Find(char c, int pos = 0) const;
+ int Find(const char *str, int pos = 0) const;
+ int Find(rcSTR_String str, int pos = 0) const;
+ int RFind(char c) const;
+ int FindOneOf(const char *set, int pos = 0) const;
+ int RFindOneOf(const char *set, int pos = 0) const;
+
+ vector<STR_String> Explode(char c) const;
+
+ // Formatting
+ STR_String& Upper();
+ STR_String& Lower();
+ STR_String& Capitalize();
+ STR_String& TrimLeft();
+ STR_String& TrimLeft(char *set);
+ STR_String& TrimRight();
+ STR_String& TrimRight(char *set);
+ STR_String& Trim();
+ STR_String& Trim(char *set);
+ STR_String& TrimQuotes();
+
+ // Conversions
+// inline operator char*() { return pData; }
+ inline operator const char *() const { return pData; }
+ inline char *Ptr() { return pData; }
+ inline const char *ReadPtr() const { return pData; }
+ inline float ToFloat() const { return (float) atof(pData); }
+ inline int ToInt() const { return atoi(pData); }
+
+ // Operators
+ inline rcSTR_String operator=(const byte *rhs) { return Copy((const char *)rhs, strlen((const char *)rhs)); }
+ inline rcSTR_String operator=(rcSTR_String rhs) { return Copy(rhs.ReadPtr(), rhs.Length()); }
+ inline rcSTR_String operator=(char rhs) { return Copy(&rhs, 1); }
+ inline rcSTR_String operator=(const char *rhs) { return Copy(rhs, strlen(rhs)); }
+
+ inline rcSTR_String operator+=(const char *rhs) { return Concat(rhs, strlen(rhs)); }
+ inline rcSTR_String operator+=(rcSTR_String rhs) { return Concat(rhs.ReadPtr(), rhs.Length()); }
+ inline rcSTR_String operator+=(char rhs) { return Concat(&rhs, 1); }
+
+
+ inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<0); }
+ inline friend bool operator<(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)<0); };
+ inline friend bool operator<(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<0); }
+ inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>0); }
+ inline friend bool operator>(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)>0); }
+ inline friend bool operator>(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>0); }
+ inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<=0); }
+ inline friend bool operator<=(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)<=0); }
+ inline friend bool operator<=(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)<=0); }
+ inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>=0); }
+ inline friend bool operator>=(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)>=0); }
+ inline friend bool operator>=(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>=0); }
+ inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length())==0)); }
+ inline friend bool operator==(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length()+1)==0); }
+ inline friend bool operator==(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length()+1)==0); }
+ inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length())!=0)); }
+ inline friend bool operator!=(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length()+1)!=0); }
+ inline friend bool operator!=(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length()+1)!=0); }
+
+ // serializing
+ //int Serialize(pCStream stream);
+
+protected:
+ // Implementation
+ void AllocBuffer(int len, bool keep_contents);
+ rcSTR_String Copy(const char *src, int len);
+ rcSTR_String Concat(const char *data, int len);
+
+ static bool isLower(char c) { return !isUpper(c); }
+ static bool isUpper(char c) { return (c>='A') && (c <= 'Z'); }
+ static bool isSpace(char c) { return (c==' ') || (c=='\t'); }
+
+ char *pData; // -> STR_String data
+ int Len; // Data length
+ int Max; // Space in data buffer
+};
+
+inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); }
+inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); }
+inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); }
+inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); }
+inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); }
+
+
+#endif //_STR_String_H_
diff --git a/intern/string/intern/Makefile b/intern/string/intern/Makefile
new file mode 100644
index 00000000000..925cdfed54a
--- /dev/null
+++ b/intern/string/intern/Makefile
@@ -0,0 +1,42 @@
+#
+# $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.
+#
+# 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 *****
+# string intern Makefile
+#
+
+LIBNAME = string
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I..
+
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
new file mode 100644
index 00000000000..074bdc7acea
--- /dev/null
+++ b/intern/string/intern/STR_String.cpp
@@ -0,0 +1,743 @@
+/**
+ * $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.
+ *
+ * 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 *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * This file was formerly known as: GEN_StdString.cpp.
+ * @date April, 25, 2001
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "STR_String.h"
+
+/*-------------------------------------------------------------------------------------------------
+ Construction / destruction
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Construct an empty string
+//
+STR_String::STR_String() :
+ pData(new char [32]),
+ Len(0),
+ Max(32)
+{
+ pData[0] = 0;
+}
+
+
+
+//
+// Construct a string of one character
+//
+STR_String::STR_String(char c) :
+ pData(new char [9]),
+ Len(1),
+ Max(9)
+{
+ pData[0] = c;
+ pData[1] = 0;
+}
+
+
+
+//
+// Construct a string of multiple repeating characters
+//
+STR_String::STR_String(char c, int len) :
+ pData(new char [len+8]),
+ Len(len),
+ Max(len+8)
+{
+ assertd(pData != NULL);
+ memset(pData, c, len);
+ pData[len] = 0;
+}
+
+
+
+//
+// Construct a string from a pointer-to-ASCIIZ-string
+//
+// MAART: Changed to test for null strings
+STR_String::STR_String(const char *str)
+{
+ if (str) {
+ Len = ::strlen(str);
+ Max = Len + 8;
+ pData = new char [Max];
+ assertd(pData != NULL);
+ ::memcpy(pData, str, Len);
+ pData[Len] = 0;
+ }
+ else {
+ pData = 0;
+ Len = 0;
+ Max = 8;
+ }
+}
+
+
+
+//
+// Construct a string from a pointer-to-ASCII-string and a length
+//
+STR_String::STR_String(const char *str, int len) :
+ pData(new char [len+8]),
+ Len(len),
+ Max(len+8)
+{
+ assertd(pData != NULL);
+ memcpy(pData, str, len);
+ pData[len] = 0;
+}
+
+
+
+//
+// Construct a string from another string
+//
+STR_String::STR_String(rcSTR_String str) :
+ pData(new char [str.Length()+8]),
+ Len(str.Length()),
+ Max(str.Length()+8)
+{
+ assertd(pData != NULL);
+ assertd(str.pData != NULL);
+ memcpy(pData, str.pData, str.Length());
+ pData[str.Length()] = 0;
+}
+
+
+
+//
+// Construct a string from the first number of characters in another string
+//
+STR_String::STR_String(rcSTR_String str, int len) :
+ pData(new char [len+8]),
+ Len(len),
+ Max(len+8)
+{
+ assertd(pData != NULL);
+ assertd(str.pData != NULL);
+ memcpy(pData, str.pData, str.Length());
+ pData[str.Length()] = 0;
+}
+
+
+
+//
+// Create a string by concatenating two sources
+//
+STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) :
+ pData(new char [len1+len2+8]),
+ Len(len1+len2),
+ Max(len1+len2+8)
+{
+ assertd(pData != NULL);
+ memcpy(pData, src1, len1);
+ memcpy(pData+len1, src2, len2);
+ pData[len1+len2] = 0;
+}
+
+
+
+//
+// Create a string with an integer value
+//
+STR_String::STR_String(int val) :
+ pData(new char [32]),
+ Max(32)
+{
+ assertd(pData != NULL);
+ Len=sprintf(pData, "%d", val);
+}
+
+
+
+
+//
+// Create a string with a dword value
+//
+STR_String::STR_String(dword val) :
+ pData(new char [32]),
+ Max(32)
+{
+ assertd(pData != NULL);
+ Len=sprintf(pData, "%lu", val);
+}
+
+
+
+//
+// Create a string with a floating point value
+//
+STR_String::STR_String(float val) :
+ pData(new char [32]),
+ Max(32)
+{
+ assertd(pData != NULL);
+ Len=sprintf(pData, "%g", val);
+}
+
+
+
+//
+// Create a string with a double value
+//
+STR_String::STR_String(double val) :
+ pData(new char [32]),
+ Max(32)
+{
+ assertd(pData != NULL);
+ Len=sprintf(pData, "%g", val);
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Buffer management
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Make sure that the allocated buffer is at least <len> in size
+//
+void STR_String::AllocBuffer(int len, bool keep_contents)
+{
+ // Check if we have enough space
+ if (len+1 <= Max) return;
+
+ // Reallocate string
+ char *new_data = new char [len+8];
+ if (keep_contents) memcpy(new_data, pData, Len);
+ delete[] pData;
+
+ // Accept new data
+ Max = len+8;
+ pData = new_data;
+ assertd(pData != NULL);
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Basic string operations
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Format string (as does sprintf)
+//
+STR_String& STR_String::Format(const char *fmt, ...)
+{
+ AllocBuffer(2048, false);
+
+ assertd(pData != NULL);
+ // Expand arguments and format to string
+ va_list args;
+ va_start(args, fmt);
+ Len = vsprintf(pData, fmt, args);
+ assertd(Len <= 2048);
+ va_end(args);
+
+ return *this;
+}
+
+
+
+//
+// Format string (as does sprintf)
+//
+STR_String& STR_String::FormatAdd(const char *fmt, ...)
+{
+ AllocBuffer(2048, false);
+
+ assertd(pData != NULL);
+ // Expand arguments and format to string
+ va_list args;
+ va_start(args, fmt);
+ Len += vsprintf(pData+Len, fmt, args);
+ assertd(Len <= 2048);
+ va_end(args);
+
+ return *this;
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Properties
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Check if string is entirely in UPPERCase
+//
+bool STR_String::IsUpper() const
+{
+ for (int i=0; i<Len; i++)
+ if (isLower(pData[i]))
+ return false;
+
+ return true;
+}
+
+
+
+//
+// Check if string is entirely in lowerCase
+//
+bool STR_String::IsLower() const
+{
+ for (int i=0; i<Len; i++)
+ if (isUpper(pData[i]))
+ return false;
+
+ return true;
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Search/Replace
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Find the first orccurence of <c> in the string
+//
+int STR_String::Find(char c, int pos) const
+{
+ assertd(pos >= 0);
+ assertd(Len==0 || pos<Len);
+ assertd(pData != NULL);
+ char *find_pos = strchr(pData+pos, c);
+ return (find_pos) ? (find_pos-pData) : -1;
+}
+
+
+
+//
+// Find the first occurence of <str> in the string
+//
+int STR_String::Find(const char *str, int pos) const
+{
+ assertd(pos >= 0);
+ assertd(Len==0 || pos<Len);
+ assertd(pData != NULL);
+ char *find_pos = strstr(pData+pos, str);
+ return (find_pos) ? (find_pos-pData) : -1;
+}
+
+
+
+//
+// Find the first occurence of <str> in the string
+//
+int STR_String::Find(rcSTR_String str, int pos) const
+{
+ assertd(pos >= 0);
+ assertd(Len==0 || pos<Len);
+ assertd(pData != NULL);
+ char *find_pos = strstr(pData+pos, str.ReadPtr());
+ return (find_pos) ? (find_pos-pData) : -1;
+}
+
+
+
+//
+// Find the last occurence of <c> in the string
+//
+int STR_String::RFind(char c) const
+{
+ assertd(pData != NULL);
+ char *pos = strrchr(pData, c);
+ return (pos) ? (pos-pData) : -1;
+}
+
+
+
+//
+// Find the first occurence of any character in character set <set> in the string
+//
+int STR_String::FindOneOf(const char *set, int pos) const
+{
+ assertd(pos >= 0);
+ assertd(Len==0 || pos<Len);
+ assertd(pData != NULL);
+ char *find_pos = strpbrk(pData+pos, set);
+ return (find_pos) ? (find_pos-pData) : -1;
+}
+
+
+
+//
+// Replace a character in this string with another string
+//
+void STR_String::Replace(int pos, rcSTR_String str)
+{
+ //bounds(pos, 0, Length()-1);
+
+ if (str.Length() < 1)
+ {
+ // Remove one character from the string
+ memcpy(pData+pos, pData+pos+1, Len-pos);
+ }
+ else
+ {
+ // Insert zero or more characters into the string
+ AllocBuffer(Len + str.Length() - 1, true);
+ if (str.Length() != 1) memcpy(pData+pos+str.Length(), pData+pos+1, Length()-pos);
+ memcpy(pData+pos, str.ReadPtr(), str.Length());
+ }
+
+ Len += str.Length()-1;
+}
+
+
+
+//
+// Replace a substring of this string with another string
+//
+void STR_String::Replace(int pos, int num, rcSTR_String str)
+{
+ //bounds(pos, 0, Length()-1);
+ //bounds(pos+num, 0, Length());
+ assertd(num >= 1);
+
+ if (str.Length() < num)
+ {
+ // Remove some data from the string by replacement
+ memcpy(pData+pos+str.Length(), pData+pos+num, Len-pos-num+1);
+ memcpy(pData+pos, str.ReadPtr(), str.Length());
+ }
+ else
+ {
+ // Insert zero or more characters into the string
+ AllocBuffer(Len + str.Length() - num, true);
+ if (str.Length() != num) memcpy(pData+pos+str.Length(), pData+pos+num, Length()-pos-num+1);
+ memcpy(pData+pos, str.ReadPtr(), str.Length());
+ }
+
+ Len += str.Length()-num;
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Comparison
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Compare two strings and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
+//
+int STR_String::Compare(rcSTR_String rhs) const
+{
+ return strcmp(pData, rhs.pData);
+}
+
+
+
+//
+// Compare two strings without respecting case and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
+//
+int STR_String::CompareNoCase(rcSTR_String rhs) const
+{
+#ifdef WIN32
+ return stricmp(pData, rhs.pData);
+#else
+ return strcasecmp(pData, rhs.pData);
+#endif
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Formatting
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Capitalize string, "heLLo" -> "HELLO"
+//
+STR_String& STR_String::Upper()
+{
+ assertd(pData != NULL);
+#ifdef WIN32
+ _strupr(pData);
+#else
+ for (int i=0;i<Len;i++)
+ pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
+#endif
+ return *this;
+}
+
+
+
+//
+// Lower string, "heLLo" -> "hello"
+//
+STR_String& STR_String::Lower()
+{
+ assertd(pData != NULL);
+#ifdef WIN32
+ _strlwr(pData);
+#else
+ for (int i=0;i<Len;i++)
+ pData[i] = (pData[i] >= 'A' && pData[i] <= 'Z')?pData[i]+'a'-'A':pData[i];
+#endif
+ return *this;
+}
+
+
+
+//
+// Capitalize string, "heLLo" -> "Hello"
+//
+STR_String& STR_String::Capitalize()
+{
+ assertd(pData != NULL);
+#ifdef WIN32
+ if (Len>0) pData[0] = toupper(pData[0]);
+ if (Len>1) _strlwr(pData+1);
+#else
+ if (Len > 0)
+ pData[0] = (pData[0] >= 'A' && pData[0] <= 'A')?pData[0]+'a'-'A':pData[0];
+ for (int i=1;i<Len;i++)
+ pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
+#endif
+ return *this;
+}
+
+
+
+//
+// Trim whitespace from the left side of the string
+//
+STR_String& STR_String::TrimLeft()
+{
+ int skip;
+ assertd(pData != NULL);
+ for (skip=0; isSpace(pData[skip]); skip++, Len--);
+ memmove(pData, pData+skip, Len+1);
+ return *this;
+}
+
+
+
+//
+// Trim whitespaces from the right side of the string
+//
+STR_String& STR_String::TrimRight()
+{
+ assertd(pData != NULL);
+ while (Len && isSpace(pData[Len-1])) Len--;
+ pData[Len]=0;
+ return *this;
+}
+
+
+
+//
+// Trim spaces from both sides of the character set
+//
+STR_String& STR_String::Trim()
+{
+ TrimRight();
+ TrimLeft();
+ return *this;
+}
+
+
+
+//
+// Trim characters from the character set <set> from the left side of the string
+//
+STR_String& STR_String::TrimLeft(char *set)
+{
+ int skip;
+ assertd(pData != NULL);
+ for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--);
+ memmove(pData, pData+skip, Len+1);
+ return *this;
+}
+
+
+
+//
+// Trim characters from the character set <set> from the right side of the string
+//
+STR_String& STR_String::TrimRight(char *set)
+{
+ assertd(pData != NULL);
+ while (Len && strchr(set, pData[Len-1])) Len--;
+ pData[Len]=0;
+ return *this;
+}
+
+
+
+//
+// Trim characters from the character set <set> from both sides of the character set
+//
+STR_String& STR_String::Trim(char *set)
+{
+ TrimRight(set);
+ TrimLeft(set);
+ return *this;
+}
+
+
+
+//
+// Trim quotes from both sides of the string
+//
+STR_String& STR_String::TrimQuotes()
+{
+ // Trim quotes if they are on both sides of the string
+ assertd(pData != NULL);
+ if ((Len >= 2) && (pData[0] == '\"') && (pData[Len-1] == '\"'))
+ {
+ memmove(pData, pData+1, Len-2+1);
+ Len-=2;
+ }
+ return *this;
+}
+
+
+
+/*-------------------------------------------------------------------------------------------------
+ Assignment/Concatenation
+-------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Set the string's conents to a copy of <src> with length <len>
+//
+rcSTR_String STR_String::Copy(const char *src, int len)
+{
+ assertd(len>=0);
+ assertd(src);
+ assertd(pData != NULL);
+
+ AllocBuffer(len, false);
+ Len = len;
+ memcpy(pData, src, len);
+ pData[Len] = 0;
+
+ return *this;
+}
+
+
+
+//
+// Concate a number of bytes to the current string
+//
+rcSTR_String STR_String::Concat(const char *data, int len)
+{
+ assertd(Len>=0);
+ assertd(len>=0);
+ assertd(data);
+ assertd(pData != NULL);
+
+ AllocBuffer(Len+len, true);
+ memcpy(pData+Len, data, len);
+ Len+=len;
+ pData[Len] = 0;
+
+ return *this;
+}
+
+
+
+
+
+vector<STR_String> STR_String::Explode(char c) const
+{
+ STR_String lcv = *this;
+ vector<STR_String> uc;
+
+ while (lcv.Length())
+ {
+ int pos = lcv.Find(c);
+ if (pos < 0)
+ {
+ uc.push_back(lcv);
+ lcv.Clear();
+ } else
+ {
+ uc.push_back(lcv.Left(pos));
+ lcv = lcv.Mid(pos+1);
+ }
+ }
+
+ //uc. -= STR_String("");
+
+ return uc;
+}
+
+
+/*
+
+int STR_String::Serialize(pCStream stream)
+{
+ if (stream->GetAccess() == CStream::Access_Read)
+ {
+ int ln;
+ stream->Read(&ln, sizeof(ln));
+ AllocBuffer(ln, false);
+ stream->Read(pData, ln);
+ pData[ln] = '\0';
+ Len = ln;
+ } else
+ {
+ stream->Write(&Len, sizeof(Len));
+ stream->Write(pData, Len);
+ }
+
+ return Len + sizeof(Len);
+}
+*/
+
diff --git a/intern/string/make/msvc_6_0/string.dsp b/intern/string/make/msvc_6_0/string.dsp
new file mode 100644
index 00000000000..4f0efe56f49
--- /dev/null
+++ b/intern/string/make/msvc_6_0/string.dsp
@@ -0,0 +1,122 @@
+# Microsoft Developer Studio Project File - Name="string" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=string - 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 "string.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 "string.mak" CFG="string - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "string - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "string - 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)" == "string - 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/string"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/string"
+# 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 "../.." /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
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\string\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\string\string.lib" "..\..\..\..\..\develop\lib\windows\string\lib\libstring.a" ECHO Done
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "string - 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/string/debug"
+# PROP Intermediate_Dir "../../../../../obj/windows/intern/string/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 "../.." /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
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\lib\windows\string\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\string\debug\string.lib" "..\..\..\..\..\develop\lib\windows\string\lib\debug\libstring.a" ECHO Done
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "string - Win32 Release"
+# Name "string - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\intern\STR_String.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\STR_HashedString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\STR_String.h
+# End Source File
+# End Group
+# End Group
+# End Target
+# End Project
diff --git a/intern/string/make/msvc_6_0/string.dsw b/intern/string/make/msvc_6_0/string.dsw
new file mode 100644
index 00000000000..b599b6407c5
--- /dev/null
+++ b/intern/string/make/msvc_6_0/string.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "string"=".\string.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+